@ash-cloud/ash-ai 0.1.12 → 0.1.15
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.cjs +415 -583
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +115 -153
- package/dist/index.d.ts +115 -153
- package/dist/index.js +414 -581
- package/dist/index.js.map +1 -1
- package/dist/playground/components/ChatInput.d.ts.map +1 -1
- package/dist/playground/pages/ChatPage.d.ts.map +1 -1
- package/dist/playground.css +1 -1
- package/dist/playground.js +1354 -1125
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -5289,6 +5289,23 @@ function isSandboxRunning(sessionId) {
|
|
|
5289
5289
|
const cached = sandboxCache.get(sessionId);
|
|
5290
5290
|
return cached !== void 0 && !cached.isExpired;
|
|
5291
5291
|
}
|
|
5292
|
+
function getCachedSandbox(sessionId) {
|
|
5293
|
+
const cached = sandboxCache.get(sessionId);
|
|
5294
|
+
if (!cached || cached.isExpired) {
|
|
5295
|
+
return null;
|
|
5296
|
+
}
|
|
5297
|
+
cached.lastUsedAt = Date.now();
|
|
5298
|
+
return {
|
|
5299
|
+
sandbox: cached.sandbox,
|
|
5300
|
+
sandboxId: cached.sandbox.sandboxId,
|
|
5301
|
+
sdkInstalled: cached.sdkInstalled,
|
|
5302
|
+
startupScriptRan: cached.startupScriptRan,
|
|
5303
|
+
startupScriptHash: cached.startupScriptHash,
|
|
5304
|
+
isNew: false,
|
|
5305
|
+
configFileUrl: cached.configFileUrl,
|
|
5306
|
+
configInstalledAt: cached.configInstalledAt
|
|
5307
|
+
};
|
|
5308
|
+
}
|
|
5292
5309
|
async function writeFileToSandbox(sessionId, path15, content) {
|
|
5293
5310
|
const cached = sandboxCache.get(sessionId);
|
|
5294
5311
|
if (!cached) {
|
|
@@ -5357,6 +5374,54 @@ async function readFileFromSandbox(sessionId, path15) {
|
|
|
5357
5374
|
};
|
|
5358
5375
|
}
|
|
5359
5376
|
}
|
|
5377
|
+
async function executeCommandInSandbox(sessionId, command, options) {
|
|
5378
|
+
const cached = sandboxCache.get(sessionId);
|
|
5379
|
+
if (!cached) {
|
|
5380
|
+
return { success: false, error: "No active sandbox for session" };
|
|
5381
|
+
}
|
|
5382
|
+
if (cached.isExpired) {
|
|
5383
|
+
return { success: false, error: "Sandbox has expired" };
|
|
5384
|
+
}
|
|
5385
|
+
const startTime = Date.now();
|
|
5386
|
+
try {
|
|
5387
|
+
const sandbox = cached.sandbox;
|
|
5388
|
+
let fullCommand = command;
|
|
5389
|
+
if (options?.cwd) {
|
|
5390
|
+
fullCommand = `cd ${JSON.stringify(options.cwd)} && ${command}`;
|
|
5391
|
+
}
|
|
5392
|
+
const result = await sandbox.runCommand({
|
|
5393
|
+
cmd: "bash",
|
|
5394
|
+
args: ["-c", fullCommand],
|
|
5395
|
+
env: options?.env
|
|
5396
|
+
});
|
|
5397
|
+
const stdout = await result.stdout();
|
|
5398
|
+
const stderr = await result.stderr();
|
|
5399
|
+
const durationMs = Date.now() - startTime;
|
|
5400
|
+
cached.lastUsedAt = Date.now();
|
|
5401
|
+
return {
|
|
5402
|
+
success: result.exitCode === 0,
|
|
5403
|
+
exitCode: result.exitCode,
|
|
5404
|
+
stdout,
|
|
5405
|
+
stderr,
|
|
5406
|
+
durationMs
|
|
5407
|
+
};
|
|
5408
|
+
} catch (error) {
|
|
5409
|
+
const durationMs = Date.now() - startTime;
|
|
5410
|
+
if (isSandboxExpiredError(error)) {
|
|
5411
|
+
cached.isExpired = true;
|
|
5412
|
+
return {
|
|
5413
|
+
success: false,
|
|
5414
|
+
error: "Sandbox has expired",
|
|
5415
|
+
durationMs
|
|
5416
|
+
};
|
|
5417
|
+
}
|
|
5418
|
+
return {
|
|
5419
|
+
success: false,
|
|
5420
|
+
error: error instanceof Error ? error.message : "Unknown error",
|
|
5421
|
+
durationMs
|
|
5422
|
+
};
|
|
5423
|
+
}
|
|
5424
|
+
}
|
|
5360
5425
|
async function listFilesInSandbox(sessionId, path15) {
|
|
5361
5426
|
const cached = sandboxCache.get(sessionId);
|
|
5362
5427
|
if (!cached) {
|
|
@@ -5836,19 +5901,7 @@ function getFileWatcherManager() {
|
|
|
5836
5901
|
function createFileWatcherManager() {
|
|
5837
5902
|
return new exports.FileWatcherManager();
|
|
5838
5903
|
}
|
|
5839
|
-
|
|
5840
|
-
return new exports.RemoteSandboxFileWatcher(options);
|
|
5841
|
-
}
|
|
5842
|
-
function getRemoteFileWatcherManager() {
|
|
5843
|
-
if (!globalRemoteWatcherManager) {
|
|
5844
|
-
globalRemoteWatcherManager = new exports.RemoteFileWatcherManager();
|
|
5845
|
-
}
|
|
5846
|
-
return globalRemoteWatcherManager;
|
|
5847
|
-
}
|
|
5848
|
-
function createRemoteFileWatcherManager() {
|
|
5849
|
-
return new exports.RemoteFileWatcherManager();
|
|
5850
|
-
}
|
|
5851
|
-
exports.SandboxFileWatcher = void 0; exports.FileWatcherManager = void 0; var globalWatcherManager; exports.RemoteSandboxFileWatcher = void 0; exports.RemoteFileWatcherManager = void 0; var globalRemoteWatcherManager;
|
|
5904
|
+
exports.SandboxFileWatcher = void 0; exports.FileWatcherManager = void 0; var globalWatcherManager;
|
|
5852
5905
|
var init_sandbox_file_watcher = __esm({
|
|
5853
5906
|
"src/runtime/sandbox-file-watcher.ts"() {
|
|
5854
5907
|
exports.SandboxFileWatcher = class {
|
|
@@ -6021,6 +6074,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6021
6074
|
type,
|
|
6022
6075
|
relativePath,
|
|
6023
6076
|
absolutePath,
|
|
6077
|
+
basePath: this.watchPath,
|
|
6024
6078
|
sessionId: this.sessionId,
|
|
6025
6079
|
fileSize,
|
|
6026
6080
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -6089,212 +6143,327 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6089
6143
|
}
|
|
6090
6144
|
};
|
|
6091
6145
|
globalWatcherManager = null;
|
|
6092
|
-
|
|
6146
|
+
}
|
|
6147
|
+
});
|
|
6148
|
+
|
|
6149
|
+
// src/runtime/in-sandbox-watcher.ts
|
|
6150
|
+
function createInSandboxWatcher(options) {
|
|
6151
|
+
return new exports.InSandboxWatcher(options);
|
|
6152
|
+
}
|
|
6153
|
+
function getInSandboxWatcherManager() {
|
|
6154
|
+
if (!globalInSandboxManager) {
|
|
6155
|
+
globalInSandboxManager = new exports.InSandboxWatcherManager();
|
|
6156
|
+
}
|
|
6157
|
+
return globalInSandboxManager;
|
|
6158
|
+
}
|
|
6159
|
+
function createInSandboxWatcherManager() {
|
|
6160
|
+
return new exports.InSandboxWatcherManager();
|
|
6161
|
+
}
|
|
6162
|
+
var WATCHER_SCRIPT; exports.InSandboxWatcher = void 0; exports.InSandboxWatcherManager = void 0; var globalInSandboxManager;
|
|
6163
|
+
var init_in_sandbox_watcher = __esm({
|
|
6164
|
+
"src/runtime/in-sandbox-watcher.ts"() {
|
|
6165
|
+
init_vercel_sandbox_executor();
|
|
6166
|
+
WATCHER_SCRIPT = `
|
|
6167
|
+
const fs = require('fs');
|
|
6168
|
+
const path = require('path');
|
|
6169
|
+
|
|
6170
|
+
const watchPath = process.argv[2] || '.';
|
|
6171
|
+
const ignored = new Set(['node_modules', '.git', '.cache', '__pycache__']);
|
|
6172
|
+
|
|
6173
|
+
// Track all watchers for cleanup
|
|
6174
|
+
const watchers = new Map();
|
|
6175
|
+
|
|
6176
|
+
// Debounce map to coalesce rapid changes
|
|
6177
|
+
const pending = new Map();
|
|
6178
|
+
const DEBOUNCE_MS = 100;
|
|
6179
|
+
|
|
6180
|
+
function emit(type, filePath) {
|
|
6181
|
+
const event = {
|
|
6182
|
+
type,
|
|
6183
|
+
path: filePath,
|
|
6184
|
+
timestamp: Date.now()
|
|
6185
|
+
};
|
|
6186
|
+
console.log(JSON.stringify(event));
|
|
6187
|
+
}
|
|
6188
|
+
|
|
6189
|
+
function shouldIgnore(name) {
|
|
6190
|
+
return ignored.has(name) || name.startsWith('.');
|
|
6191
|
+
}
|
|
6192
|
+
|
|
6193
|
+
function watchDir(dir) {
|
|
6194
|
+
try {
|
|
6195
|
+
const watcher = fs.watch(dir, { persistent: true }, (eventType, filename) => {
|
|
6196
|
+
if (!filename || shouldIgnore(filename)) return;
|
|
6197
|
+
|
|
6198
|
+
const fullPath = path.join(dir, filename);
|
|
6199
|
+
const key = fullPath;
|
|
6200
|
+
|
|
6201
|
+
// Debounce
|
|
6202
|
+
if (pending.has(key)) {
|
|
6203
|
+
clearTimeout(pending.get(key));
|
|
6204
|
+
}
|
|
6205
|
+
|
|
6206
|
+
pending.set(key, setTimeout(() => {
|
|
6207
|
+
pending.delete(key);
|
|
6208
|
+
|
|
6209
|
+
fs.stat(fullPath, (err, stats) => {
|
|
6210
|
+
if (err) {
|
|
6211
|
+
if (err.code === 'ENOENT') {
|
|
6212
|
+
emit('unlink', fullPath);
|
|
6213
|
+
// Stop watching if it was a directory
|
|
6214
|
+
if (watchers.has(fullPath)) {
|
|
6215
|
+
watchers.get(fullPath).close();
|
|
6216
|
+
watchers.delete(fullPath);
|
|
6217
|
+
}
|
|
6218
|
+
}
|
|
6219
|
+
} else {
|
|
6220
|
+
const type = eventType === 'rename' ? 'add' : 'change';
|
|
6221
|
+
emit(type, fullPath);
|
|
6222
|
+
|
|
6223
|
+
// If it's a new directory, start watching it
|
|
6224
|
+
if (stats.isDirectory() && !watchers.has(fullPath)) {
|
|
6225
|
+
watchDir(fullPath);
|
|
6226
|
+
}
|
|
6227
|
+
}
|
|
6228
|
+
});
|
|
6229
|
+
}, DEBOUNCE_MS));
|
|
6230
|
+
});
|
|
6231
|
+
|
|
6232
|
+
watchers.set(dir, watcher);
|
|
6233
|
+
|
|
6234
|
+
// Watch subdirectories
|
|
6235
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
6236
|
+
for (const entry of entries) {
|
|
6237
|
+
if (entry.isDirectory() && !shouldIgnore(entry.name)) {
|
|
6238
|
+
watchDir(path.join(dir, entry.name));
|
|
6239
|
+
}
|
|
6240
|
+
}
|
|
6241
|
+
} catch (err) {
|
|
6242
|
+
// Directory may not exist or be inaccessible
|
|
6243
|
+
console.error(JSON.stringify({ error: err.message, dir }));
|
|
6244
|
+
}
|
|
6245
|
+
}
|
|
6246
|
+
|
|
6247
|
+
// Start watching
|
|
6248
|
+
watchDir(watchPath);
|
|
6249
|
+
|
|
6250
|
+
// Keep alive
|
|
6251
|
+
process.on('SIGTERM', () => {
|
|
6252
|
+
for (const watcher of watchers.values()) {
|
|
6253
|
+
watcher.close();
|
|
6254
|
+
}
|
|
6255
|
+
process.exit(0);
|
|
6256
|
+
});
|
|
6257
|
+
|
|
6258
|
+
// Heartbeat to indicate we're running
|
|
6259
|
+
setInterval(() => {
|
|
6260
|
+
console.log(JSON.stringify({ heartbeat: true, timestamp: Date.now() }));
|
|
6261
|
+
}, 5000);
|
|
6262
|
+
|
|
6263
|
+
console.log(JSON.stringify({ started: true, path: watchPath }));
|
|
6264
|
+
`;
|
|
6265
|
+
exports.InSandboxWatcher = class {
|
|
6093
6266
|
sessionId;
|
|
6094
|
-
|
|
6095
|
-
|
|
6096
|
-
|
|
6097
|
-
|
|
6098
|
-
pollTimer = null;
|
|
6099
|
-
previousFiles = /* @__PURE__ */ new Map();
|
|
6267
|
+
watchPath;
|
|
6268
|
+
outputPollIntervalMs;
|
|
6269
|
+
sandboxState = null;
|
|
6270
|
+
outputPollTimer = null;
|
|
6100
6271
|
subscribers = /* @__PURE__ */ new Set();
|
|
6101
|
-
|
|
6272
|
+
isRunning = false;
|
|
6102
6273
|
startedAt;
|
|
6103
|
-
|
|
6104
|
-
|
|
6274
|
+
lastHeartbeat;
|
|
6275
|
+
lastOutputPosition = 0;
|
|
6105
6276
|
onError;
|
|
6277
|
+
onReady;
|
|
6106
6278
|
constructor(options) {
|
|
6107
6279
|
this.sessionId = options.sessionId;
|
|
6108
|
-
this.
|
|
6109
|
-
this.
|
|
6110
|
-
this.pollIntervalMs = options.pollIntervalMs ?? 2e3;
|
|
6111
|
-
this.ignored = options.ignored ?? ["**/node_modules/**", "**/.git/**"];
|
|
6280
|
+
this.watchPath = options.watchPath;
|
|
6281
|
+
this.outputPollIntervalMs = options.outputPollIntervalMs ?? 1e3;
|
|
6112
6282
|
this.onError = options.onError;
|
|
6283
|
+
this.onReady = options.onReady;
|
|
6113
6284
|
if (options.onFileChange) {
|
|
6114
6285
|
this.subscribers.add(options.onFileChange);
|
|
6115
6286
|
}
|
|
6116
6287
|
}
|
|
6117
6288
|
/**
|
|
6118
|
-
* Start
|
|
6289
|
+
* Start the watcher process inside the sandbox
|
|
6119
6290
|
*/
|
|
6120
6291
|
async start() {
|
|
6121
|
-
if (this.
|
|
6122
|
-
console.warn(`[
|
|
6292
|
+
if (this.isRunning) {
|
|
6293
|
+
console.warn(`[IN_SANDBOX_WATCHER] Already running for session ${this.sessionId}`);
|
|
6123
6294
|
return;
|
|
6124
6295
|
}
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
this.pollTimer = setInterval(async () => {
|
|
6130
|
-
try {
|
|
6131
|
-
await this.scan(false);
|
|
6132
|
-
} catch (error) {
|
|
6133
|
-
console.error(`[REMOTE_WATCHER] Poll error for session ${this.sessionId}:`, error);
|
|
6134
|
-
if (this.onError && error instanceof Error) {
|
|
6135
|
-
this.onError(error);
|
|
6136
|
-
}
|
|
6296
|
+
try {
|
|
6297
|
+
this.sandboxState = getCachedSandbox(this.sessionId);
|
|
6298
|
+
if (!this.sandboxState) {
|
|
6299
|
+
throw new Error(`No active sandbox found for session ${this.sessionId}. Sandbox must be created before starting file watcher.`);
|
|
6137
6300
|
}
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6301
|
+
const { sandbox } = this.sandboxState;
|
|
6302
|
+
const scriptPath = "/tmp/.file-watcher.js";
|
|
6303
|
+
const outputPath = "/tmp/.file-watcher-output.log";
|
|
6304
|
+
const writeScriptCmd = `cat > ${scriptPath} << 'WATCHER_EOF'
|
|
6305
|
+
${WATCHER_SCRIPT}
|
|
6306
|
+
WATCHER_EOF`;
|
|
6307
|
+
await sandbox.runCommand({
|
|
6308
|
+
cmd: "sh",
|
|
6309
|
+
args: ["-c", writeScriptCmd]
|
|
6310
|
+
});
|
|
6311
|
+
const startCmd = `nohup node ${scriptPath} "${this.watchPath}" > ${outputPath} 2>&1 &`;
|
|
6312
|
+
await sandbox.runCommand({
|
|
6313
|
+
cmd: "sh",
|
|
6314
|
+
args: ["-c", startCmd]
|
|
6315
|
+
});
|
|
6316
|
+
console.log(`[IN_SANDBOX_WATCHER] Started watcher in sandbox for ${this.watchPath}`);
|
|
6317
|
+
this.isRunning = true;
|
|
6318
|
+
this.startedAt = /* @__PURE__ */ new Date();
|
|
6319
|
+
this.outputPollTimer = setInterval(async () => {
|
|
6320
|
+
try {
|
|
6321
|
+
await this.pollOutput(outputPath);
|
|
6322
|
+
} catch (error) {
|
|
6323
|
+
console.error("[IN_SANDBOX_WATCHER] Error polling output:", error);
|
|
6324
|
+
if (this.onError && error instanceof Error) {
|
|
6325
|
+
this.onError(error);
|
|
6326
|
+
}
|
|
6327
|
+
}
|
|
6328
|
+
}, this.outputPollIntervalMs);
|
|
6329
|
+
setTimeout(() => {
|
|
6330
|
+
this.pollOutput(outputPath).catch(console.error);
|
|
6331
|
+
}, 500);
|
|
6332
|
+
} catch (error) {
|
|
6333
|
+
console.error(`[IN_SANDBOX_WATCHER] Failed to start watcher:`, error);
|
|
6334
|
+
throw error;
|
|
6153
6335
|
}
|
|
6154
|
-
this.isWatching = false;
|
|
6155
|
-
this.previousFiles.clear();
|
|
6156
|
-
console.log(`[REMOTE_WATCHER] Stopped watching session ${this.sessionId}`);
|
|
6157
|
-
}
|
|
6158
|
-
/**
|
|
6159
|
-
* Subscribe to file change events
|
|
6160
|
-
*/
|
|
6161
|
-
subscribe(callback) {
|
|
6162
|
-
this.subscribers.add(callback);
|
|
6163
|
-
return () => this.subscribers.delete(callback);
|
|
6164
6336
|
}
|
|
6165
6337
|
/**
|
|
6166
|
-
*
|
|
6338
|
+
* Poll the output file for new events
|
|
6167
6339
|
*/
|
|
6168
|
-
|
|
6169
|
-
this.
|
|
6340
|
+
async pollOutput(outputPath) {
|
|
6341
|
+
if (!this.sandboxState?.sandbox) return;
|
|
6342
|
+
try {
|
|
6343
|
+
const result = await this.sandboxState.sandbox.runCommand({
|
|
6344
|
+
cmd: "sh",
|
|
6345
|
+
args: ["-c", `tail -c +${this.lastOutputPosition + 1} ${outputPath} 2>/dev/null || true`]
|
|
6346
|
+
});
|
|
6347
|
+
const output = await result.stdout();
|
|
6348
|
+
if (output && output.trim()) {
|
|
6349
|
+
const sizeResult = await this.sandboxState.sandbox.runCommand({
|
|
6350
|
+
cmd: "sh",
|
|
6351
|
+
args: ["-c", `stat -c%s ${outputPath} 2>/dev/null || echo 0`]
|
|
6352
|
+
});
|
|
6353
|
+
const sizeStr = await sizeResult.stdout();
|
|
6354
|
+
this.lastOutputPosition = parseInt(sizeStr.trim(), 10) || 0;
|
|
6355
|
+
this.processOutput(output);
|
|
6356
|
+
}
|
|
6357
|
+
} catch {
|
|
6358
|
+
}
|
|
6170
6359
|
}
|
|
6171
6360
|
/**
|
|
6172
|
-
*
|
|
6361
|
+
* Process output from the watcher script
|
|
6173
6362
|
*/
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6363
|
+
processOutput(stdout) {
|
|
6364
|
+
const lines = stdout.split("\n").filter(Boolean);
|
|
6365
|
+
for (const line of lines) {
|
|
6366
|
+
try {
|
|
6367
|
+
const data = JSON.parse(line);
|
|
6368
|
+
if (data.started) {
|
|
6369
|
+
console.log(`[IN_SANDBOX_WATCHER] Watcher started for ${data.path}`);
|
|
6370
|
+
if (this.onReady) {
|
|
6371
|
+
this.onReady();
|
|
6372
|
+
}
|
|
6373
|
+
} else if (data.heartbeat) {
|
|
6374
|
+
this.lastHeartbeat = new Date(data.timestamp);
|
|
6375
|
+
} else if (data.error) {
|
|
6376
|
+
console.warn(`[IN_SANDBOX_WATCHER] Error in sandbox:`, data.error);
|
|
6377
|
+
} else if (data.type && data.path) {
|
|
6378
|
+
this.emitEvent({
|
|
6379
|
+
type: data.type,
|
|
6380
|
+
relativePath: data.path.replace(/^\.\//, ""),
|
|
6381
|
+
absolutePath: data.path,
|
|
6382
|
+
basePath: this.watchPath,
|
|
6383
|
+
sessionId: this.sessionId,
|
|
6384
|
+
timestamp: new Date(data.timestamp)
|
|
6385
|
+
});
|
|
6386
|
+
}
|
|
6387
|
+
} catch {
|
|
6388
|
+
}
|
|
6389
|
+
}
|
|
6197
6390
|
}
|
|
6198
6391
|
/**
|
|
6199
|
-
*
|
|
6392
|
+
* Stop the watcher process
|
|
6200
6393
|
*/
|
|
6201
|
-
async
|
|
6202
|
-
if (!this.
|
|
6203
|
-
console.warn(`[REMOTE_WATCHER] Sandbox stopped for session ${this.sessionId}`);
|
|
6204
|
-
await this.stop();
|
|
6394
|
+
async stop() {
|
|
6395
|
+
if (!this.isRunning) {
|
|
6205
6396
|
return;
|
|
6206
6397
|
}
|
|
6207
|
-
|
|
6208
|
-
|
|
6209
|
-
|
|
6210
|
-
}
|
|
6211
|
-
const currentFiles = /* @__PURE__ */ new Map();
|
|
6212
|
-
for (const filePath of listResult.files) {
|
|
6213
|
-
if (this.shouldIgnore(filePath)) {
|
|
6214
|
-
continue;
|
|
6215
|
-
}
|
|
6216
|
-
currentFiles.set(filePath, { path: filePath });
|
|
6217
|
-
}
|
|
6218
|
-
this.lastPollAt = /* @__PURE__ */ new Date();
|
|
6219
|
-
this.pollCount++;
|
|
6220
|
-
if (isInitial) {
|
|
6221
|
-
this.previousFiles = currentFiles;
|
|
6222
|
-
return;
|
|
6398
|
+
if (this.outputPollTimer) {
|
|
6399
|
+
clearInterval(this.outputPollTimer);
|
|
6400
|
+
this.outputPollTimer = null;
|
|
6223
6401
|
}
|
|
6224
|
-
|
|
6225
|
-
|
|
6226
|
-
|
|
6227
|
-
|
|
6228
|
-
|
|
6229
|
-
type: "add",
|
|
6230
|
-
relativePath: filePath,
|
|
6231
|
-
absolutePath: `${this.basePath}/${filePath}`,
|
|
6232
|
-
sessionId: this.sessionId,
|
|
6233
|
-
fileSize: info.size,
|
|
6234
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
6402
|
+
try {
|
|
6403
|
+
if (this.sandboxState?.sandbox) {
|
|
6404
|
+
await this.sandboxState.sandbox.runCommand({
|
|
6405
|
+
cmd: "sh",
|
|
6406
|
+
args: ["-c", "pkill -f file-watcher.js 2>/dev/null || true"]
|
|
6235
6407
|
});
|
|
6236
|
-
|
|
6237
|
-
|
|
6238
|
-
|
|
6239
|
-
if (!currentFiles.has(filePath)) {
|
|
6240
|
-
changes.push({
|
|
6241
|
-
type: "unlink",
|
|
6242
|
-
relativePath: filePath,
|
|
6243
|
-
absolutePath: `${this.basePath}/${filePath}`,
|
|
6244
|
-
sessionId: this.sessionId,
|
|
6245
|
-
timestamp: /* @__PURE__ */ new Date()
|
|
6408
|
+
await this.sandboxState.sandbox.runCommand({
|
|
6409
|
+
cmd: "sh",
|
|
6410
|
+
args: ["-c", "rm -f /tmp/.file-watcher.js /tmp/.file-watcher-output.log"]
|
|
6246
6411
|
});
|
|
6247
6412
|
}
|
|
6413
|
+
} catch {
|
|
6248
6414
|
}
|
|
6249
|
-
this.
|
|
6250
|
-
|
|
6251
|
-
|
|
6252
|
-
}
|
|
6415
|
+
this.isRunning = false;
|
|
6416
|
+
this.sandboxState = null;
|
|
6417
|
+
this.lastOutputPosition = 0;
|
|
6418
|
+
console.log(`[IN_SANDBOX_WATCHER] Stopped watcher for session ${this.sessionId}`);
|
|
6253
6419
|
}
|
|
6254
6420
|
/**
|
|
6255
|
-
*
|
|
6421
|
+
* Subscribe to file change events
|
|
6256
6422
|
*/
|
|
6257
|
-
|
|
6258
|
-
|
|
6259
|
-
|
|
6260
|
-
return true;
|
|
6261
|
-
}
|
|
6262
|
-
}
|
|
6263
|
-
return false;
|
|
6423
|
+
subscribe(callback) {
|
|
6424
|
+
this.subscribers.add(callback);
|
|
6425
|
+
return () => this.subscribers.delete(callback);
|
|
6264
6426
|
}
|
|
6265
6427
|
/**
|
|
6266
|
-
*
|
|
6428
|
+
* Check if watcher is running
|
|
6267
6429
|
*/
|
|
6268
|
-
|
|
6269
|
-
|
|
6270
|
-
const regex = new RegExp(`^${regexPattern}$`);
|
|
6271
|
-
return regex.test(filePath);
|
|
6430
|
+
isActive() {
|
|
6431
|
+
return this.isRunning;
|
|
6272
6432
|
}
|
|
6273
6433
|
/**
|
|
6274
|
-
*
|
|
6434
|
+
* Get watcher status
|
|
6435
|
+
*/
|
|
6436
|
+
getStatus() {
|
|
6437
|
+
return {
|
|
6438
|
+
sessionId: this.sessionId,
|
|
6439
|
+
watchPath: this.watchPath,
|
|
6440
|
+
isRunning: this.isRunning,
|
|
6441
|
+
startedAt: this.startedAt,
|
|
6442
|
+
lastHeartbeat: this.lastHeartbeat
|
|
6443
|
+
};
|
|
6444
|
+
}
|
|
6445
|
+
/**
|
|
6446
|
+
* Emit event to all subscribers
|
|
6275
6447
|
*/
|
|
6276
6448
|
async emitEvent(event) {
|
|
6277
6449
|
for (const callback of this.subscribers) {
|
|
6278
6450
|
try {
|
|
6279
6451
|
await callback(event);
|
|
6280
6452
|
} catch (error) {
|
|
6281
|
-
console.error("[
|
|
6453
|
+
console.error("[IN_SANDBOX_WATCHER] Error in subscriber callback:", error);
|
|
6282
6454
|
}
|
|
6283
6455
|
}
|
|
6284
6456
|
}
|
|
6285
6457
|
};
|
|
6286
|
-
exports.
|
|
6458
|
+
exports.InSandboxWatcherManager = class {
|
|
6287
6459
|
watchers = /* @__PURE__ */ new Map();
|
|
6288
6460
|
/**
|
|
6289
|
-
* Start watching a
|
|
6461
|
+
* Start watching a sandbox
|
|
6290
6462
|
*/
|
|
6291
6463
|
async startWatching(options) {
|
|
6292
6464
|
const { sessionId } = options;
|
|
6293
|
-
|
|
6294
|
-
|
|
6295
|
-
await existing.stop();
|
|
6296
|
-
}
|
|
6297
|
-
const watcher = new exports.RemoteSandboxFileWatcher(options);
|
|
6465
|
+
await this.stopWatching(sessionId);
|
|
6466
|
+
const watcher = new exports.InSandboxWatcher(options);
|
|
6298
6467
|
await watcher.start();
|
|
6299
6468
|
this.watchers.set(sessionId, watcher);
|
|
6300
6469
|
return watcher;
|
|
@@ -6310,17 +6479,16 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6310
6479
|
}
|
|
6311
6480
|
}
|
|
6312
6481
|
/**
|
|
6313
|
-
* Get
|
|
6482
|
+
* Get watcher for a session
|
|
6314
6483
|
*/
|
|
6315
6484
|
getWatcher(sessionId) {
|
|
6316
6485
|
return this.watchers.get(sessionId);
|
|
6317
6486
|
}
|
|
6318
6487
|
/**
|
|
6319
|
-
* Check if
|
|
6488
|
+
* Check if watching
|
|
6320
6489
|
*/
|
|
6321
6490
|
isWatching(sessionId) {
|
|
6322
|
-
|
|
6323
|
-
return watcher?.isActive() ?? false;
|
|
6491
|
+
return this.watchers.get(sessionId)?.isActive() ?? false;
|
|
6324
6492
|
}
|
|
6325
6493
|
/**
|
|
6326
6494
|
* Stop all watchers
|
|
@@ -6331,7 +6499,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6331
6499
|
this.watchers.clear();
|
|
6332
6500
|
}
|
|
6333
6501
|
};
|
|
6334
|
-
|
|
6502
|
+
globalInSandboxManager = null;
|
|
6335
6503
|
}
|
|
6336
6504
|
});
|
|
6337
6505
|
function extractErrorMessage(error) {
|
|
@@ -6380,6 +6548,7 @@ exports.SandboxFileSync = void 0;
|
|
|
6380
6548
|
var init_sandbox_file_sync = __esm({
|
|
6381
6549
|
"src/runtime/sandbox-file-sync.ts"() {
|
|
6382
6550
|
init_sandbox_file_watcher();
|
|
6551
|
+
init_in_sandbox_watcher();
|
|
6383
6552
|
init_types();
|
|
6384
6553
|
exports.SandboxFileSync = class {
|
|
6385
6554
|
fileStore;
|
|
@@ -6390,7 +6559,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6390
6559
|
eventStorage;
|
|
6391
6560
|
webhookConfig;
|
|
6392
6561
|
// Watcher management
|
|
6393
|
-
|
|
6562
|
+
inSandboxWatchers = /* @__PURE__ */ new Map();
|
|
6394
6563
|
localWatchers = /* @__PURE__ */ new Map();
|
|
6395
6564
|
fileChangeSubscribers = /* @__PURE__ */ new Set();
|
|
6396
6565
|
// Sequence number cache per session (for event storage)
|
|
@@ -6545,7 +6714,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6545
6714
|
}
|
|
6546
6715
|
};
|
|
6547
6716
|
const webhookType = payload.event === "file_sync" ? "file_sync" : "file_change";
|
|
6548
|
-
const filePath = payload.fileSyncEvent?.
|
|
6717
|
+
const filePath = payload.fileSyncEvent?.canonicalPath ?? payload.fileChangeEvent?.relativePath;
|
|
6549
6718
|
const operation = payload.fileSyncEvent?.operation ?? payload.fileChangeEvent?.type;
|
|
6550
6719
|
if (isAsync) {
|
|
6551
6720
|
sendWithRetry(0).then(async (result) => {
|
|
@@ -6675,7 +6844,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6675
6844
|
const eventData = {
|
|
6676
6845
|
operation: event.operation,
|
|
6677
6846
|
source: event.source,
|
|
6678
|
-
|
|
6847
|
+
canonicalPath: event.canonicalPath,
|
|
6848
|
+
basePath: event.basePath,
|
|
6849
|
+
sandboxPath: event.sandboxPath,
|
|
6679
6850
|
fileSize: event.fileSize,
|
|
6680
6851
|
success: event.success,
|
|
6681
6852
|
error: event.error,
|
|
@@ -6706,6 +6877,13 @@ var init_sandbox_file_sync = __esm({
|
|
|
6706
6877
|
setSandboxOperations(ops) {
|
|
6707
6878
|
this.sandboxOps = ops;
|
|
6708
6879
|
}
|
|
6880
|
+
/**
|
|
6881
|
+
* Get the effective base path for sandbox operations
|
|
6882
|
+
* @param targetPath - Optional override for the base path
|
|
6883
|
+
*/
|
|
6884
|
+
getBasePath(targetPath) {
|
|
6885
|
+
return targetPath ?? this.sandboxBasePath;
|
|
6886
|
+
}
|
|
6709
6887
|
/**
|
|
6710
6888
|
* Get the full sandbox path for a file
|
|
6711
6889
|
* @param path - The relative file path
|
|
@@ -6713,12 +6891,30 @@ var init_sandbox_file_sync = __esm({
|
|
|
6713
6891
|
*/
|
|
6714
6892
|
getSandboxPath(path15, targetPath) {
|
|
6715
6893
|
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6716
|
-
const basePath =
|
|
6894
|
+
const basePath = this.getBasePath(targetPath);
|
|
6717
6895
|
if (basePath === ".") {
|
|
6718
6896
|
return normalizedPath;
|
|
6719
6897
|
}
|
|
6720
6898
|
return `${basePath}/${normalizedPath}`;
|
|
6721
6899
|
}
|
|
6900
|
+
/**
|
|
6901
|
+
* Build all path fields for a FileSyncEvent
|
|
6902
|
+
* @param path - The canonical file path (used as S3 key)
|
|
6903
|
+
* @param targetPath - Optional override for the base path
|
|
6904
|
+
*/
|
|
6905
|
+
buildPathFields(path15, targetPath) {
|
|
6906
|
+
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6907
|
+
const basePath = this.getBasePath(targetPath);
|
|
6908
|
+
const sandboxPath = this.getSandboxPath(path15, targetPath);
|
|
6909
|
+
return {
|
|
6910
|
+
canonicalPath: normalizedPath,
|
|
6911
|
+
// The logical path (S3 key)
|
|
6912
|
+
basePath,
|
|
6913
|
+
// The prefix used in sandbox
|
|
6914
|
+
sandboxPath
|
|
6915
|
+
// Full computed path in sandbox
|
|
6916
|
+
};
|
|
6917
|
+
}
|
|
6722
6918
|
/**
|
|
6723
6919
|
* Push a file: writes to S3, then to sandbox if running
|
|
6724
6920
|
* @param sessionId - Session ID
|
|
@@ -6735,13 +6931,14 @@ var init_sandbox_file_sync = __esm({
|
|
|
6735
6931
|
};
|
|
6736
6932
|
const source = options?.source ?? "client_api";
|
|
6737
6933
|
const uploadToStorageOp = source === "client_api" ? "client_uploaded_to_ash_storage" : "agent_sandbox_saved_to_ash_storage";
|
|
6934
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6738
6935
|
try {
|
|
6739
6936
|
await this.fileStore.writeFile(sessionId, path15, content);
|
|
6740
6937
|
result.s3Written = true;
|
|
6741
6938
|
await this.emitFileEvent(sessionId, {
|
|
6742
6939
|
operation: uploadToStorageOp,
|
|
6743
6940
|
source,
|
|
6744
|
-
|
|
6941
|
+
...pathFields,
|
|
6745
6942
|
fileSize: content.length,
|
|
6746
6943
|
success: true,
|
|
6747
6944
|
previousContent,
|
|
@@ -6754,7 +6951,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6754
6951
|
await this.emitFileEvent(sessionId, {
|
|
6755
6952
|
operation: uploadToStorageOp,
|
|
6756
6953
|
source,
|
|
6757
|
-
|
|
6954
|
+
...pathFields,
|
|
6758
6955
|
fileSize: content.length,
|
|
6759
6956
|
success: false,
|
|
6760
6957
|
error: errorMessage
|
|
@@ -6763,13 +6960,12 @@ var init_sandbox_file_sync = __esm({
|
|
|
6763
6960
|
}
|
|
6764
6961
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6765
6962
|
try {
|
|
6766
|
-
const
|
|
6767
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
6963
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6768
6964
|
result.sandboxWritten = writeResult.success;
|
|
6769
6965
|
await this.emitFileEvent(sessionId, {
|
|
6770
6966
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6771
6967
|
source,
|
|
6772
|
-
|
|
6968
|
+
...pathFields,
|
|
6773
6969
|
fileSize: content.length,
|
|
6774
6970
|
success: writeResult.success,
|
|
6775
6971
|
error: writeResult.error
|
|
@@ -6783,7 +6979,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6783
6979
|
await this.emitFileEvent(sessionId, {
|
|
6784
6980
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6785
6981
|
source,
|
|
6786
|
-
|
|
6982
|
+
...pathFields,
|
|
6787
6983
|
fileSize: content.length,
|
|
6788
6984
|
success: false,
|
|
6789
6985
|
error: errorMessage
|
|
@@ -6826,15 +7022,15 @@ var init_sandbox_file_sync = __esm({
|
|
|
6826
7022
|
result.error = "Sandbox is not running";
|
|
6827
7023
|
return result;
|
|
6828
7024
|
}
|
|
7025
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6829
7026
|
try {
|
|
6830
|
-
const
|
|
6831
|
-
const readResult = await this.sandboxOps.readFile(sessionId, sandboxPath);
|
|
7027
|
+
const readResult = await this.sandboxOps.readFile(sessionId, pathFields.sandboxPath);
|
|
6832
7028
|
if (!readResult.success || !readResult.content) {
|
|
6833
7029
|
result.error = readResult.error ?? "File not found in sandbox";
|
|
6834
7030
|
await this.emitFileEvent(sessionId, {
|
|
6835
7031
|
operation: "read_from_agent_sandbox",
|
|
6836
7032
|
source: "ash_file_sync",
|
|
6837
|
-
|
|
7033
|
+
...pathFields,
|
|
6838
7034
|
success: false,
|
|
6839
7035
|
error: result.error
|
|
6840
7036
|
});
|
|
@@ -6844,7 +7040,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6844
7040
|
await this.emitFileEvent(sessionId, {
|
|
6845
7041
|
operation: "read_from_agent_sandbox",
|
|
6846
7042
|
source: "ash_file_sync",
|
|
6847
|
-
|
|
7043
|
+
...pathFields,
|
|
6848
7044
|
fileSize: readResult.content.length,
|
|
6849
7045
|
success: true,
|
|
6850
7046
|
newContent: readResult.content
|
|
@@ -6855,7 +7051,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6855
7051
|
await this.emitFileEvent(sessionId, {
|
|
6856
7052
|
operation: "read_from_agent_sandbox",
|
|
6857
7053
|
source: "ash_file_sync",
|
|
6858
|
-
|
|
7054
|
+
...pathFields,
|
|
6859
7055
|
success: false,
|
|
6860
7056
|
error: errorMessage
|
|
6861
7057
|
});
|
|
@@ -6867,7 +7063,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6867
7063
|
await this.emitFileEvent(sessionId, {
|
|
6868
7064
|
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6869
7065
|
source: "ash_file_sync",
|
|
6870
|
-
|
|
7066
|
+
...pathFields,
|
|
6871
7067
|
fileSize: result.content.length,
|
|
6872
7068
|
success: true,
|
|
6873
7069
|
newContent: result.content
|
|
@@ -6879,7 +7075,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6879
7075
|
await this.emitFileEvent(sessionId, {
|
|
6880
7076
|
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6881
7077
|
source: "ash_file_sync",
|
|
6882
|
-
|
|
7078
|
+
...pathFields,
|
|
6883
7079
|
fileSize: result.content?.length,
|
|
6884
7080
|
success: false,
|
|
6885
7081
|
error: errorMessage
|
|
@@ -6921,13 +7117,14 @@ var init_sandbox_file_sync = __esm({
|
|
|
6921
7117
|
*/
|
|
6922
7118
|
async deleteFile(sessionId, path15) {
|
|
6923
7119
|
const result = { s3Deleted: false, sandboxDeleted: false };
|
|
7120
|
+
const pathFields = this.buildPathFields(path15);
|
|
6924
7121
|
try {
|
|
6925
7122
|
await this.fileStore.deleteFile(sessionId, path15);
|
|
6926
7123
|
result.s3Deleted = true;
|
|
6927
7124
|
await this.emitFileEvent(sessionId, {
|
|
6928
7125
|
operation: "deleted_from_ash_storage",
|
|
6929
7126
|
source: "ash_file_sync",
|
|
6930
|
-
|
|
7127
|
+
...pathFields,
|
|
6931
7128
|
success: true
|
|
6932
7129
|
});
|
|
6933
7130
|
} catch (error) {
|
|
@@ -6936,20 +7133,19 @@ var init_sandbox_file_sync = __esm({
|
|
|
6936
7133
|
await this.emitFileEvent(sessionId, {
|
|
6937
7134
|
operation: "deleted_from_ash_storage",
|
|
6938
7135
|
source: "ash_file_sync",
|
|
6939
|
-
|
|
7136
|
+
...pathFields,
|
|
6940
7137
|
success: false,
|
|
6941
7138
|
error: errorMessage
|
|
6942
7139
|
});
|
|
6943
7140
|
}
|
|
6944
7141
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6945
7142
|
try {
|
|
6946
|
-
|
|
6947
|
-
console.log(`[FILE_SYNC] Would delete ${sandboxPath} from sandbox`);
|
|
7143
|
+
console.log(`[FILE_SYNC] Would delete ${pathFields.sandboxPath} from sandbox`);
|
|
6948
7144
|
result.sandboxDeleted = true;
|
|
6949
7145
|
await this.emitFileEvent(sessionId, {
|
|
6950
7146
|
operation: "deleted_from_agent_sandbox",
|
|
6951
7147
|
source: "ash_file_sync",
|
|
6952
|
-
|
|
7148
|
+
...pathFields,
|
|
6953
7149
|
success: true
|
|
6954
7150
|
});
|
|
6955
7151
|
} catch (error) {
|
|
@@ -6957,7 +7153,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6957
7153
|
await this.emitFileEvent(sessionId, {
|
|
6958
7154
|
operation: "deleted_from_agent_sandbox",
|
|
6959
7155
|
source: "ash_file_sync",
|
|
6960
|
-
|
|
7156
|
+
...pathFields,
|
|
6961
7157
|
success: false,
|
|
6962
7158
|
error: errorMessage
|
|
6963
7159
|
});
|
|
@@ -6977,6 +7173,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6977
7173
|
}
|
|
6978
7174
|
const files = await this.fileStore.listFiles(sessionId);
|
|
6979
7175
|
for (const file of files) {
|
|
7176
|
+
const pathFields = this.buildPathFields(file.path);
|
|
6980
7177
|
try {
|
|
6981
7178
|
const content = await this.fileStore.readFile(sessionId, file.path);
|
|
6982
7179
|
if (!content) {
|
|
@@ -6984,20 +7181,19 @@ var init_sandbox_file_sync = __esm({
|
|
|
6984
7181
|
await this.emitFileEvent(sessionId, {
|
|
6985
7182
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6986
7183
|
source: "ash_file_sync",
|
|
6987
|
-
|
|
7184
|
+
...pathFields,
|
|
6988
7185
|
success: false,
|
|
6989
7186
|
error: "File not found in Ash storage"
|
|
6990
7187
|
});
|
|
6991
7188
|
continue;
|
|
6992
7189
|
}
|
|
6993
|
-
const
|
|
6994
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
7190
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6995
7191
|
if (writeResult.success) {
|
|
6996
7192
|
result.fileCount++;
|
|
6997
7193
|
await this.emitFileEvent(sessionId, {
|
|
6998
7194
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6999
7195
|
source: "ash_file_sync",
|
|
7000
|
-
|
|
7196
|
+
...pathFields,
|
|
7001
7197
|
fileSize: content.length,
|
|
7002
7198
|
success: true
|
|
7003
7199
|
});
|
|
@@ -7006,7 +7202,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7006
7202
|
await this.emitFileEvent(sessionId, {
|
|
7007
7203
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7008
7204
|
source: "ash_file_sync",
|
|
7009
|
-
|
|
7205
|
+
...pathFields,
|
|
7010
7206
|
fileSize: content.length,
|
|
7011
7207
|
success: false,
|
|
7012
7208
|
error: writeResult.error
|
|
@@ -7021,7 +7217,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7021
7217
|
await this.emitFileEvent(sessionId, {
|
|
7022
7218
|
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7023
7219
|
source: "ash_file_sync",
|
|
7024
|
-
|
|
7220
|
+
...pathFields,
|
|
7025
7221
|
success: false,
|
|
7026
7222
|
error: errorMessage
|
|
7027
7223
|
});
|
|
@@ -7052,24 +7248,25 @@ var init_sandbox_file_sync = __esm({
|
|
|
7052
7248
|
return result;
|
|
7053
7249
|
}
|
|
7054
7250
|
}
|
|
7055
|
-
for (const
|
|
7251
|
+
for (const file of filesToSync) {
|
|
7252
|
+
const pathFields = this.buildPathFields(file);
|
|
7056
7253
|
try {
|
|
7057
|
-
const pullResult = await this.pullFile(sessionId,
|
|
7254
|
+
const pullResult = await this.pullFile(sessionId, file);
|
|
7058
7255
|
if (pullResult.s3Written) {
|
|
7059
7256
|
result.fileCount++;
|
|
7060
7257
|
} else if (pullResult.error) {
|
|
7061
|
-
result.errors.push({ path:
|
|
7258
|
+
result.errors.push({ path: file, error: pullResult.error });
|
|
7062
7259
|
}
|
|
7063
7260
|
} catch (error) {
|
|
7064
7261
|
const errorMessage = extractErrorMessage(error);
|
|
7065
7262
|
result.errors.push({
|
|
7066
|
-
path:
|
|
7263
|
+
path: file,
|
|
7067
7264
|
error: errorMessage
|
|
7068
7265
|
});
|
|
7069
7266
|
await this.emitFileEvent(sessionId, {
|
|
7070
7267
|
operation: "agent_sandbox_saved_to_ash_storage",
|
|
7071
7268
|
source: "ash_file_sync",
|
|
7072
|
-
|
|
7269
|
+
...pathFields,
|
|
7073
7270
|
success: false,
|
|
7074
7271
|
error: errorMessage
|
|
7075
7272
|
});
|
|
@@ -7153,34 +7350,27 @@ var init_sandbox_file_sync = __esm({
|
|
|
7153
7350
|
this.localWatchers.set(sessionId, watcher);
|
|
7154
7351
|
console.log(`[FILE_SYNC] Started local file watching for session ${sessionId} at ${opts.localPath}`);
|
|
7155
7352
|
} else {
|
|
7156
|
-
|
|
7157
|
-
throw new Error("Sandbox operations not configured. Call setSandboxOperations first.");
|
|
7158
|
-
}
|
|
7159
|
-
const watcher = new exports.RemoteSandboxFileWatcher({
|
|
7353
|
+
const watcher = new exports.InSandboxWatcher({
|
|
7160
7354
|
sessionId,
|
|
7161
|
-
|
|
7162
|
-
basePath: watchPath,
|
|
7163
|
-
// Use watchPath instead of sandboxBasePath
|
|
7164
|
-
pollIntervalMs: opts.pollIntervalMs ?? 2e3,
|
|
7165
|
-
ignored: opts.ignored ?? ["**/node_modules/**", "**/.git/**"],
|
|
7355
|
+
watchPath,
|
|
7166
7356
|
onFileChange: handleFileChange,
|
|
7167
7357
|
onError: (error) => {
|
|
7168
|
-
console.error(`[FILE_SYNC]
|
|
7358
|
+
console.error(`[FILE_SYNC] In-sandbox watcher error for session ${sessionId}:`, error);
|
|
7169
7359
|
}
|
|
7170
7360
|
});
|
|
7171
7361
|
await watcher.start();
|
|
7172
|
-
this.
|
|
7173
|
-
console.log(`[FILE_SYNC] Started
|
|
7362
|
+
this.inSandboxWatchers.set(sessionId, watcher);
|
|
7363
|
+
console.log(`[FILE_SYNC] Started in-sandbox file watching for session ${sessionId} at path: ${watchPath}`);
|
|
7174
7364
|
}
|
|
7175
7365
|
}
|
|
7176
7366
|
/**
|
|
7177
7367
|
* Stop watching a session's sandbox
|
|
7178
7368
|
*/
|
|
7179
7369
|
async stopWatching(sessionId) {
|
|
7180
|
-
const
|
|
7181
|
-
if (
|
|
7182
|
-
await
|
|
7183
|
-
this.
|
|
7370
|
+
const inSandboxWatcher = this.inSandboxWatchers.get(sessionId);
|
|
7371
|
+
if (inSandboxWatcher) {
|
|
7372
|
+
await inSandboxWatcher.stop();
|
|
7373
|
+
this.inSandboxWatchers.delete(sessionId);
|
|
7184
7374
|
}
|
|
7185
7375
|
const localWatcher = this.localWatchers.get(sessionId);
|
|
7186
7376
|
if (localWatcher) {
|
|
@@ -7192,7 +7382,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7192
7382
|
* Check if a session is being watched
|
|
7193
7383
|
*/
|
|
7194
7384
|
isWatching(sessionId) {
|
|
7195
|
-
return this.
|
|
7385
|
+
return this.inSandboxWatchers.has(sessionId) || this.localWatchers.has(sessionId);
|
|
7196
7386
|
}
|
|
7197
7387
|
/**
|
|
7198
7388
|
* Subscribe to file change events across all watched sessions.
|
|
@@ -7226,10 +7416,10 @@ var init_sandbox_file_sync = __esm({
|
|
|
7226
7416
|
* Stop all watchers and cleanup
|
|
7227
7417
|
*/
|
|
7228
7418
|
async stopAllWatching() {
|
|
7229
|
-
const
|
|
7419
|
+
const inSandboxPromises = Array.from(this.inSandboxWatchers.values()).map((w) => w.stop());
|
|
7230
7420
|
const localPromises = Array.from(this.localWatchers.values()).map((w) => w.stop());
|
|
7231
|
-
await Promise.all([...
|
|
7232
|
-
this.
|
|
7421
|
+
await Promise.all([...inSandboxPromises, ...localPromises]);
|
|
7422
|
+
this.inSandboxWatchers.clear();
|
|
7233
7423
|
this.localWatchers.clear();
|
|
7234
7424
|
}
|
|
7235
7425
|
/**
|
|
@@ -7237,8 +7427,8 @@ var init_sandbox_file_sync = __esm({
|
|
|
7237
7427
|
*/
|
|
7238
7428
|
getWatchingStatus() {
|
|
7239
7429
|
const statuses = [];
|
|
7240
|
-
for (const [sessionId, watcher] of this.
|
|
7241
|
-
statuses.push({ sessionId, type: "
|
|
7430
|
+
for (const [sessionId, watcher] of this.inSandboxWatchers) {
|
|
7431
|
+
statuses.push({ sessionId, type: "in-sandbox", isActive: watcher.isActive() });
|
|
7242
7432
|
}
|
|
7243
7433
|
for (const [sessionId, watcher] of this.localWatchers) {
|
|
7244
7434
|
statuses.push({ sessionId, type: "local", isActive: watcher.isActive() });
|
|
@@ -7249,363 +7439,6 @@ var init_sandbox_file_sync = __esm({
|
|
|
7249
7439
|
}
|
|
7250
7440
|
});
|
|
7251
7441
|
|
|
7252
|
-
// src/runtime/in-sandbox-watcher.ts
|
|
7253
|
-
function createInSandboxWatcher(options) {
|
|
7254
|
-
return new exports.InSandboxWatcher(options);
|
|
7255
|
-
}
|
|
7256
|
-
function getInSandboxWatcherManager() {
|
|
7257
|
-
if (!globalInSandboxManager) {
|
|
7258
|
-
globalInSandboxManager = new exports.InSandboxWatcherManager();
|
|
7259
|
-
}
|
|
7260
|
-
return globalInSandboxManager;
|
|
7261
|
-
}
|
|
7262
|
-
function createInSandboxWatcherManager() {
|
|
7263
|
-
return new exports.InSandboxWatcherManager();
|
|
7264
|
-
}
|
|
7265
|
-
var WATCHER_SCRIPT; exports.InSandboxWatcher = void 0; exports.InSandboxWatcherManager = void 0; var globalInSandboxManager;
|
|
7266
|
-
var init_in_sandbox_watcher = __esm({
|
|
7267
|
-
"src/runtime/in-sandbox-watcher.ts"() {
|
|
7268
|
-
init_vercel_sandbox_executor();
|
|
7269
|
-
WATCHER_SCRIPT = `
|
|
7270
|
-
const fs = require('fs');
|
|
7271
|
-
const path = require('path');
|
|
7272
|
-
|
|
7273
|
-
const watchPath = process.argv[2] || '.';
|
|
7274
|
-
const ignored = new Set(['node_modules', '.git', '.cache', '__pycache__']);
|
|
7275
|
-
|
|
7276
|
-
// Track all watchers for cleanup
|
|
7277
|
-
const watchers = new Map();
|
|
7278
|
-
|
|
7279
|
-
// Debounce map to coalesce rapid changes
|
|
7280
|
-
const pending = new Map();
|
|
7281
|
-
const DEBOUNCE_MS = 100;
|
|
7282
|
-
|
|
7283
|
-
function emit(type, filePath) {
|
|
7284
|
-
const event = {
|
|
7285
|
-
type,
|
|
7286
|
-
path: filePath,
|
|
7287
|
-
timestamp: Date.now()
|
|
7288
|
-
};
|
|
7289
|
-
console.log(JSON.stringify(event));
|
|
7290
|
-
}
|
|
7291
|
-
|
|
7292
|
-
function shouldIgnore(name) {
|
|
7293
|
-
return ignored.has(name) || name.startsWith('.');
|
|
7294
|
-
}
|
|
7295
|
-
|
|
7296
|
-
function watchDir(dir) {
|
|
7297
|
-
try {
|
|
7298
|
-
const watcher = fs.watch(dir, { persistent: true }, (eventType, filename) => {
|
|
7299
|
-
if (!filename || shouldIgnore(filename)) return;
|
|
7300
|
-
|
|
7301
|
-
const fullPath = path.join(dir, filename);
|
|
7302
|
-
const key = fullPath;
|
|
7303
|
-
|
|
7304
|
-
// Debounce
|
|
7305
|
-
if (pending.has(key)) {
|
|
7306
|
-
clearTimeout(pending.get(key));
|
|
7307
|
-
}
|
|
7308
|
-
|
|
7309
|
-
pending.set(key, setTimeout(() => {
|
|
7310
|
-
pending.delete(key);
|
|
7311
|
-
|
|
7312
|
-
fs.stat(fullPath, (err, stats) => {
|
|
7313
|
-
if (err) {
|
|
7314
|
-
if (err.code === 'ENOENT') {
|
|
7315
|
-
emit('unlink', fullPath);
|
|
7316
|
-
// Stop watching if it was a directory
|
|
7317
|
-
if (watchers.has(fullPath)) {
|
|
7318
|
-
watchers.get(fullPath).close();
|
|
7319
|
-
watchers.delete(fullPath);
|
|
7320
|
-
}
|
|
7321
|
-
}
|
|
7322
|
-
} else {
|
|
7323
|
-
const type = eventType === 'rename' ? 'add' : 'change';
|
|
7324
|
-
emit(type, fullPath);
|
|
7325
|
-
|
|
7326
|
-
// If it's a new directory, start watching it
|
|
7327
|
-
if (stats.isDirectory() && !watchers.has(fullPath)) {
|
|
7328
|
-
watchDir(fullPath);
|
|
7329
|
-
}
|
|
7330
|
-
}
|
|
7331
|
-
});
|
|
7332
|
-
}, DEBOUNCE_MS));
|
|
7333
|
-
});
|
|
7334
|
-
|
|
7335
|
-
watchers.set(dir, watcher);
|
|
7336
|
-
|
|
7337
|
-
// Watch subdirectories
|
|
7338
|
-
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
7339
|
-
for (const entry of entries) {
|
|
7340
|
-
if (entry.isDirectory() && !shouldIgnore(entry.name)) {
|
|
7341
|
-
watchDir(path.join(dir, entry.name));
|
|
7342
|
-
}
|
|
7343
|
-
}
|
|
7344
|
-
} catch (err) {
|
|
7345
|
-
// Directory may not exist or be inaccessible
|
|
7346
|
-
console.error(JSON.stringify({ error: err.message, dir }));
|
|
7347
|
-
}
|
|
7348
|
-
}
|
|
7349
|
-
|
|
7350
|
-
// Start watching
|
|
7351
|
-
watchDir(watchPath);
|
|
7352
|
-
|
|
7353
|
-
// Keep alive
|
|
7354
|
-
process.on('SIGTERM', () => {
|
|
7355
|
-
for (const watcher of watchers.values()) {
|
|
7356
|
-
watcher.close();
|
|
7357
|
-
}
|
|
7358
|
-
process.exit(0);
|
|
7359
|
-
});
|
|
7360
|
-
|
|
7361
|
-
// Heartbeat to indicate we're running
|
|
7362
|
-
setInterval(() => {
|
|
7363
|
-
console.log(JSON.stringify({ heartbeat: true, timestamp: Date.now() }));
|
|
7364
|
-
}, 5000);
|
|
7365
|
-
|
|
7366
|
-
console.log(JSON.stringify({ started: true, path: watchPath }));
|
|
7367
|
-
`;
|
|
7368
|
-
exports.InSandboxWatcher = class {
|
|
7369
|
-
sessionId;
|
|
7370
|
-
watchPath;
|
|
7371
|
-
outputPollIntervalMs;
|
|
7372
|
-
sandboxState = null;
|
|
7373
|
-
outputPollTimer = null;
|
|
7374
|
-
subscribers = /* @__PURE__ */ new Set();
|
|
7375
|
-
isRunning = false;
|
|
7376
|
-
startedAt;
|
|
7377
|
-
lastHeartbeat;
|
|
7378
|
-
lastOutputPosition = 0;
|
|
7379
|
-
onError;
|
|
7380
|
-
onReady;
|
|
7381
|
-
constructor(options) {
|
|
7382
|
-
this.sessionId = options.sessionId;
|
|
7383
|
-
this.watchPath = options.watchPath;
|
|
7384
|
-
this.outputPollIntervalMs = options.outputPollIntervalMs ?? 1e3;
|
|
7385
|
-
this.onError = options.onError;
|
|
7386
|
-
this.onReady = options.onReady;
|
|
7387
|
-
if (options.onFileChange) {
|
|
7388
|
-
this.subscribers.add(options.onFileChange);
|
|
7389
|
-
}
|
|
7390
|
-
}
|
|
7391
|
-
/**
|
|
7392
|
-
* Start the watcher process inside the sandbox
|
|
7393
|
-
*/
|
|
7394
|
-
async start() {
|
|
7395
|
-
if (this.isRunning) {
|
|
7396
|
-
console.warn(`[IN_SANDBOX_WATCHER] Already running for session ${this.sessionId}`);
|
|
7397
|
-
return;
|
|
7398
|
-
}
|
|
7399
|
-
try {
|
|
7400
|
-
this.sandboxState = await getOrCreateSandbox({
|
|
7401
|
-
sessionId: this.sessionId,
|
|
7402
|
-
runtime: "node22",
|
|
7403
|
-
timeout: 600
|
|
7404
|
-
});
|
|
7405
|
-
const { sandbox } = this.sandboxState;
|
|
7406
|
-
const scriptPath = "/tmp/.file-watcher.js";
|
|
7407
|
-
const outputPath = "/tmp/.file-watcher-output.log";
|
|
7408
|
-
const writeScriptCmd = `cat > ${scriptPath} << 'WATCHER_EOF'
|
|
7409
|
-
${WATCHER_SCRIPT}
|
|
7410
|
-
WATCHER_EOF`;
|
|
7411
|
-
await sandbox.runCommand({
|
|
7412
|
-
cmd: "sh",
|
|
7413
|
-
args: ["-c", writeScriptCmd]
|
|
7414
|
-
});
|
|
7415
|
-
const startCmd = `nohup node ${scriptPath} "${this.watchPath}" > ${outputPath} 2>&1 &`;
|
|
7416
|
-
await sandbox.runCommand({
|
|
7417
|
-
cmd: "sh",
|
|
7418
|
-
args: ["-c", startCmd]
|
|
7419
|
-
});
|
|
7420
|
-
console.log(`[IN_SANDBOX_WATCHER] Started watcher in sandbox for ${this.watchPath}`);
|
|
7421
|
-
this.isRunning = true;
|
|
7422
|
-
this.startedAt = /* @__PURE__ */ new Date();
|
|
7423
|
-
this.outputPollTimer = setInterval(async () => {
|
|
7424
|
-
try {
|
|
7425
|
-
await this.pollOutput(outputPath);
|
|
7426
|
-
} catch (error) {
|
|
7427
|
-
console.error("[IN_SANDBOX_WATCHER] Error polling output:", error);
|
|
7428
|
-
if (this.onError && error instanceof Error) {
|
|
7429
|
-
this.onError(error);
|
|
7430
|
-
}
|
|
7431
|
-
}
|
|
7432
|
-
}, this.outputPollIntervalMs);
|
|
7433
|
-
setTimeout(() => {
|
|
7434
|
-
this.pollOutput(outputPath).catch(console.error);
|
|
7435
|
-
}, 500);
|
|
7436
|
-
} catch (error) {
|
|
7437
|
-
console.error(`[IN_SANDBOX_WATCHER] Failed to start watcher:`, error);
|
|
7438
|
-
throw error;
|
|
7439
|
-
}
|
|
7440
|
-
}
|
|
7441
|
-
/**
|
|
7442
|
-
* Poll the output file for new events
|
|
7443
|
-
*/
|
|
7444
|
-
async pollOutput(outputPath) {
|
|
7445
|
-
if (!this.sandboxState?.sandbox) return;
|
|
7446
|
-
try {
|
|
7447
|
-
const result = await this.sandboxState.sandbox.runCommand({
|
|
7448
|
-
cmd: "sh",
|
|
7449
|
-
args: ["-c", `tail -c +${this.lastOutputPosition + 1} ${outputPath} 2>/dev/null || true`]
|
|
7450
|
-
});
|
|
7451
|
-
const output = await result.stdout();
|
|
7452
|
-
if (output && output.trim()) {
|
|
7453
|
-
const sizeResult = await this.sandboxState.sandbox.runCommand({
|
|
7454
|
-
cmd: "sh",
|
|
7455
|
-
args: ["-c", `stat -c%s ${outputPath} 2>/dev/null || echo 0`]
|
|
7456
|
-
});
|
|
7457
|
-
const sizeStr = await sizeResult.stdout();
|
|
7458
|
-
this.lastOutputPosition = parseInt(sizeStr.trim(), 10) || 0;
|
|
7459
|
-
this.processOutput(output);
|
|
7460
|
-
}
|
|
7461
|
-
} catch {
|
|
7462
|
-
}
|
|
7463
|
-
}
|
|
7464
|
-
/**
|
|
7465
|
-
* Process output from the watcher script
|
|
7466
|
-
*/
|
|
7467
|
-
processOutput(stdout) {
|
|
7468
|
-
const lines = stdout.split("\n").filter(Boolean);
|
|
7469
|
-
for (const line of lines) {
|
|
7470
|
-
try {
|
|
7471
|
-
const data = JSON.parse(line);
|
|
7472
|
-
if (data.started) {
|
|
7473
|
-
console.log(`[IN_SANDBOX_WATCHER] Watcher started for ${data.path}`);
|
|
7474
|
-
if (this.onReady) {
|
|
7475
|
-
this.onReady();
|
|
7476
|
-
}
|
|
7477
|
-
} else if (data.heartbeat) {
|
|
7478
|
-
this.lastHeartbeat = new Date(data.timestamp);
|
|
7479
|
-
} else if (data.error) {
|
|
7480
|
-
console.warn(`[IN_SANDBOX_WATCHER] Error in sandbox:`, data.error);
|
|
7481
|
-
} else if (data.type && data.path) {
|
|
7482
|
-
this.emitEvent({
|
|
7483
|
-
type: data.type,
|
|
7484
|
-
relativePath: data.path.replace(/^\.\//, ""),
|
|
7485
|
-
absolutePath: data.path,
|
|
7486
|
-
sessionId: this.sessionId,
|
|
7487
|
-
timestamp: new Date(data.timestamp)
|
|
7488
|
-
});
|
|
7489
|
-
}
|
|
7490
|
-
} catch {
|
|
7491
|
-
}
|
|
7492
|
-
}
|
|
7493
|
-
}
|
|
7494
|
-
/**
|
|
7495
|
-
* Stop the watcher process
|
|
7496
|
-
*/
|
|
7497
|
-
async stop() {
|
|
7498
|
-
if (!this.isRunning) {
|
|
7499
|
-
return;
|
|
7500
|
-
}
|
|
7501
|
-
if (this.outputPollTimer) {
|
|
7502
|
-
clearInterval(this.outputPollTimer);
|
|
7503
|
-
this.outputPollTimer = null;
|
|
7504
|
-
}
|
|
7505
|
-
try {
|
|
7506
|
-
if (this.sandboxState?.sandbox) {
|
|
7507
|
-
await this.sandboxState.sandbox.runCommand({
|
|
7508
|
-
cmd: "sh",
|
|
7509
|
-
args: ["-c", "pkill -f file-watcher.js 2>/dev/null || true"]
|
|
7510
|
-
});
|
|
7511
|
-
await this.sandboxState.sandbox.runCommand({
|
|
7512
|
-
cmd: "sh",
|
|
7513
|
-
args: ["-c", "rm -f /tmp/.file-watcher.js /tmp/.file-watcher-output.log"]
|
|
7514
|
-
});
|
|
7515
|
-
}
|
|
7516
|
-
} catch {
|
|
7517
|
-
}
|
|
7518
|
-
this.isRunning = false;
|
|
7519
|
-
this.sandboxState = null;
|
|
7520
|
-
this.lastOutputPosition = 0;
|
|
7521
|
-
console.log(`[IN_SANDBOX_WATCHER] Stopped watcher for session ${this.sessionId}`);
|
|
7522
|
-
}
|
|
7523
|
-
/**
|
|
7524
|
-
* Subscribe to file change events
|
|
7525
|
-
*/
|
|
7526
|
-
subscribe(callback) {
|
|
7527
|
-
this.subscribers.add(callback);
|
|
7528
|
-
return () => this.subscribers.delete(callback);
|
|
7529
|
-
}
|
|
7530
|
-
/**
|
|
7531
|
-
* Check if watcher is running
|
|
7532
|
-
*/
|
|
7533
|
-
isActive() {
|
|
7534
|
-
return this.isRunning;
|
|
7535
|
-
}
|
|
7536
|
-
/**
|
|
7537
|
-
* Get watcher status
|
|
7538
|
-
*/
|
|
7539
|
-
getStatus() {
|
|
7540
|
-
return {
|
|
7541
|
-
sessionId: this.sessionId,
|
|
7542
|
-
watchPath: this.watchPath,
|
|
7543
|
-
isRunning: this.isRunning,
|
|
7544
|
-
startedAt: this.startedAt,
|
|
7545
|
-
lastHeartbeat: this.lastHeartbeat
|
|
7546
|
-
};
|
|
7547
|
-
}
|
|
7548
|
-
/**
|
|
7549
|
-
* Emit event to all subscribers
|
|
7550
|
-
*/
|
|
7551
|
-
async emitEvent(event) {
|
|
7552
|
-
for (const callback of this.subscribers) {
|
|
7553
|
-
try {
|
|
7554
|
-
await callback(event);
|
|
7555
|
-
} catch (error) {
|
|
7556
|
-
console.error("[IN_SANDBOX_WATCHER] Error in subscriber callback:", error);
|
|
7557
|
-
}
|
|
7558
|
-
}
|
|
7559
|
-
}
|
|
7560
|
-
};
|
|
7561
|
-
exports.InSandboxWatcherManager = class {
|
|
7562
|
-
watchers = /* @__PURE__ */ new Map();
|
|
7563
|
-
/**
|
|
7564
|
-
* Start watching a sandbox
|
|
7565
|
-
*/
|
|
7566
|
-
async startWatching(options) {
|
|
7567
|
-
const { sessionId } = options;
|
|
7568
|
-
await this.stopWatching(sessionId);
|
|
7569
|
-
const watcher = new exports.InSandboxWatcher(options);
|
|
7570
|
-
await watcher.start();
|
|
7571
|
-
this.watchers.set(sessionId, watcher);
|
|
7572
|
-
return watcher;
|
|
7573
|
-
}
|
|
7574
|
-
/**
|
|
7575
|
-
* Stop watching a session
|
|
7576
|
-
*/
|
|
7577
|
-
async stopWatching(sessionId) {
|
|
7578
|
-
const watcher = this.watchers.get(sessionId);
|
|
7579
|
-
if (watcher) {
|
|
7580
|
-
await watcher.stop();
|
|
7581
|
-
this.watchers.delete(sessionId);
|
|
7582
|
-
}
|
|
7583
|
-
}
|
|
7584
|
-
/**
|
|
7585
|
-
* Get watcher for a session
|
|
7586
|
-
*/
|
|
7587
|
-
getWatcher(sessionId) {
|
|
7588
|
-
return this.watchers.get(sessionId);
|
|
7589
|
-
}
|
|
7590
|
-
/**
|
|
7591
|
-
* Check if watching
|
|
7592
|
-
*/
|
|
7593
|
-
isWatching(sessionId) {
|
|
7594
|
-
return this.watchers.get(sessionId)?.isActive() ?? false;
|
|
7595
|
-
}
|
|
7596
|
-
/**
|
|
7597
|
-
* Stop all watchers
|
|
7598
|
-
*/
|
|
7599
|
-
async stopAll() {
|
|
7600
|
-
const promises = Array.from(this.watchers.values()).map((w) => w.stop());
|
|
7601
|
-
await Promise.all(promises);
|
|
7602
|
-
this.watchers.clear();
|
|
7603
|
-
}
|
|
7604
|
-
};
|
|
7605
|
-
globalInSandboxManager = null;
|
|
7606
|
-
}
|
|
7607
|
-
});
|
|
7608
|
-
|
|
7609
7442
|
// src/runtime/index.ts
|
|
7610
7443
|
function generateDockerCommand(config) {
|
|
7611
7444
|
const args = ["docker", "run"];
|
|
@@ -19032,8 +18865,6 @@ exports.createQueueProcessor = createQueueProcessor;
|
|
|
19032
18865
|
exports.createQueueRouter = createQueueRouter;
|
|
19033
18866
|
exports.createR2BundleStore = createR2BundleStore;
|
|
19034
18867
|
exports.createR2FileStore = createR2FileStore;
|
|
19035
|
-
exports.createRemoteFileWatcher = createRemoteFileWatcher;
|
|
19036
|
-
exports.createRemoteFileWatcherManager = createRemoteFileWatcherManager;
|
|
19037
18868
|
exports.createS3BundleStore = createS3BundleStore;
|
|
19038
18869
|
exports.createS3FileStore = createS3FileStore;
|
|
19039
18870
|
exports.createSandboxFileOperations = createSandboxFileOperations;
|
|
@@ -19059,6 +18890,7 @@ exports.defineConfig = defineConfig;
|
|
|
19059
18890
|
exports.ensureSandboxPoolInitialized = ensureSandboxPoolInitialized;
|
|
19060
18891
|
exports.env = env;
|
|
19061
18892
|
exports.envOptional = envOptional;
|
|
18893
|
+
exports.executeCommandInSandbox = executeCommandInSandbox;
|
|
19062
18894
|
exports.extractTextContent = extractTextContent;
|
|
19063
18895
|
exports.extractTextFromMessage = extractTextFromMessage;
|
|
19064
18896
|
exports.formatToolName = formatToolName;
|
|
@@ -19071,12 +18903,12 @@ exports.getActionIcon = getActionIcon;
|
|
|
19071
18903
|
exports.getActionLabel = getActionLabel;
|
|
19072
18904
|
exports.getAllHeartbeatStatuses = getAllHeartbeatStatuses;
|
|
19073
18905
|
exports.getApiKeyEnvVar = getApiKeyEnvVar;
|
|
18906
|
+
exports.getCachedSandbox = getCachedSandbox;
|
|
19074
18907
|
exports.getDefaultModel = getDefaultModel;
|
|
19075
18908
|
exports.getFileWatcherManager = getFileWatcherManager;
|
|
19076
18909
|
exports.getHeartbeatStatus = getHeartbeatStatus;
|
|
19077
18910
|
exports.getInSandboxWatcherManager = getInSandboxWatcherManager;
|
|
19078
18911
|
exports.getOrCreateSandbox = getOrCreateSandbox;
|
|
19079
|
-
exports.getRemoteFileWatcherManager = getRemoteFileWatcherManager;
|
|
19080
18912
|
exports.getSandboxCacheStats = getSandboxCacheStats;
|
|
19081
18913
|
exports.getSandboxPool = getSandboxPool;
|
|
19082
18914
|
exports.getWorkspaceManager = getWorkspaceManager;
|