omniwire 3.0.1 → 3.1.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 CHANGED
@@ -8,13 +8,21 @@
8
8
 
9
9
  <p align="center">
10
10
  <a href="https://www.npmjs.com/package/omniwire"><img src="https://img.shields.io/npm/v/omniwire?style=for-the-badge&logo=npm&color=CB3837&labelColor=0D1117" alt="npm" /></a>
11
- <img src="https://img.shields.io/badge/MCP_Tools-56-59C2FF?style=for-the-badge&labelColor=0D1117" alt="tools" />
11
+ <img src="https://img.shields.io/badge/MCP_Tools-81-59C2FF?style=for-the-badge&labelColor=0D1117" alt="tools" />
12
12
  <img src="https://img.shields.io/badge/A2A-Protocol-00C853?style=for-the-badge&labelColor=0D1117" alt="A2A" />
13
- <img src="https://img.shields.io/badge/Latency-~80ms-FF6D00?style=for-the-badge&labelColor=0D1117" alt="latency" />
14
- <img src="https://img.shields.io/badge/Background-Dispatch-CC93E6?style=for-the-badge&labelColor=0D1117" alt="background" />
13
+ <img src="https://img.shields.io/badge/Latency-~81ms-FF6D00?style=for-the-badge&labelColor=0D1117" alt="latency" />
14
+ <img src="https://img.shields.io/badge/CyberBase-Sync-CC93E6?style=for-the-badge&labelColor=0D1117" alt="cyberbase" />
15
15
  <a href="LICENSE"><img src="https://img.shields.io/badge/GPL--3.0-license-8B949E?style=for-the-badge&labelColor=0D1117" alt="license" /></a>
16
16
  </p>
17
17
 
18
+ <div align="center">
19
+
20
+ **The infrastructure layer for AI agent swarms.**
21
+
22
+ 81 MCP tools · A2A protocol · OmniMesh VPN · nftables firewall · CDP browser · cookie sync · CyberBase persistence
23
+
24
+ </div>
25
+
18
26
  ---
19
27
 
20
28
  ## Quick Start
@@ -206,7 +214,7 @@ graph TB
206
214
  direction TB
207
215
  MCP["MCP Protocol Layer<br/>stdio | SSE | REST"]
208
216
 
209
- subgraph tools["56 Tools"]
217
+ subgraph tools["81 Tools"]
210
218
  direction LR
211
219
  EXEC["Execution<br/>exec run batch<br/>broadcast pipeline bg"]
212
220
  AGENT["Agentic<br/>store watch task<br/>a2a events locks"]
@@ -287,7 +295,7 @@ omniwire_workflow reusable named DAGs
287
295
 
288
296
  ### Adaptive File Transfer
289
297
  ```
290
- < 10 MB SFTP native, 80ms
298
+ < 10 MB SFTP native, 81ms
291
299
  10M-1GB netcat+LZ4 compressed, 100ms
292
300
  > 1 GB aria2c 16-parallel, max speed
293
301
  ```
@@ -340,7 +348,7 @@ watch(assert="ready") poll until
340
348
 
341
349
  ---
342
350
 
343
- ## All 56 Tools
351
+ ## All 81 Tools
344
352
 
345
353
  > **Every tool** supports `background: true` -- returns a task ID immediately. Poll with `omniwire_bg`.
346
354
 
@@ -408,18 +416,51 @@ watch(assert="ready") poll until
408
416
  | `omniwire_git` | Git commands on repos on any node |
409
417
  | `omniwire_syslog` | Query journalctl with filters |
410
418
 
411
- ### Network, VPN & Firewall (7)
419
+ ### Network, VPN & Security (9)
412
420
 
413
421
  | Tool | Description |
414
422
  |------|-------------|
415
423
  | `omniwire_firewall` | nftables firewall engine. Presets (server/paranoid/pentest), rate-limit, geo-block, port-knock, ban/unban, audit. Mesh always whitelisted. |
