@annals/agent-mesh 0.17.2 → 0.17.3

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 +115 -7
  2. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -1251,6 +1251,32 @@ var BridgeManager = class {
1251
1251
  }, 5 * 6e4);
1252
1252
  timer.unref?.();
1253
1253
  this.pendingTransfers.set(offer.transfer_id, { sender, timer });
1254
+ this.pushZipToWorker(offer.transfer_id, zipBuffer);
1255
+ }
1256
+ /** Push ZIP buffer to Worker DO via chunked transfer_upload messages */
1257
+ pushZipToWorker(transferId, zipBuffer) {
1258
+ const CHUNK_SIZE2 = 64 * 1024;
1259
+ const totalChunks = Math.ceil(zipBuffer.length / CHUNK_SIZE2);
1260
+ log.debug(`Pushing ZIP to Worker: transfer=${transferId.slice(0, 8)}... size=${zipBuffer.length} chunks=${totalChunks}`);
1261
+ for (let i = 0; i < totalChunks; i++) {
1262
+ const start = i * CHUNK_SIZE2;
1263
+ const end = Math.min(start + CHUNK_SIZE2, zipBuffer.length);
1264
+ const chunk = zipBuffer.subarray(start, end);
1265
+ const msg = {
1266
+ type: "transfer_upload",
1267
+ transfer_id: transferId,
1268
+ chunk_index: i,
1269
+ total_chunks: totalChunks,
1270
+ data: chunk.toString("base64")
1271
+ };
1272
+ this.wsClient.send(msg);
1273
+ }
1274
+ const complete = {
1275
+ type: "transfer_upload_complete",
1276
+ transfer_id: transferId
1277
+ };
1278
+ this.wsClient.send(complete);
1279
+ log.info(`ZIP pushed to Worker: transfer=${transferId.slice(0, 8)}... (${totalChunks} chunks)`);
1254
1280
  }
