openclaw-event-server-plugin 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.
Files changed (209) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +473 -0
  3. package/config.example.json +203 -0
  4. package/dist/broadcast/index.d.ts +3 -0
  5. package/dist/broadcast/index.d.ts.map +1 -0
  6. package/dist/broadcast/index.js +19 -0
  7. package/dist/broadcast/index.js.map +1 -0
  8. package/dist/broadcast/queue.d.ts +63 -0
  9. package/dist/broadcast/queue.d.ts.map +1 -0
  10. package/dist/broadcast/queue.js +259 -0
  11. package/dist/broadcast/queue.js.map +1 -0
  12. package/dist/broadcast/webhook.d.ts +30 -0
  13. package/dist/broadcast/webhook.d.ts.map +1 -0
  14. package/dist/broadcast/webhook.js +184 -0
  15. package/dist/broadcast/webhook.js.map +1 -0
  16. package/dist/broadcast/websocketServer.d.ts +90 -0
  17. package/dist/broadcast/websocketServer.d.ts.map +1 -0
  18. package/dist/broadcast/websocketServer.js +403 -0
  19. package/dist/broadcast/websocketServer.js.map +1 -0
  20. package/dist/config/config-types.d.ts +280 -0
  21. package/dist/config/config-types.d.ts.map +1 -0
  22. package/dist/config/config-types.js +3 -0
  23. package/dist/config/config-types.js.map +1 -0
  24. package/dist/config/default-config.d.ts +3 -0
  25. package/dist/config/default-config.d.ts.map +1 -0
  26. package/dist/config/default-config.js +136 -0
  27. package/dist/config/default-config.js.map +1 -0
  28. package/dist/config/env.d.ts +6 -0
  29. package/dist/config/env.d.ts.map +1 -0
  30. package/dist/config/env.js +160 -0
  31. package/dist/config/env.js.map +1 -0
  32. package/dist/config/event-types.d.ts +5 -0
  33. package/dist/config/event-types.d.ts.map +1 -0
  34. package/dist/config/event-types.js +54 -0
  35. package/dist/config/event-types.js.map +1 -0
  36. package/dist/config/handler.d.ts +9 -0
  37. package/dist/config/handler.d.ts.map +1 -0
  38. package/dist/config/handler.js +17 -0
  39. package/dist/config/handler.js.map +1 -0
  40. package/dist/config/helpers.d.ts +5 -0
  41. package/dist/config/helpers.d.ts.map +1 -0
  42. package/dist/config/helpers.js +40 -0
  43. package/dist/config/helpers.js.map +1 -0
  44. package/dist/config/index.d.ts +3 -0
  45. package/dist/config/index.d.ts.map +1 -0
  46. package/dist/config/index.js +19 -0
  47. package/dist/config/index.js.map +1 -0
  48. package/dist/config/merge.d.ts +6 -0
  49. package/dist/config/merge.d.ts.map +1 -0
  50. package/dist/config/merge.js +108 -0
  51. package/dist/config/merge.js.map +1 -0
  52. package/dist/config/schema-hook-bridge.d.ts +594 -0
  53. package/dist/config/schema-hook-bridge.d.ts.map +1 -0
  54. package/dist/config/schema-hook-bridge.js +423 -0
  55. package/dist/config/schema-hook-bridge.js.map +1 -0
  56. package/dist/config/schema.d.ts +915 -0
  57. package/dist/config/schema.d.ts.map +1 -0
  58. package/dist/config/schema.js +323 -0
  59. package/dist/config/schema.js.map +1 -0
  60. package/dist/config/types.d.ts +9 -0
  61. package/dist/config/types.d.ts.map +1 -0
  62. package/dist/config/types.js +28 -0
  63. package/dist/config/types.js.map +1 -0
  64. package/dist/config/validate-hook-bridge.d.ts +3 -0
  65. package/dist/config/validate-hook-bridge.d.ts.map +1 -0
  66. package/dist/config/validate-hook-bridge.js +246 -0
  67. package/dist/config/validate-hook-bridge.js.map +1 -0
  68. package/dist/config/validate.d.ts +17 -0
  69. package/dist/config/validate.d.ts.map +1 -0
  70. package/dist/config/validate.js +194 -0
  71. package/dist/config/validate.js.map +1 -0
  72. package/dist/events/index.d.ts +4 -0
  73. package/dist/events/index.d.ts.map +1 -0
  74. package/dist/events/index.js +20 -0
  75. package/dist/events/index.js.map +1 -0
  76. package/dist/events/redaction.d.ts +5 -0
  77. package/dist/events/redaction.d.ts.map +1 -0
  78. package/dist/events/redaction.js +46 -0
  79. package/dist/events/redaction.js.map +1 -0
  80. package/dist/events/signing.d.ts +8 -0
  81. package/dist/events/signing.d.ts.map +1 -0
  82. package/dist/events/signing.js +35 -0
  83. package/dist/events/signing.js.map +1 -0
  84. package/dist/events/types.d.ts +125 -0
  85. package/dist/events/types.d.ts.map +1 -0
  86. package/dist/events/types.js +9 -0
  87. package/dist/events/types.js.map +1 -0
  88. package/dist/hooks/agent-hooks.d.ts +59 -0
  89. package/dist/hooks/agent-hooks.d.ts.map +1 -0
  90. package/dist/hooks/agent-hooks.js +116 -0
  91. package/dist/hooks/agent-hooks.js.map +1 -0
  92. package/dist/hooks/command-hooks.d.ts +13 -0
  93. package/dist/hooks/command-hooks.d.ts.map +1 -0
  94. package/dist/hooks/command-hooks.js +26 -0
  95. package/dist/hooks/command-hooks.js.map +1 -0
  96. package/dist/hooks/event-factory.d.ts +21 -0
  97. package/dist/hooks/event-factory.d.ts.map +1 -0
  98. package/dist/hooks/event-factory.js +31 -0
  99. package/dist/hooks/event-factory.js.map +1 -0
  100. package/dist/hooks/gateway-hooks.d.ts +14 -0
  101. package/dist/hooks/gateway-hooks.d.ts.map +1 -0
  102. package/dist/hooks/gateway-hooks.js +43 -0
  103. package/dist/hooks/gateway-hooks.js.map +1 -0
  104. package/dist/hooks/index.d.ts +10 -0
  105. package/dist/hooks/index.d.ts.map +1 -0
  106. package/dist/hooks/index.js +26 -0
  107. package/dist/hooks/index.js.map +1 -0
  108. package/dist/hooks/message-hooks.d.ts +33 -0
  109. package/dist/hooks/message-hooks.d.ts.map +1 -0
  110. package/dist/hooks/message-hooks.js +208 -0
  111. package/dist/hooks/message-hooks.js.map +1 -0
  112. package/dist/hooks/session-hooks.d.ts +89 -0
  113. package/dist/hooks/session-hooks.d.ts.map +1 -0
  114. package/dist/hooks/session-hooks.js +253 -0
  115. package/dist/hooks/session-hooks.js.map +1 -0
  116. package/dist/hooks/status-reducer.d.ts +30 -0
  117. package/dist/hooks/status-reducer.d.ts.map +1 -0
  118. package/dist/hooks/status-reducer.js +157 -0
  119. package/dist/hooks/status-reducer.js.map +1 -0
  120. package/dist/hooks/subagent-hooks.d.ts +37 -0
  121. package/dist/hooks/subagent-hooks.d.ts.map +1 -0
  122. package/dist/hooks/subagent-hooks.js +79 -0
  123. package/dist/hooks/subagent-hooks.js.map +1 -0
  124. package/dist/hooks/subagent-tracker.d.ts +33 -0
  125. package/dist/hooks/subagent-tracker.d.ts.map +1 -0
  126. package/dist/hooks/subagent-tracker.js +73 -0
  127. package/dist/hooks/subagent-tracker.js.map +1 -0
  128. package/dist/hooks/tool-hooks.d.ts +132 -0
  129. package/dist/hooks/tool-hooks.d.ts.map +1 -0
  130. package/dist/hooks/tool-hooks.js +215 -0
  131. package/dist/hooks/tool-hooks.js.map +1 -0
  132. package/dist/index.d.ts +929 -0
  133. package/dist/index.d.ts.map +1 -0
  134. package/dist/index.js +236 -0
  135. package/dist/index.js.map +1 -0
  136. package/dist/logging/event-file-logger.d.ts +21 -0
  137. package/dist/logging/event-file-logger.d.ts.map +1 -0
  138. package/dist/logging/event-file-logger.js +167 -0
  139. package/dist/logging/event-file-logger.js.map +1 -0
  140. package/dist/logging/index.d.ts +3 -0
  141. package/dist/logging/index.d.ts.map +1 -0
  142. package/dist/logging/index.js +19 -0
  143. package/dist/logging/index.js.map +1 -0
  144. package/dist/logging/runtime-logger.d.ts +12 -0
  145. package/dist/logging/runtime-logger.d.ts.map +1 -0
  146. package/dist/logging/runtime-logger.js +45 -0
  147. package/dist/logging/runtime-logger.js.map +1 -0
  148. package/dist/runtime/hook-bridge-actions.d.ts +9 -0
  149. package/dist/runtime/hook-bridge-actions.d.ts.map +1 -0
  150. package/dist/runtime/hook-bridge-actions.js +248 -0
  151. package/dist/runtime/hook-bridge-actions.js.map +1 -0
  152. package/dist/runtime/hook-bridge-dispatch-engine.d.ts +42 -0
  153. package/dist/runtime/hook-bridge-dispatch-engine.d.ts.map +1 -0
  154. package/dist/runtime/hook-bridge-dispatch-engine.js +233 -0
  155. package/dist/runtime/hook-bridge-dispatch-engine.js.map +1 -0
  156. package/dist/runtime/hook-bridge-tool-guard.d.ts +16 -0
  157. package/dist/runtime/hook-bridge-tool-guard.d.ts.map +1 -0
  158. package/dist/runtime/hook-bridge-tool-guard.js +236 -0
  159. package/dist/runtime/hook-bridge-tool-guard.js.map +1 -0
  160. package/dist/runtime/hook-bridge-utils.d.ts +11 -0
  161. package/dist/runtime/hook-bridge-utils.d.ts.map +1 -0
  162. package/dist/runtime/hook-bridge-utils.js +116 -0
  163. package/dist/runtime/hook-bridge-utils.js.map +1 -0
  164. package/dist/runtime/hook-bridge.d.ts +33 -0
  165. package/dist/runtime/hook-bridge.d.ts.map +1 -0
  166. package/dist/runtime/hook-bridge.js +359 -0
  167. package/dist/runtime/hook-bridge.js.map +1 -0
  168. package/dist/runtime/internal-handlers.d.ts +20 -0
  169. package/dist/runtime/internal-handlers.d.ts.map +1 -0
  170. package/dist/runtime/internal-handlers.js +225 -0
  171. package/dist/runtime/internal-handlers.js.map +1 -0
  172. package/dist/runtime/register-gateway-hooks.d.ts +4 -0
  173. package/dist/runtime/register-gateway-hooks.d.ts.map +1 -0
  174. package/dist/runtime/register-gateway-hooks.js +27 -0
  175. package/dist/runtime/register-gateway-hooks.js.map +1 -0
  176. package/dist/runtime/register-session-hooks.d.ts +4 -0
  177. package/dist/runtime/register-session-hooks.d.ts.map +1 -0
  178. package/dist/runtime/register-session-hooks.js +88 -0
  179. package/dist/runtime/register-session-hooks.js.map +1 -0
  180. package/dist/runtime/register-subagent-hooks.d.ts +4 -0
  181. package/dist/runtime/register-subagent-hooks.d.ts.map +1 -0
  182. package/dist/runtime/register-subagent-hooks.js +143 -0
  183. package/dist/runtime/register-subagent-hooks.js.map +1 -0
  184. package/dist/runtime/register-tool-hooks.d.ts +4 -0
  185. package/dist/runtime/register-tool-hooks.d.ts.map +1 -0
  186. package/dist/runtime/register-tool-hooks.js +348 -0
  187. package/dist/runtime/register-tool-hooks.js.map +1 -0
  188. package/dist/runtime/runtime-events.d.ts +14 -0
  189. package/dist/runtime/runtime-events.d.ts.map +1 -0
  190. package/dist/runtime/runtime-events.js +166 -0
  191. package/dist/runtime/runtime-events.js.map +1 -0
  192. package/dist/runtime/typed-hooks.d.ts +9 -0
  193. package/dist/runtime/typed-hooks.d.ts.map +1 -0
  194. package/dist/runtime/typed-hooks.js +14 -0
  195. package/dist/runtime/typed-hooks.js.map +1 -0
  196. package/dist/runtime/types.d.ts +91 -0
  197. package/dist/runtime/types.d.ts.map +1 -0
  198. package/dist/runtime/types.js +3 -0
  199. package/dist/runtime/types.js.map +1 -0
  200. package/dist/runtime/utils.d.ts +47 -0
  201. package/dist/runtime/utils.d.ts.map +1 -0
  202. package/dist/runtime/utils.js +166 -0
  203. package/dist/runtime/utils.js.map +1 -0
  204. package/dist/tools/replay-tool-guard.d.ts +3 -0
  205. package/dist/tools/replay-tool-guard.d.ts.map +1 -0
  206. package/dist/tools/replay-tool-guard.js +96 -0
  207. package/dist/tools/replay-tool-guard.js.map +1 -0
  208. package/openclaw.plugin.json +847 -0
  209. package/package.json +63 -0
