tesseract-agent 0.2.1 → 0.2.2

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-bundle/cli.js +184 -4
  2. package/package.json +4 -1
@@ -6031,6 +6031,20 @@ function resolveUniqueName(dir, name) {
6031
6031
  }
6032
6032
  var OUTSIDE = (verb) => ({ ok: false, error: `Refusing to ${verb} outside the shared root.` });
6033
6033
  var validName = (n) => !!n && !n.includes("/") && !n.includes("\\") && n !== "." && n !== "..";
6034
+ async function readRemoteBytes(root, path) {
6035
+ if (!isInsideRoot(path, root))
6036
+ return { error: "Path is outside the shared root." };
6037
+ try {
6038
+ const s = statSync(path);
6039
+ if (!s.isFile())
6040
+ return { error: "Not a file" };
6041
+ if (s.size > REMOTE_READ_CAP)
6042
+ return { error: `File is too large to read whole over the network (${(s.size / 1024 / 1024).toFixed(1)} MB) \u2014 open it locally.` };
6043
+ return { bytes: await readFile(path), size: s.size };
6044
+ } catch (err) {
6045
+ return { error: String(err.message) };
6046
+ }
6047
+ }
6034
6048
  async function runRemoteFsOp(root, op, args) {
6035
6049
  const a = args ?? [];
6036
6050
  switch (op) {
@@ -6295,6 +6309,164 @@ function unwatchAllRemote() {
6295
6309
  remoteWatches.clear();
6296
6310
  }
6297
6311
 
6312
+ // ../../packages/host-core/dist/fs-datachannel-host.js
6313
+ var ndcPromise = null;
6314
+ function loadNdc() {
6315
+ if (!ndcPromise) {
6316
+ ndcPromise = (async () => {
6317
+ try {
6318
+ const m = await import("node-datachannel");
6319
+ return m.default ?? m;
6320
+ } catch {
6321
+ return null;
6322
+ }
6323
+ })();
6324
+ }
6325
+ return ndcPromise;
6326
+ }
6327
+ function toNdcIceServers(configs) {
6328
+ const out = [];
6329
+ for (const c of configs ?? []) {
6330
+ const urls = Array.isArray(c.urls) ? c.urls : [c.urls];
6331
+ for (const url of urls) {
6332
+ const m = /^(stun|stuns|turn|turns):([^:?]+)(?::(\d+))?(?:\?transport=(udp|tcp))?/i.exec(url);
6333
+ if (!m)
6334
+ continue;
6335
+ const scheme = m[1].toLowerCase();
6336
+ const hostname3 = m[2];
6337
+ const port = m[3] ? parseInt(m[3], 10) : scheme.endsWith("s") ? 5349 : 3478;
6338
+ if (scheme.startsWith("stun")) {
6339
+ out.push({ hostname: hostname3, port });
6340
+ continue;
6341
+ }
6342
+ const transport = (m[4] ?? "udp").toLowerCase();
6343
+ const relayType = scheme === "turns" ? "TurnTls" : transport === "tcp" ? "TurnTcp" : "TurnUdp";
6344
+ out.push({ hostname: hostname3, port, username: c.username, password: c.credential, relayType });
6345
+ }
6346
+ }
6347
+ return out;
6348
+ }
6349
+ var peers = /* @__PURE__ */ new Map();
6350
+ var delay = (ms) => new Promise((r) => setTimeout(r, ms));
6351
+ var CHUNK = 16 * 1024;
6352
+ var HIGH_WATER = 4 * 1024 * 1024;
6353
+ async function serveGet(dc, id, path, root) {
6354
+ const res = await readRemoteBytes(root, path);
6355
+ if (!dc.isOpen())
6356
+ return;
6357
+ if (res.error || !res.bytes) {
6358
+ try {
6359
+ dc.sendMessage(JSON.stringify({ t: "err", id, error: res.error ?? "read failed" }));
6360
+ } catch {
6361
+ }
6362
+ return;
6363
+ }
6364
+ const bytes = res.bytes;
6365
+ try {
6366
+ dc.sendMessage(JSON.stringify({ t: "meta", id, size: bytes.length }));
6367
+ } catch {
6368
+ return;
6369
+ }
6370
+ for (let off = 0, seq = 0; off < bytes.length; off += CHUNK, seq++) {
6371
+ let guard = 0;
6372
+ while (dc.isOpen() && dc.bufferedAmount() > HIGH_WATER && guard++ < 2e3)
6373
+ await delay(15);
6374
+ if (!dc.isOpen())
6375
+ return;
6376
+ const end = Math.min(off + CHUNK, bytes.length);
6377
+ const frame = Buffer.allocUnsafe(8 + (end - off));
6378
+ frame.writeUInt32LE(id >>> 0, 0);
6379
+ frame.writeUInt32LE(seq >>> 0, 4);
6380
+ bytes.copy(frame, 8, off, end);
6381
+ try {
6382
+ dc.sendMessageBinary(frame);
6383
+ } catch {
6384
+ return;
6385
+ }
6386
+ }
6387
+ if (dc.isOpen()) {
6388
+ try {
6389
+ dc.sendMessage(JSON.stringify({ t: "end", id }));
6390
+ } catch {
6391
+ }
6392
+ }
6393
+ }
6394
+ function wireServer(dc, root) {
6395
+ try {
6396
+ dc.setBufferedAmountLowThreshold(HIGH_WATER / 4);
6397
+ } catch {
6398
+ }
6399
+ dc.onMessage((msg) => {
6400
+ if (typeof msg !== "string")
6401
+ return;
6402
+ let req;
6403
+ try {
6404
+ req = JSON.parse(msg);
6405
+ } catch {
6406
+ return;
6407
+ }
6408
+ if (req.t === "get" && typeof req.id === "number" && typeof req.path === "string")
6409
+ void serveGet(dc, req.id, req.path, root);
6410
+ });
6411
+ }
6412
+ async function handleDcSignal(clientId, msg, root, ownHostId2, emit) {
6413
+ if (msg.type === "signal:dc-ice") {
6414
+ const peer2 = peers.get(clientId);
6415
+ if (peer2 && peer2.remoteSet) {
6416
+ try {
6417
+ peer2.pc.addRemoteCandidate(msg.candidate, msg.mid);
6418
+ } catch {
6419
+ }
6420
+ } else if (peer2)
6421
+ peer2.pendingIce.push({ candidate: msg.candidate, mid: msg.mid });
6422
+ return;
6423
+ }
6424
+ if (msg.type !== "signal:dc-offer")
6425
+ return;
6426
+ const ndc = await loadNdc();
6427
+ if (!ndc) {
6428
+ emit({ type: "signal:dc-unavailable", hostId: ownHostId2 });
6429
+ return;
6430
+ }
6431
+ releaseDcClient(clientId);
6432
+ let pc;
6433
+ try {
6434
+ pc = new ndc.PeerConnection("fsdc", { iceServers: toNdcIceServers(msg.iceServers) });
6435
+ } catch {
6436
+ emit({ type: "signal:dc-unavailable", hostId: ownHostId2 });
6437
+ return;
6438
+ }
6439
+ const peer = { pc, pendingIce: [], remoteSet: false };
6440
+ peers.set(clientId, peer);
6441
+ pc.onLocalDescription((sdp, type) => emit({ type: "signal:dc-answer", sdp, sdpType: type, hostId: ownHostId2 }));
6442
+ pc.onLocalCandidate((candidate, mid) => emit({ type: "signal:dc-ice", candidate, mid, hostId: ownHostId2 }));
6443
+ pc.onDataChannel((dc) => wireServer(dc, root));
6444
+ try {
6445
+ pc.setRemoteDescription(msg.sdp, "offer");
6446
+ peer.remoteSet = true;
6447
+ for (const c of peer.pendingIce) {
6448
+ try {
6449
+ pc.addRemoteCandidate(c.candidate, c.mid);
6450
+ } catch {
6451
+ }
6452
+ }
6453
+ peer.pendingIce = [];
6454
+ } catch {
6455
+ releaseDcClient(clientId);
6456
+ emit({ type: "signal:dc-unavailable", hostId: ownHostId2 });
6457
+ }
6458
+ }
6459
+ function releaseDcClient(clientId) {
6460
+ const peer = peers.get(clientId);
6461
+ if (!peer)
6462
+ return;
6463
+ peers.delete(clientId);
6464
+ try {
6465
+ peer.pc.close();
6466
+ } catch {
6467
+ }
6468
+ }
6469
+
6298
6470
  // ../../packages/host-core/dist/host-metrics.js
6299
6471
  import os from "node:os";
6300
6472
  function primaryIpv4(ifaces = os.networkInterfaces()) {
@@ -6331,8 +6503,8 @@ function dynamicMetrics() {
6331
6503
  import { readdir as readdir2, lstat, mkdir as mkdir3, chmod, rm as rm2, readlink, symlink, stat as stat2 } from "node:fs/promises";
6332
6504
  import { openSync as openSync2, readSync as readSync2, closeSync as closeSync2, existsSync as existsSync3, createWriteStream } from "node:fs";
6333
6505
  import { dirname as dirname4, join as join4, relative as relative2, sep as sep2 } from "node:path";
6334
- var CHUNK = 1024 * 1024;
6335
- var MAX_INFLIGHT = 8 * CHUNK;
6506
+ var CHUNK2 = 1024 * 1024;
6507
+ var MAX_INFLIGHT = 8 * CHUNK2;
6336
6508
  var IDLE_MS = 6e4;
6337
6509
  var HEAVY_DIRS = /* @__PURE__ */ new Set([".git", "node_modules", "dist", "build", ".next", ".turbo", "out", "target", ".cache", "coverage"]);
6338
6510
  var ALWAYS_SKIP = /* @__PURE__ */ new Set([".DS_Store"]);
@@ -6465,11 +6637,11 @@ async function startOutboundTransfer(msg, controllerClientId, ownHostId2, hostRo
6465
6637
  if (f.size === 0) {
6466
6638
  send2({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset: 0, base64: "", eof: true }, { hostId: toHost });
6467
6639
  } else {
6468
- for (let offset = 0; offset < f.size && !state.cancelled; offset += CHUNK) {
6640
+ for (let offset = 0; offset < f.size && !state.cancelled; offset += CHUNK2) {
6469
6641
  await waitWindow();
6470
6642
  if (state.cancelled)
6471
6643
  break;
6472
- const len = Math.min(CHUNK, f.size - offset);
6644
+ const len = Math.min(CHUNK2, f.size - offset);
6473
6645
  const buf = Buffer.alloc(len);
6474
6646
  const read = readSync2(fd, buf, 0, len, offset);
6475
6647
  send2({ type: "fs:transferChunk", transferId, toHost, fileIx, rel: f.rel, mode: f.mode, kind: "file", offset, base64: buf.subarray(0, read).toString("base64"), eof: offset + len >= f.size }, { hostId: toHost });
@@ -6939,6 +7111,7 @@ async function serveInboundFs(requestId, op, args, driverClientId) {
6939
7111
  }
6940
7112
  function releaseDriver(clientId) {
6941
7113
  unwatchRemoteClient(clientId);
7114
+ releaseDcClient(clientId);
6942
7115
  for (const [sid, cid] of [...driverBySession]) {
6943
7116
  if (cid !== clientId)
6944
7117
  continue;
@@ -7136,6 +7309,13 @@ function connect() {
7136
7309
  }
7137
7310
  return;
7138
7311
  }
7312
+ if (channel === "signal") {
7313
+ const p = env.payload;
7314
+ if (inbound && clientId && typeof p?.type === "string" && p.type.startsWith("signal:dc-")) {
7315
+ void handleDcSignal(clientId, p, HOST_ROOT, ownHostId(), (payload) => send("signal", payload, { clientId, browserId: "fsdc" }));
7316
+ }
7317
+ return;
7318
+ }
7139
7319
  };
7140
7320
  socket.onclose = () => {
7141
7321
  cleanup();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tesseract-agent",
3
- "version": "0.2.1",
3
+ "version": "0.2.2",
4
4
  "license": "UNLICENSED",
5
5
  "publishConfig": {
6
6
  "access": "public"
@@ -33,6 +33,9 @@
33
33
  "dependencies": {
34
34
  "@anthropic-ai/claude-agent-sdk": "0.2.112"
35
35
  },
36
+ "optionalDependencies": {
37
+ "node-datachannel": "^0.32.0"
38
+ },
36
39
  "devDependencies": {
37
40
  "@fineguide-tesseract/agent-core": "*",
38
41
  "@fineguide-tesseract/host-core": "*",