@myagentroam/node 0.9.179 → 0.9.180
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/connector.js
CHANGED
|
@@ -1674,13 +1674,13 @@ export class NodeConnector {
|
|
|
1674
1674
|
this.scheduledSessions.start();
|
|
1675
1675
|
await this.initializeConversationHosting();
|
|
1676
1676
|
this.computerUseEnablement.initialize();
|
|
1677
|
-
this.directTransferService ??= this.createDirectTransferService();
|
|
1677
|
+
this.directTransferService ??= await this.createDirectTransferService();
|
|
1678
1678
|
this.connectionLifecycle.start();
|
|
1679
1679
|
this.controlChannel.connect();
|
|
1680
1680
|
}
|
|
1681
|
-
createDirectTransferService() {
|
|
1681
|
+
async createDirectTransferService() {
|
|
1682
1682
|
try {
|
|
1683
|
-
return
|
|
1683
|
+
return await DirectTransferService.create({
|
|
1684
1684
|
nodeGeneration: () => this.nodeGeneration,
|
|
1685
1685
|
send: (type, payload) => this.send(type, payload),
|
|
1686
1686
|
terminalManager: this.terminalManager,
|
|
@@ -20,6 +20,7 @@ const PNG_SIGNATURE = Buffer.from([0x89, 0x50, 0x4e, 0x47, 0x0d, 0x0a, 0x1a, 0x0
|
|
|
20
20
|
const MAX_EDIT_IMAGES = 5;
|
|
21
21
|
const SUPPORTED_EDIT_MIME_TYPES = new Set(['image/png', 'image/jpeg', 'image/webp']);
|
|
22
22
|
const IMAGE_GENERATION_RESPONSE_TIMEOUT_MS = 5 * 60 * 1000;
|
|
23
|
+
const IMAGE_GENERATION_READ_IDLE_TIMEOUT_MS = 5 * 60 * 1000;
|
|
23
24
|
export const codexImageGenToolDefinition = {
|
|
24
25
|
name: 'codex_image_gen',
|
|
25
26
|
agentScope: 'ROOT_ONLY',
|
|
@@ -230,19 +231,34 @@ async function readJsonResponse(response, signal) {
|
|
|
230
231
|
if (response.body === null)
|
|
231
232
|
return {};
|
|
232
233
|
const reader = response.body.getReader();
|
|
234
|
+
const readController = new AbortController();
|
|
235
|
+
const readSignal = AbortSignal.any([signal, readController.signal]);
|
|
233
236
|
const abort = () => {
|
|
234
|
-
void reader.cancel(
|
|
237
|
+
void reader.cancel(readSignal.reason).catch(() => undefined);
|
|
235
238
|
};
|
|
236
|
-
|
|
239
|
+
readSignal.addEventListener('abort', abort, { once: true });
|
|
240
|
+
const onIdle = () => {
|
|
241
|
+
readController.abort(new MarAgentError('MAR_AGENT_IMAGE_GENERATION_READ_TIMEOUT', 'Image response body read timed out waiting for data.', {
|
|
242
|
+
details: {
|
|
243
|
+
reason: 'IMAGE_RESPONSE_READ_TIMEOUT',
|
|
244
|
+
idleTimeoutMs: IMAGE_GENERATION_READ_IDLE_TIMEOUT_MS
|
|
245
|
+
}
|
|
246
|
+
}));
|
|
247
|
+
};
|
|
248
|
+
let readTimeout = setTimeout(onIdle, IMAGE_GENERATION_READ_IDLE_TIMEOUT_MS);
|
|
237
249
|
const chunks = [];
|
|
238
250
|
let bytes = 0;
|
|
239
251
|
try {
|
|
240
|
-
|
|
252
|
+
readSignal.throwIfAborted();
|
|
241
253
|
for (;;) {
|
|
242
|
-
const chunk = await reader.read();
|
|
243
|
-
|
|
254
|
+
const chunk = await waitForImageStep(reader.read(), readSignal);
|
|
255
|
+
readSignal.throwIfAborted();
|
|
244
256
|
if (chunk.done)
|
|
245
257
|
break;
|
|
258
|
+
if (chunk.value.byteLength === 0)
|
|
259
|
+
continue;
|
|
260
|
+
clearTimeout(readTimeout);
|
|
261
|
+
readTimeout = setTimeout(onIdle, IMAGE_GENERATION_READ_IDLE_TIMEOUT_MS);
|
|
246
262
|
bytes += chunk.value.byteLength;
|
|
247
263
|
if (bytes > RESPONSE_MAX_BYTES)
|
|
248
264
|
throw new MarAgentError('MAR_AGENT_TOOL_OUTPUT_LIMIT', 'Image response exceeded the size limit.');
|
|
@@ -254,7 +270,8 @@ async function readJsonResponse(response, signal) {
|
|
|
254
270
|
throw error;
|
|
255
271
|
}
|
|
256
272
|
finally {
|
|
257
|
-
|
|
273
|
+
clearTimeout(readTimeout);
|
|
274
|
+
readSignal.removeEventListener('abort', abort);
|
|
258
275
|
reader.releaseLock();
|
|
259
276
|
}
|
|
260
277
|
try {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createSocket } from 'node:dgram';
|
|
1
2
|
import { directDataControlFrameSchema, directNodeCommandSchema } from '@myagentroam/protocol';
|
|
2
3
|
import { TerminalDirectService } from './terminal-direct-service.js';
|
|
3
4
|
import { IceUdpMuxListener as NativeIceUdpMuxListener } from 'node-datachannel';
|
|
@@ -21,12 +22,18 @@ export class DirectTransferService {
|
|
|
21
22
|
leaseCheckMs;
|
|
22
23
|
terminalDirect;
|
|
23
24
|
disposed = false;
|
|
24
|
-
|
|
25
|
-
this.options = options;
|
|
26
|
-
this.now = options.now ?? Date.now;
|
|
25
|
+
static async create(options) {
|
|
27
26
|
const range = options.udpPortRange?.() ?? { begin: 49_152, end: 49_215 };
|
|
28
27
|
const createIceUdpMuxListener = options.createIceUdpMuxListener ?? ((port) => new NativeIceUdpMuxListener(port));
|
|
29
|
-
|
|
28
|
+
// Windows can accept an IPv6 mux bind while another IPv4 endpoint owns the port.
|
|
29
|
+
const probe = options.probeUdp4Port ?? (process.platform === 'win32' ? probeUdp4Port : undefined);
|
|
30
|
+
const listener = await bindIceUdpMuxListener(range, createIceUdpMuxListener, probe);
|
|
31
|
+
return new DirectTransferService(options, listener);
|
|
32
|
+
}
|
|
33
|
+
constructor(options, iceUdpMuxListener) {
|
|
34
|
+
this.options = options;
|
|
35
|
+
this.now = options.now ?? Date.now;
|
|
36
|
+
this.iceUdpMuxListener = iceUdpMuxListener;
|
|
30
37
|
const udpPort = this.iceUdpMuxListener.port();
|
|
31
38
|
this.peerConfiguration = {
|
|
32
39
|
iceServers: [],
|
|
@@ -465,10 +472,12 @@ function openFrameSessionId(data) {
|
|
|
465
472
|
return undefined;
|
|
466
473
|
}
|
|
467
474
|
}
|
|
468
|
-
function bindIceUdpMuxListener(range, create) {
|
|
475
|
+
async function bindIceUdpMuxListener(range, create, probe) {
|
|
469
476
|
let lastError;
|
|
470
477
|
for (let port = range.begin; port <= range.end; port += 1) {
|
|
471
478
|
try {
|
|
479
|
+
if (probe !== undefined)
|
|
480
|
+
await probe(port);
|
|
472
481
|
return create(port);
|
|
473
482
|
}
|
|
474
483
|
catch (error) {
|
|
@@ -477,6 +486,13 @@ function bindIceUdpMuxListener(range, create) {
|
|
|
477
486
|
}
|
|
478
487
|
throw new Error('DIRECT_UDP_PORT_UNAVAILABLE', { cause: lastError });
|
|
479
488
|
}
|
|
489
|
+
export function probeUdp4Port(port) {
|
|
490
|
+
const socket = createSocket({ type: 'udp4', reuseAddr: false });
|
|
491
|
+
return new Promise((resolve, reject) => {
|
|
492
|
+
socket.once('error', (error) => socket.close(() => reject(error)));
|
|
493
|
+
socket.bind({ port, address: '0.0.0.0', exclusive: true }, () => socket.close(() => resolve()));
|
|
494
|
+
});
|
|
495
|
+
}
|
|
480
496
|
export function fingerprint(sdp) {
|
|
481
497
|
const match = sdp?.match(/^a=fingerprint:(sha-256 [A-F0-9:]+)\r?$/imu);
|
|
482
498
|
return match?.[1];
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@myagentroam/node",
|
|
3
|
-
"version": "0.9.
|
|
3
|
+
"version": "0.9.180",
|
|
4
4
|
"description": "MyAgentRoam Node runtime CLI.",
|
|
5
5
|
"license": "Apache-2.0 AND GPL-2.0-or-later",
|
|
6
6
|
"type": "module",
|
|
@@ -36,10 +36,10 @@
|
|
|
36
36
|
"playwright": "1.62.1",
|
|
37
37
|
"ws": "^8.21.3",
|
|
38
38
|
"zod": "4.4.3",
|
|
39
|
-
"@myagentroam/agent": "0.9.
|
|
40
|
-
"@myagentroam/
|
|
39
|
+
"@myagentroam/agent": "0.9.180",
|
|
40
|
+
"@myagentroam/protocol": "0.9.180",
|
|
41
41
|
"@myagentroam/marctl": "0.9.123",
|
|
42
|
-
"@myagentroam/
|
|
42
|
+
"@myagentroam/code-navigation": "0.9.129"
|
|
43
43
|
},
|
|
44
44
|
"devDependencies": {
|
|
45
45
|
"@types/ws": "^8.18.1"
|