416
- | `omniwire_vpn` | Manage VPN (Mullvad/OpenVPN/WireGuard/Tailscale). Split-tunnel + full-node modes. Mesh stays connected. |
424
+ | `omniwire_vpn` | VPN (Mullvad/OpenVPN/WireGuard/Tailscale). Multi-hop, DAITA, quantum, obfuscation, killswitch. Mesh-safe. |
425
+ | `omniwire_cookies` | Cookie management. JSON/Header/Netscape formats. Browser extract, CyberBase + 1Password sync. |
426
+ | `omniwire_cdp` | Chrome DevTools Protocol. Launch headless Chrome, screenshot, PDF, DOM dump, cookie extract. |
427
+ | `omniwire_proxy` | HTTP/SOCKS proxy management. Start/stop proxies on any node. |
428
+ | `omniwire_dns` | DNS management. Resolve, set server, flush cache, block domains. |
417
429
  | `omniwire_port_forward` | Create/list/close SSH tunnels |
418
- | `omniwire_open_browser` | Open URL in browser on a node |
419
430
  | `omniwire_shell` | Persistent PTY session (preserves cwd/env) |
420
- | `omniwire_stream` | Capture streaming output (tail -f, watch) |
421
431
  | `omniwire_clipboard` | Shared clipboard buffer across mesh |
422
432
 
433
+ ### Infrastructure (9)
434
+
435
+ | Tool | Description |
436
+ |------|-------------|
437
+ | `omniwire_backup` | Snapshot/restore paths on any node. Diff, cleanup, retention policies. |
438
+ | `omniwire_container` | Full Docker lifecycle. Compose up/down, build, push, logs, prune, stats. |
439
+ | `omniwire_cert` | TLS certificates. Let's Encrypt issue/renew, check expiry, self-signed generation. |
440
+ | `omniwire_user` | User & SSH key management. Add/remove users, deploy keys, sudo config. |
441
+ | `omniwire_schedule` | Distributed cron with failover. Add/remove/list/run-now scheduled tasks. |
442
+ | `omniwire_alert` | Threshold alerting. Disk/mem/load/offline checks with webhook notifications. |
443
+ | `omniwire_log_aggregate` | Cross-node log search. Grep journalctl/syslog across all nodes in parallel. |
444
+ | `omniwire_benchmark` | Node performance testing. CPU/memory/disk/network benchmarks. |
445
+ | `omniwire_stream` | Capture streaming output (tail -f, watch) |
446
+
447
+ ### Agent Toolkit (7)
448
+
449
+ | Tool | Description |
450
+ |------|-------------|
451
+ | `omniwire_snippet` | Save/run reusable command templates with `{{var}}` substitution. |
452
+ | `omniwire_alias` | In-session command shortcuts. Set/run aliases. |
453
+ | `omniwire_trace` | Distributed tracing. Start/stop/view span waterfalls across nodes. |
454
+ | `omniwire_doctor` | Health diagnostics. Checks SSH, disk, mem, docker, WireGuard, tools, CyberBase. |
455
+ | `omniwire_metrics` | Prometheus-compatible metrics. Scrape/export node stats. |
456
+ | `omniwire_audit` | Command audit log. View/search/stats on all executed commands. |
457
+ | `omniwire_plugin` | Plugin system. List/load plugins from `~/.omniwire/plugins/`. |
458
+ | `omniwire_omnimesh` | OmniMesh — built-in WireGuard mesh manager. Init/up/down/add-peer/sync-peers/health/rotate-keys/topology across all OS. |
459
+ | `omniwire_mesh_expose` | Expose localhost-bound services to the entire mesh. Discover/expose/unexpose/expose-remote. |
460
+ | `omniwire_mesh_gateway` | Auto-expose all localhost services mesh-wide. Sync/teardown/add-rule/remove-rule. |
461
+ | `omniwire_events` | Event bus with Webhook + WebSocket + SSE. Publish events, manage webhooks, query log. |
462
+ | `omniwire_knowledge` | CyberBase knowledge CRUD + text/semantic search + health + vacuum + bulk-set + export. |
463
+
423
464
  ### CyberSync (9)
424
465
 
425
466
  | Tool | Description |
@@ -441,7 +482,7 @@ watch(assert="ready") poll until
441
482
 
442
483
  | Operation | Latency | Optimization |
443
484
  |-----------|---------|-------------|
