@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.cjs
CHANGED
|
@@ -227,8 +227,10 @@ var init_types = __esm({
|
|
|
227
227
|
// error events
|
|
228
228
|
FILE: "file",
|
|
229
229
|
// file_push, file_pull, file_sync (file sync operations)
|
|
230
|
-
INPUT: "input"
|
|
230
|
+
INPUT: "input",
|
|
231
231
|
// user_input (user prompts/messages)
|
|
232
|
+
WEBHOOK: "webhook"
|
|
233
|
+
// webhook_delivery, webhook_failure (outbound webhook events)
|
|
232
234
|
};
|
|
233
235
|
}
|
|
234
236
|
});
|
|
@@ -6019,6 +6021,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6019
6021
|
type,
|
|
6020
6022
|
relativePath,
|
|
6021
6023
|
absolutePath,
|
|
6024
|
+
basePath: this.watchPath,
|
|
6022
6025
|
sessionId: this.sessionId,
|
|
6023
6026
|
fileSize,
|
|
6024
6027
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -6227,6 +6230,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6227
6230
|
type: "add",
|
|
6228
6231
|
relativePath: filePath,
|
|
6229
6232
|
absolutePath: `${this.basePath}/${filePath}`,
|
|
6233
|
+
basePath: this.basePath,
|
|
6230
6234
|
sessionId: this.sessionId,
|
|
6231
6235
|
fileSize: info.size,
|
|
6232
6236
|
timestamp: /* @__PURE__ */ new Date()
|
|
@@ -6239,6 +6243,7 @@ var init_sandbox_file_watcher = __esm({
|
|
|
6239
6243
|
type: "unlink",
|
|
6240
6244
|
relativePath: filePath,
|
|
6241
6245
|
absolutePath: `${this.basePath}/${filePath}`,
|
|
6246
|
+
basePath: this.basePath,
|
|
6242
6247
|
sessionId: this.sessionId,
|
|
6243
6248
|
timestamp: /* @__PURE__ */ new Date()
|
|
6244
6249
|
});
|
|
@@ -6428,24 +6433,72 @@ var init_sandbox_file_sync = __esm({
|
|
|
6428
6433
|
removeWebhook() {
|
|
6429
6434
|
this.webhookConfig = void 0;
|
|
6430
6435
|
}
|
|
6436
|
+
/**
|
|
6437
|
+
* Extract hostname from URL for display (security - don't expose full URL)
|
|
6438
|
+
*/
|
|
6439
|
+
extractHostname(url) {
|
|
6440
|
+
try {
|
|
6441
|
+
const urlObj = new URL(url);
|
|
6442
|
+
return urlObj.hostname;
|
|
6443
|
+
} catch {
|
|
6444
|
+
return "unknown";
|
|
6445
|
+
}
|
|
6446
|
+
}
|
|
6447
|
+
/**
|
|
6448
|
+
* Persist webhook delivery event to the session timeline
|
|
6449
|
+
*/
|
|
6450
|
+
async persistWebhookDelivery(sessionId, webhookType, result, filePath, operation) {
|
|
6451
|
+
if (!this.eventStorage || !this.webhookConfig) return;
|
|
6452
|
+
try {
|
|
6453
|
+
const now = /* @__PURE__ */ new Date();
|
|
6454
|
+
const sequenceNumber = await this.getNextSequenceNumber(sessionId);
|
|
6455
|
+
const eventData = {
|
|
6456
|
+
webhookType,
|
|
6457
|
+
targetUrl: this.extractHostname(this.webhookConfig.url),
|
|
6458
|
+
success: result.success,
|
|
6459
|
+
statusCode: result.statusCode,
|
|
6460
|
+
error: result.error,
|
|
6461
|
+
durationMs: result.durationMs,
|
|
6462
|
+
retryCount: result.retryCount > 0 ? result.retryCount : void 0,
|
|
6463
|
+
filePath,
|
|
6464
|
+
operation
|
|
6465
|
+
};
|
|
6466
|
+
const eventType = result.success ? "webhook_delivery" : "webhook_failure";
|
|
6467
|
+
const sessionEvent = {
|
|
6468
|
+
eventType,
|
|
6469
|
+
category: exports.EventCategory.WEBHOOK,
|
|
6470
|
+
startedAt: new Date(now.getTime() - result.durationMs),
|
|
6471
|
+
endedAt: now,
|
|
6472
|
+
durationMs: result.durationMs,
|
|
6473
|
+
eventData,
|
|
6474
|
+
sequenceNumber
|
|
6475
|
+
};
|
|
6476
|
+
await this.eventStorage.saveEvents(sessionId, [sessionEvent]);
|
|
6477
|
+
} catch (error) {
|
|
6478
|
+
console.error("[FILE_SYNC] Error saving webhook delivery event to storage:", error);
|
|
6479
|
+
}
|
|
6480
|
+
}
|
|
6431
6481
|
/**
|
|
6432
6482
|
* Send a webhook notification
|
|
6433
6483
|
* @param payload - The webhook payload to send
|
|
6484
|
+
* @param sessionId - Session ID for persisting delivery events
|
|
6485
|
+
* @returns WebhookDeliveryResult with success/failure info
|
|
6434
6486
|
*/
|
|
6435
|
-
async sendWebhook(payload) {
|
|
6436
|
-
if (!this.webhookConfig) return;
|
|
6487
|
+
async sendWebhook(payload, sessionId) {
|
|
6488
|
+
if (!this.webhookConfig) return null;
|
|
6437
6489
|
const config = this.webhookConfig;
|
|
6438
6490
|
const eventType = payload.fileSyncEvent?.operation ?? "file_change";
|
|
6439
6491
|
if (config.events && config.events.length > 0) {
|
|
6440
6492
|
const shouldSend = config.events.some(
|
|
6441
6493
|
(e) => e === eventType || e === "file_change" && payload.event === "file_change"
|
|
6442
6494
|
);
|
|
6443
|
-
if (!shouldSend) return;
|
|
6495
|
+
if (!shouldSend) return null;
|
|
6444
6496
|
}
|
|
6445
6497
|
const body = JSON.stringify(payload);
|
|
6446
6498
|
const timeoutMs = config.timeoutMs ?? 1e4;
|
|
6447
6499
|
const retries = config.retries ?? 3;
|
|
6448
6500
|
const isAsync = config.async !== false;
|
|
6501
|
+
const startTime = Date.now();
|
|
6449
6502
|
const headers = {
|
|
6450
6503
|
"Content-Type": "application/json",
|
|
6451
6504
|
"User-Agent": "Ash-FileSync/1.0",
|
|
@@ -6467,12 +6520,23 @@ var init_sandbox_file_sync = __esm({
|
|
|
6467
6520
|
signal: controller.signal
|
|
6468
6521
|
});
|
|
6469
6522
|
clearTimeout(timeoutId);
|
|
6523
|
+
const durationMs = Date.now() - startTime;
|
|
6470
6524
|
if (!response.ok) {
|
|
6471
|
-
|
|
6525
|
+
const error = `Webhook returned ${response.status}: ${response.statusText}`;
|
|
6526
|
+
if (attempt < retries) {
|
|
6527
|
+
const delay = Math.pow(2, attempt) * 1e3;
|
|
6528
|
+
console.warn(`[FILE_SYNC] Webhook failed (attempt ${attempt + 1}/${retries}), retrying in ${delay}ms: ${error}`);
|
|
6529
|
+
await new Promise((resolve3) => setTimeout(resolve3, delay));
|
|
6530
|
+
return sendWithRetry(attempt + 1);
|
|
6531
|
+
}
|
|
6532
|
+
console.error(`[FILE_SYNC] Webhook failed after ${retries} attempts: ${error}`);
|
|
6533
|
+
return { success: false, statusCode: response.status, error, durationMs, retryCount: attempt };
|
|
6472
6534
|
}
|
|
6473
6535
|
console.log(`[FILE_SYNC] Webhook sent successfully to ${config.url}`);
|
|
6536
|
+
return { success: true, statusCode: response.status, durationMs, retryCount: attempt };
|
|
6474
6537
|
} catch (error) {
|
|
6475
6538
|
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
6539
|
+
const durationMs = Date.now() - startTime;
|
|
6476
6540
|
if (attempt < retries) {
|
|
6477
6541
|
const delay = Math.pow(2, attempt) * 1e3;
|
|
6478
6542
|
console.warn(`[FILE_SYNC] Webhook failed (attempt ${attempt + 1}/${retries}), retrying in ${delay}ms: ${errorMsg}`);
|
|
@@ -6480,15 +6544,27 @@ var init_sandbox_file_sync = __esm({
|
|
|
6480
6544
|
return sendWithRetry(attempt + 1);
|
|
6481
6545
|
}
|
|
6482
6546
|
console.error(`[FILE_SYNC] Webhook failed after ${retries} attempts: ${errorMsg}`);
|
|
6483
|
-
|
|
6547
|
+
return { success: false, error: errorMsg, durationMs, retryCount: attempt };
|
|
6484
6548
|
}
|
|
6485
6549
|
};
|
|
6550
|
+
const webhookType = payload.event === "file_sync" ? "file_sync" : "file_change";
|
|
6551
|
+
const filePath = payload.fileSyncEvent?.canonicalPath ?? payload.fileChangeEvent?.relativePath;
|
|
6552
|
+
const operation = payload.fileSyncEvent?.operation ?? payload.fileChangeEvent?.type;
|
|
6486
6553
|
if (isAsync) {
|
|
6487
|
-
sendWithRetry(0).
|
|
6554
|
+
sendWithRetry(0).then(async (result) => {
|
|
6555
|
+
if (sessionId) {
|
|
6556
|
+
await this.persistWebhookDelivery(sessionId, webhookType, result, filePath, operation);
|
|
6557
|
+
}
|
|
6558
|
+
}).catch((error) => {
|
|
6488
6559
|
console.error("[FILE_SYNC] Async webhook failed:", error);
|
|
6489
6560
|
});
|
|
6561
|
+
return null;
|
|
6490
6562
|
} else {
|
|
6491
|
-
await sendWithRetry(0);
|
|
6563
|
+
const result = await sendWithRetry(0);
|
|
6564
|
+
if (sessionId) {
|
|
6565
|
+
await this.persistWebhookDelivery(sessionId, webhookType, result, filePath, operation);
|
|
6566
|
+
}
|
|
6567
|
+
return result;
|
|
6492
6568
|
}
|
|
6493
6569
|
}
|
|
6494
6570
|
/**
|
|
@@ -6502,7 +6578,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6502
6578
|
metadata: this.webhookConfig?.metadata,
|
|
6503
6579
|
fileSyncEvent: event
|
|
6504
6580
|
};
|
|
6505
|
-
await this.sendWebhook(payload);
|
|
6581
|
+
await this.sendWebhook(payload, sessionId);
|
|
6506
6582
|
}
|
|
6507
6583
|
/**
|
|
6508
6584
|
* Send a file change event webhook (from watcher)
|
|
@@ -6515,7 +6591,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6515
6591
|
metadata: this.webhookConfig?.metadata,
|
|
6516
6592
|
fileChangeEvent: event
|
|
6517
6593
|
};
|
|
6518
|
-
await this.sendWebhook(payload);
|
|
6594
|
+
await this.sendWebhook(payload, event.sessionId);
|
|
6519
6595
|
}
|
|
6520
6596
|
/**
|
|
6521
6597
|
* Get the next sequence number for a session
|
|
@@ -6601,10 +6677,10 @@ var init_sandbox_file_sync = __esm({
|
|
|
6601
6677
|
const isTextFile = diff !== void 0 || event.newContent && !event.newContent.slice(0, 8192).includes(0);
|
|
6602
6678
|
const eventData = {
|
|
6603
6679
|
operation: event.operation,
|
|
6604
|
-
|
|
6605
|
-
|
|
6606
|
-
|
|
6607
|
-
|
|
6680
|
+
source: event.source,
|
|
6681
|
+
canonicalPath: event.canonicalPath,
|
|
6682
|
+
basePath: event.basePath,
|
|
6683
|
+
sandboxPath: event.sandboxPath,
|
|
6608
6684
|
fileSize: event.fileSize,
|
|
6609
6685
|
success: event.success,
|
|
6610
6686
|
error: event.error,
|
|
@@ -6612,7 +6688,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
6612
6688
|
isTextFile,
|
|
6613
6689
|
previousSize: event.previousContent?.length
|
|
6614
6690
|
};
|
|
6615
|
-
const eventType =
|
|
6691
|
+
const eventType = event.operation;
|
|
6616
6692
|
const sessionEvent = {
|
|
6617
6693
|
eventType,
|
|
6618
6694
|
category: exports.EventCategory.FILE,
|
|
@@ -6635,6 +6711,13 @@ var init_sandbox_file_sync = __esm({
|
|
|
6635
6711
|
setSandboxOperations(ops) {
|
|
6636
6712
|
this.sandboxOps = ops;
|
|
6637
6713
|
}
|
|
6714
|
+
/**
|
|
6715
|
+
* Get the effective base path for sandbox operations
|
|
6716
|
+
* @param targetPath - Optional override for the base path
|
|
6717
|
+
*/
|
|
6718
|
+
getBasePath(targetPath) {
|
|
6719
|
+
return targetPath ?? this.sandboxBasePath;
|
|
6720
|
+
}
|
|
6638
6721
|
/**
|
|
6639
6722
|
* Get the full sandbox path for a file
|
|
6640
6723
|
* @param path - The relative file path
|
|
@@ -6642,18 +6725,36 @@ var init_sandbox_file_sync = __esm({
|
|
|
6642
6725
|
*/
|
|
6643
6726
|
getSandboxPath(path15, targetPath) {
|
|
6644
6727
|
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6645
|
-
const basePath =
|
|
6728
|
+
const basePath = this.getBasePath(targetPath);
|
|
6646
6729
|
if (basePath === ".") {
|
|
6647
6730
|
return normalizedPath;
|
|
6648
6731
|
}
|
|
6649
6732
|
return `${basePath}/${normalizedPath}`;
|
|
6650
6733
|
}
|
|
6734
|
+
/**
|
|
6735
|
+
* Build all path fields for a FileSyncEvent
|
|
6736
|
+
* @param path - The canonical file path (used as S3 key)
|
|
6737
|
+
* @param targetPath - Optional override for the base path
|
|
6738
|
+
*/
|
|
6739
|
+
buildPathFields(path15, targetPath) {
|
|
6740
|
+
const normalizedPath = path15.replace(/^\/+/, "");
|
|
6741
|
+
const basePath = this.getBasePath(targetPath);
|
|
6742
|
+
const sandboxPath = this.getSandboxPath(path15, targetPath);
|
|
6743
|
+
return {
|
|
6744
|
+
canonicalPath: normalizedPath,
|
|
6745
|
+
// The logical path (S3 key)
|
|
6746
|
+
basePath,
|
|
6747
|
+
// The prefix used in sandbox
|
|
6748
|
+
sandboxPath
|
|
6749
|
+
// Full computed path in sandbox
|
|
6750
|
+
};
|
|
6751
|
+
}
|
|
6651
6752
|
/**
|
|
6652
6753
|
* Push a file: writes to S3, then to sandbox if running
|
|
6653
6754
|
* @param sessionId - Session ID
|
|
6654
6755
|
* @param path - File path (stored in S3 and used as relative path in sandbox)
|
|
6655
6756
|
* @param content - File content
|
|
6656
|
-
* @param options - Push options (e.g., targetPath
|
|
6757
|
+
* @param options - Push options (e.g., targetPath, source)
|
|
6657
6758
|
* @param previousContent - Optional previous content for diff computation
|
|
6658
6759
|
*/
|
|
6659
6760
|
async pushFile(sessionId, path15, content, options, previousContent) {
|
|
@@ -6662,13 +6763,16 @@ var init_sandbox_file_sync = __esm({
|
|
|
6662
6763
|
s3Written: false,
|
|
6663
6764
|
sandboxWritten: false
|
|
6664
6765
|
};
|
|
6766
|
+
const source = options?.source ?? "client_api";
|
|
6767
|
+
const uploadToStorageOp = source === "client_api" ? "client_uploaded_to_ash_storage" : "agent_sandbox_saved_to_ash_storage";
|
|
6768
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6665
6769
|
try {
|
|
6666
6770
|
await this.fileStore.writeFile(sessionId, path15, content);
|
|
6667
6771
|
result.s3Written = true;
|
|
6668
6772
|
await this.emitFileEvent(sessionId, {
|
|
6669
|
-
operation:
|
|
6670
|
-
|
|
6671
|
-
|
|
6773
|
+
operation: uploadToStorageOp,
|
|
6774
|
+
source,
|
|
6775
|
+
...pathFields,
|
|
6672
6776
|
fileSize: content.length,
|
|
6673
6777
|
success: true,
|
|
6674
6778
|
previousContent,
|
|
@@ -6679,9 +6783,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6679
6783
|
result.error = `S3 write failed: ${errorMessage}`;
|
|
6680
6784
|
console.error(`[FILE_SYNC] S3 write failed for session ${sessionId}, path ${path15}:`, error);
|
|
6681
6785
|
await this.emitFileEvent(sessionId, {
|
|
6682
|
-
operation:
|
|
6683
|
-
|
|
6684
|
-
|
|
6786
|
+
operation: uploadToStorageOp,
|
|
6787
|
+
source,
|
|
6788
|
+
...pathFields,
|
|
6685
6789
|
fileSize: content.length,
|
|
6686
6790
|
success: false,
|
|
6687
6791
|
error: errorMessage
|
|
@@ -6690,13 +6794,12 @@ var init_sandbox_file_sync = __esm({
|
|
|
6690
6794
|
}
|
|
6691
6795
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6692
6796
|
try {
|
|
6693
|
-
const
|
|
6694
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
6797
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6695
6798
|
result.sandboxWritten = writeResult.success;
|
|
6696
6799
|
await this.emitFileEvent(sessionId, {
|
|
6697
|
-
operation: "
|
|
6698
|
-
|
|
6699
|
-
|
|
6800
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6801
|
+
source,
|
|
6802
|
+
...pathFields,
|
|
6700
6803
|
fileSize: content.length,
|
|
6701
6804
|
success: writeResult.success,
|
|
6702
6805
|
error: writeResult.error
|
|
@@ -6708,9 +6811,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6708
6811
|
const errorMessage = extractErrorMessage(error);
|
|
6709
6812
|
console.warn(`[FILE_SYNC] Sandbox write error for ${path15}: ${errorMessage}`);
|
|
6710
6813
|
await this.emitFileEvent(sessionId, {
|
|
6711
|
-
operation: "
|
|
6712
|
-
|
|
6713
|
-
|
|
6814
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
6815
|
+
source,
|
|
6816
|
+
...pathFields,
|
|
6714
6817
|
fileSize: content.length,
|
|
6715
6818
|
success: false,
|
|
6716
6819
|
error: errorMessage
|
|
@@ -6738,8 +6841,12 @@ var init_sandbox_file_sync = __esm({
|
|
|
6738
6841
|
/**
|
|
6739
6842
|
* Pull a file from sandbox to S3
|
|
6740
6843
|
* Reads from sandbox and writes to S3
|
|
6844
|
+
*
|
|
6845
|
+
* @param sessionId - Session ID
|
|
6846
|
+
* @param path - File path (relative to sandbox)
|
|
6847
|
+
* @param options - Pull options (e.g., targetPath to override sandbox location)
|
|
6741
6848
|
*/
|
|
6742
|
-
async pullFile(sessionId, path15) {
|
|
6849
|
+
async pullFile(sessionId, path15, options) {
|
|
6743
6850
|
const result = {
|
|
6744
6851
|
path: path15,
|
|
6745
6852
|
content: null,
|
|
@@ -6749,15 +6856,15 @@ var init_sandbox_file_sync = __esm({
|
|
|
6749
6856
|
result.error = "Sandbox is not running";
|
|
6750
6857
|
return result;
|
|
6751
6858
|
}
|
|
6859
|
+
const pathFields = this.buildPathFields(path15, options?.targetPath);
|
|
6752
6860
|
try {
|
|
6753
|
-
const
|
|
6754
|
-
const readResult = await this.sandboxOps.readFile(sessionId, sandboxPath);
|
|
6861
|
+
const readResult = await this.sandboxOps.readFile(sessionId, pathFields.sandboxPath);
|
|
6755
6862
|
if (!readResult.success || !readResult.content) {
|
|
6756
6863
|
result.error = readResult.error ?? "File not found in sandbox";
|
|
6757
6864
|
await this.emitFileEvent(sessionId, {
|
|
6758
|
-
operation: "
|
|
6759
|
-
|
|
6760
|
-
|
|
6865
|
+
operation: "read_from_agent_sandbox",
|
|
6866
|
+
source: "ash_file_sync",
|
|
6867
|
+
...pathFields,
|
|
6761
6868
|
success: false,
|
|
6762
6869
|
error: result.error
|
|
6763
6870
|
});
|
|
@@ -6765,9 +6872,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6765
6872
|
}
|
|
6766
6873
|
result.content = readResult.content;
|
|
6767
6874
|
await this.emitFileEvent(sessionId, {
|
|
6768
|
-
operation: "
|
|
6769
|
-
|
|
6770
|
-
|
|
6875
|
+
operation: "read_from_agent_sandbox",
|
|
6876
|
+
source: "ash_file_sync",
|
|
6877
|
+
...pathFields,
|
|
6771
6878
|
fileSize: readResult.content.length,
|
|
6772
6879
|
success: true,
|
|
6773
6880
|
newContent: readResult.content
|
|
@@ -6776,9 +6883,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6776
6883
|
const errorMessage = extractErrorMessage(error);
|
|
6777
6884
|
result.error = `Sandbox read failed: ${errorMessage}`;
|
|
6778
6885
|
await this.emitFileEvent(sessionId, {
|
|
6779
|
-
operation: "
|
|
6780
|
-
|
|
6781
|
-
|
|
6886
|
+
operation: "read_from_agent_sandbox",
|
|
6887
|
+
source: "ash_file_sync",
|
|
6888
|
+
...pathFields,
|
|
6782
6889
|
success: false,
|
|
6783
6890
|
error: errorMessage
|
|
6784
6891
|
});
|
|
@@ -6788,9 +6895,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6788
6895
|
await this.fileStore.writeFile(sessionId, path15, result.content);
|
|
6789
6896
|
result.s3Written = true;
|
|
6790
6897
|
await this.emitFileEvent(sessionId, {
|
|
6791
|
-
operation: "
|
|
6792
|
-
|
|
6793
|
-
|
|
6898
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6899
|
+
source: "ash_file_sync",
|
|
6900
|
+
...pathFields,
|
|
6794
6901
|
fileSize: result.content.length,
|
|
6795
6902
|
success: true,
|
|
6796
6903
|
newContent: result.content
|
|
@@ -6800,9 +6907,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6800
6907
|
result.error = `S3 write failed: ${errorMessage}`;
|
|
6801
6908
|
console.error(`[FILE_SYNC] S3 write failed in pullFile for session ${sessionId}, path ${path15}:`, error);
|
|
6802
6909
|
await this.emitFileEvent(sessionId, {
|
|
6803
|
-
operation: "
|
|
6804
|
-
|
|
6805
|
-
|
|
6910
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
6911
|
+
source: "ash_file_sync",
|
|
6912
|
+
...pathFields,
|
|
6806
6913
|
fileSize: result.content?.length,
|
|
6807
6914
|
success: false,
|
|
6808
6915
|
error: errorMessage
|
|
@@ -6844,43 +6951,43 @@ var init_sandbox_file_sync = __esm({
|
|
|
6844
6951
|
*/
|
|
6845
6952
|
async deleteFile(sessionId, path15) {
|
|
6846
6953
|
const result = { s3Deleted: false, sandboxDeleted: false };
|
|
6954
|
+
const pathFields = this.buildPathFields(path15);
|
|
6847
6955
|
try {
|
|
6848
6956
|
await this.fileStore.deleteFile(sessionId, path15);
|
|
6849
6957
|
result.s3Deleted = true;
|
|
6850
6958
|
await this.emitFileEvent(sessionId, {
|
|
6851
|
-
operation: "
|
|
6852
|
-
|
|
6853
|
-
|
|
6959
|
+
operation: "deleted_from_ash_storage",
|
|
6960
|
+
source: "ash_file_sync",
|
|
6961
|
+
...pathFields,
|
|
6854
6962
|
success: true
|
|
6855
6963
|
});
|
|
6856
6964
|
} catch (error) {
|
|
6857
6965
|
const errorMessage = extractErrorMessage(error);
|
|
6858
6966
|
console.warn(`[FILE_SYNC] S3 delete failed for ${path15}: ${errorMessage}`);
|
|
6859
6967
|
await this.emitFileEvent(sessionId, {
|
|
6860
|
-
operation: "
|
|
6861
|
-
|
|
6862
|
-
|
|
6968
|
+
operation: "deleted_from_ash_storage",
|
|
6969
|
+
source: "ash_file_sync",
|
|
6970
|
+
...pathFields,
|
|
6863
6971
|
success: false,
|
|
6864
6972
|
error: errorMessage
|
|
6865
6973
|
});
|
|
6866
6974
|
}
|
|
6867
6975
|
if (this.sandboxOps?.isSandboxRunning(sessionId)) {
|
|
6868
6976
|
try {
|
|
6869
|
-
|
|
6870
|
-
console.log(`[FILE_SYNC] Would delete ${sandboxPath} from sandbox`);
|
|
6977
|
+
console.log(`[FILE_SYNC] Would delete ${pathFields.sandboxPath} from sandbox`);
|
|
6871
6978
|
result.sandboxDeleted = true;
|
|
6872
6979
|
await this.emitFileEvent(sessionId, {
|
|
6873
|
-
operation: "
|
|
6874
|
-
|
|
6875
|
-
|
|
6980
|
+
operation: "deleted_from_agent_sandbox",
|
|
6981
|
+
source: "ash_file_sync",
|
|
6982
|
+
...pathFields,
|
|
6876
6983
|
success: true
|
|
6877
6984
|
});
|
|
6878
6985
|
} catch (error) {
|
|
6879
6986
|
const errorMessage = extractErrorMessage(error);
|
|
6880
6987
|
await this.emitFileEvent(sessionId, {
|
|
6881
|
-
operation: "
|
|
6882
|
-
|
|
6883
|
-
|
|
6988
|
+
operation: "deleted_from_agent_sandbox",
|
|
6989
|
+
source: "ash_file_sync",
|
|
6990
|
+
...pathFields,
|
|
6884
6991
|
success: false,
|
|
6885
6992
|
error: errorMessage
|
|
6886
6993
|
});
|
|
@@ -6900,36 +7007,36 @@ var init_sandbox_file_sync = __esm({
|
|
|
6900
7007
|
}
|
|
6901
7008
|
const files = await this.fileStore.listFiles(sessionId);
|
|
6902
7009
|
for (const file of files) {
|
|
7010
|
+
const pathFields = this.buildPathFields(file.path);
|
|
6903
7011
|
try {
|
|
6904
7012
|
const content = await this.fileStore.readFile(sessionId, file.path);
|
|
6905
7013
|
if (!content) {
|
|
6906
7014
|
result.errors.push({ path: file.path, error: "File not found in S3" });
|
|
6907
7015
|
await this.emitFileEvent(sessionId, {
|
|
6908
|
-
operation: "
|
|
6909
|
-
|
|
6910
|
-
|
|
7016
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7017
|
+
source: "ash_file_sync",
|
|
7018
|
+
...pathFields,
|
|
6911
7019
|
success: false,
|
|
6912
|
-
error: "File not found in
|
|
7020
|
+
error: "File not found in Ash storage"
|
|
6913
7021
|
});
|
|
6914
7022
|
continue;
|
|
6915
7023
|
}
|
|
6916
|
-
const
|
|
6917
|
-
const writeResult = await this.sandboxOps.writeFile(sessionId, sandboxPath, content);
|
|
7024
|
+
const writeResult = await this.sandboxOps.writeFile(sessionId, pathFields.sandboxPath, content);
|
|
6918
7025
|
if (writeResult.success) {
|
|
6919
7026
|
result.fileCount++;
|
|
6920
7027
|
await this.emitFileEvent(sessionId, {
|
|
6921
|
-
operation: "
|
|
6922
|
-
|
|
6923
|
-
|
|
7028
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7029
|
+
source: "ash_file_sync",
|
|
7030
|
+
...pathFields,
|
|
6924
7031
|
fileSize: content.length,
|
|
6925
7032
|
success: true
|
|
6926
7033
|
});
|
|
6927
7034
|
} else {
|
|
6928
7035
|
result.errors.push({ path: file.path, error: writeResult.error ?? "Unknown error" });
|
|
6929
7036
|
await this.emitFileEvent(sessionId, {
|
|
6930
|
-
operation: "
|
|
6931
|
-
|
|
6932
|
-
|
|
7037
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7038
|
+
source: "ash_file_sync",
|
|
7039
|
+
...pathFields,
|
|
6933
7040
|
fileSize: content.length,
|
|
6934
7041
|
success: false,
|
|
6935
7042
|
error: writeResult.error
|
|
@@ -6942,9 +7049,9 @@ var init_sandbox_file_sync = __esm({
|
|
|
6942
7049
|
error: errorMessage
|
|
6943
7050
|
});
|
|
6944
7051
|
await this.emitFileEvent(sessionId, {
|
|
6945
|
-
operation: "
|
|
6946
|
-
|
|
6947
|
-
|
|
7052
|
+
operation: "ash_storage_synced_to_agent_sandbox",
|
|
7053
|
+
source: "ash_file_sync",
|
|
7054
|
+
...pathFields,
|
|
6948
7055
|
success: false,
|
|
6949
7056
|
error: errorMessage
|
|
6950
7057
|
});
|
|
@@ -6975,39 +7082,25 @@ var init_sandbox_file_sync = __esm({
|
|
|
6975
7082
|
return result;
|
|
6976
7083
|
}
|
|
6977
7084
|
}
|
|
6978
|
-
for (const
|
|
7085
|
+
for (const file of filesToSync) {
|
|
7086
|
+
const pathFields = this.buildPathFields(file);
|
|
6979
7087
|
try {
|
|
6980
|
-
const pullResult = await this.pullFile(sessionId,
|
|
7088
|
+
const pullResult = await this.pullFile(sessionId, file);
|
|
6981
7089
|
if (pullResult.s3Written) {
|
|
6982
7090
|
result.fileCount++;
|
|
6983
|
-
await this.emitFileEvent(sessionId, {
|
|
6984
|
-
operation: "sync_from_sandbox",
|
|
6985
|
-
direction: "to_s3",
|
|
6986
|
-
filePath,
|
|
6987
|
-
fileSize: pullResult.content?.length,
|
|
6988
|
-
success: true,
|
|
6989
|
-
newContent: pullResult.content ?? void 0
|
|
6990
|
-
});
|
|
6991
7091
|
} else if (pullResult.error) {
|
|
6992
|
-
result.errors.push({ path:
|
|
6993
|
-
await this.emitFileEvent(sessionId, {
|
|
6994
|
-
operation: "sync_from_sandbox",
|
|
6995
|
-
direction: "to_s3",
|
|
6996
|
-
filePath,
|
|
6997
|
-
success: false,
|
|
6998
|
-
error: pullResult.error
|
|
6999
|
-
});
|
|
7092
|
+
result.errors.push({ path: file, error: pullResult.error });
|
|
7000
7093
|
}
|
|
7001
7094
|
} catch (error) {
|
|
7002
7095
|
const errorMessage = extractErrorMessage(error);
|
|
7003
7096
|
result.errors.push({
|
|
7004
|
-
path:
|
|
7097
|
+
path: file,
|
|
7005
7098
|
error: errorMessage
|
|
7006
7099
|
});
|
|
7007
7100
|
await this.emitFileEvent(sessionId, {
|
|
7008
|
-
operation: "
|
|
7009
|
-
|
|
7010
|
-
|
|
7101
|
+
operation: "agent_sandbox_saved_to_ash_storage",
|
|
7102
|
+
source: "ash_file_sync",
|
|
7103
|
+
...pathFields,
|
|
7011
7104
|
success: false,
|
|
7012
7105
|
error: errorMessage
|
|
7013
7106
|
});
|
|
@@ -7042,9 +7135,10 @@ var init_sandbox_file_sync = __esm({
|
|
|
7042
7135
|
*/
|
|
7043
7136
|
async startWatching(sessionId, options) {
|
|
7044
7137
|
const opts = { ...this.defaultWatchOptions, ...options };
|
|
7138
|
+
const watchPath = opts.watchPaths?.[0] ?? ".";
|
|
7045
7139
|
await this.stopWatching(sessionId);
|
|
7046
7140
|
const handleFileChange = async (event) => {
|
|
7047
|
-
console.log(`[FILE_SYNC] File change detected: ${event.type} ${event.relativePath}`);
|
|
7141
|
+
console.log(`[FILE_SYNC] File change detected: ${event.type} ${event.relativePath} (watching from: ${watchPath})`);
|
|
7048
7142
|
if (this.webhookConfig) {
|
|
7049
7143
|
this.sendFileChangeWebhook(event);
|
|
7050
7144
|
}
|
|
@@ -7057,7 +7151,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7057
7151
|
}
|
|
7058
7152
|
if (event.type === "add" || event.type === "change") {
|
|
7059
7153
|
try {
|
|
7060
|
-
const pullResult = await this.pullFile(sessionId, event.relativePath);
|
|
7154
|
+
const pullResult = await this.pullFile(sessionId, event.relativePath, { targetPath: watchPath });
|
|
7061
7155
|
if (pullResult.s3Written) {
|
|
7062
7156
|
console.log(`[FILE_SYNC] Auto-synced ${event.relativePath} to S3`);
|
|
7063
7157
|
} else if (pullResult.error) {
|
|
@@ -7088,7 +7182,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7088
7182
|
});
|
|
7089
7183
|
await watcher.start();
|
|
7090
7184
|
this.localWatchers.set(sessionId, watcher);
|
|
7091
|
-
console.log(`[FILE_SYNC] Started local file watching for session ${sessionId}`);
|
|
7185
|
+
console.log(`[FILE_SYNC] Started local file watching for session ${sessionId} at ${opts.localPath}`);
|
|
7092
7186
|
} else {
|
|
7093
7187
|
if (!this.sandboxOps) {
|
|
7094
7188
|
throw new Error("Sandbox operations not configured. Call setSandboxOperations first.");
|
|
@@ -7096,7 +7190,8 @@ var init_sandbox_file_sync = __esm({
|
|
|
7096
7190
|
const watcher = new exports.RemoteSandboxFileWatcher({
|
|
7097
7191
|
sessionId,
|
|
7098
7192
|
sandboxOps: this.sandboxOps,
|
|
7099
|
-
basePath:
|
|
7193
|
+
basePath: watchPath,
|
|
7194
|
+
// Use watchPath instead of sandboxBasePath
|
|
7100
7195
|
pollIntervalMs: opts.pollIntervalMs ?? 2e3,
|
|
7101
7196
|
ignored: opts.ignored ?? ["**/node_modules/**", "**/.git/**"],
|
|
7102
7197
|
onFileChange: handleFileChange,
|
|
@@ -7106,7 +7201,7 @@ var init_sandbox_file_sync = __esm({
|
|
|
7106
7201
|
});
|
|
7107
7202
|
await watcher.start();
|
|
7108
7203
|
this.remoteWatchers.set(sessionId, watcher);
|
|
7109
|
-
console.log(`[FILE_SYNC] Started remote file watching for session ${sessionId}`);
|
|
7204
|
+
console.log(`[FILE_SYNC] Started remote file watching for session ${sessionId} at path: ${watchPath}`);
|
|
7110
7205
|
}
|
|
7111
7206
|
}
|
|
7112
7207
|
/**
|
|
@@ -7419,6 +7514,7 @@ WATCHER_EOF`;
|
|
|
7419
7514
|
type: data.type,
|
|
7420
7515
|
relativePath: data.path.replace(/^\.\//, ""),
|
|
7421
7516
|
absolutePath: data.path,
|
|
7517
|
+
basePath: this.watchPath,
|
|
7422
7518
|
sessionId: this.sessionId,
|
|
7423
7519
|
timestamp: new Date(data.timestamp)
|
|
7424
7520
|
});
|
|
@@ -16241,8 +16337,10 @@ var init_schema = __esm({
|
|
|
16241
16337
|
// error events
|
|
16242
16338
|
"file",
|
|
16243
16339
|
// file_push, file_pull, file_sync (file sync operations)
|
|
16244
|
-
"input"
|
|
16340
|
+
"input",
|
|
16245
16341
|
// user_input (user prompts/messages)
|
|
16342
|
+
"webhook"
|
|
16343
|
+
// webhook_delivery, webhook_failure (outbound webhook events)
|
|
16246
16344
|
]);
|
|
16247
16345
|
sessions = pgCore.pgTable(
|
|
16248
16346
|
"sessions",
|