@robota-sdk/agent-transport-ws 3.0.0-beta.62 → 3.0.0-beta.63
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/node/index.cjs +96 -1
- package/dist/node/index.d.cts +47 -2
- package/dist/node/index.d.ts +47 -2
- package/dist/node/index.js +95 -1
- package/package.json +6 -2
package/dist/node/index.cjs
CHANGED
|
@@ -20,6 +20,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
20
20
|
// src/index.ts
|
|
21
21
|
var index_exports = {};
|
|
22
22
|
__export(index_exports, {
|
|
23
|
+
WsTransport: () => WsTransport,
|
|
23
24
|
createWsHandler: () => createWsHandler,
|
|
24
25
|
createWsTransport: () => createWsTransport
|
|
25
26
|
});
|
|
@@ -158,6 +159,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
158
159
|
const onError = (error) => send({ type: "error", message: error.message });
|
|
159
160
|
const onBackgroundTaskEvent = (event) => send({ type: "background_task_event", event });
|
|
160
161
|
const onBackgroundJobGroupEvent = (event) => send({ type: "background_job_group_event", event });
|
|
162
|
+
const onExecutionWorkspace = (event) => send({ type: "execution_workspace_event", snapshot: event.snapshot });
|
|
161
163
|
session.on("user_message", onUserMessage);
|
|
162
164
|
session.on("text_delta", onTextDelta);
|
|
163
165
|
session.on("tool_start", onToolStart);
|
|
@@ -168,6 +170,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
168
170
|
session.on("error", onError);
|
|
169
171
|
session.on("background_task_event", onBackgroundTaskEvent);
|
|
170
172
|
session.on("background_job_group_event", onBackgroundJobGroupEvent);
|
|
173
|
+
session.on("execution_workspace_event", onExecutionWorkspace);
|
|
171
174
|
return () => {
|
|
172
175
|
session.off("user_message", onUserMessage);
|
|
173
176
|
session.off("text_delta", onTextDelta);
|
|
@@ -179,6 +182,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
179
182
|
session.off("error", onError);
|
|
180
183
|
session.off("background_task_event", onBackgroundTaskEvent);
|
|
181
184
|
session.off("background_job_group_event", onBackgroundJobGroupEvent);
|
|
185
|
+
session.off("execution_workspace_event", onExecutionWorkspace);
|
|
182
186
|
};
|
|
183
187
|
}
|
|
184
188
|
function createWsMessageHandler(session, send) {
|
|
@@ -222,7 +226,7 @@ function isSessionControlMessage(msg) {
|
|
|
222
226
|
return msg.type === "submit" || msg.type === "command" || msg.type === "abort" || msg.type === "cancel-queue";
|
|
223
227
|
}
|
|
224
228
|
function isSessionQueryMessage(msg) {
|
|
225
|
-
return msg.type === "get-messages" || msg.type === "get-context" || msg.type === "get-executing" || msg.type === "get-pending";
|
|
229
|
+
return msg.type === "get-messages" || msg.type === "get-context" || msg.type === "get-executing" || msg.type === "get-pending" || msg.type === "get-execution-workspace";
|
|
226
230
|
}
|
|
227
231
|
function isBackgroundQueryMessage(msg) {
|
|
228
232
|
return msg.type === "get-background-tasks" || msg.type === "get-background-task" || msg.type === "read-background-task-log" || msg.type === "get-background-job-groups" || msg.type === "get-background-job-group" || msg.type === "wait-background-job-group";
|
|
@@ -264,6 +268,11 @@ function handleSessionQueryMessage(session, send, msg) {
|
|
|
264
268
|
send({ type: "context", state: session.getContextState() });
|
|
265
269
|
} else if (msg.type === "get-executing") {
|
|
266
270
|
send({ type: "executing", executing: session.isExecuting() });
|
|
271
|
+
} else if (msg.type === "get-execution-workspace") {
|
|
272
|
+
send({
|
|
273
|
+
type: "execution_workspace_event",
|
|
274
|
+
snapshot: session.getExecutionWorkspaceSnapshot()
|
|
275
|
+
});
|
|
267
276
|
} else {
|
|
268
277
|
send({ type: "pending", pending: session.getPendingPrompt() });
|
|
269
278
|
}
|
|
@@ -292,8 +301,94 @@ function createWsTransport(options) {
|
|
|
292
301
|
}
|
|
293
302
|
};
|
|
294
303
|
}
|
|
304
|
+
|
|
305
|
+
// src/ws-transport-configurable.ts
|
|
306
|
+
var import_node_http = require("http");
|
|
307
|
+
var import_ws = require("ws");
|
|
308
|
+
var DEFAULT_PORT = 7070;
|
|
309
|
+
var DEFAULT_MAX_RETRIES = 20;
|
|
310
|
+
var WsTransport = class {
|
|
311
|
+
name = "ws";
|
|
312
|
+
defaultEnabled = true;
|
|
313
|
+
optionsSchema = {
|
|
314
|
+
port: { type: "number", description: "WebSocket server port", default: DEFAULT_PORT },
|
|
315
|
+
maxRetries: {
|
|
316
|
+
type: "number",
|
|
317
|
+
description: "Port retry attempts when port is occupied",
|
|
318
|
+
default: DEFAULT_MAX_RETRIES
|
|
319
|
+
}
|
|
320
|
+
};
|
|
321
|
+
session = null;
|
|
322
|
+
stopFn = null;
|
|
323
|
+
port;
|
|
324
|
+
maxRetries;
|
|
325
|
+
constructor(config = {}) {
|
|
326
|
+
this.port = config.port ?? DEFAULT_PORT;
|
|
327
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
328
|
+
}
|
|
329
|
+
attach(session) {
|
|
330
|
+
this.session = session;
|
|
331
|
+
}
|
|
332
|
+
async start() {
|
|
333
|
+
if (!this.session) throw new Error("WsTransport: attach() must be called before start()");
|
|
334
|
+
const handle = await this.bindWithRetry(this.session, this.port, this.maxRetries);
|
|
335
|
+
this.stopFn = handle.stop;
|
|
336
|
+
}
|
|
337
|
+
async stop() {
|
|
338
|
+
await this.stopFn?.();
|
|
339
|
+
this.stopFn = null;
|
|
340
|
+
}
|
|
341
|
+
validateOptions(options) {
|
|
342
|
+
const { port, maxRetries } = options;
|
|
343
|
+
if (port !== void 0 && (typeof port !== "number" || port < 1 || port > 65535)) return false;
|
|
344
|
+
if (maxRetries !== void 0 && (typeof maxRetries !== "number" || maxRetries < 0))
|
|
345
|
+
return false;
|
|
346
|
+
return true;
|
|
347
|
+
}
|
|
348
|
+
bindWithRetry(session, port, retriesLeft) {
|
|
349
|
+
return this.tryBind(session, port).catch((err) => {
|
|
350
|
+
if (err.code === "EADDRINUSE" && retriesLeft > 0)
|
|
351
|
+
return this.bindWithRetry(session, port + 1, retriesLeft - 1);
|
|
352
|
+
throw err;
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
tryBind(session, port) {
|
|
356
|
+
return new Promise((resolve, reject) => {
|
|
357
|
+
const httpServer = (0, import_node_http.createServer)((_, res) => {
|
|
358
|
+
res.writeHead(400).end("WebSocket endpoint");
|
|
359
|
+
});
|
|
360
|
+
httpServer.on("error", (err) => {
|
|
361
|
+
httpServer.close();
|
|
362
|
+
reject(err);
|
|
363
|
+
});
|
|
364
|
+
httpServer.listen(port, "127.0.0.1", () => {
|
|
365
|
+
const wss = new import_ws.WebSocketServer({ server: httpServer });
|
|
366
|
+
wss.on("connection", (ws) => {
|
|
367
|
+
const send = (message) => {
|
|
368
|
+
if (ws.readyState === import_ws.WebSocket.OPEN) ws.send(JSON.stringify(message));
|
|
369
|
+
};
|
|
370
|
+
const { onMessage, cleanup } = createWsHandler({ session, send });
|
|
371
|
+
ws.on("message", (data) => onMessage(String(data)));
|
|
372
|
+
ws.on("close", cleanup);
|
|
373
|
+
ws.on("error", cleanup);
|
|
374
|
+
send({ type: "messages", messages: session.getMessages() });
|
|
375
|
+
send({
|
|
376
|
+
type: "execution_workspace_event",
|
|
377
|
+
snapshot: session.getExecutionWorkspaceSnapshot()
|
|
378
|
+
});
|
|
379
|
+
});
|
|
380
|
+
resolve({
|
|
381
|
+
stop: () => new Promise((res) => {
|
|
382
|
+
wss.close(() => httpServer.close(() => res()));
|
|
383
|
+
})
|
|
384
|
+
});
|
|
385
|
+
});
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
};
|
|
295
389
|
// Annotate the CommonJS export names for ESM import in node:
|
|
296
390
|
0 && (module.exports = {
|
|
391
|
+
WsTransport,
|
|
297
392
|
createWsHandler,
|
|
298
393
|
createWsTransport
|
|
299
394
|
});
|
package/dist/node/index.d.cts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { IToolState, IExecutionResult, ICommandResult, InteractiveSession, TBackgroundTaskEvent, TBackgroundJobGroupEvent, IBackgroundTaskState, IBackgroundJobGroupState, IBackgroundTaskLogPage, IBackgroundTaskListFilter, IBackgroundTaskInput, IBackgroundTaskLogCursor
|
|
1
|
+
import { IToolState, IExecutionResult, ICommandResult, InteractiveSession, IExecutionWorkspaceSnapshot, TBackgroundTaskEvent, TBackgroundJobGroupEvent, IBackgroundTaskState, IBackgroundJobGroupState, IBackgroundTaskLogPage, IBackgroundTaskListFilter, IBackgroundTaskInput, IBackgroundTaskLogCursor } from '@robota-sdk/agent-sdk';
|
|
2
|
+
export { IExecutionWorkspaceEntry, IExecutionWorkspaceSnapshot, TExecutionAttention, TExecutionWorkspaceStatus } from '@robota-sdk/agent-sdk';
|
|
3
|
+
import { ITransportAdapter, IConfigurableTransport } from '@robota-sdk/agent-interface-transport';
|
|
4
|
+
import { ISession, TUniversalValue } from '@robota-sdk/agent-core';
|
|
2
5
|
|
|
3
6
|
type TBackgroundControlAction = 'cancel' | 'close' | 'send';
|
|
4
7
|
/** Inbound message from client to server. */
|
|
@@ -21,6 +24,8 @@ type TClientMessage = {
|
|
|
21
24
|
type: 'get-executing';
|
|
22
25
|
} | {
|
|
23
26
|
type: 'get-pending';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'get-execution-workspace';
|
|
24
29
|
} | {
|
|
25
30
|
type: 'get-background-tasks';
|
|
26
31
|
filter?: IBackgroundTaskListFilter;
|
|
@@ -94,6 +99,9 @@ type TServerMessage = {
|
|
|
94
99
|
} | {
|
|
95
100
|
type: 'pending';
|
|
96
101
|
pending: string | null;
|
|
102
|
+
} | {
|
|
103
|
+
type: 'execution_workspace_event';
|
|
104
|
+
snapshot: IExecutionWorkspaceSnapshot;
|
|
97
105
|
} | {
|
|
98
106
|
type: 'background_task_event';
|
|
99
107
|
event: TBackgroundTaskEvent;
|
|
@@ -183,4 +191,41 @@ declare function createWsTransport(options: IWsTransportOptions): ITransportAdap
|
|
|
183
191
|
onMessage: ((data: string) => void) | null;
|
|
184
192
|
};
|
|
185
193
|
|
|
186
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Self-contained WS transport implementing IConfigurableTransport.
|
|
196
|
+
* Owns the WebSocket server lifecycle (ws package), started/stopped via the transport registry.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
interface IWsTransportConfig {
|
|
200
|
+
port?: number;
|
|
201
|
+
maxRetries?: number;
|
|
202
|
+
}
|
|
203
|
+
declare class WsTransport implements IConfigurableTransport {
|
|
204
|
+
readonly name = "ws";
|
|
205
|
+
readonly defaultEnabled = true;
|
|
206
|
+
readonly optionsSchema: {
|
|
207
|
+
port: {
|
|
208
|
+
type: string;
|
|
209
|
+
description: string;
|
|
210
|
+
default: number;
|
|
211
|
+
};
|
|
212
|
+
maxRetries: {
|
|
213
|
+
type: string;
|
|
214
|
+
description: string;
|
|
215
|
+
default: number;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
private session;
|
|
219
|
+
private stopFn;
|
|
220
|
+
private readonly port;
|
|
221
|
+
private readonly maxRetries;
|
|
222
|
+
constructor(config?: IWsTransportConfig);
|
|
223
|
+
attach(session: ISession): void;
|
|
224
|
+
start(): Promise<void>;
|
|
225
|
+
stop(): Promise<void>;
|
|
226
|
+
validateOptions(options: Record<string, TUniversalValue>): boolean;
|
|
227
|
+
private bindWithRetry;
|
|
228
|
+
private tryBind;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export { type IWsHandlerOptions, type IWsTransportConfig, type IWsTransportOptions, type TClientMessage, type TServerMessage, WsTransport, createWsHandler, createWsTransport };
|
package/dist/node/index.d.ts
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import { IToolState, IExecutionResult, ICommandResult, InteractiveSession, TBackgroundTaskEvent, TBackgroundJobGroupEvent, IBackgroundTaskState, IBackgroundJobGroupState, IBackgroundTaskLogPage, IBackgroundTaskListFilter, IBackgroundTaskInput, IBackgroundTaskLogCursor
|
|
1
|
+
import { IToolState, IExecutionResult, ICommandResult, InteractiveSession, IExecutionWorkspaceSnapshot, TBackgroundTaskEvent, TBackgroundJobGroupEvent, IBackgroundTaskState, IBackgroundJobGroupState, IBackgroundTaskLogPage, IBackgroundTaskListFilter, IBackgroundTaskInput, IBackgroundTaskLogCursor } from '@robota-sdk/agent-sdk';
|
|
2
|
+
export { IExecutionWorkspaceEntry, IExecutionWorkspaceSnapshot, TExecutionAttention, TExecutionWorkspaceStatus } from '@robota-sdk/agent-sdk';
|
|
3
|
+
import { ITransportAdapter, IConfigurableTransport } from '@robota-sdk/agent-interface-transport';
|
|
4
|
+
import { ISession, TUniversalValue } from '@robota-sdk/agent-core';
|
|
2
5
|
|
|
3
6
|
type TBackgroundControlAction = 'cancel' | 'close' | 'send';
|
|
4
7
|
/** Inbound message from client to server. */
|
|
@@ -21,6 +24,8 @@ type TClientMessage = {
|
|
|
21
24
|
type: 'get-executing';
|
|
22
25
|
} | {
|
|
23
26
|
type: 'get-pending';
|
|
27
|
+
} | {
|
|
28
|
+
type: 'get-execution-workspace';
|
|
24
29
|
} | {
|
|
25
30
|
type: 'get-background-tasks';
|
|
26
31
|
filter?: IBackgroundTaskListFilter;
|
|
@@ -94,6 +99,9 @@ type TServerMessage = {
|
|
|
94
99
|
} | {
|
|
95
100
|
type: 'pending';
|
|
96
101
|
pending: string | null;
|
|
102
|
+
} | {
|
|
103
|
+
type: 'execution_workspace_event';
|
|
104
|
+
snapshot: IExecutionWorkspaceSnapshot;
|
|
97
105
|
} | {
|
|
98
106
|
type: 'background_task_event';
|
|
99
107
|
event: TBackgroundTaskEvent;
|
|
@@ -183,4 +191,41 @@ declare function createWsTransport(options: IWsTransportOptions): ITransportAdap
|
|
|
183
191
|
onMessage: ((data: string) => void) | null;
|
|
184
192
|
};
|
|
185
193
|
|
|
186
|
-
|
|
194
|
+
/**
|
|
195
|
+
* Self-contained WS transport implementing IConfigurableTransport.
|
|
196
|
+
* Owns the WebSocket server lifecycle (ws package), started/stopped via the transport registry.
|
|
197
|
+
*/
|
|
198
|
+
|
|
199
|
+
interface IWsTransportConfig {
|
|
200
|
+
port?: number;
|
|
201
|
+
maxRetries?: number;
|
|
202
|
+
}
|
|
203
|
+
declare class WsTransport implements IConfigurableTransport {
|
|
204
|
+
readonly name = "ws";
|
|
205
|
+
readonly defaultEnabled = true;
|
|
206
|
+
readonly optionsSchema: {
|
|
207
|
+
port: {
|
|
208
|
+
type: string;
|
|
209
|
+
description: string;
|
|
210
|
+
default: number;
|
|
211
|
+
};
|
|
212
|
+
maxRetries: {
|
|
213
|
+
type: string;
|
|
214
|
+
description: string;
|
|
215
|
+
default: number;
|
|
216
|
+
};
|
|
217
|
+
};
|
|
218
|
+
private session;
|
|
219
|
+
private stopFn;
|
|
220
|
+
private readonly port;
|
|
221
|
+
private readonly maxRetries;
|
|
222
|
+
constructor(config?: IWsTransportConfig);
|
|
223
|
+
attach(session: ISession): void;
|
|
224
|
+
start(): Promise<void>;
|
|
225
|
+
stop(): Promise<void>;
|
|
226
|
+
validateOptions(options: Record<string, TUniversalValue>): boolean;
|
|
227
|
+
private bindWithRetry;
|
|
228
|
+
private tryBind;
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
export { type IWsHandlerOptions, type IWsTransportConfig, type IWsTransportOptions, type TClientMessage, type TServerMessage, WsTransport, createWsHandler, createWsTransport };
|
package/dist/node/index.js
CHANGED
|
@@ -131,6 +131,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
131
131
|
const onError = (error) => send({ type: "error", message: error.message });
|
|
132
132
|
const onBackgroundTaskEvent = (event) => send({ type: "background_task_event", event });
|
|
133
133
|
const onBackgroundJobGroupEvent = (event) => send({ type: "background_job_group_event", event });
|
|
134
|
+
const onExecutionWorkspace = (event) => send({ type: "execution_workspace_event", snapshot: event.snapshot });
|
|
134
135
|
session.on("user_message", onUserMessage);
|
|
135
136
|
session.on("text_delta", onTextDelta);
|
|
136
137
|
session.on("tool_start", onToolStart);
|
|
@@ -141,6 +142,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
141
142
|
session.on("error", onError);
|
|
142
143
|
session.on("background_task_event", onBackgroundTaskEvent);
|
|
143
144
|
session.on("background_job_group_event", onBackgroundJobGroupEvent);
|
|
145
|
+
session.on("execution_workspace_event", onExecutionWorkspace);
|
|
144
146
|
return () => {
|
|
145
147
|
session.off("user_message", onUserMessage);
|
|
146
148
|
session.off("text_delta", onTextDelta);
|
|
@@ -152,6 +154,7 @@ function subscribeSessionEvents(session, send) {
|
|
|
152
154
|
session.off("error", onError);
|
|
153
155
|
session.off("background_task_event", onBackgroundTaskEvent);
|
|
154
156
|
session.off("background_job_group_event", onBackgroundJobGroupEvent);
|
|
157
|
+
session.off("execution_workspace_event", onExecutionWorkspace);
|
|
155
158
|
};
|
|
156
159
|
}
|
|
157
160
|
function createWsMessageHandler(session, send) {
|
|
@@ -195,7 +198,7 @@ function isSessionControlMessage(msg) {
|
|
|
195
198
|
return msg.type === "submit" || msg.type === "command" || msg.type === "abort" || msg.type === "cancel-queue";
|
|
196
199
|
}
|
|
197
200
|
function isSessionQueryMessage(msg) {
|
|
198
|
-
return msg.type === "get-messages" || msg.type === "get-context" || msg.type === "get-executing" || msg.type === "get-pending";
|
|
201
|
+
return msg.type === "get-messages" || msg.type === "get-context" || msg.type === "get-executing" || msg.type === "get-pending" || msg.type === "get-execution-workspace";
|
|
199
202
|
}
|
|
200
203
|
function isBackgroundQueryMessage(msg) {
|
|
201
204
|
return msg.type === "get-background-tasks" || msg.type === "get-background-task" || msg.type === "read-background-task-log" || msg.type === "get-background-job-groups" || msg.type === "get-background-job-group" || msg.type === "wait-background-job-group";
|
|
@@ -237,6 +240,11 @@ function handleSessionQueryMessage(session, send, msg) {
|
|
|
237
240
|
send({ type: "context", state: session.getContextState() });
|
|
238
241
|
} else if (msg.type === "get-executing") {
|
|
239
242
|
send({ type: "executing", executing: session.isExecuting() });
|
|
243
|
+
} else if (msg.type === "get-execution-workspace") {
|
|
244
|
+
send({
|
|
245
|
+
type: "execution_workspace_event",
|
|
246
|
+
snapshot: session.getExecutionWorkspaceSnapshot()
|
|
247
|
+
});
|
|
240
248
|
} else {
|
|
241
249
|
send({ type: "pending", pending: session.getPendingPrompt() });
|
|
242
250
|
}
|
|
@@ -265,7 +273,93 @@ function createWsTransport(options) {
|
|
|
265
273
|
}
|
|
266
274
|
};
|
|
267
275
|
}
|
|
276
|
+
|
|
277
|
+
// src/ws-transport-configurable.ts
|
|
278
|
+
import { createServer } from "http";
|
|
279
|
+
import { WebSocketServer, WebSocket } from "ws";
|
|
280
|
+
var DEFAULT_PORT = 7070;
|
|
281
|
+
var DEFAULT_MAX_RETRIES = 20;
|
|
282
|
+
var WsTransport = class {
|
|
283
|
+
name = "ws";
|
|
284
|
+
defaultEnabled = true;
|
|
285
|
+
optionsSchema = {
|
|
286
|
+
port: { type: "number", description: "WebSocket server port", default: DEFAULT_PORT },
|
|
287
|
+
maxRetries: {
|
|
288
|
+
type: "number",
|
|
289
|
+
description: "Port retry attempts when port is occupied",
|
|
290
|
+
default: DEFAULT_MAX_RETRIES
|
|
291
|
+
}
|
|
292
|
+
};
|
|
293
|
+
session = null;
|
|
294
|
+
stopFn = null;
|
|
295
|
+
port;
|
|
296
|
+
maxRetries;
|
|
297
|
+
constructor(config = {}) {
|
|
298
|
+
this.port = config.port ?? DEFAULT_PORT;
|
|
299
|
+
this.maxRetries = config.maxRetries ?? DEFAULT_MAX_RETRIES;
|
|
300
|
+
}
|
|
301
|
+
attach(session) {
|
|
302
|
+
this.session = session;
|
|
303
|
+
}
|
|
304
|
+
async start() {
|
|
305
|
+
if (!this.session) throw new Error("WsTransport: attach() must be called before start()");
|
|
306
|
+
const handle = await this.bindWithRetry(this.session, this.port, this.maxRetries);
|
|
307
|
+
this.stopFn = handle.stop;
|
|
308
|
+
}
|
|
309
|
+
async stop() {
|
|
310
|
+
await this.stopFn?.();
|
|
311
|
+
this.stopFn = null;
|
|
312
|
+
}
|
|
313
|
+
validateOptions(options) {
|
|
314
|
+
const { port, maxRetries } = options;
|
|
315
|
+
if (port !== void 0 && (typeof port !== "number" || port < 1 || port > 65535)) return false;
|
|
316
|
+
if (maxRetries !== void 0 && (typeof maxRetries !== "number" || maxRetries < 0))
|
|
317
|
+
return false;
|
|
318
|
+
return true;
|
|
319
|
+
}
|
|
320
|
+
bindWithRetry(session, port, retriesLeft) {
|
|
321
|
+
return this.tryBind(session, port).catch((err) => {
|
|
322
|
+
if (err.code === "EADDRINUSE" && retriesLeft > 0)
|
|
323
|
+
return this.bindWithRetry(session, port + 1, retriesLeft - 1);
|
|
324
|
+
throw err;
|
|
325
|
+
});
|
|
326
|
+
}
|
|
327
|
+
tryBind(session, port) {
|
|
328
|
+
return new Promise((resolve, reject) => {
|
|
329
|
+
const httpServer = createServer((_, res) => {
|
|
330
|
+
res.writeHead(400).end("WebSocket endpoint");
|
|
331
|
+
});
|
|
332
|
+
httpServer.on("error", (err) => {
|
|
333
|
+
httpServer.close();
|
|
334
|
+
reject(err);
|
|
335
|
+
});
|
|
336
|
+
httpServer.listen(port, "127.0.0.1", () => {
|
|
337
|
+
const wss = new WebSocketServer({ server: httpServer });
|
|
338
|
+
wss.on("connection", (ws) => {
|
|
339
|
+
const send = (message) => {
|
|
340
|
+
if (ws.readyState === WebSocket.OPEN) ws.send(JSON.stringify(message));
|
|
341
|
+
};
|
|
342
|
+
const { onMessage, cleanup } = createWsHandler({ session, send });
|
|
343
|
+
ws.on("message", (data) => onMessage(String(data)));
|
|
344
|
+
ws.on("close", cleanup);
|
|
345
|
+
ws.on("error", cleanup);
|
|
346
|
+
send({ type: "messages", messages: session.getMessages() });
|
|
347
|
+
send({
|
|
348
|
+
type: "execution_workspace_event",
|
|
349
|
+
snapshot: session.getExecutionWorkspaceSnapshot()
|
|
350
|
+
});
|
|
351
|
+
});
|
|
352
|
+
resolve({
|
|
353
|
+
stop: () => new Promise((res) => {
|
|
354
|
+
wss.close(() => httpServer.close(() => res()));
|
|
355
|
+
})
|
|
356
|
+
});
|
|
357
|
+
});
|
|
358
|
+
});
|
|
359
|
+
}
|
|
360
|
+
};
|
|
268
361
|
export {
|
|
362
|
+
WsTransport,
|
|
269
363
|
createWsHandler,
|
|
270
364
|
createWsTransport
|
|
271
365
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@robota-sdk/agent-transport-ws",
|
|
3
|
-
"version": "3.0.0-beta.
|
|
3
|
+
"version": "3.0.0-beta.63",
|
|
4
4
|
"description": "WebSocket transport adapter for exposing InteractiveSession over real-time connections",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/node/index.js",
|
|
@@ -30,9 +30,13 @@
|
|
|
30
30
|
"dist"
|
|
31
31
|
],
|
|
32
32
|
"dependencies": {
|
|
33
|
-
"
|
|
33
|
+
"ws": "^8.18.3",
|
|
34
|
+
"@robota-sdk/agent-core": "3.0.0-beta.63",
|
|
35
|
+
"@robota-sdk/agent-interface-transport": "3.0.0-beta.63",
|
|
36
|
+
"@robota-sdk/agent-sdk": "3.0.0-beta.63"
|
|
34
37
|
},
|
|
35
38
|
"devDependencies": {
|
|
39
|
+
"@types/ws": "^8.5.10",
|
|
36
40
|
"rimraf": "^5.0.5",
|
|
37
41
|
"tsup": "^8.0.1",
|
|
38
42
|
"typescript": "^5.3.3",
|