444
- | **Command exec** | **~80ms** | AES-128-GCM cipher, persistent SSH2, zero-fork `:` ping |
485
+ | **Command exec** | **~81ms** | AES-128-GCM cipher, persistent SSH2, zero-fork `:` ping |
445
486
  | **Mesh status** | **~100ms** | Parallel probes, 5s cache, single `/proc` read |
446
487
  | **File read (<1MB)** | **~60ms** | SFTP-first (skips `cat` fork) |
447
488
  | **Transfer (10MB)** | **~120ms** | LZ4 compression (10x faster than gzip) |
@@ -516,6 +557,23 @@ Create `~/.omniwire/mesh.json`:
516
557
 
517
558
  ## Changelog
518
559
 
560
+ <details>
561
+ <summary><b>v3.0.0 -- 81 Tools, CyberBase Persistence, Full Platform</b></summary>
562
+
563
+ **19 new tools**: proxy, dns, backup, container, cert, user, schedule, alert, log_aggregate, benchmark, snippet, alias, trace, doctor, metrics, audit, plugin, cookies, cdp.
564
+
565
+ **CyberBase auto-persistence**: Store, audit, blackboard, cookies all sync to PostgreSQL. pgvector semantic search. 5s statement_timeout on all DB calls.
566
+
567
+ **Architecture**: Priority command queues, smart output truncation, predictive node selection, latency history, connection pool stats.
568
+
569
+ **Security**: Command denylist (blocks rm -rf /, fork bombs, disk wipes). Audit log with CyberBase persistence.
570
+
571
+ **A2A**: Typed message schemas (JSON validation), dead letter queue for failed tasks, pub/sub event filters.
572
+
573
+ **DX**: GitHub Actions CI, bash/zsh/fish shell completions, --json flag, cookie sync to 1Password.
574
+
575
+ </details>
576
+
519
577
  <details>
520
578
  <summary><b>v2.7.0 -- Firewall Engine</b></summary>
521
579
 
@@ -539,7 +597,7 @@ Create `~/.omniwire/mesh.json`:
539
597
  <details>
540
598
  <summary><b>v2.5.1 -- Universal Background Dispatch</b></summary>
541
599
 
542
- **`background: true`** auto-injected into all 56 tools via server-level wrapper. Returns task ID, poll with `omniwire_bg`. New `omniwire_bg` tool for list/poll/result.
600
+ **`background: true`** auto-injected into all 81 tools via server-level wrapper. Returns task ID, poll with `omniwire_bg`. New `omniwire_bg` tool for list/poll/result.
543
601
 
544
602
  </details>
545
603
 
