agents-library 1.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.
Files changed (89) hide show
  1. package/dist/base-agent.d.ts +172 -0
  2. package/dist/base-agent.d.ts.map +1 -0
  3. package/dist/base-agent.js +255 -0
  4. package/dist/base-agent.js.map +1 -0
  5. package/dist/base-bot.d.ts +282 -0
  6. package/dist/base-bot.d.ts.map +1 -0
  7. package/dist/base-bot.js +375 -0
  8. package/dist/base-bot.js.map +1 -0
  9. package/dist/common/result.d.ts +51 -0
  10. package/dist/common/result.d.ts.map +1 -0
  11. package/dist/common/result.js +45 -0
  12. package/dist/common/result.js.map +1 -0
  13. package/dist/common/types.d.ts +57 -0
  14. package/dist/common/types.d.ts.map +1 -0
  15. package/dist/common/types.js +42 -0
  16. package/dist/common/types.js.map +1 -0
  17. package/dist/index.d.ts +94 -0
  18. package/dist/index.d.ts.map +1 -0
  19. package/dist/index.js +108 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/kadi-event-publisher.d.ts +163 -0
  22. package/dist/kadi-event-publisher.d.ts.map +1 -0
  23. package/dist/kadi-event-publisher.js +286 -0
  24. package/dist/kadi-event-publisher.js.map +1 -0
  25. package/dist/memory/arcadedb-adapter.d.ts +159 -0
  26. package/dist/memory/arcadedb-adapter.d.ts.map +1 -0
  27. package/dist/memory/arcadedb-adapter.js +314 -0
  28. package/dist/memory/arcadedb-adapter.js.map +1 -0
  29. package/dist/memory/file-storage-adapter.d.ts +122 -0
  30. package/dist/memory/file-storage-adapter.d.ts.map +1 -0
  31. package/dist/memory/file-storage-adapter.js +352 -0
  32. package/dist/memory/file-storage-adapter.js.map +1 -0
  33. package/dist/memory/memory-service.d.ts +208 -0
  34. package/dist/memory/memory-service.d.ts.map +1 -0
  35. package/dist/memory/memory-service.js +410 -0
  36. package/dist/memory/memory-service.js.map +1 -0
  37. package/dist/memory/types.d.ts +126 -0
  38. package/dist/memory/types.d.ts.map +1 -0
  39. package/dist/memory/types.js +41 -0
  40. package/dist/memory/types.js.map +1 -0
  41. package/dist/producer-tool-utils.d.ts +474 -0
  42. package/dist/producer-tool-utils.d.ts.map +1 -0
  43. package/dist/producer-tool-utils.js +664 -0
  44. package/dist/producer-tool-utils.js.map +1 -0
  45. package/dist/providers/anthropic-provider.d.ts +160 -0
  46. package/dist/providers/anthropic-provider.d.ts.map +1 -0
  47. package/dist/providers/anthropic-provider.js +527 -0
  48. package/dist/providers/anthropic-provider.js.map +1 -0
  49. package/dist/providers/model-manager-provider.d.ts +91 -0
  50. package/dist/providers/model-manager-provider.d.ts.map +1 -0
  51. package/dist/providers/model-manager-provider.js +355 -0
  52. package/dist/providers/model-manager-provider.js.map +1 -0
  53. package/dist/providers/provider-manager.d.ts +111 -0
  54. package/dist/providers/provider-manager.d.ts.map +1 -0
  55. package/dist/providers/provider-manager.js +337 -0
  56. package/dist/providers/provider-manager.js.map +1 -0
  57. package/dist/providers/types.d.ts +145 -0
  58. package/dist/providers/types.d.ts.map +1 -0
  59. package/dist/providers/types.js +23 -0
  60. package/dist/providers/types.js.map +1 -0
  61. package/dist/shadow-agent-factory.d.ts +623 -0
  62. package/dist/shadow-agent-factory.d.ts.map +1 -0
  63. package/dist/shadow-agent-factory.js +1117 -0
  64. package/dist/shadow-agent-factory.js.map +1 -0
  65. package/dist/types/agent-config.d.ts +307 -0
  66. package/dist/types/agent-config.d.ts.map +1 -0
  67. package/dist/types/agent-config.js +15 -0
  68. package/dist/types/agent-config.js.map +1 -0
  69. package/dist/types/event-schemas.d.ts +358 -0
  70. package/dist/types/event-schemas.d.ts.map +1 -0
  71. package/dist/types/event-schemas.js +188 -0
  72. package/dist/types/event-schemas.js.map +1 -0
  73. package/dist/types/tool-schemas.d.ts +498 -0
  74. package/dist/types/tool-schemas.d.ts.map +1 -0
  75. package/dist/types/tool-schemas.js +457 -0
  76. package/dist/types/tool-schemas.js.map +1 -0
  77. package/dist/utils/logger.d.ts +135 -0
  78. package/dist/utils/logger.d.ts.map +1 -0
  79. package/dist/utils/logger.js +205 -0
  80. package/dist/utils/logger.js.map +1 -0
  81. package/dist/utils/timer.d.ts +186 -0
  82. package/dist/utils/timer.d.ts.map +1 -0
  83. package/dist/utils/timer.js +211 -0
  84. package/dist/utils/timer.js.map +1 -0
  85. package/dist/worker-agent-factory.d.ts +688 -0
  86. package/dist/worker-agent-factory.d.ts.map +1 -0
  87. package/dist/worker-agent-factory.js +1517 -0
  88. package/dist/worker-agent-factory.js.map +1 -0
  89. package/package.json +38 -0