1255
1281
  handleRtcSignalRelay(msg) {
1256
1282
  const entry = this.pendingTransfers.get(msg.transfer_id);
@@ -4502,7 +4528,10 @@ function registerDiscoverCommand(program2) {
4502
4528
  }
4503
4529
 
4504
4530
  // src/commands/call.ts
4505
- import { readFileSync as readFileSync2, writeFileSync as writeFileSync3 } from "fs";
4531
+ import { readFileSync as readFileSync2, writeFileSync as writeFileSync3, mkdirSync as mkdirSync5 } from "fs";
4532
+ import { createHash as createHash2 } from "crypto";
4533
+ import { execSync as execSync4 } from "child_process";
4534
+ import { join as join11 } from "path";
4506
4535
  var DEFAULT_BASE_URL4 = "https://agents.hot";
4507
4536
  async function submitRating(baseUrl, token, agentId, callId, rating) {
4508
4537
  const res = await fetch(`${baseUrl}/api/agents/${agentId}/rate`, {
@@ -4534,6 +4563,75 @@ function handleError2(err) {
4534
4563
  }
4535
4564
  process.exit(1);
4536
4565
  }
4566
+ async function downloadTransferFiles(agentId, offer, token, outputDir, json) {
4567
+ const url = `${DEFAULT_BASE_URL4}/api/agents/${agentId}/transfer/${offer.transfer_id}`;
4568
+ if (!json) {
4569
+ log.info(`Downloading ${offer.file_count} file(s) (${(offer.zip_size / 1024).toFixed(1)} KB)...`);
4570
+ }
4571
+ await sleep6(1e3);
4572
+ let lastError = null;
4573
+ for (let attempt = 0; attempt < 5; attempt++) {
4574
+ try {
4575
+ const res = await fetch(url, {
4576
+ headers: { Authorization: `Bearer ${token}` }
4577
+ });
4578
+ if (res.status === 202) {
4579
+ await sleep6(2e3);
4580
+ continue;
4581
+ }
4582
+ if (res.status === 404) {
4583
+ if (attempt < 4) {
4584
+ await sleep6(2e3);
4585
+ continue;
4586
+ }
4587
+ log.warn("Transfer expired or not found");
4588
+ return;
4589
+ }
4590
+ if (!res.ok) {
4591
+ log.warn(`Download failed: HTTP ${res.status}`);
4592
+ return;
4593
+ }
4594
+ const arrayBuffer = await res.arrayBuffer();
4595
+ const zipBuffer = Buffer.from(arrayBuffer);
4596
+ const hash = createHash2("sha256").update(zipBuffer).digest("hex");
4597
+ if (hash !== offer.zip_sha256) {
4598
+ log.warn(`SHA-256 mismatch: expected ${offer.zip_sha256.slice(0, 12)}... got ${hash.slice(0, 12)}...`);
4599
+ return;
4600
+ }
4601
+ mkdirSync5(outputDir, { recursive: true });
4602
+ const zipPath = join11(outputDir, `.transfer-${offer.transfer_id.slice(0, 8)}.zip`);
4603
+ writeFileSync3(zipPath, zipBuffer);
4604
+ try {
4605
+ execSync4(`unzip -o -q "${zipPath}" -d "${outputDir}"`);
4606
+ try {
4607
+ execSync4(`rm "${zipPath}"`);
4608
+ } catch {
4609
+ }
4610
+ } catch {
4611
+ log.warn(`Failed to extract ZIP. Saved to: ${zipPath}`);
4612
+ return;
4613
+ }
4614
+ if (json) {
4615
+ console.log(JSON.stringify({
4616
+ type: "files_downloaded",
4617
+ file_count: offer.file_count,
4618
+ output_dir: outputDir,
4619
+ zip_size: zipBuffer.length,
4620
+ sha256_verified: true
4621
+ }));
4622
+ } else {
4623
+ log.success(`${offer.file_count} file(s) extracted to ${outputDir}`);
4624
+ }
4625
+ return;
4626
+ } catch (err) {
4627
+ lastError = err;
4628
+ if (attempt < 4) {
4629
+ await sleep6(2e3);
4630
+ }
4631
+ }
4632
+ }
4633
+ log.warn(`Download failed after retries: ${lastError?.message || "unknown error"}`);
4634
+ }
4537
4635
  async function asyncCall(opts) {
4538
4636
  const selfAgentId = process.env.AGENT_BRIDGE_AGENT_ID;
4539
4637
  const res = await fetch(`${DEFAULT_BASE_URL4}/api/agents/${opts.id}/call`, {
@@ -4598,6 +4696,7 @@ async function asyncCall(opts) {
4598
4696
  `);
4599
4697
  }
4600
4698
  const result = task.result || "";
4699
+ const offer = task.file_transfer_offer;
4601
4700
  if (opts.json) {
4602
4701
  console.log(JSON.stringify({
4603
4702
  call_id,
@@ -4606,7 +4705,7 @@ async function asyncCall(opts) {
4606
4705
  status: "completed",
4607
4706
  result,
4608
4707
  ...task.attachments?.length ? { attachments: task.attachments } : {},
4609
- ...task.file_transfer_offer ? { file_transfer_offer: task.file_transfer_offer } : {},
4708
+ ...offer ? { file_transfer_offer: offer } : {},
4610
4709
  rate_hint: `POST /api/agents/${opts.id}/rate body: { call_id: "${call_id}", rating: 1-5 }`
4611
4710
  }));
4612
4711
  } else {
@@ -4616,10 +4715,6 @@ async function asyncCall(opts) {
4616
4715
  log.info(` ${GRAY}File:${RESET} ${att.name} ${GRAY}${att.url}${RESET}`);
4617
4716
  }
4618
4717
  }
4619
- const offer = task.file_transfer_offer;
4620
- if (offer) {
4621
- log.info(` ${GRAY}Files:${RESET} ${offer.file_count} file(s) available via WebRTC`);
4622
- }
4623
4718
  if (session_key) {
4624
4719
  log.info(` ${GRAY}Session:${RESET} ${session_key}`);
4625
4720
  }
@@ -4628,6 +4723,10 @@ async function asyncCall(opts) {
4628
4723
  writeFileSync3(opts.outputFile, result);
4629
4724
  if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
4630
4725
  }
4726
+ if (offer && opts.withFiles) {
4727
+ const outputDir = opts.outputFile ? join11(opts.outputFile, "..", "files") : join11(process.cwd(), "agent-output");
4728
+ await downloadTransferFiles(opts.id, offer, opts.token, outputDir, opts.json);
4729
+ }
4631
4730
  if (!opts.json) {
4632
4731
  log.info(`${GRAY}Rate this call: agent-mesh rate ${call_id} <1-5> --agent ${opts.id}${RESET}`);
4633
4732
  }
@@ -4715,6 +4814,7 @@ async function streamCall(opts) {
4715
4814
  let inThinkingBlock = false;
4716
4815
  let callId = res.headers.get("X-Call-Id") || "";
4717
4816
  let sessionKey = res.headers.get("X-Session-Key") || "";
4817
+ let fileOffer = null;
4718
4818
  while (true) {
4719
4819
  const { done, value } = await reader.read();
4720
4820
  if (done) break;
@@ -4756,7 +4856,7 @@ async function streamCall(opts) {
4756
4856
  }
4757
4857
  }
4758
4858
  if (event.file_transfer_offer) {
4759
- log.info(` ${GRAY}Files:${RESET} ${event.file_transfer_offer.file_count} file(s) available via WebRTC`);
4859
+ fileOffer = event.file_transfer_offer;
4760
4860
  }
4761
4861
  } else if (event.type === "error") {
4762
4862
  process.stderr.write(`
@@ -4785,6 +4885,9 @@ Error: ${event.message}
4785
4885
  }
4786
4886
  }
4787
4887
  }
4888
+ if (event.type === "done" && event.file_transfer_offer) {
4889
+ fileOffer = event.file_transfer_offer;
4890
+ }
4788
4891
  } catch {
4789
4892
  }
4790
4893
  }
@@ -4793,6 +4896,11 @@ Error: ${event.message}
4793
4896
  writeFileSync3(opts.outputFile, outputBuffer);
4794
4897
  if (!opts.json) log.info(`Saved to ${opts.outputFile}`);
4795
4898
  }
4899
+ if (fileOffer && opts.withFiles) {
4900
+ console.log("");
4901
+ const outputDir = opts.outputFile ? join11(opts.outputFile, "..", "files") : join11(process.cwd(), "agent-output");
4902
+ await downloadTransferFiles(opts.id, fileOffer, opts.token, outputDir, opts.json);
4903
+ }
4796
4904
  if (!opts.json) {
4797
4905
  console.log("\n");
4798
4906
  log.success("Call completed");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@annals/agent-mesh",
3
- "version": "0.17.2",
3
+ "version": "0.17.3",
4
4
  "description": "CLI bridge connecting local AI agents to the Agents.Hot platform",
5
5
  "type": "module",
6
6
  "bin": {