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