@clawswarm/bridge 0.1.0-alpha
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 +68 -0
- package/dist/bridge.d.ts +105 -0
- package/dist/bridge.d.ts.map +1 -0
- package/dist/bridge.js +297 -0
- package/dist/bridge.js.map +1 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +18 -0
- package/dist/index.js.map +1 -0
- package/dist/router.d.ts +88 -0
- package/dist/router.d.ts.map +1 -0
- package/dist/router.js +122 -0
- package/dist/router.js.map +1 -0
- package/dist/types.d.ts +93 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +7 -0
- package/dist/types.js.map +1 -0
- package/package.json +64 -0
- package/src/bridge.ts +330 -0
- package/src/index.ts +26 -0
- package/src/router.ts +178 -0
- package/src/types.ts +129 -0
- package/tsconfig.json +18 -0
- package/tsconfig.tsbuildinfo +1 -0
package/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# @clawswarm/bridge
|
|
2
|
+
|
|
3
|
+
WebSocket bridge server for ClawSwarm — enables real-time communication between agents, UI clients, and external services.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- 🔌 **WebSocket server** — persistent connections for agents and dashboard clients
|
|
8
|
+
- 🏢 **Org-scoped routing** — tasks and events are isolated per organization
|
|
9
|
+
- 📡 **Real-time events** — task updates, agent status, and goal progress streamed live
|
|
10
|
+
- 🔐 **Token-based auth** — per-connection authentication via Bearer tokens
|
|
11
|
+
- 🔁 **Reconnect handling** — automatic ping/pong and stale connection cleanup
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @clawswarm/bridge
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Standalone Server
|
|
22
|
+
|
|
23
|
+
```typescript
|
|
24
|
+
import { BridgeServer } from '@clawswarm/bridge';
|
|
25
|
+
|
|
26
|
+
const bridge = new BridgeServer({ port: 8787, host: '0.0.0.0' });
|
|
27
|
+
await bridge.start();
|
|
28
|
+
|
|
29
|
+
bridge.on('client:connected', (client) => {
|
|
30
|
+
console.log('New client:', client.id, 'org:', client.orgId);
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
### With ClawSwarm Core
|
|
35
|
+
|
|
36
|
+
```typescript
|
|
37
|
+
import { ClawSwarm, Agent } from '@clawswarm/core';
|
|
38
|
+
import { BridgeServer, TaskRouter } from '@clawswarm/bridge';
|
|
39
|
+
|
|
40
|
+
const bridge = new BridgeServer({ port: 8787 });
|
|
41
|
+
await bridge.start();
|
|
42
|
+
|
|
43
|
+
const router = new TaskRouter(bridge);
|
|
44
|
+
|
|
45
|
+
const swarm = new ClawSwarm({
|
|
46
|
+
agents: [Agent.research({ model: 'claude-sonnet-4' })],
|
|
47
|
+
bridgeUrl: 'ws://localhost:8787',
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
// Forward swarm events to bridge clients
|
|
51
|
+
swarm.on('task:completed', (task) => {
|
|
52
|
+
router.broadcast(task.goalId, { type: 'task:completed', payload: task });
|
|
53
|
+
});
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Configuration
|
|
57
|
+
|
|
58
|
+
| Option | Type | Default | Description |
|
|
59
|
+
|--------|------|---------|-------------|
|
|
60
|
+
| `port` | `number` | `8787` | Port to listen on |
|
|
61
|
+
| `host` | `string` | `'0.0.0.0'` | Host to bind to |
|
|
62
|
+
| `maxConnections` | `number` | `1000` | Max concurrent WebSocket connections |
|
|
63
|
+
| `pingIntervalMs` | `number` | `30000` | Ping interval for keep-alive |
|
|
64
|
+
| `authTokens` | `string[]` | `[]` | Allowed auth tokens (empty = no auth) |
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT
|
package/dist/bridge.d.ts
ADDED
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* WebSocket bridge server for ClawSwarm.
|
|
3
|
+
*
|
|
4
|
+
* Provides real-time bidirectional communication between agents,
|
|
5
|
+
* dashboard clients, and external consumers. Handles org-scoped
|
|
6
|
+
* message routing, authentication, and connection lifecycle.
|
|
7
|
+
*
|
|
8
|
+
* @module @clawswarm/bridge/bridge
|
|
9
|
+
*/
|
|
10
|
+
import EventEmitter from 'eventemitter3';
|
|
11
|
+
import { BridgeClient, BridgeMessage, BridgeServerConfig, BridgeServerEvents } from './types.js';
|
|
12
|
+
declare const BridgeServer_base: new () => EventEmitter<BridgeServerEvents>;
|
|
13
|
+
/**
|
|
14
|
+
* The ClawSwarm bridge server.
|
|
15
|
+
*
|
|
16
|
+
* Manages WebSocket connections, authenticates clients, and routes
|
|
17
|
+
* messages between agents and dashboard consumers within org boundaries.
|
|
18
|
+
*
|
|
19
|
+
* @example
|
|
20
|
+
* ```typescript
|
|
21
|
+
* const bridge = new BridgeServer({ port: 8787 });
|
|
22
|
+
*
|
|
23
|
+
* bridge.on('client:connected', (client) => {
|
|
24
|
+
* console.log('Connected:', client.id, 'org:', client.orgId);
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* await bridge.start();
|
|
28
|
+
* console.log('Bridge listening on ws://localhost:8787');
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class BridgeServer extends BridgeServer_base {
|
|
32
|
+
private readonly config;
|
|
33
|
+
private wss;
|
|
34
|
+
private clients;
|
|
35
|
+
private pingTimer;
|
|
36
|
+
constructor(config?: BridgeServerConfig);
|
|
37
|
+
/**
|
|
38
|
+
* Start the WebSocket server.
|
|
39
|
+
* Returns a promise that resolves once the server is listening.
|
|
40
|
+
*/
|
|
41
|
+
start(): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Stop the WebSocket server and disconnect all clients.
|
|
44
|
+
*/
|
|
45
|
+
stop(): Promise<void>;
|
|
46
|
+
/**
|
|
47
|
+
* Send a message to a specific client by ID.
|
|
48
|
+
* Returns false if the client is not found or not connected.
|
|
49
|
+
*/
|
|
50
|
+
send(clientId: string, message: BridgeMessage): boolean;
|
|
51
|
+
/**
|
|
52
|
+
* Broadcast a message to all clients in an organization.
|
|
53
|
+
* Optionally filter by role.
|
|
54
|
+
*
|
|
55
|
+
* @param orgId - Organization to broadcast to ('*' for all orgs)
|
|
56
|
+
* @param message - Message to send
|
|
57
|
+
* @param roles - Optional role filter
|
|
58
|
+
* @returns Number of clients reached
|
|
59
|
+
*/
|
|
60
|
+
broadcast(orgId: string, message: BridgeMessage, roles?: BridgeClient['role'][]): number;
|
|
61
|
+
/**
|
|
62
|
+
* Get all connected clients (optionally filtered by org).
|
|
63
|
+
*/
|
|
64
|
+
getClients(orgId?: string): BridgeClient[];
|
|
65
|
+
/**
|
|
66
|
+
* Get server stats.
|
|
67
|
+
*/
|
|
68
|
+
stats(): {
|
|
69
|
+
connections: number;
|
|
70
|
+
orgs: number;
|
|
71
|
+
uptime: boolean;
|
|
72
|
+
};
|
|
73
|
+
/**
|
|
74
|
+
* Handle a new WebSocket connection.
|
|
75
|
+
* @internal
|
|
76
|
+
*/
|
|
77
|
+
private _onConnection;
|
|
78
|
+
/**
|
|
79
|
+
* Handle an incoming message from a client.
|
|
80
|
+
* @internal
|
|
81
|
+
*/
|
|
82
|
+
private _onMessage;
|
|
83
|
+
/**
|
|
84
|
+
* Handle an auth message from a client.
|
|
85
|
+
* @internal
|
|
86
|
+
*/
|
|
87
|
+
private _handleAuth;
|
|
88
|
+
/**
|
|
89
|
+
* Handle a client disconnection.
|
|
90
|
+
* @internal
|
|
91
|
+
*/
|
|
92
|
+
private _onClose;
|
|
93
|
+
/**
|
|
94
|
+
* Build an error message.
|
|
95
|
+
* @internal
|
|
96
|
+
*/
|
|
97
|
+
private _errorMessage;
|
|
98
|
+
/**
|
|
99
|
+
* Start the ping timer for keep-alive.
|
|
100
|
+
* @internal
|
|
101
|
+
*/
|
|
102
|
+
private _startPingTimer;
|
|
103
|
+
}
|
|
104
|
+
export {};
|
|
105
|
+
//# sourceMappingURL=bridge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.d.ts","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAIH,OAAO,YAAY,MAAM,eAAe,CAAC;AACzC,OAAO,EACL,YAAY,EACZ,aAAa,EACb,kBAAkB,EAClB,kBAAkB,EAEnB,MAAM,YAAY,CAAC;iCA6B+B,UAAU,YAAY,CAAC,kBAAkB,CAAC;AAlB7F;;;;;;;;;;;;;;;;;GAiBG;AACH,qBAAa,YAAa,SAAQ,iBAA4D;IAC5F,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA+B;IACtD,OAAO,CAAC,GAAG,CAAgC;IAC3C,OAAO,CAAC,OAAO,CAAuE;IACtF,OAAO,CAAC,SAAS,CAA+C;gBAEpD,MAAM,GAAE,kBAAuB;IAc3C;;;OAGG;IACG,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAwB5B;;OAEG;IACG,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;IAsB3B;;;OAGG;IACH,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,OAAO;IAavD;;;;;;;;OAQG;IACH,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,YAAY,CAAC,MAAM,CAAC,EAAE,GAC7B,MAAM;IAcT;;OAEG;IACH,UAAU,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,YAAY,EAAE;IAK1C;;OAEG;IACH,KAAK,IAAI;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,OAAO,CAAA;KAAE;IAW/D;;;OAGG;IACH,OAAO,CAAC,aAAa;IA4BrB;;;OAGG;IACH,OAAO,CAAC,UAAU;IAiClB;;;OAGG;IACH,OAAO,CAAC,WAAW;IA8BnB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAKhB;;;OAGG;IACH,OAAO,CAAC,aAAa;IAQrB;;;OAGG;IACH,OAAO,CAAC,eAAe;CAcxB"}
|
package/dist/bridge.js
ADDED
|
@@ -0,0 +1,297 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* WebSocket bridge server for ClawSwarm.
|
|
4
|
+
*
|
|
5
|
+
* Provides real-time bidirectional communication between agents,
|
|
6
|
+
* dashboard clients, and external consumers. Handles org-scoped
|
|
7
|
+
* message routing, authentication, and connection lifecycle.
|
|
8
|
+
*
|
|
9
|
+
* @module @clawswarm/bridge/bridge
|
|
10
|
+
*/
|
|
11
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
12
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
13
|
+
};
|
|
14
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
15
|
+
exports.BridgeServer = void 0;
|
|
16
|
+
const ws_1 = require("ws");
|
|
17
|
+
const uuid_1 = require("uuid");
|
|
18
|
+
const eventemitter3_1 = __importDefault(require("eventemitter3"));
|
|
19
|
+
// ─── Defaults ─────────────────────────────────────────────────────────────────
|
|
20
|
+
const DEFAULT_PORT = 8787;
|
|
21
|
+
const DEFAULT_HOST = '0.0.0.0';
|
|
22
|
+
const DEFAULT_MAX_CONNECTIONS = 1000;
|
|
23
|
+
const DEFAULT_PING_INTERVAL_MS = 30_000;
|
|
24
|
+
// ─── BridgeServer ─────────────────────────────────────────────────────────────
|
|
25
|
+
/**
|
|
26
|
+
* The ClawSwarm bridge server.
|
|
27
|
+
*
|
|
28
|
+
* Manages WebSocket connections, authenticates clients, and routes
|
|
29
|
+
* messages between agents and dashboard consumers within org boundaries.
|
|
30
|
+
*
|
|
31
|
+
* @example
|
|
32
|
+
* ```typescript
|
|
33
|
+
* const bridge = new BridgeServer({ port: 8787 });
|
|
34
|
+
*
|
|
35
|
+
* bridge.on('client:connected', (client) => {
|
|
36
|
+
* console.log('Connected:', client.id, 'org:', client.orgId);
|
|
37
|
+
* });
|
|
38
|
+
*
|
|
39
|
+
* await bridge.start();
|
|
40
|
+
* console.log('Bridge listening on ws://localhost:8787');
|
|
41
|
+
* ```
|
|
42
|
+
*/
|
|
43
|
+
class BridgeServer extends eventemitter3_1.default {
|
|
44
|
+
config;
|
|
45
|
+
wss = null;
|
|
46
|
+
clients = new Map();
|
|
47
|
+
pingTimer = null;
|
|
48
|
+
constructor(config = {}) {
|
|
49
|
+
super();
|
|
50
|
+
this.config = {
|
|
51
|
+
port: config.port ?? DEFAULT_PORT,
|
|
52
|
+
host: config.host ?? DEFAULT_HOST,
|
|
53
|
+
maxConnections: config.maxConnections ?? DEFAULT_MAX_CONNECTIONS,
|
|
54
|
+
pingIntervalMs: config.pingIntervalMs ?? DEFAULT_PING_INTERVAL_MS,
|
|
55
|
+
authTokens: config.authTokens ?? [],
|
|
56
|
+
path: config.path ?? '/',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// ─── Public API ───────────────────────────────────────────────────────────
|
|
60
|
+
/**
|
|
61
|
+
* Start the WebSocket server.
|
|
62
|
+
* Returns a promise that resolves once the server is listening.
|
|
63
|
+
*/
|
|
64
|
+
async start() {
|
|
65
|
+
if (this.wss)
|
|
66
|
+
throw new Error('BridgeServer is already running');
|
|
67
|
+
return new Promise((resolve, reject) => {
|
|
68
|
+
this.wss = new ws_1.WebSocketServer({
|
|
69
|
+
port: this.config.port,
|
|
70
|
+
host: this.config.host,
|
|
71
|
+
path: this.config.path,
|
|
72
|
+
});
|
|
73
|
+
this.wss.on('connection', (socket, req) => this._onConnection(socket, req));
|
|
74
|
+
this.wss.on('error', (err) => {
|
|
75
|
+
this.emit('error', err);
|
|
76
|
+
reject(err);
|
|
77
|
+
});
|
|
78
|
+
this.wss.on('listening', () => {
|
|
79
|
+
this._startPingTimer();
|
|
80
|
+
this.emit('listening', this.config.port, this.config.host);
|
|
81
|
+
resolve();
|
|
82
|
+
});
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Stop the WebSocket server and disconnect all clients.
|
|
87
|
+
*/
|
|
88
|
+
async stop() {
|
|
89
|
+
if (!this.wss)
|
|
90
|
+
return;
|
|
91
|
+
if (this.pingTimer) {
|
|
92
|
+
clearInterval(this.pingTimer);
|
|
93
|
+
this.pingTimer = null;
|
|
94
|
+
}
|
|
95
|
+
// Close all client connections
|
|
96
|
+
for (const [id, { socket }] of this.clients) {
|
|
97
|
+
socket.close(1001, 'Server shutting down');
|
|
98
|
+
this.clients.delete(id);
|
|
99
|
+
}
|
|
100
|
+
return new Promise((resolve) => {
|
|
101
|
+
this.wss.close(() => {
|
|
102
|
+
this.wss = null;
|
|
103
|
+
resolve();
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Send a message to a specific client by ID.
|
|
109
|
+
* Returns false if the client is not found or not connected.
|
|
110
|
+
*/
|
|
111
|
+
send(clientId, message) {
|
|
112
|
+
const entry = this.clients.get(clientId);
|
|
113
|
+
if (!entry || entry.socket.readyState !== ws_1.WebSocket.OPEN)
|
|
114
|
+
return false;
|
|
115
|
+
try {
|
|
116
|
+
entry.socket.send(JSON.stringify(message));
|
|
117
|
+
this.emit('message:sent', clientId, message);
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
catch {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Broadcast a message to all clients in an organization.
|
|
126
|
+
* Optionally filter by role.
|
|
127
|
+
*
|
|
128
|
+
* @param orgId - Organization to broadcast to ('*' for all orgs)
|
|
129
|
+
* @param message - Message to send
|
|
130
|
+
* @param roles - Optional role filter
|
|
131
|
+
* @returns Number of clients reached
|
|
132
|
+
*/
|
|
133
|
+
broadcast(orgId, message, roles) {
|
|
134
|
+
let count = 0;
|
|
135
|
+
for (const [, { client, socket }] of this.clients) {
|
|
136
|
+
if (socket.readyState !== ws_1.WebSocket.OPEN)
|
|
137
|
+
continue;
|
|
138
|
+
if (orgId !== '*' && client.orgId !== orgId)
|
|
139
|
+
continue;
|
|
140
|
+
if (roles && !roles.includes(client.role))
|
|
141
|
+
continue;
|
|
142
|
+
if (!client.authenticated)
|
|
143
|
+
continue;
|
|
144
|
+
socket.send(JSON.stringify(message));
|
|
145
|
+
count++;
|
|
146
|
+
}
|
|
147
|
+
return count;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Get all connected clients (optionally filtered by org).
|
|
151
|
+
*/
|
|
152
|
+
getClients(orgId) {
|
|
153
|
+
const all = Array.from(this.clients.values()).map(e => e.client);
|
|
154
|
+
return orgId ? all.filter(c => c.orgId === orgId) : all;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get server stats.
|
|
158
|
+
*/
|
|
159
|
+
stats() {
|
|
160
|
+
const orgs = new Set(Array.from(this.clients.values()).map(e => e.client.orgId));
|
|
161
|
+
return {
|
|
162
|
+
connections: this.clients.size,
|
|
163
|
+
orgs: orgs.size,
|
|
164
|
+
uptime: this.wss !== null,
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
// ─── Private ──────────────────────────────────────────────────────────────
|
|
168
|
+
/**
|
|
169
|
+
* Handle a new WebSocket connection.
|
|
170
|
+
* @internal
|
|
171
|
+
*/
|
|
172
|
+
_onConnection(socket, _req) {
|
|
173
|
+
if (this.clients.size >= this.config.maxConnections) {
|
|
174
|
+
socket.close(1013, 'Server at capacity');
|
|
175
|
+
return;
|
|
176
|
+
}
|
|
177
|
+
const clientId = (0, uuid_1.v4)();
|
|
178
|
+
const client = {
|
|
179
|
+
id: clientId,
|
|
180
|
+
orgId: 'unknown',
|
|
181
|
+
role: 'external',
|
|
182
|
+
connectedAt: new Date().toISOString(),
|
|
183
|
+
authenticated: this.config.authTokens.length === 0, // no auth if no tokens configured
|
|
184
|
+
metadata: {},
|
|
185
|
+
};
|
|
186
|
+
this.clients.set(clientId, { client, socket });
|
|
187
|
+
this.emit('client:connected', client);
|
|
188
|
+
socket.on('message', (data) => this._onMessage(clientId, data));
|
|
189
|
+
socket.on('close', (code, reason) => this._onClose(clientId, code, reason.toString()));
|
|
190
|
+
socket.on('error', (err) => this.emit('error', err));
|
|
191
|
+
socket.on('pong', () => {
|
|
192
|
+
const entry = this.clients.get(clientId);
|
|
193
|
+
if (entry)
|
|
194
|
+
entry.client.lastPingAt = new Date().toISOString();
|
|
195
|
+
});
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Handle an incoming message from a client.
|
|
199
|
+
* @internal
|
|
200
|
+
*/
|
|
201
|
+
_onMessage(clientId, data) {
|
|
202
|
+
const entry = this.clients.get(clientId);
|
|
203
|
+
if (!entry)
|
|
204
|
+
return;
|
|
205
|
+
let message;
|
|
206
|
+
try {
|
|
207
|
+
message = JSON.parse(data.toString());
|
|
208
|
+
}
|
|
209
|
+
catch {
|
|
210
|
+
this.send(clientId, this._errorMessage('PARSE_ERROR', 'Invalid JSON'));
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Handle auth message
|
|
214
|
+
if (message.type === 'auth') {
|
|
215
|
+
this._handleAuth(clientId, message.payload);
|
|
216
|
+
return;
|
|
217
|
+
}
|
|
218
|
+
// Reject unauthenticated messages
|
|
219
|
+
if (!entry.client.authenticated) {
|
|
220
|
+
this.send(clientId, this._errorMessage('UNAUTHORIZED', 'Authenticate first'));
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
// Handle ping
|
|
224
|
+
if (message.type === 'ping') {
|
|
225
|
+
this.send(clientId, { type: 'pong', ts: new Date().toISOString(), payload: {} });
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
this.emit('message:received', entry.client, message);
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Handle an auth message from a client.
|
|
232
|
+
* @internal
|
|
233
|
+
*/
|
|
234
|
+
_handleAuth(clientId, payload) {
|
|
235
|
+
const entry = this.clients.get(clientId);
|
|
236
|
+
if (!entry)
|
|
237
|
+
return;
|
|
238
|
+
const { token, orgId, role, metadata } = payload;
|
|
239
|
+
// Validate token if auth is configured
|
|
240
|
+
if (this.config.authTokens.length > 0 &&
|
|
241
|
+
!this.config.authTokens.includes(token)) {
|
|
242
|
+
this.send(clientId, this._errorMessage('INVALID_TOKEN', 'Invalid auth token'));
|
|
243
|
+
entry.socket.close(1008, 'Unauthorized');
|
|
244
|
+
return;
|
|
245
|
+
}
|
|
246
|
+
entry.client.authenticated = true;
|
|
247
|
+
entry.client.orgId = orgId;
|
|
248
|
+
entry.client.role = role;
|
|
249
|
+
entry.client.metadata = metadata ?? {};
|
|
250
|
+
this.send(clientId, {
|
|
251
|
+
type: 'pong', // using pong as ack
|
|
252
|
+
ts: new Date().toISOString(),
|
|
253
|
+
payload: { authenticated: true, clientId },
|
|
254
|
+
});
|
|
255
|
+
this.emit('client:authenticated', entry.client);
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Handle a client disconnection.
|
|
259
|
+
* @internal
|
|
260
|
+
*/
|
|
261
|
+
_onClose(clientId, code, reason) {
|
|
262
|
+
this.clients.delete(clientId);
|
|
263
|
+
this.emit('client:disconnected', clientId, reason || String(code));
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Build an error message.
|
|
267
|
+
* @internal
|
|
268
|
+
*/
|
|
269
|
+
_errorMessage(code, message) {
|
|
270
|
+
return {
|
|
271
|
+
type: 'error',
|
|
272
|
+
ts: new Date().toISOString(),
|
|
273
|
+
payload: { code, message },
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Start the ping timer for keep-alive.
|
|
278
|
+
* @internal
|
|
279
|
+
*/
|
|
280
|
+
_startPingTimer() {
|
|
281
|
+
this.pingTimer = setInterval(() => {
|
|
282
|
+
const now = new Date().toISOString();
|
|
283
|
+
for (const [id, { socket, client }] of this.clients) {
|
|
284
|
+
if (socket.readyState === ws_1.WebSocket.OPEN) {
|
|
285
|
+
socket.ping();
|
|
286
|
+
client.lastPingAt = now;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Clean up stale connections
|
|
290
|
+
this.clients.delete(id);
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
}, this.config.pingIntervalMs);
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
exports.BridgeServer = BridgeServer;
|
|
297
|
+
//# sourceMappingURL=bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bridge.js","sourceRoot":"","sources":["../src/bridge.ts"],"names":[],"mappings":"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"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @clawswarm/bridge — Public API
|
|
3
|
+
*
|
|
4
|
+
* @example
|
|
5
|
+
* ```typescript
|
|
6
|
+
* import { BridgeServer, TaskRouter } from '@clawswarm/bridge';
|
|
7
|
+
* ```
|
|
8
|
+
*
|
|
9
|
+
* @module @clawswarm/bridge
|
|
10
|
+
*/
|
|
11
|
+
export { BridgeServer } from './bridge.js';
|
|
12
|
+
export { TaskRouter } from './router.js';
|
|
13
|
+
export type { BridgeClient, ClientRole, BridgeMessage, BridgeMessageType, BridgeServerConfig, BridgeServerEvents, AuthPayload, ErrorPayload, AgentStatusPayload, RoutingRule, } from './types.js';
|
|
14
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAEzC,YAAY,EACV,YAAY,EACZ,UAAU,EACV,aAAa,EACb,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EAClB,WAAW,EACX,YAAY,EACZ,kBAAkB,EAClB,WAAW,GACZ,MAAM,YAAY,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* @clawswarm/bridge — Public API
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* import { BridgeServer, TaskRouter } from '@clawswarm/bridge';
|
|
8
|
+
* ```
|
|
9
|
+
*
|
|
10
|
+
* @module @clawswarm/bridge
|
|
11
|
+
*/
|
|
12
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
13
|
+
exports.TaskRouter = exports.BridgeServer = void 0;
|
|
14
|
+
var bridge_js_1 = require("./bridge.js");
|
|
15
|
+
Object.defineProperty(exports, "BridgeServer", { enumerable: true, get: function () { return bridge_js_1.BridgeServer; } });
|
|
16
|
+
var router_js_1 = require("./router.js");
|
|
17
|
+
Object.defineProperty(exports, "TaskRouter", { enumerable: true, get: function () { return router_js_1.TaskRouter; } });
|
|
18
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;;;;;;;GASG;;;AAEH,yCAA2C;AAAlC,yGAAA,YAAY,OAAA;AACrB,yCAAyC;AAAhC,uGAAA,UAAU,OAAA"}
|
package/dist/router.d.ts
ADDED
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Org-scoped task router for the ClawSwarm bridge.
|
|
3
|
+
*
|
|
4
|
+
* Routes messages from ClawSwarm events to the appropriate
|
|
5
|
+
* WebSocket clients based on organization ID and client role.
|
|
6
|
+
*
|
|
7
|
+
* @module @clawswarm/bridge/router
|
|
8
|
+
*/
|
|
9
|
+
import { BridgeServer } from './bridge.js';
|
|
10
|
+
import { BridgeMessage, BridgeMessageType, ClientRole } from './types.js';
|
|
11
|
+
/**
|
|
12
|
+
* Routes ClawSwarm events to connected bridge clients.
|
|
13
|
+
*
|
|
14
|
+
* Provides a high-level API for broadcasting goal/task events
|
|
15
|
+
* to the right clients within an organization.
|
|
16
|
+
*
|
|
17
|
+
* @example
|
|
18
|
+
* ```typescript
|
|
19
|
+
* const bridge = new BridgeServer({ port: 8787 });
|
|
20
|
+
* await bridge.start();
|
|
21
|
+
*
|
|
22
|
+
* const router = new TaskRouter(bridge);
|
|
23
|
+
*
|
|
24
|
+
* // Connect a ClawSwarm instance to the router
|
|
25
|
+
* swarm.on('task:completed', (task) => {
|
|
26
|
+
* router.routeTaskEvent('task:completed', task.goalId, task, 'my-org-id');
|
|
27
|
+
* });
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare class TaskRouter {
|
|
31
|
+
private readonly bridge;
|
|
32
|
+
private readonly rules;
|
|
33
|
+
constructor(bridge: BridgeServer);
|
|
34
|
+
/**
|
|
35
|
+
* Route a task-related event to all dashboard clients in the org.
|
|
36
|
+
*
|
|
37
|
+
* @param type - Event type
|
|
38
|
+
* @param goalId - Goal ID for context
|
|
39
|
+
* @param payload - Event payload
|
|
40
|
+
* @param orgId - Organization to route to
|
|
41
|
+
*/
|
|
42
|
+
routeTaskEvent(type: BridgeMessageType, goalId: string, payload: unknown, orgId: string): number;
|
|
43
|
+
/**
|
|
44
|
+
* Route a goal-related event.
|
|
45
|
+
*
|
|
46
|
+
* @param type - Event type
|
|
47
|
+
* @param payload - Event payload (the Goal object)
|
|
48
|
+
* @param orgId - Organization to route to
|
|
49
|
+
*/
|
|
50
|
+
routeGoalEvent(type: BridgeMessageType, payload: unknown, orgId: string): number;
|
|
51
|
+
/**
|
|
52
|
+
* Route an agent status update to dashboard clients.
|
|
53
|
+
*/
|
|
54
|
+
routeAgentStatus(agentId: string, agentType: string, status: 'idle' | 'busy' | 'error' | 'offline', orgId: string, currentTaskId?: string): number;
|
|
55
|
+
/**
|
|
56
|
+
* Broadcast a raw message to all clients in an org.
|
|
57
|
+
*/
|
|
58
|
+
broadcast(orgId: string, message: BridgeMessage, roles?: ClientRole[]): number;
|
|
59
|
+
/**
|
|
60
|
+
* Add a routing rule for custom message handling.
|
|
61
|
+
* Rules are evaluated before default routing.
|
|
62
|
+
*
|
|
63
|
+
* @param id - Unique rule identifier
|
|
64
|
+
* @param rule - Route rule definition
|
|
65
|
+
*/
|
|
66
|
+
addRule(id: string, rule: RouteRule): void;
|
|
67
|
+
/**
|
|
68
|
+
* Remove a routing rule.
|
|
69
|
+
*/
|
|
70
|
+
removeRule(id: string): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Route a message through all matching rules.
|
|
73
|
+
* Returns the number of clients that received the message.
|
|
74
|
+
*/
|
|
75
|
+
route(orgId: string, message: BridgeMessage): number;
|
|
76
|
+
/**
|
|
77
|
+
* Build a typed bridge message.
|
|
78
|
+
* @internal
|
|
79
|
+
*/
|
|
80
|
+
private _buildMessage;
|
|
81
|
+
}
|
|
82
|
+
interface RouteRule {
|
|
83
|
+
messageType: BridgeMessageType | '*';
|
|
84
|
+
orgIds?: string[];
|
|
85
|
+
roles?: ClientRole[];
|
|
86
|
+
}
|
|
87
|
+
export {};
|
|
88
|
+
//# sourceMappingURL=router.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"router.d.ts","sourceRoot":"","sources":["../src/router.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAI1E;;;;;;;;;;;;;;;;;;GAkBG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAe;IACtC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAqC;gBAE/C,MAAM,EAAE,YAAY;IAMhC;;;;;;;OAOG;IACH,cAAc,CACZ,IAAI,EAAE,iBAAiB,EACvB,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,GACZ,MAAM;IAQT;;;;;;OAMG;IACH,cAAc,CACZ,IAAI,EAAE,iBAAiB,EACvB,OAAO,EAAE,OAAO,EAChB,KAAK,EAAE,MAAM,GACZ,MAAM;IAQT;;OAEG;IACH,gBAAgB,CACd,OAAO,EAAE,MAAM,EACf,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,EAC7C,KAAK,EAAE,MAAM,EACb,aAAa,CAAC,EAAE,MAAM,GACrB,MAAM;IAQT;;OAEG;IACH,SAAS,CACP,KAAK,EAAE,MAAM,EACb,OAAO,EAAE,aAAa,EACtB,KAAK,CAAC,EAAE,UAAU,EAAE,GACnB,MAAM;IAIT;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,GAAG,IAAI;IAI1C;;OAEG;IACH,UAAU,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO;IAI/B;;;OAGG;IACH,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,GAAG,MAAM;IAoBpD;;;OAGG;IACH,OAAO,CAAC,aAAa;CAYtB;AAID,UAAU,SAAS;IACjB,WAAW,EAAE,iBAAiB,GAAG,GAAG,CAAC;IACrC,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,KAAK,CAAC,EAAE,UAAU,EAAE,CAAC;CACtB"}
|