@athenafleet/bridge 1.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 +58 -0
- package/dist/client.d.ts +43 -0
- package/dist/client.js +261 -0
- package/dist/client.js.map +1 -0
- package/dist/gateway.d.ts +19 -0
- package/dist/gateway.js +71 -0
- package/dist/gateway.js.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.js +117 -0
- package/dist/index.js.map +1 -0
- package/dist/logger.d.ts +10 -0
- package/dist/logger.js +39 -0
- package/dist/logger.js.map +1 -0
- package/dist/types.d.ts +75 -0
- package/dist/types.js +15 -0
- package/dist/types.js.map +1 -0
- package/package.json +37 -0
package/README.md
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# @athenafleet/bridge
|
|
2
|
+
|
|
3
|
+
CLI bridge connecting your local OpenClaw gateway to the Athena dashboard via WebSocket.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm i -g @athenafleet/bridge
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
athena-bridge --key rtk_xxx
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
That's it. The bridge connects to the Athena API, authenticates with your runtime key, and begins syncing agent data from your local OpenClaw gateway to the dashboard.
|
|
18
|
+
|
|
19
|
+
## Options
|
|
20
|
+
|
|
21
|
+
| Flag | Default | Description |
|
|
22
|
+
|------|---------|-------------|
|
|
23
|
+
| `--key`, `-k` | *(required)* | Runtime API key (`rtk_` prefix) |
|
|
24
|
+
| `--api-url` | `https://api.athenafleet.ai` | Athena API URL |
|
|
25
|
+
| `--gateway-id` | hostname | Identifier for this gateway |
|
|
26
|
+
| `--openclaw-url` | `http://localhost:3007` | Local OpenClaw gateway URL |
|
|
27
|
+
| `--verbose`, `-v` | `false` | Enable debug logging |
|
|
28
|
+
|
|
29
|
+
## What it does
|
|
30
|
+
|
|
31
|
+
1. **Connects** to the Athena WebSocket endpoint (`/ws/runtime`)
|
|
32
|
+
2. **Authenticates** with your runtime API key (first-message auth)
|
|
33
|
+
3. **Syncs** agent data from your local OpenClaw gateway every 60 seconds
|
|
34
|
+
4. **Heartbeats** every 30 seconds to keep the connection alive
|
|
35
|
+
5. **Reconnects** automatically with exponential backoff if disconnected
|
|
36
|
+
|
|
37
|
+
## Generate a key
|
|
38
|
+
|
|
39
|
+
Runtime keys are created in the Athena dashboard under **Settings → Runtime Keys**, or via the API:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
curl -X POST https://api.athenafleet.ai/api/admin/runtime-keys \
|
|
43
|
+
-H "Authorization: Bearer <token>" \
|
|
44
|
+
-H "Content-Type: application/json" \
|
|
45
|
+
-d '{"name": "My Gateway"}'
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
The key is shown **once** on creation — save it.
|
|
49
|
+
|
|
50
|
+
## Requirements
|
|
51
|
+
|
|
52
|
+
- Node.js ≥ 18
|
|
53
|
+
- An Athena account with a runtime API key
|
|
54
|
+
- OpenClaw gateway running locally (optional — bridge works without it, just syncs empty agent list)
|
|
55
|
+
|
|
56
|
+
## License
|
|
57
|
+
|
|
58
|
+
MIT
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — WebSocket Client
|
|
3
|
+
*
|
|
4
|
+
* Manages the persistent WS connection to the Athena API:
|
|
5
|
+
* - First-message auth with runtime API key
|
|
6
|
+
* - Health pings on heartbeat_interval_ms
|
|
7
|
+
* - Agent sync every 60s + on server request
|
|
8
|
+
* - Exponential backoff reconnection with jitter
|
|
9
|
+
* - Graceful shutdown
|
|
10
|
+
*/
|
|
11
|
+
import type { BridgeOptions } from './types.js';
|
|
12
|
+
export declare class BridgeClient {
|
|
13
|
+
private ws;
|
|
14
|
+
private options;
|
|
15
|
+
private runtimeId;
|
|
16
|
+
private heartbeatIntervalMs;
|
|
17
|
+
private startedAt;
|
|
18
|
+
private heartbeatTimer;
|
|
19
|
+
private syncTimer;
|
|
20
|
+
private reconnectTimer;
|
|
21
|
+
private reconnectAttempt;
|
|
22
|
+
private intentionalClose;
|
|
23
|
+
private lastAgents;
|
|
24
|
+
private gatewayConnected;
|
|
25
|
+
constructor(options: BridgeOptions);
|
|
26
|
+
/**
|
|
27
|
+
* Start the bridge. Connects and begins sync loop.
|
|
28
|
+
*/
|
|
29
|
+
start(): void;
|
|
30
|
+
/**
|
|
31
|
+
* Graceful shutdown.
|
|
32
|
+
*/
|
|
33
|
+
stop(): void;
|
|
34
|
+
private connect;
|
|
35
|
+
private sendAuth;
|
|
36
|
+
private handleMessage;
|
|
37
|
+
private handleAuthOk;
|
|
38
|
+
private syncAgents;
|
|
39
|
+
private sendHealthPing;
|
|
40
|
+
private scheduleReconnect;
|
|
41
|
+
private send;
|
|
42
|
+
private clearTimers;
|
|
43
|
+
}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — WebSocket Client
|
|
3
|
+
*
|
|
4
|
+
* Manages the persistent WS connection to the Athena API:
|
|
5
|
+
* - First-message auth with runtime API key
|
|
6
|
+
* - Health pings on heartbeat_interval_ms
|
|
7
|
+
* - Agent sync every 60s + on server request
|
|
8
|
+
* - Exponential backoff reconnection with jitter
|
|
9
|
+
* - Graceful shutdown
|
|
10
|
+
*/
|
|
11
|
+
import WebSocket from 'ws';
|
|
12
|
+
import { CLOSE_CODES } from './types.js';
|
|
13
|
+
import { fetchAgents } from './gateway.js';
|
|
14
|
+
import * as log from './logger.js';
|
|
15
|
+
// =============================================================================
|
|
16
|
+
// Constants
|
|
17
|
+
// =============================================================================
|
|
18
|
+
const BRIDGE_VERSION = '1.0.0';
|
|
19
|
+
const SYNC_INTERVAL_MS = 60_000; // 1/min (server rate limit)
|
|
20
|
+
const BASE_BACKOFF_MS = 1_000;
|
|
21
|
+
const MAX_BACKOFF_MS = 30_000;
|
|
22
|
+
const JITTER_FACTOR = 0.25; // ±25%
|
|
23
|
+
// =============================================================================
|
|
24
|
+
// Bridge Client
|
|
25
|
+
// =============================================================================
|
|
26
|
+
export class BridgeClient {
|
|
27
|
+
ws = null;
|
|
28
|
+
options;
|
|
29
|
+
runtimeId = null;
|
|
30
|
+
heartbeatIntervalMs = 30_000;
|
|
31
|
+
startedAt = Date.now();
|
|
32
|
+
// Timers
|
|
33
|
+
heartbeatTimer = null;
|
|
34
|
+
syncTimer = null;
|
|
35
|
+
reconnectTimer = null;
|
|
36
|
+
// Reconnection state
|
|
37
|
+
reconnectAttempt = 0;
|
|
38
|
+
intentionalClose = false;
|
|
39
|
+
// Cached agent data
|
|
40
|
+
lastAgents = [];
|
|
41
|
+
gatewayConnected = false;
|
|
42
|
+
constructor(options) {
|
|
43
|
+
this.options = options;
|
|
44
|
+
}
|
|
45
|
+
// ===========================================================================
|
|
46
|
+
// Public API
|
|
47
|
+
// ===========================================================================
|
|
48
|
+
/**
|
|
49
|
+
* Start the bridge. Connects and begins sync loop.
|
|
50
|
+
*/
|
|
51
|
+
start() {
|
|
52
|
+
this.startedAt = Date.now();
|
|
53
|
+
this.intentionalClose = false;
|
|
54
|
+
this.connect();
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Graceful shutdown.
|
|
58
|
+
*/
|
|
59
|
+
stop() {
|
|
60
|
+
log.info('Shutting down...');
|
|
61
|
+
this.intentionalClose = true;
|
|
62
|
+
this.clearTimers();
|
|
63
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
64
|
+
this.ws.close(1000, 'Client shutdown');
|
|
65
|
+
}
|
|
66
|
+
this.ws = null;
|
|
67
|
+
}
|
|
68
|
+
// ===========================================================================
|
|
69
|
+
// Connection
|
|
70
|
+
// ===========================================================================
|
|
71
|
+
connect() {
|
|
72
|
+
const apiUrl = this.options.apiUrl.replace(/\/+$/, '');
|
|
73
|
+
const wsUrl = apiUrl.replace(/^http/, 'ws') + '/ws/runtime';
|
|
74
|
+
log.info(`Connecting to ${wsUrl}...`);
|
|
75
|
+
try {
|
|
76
|
+
this.ws = new WebSocket(wsUrl, {
|
|
77
|
+
headers: {
|
|
78
|
+
'User-Agent': `@athenafleet/bridge/${BRIDGE_VERSION}`,
|
|
79
|
+
},
|
|
80
|
+
handshakeTimeout: 10_000,
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
log.error('Failed to create WebSocket', err);
|
|
85
|
+
this.scheduleReconnect();
|
|
86
|
+
return;
|
|
87
|
+
}
|
|
88
|
+
this.ws.on('open', () => {
|
|
89
|
+
log.debug('WebSocket connected, sending auth...');
|
|
90
|
+
this.sendAuth();
|
|
91
|
+
});
|
|
92
|
+
this.ws.on('message', (data) => {
|
|
93
|
+
this.handleMessage(data);
|
|
94
|
+
});
|
|
95
|
+
this.ws.on('close', (code, reason) => {
|
|
96
|
+
const reasonStr = reason?.toString() || 'unknown';
|
|
97
|
+
log.info(`Disconnected (code=${code}, reason=${reasonStr})`);
|
|
98
|
+
this.clearTimers();
|
|
99
|
+
this.ws = null;
|
|
100
|
+
this.runtimeId = null;
|
|
101
|
+
// Don't reconnect on intentional close or fatal auth errors
|
|
102
|
+
if (this.intentionalClose)
|
|
103
|
+
return;
|
|
104
|
+
if (code === CLOSE_CODES.INVALID_AUTH) {
|
|
105
|
+
log.error('Authentication failed — check your --key. Not reconnecting.');
|
|
106
|
+
process.exit(1);
|
|
107
|
+
}
|
|
108
|
+
if (code === CLOSE_CODES.LIMIT_EXCEEDED) {
|
|
109
|
+
log.warn('Connection limit exceeded — will retry with backoff');
|
|
110
|
+
}
|
|
111
|
+
this.scheduleReconnect();
|
|
112
|
+
});
|
|
113
|
+
this.ws.on('error', (err) => {
|
|
114
|
+
log.error('WebSocket error', err);
|
|
115
|
+
// 'close' event will fire after this, triggering reconnect
|
|
116
|
+
});
|
|
117
|
+
// ws library auto-responds to ping with pong
|
|
118
|
+
}
|
|
119
|
+
// ===========================================================================
|
|
120
|
+
// Auth
|
|
121
|
+
// ===========================================================================
|
|
122
|
+
sendAuth() {
|
|
123
|
+
this.send({
|
|
124
|
+
type: 'auth',
|
|
125
|
+
key: this.options.key,
|
|
126
|
+
bridge_version: BRIDGE_VERSION,
|
|
127
|
+
gateway_version: 'unknown', // Future: detect OpenClaw version
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
// ===========================================================================
|
|
131
|
+
// Message handling
|
|
132
|
+
// ===========================================================================
|
|
133
|
+
handleMessage(raw) {
|
|
134
|
+
let msg;
|
|
135
|
+
try {
|
|
136
|
+
msg = JSON.parse(raw.toString());
|
|
137
|
+
}
|
|
138
|
+
catch {
|
|
139
|
+
log.debug('Received non-JSON message, ignoring');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
log.debug(`← ${msg.type}`, msg);
|
|
143
|
+
switch (msg.type) {
|
|
144
|
+
case 'auth_ok':
|
|
145
|
+
this.handleAuthOk(msg.runtime_id, msg.heartbeat_interval_ms);
|
|
146
|
+
break;
|
|
147
|
+
case 'auth_error':
|
|
148
|
+
log.error(`Auth rejected: ${msg.reason}`);
|
|
149
|
+
// Server will close the socket; close handler deals with exit
|
|
150
|
+
break;
|
|
151
|
+
case 'agents.sync_request':
|
|
152
|
+
log.info('Server requested agent sync');
|
|
153
|
+
void this.syncAgents();
|
|
154
|
+
break;
|
|
155
|
+
case 'runtime.disconnect':
|
|
156
|
+
log.warn(`Server disconnecting: ${msg.reason}`);
|
|
157
|
+
break;
|
|
158
|
+
case 'error':
|
|
159
|
+
log.warn(`Server error: ${msg.message}`);
|
|
160
|
+
break;
|
|
161
|
+
default:
|
|
162
|
+
log.debug('Unknown message type', { raw: raw.toString().slice(0, 200) });
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
handleAuthOk(runtimeId, heartbeatIntervalMs) {
|
|
166
|
+
this.runtimeId = runtimeId;
|
|
167
|
+
this.heartbeatIntervalMs = heartbeatIntervalMs;
|
|
168
|
+
this.reconnectAttempt = 0; // Reset backoff on successful auth
|
|
169
|
+
log.info(`✓ Authenticated (runtime=${runtimeId}, heartbeat=${heartbeatIntervalMs}ms)`);
|
|
170
|
+
// Start heartbeat
|
|
171
|
+
this.heartbeatTimer = setInterval(() => {
|
|
172
|
+
this.sendHealthPing();
|
|
173
|
+
}, this.heartbeatIntervalMs);
|
|
174
|
+
// Initial sync + periodic sync
|
|
175
|
+
void this.syncAgents();
|
|
176
|
+
this.syncTimer = setInterval(() => {
|
|
177
|
+
void this.syncAgents();
|
|
178
|
+
}, SYNC_INTERVAL_MS);
|
|
179
|
+
}
|
|
180
|
+
// ===========================================================================
|
|
181
|
+
// Agent sync
|
|
182
|
+
// ===========================================================================
|
|
183
|
+
async syncAgents() {
|
|
184
|
+
try {
|
|
185
|
+
const agents = await fetchAgents(this.options.openclawUrl);
|
|
186
|
+
this.lastAgents = agents;
|
|
187
|
+
this.gatewayConnected = agents.length > 0;
|
|
188
|
+
this.send({
|
|
189
|
+
type: 'agents.sync',
|
|
190
|
+
agents,
|
|
191
|
+
gateway_id: this.options.gatewayId,
|
|
192
|
+
timestamp: new Date().toISOString(),
|
|
193
|
+
});
|
|
194
|
+
log.info(`Synced ${agents.length} agent(s)`);
|
|
195
|
+
}
|
|
196
|
+
catch (err) {
|
|
197
|
+
log.error('Agent sync failed', err);
|
|
198
|
+
this.gatewayConnected = false;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
// ===========================================================================
|
|
202
|
+
// Health ping
|
|
203
|
+
// ===========================================================================
|
|
204
|
+
sendHealthPing() {
|
|
205
|
+
this.send({
|
|
206
|
+
type: 'health.ping',
|
|
207
|
+
gateway_connected: this.gatewayConnected,
|
|
208
|
+
agent_count: this.lastAgents.length,
|
|
209
|
+
uptime_ms: Date.now() - this.startedAt,
|
|
210
|
+
timestamp: new Date().toISOString(),
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
// ===========================================================================
|
|
214
|
+
// Reconnection (FINF-35: exponential backoff + jitter)
|
|
215
|
+
// ===========================================================================
|
|
216
|
+
scheduleReconnect() {
|
|
217
|
+
this.reconnectAttempt++;
|
|
218
|
+
// Exponential backoff: 1s, 2s, 4s, 8s, 16s, 30s cap
|
|
219
|
+
const baseDelay = Math.min(BASE_BACKOFF_MS * Math.pow(2, this.reconnectAttempt - 1), MAX_BACKOFF_MS);
|
|
220
|
+
// ±25% jitter
|
|
221
|
+
const jitter = baseDelay * JITTER_FACTOR * (2 * Math.random() - 1);
|
|
222
|
+
const delay = Math.max(500, Math.round(baseDelay + jitter));
|
|
223
|
+
log.info(`Reconnecting in ${(delay / 1000).toFixed(1)}s (attempt ${this.reconnectAttempt})...`);
|
|
224
|
+
this.reconnectTimer = setTimeout(() => {
|
|
225
|
+
this.reconnectTimer = null;
|
|
226
|
+
this.connect();
|
|
227
|
+
}, delay);
|
|
228
|
+
}
|
|
229
|
+
// ===========================================================================
|
|
230
|
+
// Helpers
|
|
231
|
+
// ===========================================================================
|
|
232
|
+
send(msg) {
|
|
233
|
+
if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
|
|
234
|
+
log.debug(`Cannot send ${msg.type} — not connected`);
|
|
235
|
+
return;
|
|
236
|
+
}
|
|
237
|
+
const payload = JSON.stringify(msg);
|
|
238
|
+
log.debug(`→ ${msg.type}`, { size: payload.length });
|
|
239
|
+
try {
|
|
240
|
+
this.ws.send(payload);
|
|
241
|
+
}
|
|
242
|
+
catch (err) {
|
|
243
|
+
log.error(`Failed to send ${msg.type}`, err);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
clearTimers() {
|
|
247
|
+
if (this.heartbeatTimer) {
|
|
248
|
+
clearInterval(this.heartbeatTimer);
|
|
249
|
+
this.heartbeatTimer = null;
|
|
250
|
+
}
|
|
251
|
+
if (this.syncTimer) {
|
|
252
|
+
clearInterval(this.syncTimer);
|
|
253
|
+
this.syncTimer = null;
|
|
254
|
+
}
|
|
255
|
+
if (this.reconnectTimer) {
|
|
256
|
+
clearTimeout(this.reconnectTimer);
|
|
257
|
+
this.reconnectTimer = null;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Gateway Data Collector
|
|
3
|
+
*
|
|
4
|
+
* Fetches agent data from the local OpenClaw gateway.
|
|
5
|
+
* Gracefully handles connection failures (returns empty array).
|
|
6
|
+
*/
|
|
7
|
+
import type { SyncedAgent } from './types.js';
|
|
8
|
+
/**
|
|
9
|
+
* Fetch agent list from local OpenClaw gateway.
|
|
10
|
+
*
|
|
11
|
+
* Expected response shape from OpenClaw /api/agents:
|
|
12
|
+
* ```json
|
|
13
|
+
* [{ "id": "...", "name": "...", "emoji": "...", "status": "...", ... }]
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Fields are mapped to the SyncedAgent shape expected by the server.
|
|
17
|
+
* Missing fields get safe defaults.
|
|
18
|
+
*/
|
|
19
|
+
export declare function fetchAgents(openclawUrl: string): Promise<SyncedAgent[]>;
|
package/dist/gateway.js
ADDED
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Gateway Data Collector
|
|
3
|
+
*
|
|
4
|
+
* Fetches agent data from the local OpenClaw gateway.
|
|
5
|
+
* Gracefully handles connection failures (returns empty array).
|
|
6
|
+
*/
|
|
7
|
+
import * as log from './logger.js';
|
|
8
|
+
/**
|
|
9
|
+
* Fetch agent list from local OpenClaw gateway.
|
|
10
|
+
*
|
|
11
|
+
* Expected response shape from OpenClaw /api/agents:
|
|
12
|
+
* ```json
|
|
13
|
+
* [{ "id": "...", "name": "...", "emoji": "...", "status": "...", ... }]
|
|
14
|
+
* ```
|
|
15
|
+
*
|
|
16
|
+
* Fields are mapped to the SyncedAgent shape expected by the server.
|
|
17
|
+
* Missing fields get safe defaults.
|
|
18
|
+
*/
|
|
19
|
+
export async function fetchAgents(openclawUrl) {
|
|
20
|
+
const url = `${openclawUrl.replace(/\/+$/, '')}/api/agents`;
|
|
21
|
+
try {
|
|
22
|
+
const controller = new AbortController();
|
|
23
|
+
const timeout = setTimeout(() => controller.abort(), 5_000);
|
|
24
|
+
const res = await fetch(url, {
|
|
25
|
+
signal: controller.signal,
|
|
26
|
+
headers: { Accept: 'application/json' },
|
|
27
|
+
});
|
|
28
|
+
clearTimeout(timeout);
|
|
29
|
+
if (!res.ok) {
|
|
30
|
+
log.warn(`Gateway returned ${res.status} from ${url}`);
|
|
31
|
+
return [];
|
|
32
|
+
}
|
|
33
|
+
const data = await res.json();
|
|
34
|
+
if (!Array.isArray(data)) {
|
|
35
|
+
log.warn('Gateway /api/agents did not return an array');
|
|
36
|
+
return [];
|
|
37
|
+
}
|
|
38
|
+
return data.map(sanitizeAgent).filter((a) => a !== null);
|
|
39
|
+
}
|
|
40
|
+
catch (err) {
|
|
41
|
+
if (err instanceof Error && err.name === 'AbortError') {
|
|
42
|
+
log.debug('Gateway request timed out');
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
log.debug('Gateway unreachable', { error: err instanceof Error ? err.message : String(err) });
|
|
46
|
+
}
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Map raw gateway agent data to SyncedAgent with safe defaults.
|
|
52
|
+
*/
|
|
53
|
+
function sanitizeAgent(raw) {
|
|
54
|
+
if (typeof raw !== 'object' || raw === null)
|
|
55
|
+
return null;
|
|
56
|
+
const r = raw;
|
|
57
|
+
const id = r.id;
|
|
58
|
+
if (!id || typeof id !== 'string')
|
|
59
|
+
return null;
|
|
60
|
+
return {
|
|
61
|
+
id,
|
|
62
|
+
name: typeof r.name === 'string' ? r.name : 'Unknown',
|
|
63
|
+
emoji: typeof r.emoji === 'string' ? r.emoji : '🤖',
|
|
64
|
+
status: typeof r.status === 'string' ? r.status : 'unknown',
|
|
65
|
+
model: typeof r.model === 'string' ? r.model : '',
|
|
66
|
+
uptime: typeof r.uptime === 'number' ? r.uptime : 0,
|
|
67
|
+
lastHeartbeat: typeof r.lastHeartbeat === 'string' ? r.lastHeartbeat : new Date().toISOString(),
|
|
68
|
+
sessionCount: typeof r.sessionCount === 'number' ? r.sessionCount : 0,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=gateway.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway.js","sourceRoot":"","sources":["../src/gateway.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAGH,OAAO,KAAK,GAAG,MAAM,aAAa,CAAC;AAEnC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,WAAmB;IACnD,MAAM,GAAG,GAAG,GAAG,WAAW,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,aAAa,CAAC;IAE5D,IAAI,CAAC;QACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;QACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,KAAK,CAAC,CAAC;QAE5D,MAAM,GAAG,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;YAC3B,MAAM,EAAE,UAAU,CAAC,MAAM;YACzB,OAAO,EAAE,EAAE,MAAM,EAAE,kBAAkB,EAAE;SACxC,CAAC,CAAC;QAEH,YAAY,CAAC,OAAO,CAAC,CAAC;QAEtB,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,CAAC;YACZ,GAAG,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,MAAM,SAAS,GAAG,EAAE,CAAC,CAAC;YACvD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,IAAI,GAAY,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAEvC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACzB,GAAG,CAAC,IAAI,CAAC,6CAA6C,CAAC,CAAC;YACxD,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAoB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC7E,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,IAAI,GAAG,YAAY,KAAK,IAAI,GAAG,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YACtD,GAAG,CAAC,KAAK,CAAC,2BAA2B,CAAC,CAAC;QACzC,CAAC;aAAM,CAAC;YACN,GAAG,CAAC,KAAK,CAAC,qBAAqB,EAAE,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAChG,CAAC;QACD,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;GAEG;AACH,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAEzD,MAAM,CAAC,GAAG,GAA8B,CAAC;IACzC,MAAM,EAAE,GAAG,CAAC,CAAC,EAAE,CAAC;IAChB,IAAI,CAAC,EAAE,IAAI,OAAO,EAAE,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IAE/C,OAAO;QACL,EAAE;QACF,IAAI,EAAE,OAAO,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,SAAS;QACrD,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI;QACnD,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS;QAC3D,KAAK,EAAE,OAAO,CAAC,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE;QACjD,MAAM,EAAE,OAAO,CAAC,CAAC,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;QACnD,aAAa,EAAE,OAAO,CAAC,CAAC,aAAa,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;QAC/F,YAAY,EAAE,OAAO,CAAC,CAAC,YAAY,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;KACtE,CAAC;AACJ,CAAC"}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
/**
|
|
3
|
+
* @athenafleet/bridge — CLI Entry Point
|
|
4
|
+
*
|
|
5
|
+
* Usage:
|
|
6
|
+
* athena-bridge --key rtk_xxx [--api-url https://api.athenafleet.ai] [--verbose]
|
|
7
|
+
*/
|
|
8
|
+
import { hostname } from 'os';
|
|
9
|
+
import { BridgeClient } from './client.js';
|
|
10
|
+
import * as log from './logger.js';
|
|
11
|
+
import { setVerbose } from './logger.js';
|
|
12
|
+
// =============================================================================
|
|
13
|
+
// Argument parsing (zero deps — just process.argv)
|
|
14
|
+
// =============================================================================
|
|
15
|
+
function parseArgs(argv) {
|
|
16
|
+
let key;
|
|
17
|
+
let apiUrl = 'https://api.athenafleet.ai';
|
|
18
|
+
let gatewayId = hostname();
|
|
19
|
+
let openclawUrl = 'http://localhost:3007';
|
|
20
|
+
let verbose = false;
|
|
21
|
+
for (let i = 2; i < argv.length; i++) {
|
|
22
|
+
const arg = argv[i];
|
|
23
|
+
if (arg === '--key' || arg === '-k') {
|
|
24
|
+
key = argv[++i];
|
|
25
|
+
}
|
|
26
|
+
else if (arg.startsWith('--key=')) {
|
|
27
|
+
key = arg.slice('--key='.length);
|
|
28
|
+
}
|
|
29
|
+
else if (arg === '--api-url') {
|
|
30
|
+
apiUrl = argv[++i] ?? apiUrl;
|
|
31
|
+
}
|
|
32
|
+
else if (arg.startsWith('--api-url=')) {
|
|
33
|
+
apiUrl = arg.slice('--api-url='.length);
|
|
34
|
+
}
|
|
35
|
+
else if (arg === '--gateway-id') {
|
|
36
|
+
gatewayId = argv[++i] ?? gatewayId;
|
|
37
|
+
}
|
|
38
|
+
else if (arg.startsWith('--gateway-id=')) {
|
|
39
|
+
gatewayId = arg.slice('--gateway-id='.length);
|
|
40
|
+
}
|
|
41
|
+
else if (arg === '--openclaw-url') {
|
|
42
|
+
openclawUrl = argv[++i] ?? openclawUrl;
|
|
43
|
+
}
|
|
44
|
+
else if (arg.startsWith('--openclaw-url=')) {
|
|
45
|
+
openclawUrl = arg.slice('--openclaw-url='.length);
|
|
46
|
+
}
|
|
47
|
+
else if (arg === '--verbose' || arg === '-v') {
|
|
48
|
+
verbose = true;
|
|
49
|
+
}
|
|
50
|
+
else if (arg === '--help' || arg === '-h') {
|
|
51
|
+
printHelp();
|
|
52
|
+
process.exit(0);
|
|
53
|
+
}
|
|
54
|
+
else if (arg === '--version') {
|
|
55
|
+
console.log('1.0.0');
|
|
56
|
+
process.exit(0);
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
console.error(`Unknown argument: ${arg}`);
|
|
60
|
+
printHelp();
|
|
61
|
+
process.exit(1);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!key) {
|
|
65
|
+
console.error('Error: --key is required\n');
|
|
66
|
+
printHelp();
|
|
67
|
+
process.exit(1);
|
|
68
|
+
}
|
|
69
|
+
if (!key.startsWith('rtk_')) {
|
|
70
|
+
console.error('Error: key must start with rtk_ prefix\n');
|
|
71
|
+
process.exit(1);
|
|
72
|
+
}
|
|
73
|
+
return { key, apiUrl, gatewayId, openclawUrl, verbose };
|
|
74
|
+
}
|
|
75
|
+
function printHelp() {
|
|
76
|
+
console.log(`
|
|
77
|
+
@athenafleet/bridge — Connect your OpenClaw gateway to Athena
|
|
78
|
+
|
|
79
|
+
Usage:
|
|
80
|
+
athena-bridge --key rtk_xxx [options]
|
|
81
|
+
|
|
82
|
+
Options:
|
|
83
|
+
--key, -k <key> Runtime API key (required, rtk_ prefix)
|
|
84
|
+
--api-url <url> Athena API URL (default: https://api.athenafleet.ai)
|
|
85
|
+
--gateway-id <id> Gateway identifier (default: hostname)
|
|
86
|
+
--openclaw-url <url> Local OpenClaw URL (default: http://localhost:3007)
|
|
87
|
+
--verbose, -v Enable debug logging
|
|
88
|
+
--version Print version
|
|
89
|
+
--help, -h Print this help
|
|
90
|
+
|
|
91
|
+
Examples:
|
|
92
|
+
athena-bridge --key rtk_abc123
|
|
93
|
+
athena-bridge --key rtk_abc123 --api-url http://localhost:4000 --verbose
|
|
94
|
+
`);
|
|
95
|
+
}
|
|
96
|
+
// =============================================================================
|
|
97
|
+
// Main
|
|
98
|
+
// =============================================================================
|
|
99
|
+
const options = parseArgs(process.argv);
|
|
100
|
+
setVerbose(options.verbose);
|
|
101
|
+
log.info('@athenafleet/bridge starting...');
|
|
102
|
+
log.info(` API: ${options.apiUrl}`);
|
|
103
|
+
log.info(` Gateway: ${options.gatewayId}`);
|
|
104
|
+
log.info(` OpenClaw: ${options.openclawUrl}`);
|
|
105
|
+
log.info(` Verbose: ${options.verbose}`);
|
|
106
|
+
const client = new BridgeClient(options);
|
|
107
|
+
// Graceful shutdown
|
|
108
|
+
function shutdown(signal) {
|
|
109
|
+
log.info(`Received ${signal}`);
|
|
110
|
+
client.stop();
|
|
111
|
+
// Give WS close frame time to send
|
|
112
|
+
setTimeout(() => process.exit(0), 500);
|
|
113
|
+
}
|
|
114
|
+
process.on('SIGINT', () => shutdown('SIGINT'));
|
|
115
|
+
process.on('SIGTERM', () => shutdown('SIGTERM'));
|
|
116
|
+
client.start();
|
|
117
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/logger.d.ts
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Logger
|
|
3
|
+
*
|
|
4
|
+
* Simple structured logger with verbose mode.
|
|
5
|
+
*/
|
|
6
|
+
export declare function setVerbose(enabled: boolean): void;
|
|
7
|
+
export declare function info(msg: string, data?: Record<string, unknown>): void;
|
|
8
|
+
export declare function error(msg: string, err?: unknown): void;
|
|
9
|
+
export declare function warn(msg: string): void;
|
|
10
|
+
export declare function debug(msg: string, data?: Record<string, unknown>): void;
|
package/dist/logger.js
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Logger
|
|
3
|
+
*
|
|
4
|
+
* Simple structured logger with verbose mode.
|
|
5
|
+
*/
|
|
6
|
+
let verboseEnabled = false;
|
|
7
|
+
export function setVerbose(enabled) {
|
|
8
|
+
verboseEnabled = enabled;
|
|
9
|
+
}
|
|
10
|
+
function timestamp() {
|
|
11
|
+
return new Date().toISOString();
|
|
12
|
+
}
|
|
13
|
+
export function info(msg, data) {
|
|
14
|
+
const parts = [`[${timestamp()}] ${msg}`];
|
|
15
|
+
if (data && verboseEnabled) {
|
|
16
|
+
parts.push(JSON.stringify(data));
|
|
17
|
+
}
|
|
18
|
+
console.log(parts.join(' '));
|
|
19
|
+
}
|
|
20
|
+
export function error(msg, err) {
|
|
21
|
+
const parts = [`[${timestamp()}] ERROR: ${msg}`];
|
|
22
|
+
if (err instanceof Error) {
|
|
23
|
+
parts.push(`— ${err.message}`);
|
|
24
|
+
}
|
|
25
|
+
console.error(parts.join(' '));
|
|
26
|
+
}
|
|
27
|
+
export function warn(msg) {
|
|
28
|
+
console.warn(`[${timestamp()}] WARN: ${msg}`);
|
|
29
|
+
}
|
|
30
|
+
export function debug(msg, data) {
|
|
31
|
+
if (!verboseEnabled)
|
|
32
|
+
return;
|
|
33
|
+
const parts = [`[${timestamp()}] DEBUG: ${msg}`];
|
|
34
|
+
if (data) {
|
|
35
|
+
parts.push(JSON.stringify(data));
|
|
36
|
+
}
|
|
37
|
+
console.log(parts.join(' '));
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=logger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,IAAI,cAAc,GAAG,KAAK,CAAC;AAE3B,MAAM,UAAU,UAAU,CAAC,OAAgB;IACzC,cAAc,GAAG,OAAO,CAAC;AAC3B,CAAC;AAED,SAAS,SAAS;IAChB,OAAO,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW,EAAE,IAA8B;IAC9D,MAAM,KAAK,GAAG,CAAC,IAAI,SAAS,EAAE,KAAK,GAAG,EAAE,CAAC,CAAC;IAC1C,IAAI,IAAI,IAAI,cAAc,EAAE,CAAC;QAC3B,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW,EAAE,GAAa;IAC9C,MAAM,KAAK,GAAG,CAAC,IAAI,SAAS,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC;IACjD,IAAI,GAAG,YAAY,KAAK,EAAE,CAAC;QACzB,KAAK,CAAC,IAAI,CAAC,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;IACjC,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AACjC,CAAC;AAED,MAAM,UAAU,IAAI,CAAC,GAAW;IAC9B,OAAO,CAAC,IAAI,CAAC,IAAI,SAAS,EAAE,WAAW,GAAG,EAAE,CAAC,CAAC;AAChD,CAAC;AAED,MAAM,UAAU,KAAK,CAAC,GAAW,EAAE,IAA8B;IAC/D,IAAI,CAAC,cAAc;QAAE,OAAO;IAC5B,MAAM,KAAK,GAAG,CAAC,IAAI,SAAS,EAAE,YAAY,GAAG,EAAE,CAAC,CAAC;IACjD,IAAI,IAAI,EAAE,CAAC;QACT,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;IACnC,CAAC;IACD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;AAC/B,CAAC"}
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Message Types
|
|
3
|
+
*
|
|
4
|
+
* Mirrors athena-api src/ws/runtime-types.ts
|
|
5
|
+
*/
|
|
6
|
+
export interface SyncedAgent {
|
|
7
|
+
id: string;
|
|
8
|
+
name: string;
|
|
9
|
+
emoji: string;
|
|
10
|
+
status: string;
|
|
11
|
+
model: string;
|
|
12
|
+
uptime: number;
|
|
13
|
+
lastHeartbeat: string;
|
|
14
|
+
sessionCount: number;
|
|
15
|
+
}
|
|
16
|
+
export interface AuthMessage {
|
|
17
|
+
type: 'auth';
|
|
18
|
+
key: string;
|
|
19
|
+
bridge_version: string;
|
|
20
|
+
gateway_version: string;
|
|
21
|
+
}
|
|
22
|
+
export interface AgentsSyncMessage {
|
|
23
|
+
type: 'agents.sync';
|
|
24
|
+
agents: SyncedAgent[];
|
|
25
|
+
gateway_id: string;
|
|
26
|
+
timestamp: string;
|
|
27
|
+
}
|
|
28
|
+
export interface AgentStatusMessage {
|
|
29
|
+
type: 'agents.status';
|
|
30
|
+
agent_id: string;
|
|
31
|
+
status: string;
|
|
32
|
+
timestamp: string;
|
|
33
|
+
}
|
|
34
|
+
export interface HealthPingMessage {
|
|
35
|
+
type: 'health.ping';
|
|
36
|
+
gateway_connected: boolean;
|
|
37
|
+
agent_count: number;
|
|
38
|
+
uptime_ms: number;
|
|
39
|
+
timestamp: string;
|
|
40
|
+
}
|
|
41
|
+
export type BridgeOutbound = AuthMessage | AgentsSyncMessage | AgentStatusMessage | HealthPingMessage;
|
|
42
|
+
export interface AuthOkMessage {
|
|
43
|
+
type: 'auth_ok';
|
|
44
|
+
runtime_id: string;
|
|
45
|
+
heartbeat_interval_ms: number;
|
|
46
|
+
}
|
|
47
|
+
export interface AuthErrorMessage {
|
|
48
|
+
type: 'auth_error';
|
|
49
|
+
reason: string;
|
|
50
|
+
}
|
|
51
|
+
export interface SyncRequestMessage {
|
|
52
|
+
type: 'agents.sync_request';
|
|
53
|
+
}
|
|
54
|
+
export interface RuntimeDisconnectMessage {
|
|
55
|
+
type: 'runtime.disconnect';
|
|
56
|
+
reason: string;
|
|
57
|
+
}
|
|
58
|
+
export interface ErrorMessage {
|
|
59
|
+
type: 'error';
|
|
60
|
+
message: string;
|
|
61
|
+
}
|
|
62
|
+
export type ServerInbound = AuthOkMessage | AuthErrorMessage | SyncRequestMessage | RuntimeDisconnectMessage | ErrorMessage;
|
|
63
|
+
export declare const CLOSE_CODES: {
|
|
64
|
+
readonly INVALID_AUTH: 4001;
|
|
65
|
+
readonly LIMIT_EXCEEDED: 4003;
|
|
66
|
+
readonly AUTH_TIMEOUT: 4008;
|
|
67
|
+
readonly PONG_TIMEOUT: 4009;
|
|
68
|
+
};
|
|
69
|
+
export interface BridgeOptions {
|
|
70
|
+
key: string;
|
|
71
|
+
apiUrl: string;
|
|
72
|
+
gatewayId: string;
|
|
73
|
+
openclawUrl: string;
|
|
74
|
+
verbose: boolean;
|
|
75
|
+
}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @athenafleet/bridge — Message Types
|
|
3
|
+
*
|
|
4
|
+
* Mirrors athena-api src/ws/runtime-types.ts
|
|
5
|
+
*/
|
|
6
|
+
// =============================================================================
|
|
7
|
+
// Close codes (from server)
|
|
8
|
+
// =============================================================================
|
|
9
|
+
export const CLOSE_CODES = {
|
|
10
|
+
INVALID_AUTH: 4001,
|
|
11
|
+
LIMIT_EXCEEDED: 4003,
|
|
12
|
+
AUTH_TIMEOUT: 4008,
|
|
13
|
+
PONG_TIMEOUT: 4009,
|
|
14
|
+
};
|
|
15
|
+
//# sourceMappingURL=types.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AA4FH,gFAAgF;AAChF,4BAA4B;AAC5B,gFAAgF;AAEhF,MAAM,CAAC,MAAM,WAAW,GAAG;IACzB,YAAY,EAAE,IAAI;IAClB,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE,IAAI;IAClB,YAAY,EAAE,IAAI;CACV,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@athenafleet/bridge",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "CLI bridge connecting local OpenClaw gateway to Athena dashboard via WebSocket",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"bin": {
|
|
7
|
+
"athena-bridge": "dist/index.js"
|
|
8
|
+
},
|
|
9
|
+
"main": "dist/index.js",
|
|
10
|
+
"files": [
|
|
11
|
+
"dist"
|
|
12
|
+
],
|
|
13
|
+
"scripts": {
|
|
14
|
+
"build": "tsc",
|
|
15
|
+
"prepare": "npm run build",
|
|
16
|
+
"dev": "tsc --watch"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [
|
|
19
|
+
"athena",
|
|
20
|
+
"bridge",
|
|
21
|
+
"openclaw",
|
|
22
|
+
"runtime",
|
|
23
|
+
"websocket"
|
|
24
|
+
],
|
|
25
|
+
"license": "MIT",
|
|
26
|
+
"engines": {
|
|
27
|
+
"node": ">=18.0.0"
|
|
28
|
+
},
|
|
29
|
+
"dependencies": {
|
|
30
|
+
"ws": "^8.18.0"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^22.0.0",
|
|
34
|
+
"@types/ws": "^8.5.0",
|
|
35
|
+
"typescript": "^5.7.0"
|
|
36
|
+
}
|
|
37
|
+
}
|