@@ -0,0 +1,3 @@
1
+ export * from './webhook';
2
+ export * from './queue';
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/broadcast/index.ts"],"names":[],"mappings":"AAAA,cAAc,WAAW,CAAC;AAC1B,cAAc,SAAS,CAAC"}
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ __exportStar(require("./webhook"), exports);
18
+ __exportStar(require("./queue"), exports);
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/broadcast/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;AAAA,4CAA0B;AAC1B,0CAAwB"}
@@ -0,0 +1,63 @@
1
+ /**
2
+ * Event queue for reliable delivery
3
+ */
4
+ import { OpenClawEvent, QueueConfig, WebhookConfig, RetryConfig } from '../events/types';
5
+ import { DeliveryResult } from './webhook';
6
+ /**
7
+ * Event queue manager
8
+ */
9
+ export declare class EventQueue {
10
+ private queue;
11
+ private maxSize;
12
+ private flushIntervalMs;
13
+ private persistToDisk;
14
+ private persistPath?;
15
+ private flushTimer?;
16
+ private webhooks;
17
+ private retryConfig;
18
+ private timeoutMs;
19
+ private correlationIdHeader;
20
+ private isFlushing;
21
+ private persistChain;
22
+ private persistSequence;
23
+ constructor(config: QueueConfig, webhooks: WebhookConfig[], retryConfig: RetryConfig, timeoutMs: number, correlationIdHeader: string);
24
+ /**
25
+ * Add event to queue
26
+ */
27
+ enqueue(event: OpenClawEvent): boolean;
28
+ /**
29
+ * Flush queue to webhooks
30
+ */
31
+ flush(): Promise<DeliveryResult[]>;
32
+ /**
33
+ * Get queue statistics
34
+ */
35
+ getStats(): {
36
+ size: number;
37
+ maxSize: number;
38
+ oldestEventAge: number;
39
+ isFlushing: boolean;
40
+ };
41
+ /**
42
+ * Clear the queue
43
+ */
44
+ clear(): void;
45
+ /**
46
+ * Update webhooks configuration
47
+ */
48
+ updateWebhooks(webhooks: WebhookConfig[]): void;
49
+ /**
50
+ * Start the periodic flush timer
51
+ */
52
+ private startFlushTimer;
53
+ /**
54
+ * Stop the flush timer
55
+ */
56
+ stop(): void;
57
+ private getPersistPath;
58
+ private loadPersistedQueue;
59
+ private mergeRestoredQueue;
60
+ private persistQueue;
61
+ private writeQueueAtomically;
62
+ }
63
+ //# sourceMappingURL=queue.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.d.ts","sourceRoot":"","sources":["../../src/broadcast/queue.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,aAAa,EAAE,WAAW,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AACzF,OAAO,EAAuB,cAAc,EAAE,MAAM,WAAW,CAAC;AAiChE;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,aAAa,CAAU;IAC/B,OAAO,CAAC,WAAW,CAAC,CAAS;IAC7B,OAAO,CAAC,UAAU,CAAC,CAAiB;IACpC,OAAO,CAAC,QAAQ,CAAuB;IACvC,OAAO,CAAC,WAAW,CAAc;IACjC,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,mBAAmB,CAAS;IACpC,OAAO,CAAC,UAAU,CAAS;IAC3B,OAAO,CAAC,YAAY,CAAoC;IACxD,OAAO,CAAC,eAAe,CAAK;gBAG1B,MAAM,EAAE,WAAW,EACnB,QAAQ,EAAE,aAAa,EAAE,EACzB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,MAAM;IAsB7B;;OAEG;IACH,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG,OAAO;IAuBtC;;OAEG;IACG,KAAK,IAAI,OAAO,CAAC,cAAc,EAAE,CAAC;IAwDxC;;OAEG;IACH,QAAQ,IAAI;QACV,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,cAAc,EAAE,MAAM,CAAC;QACvB,UAAU,EAAE,OAAO,CAAC;KACrB;IAUD;;OAEG;IACH,KAAK,IAAI,IAAI;IAKb;;OAEG;IACH,cAAc,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,IAAI;IAuB/C;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACH,IAAI,IAAI,IAAI;IAQZ,OAAO,CAAC,cAAc;YAIR,kBAAkB;IAiBhC,OAAO,CAAC,kBAAkB;YAkBZ,YAAY;YAeZ,oBAAoB;CAanC"}
@@ -0,0 +1,259 @@
1
+ "use strict";
2
+ /**
3
+ * Event queue for reliable delivery
4
+ */
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.EventQueue = void 0;
7
+ const promises_1 = require("node:fs/promises");
8
+ const webhook_1 = require("./webhook");
9
+ const logging_1 = require("../logging");
10
+ function isRecord(value) {
11
+ return typeof value === 'object' && value !== null;
12
+ }
13
+ function isQueuedEvent(value) {
14
+ if (!isRecord(value)) {
15
+ return false;
16
+ }
17
+ const event = value.event;
18
+ return (typeof value.enqueuedAt === 'number' &&
19
+ typeof value.attempts === 'number' &&
20
+ isRecord(event) &&
21
+ typeof event.eventId === 'string' &&
22
+ typeof event.type === 'string' &&
23
+ typeof event.timestamp === 'string');
24
+ }
25
+ /**
26
+ * Event queue manager
27
+ */
28
+ class EventQueue {
29
+ queue = [];
30
+ maxSize;
31
+ flushIntervalMs;
32
+ persistToDisk;
33
+ persistPath;
34
+ flushTimer;
35
+ webhooks = [];
36
+ retryConfig;
37
+ timeoutMs;
38
+ correlationIdHeader;
39
+ isFlushing = false;
40
+ persistChain = Promise.resolve();
41
+ persistSequence = 0;
42
+ constructor(config, webhooks, retryConfig, timeoutMs, correlationIdHeader) {
43
+ this.maxSize = config.maxSize;
44
+ this.flushIntervalMs = config.flushIntervalMs;
45
+ this.persistToDisk = config.persistToDisk;
46
+ this.persistPath = config.persistPath;
47
+ this.webhooks = webhooks;
48
+ this.retryConfig = retryConfig;
49
+ this.timeoutMs = timeoutMs;
50
+ this.correlationIdHeader = correlationIdHeader;
51
+ if (this.persistToDisk) {
52
+ void this.loadPersistedQueue().finally(() => {
53
+ this.startFlushTimer();
54
+ });
55
+ return;
56
+ }
57
+ // Start periodic flush
58
+ this.startFlushTimer();
59
+ }
60
+ /**
61
+ * Add event to queue
62
+ */
63
+ enqueue(event) {
64
+ if (this.queue.length >= this.maxSize) {
65
+ // Queue is full, drop oldest event
66
+ this.queue.shift();
67
+ }
68
+ this.queue.push({
69
+ event,
70
+ enqueuedAt: Date.now(),
71
+ attempts: 0,
72
+ });
73
+ // Trigger immediate flush if queue is getting large
74
+ if (this.queue.length >= this.maxSize * 0.8) {
75
+ this.flush().catch((error) => {
76
+ (0, logging_1.getRuntimeLogger)().error('[EventQueue] Flush failed:', (0, logging_1.getErrorMessage)(error));
77
+ });
78
+ }
79
+ void this.persistQueue();
80
+ return true;
81
+ }
82
+ /**
83
+ * Flush queue to webhooks
84
+ */
85
+ async flush() {
86
+ if (this.isFlushing || this.queue.length === 0) {
87
+ return [];
88
+ }
89
+ this.isFlushing = true;
90
+ const results = [];
91
+ try {
92
+ // Process events in batches - collect indices to remove after processing
93
+ const batchSize = 10;
94
+ const indicesToRemove = [];
95
+ for (let i = 0; i < this.queue.length; i += batchSize) {
96
+ const batch = this.queue.slice(i, i + batchSize);
97
+ const batchResults = await Promise.all(batch.map(async (queuedEvent, batchIndex) => {
98
+ const deliveryResults = await (0, webhook_1.broadcastToWebhooks)(queuedEvent.event, this.webhooks, this.retryConfig, this.timeoutMs, this.correlationIdHeader);
99
+ // Check if all webhooks failed. If no webhooks exist, remove event.
100
+ const allFailed = deliveryResults.length > 0 && deliveryResults.every((result) => !result.success);
101
+ if (allFailed && queuedEvent.attempts < this.retryConfig.maxAttempts) {
102
+ // Re-queue for later retry
103
+ queuedEvent.attempts++;
104
+ queuedEvent.lastError = deliveryResults[0]?.error;
105
+ return deliveryResults;
106
+ }
107
+ // Mark for removal (success, max attempts reached, or no webhooks)
108
+ indicesToRemove.push(i + batchIndex);
109
+ return deliveryResults;
110
+ }));
111
+ results.push(...batchResults.flat());
112
+ }
113
+ // Remove processed events from queue (in reverse order to preserve indices)
114
+ for (let i = indicesToRemove.length - 1; i >= 0; i--) {
115
+ this.queue.splice(indicesToRemove[i], 1);
116
+ }
117
+ await this.persistQueue();
118
+ }
119
+ finally {
120
+ this.isFlushing = false;
121
+ }
122
+ return results;
123
+ }
124
+ /**
125
+ * Get queue statistics
126
+ */
127
+ getStats() {
128
+ const oldestEvent = this.queue[0];
129
+ return {
130
+ size: this.queue.length,
131
+ maxSize: this.maxSize,
132
+ oldestEventAge: oldestEvent ? Date.now() - oldestEvent.enqueuedAt : 0,
133
+ isFlushing: this.isFlushing,
134
+ };
135
+ }
136
+ /**
137
+ * Clear the queue
138
+ */
139
+ clear() {
140
+ this.queue = [];
141
+ void this.persistQueue();
142
+ }
143
+ /**
144
+ * Update webhooks configuration
145
+ */
146
+ updateWebhooks(webhooks) {
147
+ const logger = (0, logging_1.getRuntimeLogger)();
148
+ // Validate webhooks before updating
149
+ const validWebhooks = webhooks.filter((webhook) => {
150
+ if (!webhook.url || webhook.url.trim() === '') {
151
+ logger.error('[EventQueue] Invalid webhook URL, skipping');
152
+ return false;
153
+ }
154
+ try {
155
+ const parsed = new URL(webhook.url);
156
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
157
+ logger.error('[EventQueue] Only HTTP(S) webhook URLs are allowed:', webhook.url);
158
+ return false;
159
+ }
160
+ return true;
161
+ }
162
+ catch {
163
+ logger.error('[EventQueue] Invalid webhook URL format:', webhook.url);
164
+ return false;
165
+ }
166
+ });
167
+ this.webhooks = validWebhooks;
168
+ }
169
+ /**
170
+ * Start the periodic flush timer
171
+ */
172
+ startFlushTimer() {
173
+ if (this.flushTimer) {
174
+ clearInterval(this.flushTimer);
175
+ }
176
+ this.flushTimer = setInterval(() => {
177
+ if (!this.isFlushing && this.queue.length > 0) {
178
+ this.flush().catch((error) => {
179
+ (0, logging_1.getRuntimeLogger)().error('[EventQueue] Flush failed:', (0, logging_1.getErrorMessage)(error));
180
+ });
181
+ }
182
+ }, this.flushIntervalMs);
183
+ // Don't prevent process exit
184
+ if (this.flushTimer.unref) {
185
+ this.flushTimer.unref();
186
+ }
187
+ }
188
+ /**
189
+ * Stop the flush timer
190
+ */
191
+ stop() {
192
+ if (this.flushTimer) {
193
+ clearInterval(this.flushTimer);
194
+ this.flushTimer = undefined;
195
+ }
196
+ void this.persistQueue();
197
+ }
198
+ getPersistPath() {
199
+ return this.persistPath ?? `${process.cwd()}/.event-plugin-queue.json`;
200
+ }
201
+ async loadPersistedQueue() {
202
+ const persistPath = this.getPersistPath();
203
+ try {
204
+ const raw = await (0, promises_1.readFile)(persistPath, 'utf8');
205
+ const parsed = JSON.parse(raw);
206
+ if (!Array.isArray(parsed)) {
207
+ return;
208
+ }
209
+ const restored = parsed.filter((item) => isQueuedEvent(item));
210
+ this.mergeRestoredQueue(restored);
211
+ }
212
+ catch {
213
+ // No persisted queue file or invalid content; start fresh.
214
+ }
215
+ }
216
+ mergeRestoredQueue(restored) {
217
+ if (restored.length === 0) {
218
+ return;
219
+ }
220
+ const existingEventIds = new Set(this.queue.map((item) => item.event.eventId));
221
+ for (const item of restored) {
222
+ if (existingEventIds.has(item.event.eventId)) {
223
+ continue;
224
+ }
225
+ this.queue.push(item);
226
+ }
227
+ if (this.queue.length > this.maxSize) {
228
+ this.queue = this.queue.slice(this.queue.length - this.maxSize);
229
+ }
230
+ }
231
+ async persistQueue() {
232
+ if (!this.persistToDisk) {
233
+ return;
234
+ }
235
+ const snapshot = JSON.stringify(this.queue);
236
+ this.persistChain = this.persistChain
237
+ .catch(() => undefined)
238
+ .then(() => this.writeQueueAtomically(snapshot))
239
+ .catch((error) => {
240
+ (0, logging_1.getRuntimeLogger)().error('[EventQueue] Failed to persist queue:', (0, logging_1.getErrorMessage)(error));
241
+ });
242
+ await this.persistChain;
243
+ }
244
+ async writeQueueAtomically(serializedQueue) {
245
+ const persistPath = this.getPersistPath();
246
+ const tempPath = `${persistPath}.${process.pid}.${Date.now()}.${this.persistSequence}.tmp`;
247
+ this.persistSequence += 1;
248
+ await (0, promises_1.writeFile)(tempPath, serializedQueue, 'utf8');
249
+ try {
250
+ await (0, promises_1.rename)(tempPath, persistPath);
251
+ }
252
+ catch (error) {
253
+ await (0, promises_1.rm)(tempPath, { force: true }).catch(() => undefined);
254
+ throw error;
255
+ }
256
+ }
257
+ }
258
+ exports.EventQueue = EventQueue;
259
+ //# sourceMappingURL=queue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"queue.js","sourceRoot":"","sources":["../../src/broadcast/queue.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Webhook broadcasting with retry logic
3
+ */
4
+ import { OpenClawEvent, WebhookConfig, RetryConfig } from '../events/types';
5
+ /**
6
+ * Result of a webhook delivery attempt
7
+ */
8
+ export interface DeliveryResult {
9
+ success: boolean;
10
+ webhookUrl: string;
11
+ attempts: number;
12
+ error?: string;
13
+ responseStatus?: number;
14
+ durationMs: number;
15
+ }
16
+ /**
17
+ * Send event to a single webhook with retry logic
18
+ * @param event - The event to send
19
+ * @param webhook - Webhook configuration
20
+ * @param retryConfig - Retry configuration
21
+ * @param timeoutMs - Request timeout in milliseconds
22
+ * @param correlationIdHeader - Header name for correlation ID
23
+ * @returns Delivery result with success status and metadata
24
+ */
25
+ export declare function sendToWebhook(event: OpenClawEvent, webhook: WebhookConfig, retryConfig: RetryConfig, timeoutMs: number, correlationIdHeader: string): Promise<DeliveryResult>;
26
+ /**
27
+ * Send event to multiple webhooks in parallel
28
+ */
29
+ export declare function broadcastToWebhooks(event: OpenClawEvent, webhooks: WebhookConfig[], retryConfig: RetryConfig, timeoutMs: number, correlationIdHeader: string): Promise<DeliveryResult[]>;
30
+ //# sourceMappingURL=webhook.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.d.ts","sourceRoot":"","sources":["../../src/broadcast/webhook.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AA2B5E;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;;;;;;;GAQG;AACH,wBAAsB,aAAa,CACjC,KAAK,EAAE,aAAa,EACpB,OAAO,EAAE,aAAa,EACtB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,cAAc,CAAC,CA4GzB;AAED;;GAEG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,aAAa,EAAE,EACzB,WAAW,EAAE,WAAW,EACxB,SAAS,EAAE,MAAM,EACjB,mBAAmB,EAAE,MAAM,GAC1B,OAAO,CAAC,cAAc,EAAE,CAAC,CAY3B"}
@@ -0,0 +1,184 @@
1
+ "use strict";
2
+ /**
3
+ * Webhook broadcasting with retry logic
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.sendToWebhook = sendToWebhook;
40
+ exports.broadcastToWebhooks = broadcastToWebhooks;
41
+ let axiosImport = null;
42
+ function getAxios() {
43
+ if (!axiosImport) {
44
+ axiosImport = Promise.resolve().then(() => __importStar(require('axios')));
45
+ }
46
+ return axiosImport;
47
+ }
48
+ function getErrorMessage(error) {
49
+ if (error instanceof Error) {
50
+ return error.message;
51
+ }
52
+ return String(error);
53
+ }
54
+ function getResponseStatus(error) {
55
+ if (typeof error !== 'object' || error === null) {
56
+ return undefined;
57
+ }
58
+ const response = error.response;
59
+ return typeof response?.status === 'number' ? response.status : undefined;
60
+ }
61
+ /**
62
+ * Send event to a single webhook with retry logic
63
+ * @param event - The event to send
64
+ * @param webhook - Webhook configuration
65
+ * @param retryConfig - Retry configuration
66
+ * @param timeoutMs - Request timeout in milliseconds
67
+ * @param correlationIdHeader - Header name for correlation ID
68
+ * @returns Delivery result with success status and metadata
69
+ */
70
+ async function sendToWebhook(event, webhook, retryConfig, timeoutMs, correlationIdHeader) {
71
+ const startTime = Date.now();
72
+ let lastError;
73
+ let lastStatus;
74
+ let attempts = 0;
75
+ let delayMs = retryConfig.initialDelayMs;
76
+ const webhookUrl = webhook.url?.trim() ?? '';
77
+ // Validate webhook URL
78
+ if (webhookUrl === '') {
79
+ return {
80
+ success: false,
81
+ webhookUrl,
82
+ attempts: 0,
83
+ error: 'Invalid webhook URL',
84
+ durationMs: Date.now() - startTime,
85
+ };
86
+ }
87
+ let parsedUrl;
88
+ try {
89
+ parsedUrl = new URL(webhookUrl);
90
+ if (parsedUrl.protocol !== 'http:' && parsedUrl.protocol !== 'https:') {
91
+ return {
92
+ success: false,
93
+ webhookUrl,
94
+ attempts: 0,
95
+ error: 'Only HTTP and HTTPS webhook URLs are supported',
96
+ durationMs: Date.now() - startTime,
97
+ };
98
+ }
99
+ }
100
+ catch {
101
+ return {
102
+ success: false,
103
+ webhookUrl,
104
+ attempts: 0,
105
+ error: 'Invalid webhook URL format',
106
+ durationMs: Date.now() - startTime,
107
+ };
108
+ }
109
+ const axios = (await getAxios()).default;
110
+ while (attempts < retryConfig.maxAttempts) {
111
+ attempts++;
112
+ try {
113
+ const headers = {
114
+ 'Content-Type': 'application/json',
115
+ 'User-Agent': 'OpenClaw-Event-Plugin/1.0.0',
116
+ ...webhook.headers,
117
+ };
118
+ // Add correlation ID header
119
+ if (event.correlationId) {
120
+ headers[correlationIdHeader] = event.correlationId;
121
+ }
122
+ // Add auth header if token provided
123
+ if (webhook.authToken) {
124
+ headers['Authorization'] = `Bearer ${webhook.authToken}`;
125
+ }
126
+ const response = await axios({
127
+ method: webhook.method ?? 'POST',
128
+ url: parsedUrl.toString(),
129
+ data: webhook.includeFullPayload !== false ? event : { type: event.type, timestamp: event.timestamp },
130
+ headers,
131
+ timeout: timeoutMs,
132
+ validateStatus: (status) => status >= 200 && status < 300,
133
+ });
134
+ return {
135
+ success: true,
136
+ webhookUrl: webhook.url,
137
+ attempts,
138
+ responseStatus: response.status,
139
+ durationMs: Date.now() - startTime,
140
+ };
141
+ }
142
+ catch (error) {
143
+ lastError = getErrorMessage(error);
144
+ lastStatus = getResponseStatus(error);
145
+ // Don't retry on client errors (4xx) except 429 (rate limit)
146
+ if (lastStatus !== undefined &&
147
+ lastStatus >= 400 &&
148
+ lastStatus < 500 &&
149
+ lastStatus !== 429) {
150
+ break;
151
+ }
152
+ // Wait before retry (exponential backoff)
153
+ if (attempts < retryConfig.maxAttempts) {
154
+ await sleep(delayMs);
155
+ delayMs = Math.min(delayMs * retryConfig.backoffMultiplier, retryConfig.maxDelayMs);
156
+ }
157
+ }
158
+ }
159
+ return {
160
+ success: false,
161
+ webhookUrl,
162
+ attempts,
163
+ error: lastError,
164
+ responseStatus: lastStatus,
165
+ durationMs: Date.now() - startTime,
166
+ };
167
+ }
168
+ /**
169
+ * Send event to multiple webhooks in parallel
170
+ */
171
+ async function broadcastToWebhooks(event, webhooks, retryConfig, timeoutMs, correlationIdHeader) {
172
+ if (webhooks.length === 0) {
173
+ return [];
174
+ }
175
+ const results = await Promise.all(webhooks.map((webhook) => sendToWebhook(event, webhook, retryConfig, timeoutMs, correlationIdHeader)));
176
+ return results;
177
+ }
178
+ /**
179
+ * Sleep for specified milliseconds
180
+ */
181
+ function sleep(ms) {
182
+ return new Promise((resolve) => setTimeout(resolve, ms));
183
+ }
184
+ //# sourceMappingURL=webhook.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"webhook.js","sourceRoot":"","sources":["../../src/broadcast/webhook.ts"],"names":[],"mappings":"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"}