@ash-cloud/ash-ai 0.1.11 → 0.1.13
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 +204 -106
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +167 -20
- package/dist/index.d.ts +167 -20
- package/dist/index.js +204 -106
- package/dist/index.js.map +1 -1
- package/dist/playground.js +1275 -1126
- package/dist/{schema-B7RbjHWi.d.cts → schema-DSLyNeoS.d.cts} +3 -3
- package/dist/{schema-B7RbjHWi.d.ts → schema-DSLyNeoS.d.ts} +3 -3
- package/dist/schema.cjs +3 -1
- package/dist/schema.cjs.map +1 -1
- package/dist/schema.d.cts +1 -1
- package/dist/schema.d.ts +1 -1
- package/dist/schema.js +3 -1
- package/dist/schema.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -199,8 +199,10 @@ var init_types = __esm({
|
|
|
199
199
|
// error events
|
|
200
200
|
FILE: "file",
|
|
201
201
|
// file_push, file_pull, file_sync (file sync operations)
|
|
202
|
-
INPUT: "input"
|
|
202
|
+
INPUT: "input",
|
|
203
203
|
// user_input (user prompts/messages)
|
|
204
|
+
WEBHOOK: "webhook"
|
|
205
|
+
// webhook_delivery, webhook_failure (outbound webhook events)
|
|
204
206
|
};
|
|
205
207
|
}
|
|
206
208
|
});
|
|
@@ -5991,6 +5993,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
5991
5993
|
type,
|
|
5992
5994
|
relativePath,
|
|
5993
5995
|
absolutePath,
|
|
5996
|
+
basePath: this.watchPath,
|
|
5994
5997
|
sessionId: this.sessionId,
|
|
5995
5998
|
fileSize,
|
|
5996
5999
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -6199,6 +6202,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6199
6202
|
type: "add",
|
|
6200
6203
|
relativePath: filePath,
|
|
6201
6204
|
absolutePath: `${this.basePath}/${filePath}`,
|
|
6205
|
+
basePath: this.basePath,
|
|
6202
6206
|
sessionId: this.sessionId,
|
|
6203
6207
|
fileSize: info.size,
|
|
6204
6208
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -6211,6 +6215,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6211
6215
|
type: "unlink",
|
|
6212
6216
|
relativePath: filePath,
|
|
6213
6217
|
absolutePath: `${this.basePath}/${filePath}`,
|
|
6218
|
+
basePath: this.basePath,
|
|
6214
6219
|
sessionId: this.sessionId,
|
|
6215
6220
|
timestamp: /* @__PURE__ */ new Date()
|
|
6216
6221
|
});
|
|
@@ -6400,24 +6405,72 @@ var init_sandbox_file_sync = __esm({
|
|
|
6400
6405
|
removeWebhook() {
|
|
6401
6406
|
this.webhookConfig = void 0;
|
|
6402
6407
|
}
|
|
6408
|
+
/**
|
|
6409
|
+
* Extract hostname from URL for display (security - don't expose full URL)
|
|
6410
|
+
*/
|
|
6411
|
+
extractHostname(url) {
|
|
6412
|
+
try {
|
|
6413
|
+
const urlObj = new URL(url);
|
|
6414
|
+
return urlObj.hostname;
|
|
6415
|
+
} catch {
|
|
6416
|
+
return "unknown";
|
|
6417
|
+
}
|
|
6418
|
+
}
|
|
6419
|
+
/**
|
|
6420
|
+
* Persist webhook delivery event to the session timeline
|
|
6421
|
+
*/
|
|
6422
|
+
async persistWebhookDelivery(sessionId, webhookType, result, filePath, operation) {
|
|
6423
|
+
if (!this.eventStorage || !this.webhookConfig) return;
|
|
6424
|
+
try {
|
|
6425
|
+
const now = /* @__PURE__ */ new Date();
|
|
6426
|
+
const sequenceNumber = await this.getNextSequenceNumber(sessionId);
|
|
6427
|
+
const eventData = {
|
|
6428
|
+
webhookType,
|
|
6429
|
+
targetUrl: this.extractHostname(this.webhookConfig.url),
|
|
6430
|
+
success: result.success,
|
|
6431
|
+
statusCode: result.statusCode,
|
|
6432
|
+
error: result.error,
|
|
6433
|
+
durationMs: result.durationMs,
|
|
6434
|
+
retryCount: result.retryCount > 0 ? result.retryCount : void 0,
|
|
6435
|
+
filePath,
|
|
6436
|
+
operation
|
|
6437
|
+
};
|
|
6438
|
+
const eventType = result.success ? "webhook_delivery" : "webhook_failure";
|
|
6439
|
+
const sessionEvent = {
|
|
6440
|
+
eventType,
|
|
6441
|
+
category: EventCategory.WEBHOOK,
|
|
6442
|
+
startedAt: new Date(now.getTime() - result.durationMs),
|
|
6443
|
+
endedAt: now,
|
|
6444
|
+
durationMs: result.durationMs,
|
|
6445
|
+
eventData,
|
|
6446
|
+
sequenceNumber
|
|
6447
|
+
};
|
|
6448
|
+
await this.eventStorage.saveEvents(sessionId, [sessionEvent]);
|
|
6449
|
+
} catch (error) {
|
|
6450
|
+
console.error("[FILE_SYNC] Error saving webhook delivery event to storage:", error);
|
|
6451
|
+
}
|
|
6452
|
+
}
|
|
6403
6453
|
/**
|
|
6404
6454
|
* Send a webhook notification
|
|
6405
6455
|
* @param payload - The webhook payload to send
|
|
6456
|
+
* @param sessionId - Session ID for persisting delivery events
|
|
6457
|
+
* @returns WebhookDeliveryResult with success/failure info
|
|
6406
6458
|
*/
|
|
6407
|
-
async sendWebhook(payload) {
|
|
6408
|
-
if (!this.webhookConfig) return;
|
|
6459
|
+
async sendWebhook(payload, sessionId) {
|
|
6460
|
+
if (!this.webhookConfig) return null;
|
|
6409
6461
|
const config = this.webhookConfig;
|
|
6410
6462
|
const eventType = payload.fileSyncEvent?.operation ?? "file_change";
|
|
6411
6463
|
if (config.events && config.events.length > 0) {
|
|
6412
6464
|
const shouldSend = config.events.some(
|
|
6413
6465
|
(e) => e === eventType || e === "file_change" && payload.event === "file_change"
|
|
6414
6466
|
);
|
|
6415
|
-
if (!shouldSend) return;
|
|
6467
|
+
if (!shouldSend) return null;
|
|
6416
6468
|
}
|
|
6417
6469
|
const body = JSON.stringify(payload);
|
|
6418
6470
|
const timeoutMs = config.timeoutMs ?? 1e4;
|
|
6419
6471
|
const retries = config.retries ?? 3;
|
|
6420
6472
|
const isAsync = config.async !== false;
|
|
6473
|
+
const startTime = Date.now();
|
|
6421
6474
|
const headers = {
|
|
6422
6475
|
"Content-Type": "application/json",
|
|
6423
6476
|
"User-Agent": "Ash-FileSync/1.0",
|
|
@@ -6439,12 +6492,23 @@ var init_sandbox_file_sync = __esm({
|
|
|
6439
6492
|
signal: controller.signal
|
|
6440
6493
|
});
|
|
6441
6494
|
clearTimeout(timeoutId);
|
|
6495
|
+
const durationMs = Date.now() - startTime;
|
|
6442
6496
|
if (!response.ok) {
|
|
6443
|
-
|
|
6497
|
+
const error = `Webhook returned ${response.status}: ${response.statusText}`;
|
|
6498
|
+
if (attempt < retries) {
|
|
6499
|
+
const delay = Math.pow(2, attempt) * 1e3;
|
|
6500
|
+
console.warn(`[FILE_SYNC] Webhook failed (attempt ${attempt + 1}/${retries}), retrying in ${delay}ms: ${error}`);
|
|
6501
|
+
await new Promise((resolve3) => setTimeout(resolve3, delay));
|
|
6502
|
+
return sendWithRetry(attempt + 1);
|
|
6503
|
+
}
|
|
6504
|
+
console.error(`[FILE_SYNC] Webhook failed after ${retries} attempts: ${error}`);
|
|
6505
|
+
return { success: false, statusCode: response.status, error, durationMs, retryCount: attempt };
|
|
6444
6506
|
}
|
|
6445
6507
|
console.log(`[FILE_SYNC] Webhook sent successfully to ${config.url}`);
|
|
6508
|
+
return { success: true, statusCode: response.status, durationMs, retryCount: attempt };
|
|
6446
6509
|
} catch (error) {
|
|
6447
6510
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6511
|
+
const durationMs = Date.now() - startTime;
|
|
6448
6512
|
if (attempt < retries) {
|
|
6449
6513
|
const delay = Math.pow(2, attempt) * 1e3;
|
|
6450
6514
|
console.warn(`[FILE_SYNC] Webhook failed (attempt ${attempt + 1}/${retries}), retrying in ${delay}ms: ${errorMsg}`);
|
|
@@ -6452,15 +6516,27 @@ var init_sandbox_file_sync = __esm({
|
|
|
6452
6516
|
return sendWithRetry(attempt + 1);
|
|
6453
6517
|
}
|
|
6454
6518
|
console.error(`[FILE_SYNC] Webhook failed after ${retries} attempts: ${errorMsg}`);
|
|
6455
|
-
|
|
6519
|
+
return { success: false, error: errorMsg, durationMs, retryCount: attempt };
|
|
6456
6520
|
}
|
|
6457
6521
|
};
|
|
6522
|
+
const webhookType = payload.event === "file_sync" ? "file_sync" : "file_change";
|
|
6523
|
+
const filePath = payload.fileSyncEvent?.canonicalPath ?? payload.fileChangeEvent?.relativePath;
|
|
6524
|
+
const operation = payload.fileSyncEvent?.operation ?? payload.fileChangeEvent?.type;
|
|
6458
6525
|
if (isAsync) {
|
|
6459
|
-
sendWithRetry(0).
|
|
6526
|
+
sendWithRetry(0).then(async (result) => {
|
|
6527
|
+
if (sessionId) {
|
|
6528
|
+
await this.persistWebhookDelivery(sessionId, webhookType, result, filePath, operation);
|
|
6529
|
+
}
|
|
6530
|
+
}).catch((error) => {
|
|
6460
6531
|
console.error("[FILE_SYNC] Async webhook failed:", error);
|
|
6461
6532
|
});
|
|
6533
|
+
return null;
|
|
6462
6534
|
} else {
|
|
6463
|
-
await sendWithRetry(0);
|
|
6535
|
+
const result = await sendWithRetry(0);
|
|
6536
|
+
if (sessionId) {
|
|
6537
|
+
await this.persistWebhookDelivery(sessionId, webhookType, result, filePath, operation);
|
|
6538
|
+
}
|
|
6539
|
+
return result;
|
|
6464
6540
|
}
|
|
6465
6541
|
}
|
|
6466
6542
|
/**
|
|
@@ -6474,7 +6550,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6474
6550
|
metadata: this.webhookConfig?.metadata,
|
|
6475
6551
|
fileSyncEvent: event
|
|
6476
6552
|
};
|
|
6477
|
-
await this.sendWebhook(payload);
|
|
6553
|
+
await this.sendWebhook(payload, sessionId);
|
|
6478
6554
|
}
|
|
6479
6555
|
/**
|
|
6480
6556
|
* Send a file change event webhook (from watcher)
|
|
@@ -6487,7 +6563,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6487
6563
|
metadata: this.webhookConfig?.metadata,
|
|
6488
6564
|
fileChangeEvent: event
|
|
6489
6565
|
};
|
|
6490
|
-
await this.sendWebhook(payload);
|
|
6566
|
+
await this.sendWebhook(payload, event.sessionId);
|
|
6491
6567
|
}
|
|
6492
6568
|
/**
|
|
6493
6569
|
* Get the next sequence number for a session
|
|
@@ -6573,10 +6649,10 @@ var init_sandbox_file_sync = __esm({
|
|
|
6573
6649
|
const isTextFile = diff !== void 0 || event.newContent && !event.newContent.slice(0, 8192).includes(0);
|
|
6574
6650
|
const eventData = {
|
|
6575
6651
|
operation: event.operation,
|
|
6576
|
-
|
|
6577
|
-
|
|
6578
|
-
|
|
6579
|
-
|
|
6652
|
+
source: event.source,
|
|
6653
|
+
canonicalPath: event.canonicalPath,
|
|
6654
|
+
basePath: event.basePath,
|
|
6655
|
+
sandboxPath: event.sandboxPath,
|
|
6580
6656
|
fileSize: event.fileSize,
|
|
6581
6657
|
success: event.success,
|
|
6582
6658
|
error: event.error,
|
|
@@ -6584,7 +6660,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6584
6660
|
isTextFile,
|
|
6585
6661
|
previousSize: event.previousContent?.length
|
|
6586
6662
|
};
|
|
6587
|
-
const eventType =
|
|
6663
|
+
const eventType = event.operation;
|
|
6588
6664
|
const sessionEvent = {
|
|
6589
6665
|
eventType,
|
|
6590
6666
|
category: EventCategory.FILE,
|
|
@@ -6607,6 +6683,13 @@ var init_sandbox_file_sync = __esm({
|
|
|
6607
6683
|
setSandboxOperations(ops) {
|
|
6608
6684
|
this.sandboxOps = ops;
|
|
6609
6685
|
}
|
|
6686
|
+
/**
|
|
6687
|
+
* Get the effective base path for sandbox operations
|
|
6688
|
+
* @param targetPath - Optional override for the base path
|
|
6689
|
+
*/
|
|
6690
|
+
getBasePath(targetPath) {
|
|
6691
|
+
return targetPath ?? this.sandboxBasePath;
|
|
6692
|
+
}
|
|
6610
6693
|
/**
|
|
6611
6694
|
* Get the full sandbox path for a file
|
|
6612
6695
|
* @param path - The relative file path
|
|
@@ -6614,18 +6697,36 @@ var init_sandbox_file_sync = __esm({
|
|
|
6614
6697
|
*/
|
|
6615
6698
|
getSandboxPath(path15, targetPath) {
|
|
6616
6699
|
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6617
|
-
const basePath =
|
|
6700
|
+
const basePath = this.getBasePath(targetPath);
|
|
6618
6701
|
if (basePath === ".") {
|
|
6619
6702
|
return normalizedPath;
|
|
6620
6703
|
}
|
|
6621
6704
|
return `${basePath}/${normalizedPath}`;
|
|
6622
6705
|
}
|
|
6706
|
+
/**
|
|
6707
|
+
* Build all path fields for a FileSyncEvent
|
|
6708
|
+
* @param path - The canonical file path (used as S3 key)
|
|
6709
|
+
* @param targetPath - Optional override for the base path
|
|
6710
|
+
*/
|
|
6711
|
+
buildPathFields(path15, targetPath) {
|
|
6712
|
+
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6713
|
+
const basePath = this.getBasePath(targetPath);
|
|
6714
|
+
const sandboxPath = this.getSandboxPath(path15, targetPath);
|
|
6715
|
+
return {
|
|
6716
|
+
canonicalPath: normalizedPath,
|
|
6717
|
+
// The logical path (S3 key)
|
|
6718
|
+
basePath,
|
|
6719
|
+
// The prefix used in sandbox
|
|
6720
|
+
sandboxPath
|
|
6721
|
+
// Full computed path in sandbox
|
|
6722
|
+
};
|
|
6723
|
+
}
|
|
6623
6724
|
/**
|
|
6624
6725
|
* Push a file: writes to S3, then to sandbox if running
|
|
6625
6726
|
* @param sessionId - Session ID
|
|
6626
6727
|
* @param path - File path (stored in S3 and used as relative path in sandbox)
|
|
6627
6728
|
* @param content - File content
|
|
6628
|
-
* @param options - Push options (e.g., targetPath
|
|
6729
|
+
* @param options - Push options (e.g., targetPath, source)
|
|
6629
6730
|
* @param previousContent - Optional previous content for diff computation
|
|
6630
6731
|
*/
|
|
6631
6732
|
async pushFile(sessionId, path15, content, options, previousContent) {
|
|
@@ -6634,13 +6735,16 @@ var init_sandbox_file_sync = __esm({
|
|
|
6634
6735
|
s3Written: false,
|
|
6635
6736
|
sandboxWritten: false
|
|
6636
6737
|
};
|
|
6738
|
+
const source = options?.source ?? "client_api";
|
|
6739
|
+
const uploadToStorageOp = source === "client_api" ? "client_uploaded_to_ash_storage" : "agent_sandbox_saved_to_ash_storage";
|
|
6740
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6637
6741
|
try {
|
|
6638
6742
|
await this.fileStore.writeFile(sessionId, path15, content);
|
|
6639
6743
|
result.s3Written = true;
|
|
6640
6744
|
await this.emitFileEvent(sessionId, {
|
|
6641
|
-
operation:
|
|
6642
|
-
|
|
6643
|
-
|
|
6745
|
+
operation: uploadToStorageOp,
|
|
6746
|
+
source,
|
|
6747
|
+
...pathFields,
|
|
6644
6748
|
fileSize: content.length,
|
|
6645
6749
|
success: true,
|
|
6646
6750
|
previousContent,
|
|
@@ -6651,9 +6755,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6651
6755
|
result.error = `S3 write failed: ${errorMessage}`;
|
|
6652
6756
|
console.error(`[FILE_SYNC] S3 write failed for session ${sessionId}, path ${path15}:`, error);
|
|
6653
6757
|
await this.emitFileEvent(sessionId, {
|
|
6654
|
-
operation:
|
|
6655
|
-
|
|
6656
|
-
|
|
6758
|
+
operation: uploadToStorageOp,
|
|
6759
|
+
source,
|
|
6760
|
+
...pathFields,
|
|
6657
6761
|
fileSize: content.length,
|
|
6658
6762
|
success: false,
|
|
6659
6763
|
error: errorMessage
|
|
@@ -6662,13 +6766,12 @@ var init_sandbox_file_sync = __esm({
|
|
|
6662
6766
|
}
|
|
6663
6767
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6664
6768
|
try {
|
|
6665
|
-
const
|
|
6666
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
6769
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6667
6770
|
result.sandboxWritten = writeResult.success;
|
|
6668
6771
|
await this.emitFileEvent(sessionId, {
|
|
6669
|
-
operation: "
|
|
6670
|
-
|
|
6671
|
-
|
|
6772
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6773
|
+
source,
|
|
6774
|
+
...pathFields,
|
|
6672
6775
|
fileSize: content.length,
|
|
6673
6776
|
success: writeResult.success,
|
|
6674
6777
|
error: writeResult.error
|
|
@@ -6680,9 +6783,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6680
6783
|
const errorMessage = extractErrorMessage(error);
|
|
6681
6784
|
console.warn(`[FILE_SYNC] Sandbox write error for ${path15}: ${errorMessage}`);
|
|
6682
6785
|
await this.emitFileEvent(sessionId, {
|
|
6683
|
-
operation: "
|
|
6684
|
-
|
|
6685
|
-
|
|
6786
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6787
|
+
source,
|
|
6788
|
+
...pathFields,
|
|
6686
6789
|
fileSize: content.length,
|
|
6687
6790
|
success: false,
|
|
6688
6791
|
error: errorMessage
|
|
@@ -6710,8 +6813,12 @@ var init_sandbox_file_sync = __esm({
|
|
|
6710
6813
|
/**
|
|
6711
6814
|
* Pull a file from sandbox to S3
|
|
6712
6815
|
* Reads from sandbox and writes to S3
|
|
6816
|
+
*
|
|
6817
|
+
* @param sessionId - Session ID
|
|
6818
|
+
* @param path - File path (relative to sandbox)
|
|
6819
|
+
* @param options - Pull options (e.g., targetPath to override sandbox location)
|
|
6713
6820
|
*/
|
|
6714
|
-
async pullFile(sessionId, path15) {
|
|
6821
|
+
async pullFile(sessionId, path15, options) {
|
|
6715
6822
|
const result = {
|
|
6716
6823
|
path: path15,
|
|
6717
6824
|
content: null,
|
|
@@ -6721,15 +6828,15 @@ var init_sandbox_file_sync = __esm({
|
|
|
6721
6828
|
result.error = "Sandbox is not running";
|
|
6722
6829
|
return result;
|
|
6723
6830
|
}
|
|
6831
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6724
6832
|
try {
|
|
6725
|
-
const
|
|
6726
|
-
const readResult = await this.sandboxOps.readFile(sessionId, sandboxPath);
|
|
6833
|
+
const readResult = await this.sandboxOps.readFile(sessionId, pathFields.sandboxPath);
|
|
6727
6834
|
if (!readResult.success || !readResult.content) {
|
|
6728
6835
|
result.error = readResult.error ?? "File not found in sandbox";
|
|
6729
6836
|
await this.emitFileEvent(sessionId, {
|
|
6730
|
-
operation: "
|
|
6731
|
-
|
|
6732
|
-
|
|
6837
|
+
operation: "read_from_agent_sandbox",
|
|
6838
|
+
source: "ash_file_sync",
|
|
6839
|
+
...pathFields,
|
|
6733
6840
|
success: false,
|
|
6734
6841
|
error: result.error
|
|
6735
6842
|
});
|
|
@@ -6737,9 +6844,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6737
6844
|
}
|
|
6738
6845
|
result.content = readResult.content;
|
|
6739
6846
|
await this.emitFileEvent(sessionId, {
|
|
6740
|
-
operation: "
|
|
6741
|
-
|
|
6742
|
-
|
|
6847
|
+
operation: "read_from_agent_sandbox",
|
|
6848
|
+
source: "ash_file_sync",
|
|
6849
|
+
...pathFields,
|
|
6743
6850
|
fileSize: readResult.content.length,
|
|
6744
6851
|
success: true,
|
|
6745
6852
|
newContent: readResult.content
|
|
@@ -6748,9 +6855,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6748
6855
|
const errorMessage = extractErrorMessage(error);
|
|
6749
6856
|
result.error = `Sandbox read failed: ${errorMessage}`;
|
|
6750
6857
|
await this.emitFileEvent(sessionId, {
|
|
6751
|
-
operation: "
|
|
6752
|
-
|
|
6753
|
-
|
|
6858
|
+
operation: "read_from_agent_sandbox",
|
|
6859
|
+
source: "ash_file_sync",
|
|
6860
|
+
...pathFields,
|
|
6754
6861
|
success: false,
|
|
6755
6862
|
error: errorMessage
|
|
6756
6863
|
});
|
|
@@ -6760,9 +6867,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6760
6867
|
await this.fileStore.writeFile(sessionId, path15, result.content);
|
|
6761
6868
|
result.s3Written = true;
|
|
6762
6869
|
await this.emitFileEvent(sessionId, {
|
|
6763
|
-
operation: "
|
|
6764
|
-
|
|
6765
|
-
|
|
6870
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6871
|
+
source: "ash_file_sync",
|
|
6872
|
+
...pathFields,
|
|
6766
6873
|
fileSize: result.content.length,
|
|
6767
6874
|
success: true,
|
|
6768
6875
|
newContent: result.content
|
|
@@ -6772,9 +6879,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6772
6879
|
result.error = `S3 write failed: ${errorMessage}`;
|
|
6773
6880
|
console.error(`[FILE_SYNC] S3 write failed in pullFile for session ${sessionId}, path ${path15}:`, error);
|
|
6774
6881
|
await this.emitFileEvent(sessionId, {
|
|
6775
|
-
operation: "
|
|
6776
|
-
|
|
6777
|
-
|
|
6882
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6883
|
+
source: "ash_file_sync",
|
|
6884
|
+
...pathFields,
|
|
6778
6885
|
fileSize: result.content?.length,
|
|
6779
6886
|
success: false,
|
|
6780
6887
|
error: errorMessage
|
|
@@ -6816,43 +6923,43 @@ var init_sandbox_file_sync = __esm({
|
|
|
6816
6923
|
*/
|
|
6817
6924
|
async deleteFile(sessionId, path15) {
|
|
6818
6925
|
const result = { s3Deleted: false, sandboxDeleted: false };
|
|
6926
|
+
const pathFields = this.buildPathFields(path15);
|
|
6819
6927
|
try {
|
|
6820
6928
|
await this.fileStore.deleteFile(sessionId, path15);
|
|
6821
6929
|
result.s3Deleted = true;
|
|
6822
6930
|
await this.emitFileEvent(sessionId, {
|
|
6823
|
-
operation: "
|
|
6824
|
-
|
|
6825
|
-
|
|
6931
|
+
operation: "deleted_from_ash_storage",
|
|
6932
|
+
source: "ash_file_sync",
|
|
6933
|
+
...pathFields,
|
|
6826
6934
|
success: true
|
|
6827
6935
|
});
|
|
6828
6936
|
} catch (error) {
|
|
6829
6937
|
const errorMessage = extractErrorMessage(error);
|
|
6830
6938
|
console.warn(`[FILE_SYNC] S3 delete failed for ${path15}: ${errorMessage}`);
|
|
6831
6939
|
await this.emitFileEvent(sessionId, {
|
|
6832
|
-
operation: "
|
|
6833
|
-
|
|
6834
|
-
|
|
6940
|
+
operation: "deleted_from_ash_storage",
|
|
6941
|
+
source: "ash_file_sync",
|
|
6942
|
+
...pathFields,
|
|
6835
6943
|
success: false,
|
|
6836
6944
|
error: errorMessage
|
|
6837
6945
|
});
|
|
6838
6946
|
}
|
|
6839
6947
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6840
6948
|
try {
|
|
6841
|
-
|
|
6842
|
-
console.log(`[FILE_SYNC] Would delete ${sandboxPath} from sandbox`);
|
|
6949
|
+
console.log(`[FILE_SYNC] Would delete ${pathFields.sandboxPath} from sandbox`);
|
|
6843
6950
|
result.sandboxDeleted = true;
|
|
6844
6951
|
await this.emitFileEvent(sessionId, {
|
|
6845
|
-
operation: "
|
|
6846
|
-
|
|
6847
|
-
|
|
6952
|
+
operation: "deleted_from_agent_sandbox",
|
|
6953
|
+
source: "ash_file_sync",
|
|
6954
|
+
...pathFields,
|
|
6848
6955
|
success: true
|
|
6849
6956
|
});
|
|
6850
6957
|
} catch (error) {
|
|
6851
6958
|
const errorMessage = extractErrorMessage(error);
|
|
6852
6959
|
await this.emitFileEvent(sessionId, {
|
|
6853
|
-
operation: "
|
|
6854
|
-
|
|
6855
|
-
|
|
6960
|
+
operation: "deleted_from_agent_sandbox",
|
|
6961
|
+
source: "ash_file_sync",
|
|
6962
|
+
...pathFields,
|
|
6856
6963
|
success: false,
|
|
6857
6964
|
error: errorMessage
|
|
6858
6965
|
});
|
|
@@ -6872,36 +6979,36 @@ var init_sandbox_file_sync = __esm({
|
|
|
6872
6979
|
}
|
|
6873
6980
|
const files = await this.fileStore.listFiles(sessionId);
|
|
6874
6981
|
for (const file of files) {
|
|
6982
|
+
const pathFields = this.buildPathFields(file.path);
|
|
6875
6983
|
try {
|
|
6876
6984
|
const content = await this.fileStore.readFile(sessionId, file.path);
|
|
6877
6985
|
if (!content) {
|
|
6878
6986
|
result.errors.push({ path: file.path, error: "File not found in S3" });
|
|
6879
6987
|
await this.emitFileEvent(sessionId, {
|
|
6880
|
-
operation: "
|
|
6881
|
-
|
|
6882
|
-
|
|
6988
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6989
|
+
source: "ash_file_sync",
|
|
6990
|
+
...pathFields,
|
|
6883
6991
|
success: false,
|
|
6884
|
-
error: "File not found in
|
|
6992
|
+
error: "File not found in Ash storage"
|
|
6885
6993
|
});
|
|
6886
6994
|
continue;
|
|
6887
6995
|
}
|
|
6888
|
-
const
|
|
6889
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
6996
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6890
6997
|
if (writeResult.success) {
|
|
6891
6998
|
result.fileCount++;
|
|
6892
6999
|
await this.emitFileEvent(sessionId, {
|
|
6893
|
-
operation: "
|
|
6894
|
-
|
|
6895
|
-
|
|
7000
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7001
|
+
source: "ash_file_sync",
|
|
7002
|
+
...pathFields,
|
|
6896
7003
|
fileSize: content.length,
|
|
6897
7004
|
success: true
|
|
6898
7005
|
});
|
|
6899
7006
|
} else {
|
|
6900
7007
|
result.errors.push({ path: file.path, error: writeResult.error ?? "Unknown error" });
|
|
6901
7008
|
await this.emitFileEvent(sessionId, {
|
|
6902
|
-
operation: "
|
|
6903
|
-
|
|
6904
|
-
|
|
7009
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7010
|
+
source: "ash_file_sync",
|
|
7011
|
+
...pathFields,
|
|
6905
7012
|
fileSize: content.length,
|
|
6906
7013
|
success: false,
|
|
6907
7014
|
error: writeResult.error
|
|
@@ -6914,9 +7021,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6914
7021
|
error: errorMessage
|
|
6915
7022
|
});
|
|
6916
7023
|
await this.emitFileEvent(sessionId, {
|
|
6917
|
-
operation: "
|
|
6918
|
-
|
|
6919
|
-
|
|
7024
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7025
|
+
source: "ash_file_sync",
|
|
7026
|
+
...pathFields,
|
|
6920
7027
|
success: false,
|
|
6921
7028
|
error: errorMessage
|
|
6922
7029
|
});
|
|
@@ -6947,39 +7054,25 @@ var init_sandbox_file_sync = __esm({
|
|
|
6947
7054
|
return result;
|
|
6948
7055
|
}
|
|
6949
7056
|
}
|
|
6950
|
-
for (const
|
|
7057
|
+
for (const file of filesToSync) {
|
|
7058
|
+
const pathFields = this.buildPathFields(file);
|
|
6951
7059
|
try {
|
|
6952
|
-
const pullResult = await this.pullFile(sessionId,
|
|
7060
|
+
const pullResult = await this.pullFile(sessionId, file);
|
|
6953
7061
|
if (pullResult.s3Written) {
|
|
6954
7062
|
result.fileCount++;
|
|
6955
|
-
await this.emitFileEvent(sessionId, {
|
|
6956
|
-
operation: "sync_from_sandbox",
|
|
6957
|
-
direction: "to_s3",
|
|
6958
|
-
filePath,
|
|
6959
|
-
fileSize: pullResult.content?.length,
|
|
6960
|
-
success: true,
|
|
6961
|
-
newContent: pullResult.content ?? void 0
|
|
6962
|
-
});
|
|
6963
7063
|
} else if (pullResult.error) {
|
|
6964
|
-
result.errors.push({ path:
|
|
6965
|
-
await this.emitFileEvent(sessionId, {
|
|
6966
|
-
operation: "sync_from_sandbox",
|
|
6967
|
-
direction: "to_s3",
|
|
6968
|
-
filePath,
|
|
6969
|
-
success: false,
|
|
6970
|
-
error: pullResult.error
|
|
6971
|
-
});
|
|
7064
|
+
result.errors.push({ path: file, error: pullResult.error });
|
|
6972
7065
|
}
|
|
6973
7066
|
} catch (error) {
|
|
6974
7067
|
const errorMessage = extractErrorMessage(error);
|
|
6975
7068
|
result.errors.push({
|
|
6976
|
-
path:
|
|
7069
|
+
path: file,
|
|
6977
7070
|
error: errorMessage
|
|
6978
7071
|
});
|
|
6979
7072
|
await this.emitFileEvent(sessionId, {
|
|
6980
|
-
operation: "
|
|
6981
|
-
|
|
6982
|
-
|
|
7073
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
7074
|
+
source: "ash_file_sync",
|
|
7075
|
+
...pathFields,
|
|
6983
7076
|
success: false,
|
|
6984
7077
|
error: errorMessage
|
|
6985
7078
|
});
|
|
@@ -7014,9 +7107,10 @@ var init_sandbox_file_sync = __esm({
|
|
|
7014
7107
|
*/
|
|
7015
7108
|
async startWatching(sessionId, options) {
|
|
7016
7109
|
const opts = { ...this.defaultWatchOptions, ...options };
|
|
7110
|
+
const watchPath = opts.watchPaths?.[0] ?? ".";
|
|
7017
7111
|
await this.stopWatching(sessionId);
|
|
7018
7112
|
const handleFileChange = async (event) => {
|
|
7019
|
-
console.log(`[FILE_SYNC] File change detected: ${event.type} ${event.relativePath}`);
|
|
7113
|
+
console.log(`[FILE_SYNC] File change detected: ${event.type} ${event.relativePath} (watching from: ${watchPath})`);
|
|
7020
7114
|
if (this.webhookConfig) {
|
|
7021
7115
|
this.sendFileChangeWebhook(event);
|
|
7022
7116
|
}
|
|
@@ -7029,7 +7123,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7029
7123
|
}
|
|
7030
7124
|
if (event.type === "add" || event.type === "change") {
|
|
7031
7125
|
try {
|
|
7032
|
-
const pullResult = await this.pullFile(sessionId, event.relativePath);
|
|
7126
|
+
const pullResult = await this.pullFile(sessionId, event.relativePath, { targetPath: watchPath });
|
|
7033
7127
|
if (pullResult.s3Written) {
|
|
7034
7128
|
console.log(`[FILE_SYNC] Auto-synced ${event.relativePath} to S3`);
|
|
7035
7129
|
} else if (pullResult.error) {
|
|
@@ -7060,7 +7154,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7060
7154
|
});
|
|
7061
7155
|
await watcher.start();
|
|
7062
7156
|
this.localWatchers.set(sessionId, watcher);
|
|
7063
|
-
console.log(`[FILE_SYNC] Started local file watching for session ${sessionId}`);
|
|
7157
|
+
console.log(`[FILE_SYNC] Started local file watching for session ${sessionId} at ${opts.localPath}`);
|
|
7064
7158
|
} else {
|
|
7065
7159
|
if (!this.sandboxOps) {
|
|
7066
7160
|
throw new Error("Sandbox operations not configured. Call setSandboxOperations first.");
|
|
@@ -7068,7 +7162,8 @@ var init_sandbox_file_sync = __esm({
|
|
|
7068
7162
|
const watcher = new RemoteSandboxFileWatcher({
|
|
7069
7163
|
sessionId,
|
|
7070
7164
|
sandboxOps: this.sandboxOps,
|
|
7071
|
-
basePath:
|
|
7165
|
+
basePath: watchPath,
|
|
7166
|
+
// Use watchPath instead of sandboxBasePath
|
|
7072
7167
|
pollIntervalMs: opts.pollIntervalMs ?? 2e3,
|
|
7073
7168
|
ignored: opts.ignored ?? ["**/node_modules/**", "**/.git/**"],
|
|
7074
7169
|
onFileChange: handleFileChange,
|
|
@@ -7078,7 +7173,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7078
7173
|
});
|
|
7079
7174
|
await watcher.start();
|
|
7080
7175
|
this.remoteWatchers.set(sessionId, watcher);
|
|
7081
|
-
console.log(`[FILE_SYNC] Started remote file watching for session ${sessionId}`);
|
|
7176
|
+
console.log(`[FILE_SYNC] Started remote file watching for session ${sessionId} at path: ${watchPath}`);
|
|
7082
7177
|
}
|
|
7083
7178
|
}
|
|
7084
7179
|
/**
|
|
@@ -7391,6 +7486,7 @@ WATCHER_EOF`;
|
|
|
7391
7486
|
type: data.type,
|
|
7392
7487
|
relativePath: data.path.replace(/^\.\//, ""),
|
|
7393
7488
|
absolutePath: data.path,
|
|
7489
|
+
basePath: this.watchPath,
|
|
7394
7490
|
sessionId: this.sessionId,
|
|
7395
7491
|
timestamp: new Date(data.timestamp)
|
|
7396
7492
|
});
|
|
@@ -16213,8 +16309,10 @@ var init_schema = __esm({
|
|
|
16213
16309
|
// error events
|
|
16214
16310
|
"file",
|
|
16215
16311
|
// file_push, file_pull, file_sync (file sync operations)
|
|
16216
|
-
"input"
|
|
16312
|
+
"input",
|
|
16217
16313
|
// user_input (user prompts/messages)
|
|
16314
|
+
"webhook"
|
|
16315
|
+
// webhook_delivery, webhook_failure (outbound webhook events)
|
|
16218
16316
|
]);
|
|
16219
16317
|
sessions = pgTable(
|
|
16220
16318
|
"sessions",
|