@@ -0,0 +1,282 @@
1
+ /**
2
+ * Base Bot Abstract Class for Platform-Agnostic Bot Logic
3
+ * ========================================================
4
+ *
5
+ * Provides shared functionality for all platform-specific bots (Slack, Discord, etc.)
6
+ * Eliminates code duplication by consolidating common patterns:
7
+ * - Circuit breaker pattern for fault tolerance
8
+ * - Exponential backoff retry logic
9
+ * - Metrics tracking and monitoring
10
+ * - Tool invocation with resilience
11
+ *
12
+ * This is an abstract class - cannot be instantiated directly.
13
+ * Platform-specific bots must extend this and implement abstract methods.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * export class SlackBot extends BaseBot {
18
+ * async handleMention(event: SlackMentionEvent): Promise<void> {
19
+ * // Slack-specific mention handling
20
+ * }
21
+ *
22
+ * async start(): Promise<void> {
23
+ * await super.initializeAbilityResponseSubscription();
24
+ * await this.subscribeToMentions();
25
+ * }
26
+ *
27
+ * stop(): void {
28
+ * // Cleanup logic
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ import Anthropic from '@anthropic-ai/sdk';
34
+ import type { KadiClient } from '@kadi.build/core';
35
+ import type { ProviderManager } from './providers/provider-manager.js';
36
+ import type { MemoryService } from './memory/memory-service.js';
37
+ /**
38
+ * Base configuration required by all bots
39
+ */
40
+ export interface BaseBotConfig {
41
+ /** KĀDI client instance for event subscription and tool invocation */
42
+ client: KadiClient;
43
+ /** Anthropic API key for Claude integration */
44
+ anthropicApiKey: string;
45
+ /** Bot user ID for topic routing (platform-specific format) */
46
+ botUserId: string;
47
+ /** Optional provider manager for LLM operations (shared service) */
48
+ providerManager?: ProviderManager;
49
+ /** Optional memory service for conversation context (shared service) */
50
+ memoryService?: MemoryService;
51
+ }
52
+ /**
53
+ * Abstract base class for platform-agnostic bot logic
54
+ *
55
+ * Provides common functionality shared across all platform bots:
56
+ * - Circuit breaker for fault tolerance
57
+ * - Retry logic with exponential backoff
58
+ * - Metrics tracking
59
+ * - Tool invocation helpers
60
+ *
61
+ * Platform-specific bots (SlackBot, DiscordBot) extend this class
62
+ * and implement the abstract methods.
63
+ */
64
+ export declare abstract class BaseBot {
65
+ /** KĀDI client for broker communication */
66
+ protected client: KadiClient;
67
+ /** Anthropic API client for Claude integration */
68
+ protected anthropic: Anthropic;
69
+ /** Bot user ID for topic routing */
70
+ protected botUserId: string;
71
+ /** Optional provider manager for LLM operations */
72
+ protected providerManager?: ProviderManager;
73
+ /** Optional memory service for conversation context */
74
+ protected memoryService?: MemoryService;
75
+ /** Pending async tool responses (requestId -> Promise resolver) */
76
+ private pendingResponses;
77
+ /** Number of consecutive failures */
78
+ private failureCount;
79
+ /** Timestamp of last failure (for reset timeout) */
80
+ private lastFailureTime;
81
+ /** Maximum failures before circuit opens */
82
+ private readonly maxFailures;
83
+ /** Time in ms before circuit breaker resets */
84
+ private readonly resetTimeMs;
85
+ /** Whether circuit breaker is open (blocking requests) */
86
+ private isCircuitOpen;
87
+ /** Maximum retry attempts for failed operations */
88
+ private readonly maxRetries;
89
+ /** Base delay in ms for exponential backoff (1s, 2s, 4s) */
90
+ private readonly baseDelayMs;
91
+ /** Total number of requests processed */
92
+ private totalRequests;
93
+ /** Number of requests that timed out */
94
+ private timeoutCount;
95
+ /** Number of successful requests */
96
+ private successCount;
97
+ /**
98
+ * Create a new BaseBot instance
99
+ *
100
+ * @param config - Base bot configuration with client, API key, and bot ID
101
+ */
102
+ constructor(config: BaseBotConfig);
103
+ /**
104
+ * Handle platform-specific mention event
105
+ *
106
+ * Subclasses must implement this to process @mentions for their platform.
107
+ *
108
+ * @param event - Platform-specific mention event (e.g., SlackMentionEvent, DiscordMentionEvent)
109
+ */
110
+ protected abstract handleMention(event: any): Promise<void>;
111
+ /**
112
+ * Start the bot and begin processing events
113
+ *
114
+ * Subclasses must implement this to:
115
+ * 1. Call initializeAbilityResponseSubscription()
116
+ * 2. Subscribe to platform-specific events
117
+ */
118
+ abstract start(): Promise<void>;
119
+ /**
120
+ * Stop the bot and cleanup resources
121
+ *
122
+ * Subclasses must implement this to unsubscribe from events
123
+ * and perform any platform-specific cleanup.
124
+ */
125
+ abstract stop(): void;
126
+ /**
127
+ * Initialize ability response subscription
128
+ *
129
+ * Must be called by subclasses in their start() method
130
+ * before attempting to invoke tools or subscribe to events.
131
+ *
132
+ * Subscribes to async ability responses from kadi-broker.
133
+ */
134
+ protected initializeAbilityResponseSubscription(): Promise<void>;
135
+ /**
136
+ * Subscribe to kadi.ability.response notifications
137
+ *
138
+ * Handles async tool results from broker. When a tool returns {status: "pending"},
139
+ * the actual result arrives later as a kadi.ability.response notification.
140
+ *
141
+ * @private
142
+ */
143
+ private subscribeToAbilityResponses;
144
+ /**
145
+ * Wait for async ability response from kadi-broker
146
+ *
147
+ * When a tool returns {status: "pending", requestId: "..."}, this method
148
+ * waits for the actual result to arrive via kadi.ability.response notification.
149
+ *
150
+ * @param requestId - Request ID from pending status response
151
+ * @param timeout - Timeout in milliseconds (default: 30000)
152
+ * @returns Promise that resolves with the actual tool result
153
+ * @throws Error if timeout expires before result arrives
154
+ *
155
+ * @example
156
+ * ```typescript
157
+ * const result = await this.protocol.invokeTool({...});
158
+ * if (result?.status === 'pending') {
159
+ * const actualResult = await this.waitForAbilityResponse(result.requestId);
160
+ * return actualResult;
161
+ * }
162
+ * ```
163
+ */
164
+ protected waitForAbilityResponse(requestId: string, timeout?: number): Promise<any>;
165
+ /**
166
+ * Sleep for specified milliseconds
167
+ *
168
+ * Used for exponential backoff delays in retry logic.
169
+ *
170
+ * @param ms - Milliseconds to sleep
171
+ */
172
+ protected sleep(ms: number): Promise<void>;
173
+ /**
174
+ * Check circuit breaker state and reset if needed
175
+ *
176
+ * Returns true if circuit is open (blocking requests).
177
+ * Automatically resets circuit after resetTimeMs has elapsed.
178
+ *
179
+ * @returns true if circuit is open, false if closed
180
+ *
181
+ * @example
182
+ * ```typescript
183
+ * if (this.checkCircuitBreaker()) {
184
+ * console.log('Circuit open - skipping request');
185
+ * return;
186
+ * }
187
+ * ```
188
+ */
189
+ protected checkCircuitBreaker(): boolean;
190
+ /**
191
+ * Record failure and update circuit breaker state
192
+ *
193
+ * Increments failure count and opens circuit if maxFailures threshold reached.
194
+ * Logs metrics every 10 requests.
195
+ *
196
+ * @param _error - Error object (for potential future use)
197
+ */
198
+ protected recordFailure(_error: any): void;
199
+ /**
200
+ * Record success and reset failure counter
201
+ *
202
+ * Resets consecutive failure count when a request succeeds.
203
+ * Increments success metrics.
204
+ */
205
+ protected recordSuccess(): void;
206
+ /**
207
+ * Reset circuit breaker state
208
+ *
209
+ * Manually resets circuit breaker and clears failure count.
210
+ * Use with caution - typically circuit should auto-reset.
211
+ */
212
+ protected resetCircuitBreaker(): void;
213
+ /**
214
+ * Invoke KĀDI tool with retry logic and exponential backoff
215
+ *
216
+ * Automatically retries failed tool invocations with exponential backoff:
217
+ * - Attempt 1: Immediate
218
+ * - Attempt 2: 1s delay
219
+ * - Attempt 3: 2s delay
220
+ * - Attempt 4: 4s delay
221
+ *
222
+ * Only retries on timeout or network errors. Other errors fail immediately.
223
+ *
224
+ * @param params - Tool invocation parameters
225
+ * @param params.targetAgent - Target agent ID (e.g., 'mcp-server-slack')
226
+ * @param params.toolName - Tool name to invoke (e.g., 'send_slack_message')
227
+ * @param params.toolInput - Tool input parameters
228
+ * @param params.timeout - Timeout in milliseconds
229
+ * @param retryCount - Current retry attempt (internal, do not set)
230
+ * @returns Tool invocation result
231
+ * @throws Error if all retries exhausted
232
+ *
233
+ * @example
234
+ * ```typescript
235
+ * await this.invokeToolWithRetry({
236
+ * targetAgent: 'mcp-server-slack',
237
+ * toolName: 'send_slack_message',
238
+ * toolInput: { channel: 'C123', text: 'Hello' },
239
+ * timeout: 10000
240
+ * });
241
+ * ```
242
+ */
243
+ protected invokeToolWithRetry(params: {
244
+ targetAgent: string;
245
+ toolName: string;
246
+ toolInput: any;
247
+ timeout: number;
248
+ }, retryCount?: number): Promise<any>;
249
+ /**
250
+ * Get current bot metrics
251
+ *
252
+ * Returns metrics for monitoring and debugging:
253
+ * - Total requests processed
254
+ * - Success count and rate
255
+ * - Timeout count and rate
256
+ * - Circuit breaker state
257
+ *
258
+ * @returns Metrics object
259
+ *
260
+ * @example
261
+ * ```typescript
262
+ * const metrics = this.getMetrics();
263
+ * console.log(`Success rate: ${metrics.successRate}%`);
264
+ * ```
265
+ */
266
+ protected getMetrics(): {
267
+ totalRequests: number;
268
+ successCount: number;
269
+ timeoutCount: number;
270
+ successRate: number;
271
+ timeoutRate: number;
272
+ isCircuitOpen: boolean;
273
+ };
274
+ /**
275
+ * Log timeout and success metrics
276
+ *
277
+ * Logs formatted metrics to console for monitoring.
278
+ * Called automatically every 10 requests or can be called manually.
279
+ */
280
+ protected logMetrics(): void;
281
+ }
282
+ //# sourceMappingURL=base-bot.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-bot.d.ts","sourceRoot":"","sources":["../src/base-bot.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+BG;AAEH,OAAO,SAAS,MAAM,mBAAmB,CAAC;AAC1C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAGnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAMhE;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,sEAAsE;IACtE,MAAM,EAAE,UAAU,CAAC;IAEnB,+CAA+C;IAC/C,eAAe,EAAE,MAAM,CAAC;IAExB,+DAA+D;IAC/D,SAAS,EAAE,MAAM,CAAC;IAElB,oEAAoE;IACpE,eAAe,CAAC,EAAE,eAAe,CAAC;IAElC,wEAAwE;IACxE,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAMD;;;;;;;;;;;GAWG;AACH,8BAAsB,OAAO;IAK3B,2CAA2C;IAC3C,SAAS,CAAC,MAAM,EAAE,UAAU,CAAC;IAE7B,kDAAkD;IAClD,SAAS,CAAC,SAAS,EAAE,SAAS,CAAC;IAE/B,oCAAoC;IACpC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC;IAE5B,mDAAmD;IACnD,SAAS,CAAC,eAAe,CAAC,EAAE,eAAe,CAAC;IAE5C,uDAAuD;IACvD,SAAS,CAAC,aAAa,CAAC,EAAE,aAAa,CAAC;IAExC,mEAAmE;IACnE,OAAO,CAAC,gBAAgB,CAInB;IAML,qCAAqC;IACrC,OAAO,CAAC,YAAY,CAAK;IAEzB,oDAAoD;IACpD,OAAO,CAAC,eAAe,CAAK;IAE5B,4CAA4C;IAC5C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAK;IAEjC,+CAA+C;IAC/C,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAS;IAErC,0DAA0D;IAC1D,OAAO,CAAC,aAAa,CAAS;IAM9B,mDAAmD;IACnD,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAK;IAEhC,4DAA4D;IAC5D,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAQ;IAMpC,yCAAyC;IACzC,OAAO,CAAC,aAAa,CAAK;IAE1B,wCAAwC;IACxC,OAAO,CAAC,YAAY,CAAK;IAEzB,oCAAoC;IACpC,OAAO,CAAC,YAAY,CAAK;IAMzB;;;;OAIG;gBACS,MAAM,EAAE,aAAa;IAYjC;;;;;;OAMG;IACH,SAAS,CAAC,QAAQ,CAAC,aAAa,CAAC,KAAK,EAAE,GAAG,GAAG,OAAO,CAAC,IAAI,CAAC;IAE3D;;;;;;OAMG;aACa,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAEtC;;;;;OAKG;aACa,IAAI,IAAI,IAAI;IAM5B;;;;;;;OAOG;cACa,qCAAqC,IAAI,OAAO,CAAC,IAAI,CAAC;IAKtE;;;;;;;OAOG;YACW,2BAA2B;IA0BzC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,SAAS,CAAC,sBAAsB,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,SAAQ,GAAG,OAAO,CAAC,GAAG,CAAC;IAiBlF;;;;;;OAMG;IACH,SAAS,CAAC,KAAK,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C;;;;;;;;;;;;;;;OAeG;IACH,SAAS,CAAC,mBAAmB,IAAI,OAAO;IAaxC;;;;;;;OAOG;IACH,SAAS,CAAC,aAAa,CAAC,MAAM,EAAE,GAAG,GAAG,IAAI;IAiB1C;;;;;OAKG;IACH,SAAS,CAAC,aAAa,IAAI,IAAI;IAQ/B;;;;;OAKG;IACH,SAAS,CAAC,mBAAmB,IAAI,IAAI;IAOrC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6BG;cACa,mBAAmB,CACjC,MAAM,EAAE;QACN,WAAW,EAAE,MAAM,CAAC;QACpB,QAAQ,EAAE,MAAM,CAAC;QACjB,SAAS,EAAE,GAAG,CAAC;QACf,OAAO,EAAE,MAAM,CAAC;KACjB,EACD,UAAU,SAAI,GACb,OAAO,CAAC,GAAG,CAAC;IA+Bf;;;;;;;;;;;;;;;;OAgBG;IACH,SAAS,CAAC,UAAU,IAAI;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,WAAW,EAAE,MAAM,CAAC;QACpB,WAAW,EAAE,MAAM,CAAC;QACpB,aAAa,EAAE,OAAO,CAAC;KACxB;IAkBD;;;;;OAKG;IACH,SAAS,CAAC,UAAU,IAAI,IAAI;CAS7B"}
@@ -0,0 +1,375 @@
1
+ /**
2
+ * Base Bot Abstract Class for Platform-Agnostic Bot Logic
3
+ * ========================================================
4
+ *
5
+ * Provides shared functionality for all platform-specific bots (Slack, Discord, etc.)
6
+ * Eliminates code duplication by consolidating common patterns:
7
+ * - Circuit breaker pattern for fault tolerance
8
+ * - Exponential backoff retry logic
9
+ * - Metrics tracking and monitoring
10
+ * - Tool invocation with resilience
11
+ *
12
+ * This is an abstract class - cannot be instantiated directly.
13
+ * Platform-specific bots must extend this and implement abstract methods.
14
+ *
15
+ * @example
16
+ * ```typescript
17
+ * export class SlackBot extends BaseBot {
18
+ * async handleMention(event: SlackMentionEvent): Promise<void> {
19
+ * // Slack-specific mention handling
20
+ * }
21
+ *
22
+ * async start(): Promise<void> {
23
+ * await super.initializeAbilityResponseSubscription();
24
+ * await this.subscribeToMentions();
25
+ * }
26
+ *
27
+ * stop(): void {
28
+ * // Cleanup logic
29
+ * }
30
+ * }
31
+ * ```
32
+ */
33
+ import Anthropic from '@anthropic-ai/sdk';
34
+ import { logger, MODULE_AGENT } from './utils/logger.js';
35
+ import { timer } from './utils/timer.js';
36
+ // ============================================================================
37
+ // Abstract Base Bot Class
38
+ // ============================================================================
39
+ /**
40
+ * Abstract base class for platform-agnostic bot logic
41
+ *
42
+ * Provides common functionality shared across all platform bots:
43
+ * - Circuit breaker for fault tolerance
44
+ * - Retry logic with exponential backoff
45
+ * - Metrics tracking
46
+ * - Tool invocation helpers
47
+ *
48
+ * Platform-specific bots (SlackBot, DiscordBot) extend this class
49
+ * and implement the abstract methods.
50
+ */
51
+ export class BaseBot {
52
+ // ============================================================================
53
+ // Protected Properties (accessible to subclasses)
54
+ // ============================================================================
55
+ /** KĀDI client for broker communication */
56
+ client;
57
+ /** Anthropic API client for Claude integration */
58
+ anthropic;
59
+ /** Bot user ID for topic routing */
60
+ botUserId;
61
+ /** Optional provider manager for LLM operations */
62
+ providerManager;
63
+ /** Optional memory service for conversation context */
64
+ memoryService;
65
+ /** Pending async tool responses (requestId -> Promise resolver) */
66
+ pendingResponses = new Map();
67
+ // ============================================================================
68
+ // Circuit Breaker State (private)
69
+ // ============================================================================
70
+ /** Number of consecutive failures */
71
+ failureCount = 0;
72
+ /** Timestamp of last failure (for reset timeout) */
73
+ lastFailureTime = 0;
74
+ /** Maximum failures before circuit opens */
75
+ maxFailures = 5;
76
+ /** Time in ms before circuit breaker resets */
77
+ resetTimeMs = 60000; // 1 minute
78
+ /** Whether circuit breaker is open (blocking requests) */
79
+ isCircuitOpen = false;
80
+ // ============================================================================
81
+ // Retry Configuration (private)
82
+ // ============================================================================
83
+ /** Maximum retry attempts for failed operations */
84
+ maxRetries = 3;
85
+ /** Base delay in ms for exponential backoff (1s, 2s, 4s) */
86
+ baseDelayMs = 1000;
87
+ // ============================================================================
88
+ // Metrics Tracking (private)
89
+ // ============================================================================
90
+ /** Total number of requests processed */
91
+ totalRequests = 0;
92
+ /** Number of requests that timed out */
93
+ timeoutCount = 0;
94
+ /** Number of successful requests */
95
+ successCount = 0;
96
+ // ============================================================================
97
+ // Constructor
98
+ // ============================================================================
99
+ /**
100
+ * Create a new BaseBot instance
101
+ *
102
+ * @param config - Base bot configuration with client, API key, and bot ID
103
+ */
104
+ constructor(config) {
105
+ this.client = config.client;
106
+ this.anthropic = new Anthropic({ apiKey: config.anthropicApiKey });
107
+ this.botUserId = config.botUserId;
108
+ this.providerManager = config.providerManager;
109
+ this.memoryService = config.memoryService;
110
+ }
111
+ // ============================================================================
112
+ // Protected Helper Methods (available to subclasses)
113
+ // ============================================================================
114
+ /**
115
+ * Initialize ability response subscription
116
+ *
117
+ * Must be called by subclasses in their start() method
118
+ * before attempting to invoke tools or subscribe to events.
119
+ *
120
+ * Subscribes to async ability responses from kadi-broker.
121
+ */
122
+ async initializeAbilityResponseSubscription() {
123
+ // Subscribe to async ability responses from kadi-broker
124
+ await this.subscribeToAbilityResponses();
125
+ }
126
+ /**
127
+ * Subscribe to kadi.ability.response notifications
128
+ *
129
+ * Handles async tool results from broker. When a tool returns {status: "pending"},
130
+ * the actual result arrives later as a kadi.ability.response notification.
131
+ *
132
+ * @private
133
+ */
134
+ async subscribeToAbilityResponses() {
135
+ // Subscribe to kadi.ability.response events via kadi-core v0.6.0 subscribe API
136
+ await this.client.subscribe('kadi.ability.response', (event) => {
137
+ const { requestId, result, error } = event || {};
138
+ const pending = this.pendingResponses.get(requestId);
139
+ if (!pending) {
140
+ // This response is for a different request or already handled
141
+ return;
142
+ }
143
+ // Clear timeout timer
144
+ clearTimeout(pending.timer);
145
+ this.pendingResponses.delete(requestId);
146
+ // Resolve or reject the promise
147
+ if (error) {
148
+ pending.reject(new Error(`Async tool failed: ${error}`));
149
+ }
150
+ else {
151
+ pending.resolve(result);
152
+ }
153
+ }, { broker: 'default' });
154
+ logger.info(MODULE_AGENT, 'Subscribed to kadi.ability.response notifications', timer.elapsed('main'));
155
+ }
156
+ /**
157
+ * Wait for async ability response from kadi-broker
158
+ *
159
+ * When a tool returns {status: "pending", requestId: "..."}, this method
160
+ * waits for the actual result to arrive via kadi.ability.response notification.
161
+ *
162
+ * @param requestId - Request ID from pending status response
163
+ * @param timeout - Timeout in milliseconds (default: 30000)
164
+ * @returns Promise that resolves with the actual tool result
165
+ * @throws Error if timeout expires before result arrives
166
+ *
167
+ * @example
168
+ * ```typescript
169
+ * const result = await this.protocol.invokeTool({...});
170
+ * if (result?.status === 'pending') {
171
+ * const actualResult = await this.waitForAbilityResponse(result.requestId);
172
+ * return actualResult;
173
+ * }
174
+ * ```
175
+ */
176
+ waitForAbilityResponse(requestId, timeout = 30000) {
177
+ return new Promise((resolve, reject) => {
178
+ // Setup timeout
179
+ const timer = setTimeout(() => {
180
+ this.pendingResponses.delete(requestId);
181
+ reject(new Error(`Timeout waiting for async tool result: ${requestId}`));
182
+ }, timeout);
183
+ // Register promise resolver
184
+ this.pendingResponses.set(requestId, {
185
+ resolve,
186
+ reject,
187
+ timer
188
+ });
189
+ });
190
+ }
191
+ /**
192
+ * Sleep for specified milliseconds
193
+ *
194
+ * Used for exponential backoff delays in retry logic.
195
+ *
196
+ * @param ms - Milliseconds to sleep
197
+ */
198
+ sleep(ms) {
199
+ return new Promise(resolve => setTimeout(resolve, ms));
200
+ }
201
+ /**
202
+ * Check circuit breaker state and reset if needed
203
+ *
204
+ * Returns true if circuit is open (blocking requests).
205
+ * Automatically resets circuit after resetTimeMs has elapsed.
206
+ *
207
+ * @returns true if circuit is open, false if closed
208
+ *
209
+ * @example
210
+ * ```typescript
211
+ * if (this.checkCircuitBreaker()) {
212
+ * console.log('Circuit open - skipping request');
213
+ * return;
214
+ * }
215
+ * ```
216
+ */
217
+ checkCircuitBreaker() {
218
+ const now = Date.now();
219
+ // Reset circuit if enough time has passed
220
+ if (this.isCircuitOpen && (now - this.lastFailureTime) > this.resetTimeMs) {
221
+ console.log('🔧 Circuit breaker reset - attempting recovery');
222
+ this.isCircuitOpen = false;
223
+ this.failureCount = 0;
224
+ }
225
+ return this.isCircuitOpen;
226
+ }
227
+ /**
228
+ * Record failure and update circuit breaker state
229
+ *
230
+ * Increments failure count and opens circuit if maxFailures threshold reached.
231
+ * Logs metrics every 10 requests.
232
+ *
233
+ * @param _error - Error object (for potential future use)
234
+ */
235
+ recordFailure(_error) {
236
+ this.failureCount++;
237
+ this.lastFailureTime = Date.now();
238
+ this.timeoutCount++;
239
+ if (this.failureCount >= this.maxFailures && !this.isCircuitOpen) {
240
+ this.isCircuitOpen = true;
241
+ console.error(`⚡ Circuit breaker OPEN after ${this.failureCount} failures`);
242
+ console.error(` Will retry after ${this.resetTimeMs / 1000} seconds`);
243
+ }
244
+ // Log timeout metrics every 10 requests
245
+ if (this.totalRequests % 10 === 0) {
246
+ this.logMetrics();
247
+ }
248
+ }
249
+ /**
250
+ * Record success and reset failure counter
251
+ *
252
+ * Resets consecutive failure count when a request succeeds.
253
+ * Increments success metrics.
254
+ */
255
+ recordSuccess() {
256
+ if (this.failureCount > 0) {
257
+ console.log(`✅ Request succeeded - resetting failure count (was ${this.failureCount})`);
258
+ }
259
+ this.failureCount = 0;
260
+ this.successCount++;
261
+ }
262
+ /**
263
+ * Reset circuit breaker state
264
+ *
265
+ * Manually resets circuit breaker and clears failure count.
266
+ * Use with caution - typically circuit should auto-reset.
267
+ */
268
+ resetCircuitBreaker() {
269
+ this.isCircuitOpen = false;
270
+ this.failureCount = 0;
271
+ this.lastFailureTime = 0;
272
+ console.log('🔧 Circuit breaker manually reset');
273
+ }
274
+ /**
275
+ * Invoke KĀDI tool with retry logic and exponential backoff
276
+ *
277
+ * Automatically retries failed tool invocations with exponential backoff:
278
+ * - Attempt 1: Immediate
279
+ * - Attempt 2: 1s delay
280
+ * - Attempt 3: 2s delay
281
+ * - Attempt 4: 4s delay
282
+ *
283
+ * Only retries on timeout or network errors. Other errors fail immediately.
284
+ *
285
+ * @param params - Tool invocation parameters
286
+ * @param params.targetAgent - Target agent ID (e.g., 'mcp-server-slack')
287
+ * @param params.toolName - Tool name to invoke (e.g., 'send_slack_message')
288
+ * @param params.toolInput - Tool input parameters
289
+ * @param params.timeout - Timeout in milliseconds
290
+ * @param retryCount - Current retry attempt (internal, do not set)
291
+ * @returns Tool invocation result
292
+ * @throws Error if all retries exhausted
293
+ *
294
+ * @example
295
+ * ```typescript
296
+ * await this.invokeToolWithRetry({
297
+ * targetAgent: 'mcp-server-slack',
298
+ * toolName: 'send_slack_message',
299
+ * toolInput: { channel: 'C123', text: 'Hello' },
300
+ * timeout: 10000
301
+ * });
302
+ * ```
303
+ */
304
+ async invokeToolWithRetry(params, retryCount = 0) {
305
+ this.totalRequests++;
306
+ try {
307
+ const result = await this.client.invokeRemote(params.toolName, params.toolInput, { timeout: params.timeout });
308
+ this.recordSuccess();
309
+ return result;
310
+ }
311
+ catch (error) {
312
+ const isTimeout = error.message?.includes('timeout');
313
+ const isNetworkError = error.message?.includes('ECONNREFUSED') ||
314
+ error.message?.includes('ENOTFOUND');
315
+ // Only retry on timeout or network errors
316
+ if ((isTimeout || isNetworkError) && retryCount < this.maxRetries) {
317
+ const delayMs = this.baseDelayMs * Math.pow(2, retryCount);
318
+ console.warn(`⚠️ Request failed (${error.message}), retrying in ${delayMs}ms (attempt ${retryCount + 1}/${this.maxRetries})...`);
319
+ await this.sleep(delayMs);
320
+ return this.invokeToolWithRetry(params, retryCount + 1);
321
+ }
322
+ // Record failure after all retries exhausted
323
+ this.recordFailure(error);
324
+ throw error;
325
+ }
326
+ }
327
+ /**
328
+ * Get current bot metrics
329
+ *
330
+ * Returns metrics for monitoring and debugging:
331
+ * - Total requests processed
332
+ * - Success count and rate
333
+ * - Timeout count and rate
334
+ * - Circuit breaker state
335
+ *
336
+ * @returns Metrics object
337
+ *
338
+ * @example
339
+ * ```typescript
340
+ * const metrics = this.getMetrics();
341
+ * console.log(`Success rate: ${metrics.successRate}%`);
342
+ * ```
343
+ */
344
+ getMetrics() {
345
+ const successRate = this.totalRequests > 0
346
+ ? (this.successCount / this.totalRequests) * 100
347
+ : 0;
348
+ const timeoutRate = this.totalRequests > 0
349
+ ? (this.timeoutCount / this.totalRequests) * 100
350
+ : 0;
351
+ return {
352
+ totalRequests: this.totalRequests,
353
+ successCount: this.successCount,
354
+ timeoutCount: this.timeoutCount,
355
+ successRate: parseFloat(successRate.toFixed(1)),
356
+ timeoutRate: parseFloat(timeoutRate.toFixed(1)),
357
+ isCircuitOpen: this.isCircuitOpen
358
+ };
359
+ }
360
+ /**
361
+ * Log timeout and success metrics
362
+ *
363
+ * Logs formatted metrics to console for monitoring.
364
+ * Called automatically every 10 requests or can be called manually.
365
+ */
366
+ logMetrics() {
367
+ const metrics = this.getMetrics();
368
+ console.log('📊 Bot Metrics:');
369
+ console.log(` Total Requests: ${metrics.totalRequests}`);
370
+ console.log(` Successes: ${metrics.successCount} (${metrics.successRate}%)`);
371
+ console.log(` Timeouts: ${metrics.timeoutCount} (${metrics.timeoutRate}%)`);
372
+ console.log(` Circuit Breaker: ${metrics.isCircuitOpen ? 'OPEN' : 'CLOSED'}`);
373
+ }
374
+ }
375
+ //# sourceMappingURL=base-bot.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-bot.js","sourceRoot":"","sources":["../src/base-bot.ts"],"names":[],"mappings":"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"}