@annals/agent-mesh 0.18.4 → 0.18.5

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.
Files changed (2) hide show
  1. package/dist/index.js +387 -215
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -125,7 +125,7 @@ var BridgeWSClient = class extends EventEmitter {
125
125
  this.opts = opts;
126
126
  }
127
127
  async connect() {
128
- return new Promise((resolve2, reject) => {
128
+ return new Promise((resolve3, reject) => {
129
129
  this.intentionalClose = false;
130
130
  this.registered = false;
131
131
  try {
@@ -143,7 +143,7 @@ var BridgeWSClient = class extends EventEmitter {
143
143
  this.registered = true;
144
144
  this.reconnectDelay = INITIAL_RECONNECT_DELAY;
145
145
  this.startHeartbeat();
146
- resolve2();
146
+ resolve3();
147
147
  } else {
148
148
  reject(new Error(`Registration failed: ${msg.error || "unknown"}`));
149
149
  }
@@ -439,10 +439,10 @@ var FileReceiver = class {
439
439
  this.peer = new ndc.PeerConnection("receiver", {
440
440
  iceServers: ICE_SERVERS
441
441
  });
442
- return new Promise((resolve2) => {
442
+ return new Promise((resolve3) => {
443
443
  this.peer.onLocalDescription((sdp, type) => {
444
444
  if (type === "offer") {
445
- resolve2(sdp);
445
+ resolve3(sdp);
446
446
  }
447
447
  this.signalCallback?.({ signal_type: type, payload: sdp });
448
448
  });
@@ -491,8 +491,8 @@ var FileReceiver = class {
491
491
  }
492
492
  }
493
493
  waitForCompletion(timeoutMs = CONNECT_TIMEOUT_MS) {
494
- return new Promise((resolve2, reject) => {
495
- this.resolveComplete = resolve2;
494
+ return new Promise((resolve3, reject) => {
495
+ this.resolveComplete = resolve3;
496
496
  this.rejectComplete = reject;
497
497
  setTimeout(() => {
498
498
  if (!this.closed) {
@@ -608,8 +608,8 @@ var FileUploadReceiver = class {
608
608
  }
609
609
  }
610
610
  waitForCompletion(timeoutMs = 3e4) {
611
- return new Promise((resolve2, reject) => {
612
- this.resolveComplete = resolve2;
611
+ return new Promise((resolve3, reject) => {
612
+ this.resolveComplete = resolve3;
613
613
  this.rejectComplete = reject;
614
614
  setTimeout(() => {
615
615
  if (!this.closed) {
@@ -672,10 +672,10 @@ var FileUploadSender = class {
672
672
  this.peer = new ndc.PeerConnection("upload-sender", {
673
673
  iceServers: ICE_SERVERS
674
674
  });
675
- return new Promise((resolve2) => {
675
+ return new Promise((resolve3) => {
676
676
  this.peer.onLocalDescription((sdp, type) => {
677
677
  if (type === "offer") {
678
- resolve2(sdp);
678
+ resolve3(sdp);
679
679
  }
680
680
  this.signalCallback?.({ signal_type: type, payload: sdp });
681
681
  });
@@ -712,8 +712,8 @@ var FileUploadSender = class {
712
712
  }
713
713
  }
714
714
  waitForCompletion(timeoutMs = 3e4) {
715
- return new Promise((resolve2, reject) => {
716
- this.resolveComplete = resolve2;
715
+ return new Promise((resolve3, reject) => {
716
+ this.resolveComplete = resolve3;
717
717
  this.rejectComplete = reject;
718
718
  setTimeout(() => {
719
719
  if (!this.closed) {
@@ -833,7 +833,7 @@ var LocalRuntimeQueueError = class extends Error {
833
833
  }
834
834
  };
835
835
  function sleep(ms) {
836
- return new Promise((resolve2) => setTimeout(resolve2, ms));
836
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
837
837
  }
838
838
  function isProcessAlive2(pid) {
839
839
  try {
@@ -1152,14 +1152,193 @@ function createLocalRuntimeQueue(config) {
1152
1152
  }
1153
1153
 
1154
1154
  // src/bridge/manager.ts
1155
- import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2 } from "fs";
1156
- import { execSync } from "child_process";
1155
+ import { mkdirSync as mkdirSync3, writeFileSync as writeFileSync2, readdirSync } from "fs";
1156
+ import { readFile as readFileAsync, writeFile as writeFileAsync, unlink, mkdir as mkdirAsync } from "fs/promises";
1157
+ import { execSync as execSync2 } from "child_process";
1157
1158
  import { join as join3 } from "path";
1158
1159
  import { homedir as homedir2 } from "os";
1160
+
1161
+ // src/utils/zip.ts
1162
+ import { deflateRawSync, inflateRawSync } from "zlib";
1163
+ import { execSync } from "child_process";
1164
+ import { resolve, relative } from "path";
1165
+ function dosTime(date) {
1166
+ return {
1167
+ time: date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1,
1168
+ date: date.getFullYear() - 1980 << 9 | date.getMonth() + 1 << 5 | date.getDate()
1169
+ };
1170
+ }
1171
+ function crc32(buf) {
1172
+ let crc = 4294967295;
1173
+ for (let i = 0; i < buf.length; i++) {
1174
+ crc ^= buf[i];
1175
+ for (let j = 0; j < 8; j++) {
1176
+ crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
1177
+ }
1178
+ }
1179
+ return (crc ^ 4294967295) >>> 0;
1180
+ }
1181
+ function writeUint16LE(buf, val, offset) {
1182
+ buf[offset] = val & 255;
1183
+ buf[offset + 1] = val >>> 8 & 255;
1184
+ }
1185
+ function writeUint32LE(buf, val, offset) {
1186
+ buf[offset] = val & 255;
1187
+ buf[offset + 1] = val >>> 8 & 255;
1188
+ buf[offset + 2] = val >>> 16 & 255;
1189
+ buf[offset + 3] = val >>> 24 & 255;
1190
+ }
1191
+ function createZipBuffer(entries) {
1192
+ const now = /* @__PURE__ */ new Date();
1193
+ const { time, date } = dosTime(now);
1194
+ const records = [];
1195
+ const chunks = [];
1196
+ let offset = 0;
1197
+ for (const entry of entries) {
1198
+ const nameBytes = Buffer.from(entry.path, "utf-8");
1199
+ const crc = crc32(entry.data);
1200
+ const compressed = deflateRawSync(entry.data, { level: 6 });
1201
+ const compressedSize = compressed.length;
1202
+ const uncompressedSize = entry.data.length;
1203
+ const header = Buffer.alloc(30 + nameBytes.length);
1204
+ writeUint32LE(header, 67324752, 0);
1205
+ writeUint16LE(header, 20, 4);
1206
+ writeUint16LE(header, 0, 6);
1207
+ writeUint16LE(header, 8, 8);
1208
+ writeUint16LE(header, time, 10);
1209
+ writeUint16LE(header, date, 12);
1210
+ writeUint32LE(header, crc, 14);
1211
+ writeUint32LE(header, compressedSize, 18);
1212
+ writeUint32LE(header, uncompressedSize, 22);
1213
+ writeUint16LE(header, nameBytes.length, 26);
1214
+ writeUint16LE(header, 0, 28);
1215
+ nameBytes.copy(header, 30);
1216
+ records.push({ header, compressed, crc, compressedSize, uncompressedSize, offset });
1217
+ chunks.push(header, compressed);
1218
+ offset += header.length + compressed.length;
1219
+ }
1220
+ const centralDirStart = offset;
1221
+ for (let i = 0; i < entries.length; i++) {
1222
+ const entry = entries[i];
1223
+ const rec = records[i];
1224
+ const nameBytes = Buffer.from(entry.path, "utf-8");
1225
+ const cdh = Buffer.alloc(46 + nameBytes.length);
1226
+ writeUint32LE(cdh, 33639248, 0);
1227
+ writeUint16LE(cdh, 20, 4);
1228
+ writeUint16LE(cdh, 20, 6);
1229
+ writeUint16LE(cdh, 0, 8);
1230
+ writeUint16LE(cdh, 8, 10);
1231
+ writeUint16LE(cdh, time, 12);
1232
+ writeUint16LE(cdh, date, 14);
1233
+ writeUint32LE(cdh, rec.crc, 16);
1234
+ writeUint32LE(cdh, rec.compressedSize, 20);
1235
+ writeUint32LE(cdh, rec.uncompressedSize, 24);
1236
+ writeUint16LE(cdh, nameBytes.length, 28);
1237
+ writeUint16LE(cdh, 0, 30);
1238
+ writeUint16LE(cdh, 0, 32);
1239
+ writeUint16LE(cdh, 0, 34);
1240
+ writeUint16LE(cdh, 0, 36);
1241
+ writeUint32LE(cdh, 0, 38);
1242
+ writeUint32LE(cdh, rec.offset, 42);
1243
+ nameBytes.copy(cdh, 46);
1244
+ chunks.push(cdh);
1245
+ offset += cdh.length;
1246
+ }
1247
+ const centralDirSize = offset - centralDirStart;
1248
+ const eocd = Buffer.alloc(22);
1249
+ writeUint32LE(eocd, 101010256, 0);
1250
+ writeUint16LE(eocd, 0, 4);
1251
+ writeUint16LE(eocd, 0, 6);
1252
+ writeUint16LE(eocd, entries.length, 8);
1253
+ writeUint16LE(eocd, entries.length, 10);
1254
+ writeUint32LE(eocd, centralDirSize, 12);
1255
+ writeUint32LE(eocd, centralDirStart, 16);
1256
+ writeUint16LE(eocd, 0, 20);
1257
+ chunks.push(eocd);
1258
+ return Buffer.concat(chunks);
1259
+ }
1260
+ function safeUnzip(zipPath, destDir) {
1261
+ const absDestDir = resolve(destDir);
1262
+ const listing = execSync(`unzip -l "${zipPath}"`, { encoding: "utf-8" });
1263
+ const lines = listing.split("\n");
1264
+ for (const line of lines) {
1265
+ const match = line.match(/^\s*\d+\s+\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}\s+(.+)$/);
1266
+ if (!match) continue;
1267
+ const entryPath = match[1].trim();
1268
+ if (!entryPath) continue;
1269
+ if (entryPath.startsWith("/")) {
1270
+ throw new Error(`Blocked: ZIP contains absolute path entry: ${entryPath}`);
1271
+ }
1272
+ if (entryPath.includes("..")) {
1273
+ throw new Error(`Blocked: ZIP contains path traversal entry: ${entryPath}`);
1274
+ }
1275
+ const resolved = resolve(absDestDir, entryPath);
1276
+ const rel = relative(absDestDir, resolved);
1277
+ if (rel.startsWith("..") || resolve(resolved) !== resolved.replace(/\/$/, "")) {
1278
+ if (rel.startsWith("..")) {
1279
+ throw new Error(`Blocked: ZIP entry escapes target directory: ${entryPath}`);
1280
+ }
1281
+ }
1282
+ }
1283
+ execSync(`unzip -o -q "${zipPath}" -d "${destDir}"`);
1284
+ }
1285
+ function extractZipBuffer(buf) {
1286
+ const entries = [];
1287
+ let eocdOffset = -1;
1288
+ for (let i = buf.length - 22; i >= 0; i--) {
1289
+ if (buf.readUInt32LE(i) === 101010256) {
1290
+ eocdOffset = i;
1291
+ break;
1292
+ }
1293
+ }
1294
+ if (eocdOffset === -1) {
1295
+ throw new Error("Invalid ZIP: EOCD not found");
1296
+ }
1297
+ const entryCount = buf.readUInt16LE(eocdOffset + 10);
1298
+ const centralDirOffset = buf.readUInt32LE(eocdOffset + 16);
1299
+ let offset = centralDirOffset;
1300
+ for (let i = 0; i < entryCount; i++) {
1301
+ if (buf.readUInt32LE(offset) !== 33639248) {
1302
+ throw new Error(`Invalid ZIP: bad central directory signature at ${offset}`);
1303
+ }
1304
+ const compressionMethod = buf.readUInt16LE(offset + 10);
1305
+ const compressedSize = buf.readUInt32LE(offset + 20);
1306
+ const uncompressedSize = buf.readUInt32LE(offset + 24);
1307
+ const nameLen = buf.readUInt16LE(offset + 28);
1308
+ const extraLen = buf.readUInt16LE(offset + 30);
1309
+ const commentLen = buf.readUInt16LE(offset + 32);
1310
+ const localHeaderOffset = buf.readUInt32LE(offset + 42);
1311
+ const name = buf.subarray(offset + 46, offset + 46 + nameLen).toString("utf-8");
1312
+ if (!name.endsWith("/")) {
1313
+ const localNameLen = buf.readUInt16LE(localHeaderOffset + 26);
1314
+ const localExtraLen = buf.readUInt16LE(localHeaderOffset + 28);
1315
+ const dataOffset = localHeaderOffset + 30 + localNameLen + localExtraLen;
1316
+ const compressedData = buf.subarray(dataOffset, dataOffset + compressedSize);
1317
+ let data;
1318
+ if (compressionMethod === 0) {
1319
+ data = Buffer.from(compressedData);
1320
+ } else if (compressionMethod === 8) {
1321
+ data = inflateRawSync(compressedData);
1322
+ } else {
1323
+ throw new Error(`Unsupported compression method: ${compressionMethod}`);
1324
+ }
1325
+ if (data.length !== uncompressedSize) {
1326
+ throw new Error(`Size mismatch for ${name}: expected ${uncompressedSize}, got ${data.length}`);
1327
+ }
1328
+ entries.push({ path: name, data });
1329
+ }
1330
+ offset += 46 + nameLen + extraLen + commentLen;
1331
+ }
1332
+ return entries;
1333
+ }
1334
+
1335
+ // src/bridge/manager.ts
1159
1336
  var DUPLICATE_REQUEST_TTL_MS = 10 * 6e4;
1160
1337
  var SESSION_SWEEP_INTERVAL_MS = 6e4;
1161
1338
  var DEFAULT_SESSION_IDLE_TTL_MS = 10 * 6e4;
1162
1339
  var MIN_SESSION_IDLE_TTL_MS = 6e4;
1340
+ var TRANSFER_ACTIVE_TTL_MS = 5 * 6e4;
1341
+ var TRANSFER_DORMANT_TTL_MS = 60 * 6e4;
1163
1342
  function resolveSessionIdleTtlMs() {
1164
1343
  const raw = process.env.AGENT_BRIDGE_SESSION_IDLE_TTL_MS;
1165
1344
  if (!raw) {
@@ -1193,6 +1372,10 @@ var BridgeManager = class {
1193
1372
  pendingTransfers = /* @__PURE__ */ new Map();
1194
1373
  /** Pending WebRTC file uploads (caller→agent): transfer_id → FileUploadReceiver + cleanup timer */
1195
1374
  pendingUploads = /* @__PURE__ */ new Map();
1375
+ /** Dormant transfers: ZIP evicted from memory, cached on disk for up to 1h */
1376
+ dormantTransfers = /* @__PURE__ */ new Map();
1377
+ /** Signals queued while a dormant transfer is being revived (prevents signal loss during async disk read) */
1378
+ revivingTransfers = /* @__PURE__ */ new Map();
1196
1379
  constructor(opts) {
1197
1380
  this.wsClient = opts.wsClient;
1198
1381
  this.adapter = opts.adapter;
@@ -1205,6 +1388,7 @@ var BridgeManager = class {
1205
1388
  this.pruneIdleSessions();
1206
1389
  }, SESSION_SWEEP_INTERVAL_MS);
1207
1390
  this.cleanupTimer.unref?.();
1391
+ void this.cleanupOrphanedTransferCache();
1208
1392
  log.info(`Bridge manager started with ${this.adapter.displayName} adapter`);
1209
1393
  }
1210
1394
  stop() {
@@ -1620,11 +1804,27 @@ var BridgeManager = class {
1620
1804
  };
1621
1805
  this.wsClient.send(rtcSignal);
1622
1806
  });
1807
+ const zipPath = this.transferCachePath(offer.transfer_id);
1808
+ void (async () => {
1809
+ try {
1810
+ await mkdirAsync(this.transferCacheDir(), { recursive: true });
1811
+ await writeFileAsync(zipPath, zipBuffer);
1812
+ log.debug(`ZIP cached to disk: transfer=${offer.transfer_id.slice(0, 8)}... path=${zipPath}`);
1813
+ } catch (err) {
1814
+ log.warn(`Failed to cache ZIP to disk: ${err}`);
1815
+ }
1816
+ })();
1623
1817
  const timer = setTimeout(() => {
1624
1818
  sender.close();
1625
1819
  this.pendingTransfers.delete(offer.transfer_id);
1626
- log.debug(`Transfer ${offer.transfer_id.slice(0, 8)}... expired`);
1627
- }, 5 * 6e4);
1820
+ const dormantTimer = setTimeout(() => {
1821
+ this.cleanupDormantTransfer(offer.transfer_id);
1822
+ log.debug(`Dormant expired, disk cache removed: transfer=${offer.transfer_id.slice(0, 8)}...`);
1823
+ }, TRANSFER_DORMANT_TTL_MS);
1824
+ dormantTimer.unref?.();
1825
+ this.dormantTransfers.set(offer.transfer_id, { zipPath, offer, timer: dormantTimer });
1826
+ log.info(`Transfer transitioned to dormant: transfer=${offer.transfer_id.slice(0, 8)}...`);
1827
+ }, TRANSFER_ACTIVE_TTL_MS);
1628
1828
  timer.unref?.();
1629
1829
  this.pendingTransfers.set(offer.transfer_id, { sender, timer });
1630
1830
  log.info(`WebRTC transfer registered: transfer=${offer.transfer_id.slice(0, 8)}... (${(zipBuffer.length / 1024).toFixed(1)} KB in memory)`);
@@ -1639,6 +1839,10 @@ var BridgeManager = class {
1639
1839
  });
1640
1840
  return;
1641
1841
  }
1842
+ if (this.dormantTransfers.has(msg.transfer_id) || this.revivingTransfers.has(msg.transfer_id)) {
1843
+ void this.handleDormantSignal(msg);
1844
+ return;
1845
+ }
1642
1846
  const uploadEntry = this.pendingUploads.get(msg.transfer_id);
1643
1847
  if (uploadEntry) {
1644
1848
  void uploadEntry.receiver.handleSignal({
@@ -1680,14 +1884,14 @@ var BridgeManager = class {
1680
1884
  const zipPath = join3(workspaceDir, ".upload.zip");
1681
1885
  writeFileSync2(zipPath, zipBuffer);
1682
1886
  try {
1683
- execSync(`unzip -o -q "${zipPath}" -d "${workspaceDir}"`);
1887
+ safeUnzip(zipPath, workspaceDir);
1684
1888
  try {
1685
- execSync(`rm "${zipPath}"`);
1889
+ execSync2(`rm "${zipPath}"`);
1686
1890
  } catch {
1687
1891
  }
1688
1892
  log.info(`[WebRTC] Upload: ${offer.file_count} file(s) extracted to ${workspaceDir}`);
1689
- } catch {
1690
- log.warn(`[WebRTC] Upload: Failed to extract ZIP. Saved to: ${zipPath}`);
1893
+ } catch (unzipErr) {
1894
+ log.warn(`[WebRTC] Upload: Failed to extract ZIP: ${unzipErr.message}. Saved to: ${zipPath}`);
1691
1895
  }
1692
1896
  } catch (err) {
1693
1897
  log.error(`[WebRTC] Upload extraction failed: ${err}`);
@@ -1715,6 +1919,121 @@ var BridgeManager = class {
1715
1919
  entry.sender.close();
1716
1920
  }
1717
1921
  this.pendingTransfers.clear();
1922
+ for (const [id] of this.dormantTransfers) {
1923
+ this.cleanupDormantTransfer(id);
1924
+ }
1925
+ this.revivingTransfers.clear();
1926
+ }
1927
+ // ========================================================
1928
+ // Dormant transfer: disk cache + revival
1929
+ // ========================================================
1930
+ transferCacheDir() {
1931
+ return join3(homedir2(), ".agent-mesh", "transfers");
1932
+ }
1933
+ transferCachePath(transferId) {
1934
+ return join3(this.transferCacheDir(), `${transferId}.zip`);
1935
+ }
1936
+ cleanupDormantTransfer(transferId) {
1937
+ const entry = this.dormantTransfers.get(transferId);
1938
+ if (!entry) return;
1939
+ clearTimeout(entry.timer);
1940
+ this.dormantTransfers.delete(transferId);
1941
+ void unlink(entry.zipPath).catch(() => {
1942
+ });
1943
+ }
1944
+ async reviveDormantTransfer(dormant) {
1945
+ const zipBuffer = await readFileAsync(dormant.zipPath);
1946
+ if (zipBuffer.length !== dormant.offer.zip_size) {
1947
+ throw new Error(`ZIP size mismatch: expected ${dormant.offer.zip_size}, got ${zipBuffer.length}`);
1948
+ }
1949
+ const sender = new FileSender(dormant.offer.transfer_id, zipBuffer);
1950
+ sender.onSignal((signal) => {
1951
+ const entry = this.pendingTransfers.get(dormant.offer.transfer_id);
1952
+ if (!entry) return;
1953
+ const rtcSignal = {
1954
+ type: "rtc_signal",
1955
+ transfer_id: dormant.offer.transfer_id,
1956
+ target_agent_id: entry.targetAgentId || "",
1957
+ signal_type: signal.signal_type,
1958
+ payload: signal.payload
1959
+ };
1960
+ this.wsClient.send(rtcSignal);
1961
+ });
1962
+ const timer = setTimeout(() => {
1963
+ sender.close();
1964
+ this.pendingTransfers.delete(dormant.offer.transfer_id);
1965
+ void unlink(dormant.zipPath).catch(() => {
1966
+ });
1967
+ log.debug(`Revived transfer expired: transfer=${dormant.offer.transfer_id.slice(0, 8)}...`);
1968
+ }, TRANSFER_ACTIVE_TTL_MS);
1969
+ timer.unref?.();
1970
+ this.pendingTransfers.set(dormant.offer.transfer_id, { sender, timer });
1971
+ log.info(`Revived from disk cache: transfer=${dormant.offer.transfer_id.slice(0, 8)}... (${(zipBuffer.length / 1024).toFixed(1)} KB)`);
1972
+ return sender;
1973
+ }
1974
+ async handleDormantSignal(msg) {
1975
+ const transferId = msg.transfer_id;
1976
+ const alreadyRevived = this.pendingTransfers.get(transferId);
1977
+ if (alreadyRevived) {
1978
+ alreadyRevived.targetAgentId = msg.from_agent_id;
1979
+ void alreadyRevived.sender.handleSignal({
1980
+ signal_type: msg.signal_type,
1981
+ payload: msg.payload
1982
+ });
1983
+ return;
1984
+ }
1985
+ const queue = this.revivingTransfers.get(transferId);
1986
+ if (queue) {
1987
+ queue.push(msg);
1988
+ return;
1989
+ }
1990
+ const dormant = this.dormantTransfers.get(transferId);
1991
+ if (!dormant) return;
1992
+ this.revivingTransfers.set(transferId, []);
1993
+ clearTimeout(dormant.timer);
1994
+ this.dormantTransfers.delete(transferId);
1995
+ try {
1996
+ const sender = await this.reviveDormantTransfer(dormant);
1997
+ const entry = this.pendingTransfers.get(transferId);
1998
+ if (entry) {
1999
+ entry.targetAgentId = msg.from_agent_id;
2000
+ }
2001
+ void sender.handleSignal({
2002
+ signal_type: msg.signal_type,
2003
+ payload: msg.payload
2004
+ });
2005
+ const queued = this.revivingTransfers.get(transferId) || [];
2006
+ this.revivingTransfers.delete(transferId);
2007
+ for (const queuedMsg of queued) {
2008
+ void sender.handleSignal({
2009
+ signal_type: queuedMsg.signal_type,
2010
+ payload: queuedMsg.payload
2011
+ });
2012
+ }
2013
+ } catch (err) {
2014
+ log.warn(`Failed to revive dormant transfer ${transferId.slice(0, 8)}...: ${err}`);
2015
+ this.revivingTransfers.delete(transferId);
2016
+ void unlink(dormant.zipPath).catch(() => {
2017
+ });
2018
+ }
2019
+ }
2020
+ async cleanupOrphanedTransferCache() {
2021
+ try {
2022
+ const dir = this.transferCacheDir();
2023
+ let files;
2024
+ try {
2025
+ files = readdirSync(dir);
2026
+ } catch {
2027
+ return;
2028
+ }
2029
+ const zipFiles = files.filter((f) => f.endsWith(".zip"));
2030
+ if (zipFiles.length === 0) return;
2031
+ await Promise.all(zipFiles.map((f) => unlink(join3(dir, f)).catch(() => {
2032
+ })));
2033
+ log.info(`Cleaned ${zipFiles.length} orphaned transfer cache file(s)`);
2034
+ } catch (err) {
2035
+ log.debug(`Transfer cache cleanup failed: ${err}`);
2036
+ }
1718
2037
  }
1719
2038
  updateSessionCount() {
1720
2039
  this.wsClient.setActiveSessions(this.pool.size);
@@ -1729,7 +2048,7 @@ var AgentAdapter = class {
1729
2048
  import { spawn } from "child_process";
1730
2049
 
1731
2050
  // src/utils/sandbox.ts
1732
- import { execSync as execSync2 } from "child_process";
2051
+ import { execSync as execSync3 } from "child_process";
1733
2052
  import { join as join4 } from "path";
1734
2053
  var SRT_PACKAGE = "@anthropic-ai/sandbox-runtime";
1735
2054
  var SENSITIVE_PATHS = [
@@ -1788,7 +2107,7 @@ var sandboxManager = null;
1788
2107
  var sandboxInitialized = false;
1789
2108
  async function importSandboxManager() {
1790
2109
  try {
1791
- const globalRoot = execSync2("npm root -g", { encoding: "utf-8" }).trim();
2110
+ const globalRoot = execSync3("npm root -g", { encoding: "utf-8" }).trim();
1792
2111
  const srtPath = join4(globalRoot, "@anthropic-ai/sandbox-runtime/dist/index.js");
1793
2112
  const mod = await import(srtPath);
1794
2113
  return mod.SandboxManager;
@@ -1877,7 +2196,7 @@ function buildCommandString(command, args) {
1877
2196
  function installSandboxRuntime() {
1878
2197
  log.info(`Installing ${SRT_PACKAGE}...`);
1879
2198
  try {
1880
- execSync2(`npm install -g ${SRT_PACKAGE}`, { stdio: "inherit" });
2199
+ execSync3(`npm install -g ${SRT_PACKAGE}`, { stdio: "inherit" });
1881
2200
  log.success(`${SRT_PACKAGE} installed successfully`);
1882
2201
  return true;
1883
2202
  } catch {
@@ -1986,20 +2305,20 @@ function which(command) {
1986
2305
  if (!ALLOWED_COMMANDS.test(command)) {
1987
2306
  return Promise.resolve(null);
1988
2307
  }
1989
- return new Promise((resolve2) => {
2308
+ return new Promise((resolve3) => {
1990
2309
  execFile("which", [command], async (err, stdout) => {
1991
2310
  if (!err && stdout.trim()) {
1992
- resolve2(stdout.trim());
2311
+ resolve3(stdout.trim());
1993
2312
  return;
1994
2313
  }
1995
- resolve2(await resolveFallbackPath(command));
2314
+ resolve3(await resolveFallbackPath(command));
1996
2315
  });
1997
2316
  });
1998
2317
  }
1999
2318
 
2000
2319
  // src/utils/client-workspace.ts
2001
- import { mkdirSync as mkdirSync4, readdirSync, symlinkSync, existsSync as existsSync3, lstatSync } from "fs";
2002
- import { join as join5, relative } from "path";
2320
+ import { mkdirSync as mkdirSync4, readdirSync as readdirSync2, symlinkSync, existsSync as existsSync3, lstatSync } from "fs";
2321
+ import { join as join5, relative as relative2 } from "path";
2003
2322
  var SYMLINK_ALLOW = /* @__PURE__ */ new Set([
2004
2323
  "CLAUDE.md",
2005
2324
  ".claude",
@@ -2031,7 +2350,7 @@ function createClientWorkspace(projectPath, clientId) {
2031
2350
  const wsDir = join5(projectPath, ".bridge-clients", clientId);
2032
2351
  const isNew = !existsSync3(wsDir);
2033
2352
  mkdirSync4(wsDir, { recursive: true });
2034
- const entries = readdirSync(projectPath, { withFileTypes: true });
2353
+ const entries = readdirSync2(projectPath, { withFileTypes: true });
2035
2354
  for (const entry of entries) {
2036
2355
  if (!shouldInclude(entry.name)) continue;
2037
2356
  const link = join5(wsDir, entry.name);
@@ -2041,7 +2360,7 @@ function createClientWorkspace(projectPath, clientId) {
2041
2360
  } catch {
2042
2361
  }
2043
2362
  const target = join5(projectPath, entry.name);
2044
- const relTarget = relative(wsDir, target);
2363
+ const relTarget = relative2(wsDir, target);
2045
2364
  try {
2046
2365
  symlinkSync(relTarget, link);
2047
2366
  } catch (err) {
@@ -2056,11 +2375,11 @@ function createClientWorkspace(projectPath, clientId) {
2056
2375
 
2057
2376
  // src/adapters/claude.ts
2058
2377
  import { writeFile, mkdir, stat as stat2 } from "fs/promises";
2059
- import { join as join7, relative as relative3, basename } from "path";
2378
+ import { join as join7, relative as relative4, basename } from "path";
2060
2379
 
2061
2380
  // src/utils/auto-upload.ts
2062
2381
  import { readdir, readFile, stat } from "fs/promises";
2063
- import { join as join6, relative as relative2 } from "path";
2382
+ import { join as join6, relative as relative3 } from "path";
2064
2383
  var MAX_AUTO_UPLOAD_FILE_SIZE = 10 * 1024 * 1024;
2065
2384
  var SKIP_DIRS = /* @__PURE__ */ new Set([
2066
2385
  ".git",
@@ -2116,153 +2435,6 @@ async function collectRealFiles(dir, maxFiles = Infinity) {
2116
2435
  return files;
2117
2436
  }
2118
2437
 
2119
- // src/utils/zip.ts
2120
- import { deflateRawSync, inflateRawSync } from "zlib";
2121
- function dosTime(date) {
2122
- return {
2123
- time: date.getHours() << 11 | date.getMinutes() << 5 | date.getSeconds() >> 1,
2124
- date: date.getFullYear() - 1980 << 9 | date.getMonth() + 1 << 5 | date.getDate()
2125
- };
2126
- }
2127
- function crc32(buf) {
2128
- let crc = 4294967295;
2129
- for (let i = 0; i < buf.length; i++) {
2130
- crc ^= buf[i];
2131
- for (let j = 0; j < 8; j++) {
2132
- crc = crc >>> 1 ^ (crc & 1 ? 3988292384 : 0);
2133
- }
2134
- }
2135
- return (crc ^ 4294967295) >>> 0;
2136
- }
2137
- function writeUint16LE(buf, val, offset) {
2138
- buf[offset] = val & 255;
2139
- buf[offset + 1] = val >>> 8 & 255;
2140
- }
2141
- function writeUint32LE(buf, val, offset) {
2142
- buf[offset] = val & 255;
2143
- buf[offset + 1] = val >>> 8 & 255;
2144
- buf[offset + 2] = val >>> 16 & 255;
2145
- buf[offset + 3] = val >>> 24 & 255;
2146
- }
2147
- function createZipBuffer(entries) {
2148
- const now = /* @__PURE__ */ new Date();
2149
- const { time, date } = dosTime(now);
2150
- const records = [];
2151
- const chunks = [];
2152
- let offset = 0;
2153
- for (const entry of entries) {
2154
- const nameBytes = Buffer.from(entry.path, "utf-8");
2155
- const crc = crc32(entry.data);
2156
- const compressed = deflateRawSync(entry.data, { level: 6 });
2157
- const compressedSize = compressed.length;
2158
- const uncompressedSize = entry.data.length;
2159
- const header = Buffer.alloc(30 + nameBytes.length);
2160
- writeUint32LE(header, 67324752, 0);
2161
- writeUint16LE(header, 20, 4);
2162
- writeUint16LE(header, 0, 6);
2163
- writeUint16LE(header, 8, 8);
2164
- writeUint16LE(header, time, 10);
2165
- writeUint16LE(header, date, 12);
2166
- writeUint32LE(header, crc, 14);
2167
- writeUint32LE(header, compressedSize, 18);
2168
- writeUint32LE(header, uncompressedSize, 22);
2169
- writeUint16LE(header, nameBytes.length, 26);
2170
- writeUint16LE(header, 0, 28);
2171
- nameBytes.copy(header, 30);
2172
- records.push({ header, compressed, crc, compressedSize, uncompressedSize, offset });
2173
- chunks.push(header, compressed);
2174
- offset += header.length + compressed.length;
2175
- }
2176
- const centralDirStart = offset;
2177
- for (let i = 0; i < entries.length; i++) {
2178
- const entry = entries[i];
2179
- const rec = records[i];
2180
- const nameBytes = Buffer.from(entry.path, "utf-8");
2181
- const cdh = Buffer.alloc(46 + nameBytes.length);
2182
- writeUint32LE(cdh, 33639248, 0);
2183
- writeUint16LE(cdh, 20, 4);
2184
- writeUint16LE(cdh, 20, 6);
2185
- writeUint16LE(cdh, 0, 8);
2186
- writeUint16LE(cdh, 8, 10);
2187
- writeUint16LE(cdh, time, 12);
2188
- writeUint16LE(cdh, date, 14);
2189
- writeUint32LE(cdh, rec.crc, 16);
2190
- writeUint32LE(cdh, rec.compressedSize, 20);
2191
- writeUint32LE(cdh, rec.uncompressedSize, 24);
2192
- writeUint16LE(cdh, nameBytes.length, 28);
2193
- writeUint16LE(cdh, 0, 30);
2194
- writeUint16LE(cdh, 0, 32);
2195
- writeUint16LE(cdh, 0, 34);
2196
- writeUint16LE(cdh, 0, 36);
2197
- writeUint32LE(cdh, 0, 38);
2198
- writeUint32LE(cdh, rec.offset, 42);
2199
- nameBytes.copy(cdh, 46);
2200
- chunks.push(cdh);
2201
- offset += cdh.length;
2202
- }
2203
- const centralDirSize = offset - centralDirStart;
2204
- const eocd = Buffer.alloc(22);
2205
- writeUint32LE(eocd, 101010256, 0);
2206
- writeUint16LE(eocd, 0, 4);
2207
- writeUint16LE(eocd, 0, 6);
2208
- writeUint16LE(eocd, entries.length, 8);
2209
- writeUint16LE(eocd, entries.length, 10);
2210
- writeUint32LE(eocd, centralDirSize, 12);
2211
- writeUint32LE(eocd, centralDirStart, 16);
2212
- writeUint16LE(eocd, 0, 20);
2213
- chunks.push(eocd);
2214
- return Buffer.concat(chunks);
2215
- }
2216
- function extractZipBuffer(buf) {
2217
- const entries = [];
2218
- let eocdOffset = -1;
2219
- for (let i = buf.length - 22; i >= 0; i--) {
2220
- if (buf.readUInt32LE(i) === 101010256) {
2221
- eocdOffset = i;
2222
- break;
2223
- }
2224
- }
2225
- if (eocdOffset === -1) {
2226
- throw new Error("Invalid ZIP: EOCD not found");
2227
- }
2228
- const entryCount = buf.readUInt16LE(eocdOffset + 10);
2229
- const centralDirOffset = buf.readUInt32LE(eocdOffset + 16);
2230
- let offset = centralDirOffset;
2231
- for (let i = 0; i < entryCount; i++) {
2232
- if (buf.readUInt32LE(offset) !== 33639248) {
2233
- throw new Error(`Invalid ZIP: bad central directory signature at ${offset}`);
2234
- }
2235
- const compressionMethod = buf.readUInt16LE(offset + 10);
2236
- const compressedSize = buf.readUInt32LE(offset + 20);
2237
- const uncompressedSize = buf.readUInt32LE(offset + 24);
2238
- const nameLen = buf.readUInt16LE(offset + 28);
2239
- const extraLen = buf.readUInt16LE(offset + 30);
2240
- const commentLen = buf.readUInt16LE(offset + 32);
2241
- const localHeaderOffset = buf.readUInt32LE(offset + 42);
2242
- const name = buf.subarray(offset + 46, offset + 46 + nameLen).toString("utf-8");
2243
- if (!name.endsWith("/")) {
2244
- const localNameLen = buf.readUInt16LE(localHeaderOffset + 26);
2245
- const localExtraLen = buf.readUInt16LE(localHeaderOffset + 28);
2246
- const dataOffset = localHeaderOffset + 30 + localNameLen + localExtraLen;
2247
- const compressedData = buf.subarray(dataOffset, dataOffset + compressedSize);
2248
- let data;
2249
- if (compressionMethod === 0) {
2250
- data = Buffer.from(compressedData);
2251
- } else if (compressionMethod === 8) {
2252
- data = inflateRawSync(compressedData);
2253
- } else {
2254
- throw new Error(`Unsupported compression method: ${compressionMethod}`);
2255
- }
2256
- if (data.length !== uncompressedSize) {
2257
- throw new Error(`Size mismatch for ${name}: expected ${uncompressedSize}, got ${data.length}`);
2258
- }
2259
- entries.push({ path: name, data });
2260
- }
2261
- offset += 46 + nameLen + extraLen + commentLen;
2262
- }
2263
- return entries;
2264
- }
2265
-
2266
2438
  // src/adapters/claude.ts
2267
2439
  var DEFAULT_IDLE_TIMEOUT = 30 * 60 * 1e3;
2268
2440
  var MIN_IDLE_TIMEOUT = 60 * 1e3;
@@ -2425,7 +2597,7 @@ var ClaudeSession = class {
2425
2597
  const entries = [];
2426
2598
  let totalBytes = 0;
2427
2599
  for (const absPath of files) {
2428
- const relPath = relative3(workspaceRoot, absPath).replace(/\\/g, "/");
2600
+ const relPath = relative4(workspaceRoot, absPath).replace(/\\/g, "/");
2429
2601
  if (!relPath || relPath.startsWith("..")) continue;
2430
2602
  try {
2431
2603
  const fileStat = await stat2(absPath);
@@ -2714,7 +2886,7 @@ function logWorkspaceHint(slug, projectPath) {
2714
2886
  console.log(` ${GRAY}${getWorkspaceHint()}${RESET}`);
2715
2887
  }
2716
2888
  function sleep2(ms) {
2717
- return new Promise((resolve2) => setTimeout(resolve2, ms));
2889
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
2718
2890
  }
2719
2891
  function createAdapter(type, config) {
2720
2892
  switch (type) {
@@ -2985,7 +3157,7 @@ async function pollForToken(baseUrl, deviceCode, expiresIn, interval) {
2985
3157
  const deadline = Date.now() + expiresIn * 1e3;
2986
3158
  let pollMs = Math.max(interval * 1e3, POLL_INTERVAL_MS);
2987
3159
  while (Date.now() < deadline) {
2988
- await new Promise((resolve2) => setTimeout(resolve2, pollMs));
3160
+ await new Promise((resolve3) => setTimeout(resolve3, pollMs));
2989
3161
  const res = await fetch(`${baseUrl}/api/auth/device/token`, {
2990
3162
  method: "POST",
2991
3163
  headers: { "Content-Type": "application/json" },
@@ -3112,7 +3284,7 @@ function registerStatusCommand(program2) {
3112
3284
 
3113
3285
  // src/commands/start.ts
3114
3286
  function sleep3(ms) {
3115
- return new Promise((resolve2) => setTimeout(resolve2, ms));
3287
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
3116
3288
  }
3117
3289
  function registerStartCommand(program2) {
3118
3290
  program2.command("start [name]").description("Start agent(s) in the background").option("--all", "Start all registered agents").action(async (name, opts) => {
@@ -3207,7 +3379,7 @@ function registerStopCommand(program2) {
3207
3379
 
3208
3380
  // src/commands/restart.ts
3209
3381
  function sleep4(ms) {
3210
- return new Promise((resolve2) => setTimeout(resolve2, ms));
3382
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
3211
3383
  }
3212
3384
  function registerRestartCommand(program2) {
3213
3385
  program2.command("restart [name]").description("Restart agent(s)").option("--all", "Restart all registered agents").action(async (name, opts) => {
@@ -3294,10 +3466,10 @@ import { createInterface as createInterface2 } from "readline";
3294
3466
  import { unlinkSync } from "fs";
3295
3467
  function confirm(prompt) {
3296
3468
  const rl = createInterface2({ input: process.stdin, output: process.stderr });
3297
- return new Promise((resolve2) => {
3469
+ return new Promise((resolve3) => {
3298
3470
  rl.question(prompt, (answer) => {
3299
3471
  rl.close();
3300
- resolve2(answer.trim().toLowerCase() === "y");
3472
+ resolve3(answer.trim().toLowerCase() === "y");
3301
3473
  });
3302
3474
  });
3303
3475
  }
@@ -3350,7 +3522,7 @@ function registerOpenCommand(program2) {
3350
3522
  import { writeFileSync as writeFileSync3, existsSync as existsSync5, mkdirSync as mkdirSync5 } from "fs";
3351
3523
  import { join as join8 } from "path";
3352
3524
  import { homedir as homedir5 } from "os";
3353
- import { execSync as execSync3 } from "child_process";
3525
+ import { execSync as execSync4 } from "child_process";
3354
3526
  var LABEL = "com.agents-hot.agent-mesh";
3355
3527
  var PLIST_DIR = join8(homedir5(), "Library", "LaunchAgents");
3356
3528
  var PLIST_PATH = join8(PLIST_DIR, `${LABEL}.plist`);
@@ -3416,17 +3588,17 @@ function registerInstallCommand(program2) {
3416
3588
  }
3417
3589
  if (existsSync5(PLIST_PATH)) {
3418
3590
  try {
3419
- execSync3(`launchctl bootout gui/$(id -u) "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
3591
+ execSync4(`launchctl bootout gui/$(id -u) "${PLIST_PATH}" 2>/dev/null`, { stdio: "ignore" });
3420
3592
  } catch {
3421
3593
  }
3422
3594
  }
3423
3595
  const plist = generatePlist(node, script);
3424
3596
  writeFileSync3(PLIST_PATH, plist, { encoding: "utf-8" });
3425
3597
  try {
3426
- execSync3(`launchctl bootstrap gui/$(id -u) "${PLIST_PATH}"`, { stdio: "pipe" });
3598
+ execSync4(`launchctl bootstrap gui/$(id -u) "${PLIST_PATH}"`, { stdio: "pipe" });
3427
3599
  } catch {
3428
3600
  try {
3429
- execSync3(`launchctl load "${PLIST_PATH}"`, { stdio: "pipe" });
3601
+ execSync4(`launchctl load "${PLIST_PATH}"`, { stdio: "pipe" });
3430
3602
  } catch (err) {
3431
3603
  log.error(`Failed to load LaunchAgent: ${err}`);
3432
3604
  log.info(`Plist written to ${PLIST_PATH} \u2014 you can load it manually.`);
@@ -3450,7 +3622,7 @@ function registerInstallCommand(program2) {
3450
3622
  import { existsSync as existsSync6, unlinkSync as unlinkSync2 } from "fs";
3451
3623
  import { join as join9 } from "path";
3452
3624
  import { homedir as homedir6 } from "os";
3453
- import { execSync as execSync4 } from "child_process";
3625
+ import { execSync as execSync5 } from "child_process";
3454
3626
  var LABEL2 = "com.agents-hot.agent-mesh";
3455
3627
  var PLIST_PATH2 = join9(homedir6(), "Library", "LaunchAgents", `${LABEL2}.plist`);
3456
3628
  function registerUninstallCommand(program2) {
@@ -3466,10 +3638,10 @@ function registerUninstallCommand(program2) {
3466
3638
  return;
3467
3639
  }
3468
3640
  try {
3469
- execSync4(`launchctl bootout gui/$(id -u) "${PLIST_PATH2}" 2>/dev/null`, { stdio: "ignore" });
3641
+ execSync5(`launchctl bootout gui/$(id -u) "${PLIST_PATH2}" 2>/dev/null`, { stdio: "ignore" });
3470
3642
  } catch {
3471
3643
  try {
3472
- execSync4(`launchctl unload "${PLIST_PATH2}" 2>/dev/null`, { stdio: "ignore" });
3644
+ execSync5(`launchctl unload "${PLIST_PATH2}" 2>/dev/null`, { stdio: "ignore" });
3473
3645
  } catch {
3474
3646
  }
3475
3647
  }
@@ -3670,10 +3842,10 @@ function parseVisibilityOrExit(input) {
3670
3842
  }
3671
3843
  function readLine(prompt) {
3672
3844
  const rl = createInterface3({ input: process.stdin, output: process.stderr });
3673
- return new Promise((resolve2) => {
3845
+ return new Promise((resolve3) => {
3674
3846
  rl.question(prompt, (answer) => {
3675
3847
  rl.close();
3676
- resolve2(answer.trim());
3848
+ resolve3(answer.trim());
3677
3849
  });
3678
3850
  });
3679
3851
  }
@@ -3866,7 +4038,7 @@ function registerAgentsCommand(program2) {
3866
4038
  import { createInterface as createInterface4 } from "readline";
3867
4039
  import { existsSync as existsSync7, readFileSync as readFileSync2, mkdirSync as mkdirSync6, copyFileSync as copyFileSync2 } from "fs";
3868
4040
  import { basename as basename2, join as join10 } from "path";
3869
- import { execSync as execSync5 } from "child_process";
4041
+ import { execSync as execSync6 } from "child_process";
3870
4042
  import { createHash as createHash2, randomUUID } from "crypto";
3871
4043
  import { tmpdir } from "os";
3872
4044
 
@@ -3898,10 +4070,10 @@ function prepareUploadFile(filePath) {
3898
4070
  const tempFile = join10(tempDir, fileName);
3899
4071
  copyFileSync2(filePath, tempFile);
3900
4072
  const zipPath = join10(tempDir, "upload.zip");
3901
- execSync5(`cd "${tempDir}" && zip -q "${zipPath}" "${fileName}"`);
4073
+ execSync6(`cd "${tempDir}" && zip -q "${zipPath}" "${fileName}"`);
3902
4074
  const zipBuffer = readFileSync2(zipPath);
3903
4075
  try {
3904
- execSync5(`rm -rf "${tempDir}"`);
4076
+ execSync6(`rm -rf "${tempDir}"`);
3905
4077
  } catch {
3906
4078
  }
3907
4079
  const zipSha256 = createHash2("sha256").update(zipBuffer).digest("hex");
@@ -3917,7 +4089,7 @@ function prepareUploadFile(filePath) {
3917
4089
  };
3918
4090
  }
3919
4091
  function sleep5(ms) {
3920
- return new Promise((resolve2) => setTimeout(resolve2, ms));
4092
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
3921
4093
  }
3922
4094
  async function chatWebrtcUpload(agentId, offer, zipBuffer, token, baseUrl) {
3923
4095
  log.info(`[WebRTC] Uploading file (${(offer.zip_size / 1024).toFixed(1)} KB)...`);
@@ -4276,8 +4448,8 @@ function registerChatCommand(program2) {
4276
4448
  }
4277
4449
 
4278
4450
  // src/commands/skills.ts
4279
- import { readFile as readFile3, writeFile as writeFile3, readdir as readdir2, mkdir as mkdir2, rm, symlink, unlink } from "fs/promises";
4280
- import { join as join12, resolve, relative as relative4 } from "path";
4451
+ import { readFile as readFile3, writeFile as writeFile3, readdir as readdir2, mkdir as mkdir2, rm, symlink, unlink as unlink2 } from "fs/promises";
4452
+ import { join as join12, resolve as resolve2, relative as relative5 } from "path";
4281
4453
 
4282
4454
  // src/utils/skill-parser.ts
4283
4455
  import { readFile as readFile2, writeFile as writeFile2, stat as stat3 } from "fs/promises";
@@ -4451,7 +4623,7 @@ function outputError(error, message, hint) {
4451
4623
  process.exit(1);
4452
4624
  }
4453
4625
  function resolveSkillDir(pathArg) {
4454
- return pathArg ? resolve(pathArg) : process.cwd();
4626
+ return pathArg ? resolve2(pathArg) : process.cwd();
4455
4627
  }
4456
4628
  function parseSkillRef(ref) {
4457
4629
  if (!ref.includes("/")) {
@@ -4467,7 +4639,7 @@ function skillApiPath(authorLogin, slug) {
4467
4639
  return `/api/skills/${encodeURIComponent(authorLogin)}/${encodeURIComponent(slug)}`;
4468
4640
  }
4469
4641
  async function resolveSkillsRootAsync(pathArg) {
4470
- const projectRoot = pathArg ? resolve(pathArg) : process.cwd();
4642
+ const projectRoot = pathArg ? resolve2(pathArg) : process.cwd();
4471
4643
  const skillsDir = join12(projectRoot, ".agents", "skills");
4472
4644
  const claudeSkillsDir = join12(projectRoot, ".claude", "skills");
4473
4645
  return { projectRoot, skillsDir, claudeSkillsDir };
@@ -4476,7 +4648,7 @@ async function ensureClaudeSymlink(claudeSkillsDir, slug) {
4476
4648
  await mkdir2(claudeSkillsDir, { recursive: true });
4477
4649
  const linkPath = join12(claudeSkillsDir, slug);
4478
4650
  try {
4479
- await unlink(linkPath);
4651
+ await unlink2(linkPath);
4480
4652
  } catch {
4481
4653
  }
4482
4654
  try {
@@ -4489,7 +4661,7 @@ async function collectPackFiles(dir, manifest) {
4489
4661
  const results = [];
4490
4662
  const all = await walkDir(dir);
4491
4663
  for (const f of all) {
4492
- const rel = relative4(dir, f);
4664
+ const rel = relative5(dir, f);
4493
4665
  results.push(rel);
4494
4666
  }
4495
4667
  const mainFile = manifest.main || "SKILL.md";
@@ -4963,7 +5135,7 @@ function registerSkillsCommand(program2) {
4963
5135
  }
4964
5136
  await rm(targetDir, { recursive: true, force: true });
4965
5137
  try {
4966
- await unlink(join12(claudeSkillsDir, slug));
5138
+ await unlink2(join12(claudeSkillsDir, slug));
4967
5139
  } catch {
4968
5140
  }
4969
5141
  slog.success(`Removed skill: ${slug}`);
@@ -5101,7 +5273,7 @@ function registerDiscoverCommand(program2) {
5101
5273
 
5102
5274
  // src/commands/call.ts
5103
5275
  import { readFileSync as readFileSync3, writeFileSync as writeFileSync4, mkdirSync as mkdirSync7, copyFileSync as copyFileSync3, existsSync as existsSync8 } from "fs";
5104
- import { execSync as execSync6 } from "child_process";
5276
+ import { execSync as execSync7 } from "child_process";
5105
5277
  import { createHash as createHash3, randomUUID as randomUUID2 } from "crypto";
5106
5278
  import { join as join13, basename as basename3 } from "path";
5107
5279
  import { tmpdir as tmpdir2 } from "os";
@@ -5126,7 +5298,7 @@ async function submitRating(baseUrl, token, agentId, callId, rating) {
5126
5298
  }
5127
5299
  }
5128
5300
  function sleep6(ms) {
5129
- return new Promise((resolve2) => setTimeout(resolve2, ms));
5301
+ return new Promise((resolve3) => setTimeout(resolve3, ms));
5130
5302
  }
5131
5303
  function handleError2(err) {
5132
5304
  if (err instanceof PlatformApiError) {
@@ -5201,13 +5373,13 @@ async function webrtcDownload(agentId, offer, token, outputDir, json) {
5201
5373
  const zipPath = join13(outputDir, ".transfer.zip");
5202
5374
  writeFileSync4(zipPath, zipBuffer);
5203
5375
  try {
5204
- execSync6(`unzip -o -q "${zipPath}" -d "${outputDir}"`);
5376
+ safeUnzip(zipPath, outputDir);
5205
5377
  try {
5206
- execSync6(`rm "${zipPath}"`);
5378
+ execSync7(`rm "${zipPath}"`);
5207
5379
  } catch {
5208
5380
  }
5209
- } catch {
5210
- log.warn(`Failed to extract ZIP. Saved to: ${zipPath}`);
5381
+ } catch (unzipErr) {
5382
+ log.warn(`Failed to extract ZIP: ${unzipErr.message}. Saved to: ${zipPath}`);
5211
5383
  return;
5212
5384
  }
5213
5385
  if (json) {
@@ -5239,10 +5411,10 @@ function prepareFileForUpload(filePath) {
5239
5411
  const tempFile = join13(tempDir, fileName);
5240
5412
  copyFileSync3(filePath, tempFile);
5241
5413
  const zipPath = join13(tempDir, "upload.zip");
5242
- execSync6(`cd "${tempDir}" && zip -q "${zipPath}" "${fileName}"`);
5414
+ execSync7(`cd "${tempDir}" && zip -q "${zipPath}" "${fileName}"`);
5243
5415
  const zipBuffer = readFileSync3(zipPath);
5244
5416
  try {
5245
- execSync6(`rm -rf "${tempDir}"`);
5417
+ execSync7(`rm -rf "${tempDir}"`);
5246
5418
  } catch {
5247
5419
  }
5248
5420
  const zipSha256 = createHash3("sha256").update(zipBuffer).digest("hex");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@annals/agent-mesh",
3
- "version": "0.18.4",
3
+ "version": "0.18.5",
4
4
  "description": "CLI bridge connecting local AI agents to the Agents.Hot platform",
5
5
  "type": "module",
6
6
  "bin": {