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.
- package/dist-bundle/cli.js +195 -6
- package/package.json +4 -1
package/dist-bundle/cli.js
CHANGED
|
@@ -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
|
|
6335
|
-
var MAX_INFLIGHT = 8 *
|
|
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 +=
|
|
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(
|
|
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
|
-
|
|
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.
|
|
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": "*",
|