@agentproto/acp 0.1.0 → 0.3.0
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/client/index.d.ts +66 -2
- package/dist/client/index.mjs +140 -10
- package/dist/client/index.mjs.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/manifest/index.d.ts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/tunnel/index.d.ts +77 -1
- package/dist/tunnel/index.mjs +93 -10
- package/dist/tunnel/index.mjs.map +1 -1
- package/dist/{types-BPyht7LH.d.ts → types-DC2phPNG.d.ts} +25 -1
- package/package.json +1 -1
package/dist/tunnel/index.mjs
CHANGED
|
@@ -58,6 +58,8 @@ function encodeData(bytes) {
|
|
|
58
58
|
function decodeData(data) {
|
|
59
59
|
return Buffer.from(data, "base64");
|
|
60
60
|
}
|
|
61
|
+
var DEFAULT_WS_DIAL_TIMEOUT_MS = 1e4;
|
|
62
|
+
var DEFAULT_HTTP_FORWARD_TIMEOUT_MS = 3e4;
|
|
61
63
|
function createTunnelServer(opts) {
|
|
62
64
|
const children = /* @__PURE__ */ new Map();
|
|
63
65
|
const ptyProcs = /* @__PURE__ */ new Map();
|
|
@@ -68,7 +70,8 @@ function createTunnelServer(opts) {
|
|
|
68
70
|
version: TUNNEL_VERSION,
|
|
69
71
|
capabilities: {
|
|
70
72
|
pty: opts.pty === true,
|
|
71
|
-
wsForward: opts.dialUpstreamWs !== void 0 && !!opts.httpUpstream
|
|
73
|
+
wsForward: opts.dialUpstreamWs !== void 0 && !!opts.httpUpstream,
|
|
74
|
+
...opts.tools && opts.tools.length ? { tools: opts.tools } : {}
|
|
72
75
|
},
|
|
73
76
|
label: opts.label,
|
|
74
77
|
daemon: {
|
|
@@ -383,22 +386,69 @@ function createTunnelServer(opts) {
|
|
|
383
386
|
if (HOP_BY_HOP.has(k.toLowerCase())) continue;
|
|
384
387
|
headers[k] = v;
|
|
385
388
|
}
|
|
386
|
-
|
|
389
|
+
let httpBase = opts.httpUpstream;
|
|
390
|
+
if (req.upstream) {
|
|
391
|
+
const resolved = await opts.resolveWsUpstream?.(req.upstream);
|
|
392
|
+
if (!resolved) {
|
|
393
|
+
reject(
|
|
394
|
+
502,
|
|
395
|
+
"unknown_ws_upstream",
|
|
396
|
+
`No WS upstream registered for '${req.upstream}'.`
|
|
397
|
+
);
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
httpBase = resolved;
|
|
401
|
+
}
|
|
402
|
+
const base = httpBase.replace(/^http(s?):\/\//, "ws$1://");
|
|
387
403
|
const url = `${base.replace(/\/$/, "")}${req.path}`;
|
|
404
|
+
const dialTimeoutMs = opts.wsDialTimeoutMs ?? DEFAULT_WS_DIAL_TIMEOUT_MS;
|
|
405
|
+
const dialAbort = new AbortController();
|
|
406
|
+
let dialTimedOut = false;
|
|
407
|
+
let dialTimer = null;
|
|
408
|
+
const dialPromise = opts.dialUpstreamWs({
|
|
409
|
+
url,
|
|
410
|
+
...req.protocols && req.protocols.length > 0 ? { protocols: req.protocols } : {},
|
|
411
|
+
headers,
|
|
412
|
+
signal: dialAbort.signal
|
|
413
|
+
});
|
|
414
|
+
const timeoutPromise = new Promise((_resolve, rej) => {
|
|
415
|
+
dialTimer = setTimeout(() => {
|
|
416
|
+
dialTimedOut = true;
|
|
417
|
+
dialAbort.abort(new Error("ws_dial_timeout"));
|
|
418
|
+
rej(new Error(`upstream WS dial timed out after ${dialTimeoutMs}ms`));
|
|
419
|
+
}, dialTimeoutMs);
|
|
420
|
+
if (typeof dialTimer !== "number") dialTimer.unref();
|
|
421
|
+
});
|
|
388
422
|
let upstream;
|
|
389
423
|
try {
|
|
390
|
-
upstream = await
|
|
391
|
-
url,
|
|
392
|
-
...req.protocols && req.protocols.length > 0 ? { protocols: req.protocols } : {},
|
|
393
|
-
headers
|
|
394
|
-
});
|
|
424
|
+
upstream = await Promise.race([dialPromise, timeoutPromise]);
|
|
395
425
|
} catch (err) {
|
|
426
|
+
if (dialTimer) clearTimeout(dialTimer);
|
|
427
|
+
if (dialTimedOut) {
|
|
428
|
+
dialPromise.then(
|
|
429
|
+
(sock) => {
|
|
430
|
+
try {
|
|
431
|
+
sock.close(1001, "dial_timeout");
|
|
432
|
+
} catch {
|
|
433
|
+
}
|
|
434
|
+
},
|
|
435
|
+
() => {
|
|
436
|
+
}
|
|
437
|
+
);
|
|
438
|
+
reject(
|
|
439
|
+
504,
|
|
440
|
+
"upstream_ws_timeout",
|
|
441
|
+
`Upstream did not complete the WS upgrade within ${dialTimeoutMs}ms.`
|
|
442
|
+
);
|
|
443
|
+
return;
|
|
444
|
+
}
|
|
396
445
|
const message = err instanceof Error ? err.message : String(err);
|
|
397
446
|
const m = message.match(/Unexpected server response: (\d+)/);
|
|
398
447
|
const status = m ? Number.parseInt(m[1], 10) : 502;
|
|
399
448
|
reject(status, "upstream_ws_failed", message);
|
|
400
449
|
return;
|
|
401
450
|
}
|
|
451
|
+
if (dialTimer) clearTimeout(dialTimer);
|
|
402
452
|
if (closed) {
|
|
403
453
|
try {
|
|
404
454
|
upstream.close(1001, "tunnel_closed");
|
|
@@ -501,7 +551,7 @@ function createTunnelServer(opts) {
|
|
|
501
551
|
}
|
|
502
552
|
const url = `${opts.httpUpstream.replace(/\/$/, "")}${req.path}`;
|
|
503
553
|
const controller = new AbortController();
|
|
504
|
-
const timeoutMs = req.timeoutMs ??
|
|
554
|
+
const timeoutMs = req.timeoutMs ?? opts.httpForwardTimeoutMs ?? DEFAULT_HTTP_FORWARD_TIMEOUT_MS;
|
|
505
555
|
let timer = setTimeout(
|
|
506
556
|
() => controller.abort(),
|
|
507
557
|
timeoutMs
|
|
@@ -537,9 +587,41 @@ function createTunnelServer(opts) {
|
|
|
537
587
|
headers: outHeaders
|
|
538
588
|
});
|
|
539
589
|
const reader = upstreamRes.body.getReader();
|
|
590
|
+
const idleMs = opts.httpStreamIdleTimeoutMs;
|
|
591
|
+
const IDLE = /* @__PURE__ */ Symbol("idle");
|
|
592
|
+
const readChunk = async () => {
|
|
593
|
+
if (!idleMs) return reader.read();
|
|
594
|
+
let idleTimer = null;
|
|
595
|
+
const idle = new Promise((resolve) => {
|
|
596
|
+
idleTimer = setTimeout(() => resolve(IDLE), idleMs);
|
|
597
|
+
if (typeof idleTimer !== "number") idleTimer.unref();
|
|
598
|
+
});
|
|
599
|
+
try {
|
|
600
|
+
return await Promise.race([reader.read(), idle]);
|
|
601
|
+
} finally {
|
|
602
|
+
if (idleTimer) clearTimeout(idleTimer);
|
|
603
|
+
}
|
|
604
|
+
};
|
|
540
605
|
try {
|
|
541
606
|
while (true) {
|
|
542
|
-
const
|
|
607
|
+
const chunk = await readChunk();
|
|
608
|
+
if (chunk === IDLE) {
|
|
609
|
+
try {
|
|
610
|
+
await reader.cancel();
|
|
611
|
+
} catch {
|
|
612
|
+
}
|
|
613
|
+
opts.sink.send({
|
|
614
|
+
t: "http_response_chunk",
|
|
615
|
+
reqId: req.reqId,
|
|
616
|
+
end: true,
|
|
617
|
+
error: {
|
|
618
|
+
code: "upstream_stream_idle_timeout",
|
|
619
|
+
message: `No data from upstream for ${idleMs}ms.`
|
|
620
|
+
}
|
|
621
|
+
});
|
|
622
|
+
return;
|
|
623
|
+
}
|
|
624
|
+
const { value, done } = chunk;
|
|
543
625
|
if (done) {
|
|
544
626
|
opts.sink.send({
|
|
545
627
|
t: "http_response_chunk",
|
|
@@ -1031,6 +1113,7 @@ function createTunnelClient(opts) {
|
|
|
1031
1113
|
t: "ws_open",
|
|
1032
1114
|
reqId,
|
|
1033
1115
|
path: req.path,
|
|
1116
|
+
...req.upstream ? { upstream: req.upstream } : {},
|
|
1034
1117
|
...req.headers ? { headers: req.headers } : {},
|
|
1035
1118
|
...req.protocols && req.protocols.length > 0 ? { protocols: req.protocols } : {}
|
|
1036
1119
|
};
|
|
@@ -1280,6 +1363,6 @@ function wrapWebSocket(ws) {
|
|
|
1280
1363
|
};
|
|
1281
1364
|
}
|
|
1282
1365
|
|
|
1283
|
-
export { TUNNEL_VERSION, createTunnelClient, createTunnelServer, decodeData, encodeData, encodeFrame, parseFrame, wrapWebSocket };
|
|
1366
|
+
export { DEFAULT_HTTP_FORWARD_TIMEOUT_MS, DEFAULT_WS_DIAL_TIMEOUT_MS, TUNNEL_VERSION, createTunnelClient, createTunnelServer, decodeData, encodeData, encodeFrame, parseFrame, wrapWebSocket };
|
|
1284
1367
|
//# sourceMappingURL=index.mjs.map
|
|
1285
1368
|
//# sourceMappingURL=index.mjs.map
|