genesis-ai-cli 13.7.0 → 13.9.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/.env.example +26 -0
- package/dist/src/bus/event-bus.d.ts +146 -0
- package/dist/src/bus/event-bus.js +296 -0
- package/dist/src/bus/events.d.ts +468 -0
- package/dist/src/bus/events.js +13 -0
- package/dist/src/bus/index.d.ts +77 -0
- package/dist/src/bus/index.js +146 -0
- package/dist/src/causal/index.d.ts +6 -0
- package/dist/src/causal/index.js +30 -6
- package/dist/src/consciousness/central-awareness.d.ts +190 -0
- package/dist/src/consciousness/central-awareness.js +527 -0
- package/dist/src/consciousness/index.d.ts +1 -0
- package/dist/src/consciousness/index.js +7 -1
- package/dist/src/economy/autonomous.js +62 -0
- package/dist/src/economy/cli/boot.d.ts +10 -0
- package/dist/src/economy/cli/boot.js +83 -0
- package/dist/src/economy/cli/status.d.ts +10 -0
- package/dist/src/economy/cli/status.js +60 -0
- package/dist/src/economy/generators/bounty-hunter.d.ts +6 -0
- package/dist/src/economy/generators/bounty-hunter.js +126 -81
- package/dist/src/economy/generators/keeper.d.ts +1 -0
- package/dist/src/economy/generators/keeper.js +181 -53
- package/dist/src/economy/live/alerts.d.ts +81 -0
- package/dist/src/economy/live/alerts.js +343 -0
- package/dist/src/economy/live/balance-monitor.d.ts +76 -0
- package/dist/src/economy/live/balance-monitor.js +198 -0
- package/dist/src/economy/live/boot.js +71 -3
- package/dist/src/economy/live/defi-executor.d.ts +96 -0
- package/dist/src/economy/live/defi-executor.js +519 -0
- package/dist/src/economy/live/emergency.d.ts +101 -0
- package/dist/src/economy/live/emergency.js +340 -0
- package/dist/src/economy/live/gas-manager.d.ts +99 -0
- package/dist/src/economy/live/gas-manager.js +259 -0
- package/dist/src/economy/live/health.d.ts +72 -0
- package/dist/src/economy/live/health.js +423 -0
- package/dist/src/economy/live/index.d.ts +23 -1
- package/dist/src/economy/live/index.js +75 -2
- package/dist/src/economy/live/payment-verifier.d.ts +57 -0
- package/dist/src/economy/live/payment-verifier.js +185 -0
- package/dist/src/economy/live/position-tracker.d.ts +131 -0
- package/dist/src/economy/live/position-tracker.js +296 -0
- package/dist/src/economy/live/price-feeds.d.ts +81 -0
- package/dist/src/economy/live/price-feeds.js +293 -0
- package/dist/src/economy/live/retry.d.ts +129 -0
- package/dist/src/economy/live/retry.js +331 -0
- package/dist/src/economy/live/revenue-tracker.d.ts +92 -0
- package/dist/src/economy/live/revenue-tracker.js +233 -0
- package/dist/src/economy/live/wallet.d.ts +30 -0
- package/dist/src/economy/live/wallet.js +72 -0
- package/dist/src/finance/bus-wiring.d.ts +95 -0
- package/dist/src/finance/bus-wiring.js +416 -0
- package/dist/src/finance/example.d.ts +8 -0
- package/dist/src/finance/example.js +147 -0
- package/dist/src/finance/index.d.ts +73 -0
- package/dist/src/finance/index.js +243 -0
- package/dist/src/finance/integration-test.d.ts +7 -0
- package/dist/src/finance/integration-test.js +191 -0
- package/dist/src/finance/market-data.d.ts +128 -0
- package/dist/src/finance/market-data.js +444 -0
- package/dist/src/finance/polymarket/bus-wiring.d.ts +90 -0
- package/dist/src/finance/polymarket/bus-wiring.js +270 -0
- package/dist/src/finance/polymarket/client.d.ts +65 -0
- package/dist/src/finance/polymarket/client.js +339 -0
- package/dist/src/finance/polymarket/executor.d.ts +113 -0
- package/dist/src/finance/polymarket/executor.js +305 -0
- package/dist/src/finance/polymarket/index.d.ts +132 -0
- package/dist/src/finance/polymarket/index.js +300 -0
- package/dist/src/finance/polymarket/markets.d.ts +98 -0
- package/dist/src/finance/polymarket/markets.js +256 -0
- package/dist/src/finance/polymarket/strategy.d.ts +104 -0
- package/dist/src/finance/polymarket/strategy.js +319 -0
- package/dist/src/finance/polymarket/test.d.ts +13 -0
- package/dist/src/finance/polymarket/test.js +182 -0
- package/dist/src/finance/polymarket/types.d.ts +167 -0
- package/dist/src/finance/polymarket/types.js +14 -0
- package/dist/src/finance/portfolio.d.ts +121 -0
- package/dist/src/finance/portfolio.js +508 -0
- package/dist/src/finance/regime-detector.d.ts +71 -0
- package/dist/src/finance/regime-detector.js +336 -0
- package/dist/src/finance/risk-engine.d.ts +76 -0
- package/dist/src/finance/risk-engine.js +375 -0
- package/dist/src/finance/signals.d.ts +96 -0
- package/dist/src/finance/signals.js +479 -0
- package/dist/src/finance/types.d.ts +299 -0
- package/dist/src/finance/types.js +30 -0
- package/dist/src/genesis.d.ts +127 -0
- package/dist/src/genesis.js +472 -30
- package/dist/src/governance/self-modification.js +18 -3
- package/dist/src/integration/index.d.ts +7 -1
- package/dist/src/integration/index.js +11 -2
- package/dist/src/integration/module-wiring.d.ts +69 -0
- package/dist/src/integration/module-wiring.js +261 -0
- package/dist/src/kernel/free-energy-kernel.d.ts +13 -0
- package/dist/src/kernel/free-energy-kernel.js +48 -4
- package/dist/src/lifecycle/env-validator.d.ts +65 -0
- package/dist/src/lifecycle/env-validator.js +278 -0
- package/dist/src/lifecycle/index.d.ts +12 -0
- package/dist/src/lifecycle/index.js +27 -0
- package/dist/src/lifecycle/rate-limiter.d.ts +97 -0
- package/dist/src/lifecycle/rate-limiter.js +262 -0
- package/dist/src/lifecycle/shutdown-manager.d.ts +132 -0
- package/dist/src/lifecycle/shutdown-manager.js +340 -0
- package/dist/src/llm/index.d.ts +6 -1
- package/dist/src/llm/index.js +96 -32
- package/dist/src/mcp-finance/index.d.ts +97 -0
- package/dist/src/mcp-finance/index.js +269 -0
- package/dist/src/memory/index.d.ts +29 -1
- package/dist/src/memory/index.js +99 -1
- package/dist/src/memory/persistence.js +5 -1
- package/dist/src/neuromodulation/index.d.ts +15 -1
- package/dist/src/neuromodulation/index.js +74 -1
- package/dist/src/payments/x402/client.d.ts +98 -0
- package/dist/src/payments/x402/client.js +361 -0
- package/dist/src/payments/x402/example.d.ts +12 -0
- package/dist/src/payments/x402/example.js +268 -0
- package/dist/src/payments/x402/index.d.ts +102 -0
- package/dist/src/payments/x402/index.js +178 -0
- package/dist/src/payments/x402/pricing.d.ts +106 -0
- package/dist/src/payments/x402/pricing.js +312 -0
- package/dist/src/payments/x402/server.d.ts +101 -0
- package/dist/src/payments/x402/server.js +385 -0
- package/dist/src/payments/x402/types.d.ts +318 -0
- package/dist/src/payments/x402/types.js +31 -0
- package/dist/src/payments/x402/verification.d.ts +94 -0
- package/dist/src/payments/x402/verification.js +338 -0
- package/dist/src/perception/multi-modal.d.ts +10 -0
- package/dist/src/perception/multi-modal.js +29 -2
- package/dist/src/reasoning/metacognitive-controller.d.ts +15 -0
- package/dist/src/reasoning/metacognitive-controller.js +25 -2
- package/dist/src/revenue/bus-wiring.d.ts +79 -0
- package/dist/src/revenue/bus-wiring.js +260 -0
- package/dist/src/revenue/example.d.ts +7 -0
- package/dist/src/revenue/example.js +191 -0
- package/dist/src/revenue/index.d.ts +127 -0
- package/dist/src/revenue/index.js +283 -0
- package/dist/src/revenue/stream-manager.d.ts +97 -0
- package/dist/src/revenue/stream-manager.js +392 -0
- package/dist/src/revenue/streams/bounty-hunter.d.ts +66 -0
- package/dist/src/revenue/streams/bounty-hunter.js +336 -0
- package/dist/src/revenue/streams/content.d.ts +68 -0
- package/dist/src/revenue/streams/content.js +405 -0
- package/dist/src/revenue/streams/keeper.d.ts +62 -0
- package/dist/src/revenue/streams/keeper.js +351 -0
- package/dist/src/revenue/streams/mcp-services.d.ts +73 -0
- package/dist/src/revenue/streams/mcp-services.js +405 -0
- package/dist/src/revenue/streams/yield.d.ts +73 -0
- package/dist/src/revenue/streams/yield.js +469 -0
- package/dist/src/revenue/types.d.ts +177 -0
- package/dist/src/revenue/types.js +9 -0
- package/dist/src/streaming/mcp-bridge.d.ts +2 -0
- package/dist/src/streaming/mcp-bridge.js +5 -1
- package/dist/src/ui/components/agent-network.d.ts +99 -0
- package/dist/src/ui/components/agent-network.js +495 -0
- package/dist/src/ui/components/economy-card.d.ts +110 -0
- package/dist/src/ui/components/economy-card.js +341 -0
- package/dist/src/ui/components/neuromod-display.d.ts +84 -0
- package/dist/src/ui/components/neuromod-display.js +331 -0
- package/dist/src/ui/components/phi-orb.d.ts +72 -0
- package/dist/src/ui/components/phi-orb.js +250 -0
- package/dist/src/ui/example.d.ts +14 -0
- package/dist/src/ui/example.js +187 -0
- package/dist/src/ui/generative/index.d.ts +97 -0
- package/dist/src/ui/generative/index.js +344 -0
- package/dist/src/ui/index.d.ts +131 -0
- package/dist/src/ui/index.js +298 -0
- package/dist/src/ui/sse-client.d.ts +95 -0
- package/dist/src/ui/sse-client.js +297 -0
- package/dist/src/ui/state-mapper.d.ts +94 -0
- package/dist/src/ui/state-mapper.js +525 -0
- package/dist/src/ui/test.d.ts +7 -0
- package/dist/src/ui/test.js +275 -0
- package/dist/src/ui/types.d.ts +129 -0
- package/dist/src/ui/types.js +17 -0
- package/dist/test/active-inference.test.d.ts +10 -0
- package/dist/test/active-inference.test.js +401 -0
- package/dist/test/economy.test.d.ts +10 -0
- package/dist/test/economy.test.js +421 -0
- package/dist/test/lifecycle.test.d.ts +9 -0
- package/dist/test/lifecycle.test.js +496 -0
- package/dist/test/llm.test.d.ts +13 -0
- package/dist/test/llm.test.js +454 -0
- package/dist/test/mcp.test.d.ts +9 -0
- package/dist/test/mcp.test.js +578 -0
- package/dist/test/memory.test.d.ts +9 -0
- package/dist/test/memory.test.js +631 -0
- package/package.json +1 -1
package/.env.example
CHANGED
|
@@ -144,3 +144,29 @@ GENESIS_MAX_DRAWDOWN=0.20
|
|
|
144
144
|
|
|
145
145
|
# Safety: daily spending limit USD (default: 100)
|
|
146
146
|
GENESIS_DAILY_LIMIT=100
|
|
147
|
+
|
|
148
|
+
# ============================================================================
|
|
149
|
+
# v19.0 - MONITORING & ALERTS
|
|
150
|
+
# ============================================================================
|
|
151
|
+
|
|
152
|
+
# Enable/disable alerts (default: true)
|
|
153
|
+
GENESIS_ALERTS_ENABLED=true
|
|
154
|
+
|
|
155
|
+
# Minimum alert level: info, success, warning, error (default: info)
|
|
156
|
+
GENESIS_ALERTS_LEVEL=info
|
|
157
|
+
|
|
158
|
+
# Telegram alerts
|
|
159
|
+
# Create bot via @BotFather, get chat ID via @userinfobot
|
|
160
|
+
GENESIS_TELEGRAM_BOT_TOKEN=
|
|
161
|
+
GENESIS_TELEGRAM_CHAT_ID=
|
|
162
|
+
|
|
163
|
+
# Discord webhook
|
|
164
|
+
# Create in Server Settings → Integrations → Webhooks
|
|
165
|
+
GENESIS_DISCORD_WEBHOOK=
|
|
166
|
+
|
|
167
|
+
# Slack webhook
|
|
168
|
+
# Create in Slack App → Incoming Webhooks
|
|
169
|
+
GENESIS_SLACK_WEBHOOK=
|
|
170
|
+
|
|
171
|
+
# Custom webhook (receives JSON POST)
|
|
172
|
+
GENESIS_ALERT_WEBHOOK=
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Genesis Event Bus - Core Implementation
|
|
3
|
+
*
|
|
4
|
+
* A typed, precision-weighted event bus implementing Global Workspace Theory
|
|
5
|
+
* for inter-module communication in the Genesis cognitive architecture.
|
|
6
|
+
*
|
|
7
|
+
* Features:
|
|
8
|
+
* - Type-safe publish/subscribe with GenesisEventMap
|
|
9
|
+
* - Priority-ordered dispatch (critical handlers first)
|
|
10
|
+
* - Async handler support (non-blocking)
|
|
11
|
+
* - Ring-buffer history for late-joining subscribers
|
|
12
|
+
* - Prefix-based subscriptions for domain monitoring
|
|
13
|
+
* - Memory-safe unsubscription
|
|
14
|
+
* - Correlation IDs for causal tracing
|
|
15
|
+
*
|
|
16
|
+
* Scientific grounding:
|
|
17
|
+
* - Acts as Markov Blanket boundary between modules
|
|
18
|
+
* - Precision field enables reliability-weighted processing
|
|
19
|
+
* - History buffer supports temporal integration
|
|
20
|
+
*/
|
|
21
|
+
import type { GenesisEventMap, GenesisEventTopic, BusEvent } from './events.js';
|
|
22
|
+
/** Handler function type */
|
|
23
|
+
type EventHandler<T extends BusEvent> = (event: T) => void | Promise<void>;
|
|
24
|
+
/** Subscription handle with unsubscribe capability */
|
|
25
|
+
export interface Subscription {
|
|
26
|
+
/** Unique subscription ID */
|
|
27
|
+
id: string;
|
|
28
|
+
/** Topic subscribed to */
|
|
29
|
+
topic: GenesisEventTopic | string;
|
|
30
|
+
/** Remove this subscription */
|
|
31
|
+
unsubscribe: () => void;
|
|
32
|
+
}
|
|
33
|
+
/** Subscribe options */
|
|
34
|
+
export interface SubscribeOptions {
|
|
35
|
+
/** Higher priority = called first. Default 0. */
|
|
36
|
+
priority?: number;
|
|
37
|
+
/** Custom subscription ID */
|
|
38
|
+
id?: string;
|
|
39
|
+
}
|
|
40
|
+
/** History entry */
|
|
41
|
+
interface HistoryEntry {
|
|
42
|
+
topic: string;
|
|
43
|
+
event: BusEvent;
|
|
44
|
+
}
|
|
45
|
+
/** Bus statistics */
|
|
46
|
+
export interface BusStats {
|
|
47
|
+
topics: number;
|
|
48
|
+
totalSubscriptions: number;
|
|
49
|
+
eventsPublished: number;
|
|
50
|
+
historySize: number;
|
|
51
|
+
}
|
|
52
|
+
export declare class GenesisEventBus {
|
|
53
|
+
private seq;
|
|
54
|
+
private subscribers;
|
|
55
|
+
private history;
|
|
56
|
+
private readonly maxHistory;
|
|
57
|
+
private correlationStack;
|
|
58
|
+
constructor(options?: {
|
|
59
|
+
maxHistory?: number;
|
|
60
|
+
});
|
|
61
|
+
/**
|
|
62
|
+
* Publish an event to all subscribers.
|
|
63
|
+
* Synchronous handlers execute in priority order.
|
|
64
|
+
* Async handlers are dispatched but not awaited (fire-and-forget with error logging).
|
|
65
|
+
*
|
|
66
|
+
* @param topic - The event topic
|
|
67
|
+
* @param payload - Event data (seq and timestamp added automatically)
|
|
68
|
+
* @returns The complete event with sequence number
|
|
69
|
+
*/
|
|
70
|
+
publish<K extends GenesisEventTopic>(topic: K, payload: Omit<GenesisEventMap[K], 'seq' | 'timestamp'>): GenesisEventMap[K];
|
|
71
|
+
/**
|
|
72
|
+
* Publish with a specific correlation ID for causal tracing.
|
|
73
|
+
*/
|
|
74
|
+
publishWithCorrelation<K extends GenesisEventTopic>(topic: K, payload: Omit<GenesisEventMap[K], 'seq' | 'timestamp' | 'correlationId'>, correlationId: string): GenesisEventMap[K];
|
|
75
|
+
/**
|
|
76
|
+
* Execute a function within a correlation context.
|
|
77
|
+
* All events published within the callback share the correlation ID.
|
|
78
|
+
*/
|
|
79
|
+
withCorrelation<T>(correlationId: string, fn: () => T): T;
|
|
80
|
+
private currentCorrelation;
|
|
81
|
+
private recordHistory;
|
|
82
|
+
private dispatch;
|
|
83
|
+
/**
|
|
84
|
+
* Subscribe to a specific topic.
|
|
85
|
+
*
|
|
86
|
+
* @param topic - The event topic to subscribe to
|
|
87
|
+
* @param handler - Function called when event is published
|
|
88
|
+
* @param options - Priority and custom ID
|
|
89
|
+
* @returns Subscription with unsubscribe method
|
|
90
|
+
*/
|
|
91
|
+
subscribe<K extends GenesisEventTopic>(topic: K, handler: EventHandler<GenesisEventMap[K]>, options?: SubscribeOptions): Subscription;
|
|
92
|
+
/**
|
|
93
|
+
* Subscribe to multiple topics matching a prefix.
|
|
94
|
+
* E.g., subscribePrefix('kernel.') matches all kernel events.
|
|
95
|
+
*
|
|
96
|
+
* @param prefix - Topic prefix to match
|
|
97
|
+
* @param handler - Function called for matching events
|
|
98
|
+
* @param options - Priority settings
|
|
99
|
+
* @returns Subscription covering all matching topics
|
|
100
|
+
*/
|
|
101
|
+
subscribePrefix(prefix: string, handler: EventHandler<BusEvent>, options?: SubscribeOptions): Subscription;
|
|
102
|
+
/**
|
|
103
|
+
* Subscribe to all events (useful for logging/monitoring).
|
|
104
|
+
*/
|
|
105
|
+
subscribeAll(handler: EventHandler<BusEvent>, options?: SubscribeOptions): Subscription;
|
|
106
|
+
/**
|
|
107
|
+
* One-time subscription that auto-unsubscribes after first event.
|
|
108
|
+
*/
|
|
109
|
+
once<K extends GenesisEventTopic>(topic: K, handler: EventHandler<GenesisEventMap[K]>, options?: SubscribeOptions): Subscription;
|
|
110
|
+
/**
|
|
111
|
+
* Get recent event history (useful for late-joining subscribers).
|
|
112
|
+
*
|
|
113
|
+
* @param topic - Optional topic filter
|
|
114
|
+
* @param limit - Maximum entries to return
|
|
115
|
+
*/
|
|
116
|
+
getHistory(topic?: GenesisEventTopic, limit?: number): HistoryEntry[];
|
|
117
|
+
/**
|
|
118
|
+
* Get events matching a correlation ID.
|
|
119
|
+
*/
|
|
120
|
+
getCorrelatedEvents(correlationId: string): HistoryEntry[];
|
|
121
|
+
/**
|
|
122
|
+
* Wait for a specific event (promise-based).
|
|
123
|
+
*/
|
|
124
|
+
waitFor<K extends GenesisEventTopic>(topic: K, predicate?: (event: GenesisEventMap[K]) => boolean, timeoutMs?: number): Promise<GenesisEventMap[K]>;
|
|
125
|
+
/**
|
|
126
|
+
* List all active topic subscriptions.
|
|
127
|
+
*/
|
|
128
|
+
listTopics(): string[];
|
|
129
|
+
/**
|
|
130
|
+
* Get statistics for monitoring.
|
|
131
|
+
*/
|
|
132
|
+
stats(): BusStats;
|
|
133
|
+
/**
|
|
134
|
+
* Check if a topic has any subscribers.
|
|
135
|
+
*/
|
|
136
|
+
hasSubscribers(topic: GenesisEventTopic): boolean;
|
|
137
|
+
/**
|
|
138
|
+
* Clear all subscriptions (useful for testing).
|
|
139
|
+
*/
|
|
140
|
+
clear(): void;
|
|
141
|
+
/**
|
|
142
|
+
* Clear history only.
|
|
143
|
+
*/
|
|
144
|
+
clearHistory(): void;
|
|
145
|
+
}
|
|
146
|
+
export {};
|
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Genesis Event Bus - Core Implementation
|
|
4
|
+
*
|
|
5
|
+
* A typed, precision-weighted event bus implementing Global Workspace Theory
|
|
6
|
+
* for inter-module communication in the Genesis cognitive architecture.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Type-safe publish/subscribe with GenesisEventMap
|
|
10
|
+
* - Priority-ordered dispatch (critical handlers first)
|
|
11
|
+
* - Async handler support (non-blocking)
|
|
12
|
+
* - Ring-buffer history for late-joining subscribers
|
|
13
|
+
* - Prefix-based subscriptions for domain monitoring
|
|
14
|
+
* - Memory-safe unsubscription
|
|
15
|
+
* - Correlation IDs for causal tracing
|
|
16
|
+
*
|
|
17
|
+
* Scientific grounding:
|
|
18
|
+
* - Acts as Markov Blanket boundary between modules
|
|
19
|
+
* - Precision field enables reliability-weighted processing
|
|
20
|
+
* - History buffer supports temporal integration
|
|
21
|
+
*/
|
|
22
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
23
|
+
exports.GenesisEventBus = void 0;
|
|
24
|
+
// ============================================================================
|
|
25
|
+
// Event Bus Implementation
|
|
26
|
+
// ============================================================================
|
|
27
|
+
class GenesisEventBus {
|
|
28
|
+
seq = 0;
|
|
29
|
+
subscribers = new Map();
|
|
30
|
+
history = [];
|
|
31
|
+
maxHistory;
|
|
32
|
+
correlationStack = [];
|
|
33
|
+
constructor(options) {
|
|
34
|
+
this.maxHistory = options?.maxHistory ?? 500;
|
|
35
|
+
}
|
|
36
|
+
// --------------------------------------------------------------------------
|
|
37
|
+
// Publishing
|
|
38
|
+
// --------------------------------------------------------------------------
|
|
39
|
+
/**
|
|
40
|
+
* Publish an event to all subscribers.
|
|
41
|
+
* Synchronous handlers execute in priority order.
|
|
42
|
+
* Async handlers are dispatched but not awaited (fire-and-forget with error logging).
|
|
43
|
+
*
|
|
44
|
+
* @param topic - The event topic
|
|
45
|
+
* @param payload - Event data (seq and timestamp added automatically)
|
|
46
|
+
* @returns The complete event with sequence number
|
|
47
|
+
*/
|
|
48
|
+
publish(topic, payload) {
|
|
49
|
+
const event = {
|
|
50
|
+
...payload,
|
|
51
|
+
seq: ++this.seq,
|
|
52
|
+
timestamp: new Date().toISOString(),
|
|
53
|
+
correlationId: payload.correlationId ?? this.currentCorrelation(),
|
|
54
|
+
};
|
|
55
|
+
this.recordHistory(topic, event);
|
|
56
|
+
this.dispatch(topic, event);
|
|
57
|
+
return event;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Publish with a specific correlation ID for causal tracing.
|
|
61
|
+
*/
|
|
62
|
+
publishWithCorrelation(topic, payload, correlationId) {
|
|
63
|
+
return this.publish(topic, { ...payload, correlationId });
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Execute a function within a correlation context.
|
|
67
|
+
* All events published within the callback share the correlation ID.
|
|
68
|
+
*/
|
|
69
|
+
withCorrelation(correlationId, fn) {
|
|
70
|
+
this.correlationStack.push(correlationId);
|
|
71
|
+
try {
|
|
72
|
+
return fn();
|
|
73
|
+
}
|
|
74
|
+
finally {
|
|
75
|
+
this.correlationStack.pop();
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
currentCorrelation() {
|
|
79
|
+
return this.correlationStack.length > 0
|
|
80
|
+
? this.correlationStack[this.correlationStack.length - 1]
|
|
81
|
+
: undefined;
|
|
82
|
+
}
|
|
83
|
+
recordHistory(topic, event) {
|
|
84
|
+
this.history.push({ topic, event });
|
|
85
|
+
if (this.history.length > this.maxHistory) {
|
|
86
|
+
this.history.shift();
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
dispatch(topic, event) {
|
|
90
|
+
const subs = this.subscribers.get(topic);
|
|
91
|
+
if (!subs || subs.size === 0)
|
|
92
|
+
return;
|
|
93
|
+
// Sort by priority (descending)
|
|
94
|
+
const sorted = [...subs.values()].sort((a, b) => b.priority - a.priority);
|
|
95
|
+
for (const sub of sorted) {
|
|
96
|
+
try {
|
|
97
|
+
const result = sub.handler(event);
|
|
98
|
+
if (result instanceof Promise) {
|
|
99
|
+
result.catch((err) => {
|
|
100
|
+
console.error(`[EventBus] Async handler error on ${topic}:`, err);
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
console.error(`[EventBus] Sync handler error on ${topic}:`, err);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
// --------------------------------------------------------------------------
|
|
110
|
+
// Subscribing
|
|
111
|
+
// --------------------------------------------------------------------------
|
|
112
|
+
/**
|
|
113
|
+
* Subscribe to a specific topic.
|
|
114
|
+
*
|
|
115
|
+
* @param topic - The event topic to subscribe to
|
|
116
|
+
* @param handler - Function called when event is published
|
|
117
|
+
* @param options - Priority and custom ID
|
|
118
|
+
* @returns Subscription with unsubscribe method
|
|
119
|
+
*/
|
|
120
|
+
subscribe(topic, handler, options) {
|
|
121
|
+
const id = options?.id ?? `sub-${++this.seq}`;
|
|
122
|
+
const priority = options?.priority ?? 0;
|
|
123
|
+
if (!this.subscribers.has(topic)) {
|
|
124
|
+
this.subscribers.set(topic, new Map());
|
|
125
|
+
}
|
|
126
|
+
this.subscribers.get(topic).set(id, {
|
|
127
|
+
handler,
|
|
128
|
+
priority,
|
|
129
|
+
async: true,
|
|
130
|
+
});
|
|
131
|
+
return {
|
|
132
|
+
id,
|
|
133
|
+
topic,
|
|
134
|
+
unsubscribe: () => {
|
|
135
|
+
this.subscribers.get(topic)?.delete(id);
|
|
136
|
+
},
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
/**
|
|
140
|
+
* Subscribe to multiple topics matching a prefix.
|
|
141
|
+
* E.g., subscribePrefix('kernel.') matches all kernel events.
|
|
142
|
+
*
|
|
143
|
+
* @param prefix - Topic prefix to match
|
|
144
|
+
* @param handler - Function called for matching events
|
|
145
|
+
* @param options - Priority settings
|
|
146
|
+
* @returns Subscription covering all matching topics
|
|
147
|
+
*/
|
|
148
|
+
subscribePrefix(prefix, handler, options) {
|
|
149
|
+
const id = options?.id ?? `prefix-${++this.seq}`;
|
|
150
|
+
const priority = options?.priority ?? 0;
|
|
151
|
+
// Store as a special prefix subscription
|
|
152
|
+
const prefixKey = `__prefix__${prefix}`;
|
|
153
|
+
if (!this.subscribers.has(prefixKey)) {
|
|
154
|
+
this.subscribers.set(prefixKey, new Map());
|
|
155
|
+
}
|
|
156
|
+
this.subscribers.get(prefixKey).set(id, {
|
|
157
|
+
handler,
|
|
158
|
+
priority,
|
|
159
|
+
async: true,
|
|
160
|
+
});
|
|
161
|
+
// Override dispatch to check prefixes
|
|
162
|
+
const originalDispatch = this.dispatch.bind(this);
|
|
163
|
+
this.dispatch = (topic, event) => {
|
|
164
|
+
originalDispatch(topic, event);
|
|
165
|
+
// Check prefix subscriptions
|
|
166
|
+
for (const [key, subs] of this.subscribers) {
|
|
167
|
+
if (key.startsWith('__prefix__')) {
|
|
168
|
+
const p = key.slice('__prefix__'.length);
|
|
169
|
+
if (topic.startsWith(p)) {
|
|
170
|
+
for (const sub of subs.values()) {
|
|
171
|
+
try {
|
|
172
|
+
const result = sub.handler(event);
|
|
173
|
+
if (result instanceof Promise) {
|
|
174
|
+
result.catch((err) => {
|
|
175
|
+
console.error(`[EventBus] Prefix handler error:`, err);
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
catch (err) {
|
|
180
|
+
console.error(`[EventBus] Prefix handler error:`, err);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
};
|
|
187
|
+
return {
|
|
188
|
+
id,
|
|
189
|
+
topic: prefix,
|
|
190
|
+
unsubscribe: () => {
|
|
191
|
+
this.subscribers.get(prefixKey)?.delete(id);
|
|
192
|
+
},
|
|
193
|
+
};
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Subscribe to all events (useful for logging/monitoring).
|
|
197
|
+
*/
|
|
198
|
+
subscribeAll(handler, options) {
|
|
199
|
+
return this.subscribePrefix('', handler, options);
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* One-time subscription that auto-unsubscribes after first event.
|
|
203
|
+
*/
|
|
204
|
+
once(topic, handler, options) {
|
|
205
|
+
const sub = this.subscribe(topic, (event) => {
|
|
206
|
+
sub.unsubscribe();
|
|
207
|
+
return handler(event);
|
|
208
|
+
}, options);
|
|
209
|
+
return sub;
|
|
210
|
+
}
|
|
211
|
+
// --------------------------------------------------------------------------
|
|
212
|
+
// History & Introspection
|
|
213
|
+
// --------------------------------------------------------------------------
|
|
214
|
+
/**
|
|
215
|
+
* Get recent event history (useful for late-joining subscribers).
|
|
216
|
+
*
|
|
217
|
+
* @param topic - Optional topic filter
|
|
218
|
+
* @param limit - Maximum entries to return
|
|
219
|
+
*/
|
|
220
|
+
getHistory(topic, limit = 50) {
|
|
221
|
+
const filtered = topic
|
|
222
|
+
? this.history.filter((h) => h.topic === topic)
|
|
223
|
+
: this.history;
|
|
224
|
+
return filtered.slice(-limit);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Get events matching a correlation ID.
|
|
228
|
+
*/
|
|
229
|
+
getCorrelatedEvents(correlationId) {
|
|
230
|
+
return this.history.filter((h) => h.event.correlationId === correlationId);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Wait for a specific event (promise-based).
|
|
234
|
+
*/
|
|
235
|
+
waitFor(topic, predicate, timeoutMs = 30000) {
|
|
236
|
+
return new Promise((resolve, reject) => {
|
|
237
|
+
const timeout = setTimeout(() => {
|
|
238
|
+
sub.unsubscribe();
|
|
239
|
+
reject(new Error(`Timeout waiting for ${topic}`));
|
|
240
|
+
}, timeoutMs);
|
|
241
|
+
const sub = this.subscribe(topic, (event) => {
|
|
242
|
+
if (!predicate || predicate(event)) {
|
|
243
|
+
clearTimeout(timeout);
|
|
244
|
+
sub.unsubscribe();
|
|
245
|
+
resolve(event);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
});
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* List all active topic subscriptions.
|
|
252
|
+
*/
|
|
253
|
+
listTopics() {
|
|
254
|
+
return [...this.subscribers.keys()].filter((k) => !k.startsWith('__prefix__'));
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Get statistics for monitoring.
|
|
258
|
+
*/
|
|
259
|
+
stats() {
|
|
260
|
+
let totalSubs = 0;
|
|
261
|
+
for (const subs of this.subscribers.values()) {
|
|
262
|
+
totalSubs += subs.size;
|
|
263
|
+
}
|
|
264
|
+
return {
|
|
265
|
+
topics: this.listTopics().length,
|
|
266
|
+
totalSubscriptions: totalSubs,
|
|
267
|
+
eventsPublished: this.seq,
|
|
268
|
+
historySize: this.history.length,
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Check if a topic has any subscribers.
|
|
273
|
+
*/
|
|
274
|
+
hasSubscribers(topic) {
|
|
275
|
+
const subs = this.subscribers.get(topic);
|
|
276
|
+
return subs !== undefined && subs.size > 0;
|
|
277
|
+
}
|
|
278
|
+
// --------------------------------------------------------------------------
|
|
279
|
+
// Lifecycle
|
|
280
|
+
// --------------------------------------------------------------------------
|
|
281
|
+
/**
|
|
282
|
+
* Clear all subscriptions (useful for testing).
|
|
283
|
+
*/
|
|
284
|
+
clear() {
|
|
285
|
+
this.subscribers.clear();
|
|
286
|
+
this.history = [];
|
|
287
|
+
this.correlationStack = [];
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Clear history only.
|
|
291
|
+
*/
|
|
292
|
+
clearHistory() {
|
|
293
|
+
this.history = [];
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
exports.GenesisEventBus = GenesisEventBus;
|