@agentxjs/node-platform 2.0.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/README.md +134 -0
- package/dist/WebSocketConnection-BUL85bFC.d.ts +66 -0
- package/dist/WebSocketFactory-SDWPRZVB.js +8 -0
- package/dist/WebSocketFactory-SDWPRZVB.js.map +1 -0
- package/dist/chunk-BBZV6B5R.js +264 -0
- package/dist/chunk-BBZV6B5R.js.map +1 -0
- package/dist/chunk-DGUM43GV.js +11 -0
- package/dist/chunk-DGUM43GV.js.map +1 -0
- package/dist/chunk-PK2K7CCJ.js +213 -0
- package/dist/chunk-PK2K7CCJ.js.map +1 -0
- package/dist/chunk-TXESAX3X.js +361 -0
- package/dist/chunk-TXESAX3X.js.map +1 -0
- package/dist/chunk-V664KD3R.js +14 -0
- package/dist/chunk-V664KD3R.js.map +1 -0
- package/dist/index.d.ts +140 -0
- package/dist/index.js +223 -0
- package/dist/index.js.map +1 -0
- package/dist/mq/index.d.ts +63 -0
- package/dist/mq/index.js +10 -0
- package/dist/mq/index.js.map +1 -0
- package/dist/network/index.d.ts +17 -0
- package/dist/network/index.js +14 -0
- package/dist/network/index.js.map +1 -0
- package/dist/persistence/index.d.ts +175 -0
- package/dist/persistence/index.js +18 -0
- package/dist/persistence/index.js.map +1 -0
- package/package.json +50 -0
- package/src/bash/NodeBashProvider.ts +54 -0
- package/src/index.ts +151 -0
- package/src/logger/FileLoggerFactory.ts +175 -0
- package/src/logger/index.ts +5 -0
- package/src/mq/OffsetGenerator.ts +48 -0
- package/src/mq/SqliteMessageQueue.ts +240 -0
- package/src/mq/index.ts +30 -0
- package/src/network/WebSocketConnection.ts +206 -0
- package/src/network/WebSocketFactory.ts +17 -0
- package/src/network/WebSocketServer.ts +156 -0
- package/src/network/index.ts +32 -0
- package/src/persistence/Persistence.ts +53 -0
- package/src/persistence/StorageContainerRepository.ts +58 -0
- package/src/persistence/StorageImageRepository.ts +153 -0
- package/src/persistence/StorageSessionRepository.ts +171 -0
- package/src/persistence/index.ts +38 -0
- package/src/persistence/memory.ts +27 -0
- package/src/persistence/sqlite.ts +111 -0
- package/src/persistence/types.ts +32 -0
package/README.md
ADDED
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# @agentxjs/node-platform
|
|
2
|
+
|
|
3
|
+
Node.js runtime platform for AgentX. Provides concrete implementations of persistence (SQLite), bash execution, networking (WebSocket), message queue, and logging.
|
|
4
|
+
|
|
5
|
+
## Overview
|
|
6
|
+
|
|
7
|
+
`@agentxjs/node-platform` assembles platform-specific components into an `AgentXPlatform` instance that the AgentX runtime requires. It handles storage, shell execution, and event infrastructure -- the driver (LLM) is injected separately.
|
|
8
|
+
|
|
9
|
+
## Quick Start
|
|
10
|
+
|
|
11
|
+
```typescript
|
|
12
|
+
import { createNodePlatform } from "@agentxjs/node-platform";
|
|
13
|
+
|
|
14
|
+
const platform = await createNodePlatform({
|
|
15
|
+
dataPath: "./data",
|
|
16
|
+
});
|
|
17
|
+
|
|
18
|
+
// platform.containerRepository -- SQLite container storage
|
|
19
|
+
// platform.imageRepository -- SQLite image storage
|
|
20
|
+
// platform.sessionRepository -- SQLite session + message storage
|
|
21
|
+
// platform.eventBus -- In-memory EventBus
|
|
22
|
+
// platform.bashProvider -- Shell execution via execa
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
### Deferred Initialization
|
|
26
|
+
|
|
27
|
+
Use `nodePlatform()` for lazy initialization (e.g., when passing to `createServer`):
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
import { nodePlatform } from "@agentxjs/node-platform";
|
|
31
|
+
import { createServer } from "@agentxjs/server";
|
|
32
|
+
|
|
33
|
+
const server = await createServer({
|
|
34
|
+
platform: nodePlatform({ dataPath: "./data" }), // resolved lazily
|
|
35
|
+
createDriver: myCreateDriver,
|
|
36
|
+
});
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## API Reference
|
|
40
|
+
|
|
41
|
+
### `createNodePlatform(options?): Promise<AgentXPlatform>`
|
|
42
|
+
|
|
43
|
+
Immediately creates and returns a fully initialized platform.
|
|
44
|
+
|
|
45
|
+
### `nodePlatform(options?): DeferredPlatformConfig`
|
|
46
|
+
|
|
47
|
+
Returns a deferred config. Call `.resolve()` to initialize.
|
|
48
|
+
|
|
49
|
+
### `isDeferredPlatform(value): value is DeferredPlatformConfig`
|
|
50
|
+
|
|
51
|
+
Type guard for deferred platform configs.
|
|
52
|
+
|
|
53
|
+
### Returned `AgentXPlatform`
|
|
54
|
+
|
|
55
|
+
| Property | Type | Description |
|
|
56
|
+
| --------------------- | --------------------- | ------------------------------- |
|
|
57
|
+
| `containerRepository` | `ContainerRepository` | Container CRUD (SQLite) |
|
|
58
|
+
| `imageRepository` | `ImageRepository` | Image CRUD (SQLite) |
|
|
59
|
+
| `sessionRepository` | `SessionRepository` | Session + message CRUD (SQLite) |
|
|
60
|
+
| `eventBus` | `EventBus` | In-memory pub/sub |
|
|
61
|
+
| `bashProvider` | `BashProvider` | Shell execution via execa |
|
|
62
|
+
|
|
63
|
+
### Additional Exports
|
|
64
|
+
|
|
65
|
+
```typescript
|
|
66
|
+
// Persistence
|
|
67
|
+
import { createPersistence, sqliteDriver, memoryDriver } from "@agentxjs/node-platform/persistence";
|
|
68
|
+
|
|
69
|
+
// Network
|
|
70
|
+
import { WebSocketServer, WebSocketConnection } from "@agentxjs/node-platform/network";
|
|
71
|
+
|
|
72
|
+
// Message Queue
|
|
73
|
+
import { SqliteMessageQueue, OffsetGenerator } from "@agentxjs/node-platform/mq";
|
|
74
|
+
|
|
75
|
+
// Bash
|
|
76
|
+
import { NodeBashProvider } from "@agentxjs/node-platform";
|
|
77
|
+
|
|
78
|
+
// Logger
|
|
79
|
+
import { FileLoggerFactory } from "@agentxjs/node-platform";
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Configuration
|
|
83
|
+
|
|
84
|
+
### NodePlatformOptions
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
interface NodePlatformOptions {
|
|
88
|
+
dataPath?: string; // default: "./data"
|
|
89
|
+
logDir?: string; // enables file logging if set
|
|
90
|
+
logLevel?: LogLevel; // default: "debug" (file) / "info" (console)
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
| Option | Type | Default | Description |
|
|
95
|
+
| ---------- | ---------- | ------------------------------------- | ------------------------------------------------------------ |
|
|
96
|
+
| `dataPath` | `string` | `"./data"` | Base directory for SQLite database (`<dataPath>/agentx.db`) |
|
|
97
|
+
| `logDir` | `string` | -- | Log file directory. Enables file logging when set. |
|
|
98
|
+
| `logLevel` | `LogLevel` | `"debug"` (file) / `"info"` (console) | `"debug"` \| `"info"` \| `"warn"` \| `"error"` \| `"silent"` |
|
|
99
|
+
|
|
100
|
+
### Persistence Drivers
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
// SQLite (production)
|
|
104
|
+
const persistence = await createPersistence(sqliteDriver({ path: "./data/agentx.db" }));
|
|
105
|
+
|
|
106
|
+
// In-memory (testing)
|
|
107
|
+
const persistence = await createPersistence(memoryDriver());
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### File Logging
|
|
111
|
+
|
|
112
|
+
```typescript
|
|
113
|
+
import { FileLoggerFactory } from "@agentxjs/node-platform";
|
|
114
|
+
import { setLoggerFactory } from "commonxjs/logger";
|
|
115
|
+
|
|
116
|
+
setLoggerFactory(
|
|
117
|
+
new FileLoggerFactory({
|
|
118
|
+
logDir: ".agentx/logs",
|
|
119
|
+
level: "info",
|
|
120
|
+
filename: "app.log", // default
|
|
121
|
+
})
|
|
122
|
+
);
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
When `logDir` is passed to `createNodePlatform`, file logging is configured automatically.
|
|
126
|
+
|
|
127
|
+
### Sub-path Exports
|
|
128
|
+
|
|
129
|
+
| Import path | Contents |
|
|
130
|
+
| ------------------------------------- | --------------------------------------------------- |
|
|
131
|
+
| `@agentxjs/node-platform` | Main entry (everything) |
|
|
132
|
+
| `@agentxjs/node-platform/persistence` | `createPersistence`, `sqliteDriver`, `memoryDriver` |
|
|
133
|
+
| `@agentxjs/node-platform/mq` | `SqliteMessageQueue`, `OffsetGenerator` |
|
|
134
|
+
| `@agentxjs/node-platform/network` | `WebSocketServer`, `WebSocketConnection` |
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { ChannelServer, ChannelServerOptions, MinimalHTTPServer, ChannelConnection, Unsubscribe, SendReliableOptions } from '@agentxjs/core/network';
|
|
2
|
+
import { WebSocket } from 'ws';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* WebSocket Server - Manages WebSocket connections
|
|
6
|
+
*
|
|
7
|
+
* Supports:
|
|
8
|
+
* - Standalone mode (listen on port)
|
|
9
|
+
* - Attached mode (attach to existing HTTP server)
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
* WebSocket Server
|
|
14
|
+
*/
|
|
15
|
+
declare class WebSocketServer implements ChannelServer {
|
|
16
|
+
private wss;
|
|
17
|
+
private connections;
|
|
18
|
+
private connectionHandlers;
|
|
19
|
+
private options;
|
|
20
|
+
private attachedToServer;
|
|
21
|
+
constructor(options?: ChannelServerOptions);
|
|
22
|
+
listen(port: number, host?: string): Promise<void>;
|
|
23
|
+
attach(server: MinimalHTTPServer, path?: string): void;
|
|
24
|
+
private handleConnection;
|
|
25
|
+
onConnection(handler: (connection: ChannelConnection) => void): Unsubscribe;
|
|
26
|
+
broadcast(message: string): void;
|
|
27
|
+
close(): Promise<void>;
|
|
28
|
+
dispose(): Promise<void>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* WebSocket Connection - Server-side connection wrapper
|
|
33
|
+
*
|
|
34
|
+
* Handles:
|
|
35
|
+
* - Heartbeat (ping/pong)
|
|
36
|
+
* - Reliable message delivery with ACK
|
|
37
|
+
* - Message routing
|
|
38
|
+
*/
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* WebSocket connection implementation
|
|
42
|
+
*/
|
|
43
|
+
declare class WebSocketConnection implements ChannelConnection {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
private ws;
|
|
46
|
+
private messageHandlers;
|
|
47
|
+
private closeHandlers;
|
|
48
|
+
private errorHandlers;
|
|
49
|
+
private heartbeatInterval?;
|
|
50
|
+
private isAlive;
|
|
51
|
+
private pendingAcks;
|
|
52
|
+
private msgIdCounter;
|
|
53
|
+
constructor(ws: WebSocket, options: ChannelServerOptions);
|
|
54
|
+
private setupHeartbeat;
|
|
55
|
+
private setupMessageHandler;
|
|
56
|
+
private setupCloseHandler;
|
|
57
|
+
private setupErrorHandler;
|
|
58
|
+
send(message: string): void;
|
|
59
|
+
sendReliable(message: string, options?: SendReliableOptions): void;
|
|
60
|
+
onMessage(handler: (message: string) => void): Unsubscribe;
|
|
61
|
+
onClose(handler: () => void): Unsubscribe;
|
|
62
|
+
onError(handler: (error: Error) => void): Unsubscribe;
|
|
63
|
+
close(): void;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export { WebSocketServer as W, WebSocketConnection as a };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
// src/network/WebSocketServer.ts
|
|
2
|
+
import { createLogger as createLogger2 } from "commonxjs/logger";
|
|
3
|
+
|
|
4
|
+
// src/network/WebSocketConnection.ts
|
|
5
|
+
import { isAckMessage } from "@agentxjs/core/network";
|
|
6
|
+
import { createLogger } from "commonxjs/logger";
|
|
7
|
+
var logger = createLogger("node-platform/WebSocketConnection");
|
|
8
|
+
var WebSocketConnection = class {
|
|
9
|
+
id;
|
|
10
|
+
ws;
|
|
11
|
+
messageHandlers = /* @__PURE__ */ new Set();
|
|
12
|
+
closeHandlers = /* @__PURE__ */ new Set();
|
|
13
|
+
errorHandlers = /* @__PURE__ */ new Set();
|
|
14
|
+
heartbeatInterval;
|
|
15
|
+
isAlive = true;
|
|
16
|
+
pendingAcks = /* @__PURE__ */ new Map();
|
|
17
|
+
msgIdCounter = 0;
|
|
18
|
+
constructor(ws, options) {
|
|
19
|
+
this.ws = ws;
|
|
20
|
+
this.id = `conn_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;
|
|
21
|
+
this.setupHeartbeat(options);
|
|
22
|
+
this.setupMessageHandler();
|
|
23
|
+
this.setupCloseHandler();
|
|
24
|
+
this.setupErrorHandler();
|
|
25
|
+
}
|
|
26
|
+
setupHeartbeat(options) {
|
|
27
|
+
if (options.heartbeat === false) return;
|
|
28
|
+
const interval = options.heartbeatInterval || 3e4;
|
|
29
|
+
this.ws.on("pong", () => {
|
|
30
|
+
this.isAlive = true;
|
|
31
|
+
logger.debug("Heartbeat pong received", { id: this.id });
|
|
32
|
+
});
|
|
33
|
+
this.heartbeatInterval = setInterval(() => {
|
|
34
|
+
if (!this.isAlive) {
|
|
35
|
+
logger.warn("Client heartbeat timeout, terminating connection", { id: this.id });
|
|
36
|
+
clearInterval(this.heartbeatInterval);
|
|
37
|
+
this.ws.terminate();
|
|
38
|
+
return;
|
|
39
|
+
}
|
|
40
|
+
this.isAlive = false;
|
|
41
|
+
this.ws.ping();
|
|
42
|
+
logger.debug("Heartbeat ping sent", { id: this.id });
|
|
43
|
+
}, interval);
|
|
44
|
+
}
|
|
45
|
+
setupMessageHandler() {
|
|
46
|
+
this.ws.on("message", (data) => {
|
|
47
|
+
const message = data.toString();
|
|
48
|
+
try {
|
|
49
|
+
const parsed = JSON.parse(message);
|
|
50
|
+
if (isAckMessage(parsed)) {
|
|
51
|
+
const pending = this.pendingAcks.get(parsed.__ack);
|
|
52
|
+
if (pending) {
|
|
53
|
+
clearTimeout(pending.timer);
|
|
54
|
+
pending.resolve();
|
|
55
|
+
this.pendingAcks.delete(parsed.__ack);
|
|
56
|
+
logger.debug("ACK received", { msgId: parsed.__ack, connectionId: this.id });
|
|
57
|
+
}
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
} catch {
|
|
61
|
+
}
|
|
62
|
+
for (const handler of this.messageHandlers) {
|
|
63
|
+
handler(message);
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
setupCloseHandler() {
|
|
68
|
+
this.ws.on("close", () => {
|
|
69
|
+
if (this.heartbeatInterval) {
|
|
70
|
+
clearInterval(this.heartbeatInterval);
|
|
71
|
+
}
|
|
72
|
+
for (const handler of this.closeHandlers) {
|
|
73
|
+
handler();
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
setupErrorHandler() {
|
|
78
|
+
this.ws.on("error", (err) => {
|
|
79
|
+
if (this.heartbeatInterval) {
|
|
80
|
+
clearInterval(this.heartbeatInterval);
|
|
81
|
+
}
|
|
82
|
+
for (const handler of this.errorHandlers) {
|
|
83
|
+
handler(err);
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
send(message) {
|
|
88
|
+
if (this.ws.readyState === 1) {
|
|
89
|
+
this.ws.send(message);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
sendReliable(message, options) {
|
|
93
|
+
if (this.ws.readyState !== 1) {
|
|
94
|
+
options?.onTimeout?.();
|
|
95
|
+
return;
|
|
96
|
+
}
|
|
97
|
+
if (!options?.onAck) {
|
|
98
|
+
this.send(message);
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
const msgId = `${this.id}_${++this.msgIdCounter}`;
|
|
102
|
+
const wrapped = {
|
|
103
|
+
__msgId: msgId,
|
|
104
|
+
__payload: message
|
|
105
|
+
};
|
|
106
|
+
const timeout = options.timeout ?? 5e3;
|
|
107
|
+
const timer = setTimeout(() => {
|
|
108
|
+
if (this.pendingAcks.has(msgId)) {
|
|
109
|
+
this.pendingAcks.delete(msgId);
|
|
110
|
+
logger.warn("ACK timeout", { msgId, connectionId: this.id, timeout });
|
|
111
|
+
options.onTimeout?.();
|
|
112
|
+
}
|
|
113
|
+
}, timeout);
|
|
114
|
+
this.pendingAcks.set(msgId, {
|
|
115
|
+
resolve: options.onAck,
|
|
116
|
+
timer
|
|
117
|
+
});
|
|
118
|
+
this.ws.send(JSON.stringify(wrapped));
|
|
119
|
+
logger.debug("Sent reliable message", { msgId, connectionId: this.id });
|
|
120
|
+
}
|
|
121
|
+
onMessage(handler) {
|
|
122
|
+
this.messageHandlers.add(handler);
|
|
123
|
+
return () => {
|
|
124
|
+
this.messageHandlers.delete(handler);
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
onClose(handler) {
|
|
128
|
+
this.closeHandlers.add(handler);
|
|
129
|
+
return () => {
|
|
130
|
+
this.closeHandlers.delete(handler);
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
onError(handler) {
|
|
134
|
+
this.errorHandlers.add(handler);
|
|
135
|
+
return () => {
|
|
136
|
+
this.errorHandlers.delete(handler);
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
close() {
|
|
140
|
+
if (this.heartbeatInterval) {
|
|
141
|
+
clearInterval(this.heartbeatInterval);
|
|
142
|
+
}
|
|
143
|
+
for (const pending of this.pendingAcks.values()) {
|
|
144
|
+
clearTimeout(pending.timer);
|
|
145
|
+
}
|
|
146
|
+
this.pendingAcks.clear();
|
|
147
|
+
this.ws.close();
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
|
|
151
|
+
// src/network/WebSocketServer.ts
|
|
152
|
+
var logger2 = createLogger2("node-platform/WebSocketServer");
|
|
153
|
+
var WebSocketServer = class {
|
|
154
|
+
wss = null;
|
|
155
|
+
connections = /* @__PURE__ */ new Set();
|
|
156
|
+
connectionHandlers = /* @__PURE__ */ new Set();
|
|
157
|
+
options;
|
|
158
|
+
attachedToServer = false;
|
|
159
|
+
constructor(options = {}) {
|
|
160
|
+
this.options = options;
|
|
161
|
+
}
|
|
162
|
+
async listen(port, host = "0.0.0.0") {
|
|
163
|
+
if (this.wss) {
|
|
164
|
+
throw new Error("Server already listening");
|
|
165
|
+
}
|
|
166
|
+
if (this.attachedToServer) {
|
|
167
|
+
throw new Error(
|
|
168
|
+
"Cannot listen when attached to existing server. The server should call listen() instead."
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
const { WebSocketServer: WSS } = await import("ws");
|
|
172
|
+
this.wss = new WSS({ port, host });
|
|
173
|
+
this.wss.on("connection", (ws) => {
|
|
174
|
+
this.handleConnection(ws);
|
|
175
|
+
});
|
|
176
|
+
logger2.info("WebSocket server listening", { port, host });
|
|
177
|
+
}
|
|
178
|
+
attach(server, path = "/ws") {
|
|
179
|
+
if (this.wss) {
|
|
180
|
+
throw new Error("Server already initialized");
|
|
181
|
+
}
|
|
182
|
+
import("ws").then(({ WebSocketServer: WSS }) => {
|
|
183
|
+
this.wss = new WSS({ noServer: true });
|
|
184
|
+
server.on("upgrade", (request, socket, head) => {
|
|
185
|
+
const url = new URL(
|
|
186
|
+
request.url || "",
|
|
187
|
+
`http://${request.headers.host}`
|
|
188
|
+
);
|
|
189
|
+
if (url.pathname === path) {
|
|
190
|
+
this.wss.handleUpgrade(request, socket, head, (ws) => {
|
|
191
|
+
this.wss.emit("connection", ws, request);
|
|
192
|
+
});
|
|
193
|
+
} else {
|
|
194
|
+
socket.destroy();
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
this.wss.on("connection", (ws) => {
|
|
198
|
+
this.handleConnection(ws);
|
|
199
|
+
});
|
|
200
|
+
this.attachedToServer = true;
|
|
201
|
+
logger2.info("WebSocket attached to existing HTTP server", { path });
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
handleConnection(ws) {
|
|
205
|
+
const connection = new WebSocketConnection(ws, this.options);
|
|
206
|
+
this.connections.add(connection);
|
|
207
|
+
logger2.info("Client connected", {
|
|
208
|
+
connectionId: connection.id,
|
|
209
|
+
totalConnections: this.connections.size
|
|
210
|
+
});
|
|
211
|
+
connection.onClose(() => {
|
|
212
|
+
this.connections.delete(connection);
|
|
213
|
+
logger2.info("Client disconnected", {
|
|
214
|
+
connectionId: connection.id,
|
|
215
|
+
totalConnections: this.connections.size
|
|
216
|
+
});
|
|
217
|
+
});
|
|
218
|
+
for (const handler of this.connectionHandlers) {
|
|
219
|
+
handler(connection);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
onConnection(handler) {
|
|
223
|
+
this.connectionHandlers.add(handler);
|
|
224
|
+
return () => {
|
|
225
|
+
this.connectionHandlers.delete(handler);
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
broadcast(message) {
|
|
229
|
+
for (const connection of this.connections) {
|
|
230
|
+
connection.send(message);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
async close() {
|
|
234
|
+
if (!this.wss) return;
|
|
235
|
+
for (const connection of this.connections) {
|
|
236
|
+
connection.close();
|
|
237
|
+
}
|
|
238
|
+
this.connections.clear();
|
|
239
|
+
if (!this.attachedToServer) {
|
|
240
|
+
await new Promise((resolve) => {
|
|
241
|
+
const timeout = setTimeout(() => {
|
|
242
|
+
logger2.warn("WebSocket server close timeout, forcing close");
|
|
243
|
+
resolve();
|
|
244
|
+
}, 1e3);
|
|
245
|
+
this.wss.close(() => {
|
|
246
|
+
clearTimeout(timeout);
|
|
247
|
+
resolve();
|
|
248
|
+
});
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
this.wss = null;
|
|
252
|
+
logger2.info("WebSocket server closed");
|
|
253
|
+
}
|
|
254
|
+
async dispose() {
|
|
255
|
+
await this.close();
|
|
256
|
+
this.connectionHandlers.clear();
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
export {
|
|
261
|
+
WebSocketConnection,
|
|
262
|
+
WebSocketServer
|
|
263
|
+
};
|
|
264
|
+
//# sourceMappingURL=chunk-BBZV6B5R.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/network/WebSocketServer.ts","../src/network/WebSocketConnection.ts"],"sourcesContent":["/**\n * WebSocket Server - Manages WebSocket connections\n *\n * Supports:\n * - Standalone mode (listen on port)\n * - Attached mode (attach to existing HTTP server)\n */\n\nimport type { WebSocket as WS, WebSocketServer as WSS } from \"ws\";\nimport type {\n ChannelServer,\n ChannelConnection,\n ChannelServerOptions,\n MinimalHTTPServer,\n Unsubscribe,\n} from \"@agentxjs/core/network\";\nimport { createLogger } from \"commonxjs/logger\";\nimport { WebSocketConnection } from \"./WebSocketConnection\";\n\nconst logger = createLogger(\"node-platform/WebSocketServer\");\n\n/**\n * WebSocket Server\n */\nexport class WebSocketServer implements ChannelServer {\n private wss: WSS | null = null;\n private connections = new Set<WebSocketConnection>();\n private connectionHandlers = new Set<(connection: ChannelConnection) => void>();\n private options: ChannelServerOptions;\n private attachedToServer = false;\n\n constructor(options: ChannelServerOptions = {}) {\n this.options = options;\n }\n\n async listen(port: number, host: string = \"0.0.0.0\"): Promise<void> {\n if (this.wss) {\n throw new Error(\"Server already listening\");\n }\n if (this.attachedToServer) {\n throw new Error(\n \"Cannot listen when attached to existing server. The server should call listen() instead.\"\n );\n }\n\n const { WebSocketServer: WSS } = await import(\"ws\");\n this.wss = new WSS({ port, host });\n\n this.wss.on(\"connection\", (ws: WS) => {\n this.handleConnection(ws);\n });\n\n logger.info(\"WebSocket server listening\", { port, host });\n }\n\n attach(server: MinimalHTTPServer, path: string = \"/ws\"): void {\n if (this.wss) {\n throw new Error(\"Server already initialized\");\n }\n\n import(\"ws\").then(({ WebSocketServer: WSS }) => {\n this.wss = new WSS({ noServer: true });\n\n // Handle WebSocket upgrade on the HTTP server\n server.on(\"upgrade\", (request, socket, head) => {\n const url = new URL(\n (request as { url?: string }).url || \"\",\n `http://${(request as { headers: { host?: string } }).headers.host}`\n );\n if (url.pathname === path) {\n this.wss!.handleUpgrade(request as never, socket as never, head as never, (ws: WS) => {\n this.wss!.emit(\"connection\", ws, request);\n });\n } else {\n (socket as { destroy: () => void }).destroy();\n }\n });\n\n this.wss.on(\"connection\", (ws: WS) => {\n this.handleConnection(ws);\n });\n\n this.attachedToServer = true;\n logger.info(\"WebSocket attached to existing HTTP server\", { path });\n });\n }\n\n private handleConnection(ws: WS): void {\n const connection = new WebSocketConnection(ws, this.options);\n this.connections.add(connection);\n\n logger.info(\"Client connected\", {\n connectionId: connection.id,\n totalConnections: this.connections.size,\n });\n\n connection.onClose(() => {\n this.connections.delete(connection);\n\n logger.info(\"Client disconnected\", {\n connectionId: connection.id,\n totalConnections: this.connections.size,\n });\n });\n\n // Notify handlers\n for (const handler of this.connectionHandlers) {\n handler(connection);\n }\n }\n\n onConnection(handler: (connection: ChannelConnection) => void): Unsubscribe {\n this.connectionHandlers.add(handler);\n return () => {\n this.connectionHandlers.delete(handler);\n };\n }\n\n broadcast(message: string): void {\n for (const connection of this.connections) {\n connection.send(message);\n }\n }\n\n async close(): Promise<void> {\n if (!this.wss) return;\n\n for (const connection of this.connections) {\n connection.close();\n }\n this.connections.clear();\n\n // Don't close the server if attached to existing HTTP server\n if (!this.attachedToServer) {\n await new Promise<void>((resolve) => {\n // Add timeout to prevent hanging\n const timeout = setTimeout(() => {\n logger.warn(\"WebSocket server close timeout, forcing close\");\n resolve();\n }, 1000);\n\n this.wss!.close(() => {\n clearTimeout(timeout);\n resolve();\n });\n });\n }\n this.wss = null;\n logger.info(\"WebSocket server closed\");\n }\n\n async dispose(): Promise<void> {\n await this.close();\n this.connectionHandlers.clear();\n }\n}\n","/**\n * WebSocket Connection - Server-side connection wrapper\n *\n * Handles:\n * - Heartbeat (ping/pong)\n * - Reliable message delivery with ACK\n * - Message routing\n */\n\nimport type { WebSocket as WS } from \"ws\";\nimport type {\n ChannelConnection,\n ChannelServerOptions,\n Unsubscribe,\n SendReliableOptions,\n} from \"@agentxjs/core/network\";\nimport { isAckMessage, type ReliableWrapper } from \"@agentxjs/core/network\";\nimport { createLogger } from \"commonxjs/logger\";\n\nconst logger = createLogger(\"node-platform/WebSocketConnection\");\n\n/**\n * WebSocket connection implementation\n */\nexport class WebSocketConnection implements ChannelConnection {\n public readonly id: string;\n private ws: WS;\n private messageHandlers = new Set<(message: string) => void>();\n private closeHandlers = new Set<() => void>();\n private errorHandlers = new Set<(error: Error) => void>();\n private heartbeatInterval?: ReturnType<typeof setInterval>;\n private isAlive = true;\n private pendingAcks = new Map<\n string,\n { resolve: () => void; timer: ReturnType<typeof setTimeout> }\n >();\n private msgIdCounter = 0;\n\n constructor(ws: WS, options: ChannelServerOptions) {\n this.ws = ws;\n this.id = `conn_${Date.now()}_${Math.random().toString(36).substring(2, 8)}`;\n\n this.setupHeartbeat(options);\n this.setupMessageHandler();\n this.setupCloseHandler();\n this.setupErrorHandler();\n }\n\n private setupHeartbeat(options: ChannelServerOptions): void {\n if (options.heartbeat === false) return;\n\n const interval = options.heartbeatInterval || 30000;\n\n this.ws.on(\"pong\", () => {\n this.isAlive = true;\n logger.debug(\"Heartbeat pong received\", { id: this.id });\n });\n\n this.heartbeatInterval = setInterval(() => {\n if (!this.isAlive) {\n logger.warn(\"Client heartbeat timeout, terminating connection\", { id: this.id });\n clearInterval(this.heartbeatInterval);\n this.ws.terminate();\n return;\n }\n this.isAlive = false;\n this.ws.ping();\n logger.debug(\"Heartbeat ping sent\", { id: this.id });\n }, interval);\n }\n\n private setupMessageHandler(): void {\n this.ws.on(\"message\", (data: Buffer) => {\n const message = data.toString();\n\n // Try to parse as JSON to check for ACK messages\n try {\n const parsed = JSON.parse(message);\n\n // Handle ACK response from client\n if (isAckMessage(parsed)) {\n const pending = this.pendingAcks.get(parsed.__ack);\n if (pending) {\n clearTimeout(pending.timer);\n pending.resolve();\n this.pendingAcks.delete(parsed.__ack);\n logger.debug(\"ACK received\", { msgId: parsed.__ack, connectionId: this.id });\n }\n return; // Don't pass ACK messages to application layer\n }\n } catch {\n // Not JSON, pass through as normal message\n }\n\n // Pass message to handlers\n for (const handler of this.messageHandlers) {\n handler(message);\n }\n });\n }\n\n private setupCloseHandler(): void {\n this.ws.on(\"close\", () => {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n for (const handler of this.closeHandlers) {\n handler();\n }\n });\n }\n\n private setupErrorHandler(): void {\n this.ws.on(\"error\", (err: Error) => {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n for (const handler of this.errorHandlers) {\n handler(err);\n }\n });\n }\n\n send(message: string): void {\n if (this.ws.readyState === 1) {\n // WebSocket.OPEN\n this.ws.send(message);\n }\n }\n\n sendReliable(message: string, options?: SendReliableOptions): void {\n if (this.ws.readyState !== 1) {\n // WebSocket not open, trigger timeout immediately if callback provided\n options?.onTimeout?.();\n return;\n }\n\n // If no ACK callback needed, just send normally\n if (!options?.onAck) {\n this.send(message);\n return;\n }\n\n // Generate unique message ID\n const msgId = `${this.id}_${++this.msgIdCounter}`;\n\n // Wrap message with msgId\n const wrapped: ReliableWrapper = {\n __msgId: msgId,\n __payload: message,\n };\n\n // Set up timeout\n const timeout = options.timeout ?? 5000;\n const timer = setTimeout(() => {\n if (this.pendingAcks.has(msgId)) {\n this.pendingAcks.delete(msgId);\n logger.warn(\"ACK timeout\", { msgId, connectionId: this.id, timeout });\n options.onTimeout?.();\n }\n }, timeout);\n\n // Store pending ACK\n this.pendingAcks.set(msgId, {\n resolve: options.onAck,\n timer,\n });\n\n // Send wrapped message\n this.ws.send(JSON.stringify(wrapped));\n logger.debug(\"Sent reliable message\", { msgId, connectionId: this.id });\n }\n\n onMessage(handler: (message: string) => void): Unsubscribe {\n this.messageHandlers.add(handler);\n return () => {\n this.messageHandlers.delete(handler);\n };\n }\n\n onClose(handler: () => void): Unsubscribe {\n this.closeHandlers.add(handler);\n return () => {\n this.closeHandlers.delete(handler);\n };\n }\n\n onError(handler: (error: Error) => void): Unsubscribe {\n this.errorHandlers.add(handler);\n return () => {\n this.errorHandlers.delete(handler);\n };\n }\n\n close(): void {\n if (this.heartbeatInterval) {\n clearInterval(this.heartbeatInterval);\n }\n // Clean up pending ACKs\n for (const pending of this.pendingAcks.values()) {\n clearTimeout(pending.timer);\n }\n this.pendingAcks.clear();\n this.ws.close();\n }\n}\n"],"mappings":"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","names":["createLogger","logger","createLogger"]}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
export {
|
|
9
|
+
__require
|
|
10
|
+
};
|
|
11
|
+
//# sourceMappingURL=chunk-DGUM43GV.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":[],"sourcesContent":[],"mappings":"","names":[]}
|