@@ -578,7 +636,7 @@ Security fixes, multi-path SSH failover, CyberBase integration, VaultBridge Obsi
578
636
  ```
579
637
  omniwire/
580
638
  src/
581
- mcp/ MCP server (56 tools, 3 transports)
639
+ mcp/ MCP server (81 tools, 3 transports)
582
640
  nodes/ SSH2 pool, transfer engine, PTY, tunnels
583
641
  sync/ CyberSync + CyberBase (PostgreSQL, Obsidian, encryption)
584
642
  protocol/ Mesh config, types, path parsing
@@ -60,20 +60,24 @@
60
60
  <text x="450" y="130" font-family="'Segoe UI', system-ui, -apple-system, sans-serif" font-size="20" font-weight="400" fill="#8B949E" text-anchor="middle">The infrastructure layer for AI agent swarms</text>
61
61
 
62
62
  <!-- Stats bar -->
63
- <g font-family="'Segoe UI Mono', 'SF Mono', monospace" font-size="13" fill="#59C2FF" opacity="0.7">
64
- <text x="175" y="175" text-anchor="middle">56 MCP Tools</text>
65
- <text x="325" y="175" text-anchor="middle">A2A Protocol</text>
66
- <text x="450" y="175" text-anchor="middle">~80ms Latency</text>
67
- <text x="575" y="175" text-anchor="middle">LZ4 Transfer</text>
68
- <text x="725" y="175" text-anchor="middle">AES-128-GCM</text>
63
+ <g font-family="'Segoe UI Mono', 'SF Mono', monospace" font-size="12" fill="#59C2FF" opacity="0.7">
64
+ <text x="112" y="175" text-anchor="middle">81 MCP Tools</text>
65
+ <text x="250" y="175" text-anchor="middle">A2A Protocol</text>
66
+ <text x="375" y="175" text-anchor="middle">OmniMesh</text>
67
+ <text x="490" y="175" text-anchor="middle">nftables FW</text>
68
+ <text x="612" y="175" text-anchor="middle">CyberBase</text>
69
+ <text x="728" y="175" text-anchor="middle">~80ms</text>
70
+ <text x="815" y="175" text-anchor="middle">v3.1</text>
69
71
  </g>
70
72
 
71
73
  <!-- Separator dots between stats -->
72
74
  <g fill="#59C2FF" opacity="0.3">
73
- <circle cx="250" cy="172" r="2"/>
74
- <circle cx="387" cy="172" r="2"/>
75
- <circle cx="513" cy="172" r="2"/>
76
- <circle cx="650" cy="172" r="2"/>
75
+ <circle cx="182" cy="172" r="1.5"/>
76
+ <circle cx="313" cy="172" r="1.5"/>
77
+ <circle cx="432" cy="172" r="1.5"/>
78
+ <circle cx="550" cy="172" r="1.5"/>
79
+ <circle cx="670" cy="172" r="1.5"/>
80
+ <circle cx="770" cy="172" r="1.5"/>
77
81
  </g>
78
82
 
79
83
  <!-- Bottom wave -->
@@ -53,20 +53,24 @@
53
53
  <text x="450" y="130" font-family="'Segoe UI', system-ui, -apple-system, sans-serif" font-size="20" font-weight="400" fill="#586069" text-anchor="middle">The infrastructure layer for AI agent swarms</text>
54
54
 
55
55
  <!-- Stats bar -->
56
- <g font-family="'Segoe UI Mono', 'SF Mono', monospace" font-size="13" fill="#1A3A5C" opacity="0.6">
57
- <text x="175" y="175" text-anchor="middle">56 MCP Tools</text>
58
- <text x="325" y="175" text-anchor="middle">A2A Protocol</text>
59
- <text x="450" y="175" text-anchor="middle">~80ms Latency</text>
60
- <text x="575" y="175" text-anchor="middle">LZ4 Transfer</text>
61
- <text x="725" y="175" text-anchor="middle">AES-128-GCM</text>
56
+ <g font-family="'Segoe UI Mono', 'SF Mono', monospace" font-size="12" fill="#1A3A5C" opacity="0.6">
57
+ <text x="112" y="175" text-anchor="middle">81 MCP Tools</text>
58
+ <text x="250" y="175" text-anchor="middle">A2A Protocol</text>
59
+ <text x="375" y="175" text-anchor="middle">OmniMesh</text>
60
+ <text x="490" y="175" text-anchor="middle">nftables FW</text>
61
+ <text x="612" y="175" text-anchor="middle">CyberBase</text>
62
+ <text x="728" y="175" text-anchor="middle">~80ms</text>
63
+ <text x="815" y="175" text-anchor="middle">v3.1</text>
62
64
  </g>
63
65
 
64
66
  <!-- Separator dots between stats -->
65
67
  <g fill="#1A3A5C" opacity="0.25">
66
- <circle cx="250" cy="172" r="2"/>
67
- <circle cx="387" cy="172" r="2"/>
68
- <circle cx="513" cy="172" r="2"/>
69
- <circle cx="650" cy="172" r="2"/>
68
+ <circle cx="182" cy="172" r="1.5"/>
69
+ <circle cx="313" cy="172" r="1.5"/>
70
+ <circle cx="432" cy="172" r="1.5"/>
71
+ <circle cx="550" cy="172" r="1.5"/>
72
+ <circle cx="670" cy="172" r="1.5"/>
73
+ <circle cx="770" cy="172" r="1.5"/>
70
74
  </g>
71
75
 
72
76
  <!-- Bottom wave -->
@@ -0,0 +1,53 @@
1
+ import { type ServerResponse } from 'node:http';
2
+ import { WebSocket } from 'ws';
3
+ import { EventEmitter } from 'node:events';
4
+ export interface OmniWireEvent {
5
+ readonly id: string;
6
+ readonly type: OmniWireEventType;
7
+ readonly timestamp: number;
8
+ readonly source: string;
9
+ readonly data: Record<string, unknown>;
10
+ }
11
+ export type OmniWireEventType = 'exec.start' | 'exec.complete' | 'exec.error' | 'node.online' | 'node.offline' | 'node.health' | 'transfer.start' | 'transfer.complete' | 'transfer.error' | 'update.available' | 'update.applied' | 'mesh.peer-added' | 'mesh.peer-removed' | 'mesh.health' | 'sync.start' | 'sync.complete' | 'sync.conflict' | 'alert.fired' | 'alert.resolved' | 'firewall.blocked' | 'firewall.rule-changed' | 'vpn.connected' | 'vpn.disconnected' | 'store.set' | 'store.delete' | 'a2a.message' | 'a2a.task' | 'custom';
12
+ export interface WebhookConfig {
13
+ readonly id: string;
14
+ readonly url: string;
15
+ readonly events: readonly OmniWireEventType[] | '*';
16
+ readonly secret?: string;
17
+ readonly headers?: Record<string, string>;
18
+ readonly retries: number;
19
+ readonly timeoutMs: number;
20
+ readonly active: boolean;
21
+ }
22
+ declare class OmniWireEventBus extends EventEmitter {
23
+ private sseClients;
24
+ private wsClients;
25
+ private webhooks;
26
+ private eventLog;
27
+ private maxLogSize;
28
+ private eventCounter;
29
+ /** Emit an event to all transports */
30
+ emit(type: string, ...args: unknown[]): boolean;
31
+ /** Publish an event to all connected clients (SSE, WS, webhooks) */
32
+ publish(type: OmniWireEventType, source: string, data?: Record<string, unknown>): OmniWireEvent;
33
+ addSSEClient(res: ServerResponse, filter?: readonly OmniWireEventType[]): void;
34
+ private broadcastSSE;
35
+ addWSClient(ws: WebSocket): void;
36
+ private broadcastWS;
37
+ addWebhook(config: WebhookConfig): void;
38
+ removeWebhook(id: string): boolean;
39
+ listWebhooks(): WebhookConfig[];
40
+ private broadcastWebhooks;
41
+ private sendWebhook;
42
+ getRecentEvents(count?: number, filter?: OmniWireEventType): readonly OmniWireEvent[];
43
+ getStats(): {
44
+ sseClients: number;
45
+ wsClients: number;
46
+ webhooks: number;
47
+ totalEvents: number;
48
+ logSize: number;
49
+ };
50
+ }
51
+ export declare const eventBus: OmniWireEventBus;
52
+ export declare function startEventServer(port: number): void;
53
+ export {};
@@ -0,0 +1,317 @@
1
+ // OmniWire Events — Webhook + WebSocket + SSE event bus
2
+ // Unified event system for real-time notifications across all transports
3
+ import { createServer as createHttpServer } from 'node:http';
4
+ import { WebSocketServer, WebSocket } from 'ws';
5
+ import { EventEmitter } from 'node:events';
6
+ // --- Event Bus ---
7
+ class OmniWireEventBus extends EventEmitter {
8
+ sseClients = new Set();
9
+ wsClients = new Set();
10
+ webhooks = new Map();
11
+ eventLog = [];
12
+ maxLogSize = 1000;
13
+ eventCounter = 0;
14
+ /** Emit an event to all transports */
15
+ emit(type, ...args) {
16
+ return super.emit(type, ...args);
17
+ }
18
+ /** Publish an event to all connected clients (SSE, WS, webhooks) */
19
+ publish(type, source, data = {}) {
20
+ const event = {
21
+ id: `evt-${Date.now()}-${++this.eventCounter}`,
22
+ type,
23
+ timestamp: Date.now(),
24
+ source,
25
+ data,
26
+ };
27
+ // Store in log (ring buffer)
28
+ this.eventLog.push(event);
29
+ if (this.eventLog.length > this.maxLogSize) {
30
+ this.eventLog = this.eventLog.slice(-this.maxLogSize);
31
+ }
32
+ // Emit locally
33
+ super.emit(type, event);
34
+ super.emit('*', event);
35
+ // Send to SSE clients
36
+ this.broadcastSSE(event);
37
+ // Send to WebSocket clients
38
+ this.broadcastWS(event);
39
+ // Send to webhooks (fire-and-forget)
40
+ this.broadcastWebhooks(event);
41
+ return event;
42
+ }
43
+ // --- SSE ---
44
+ addSSEClient(res, filter) {
45
+ res.writeHead(200, {
46
+ 'Content-Type': 'text/event-stream',
47
+ 'Cache-Control': 'no-cache',
48
+ 'Connection': 'keep-alive',
49
+ 'Access-Control-Allow-Origin': '*',
50
+ });
51
+ // Send initial connection event
52
+ const init = {
53
+ id: `evt-${Date.now()}-init`,
54
+ type: 'custom',
55
+ timestamp: Date.now(),
56
+ source: 'system',
57
+ data: { message: 'connected', filter: filter ?? '*' },
58
+ };
59
+ res.write(`data: ${JSON.stringify(init)}\n\n`);
60
+ // Tag the response with filter for selective broadcasting
61
+ res.__omniwireFilter = filter;
62
+ this.sseClients.add(res);
63
+ res.on('close', () => this.sseClients.delete(res));
64
+ }
65
+ broadcastSSE(event) {
66
+ const payload = `id: ${event.id}\nevent: ${event.type}\ndata: ${JSON.stringify(event)}\n\n`;
67
+ for (const client of this.sseClients) {
68
+ const filter = client.__omniwireFilter;
69
+ if (!filter || filter.includes(event.type)) {
70
+ try {
71
+ client.write(payload);
72
+ }
73
+ catch {
74
+ this.sseClients.delete(client);
75
+ }
76
+ }
77
+ }
78
+ }
79
+ // --- WebSocket ---
80
+ addWSClient(ws) {
81
+ this.wsClients.add(ws);
82
+ ws.on('close', () => this.wsClients.delete(ws));
83
+ ws.on('error', () => this.wsClients.delete(ws));
84
+ // Handle incoming messages (subscriptions, commands)
85
+ ws.on('message', (data) => {
86
+ try {
87
+ const msg = JSON.parse(data.toString());
88
+ if (msg.type === 'subscribe') {
89
+ ws.__omniwireFilter = msg.events;
90
+ ws.send(JSON.stringify({ type: 'subscribed', events: msg.events }));
91
+ }
92
+ else if (msg.type === 'ping') {
93
+ ws.send(JSON.stringify({ type: 'pong', timestamp: Date.now() }));
94
+ }
95
+ else if (msg.type === 'replay') {
96
+ // Replay recent events
97
+ const count = Math.min(msg.count ?? 50, this.eventLog.length);
98
+ const events = this.eventLog.slice(-count);
99
+ ws.send(JSON.stringify({ type: 'replay', events }));
100
+ }
101
+ }
102
+ catch { /* ignore malformed messages */ }
103
+ });
104
+ // Send connected event
105
+ ws.send(JSON.stringify({ type: 'connected', timestamp: Date.now(), logSize: this.eventLog.length }));
106
+ }
107
+ broadcastWS(event) {
108
+ const payload = JSON.stringify(event);
109
+ for (const ws of this.wsClients) {
110
+ if (ws.readyState !== WebSocket.OPEN) {
111
+ this.wsClients.delete(ws);
112
+ continue;
113
+ }
114
+ const filter = ws.__omniwireFilter;
115
+ if (!filter || filter.includes(event.type)) {
116
+ try {
117
+ ws.send(payload);
118
+ }
119
+ catch {
120
+ this.wsClients.delete(ws);
121
+ }
122
+ }
123
+ }
124
+ }
125
+ // --- Webhooks ---
126
+ addWebhook(config) {
127
+ this.webhooks.set(config.id, config);
128
+ }
129
+ removeWebhook(id) {
130
+ return this.webhooks.delete(id);
131
+ }
132
+ listWebhooks() {
133
+ return [...this.webhooks.values()];
134
+ }
135
+ async broadcastWebhooks(event) {
136
+ for (const webhook of this.webhooks.values()) {
137
+ if (!webhook.active)
138
+ continue;
139
+ if (webhook.events !== '*' && !webhook.events.includes(event.type))
140
+ continue;
141
+ // Fire-and-forget with retries
142
+ void this.sendWebhook(webhook, event);
143
+ }
144
+ }
145
+ async sendWebhook(webhook, event, attempt = 0) {
146
+ try {
147
+ const body = JSON.stringify(event);
148
+ const headers = {
149
+ 'Content-Type': 'application/json',
150
+ 'X-OmniWire-Event': event.type,
151
+ 'X-OmniWire-Event-ID': event.id,
152
+ 'X-OmniWire-Timestamp': String(event.timestamp),
153
+ ...webhook.headers,
154
+ };
155
+ // HMAC signature if secret is configured
156
+ if (webhook.secret) {
157
+ const { createHmac } = await import('node:crypto');
158
+ const sig = createHmac('sha256', webhook.secret).update(body).digest('hex');
159
+ headers['X-OmniWire-Signature'] = `sha256=${sig}`;
160
+ }
161
+ const controller = new AbortController();
162
+ const timeout = setTimeout(() => controller.abort(), webhook.timeoutMs);
163
+ const response = await fetch(webhook.url, {
164
+ method: 'POST',
165
+ headers,
166
+ body,
167
+ signal: controller.signal,
168
+ });
169
+ clearTimeout(timeout);
170
+ if (!response.ok && attempt < webhook.retries) {
171
+ // Exponential backoff: 1s, 2s, 4s
172
+ await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, attempt)));
173
+ return this.sendWebhook(webhook, event, attempt + 1);
174
+ }
175
+ }
176
+ catch {
177
+ if (attempt < webhook.retries) {
178
+ await new Promise((r) => setTimeout(r, 1000 * Math.pow(2, attempt)));
179
+ return this.sendWebhook(webhook, event, attempt + 1);
180
+ }
181
+ }
182
+ }
183
+ // --- Query ---
184
+ getRecentEvents(count = 50, filter) {
185
+ const events = filter ? this.eventLog.filter((e) => e.type === filter) : this.eventLog;
186
+ return events.slice(-count);
187
+ }
188
+ getStats() {
189
+ return {
190
+ sseClients: this.sseClients.size,
191
+ wsClients: this.wsClients.size,
192
+ webhooks: this.webhooks.size,
193
+ totalEvents: this.eventCounter,
194
+ logSize: this.eventLog.length,
195
+ };
196
+ }
197
+ }
198
+ // Singleton event bus
199
+ export const eventBus = new OmniWireEventBus();
200
+ // --- HTTP + WebSocket Server ---
201
+ export function startEventServer(port) {
202
+ const httpServer = createHttpServer((req, res) => {
203
+ res.setHeader('Access-Control-Allow-Origin', '*');
204
+ res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');
205
+ res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
206
+ if (req.method === 'OPTIONS') {
207
+ res.writeHead(204);
208
+ res.end();
209
+ return;
210
+ }
211
+ const url = new URL(req.url ?? '/', `http://localhost:${port}`);
212
+ // GET /events/stream — SSE stream
213
+ if (req.method === 'GET' && url.pathname === '/events/stream') {
214
+ const filterParam = url.searchParams.get('filter');
215
+ const filter = filterParam ? filterParam.split(',') : undefined;
216
+ eventBus.addSSEClient(res, filter);
217
+ return;
218
+ }
219
+ // GET /events/recent — recent events
220
+ if (req.method === 'GET' && url.pathname === '/events/recent') {
221
+ const count = parseInt(url.searchParams.get('count') ?? '50');
222
+ const filter = url.searchParams.get('type');
223
+ const events = eventBus.getRecentEvents(count, filter || undefined);
224
+ res.writeHead(200, { 'Content-Type': 'application/json' });
225
+ res.end(JSON.stringify({ events }));
226
+ return;
227
+ }
228
+ // GET /events/stats — event bus stats
229
+ if (req.method === 'GET' && url.pathname === '/events/stats') {
230
+ res.writeHead(200, { 'Content-Type': 'application/json' });
231
+ res.end(JSON.stringify(eventBus.getStats()));
232
+ return;
233
+ }
234
+ // POST /events/publish — publish custom event
235
+ if (req.method === 'POST' && url.pathname === '/events/publish') {
236
+ let body = '';
237
+ req.on('data', (chunk) => { body += chunk; });
238
+ req.on('end', () => {
239
+ try {
240
+ const { type, source, data } = JSON.parse(body);
241
+ const event = eventBus.publish(type ?? 'custom', source ?? 'api', data ?? {});
242
+ res.writeHead(200, { 'Content-Type': 'application/json' });
243
+ res.end(JSON.stringify(event));
244
+ }
245
+ catch {
246
+ res.writeHead(400, { 'Content-Type': 'application/json' });
247
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
248
+ }
249
+ });
250
+ return;
251
+ }
252
+ // GET /webhooks — list webhooks
253
+ if (req.method === 'GET' && url.pathname === '/webhooks') {
254
+ res.writeHead(200, { 'Content-Type': 'application/json' });
255
+ res.end(JSON.stringify({ webhooks: eventBus.listWebhooks() }));
256
+ return;
257
+ }
258
+ // POST /webhooks — register webhook
259
+ if (req.method === 'POST' && url.pathname === '/webhooks') {
260
+ let body = '';
261
+ req.on('data', (chunk) => { body += chunk; });
262
+ req.on('end', () => {
263
+ try {
264
+ const config = JSON.parse(body);
265
+ if (!config.url) {
266
+ res.writeHead(400, { 'Content-Type': 'application/json' });
267
+ res.end(JSON.stringify({ error: 'url required' }));
268
+ return;
269
+ }
270
+ const webhook = {
271
+ id: config.id ?? `wh-${Date.now()}`,
272
+ url: config.url,
273
+ events: config.events ?? '*',
274
+ secret: config.secret,
275
+ headers: config.headers,
276
+ retries: config.retries ?? 3,
277
+ timeoutMs: config.timeoutMs ?? 5000,
278
+ active: config.active ?? true,
279
+ };
280
+ eventBus.addWebhook(webhook);
281
+ res.writeHead(201, { 'Content-Type': 'application/json' });
282
+ res.end(JSON.stringify(webhook));
283
+ }
284
+ catch {
285
+ res.writeHead(400, { 'Content-Type': 'application/json' });
286
+ res.end(JSON.stringify({ error: 'Invalid JSON' }));
287
+ }
288
+ });
289
+ return;
290
+ }
291
+ // DELETE /webhooks/:id — remove webhook
292
+ const whMatch = url.pathname.match(/^\/webhooks\/(.+)$/);
293
+ if (req.method === 'DELETE' && whMatch) {
294
+ const removed = eventBus.removeWebhook(whMatch[1]);
295
+ res.writeHead(removed ? 200 : 404, { 'Content-Type': 'application/json' });
296
+ res.end(JSON.stringify({ removed }));
297
+ return;
298
+ }
299
+ res.writeHead(404, { 'Content-Type': 'application/json' });
300
+ res.end(JSON.stringify({ error: 'Not found. Endpoints: /events/stream, /events/recent, /events/stats, /events/publish, /webhooks' }));
301
+ });
302
+ // WebSocket upgrade
303
+ const wss = new WebSocketServer({ noServer: true });
304
+ httpServer.on('upgrade', (req, socket, head) => {
305
+ const url = new URL(req.url ?? '/', `http://localhost:${port}`);
306
+ if (url.pathname === '/ws' || url.pathname === '/events/ws') {
307
+ wss.handleUpgrade(req, socket, head, (ws) => {
308
+ eventBus.addWSClient(ws);
309
+ });
310
+ }
311
+ else {
312
+ socket.destroy();
313
+ }
314
+ });
315
+ httpServer.listen(port, '0.0.0.0');
316
+ }
317
+ //# sourceMappingURL=events.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"events.js","sourceRoot":"","sources":["../../src/mcp/events.ts"],"names":[],"mappings":"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"}