@stackmemoryai/stackmemory 0.3.8 → 0.3.9
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/dist/core/context/recursive-context-manager.js +582 -0
- package/dist/core/context/recursive-context-manager.js.map +7 -0
- package/dist/core/execution/parallel-executor.js +254 -0
- package/dist/core/execution/parallel-executor.js.map +7 -0
- package/dist/integrations/anthropic/client.js +259 -0
- package/dist/integrations/anthropic/client.js.map +7 -0
- package/dist/integrations/claude-code/subagent-client.js +404 -0
- package/dist/integrations/claude-code/subagent-client.js.map +7 -0
- package/dist/skills/claude-skills.js +97 -0
- package/dist/skills/claude-skills.js.map +2 -2
- package/dist/skills/recursive-agent-orchestrator.js +559 -0
- package/dist/skills/recursive-agent-orchestrator.js.map +7 -0
- package/dist/skills/security-secrets-scanner.js +265 -0
- package/dist/skills/security-secrets-scanner.js.map +7 -0
- package/package.json +1 -1
|
@@ -0,0 +1,254 @@
|
|
|
1
|
+
import { EventEmitter } from "events";
|
|
2
|
+
import { logger } from "../monitoring/logger.js";
|
|
3
|
+
class ParallelExecutor extends EventEmitter {
|
|
4
|
+
maxConcurrency;
|
|
5
|
+
queueSize;
|
|
6
|
+
defaultTimeout;
|
|
7
|
+
defaultRetries;
|
|
8
|
+
rateLimitPerMinute;
|
|
9
|
+
activeCount = 0;
|
|
10
|
+
queue = [];
|
|
11
|
+
rateLimitTokens;
|
|
12
|
+
lastRateLimitReset;
|
|
13
|
+
// Metrics
|
|
14
|
+
totalExecuted = 0;
|
|
15
|
+
totalSucceeded = 0;
|
|
16
|
+
totalFailed = 0;
|
|
17
|
+
totalDuration = 0;
|
|
18
|
+
constructor(maxConcurrency = 5, options = {}) {
|
|
19
|
+
super();
|
|
20
|
+
this.maxConcurrency = maxConcurrency;
|
|
21
|
+
this.queueSize = options.queueSize || 100;
|
|
22
|
+
this.defaultTimeout = options.defaultTimeout || 3e5;
|
|
23
|
+
this.defaultRetries = options.defaultRetries || 3;
|
|
24
|
+
this.rateLimitPerMinute = options.rateLimitPerMinute || 60;
|
|
25
|
+
this.rateLimitTokens = this.rateLimitPerMinute;
|
|
26
|
+
this.lastRateLimitReset = Date.now();
|
|
27
|
+
logger.info("Parallel Executor initialized", {
|
|
28
|
+
maxConcurrency,
|
|
29
|
+
queueSize: this.queueSize,
|
|
30
|
+
rateLimitPerMinute: this.rateLimitPerMinute
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Execute multiple tasks in parallel
|
|
35
|
+
*/
|
|
36
|
+
async executeParallel(items, executor, options) {
|
|
37
|
+
const results = [];
|
|
38
|
+
const batchSize = options?.batchSize || this.maxConcurrency;
|
|
39
|
+
const delayBetweenBatches = options?.delayBetweenBatches || 0;
|
|
40
|
+
for (let i = 0; i < items.length; i += batchSize) {
|
|
41
|
+
const batch = items.slice(i, i + batchSize);
|
|
42
|
+
const batchPromises = batch.map(
|
|
43
|
+
(item, index) => this.executeWithTracking(
|
|
44
|
+
`parallel-${i + index}`,
|
|
45
|
+
() => executor(item, i + index)
|
|
46
|
+
)
|
|
47
|
+
);
|
|
48
|
+
const batchResults = await Promise.allSettled(batchPromises);
|
|
49
|
+
batchResults.forEach((result, index) => {
|
|
50
|
+
if (result.status === "fulfilled") {
|
|
51
|
+
results.push(result.value);
|
|
52
|
+
} else {
|
|
53
|
+
results.push({
|
|
54
|
+
taskId: `parallel-${i + index}`,
|
|
55
|
+
success: false,
|
|
56
|
+
error: result.reason,
|
|
57
|
+
duration: 0,
|
|
58
|
+
attempts: 1
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
});
|
|
62
|
+
if (delayBetweenBatches > 0 && i + batchSize < items.length) {
|
|
63
|
+
await this.delay(delayBetweenBatches);
|
|
64
|
+
}
|
|
65
|
+
logger.debug("Batch completed", {
|
|
66
|
+
batchNumber: Math.floor(i / batchSize) + 1,
|
|
67
|
+
totalBatches: Math.ceil(items.length / batchSize),
|
|
68
|
+
successRate: results.filter((r) => r.success).length / results.length
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return results;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Execute a single task with tracking and retries
|
|
75
|
+
*/
|
|
76
|
+
async executeWithTracking(taskId, executor, options) {
|
|
77
|
+
const timeout = options?.timeout || this.defaultTimeout;
|
|
78
|
+
const maxRetries = options?.retries || this.defaultRetries;
|
|
79
|
+
let attempts = 0;
|
|
80
|
+
let lastError;
|
|
81
|
+
const startTime = Date.now();
|
|
82
|
+
while (attempts < maxRetries) {
|
|
83
|
+
attempts++;
|
|
84
|
+
try {
|
|
85
|
+
await this.checkRateLimit();
|
|
86
|
+
await this.waitForSlot();
|
|
87
|
+
this.activeCount++;
|
|
88
|
+
this.emit("task-start", { taskId, attempt: attempts });
|
|
89
|
+
const result = await this.executeWithTimeout(executor, timeout);
|
|
90
|
+
this.totalSucceeded++;
|
|
91
|
+
this.emit("task-success", { taskId, attempts });
|
|
92
|
+
return {
|
|
93
|
+
taskId,
|
|
94
|
+
success: true,
|
|
95
|
+
result,
|
|
96
|
+
duration: Date.now() - startTime,
|
|
97
|
+
attempts
|
|
98
|
+
};
|
|
99
|
+
} catch (error) {
|
|
100
|
+
lastError = error;
|
|
101
|
+
logger.warn(`Task failed (attempt ${attempts}/${maxRetries})`, {
|
|
102
|
+
taskId,
|
|
103
|
+
error: lastError.message
|
|
104
|
+
});
|
|
105
|
+
this.emit("task-retry", { taskId, attempt: attempts, error: lastError });
|
|
106
|
+
if (attempts < maxRetries) {
|
|
107
|
+
await this.delay(Math.pow(2, attempts) * 1e3);
|
|
108
|
+
}
|
|
109
|
+
} finally {
|
|
110
|
+
this.activeCount--;
|
|
111
|
+
this.totalExecuted++;
|
|
112
|
+
this.totalDuration += Date.now() - startTime;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
this.totalFailed++;
|
|
116
|
+
this.emit("task-failed", { taskId, attempts, error: lastError });
|
|
117
|
+
return {
|
|
118
|
+
taskId,
|
|
119
|
+
success: false,
|
|
120
|
+
error: lastError,
|
|
121
|
+
duration: Date.now() - startTime,
|
|
122
|
+
attempts
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Execute task with timeout
|
|
127
|
+
*/
|
|
128
|
+
async executeWithTimeout(executor, timeout) {
|
|
129
|
+
return Promise.race([
|
|
130
|
+
executor(),
|
|
131
|
+
new Promise(
|
|
132
|
+
(_, reject) => setTimeout(() => reject(new Error("Task timeout")), timeout)
|
|
133
|
+
)
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Check and enforce rate limiting
|
|
138
|
+
*/
|
|
139
|
+
async checkRateLimit() {
|
|
140
|
+
const now = Date.now();
|
|
141
|
+
const timeSinceReset = now - this.lastRateLimitReset;
|
|
142
|
+
if (timeSinceReset >= 6e4) {
|
|
143
|
+
this.rateLimitTokens = this.rateLimitPerMinute;
|
|
144
|
+
this.lastRateLimitReset = now;
|
|
145
|
+
}
|
|
146
|
+
if (this.rateLimitTokens <= 0) {
|
|
147
|
+
const waitTime = 6e4 - timeSinceReset;
|
|
148
|
+
logger.debug(`Rate limit reached, waiting ${waitTime}ms`);
|
|
149
|
+
await this.delay(waitTime);
|
|
150
|
+
this.rateLimitTokens = this.rateLimitPerMinute;
|
|
151
|
+
this.lastRateLimitReset = Date.now();
|
|
152
|
+
}
|
|
153
|
+
this.rateLimitTokens--;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Wait for an available execution slot
|
|
157
|
+
*/
|
|
158
|
+
async waitForSlot() {
|
|
159
|
+
while (this.activeCount >= this.maxConcurrency) {
|
|
160
|
+
await this.delay(100);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
/**
|
|
164
|
+
* Queue a task for execution
|
|
165
|
+
*/
|
|
166
|
+
async queueTask(task) {
|
|
167
|
+
if (this.queue.length >= this.queueSize) {
|
|
168
|
+
throw new Error("Execution queue is full");
|
|
169
|
+
}
|
|
170
|
+
return new Promise((resolve) => {
|
|
171
|
+
this.queue.push({
|
|
172
|
+
...task,
|
|
173
|
+
execute: async () => {
|
|
174
|
+
const result = await task.execute();
|
|
175
|
+
resolve({
|
|
176
|
+
taskId: task.id,
|
|
177
|
+
success: true,
|
|
178
|
+
result,
|
|
179
|
+
duration: 0,
|
|
180
|
+
attempts: 1
|
|
181
|
+
});
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
});
|
|
185
|
+
this.processQueue();
|
|
186
|
+
});
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Process queued tasks
|
|
190
|
+
*/
|
|
191
|
+
async processQueue() {
|
|
192
|
+
if (this.activeCount >= this.maxConcurrency || this.queue.length === 0) {
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
this.queue.sort((a, b) => (b.priority || 0) - (a.priority || 0));
|
|
196
|
+
const task = this.queue.shift();
|
|
197
|
+
if (task) {
|
|
198
|
+
this.executeWithTracking(task.id, task.execute, {
|
|
199
|
+
timeout: task.timeout,
|
|
200
|
+
retries: task.retries
|
|
201
|
+
}).then(() => {
|
|
202
|
+
this.processQueue();
|
|
203
|
+
});
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
/**
|
|
207
|
+
* Utility delay function
|
|
208
|
+
*/
|
|
209
|
+
delay(ms) {
|
|
210
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
211
|
+
}
|
|
212
|
+
/**
|
|
213
|
+
* Get execution metrics
|
|
214
|
+
*/
|
|
215
|
+
getMetrics() {
|
|
216
|
+
return {
|
|
217
|
+
activeCount: this.activeCount,
|
|
218
|
+
queueLength: this.queue.length,
|
|
219
|
+
totalExecuted: this.totalExecuted,
|
|
220
|
+
totalSucceeded: this.totalSucceeded,
|
|
221
|
+
totalFailed: this.totalFailed,
|
|
222
|
+
successRate: this.totalExecuted > 0 ? this.totalSucceeded / this.totalExecuted : 0,
|
|
223
|
+
averageDuration: this.totalExecuted > 0 ? this.totalDuration / this.totalExecuted : 0,
|
|
224
|
+
rateLimitTokens: this.rateLimitTokens
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Reset all metrics
|
|
229
|
+
*/
|
|
230
|
+
resetMetrics() {
|
|
231
|
+
this.totalExecuted = 0;
|
|
232
|
+
this.totalSucceeded = 0;
|
|
233
|
+
this.totalFailed = 0;
|
|
234
|
+
this.totalDuration = 0;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Gracefully shutdown executor
|
|
238
|
+
*/
|
|
239
|
+
async shutdown() {
|
|
240
|
+
logger.info("Shutting down Parallel Executor", {
|
|
241
|
+
activeCount: this.activeCount,
|
|
242
|
+
queueLength: this.queue.length
|
|
243
|
+
});
|
|
244
|
+
this.queue = [];
|
|
245
|
+
while (this.activeCount > 0) {
|
|
246
|
+
await this.delay(100);
|
|
247
|
+
}
|
|
248
|
+
logger.info("Parallel Executor shutdown complete");
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
export {
|
|
252
|
+
ParallelExecutor
|
|
253
|
+
};
|
|
254
|
+
//# sourceMappingURL=parallel-executor.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/core/execution/parallel-executor.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Parallel Execution Engine for RLM\n * \n * Manages concurrent execution of multiple Claude API calls\n * with rate limiting, resource pooling, and failure recovery\n */\n\nimport { EventEmitter } from 'events';\nimport { logger } from '../monitoring/logger.js';\n\nexport interface ExecutionTask<T> {\n id: string;\n execute: () => Promise<T>;\n priority?: number;\n timeout?: number;\n retries?: number;\n}\n\nexport interface ExecutionResult<T> {\n taskId: string;\n success: boolean;\n result?: T;\n error?: Error;\n duration: number;\n attempts: number;\n}\n\nexport interface ParallelExecutorOptions {\n maxConcurrency?: number;\n queueSize?: number;\n defaultTimeout?: number;\n defaultRetries?: number;\n rateLimitPerMinute?: number;\n}\n\n/**\n * Parallel Executor for managing concurrent operations\n */\nexport class ParallelExecutor extends EventEmitter {\n private maxConcurrency: number;\n private queueSize: number;\n private defaultTimeout: number;\n private defaultRetries: number;\n private rateLimitPerMinute: number;\n \n private activeCount: number = 0;\n private queue: ExecutionTask<any>[] = [];\n private rateLimitTokens: number;\n private lastRateLimitReset: number;\n \n // Metrics\n private totalExecuted: number = 0;\n private totalSucceeded: number = 0;\n private totalFailed: number = 0;\n private totalDuration: number = 0;\n\n constructor(maxConcurrency: number = 5, options: ParallelExecutorOptions = {}) {\n super();\n \n this.maxConcurrency = maxConcurrency;\n this.queueSize = options.queueSize || 100;\n this.defaultTimeout = options.defaultTimeout || 300000; // 5 minutes\n this.defaultRetries = options.defaultRetries || 3;\n this.rateLimitPerMinute = options.rateLimitPerMinute || 60;\n \n this.rateLimitTokens = this.rateLimitPerMinute;\n this.lastRateLimitReset = Date.now();\n \n logger.info('Parallel Executor initialized', {\n maxConcurrency,\n queueSize: this.queueSize,\n rateLimitPerMinute: this.rateLimitPerMinute,\n });\n }\n \n /**\n * Execute multiple tasks in parallel\n */\n async executeParallel<T>(\n items: T[],\n executor: (item: T, index: number) => Promise<void>,\n options?: {\n batchSize?: number;\n delayBetweenBatches?: number;\n }\n ): Promise<ExecutionResult<void>[]> {\n const results: ExecutionResult<void>[] = [];\n const batchSize = options?.batchSize || this.maxConcurrency;\n const delayBetweenBatches = options?.delayBetweenBatches || 0;\n \n // Process items in batches\n for (let i = 0; i < items.length; i += batchSize) {\n const batch = items.slice(i, i + batchSize);\n const batchPromises = batch.map((item, index) => \n this.executeWithTracking(\n `parallel-${i + index}`,\n () => executor(item, i + index)\n )\n );\n \n const batchResults = await Promise.allSettled(batchPromises);\n \n // Convert to ExecutionResult format\n batchResults.forEach((result, index) => {\n if (result.status === 'fulfilled') {\n results.push(result.value);\n } else {\n results.push({\n taskId: `parallel-${i + index}`,\n success: false,\n error: result.reason,\n duration: 0,\n attempts: 1,\n });\n }\n });\n \n // Delay between batches if specified\n if (delayBetweenBatches > 0 && i + batchSize < items.length) {\n await this.delay(delayBetweenBatches);\n }\n \n // Log batch progress\n logger.debug('Batch completed', {\n batchNumber: Math.floor(i / batchSize) + 1,\n totalBatches: Math.ceil(items.length / batchSize),\n successRate: results.filter(r => r.success).length / results.length,\n });\n }\n \n return results;\n }\n \n /**\n * Execute a single task with tracking and retries\n */\n async executeWithTracking<T>(\n taskId: string,\n executor: () => Promise<T>,\n options?: {\n timeout?: number;\n retries?: number;\n }\n ): Promise<ExecutionResult<T>> {\n const timeout = options?.timeout || this.defaultTimeout;\n const maxRetries = options?.retries || this.defaultRetries;\n \n let attempts = 0;\n let lastError: Error | undefined;\n const startTime = Date.now();\n \n while (attempts < maxRetries) {\n attempts++;\n \n try {\n // Check rate limit\n await this.checkRateLimit();\n \n // Wait for available slot\n await this.waitForSlot();\n \n this.activeCount++;\n this.emit('task-start', { taskId, attempt: attempts });\n \n // Execute with timeout\n const result = await this.executeWithTimeout(executor, timeout);\n \n // Success\n this.totalSucceeded++;\n this.emit('task-success', { taskId, attempts });\n \n return {\n taskId,\n success: true,\n result,\n duration: Date.now() - startTime,\n attempts,\n };\n \n } catch (error) {\n lastError = error as Error;\n \n logger.warn(`Task failed (attempt ${attempts}/${maxRetries})`, {\n taskId,\n error: lastError.message,\n });\n \n this.emit('task-retry', { taskId, attempt: attempts, error: lastError });\n \n // Exponential backoff for retries\n if (attempts < maxRetries) {\n await this.delay(Math.pow(2, attempts) * 1000);\n }\n \n } finally {\n this.activeCount--;\n this.totalExecuted++;\n this.totalDuration += Date.now() - startTime;\n }\n }\n \n // All retries exhausted\n this.totalFailed++;\n this.emit('task-failed', { taskId, attempts, error: lastError });\n \n return {\n taskId,\n success: false,\n error: lastError,\n duration: Date.now() - startTime,\n attempts,\n };\n }\n \n /**\n * Execute task with timeout\n */\n private async executeWithTimeout<T>(\n executor: () => Promise<T>,\n timeout: number\n ): Promise<T> {\n return Promise.race([\n executor(),\n new Promise<T>((_, reject) => \n setTimeout(() => reject(new Error('Task timeout')), timeout)\n ),\n ]);\n }\n \n /**\n * Check and enforce rate limiting\n */\n private async checkRateLimit(): Promise<void> {\n const now = Date.now();\n const timeSinceReset = now - this.lastRateLimitReset;\n \n // Reset tokens if a minute has passed\n if (timeSinceReset >= 60000) {\n this.rateLimitTokens = this.rateLimitPerMinute;\n this.lastRateLimitReset = now;\n }\n \n // Wait if no tokens available\n if (this.rateLimitTokens <= 0) {\n const waitTime = 60000 - timeSinceReset;\n logger.debug(`Rate limit reached, waiting ${waitTime}ms`);\n await this.delay(waitTime);\n \n // Reset after waiting\n this.rateLimitTokens = this.rateLimitPerMinute;\n this.lastRateLimitReset = Date.now();\n }\n \n this.rateLimitTokens--;\n }\n \n /**\n * Wait for an available execution slot\n */\n private async waitForSlot(): Promise<void> {\n while (this.activeCount >= this.maxConcurrency) {\n await this.delay(100); // Check every 100ms\n }\n }\n \n /**\n * Queue a task for execution\n */\n async queueTask<T>(task: ExecutionTask<T>): Promise<ExecutionResult<T>> {\n if (this.queue.length >= this.queueSize) {\n throw new Error('Execution queue is full');\n }\n \n return new Promise((resolve) => {\n this.queue.push({\n ...task,\n execute: async () => {\n const result = await task.execute();\n resolve({\n taskId: task.id,\n success: true,\n result,\n duration: 0,\n attempts: 1,\n });\n return result;\n },\n });\n \n this.processQueue();\n });\n }\n \n /**\n * Process queued tasks\n */\n private async processQueue(): Promise<void> {\n if (this.activeCount >= this.maxConcurrency || this.queue.length === 0) {\n return;\n }\n \n // Sort by priority (higher first)\n this.queue.sort((a, b) => (b.priority || 0) - (a.priority || 0));\n \n const task = this.queue.shift();\n if (task) {\n this.executeWithTracking(task.id, task.execute, {\n timeout: task.timeout,\n retries: task.retries,\n }).then(() => {\n this.processQueue(); // Process next task\n });\n }\n }\n \n /**\n * Utility delay function\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n \n /**\n * Get execution metrics\n */\n getMetrics() {\n return {\n activeCount: this.activeCount,\n queueLength: this.queue.length,\n totalExecuted: this.totalExecuted,\n totalSucceeded: this.totalSucceeded,\n totalFailed: this.totalFailed,\n successRate: this.totalExecuted > 0 ? this.totalSucceeded / this.totalExecuted : 0,\n averageDuration: this.totalExecuted > 0 ? this.totalDuration / this.totalExecuted : 0,\n rateLimitTokens: this.rateLimitTokens,\n };\n }\n \n /**\n * Reset all metrics\n */\n resetMetrics(): void {\n this.totalExecuted = 0;\n this.totalSucceeded = 0;\n this.totalFailed = 0;\n this.totalDuration = 0;\n }\n \n /**\n * Gracefully shutdown executor\n */\n async shutdown(): Promise<void> {\n logger.info('Shutting down Parallel Executor', {\n activeCount: this.activeCount,\n queueLength: this.queue.length,\n });\n \n // Clear queue\n this.queue = [];\n \n // Wait for active tasks to complete\n while (this.activeCount > 0) {\n await this.delay(100);\n }\n \n logger.info('Parallel Executor shutdown complete');\n }\n}"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
import { logger } from "../../core/monitoring/logger.js";
|
|
2
|
+
class AnthropicClient {
|
|
3
|
+
apiKey;
|
|
4
|
+
baseURL;
|
|
5
|
+
maxRetries;
|
|
6
|
+
timeout;
|
|
7
|
+
// Rate limiting
|
|
8
|
+
requestCount = 0;
|
|
9
|
+
lastResetTime = Date.now();
|
|
10
|
+
rateLimitPerMinute = 60;
|
|
11
|
+
constructor(config) {
|
|
12
|
+
this.apiKey = config?.apiKey || process.env["ANTHROPIC_API_KEY"] || "";
|
|
13
|
+
this.baseURL = config?.baseURL || "https://api.anthropic.com";
|
|
14
|
+
this.maxRetries = config?.maxRetries || 3;
|
|
15
|
+
this.timeout = config?.timeout || 6e4;
|
|
16
|
+
if (!this.apiKey) {
|
|
17
|
+
logger.warn("Anthropic API key not configured. Using mock mode.");
|
|
18
|
+
}
|
|
19
|
+
logger.info("Anthropic client initialized", {
|
|
20
|
+
baseURL: this.baseURL,
|
|
21
|
+
maxRetries: this.maxRetries,
|
|
22
|
+
timeout: this.timeout,
|
|
23
|
+
mockMode: !this.apiKey
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Send completion request to Claude
|
|
28
|
+
*/
|
|
29
|
+
async complete(request) {
|
|
30
|
+
await this.checkRateLimit();
|
|
31
|
+
logger.debug("Sending completion request", {
|
|
32
|
+
model: request.model,
|
|
33
|
+
promptLength: request.prompt.length,
|
|
34
|
+
maxTokens: request.maxTokens
|
|
35
|
+
});
|
|
36
|
+
if (!this.apiKey) {
|
|
37
|
+
return this.mockComplete(request);
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const response = await this.sendRequest(request);
|
|
41
|
+
return response.content;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
logger.error("Anthropic API error", { error });
|
|
44
|
+
throw error;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Send request with retry logic
|
|
49
|
+
*/
|
|
50
|
+
async sendRequest(request, attempt = 1) {
|
|
51
|
+
try {
|
|
52
|
+
return this.createMockResponse(request);
|
|
53
|
+
} catch (error) {
|
|
54
|
+
if (attempt < this.maxRetries) {
|
|
55
|
+
const delay = Math.pow(2, attempt) * 1e3;
|
|
56
|
+
logger.warn(`Retrying after ${delay}ms (attempt ${attempt}/${this.maxRetries})`);
|
|
57
|
+
await this.delay(delay);
|
|
58
|
+
return this.sendRequest(request, attempt + 1);
|
|
59
|
+
}
|
|
60
|
+
throw error;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Mock completion for development/testing
|
|
65
|
+
*/
|
|
66
|
+
async mockComplete(request) {
|
|
67
|
+
await this.delay(500 + Math.random() * 1500);
|
|
68
|
+
if (request.systemPrompt.includes("Planning Agent")) {
|
|
69
|
+
return this.mockPlanningResponse(request.prompt);
|
|
70
|
+
} else if (request.systemPrompt.includes("Code Agent")) {
|
|
71
|
+
return this.mockCodeResponse(request.prompt);
|
|
72
|
+
} else if (request.systemPrompt.includes("Testing Agent")) {
|
|
73
|
+
return this.mockTestingResponse(request.prompt);
|
|
74
|
+
} else if (request.systemPrompt.includes("Review Agent")) {
|
|
75
|
+
return this.mockReviewResponse(request.prompt);
|
|
76
|
+
} else {
|
|
77
|
+
return `Mock response for: ${request.prompt.slice(0, 100)}...`;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Mock response generators
|
|
82
|
+
*/
|
|
83
|
+
mockPlanningResponse(prompt) {
|
|
84
|
+
return JSON.stringify({
|
|
85
|
+
plan: {
|
|
86
|
+
type: "sequential",
|
|
87
|
+
tasks: [
|
|
88
|
+
{
|
|
89
|
+
id: "task-1",
|
|
90
|
+
description: "Analyze requirements",
|
|
91
|
+
agent: "context",
|
|
92
|
+
dependencies: []
|
|
93
|
+
},
|
|
94
|
+
{
|
|
95
|
+
id: "task-2",
|
|
96
|
+
type: "parallel",
|
|
97
|
+
description: "Implementation phase",
|
|
98
|
+
children: [
|
|
99
|
+
{
|
|
100
|
+
id: "task-2a",
|
|
101
|
+
description: "Write core logic",
|
|
102
|
+
agent: "code",
|
|
103
|
+
dependencies: ["task-1"]
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
id: "task-2b",
|
|
107
|
+
description: "Write tests",
|
|
108
|
+
agent: "testing",
|
|
109
|
+
dependencies: ["task-1"]
|
|
110
|
+
}
|
|
111
|
+
]
|
|
112
|
+
},
|
|
113
|
+
{
|
|
114
|
+
id: "task-3",
|
|
115
|
+
description: "Review and improve",
|
|
116
|
+
agent: "review",
|
|
117
|
+
dependencies: ["task-2"]
|
|
118
|
+
}
|
|
119
|
+
]
|
|
120
|
+
}
|
|
121
|
+
}, null, 2);
|
|
122
|
+
}
|
|
123
|
+
mockCodeResponse(prompt) {
|
|
124
|
+
return `
|
|
125
|
+
// Mock implementation
|
|
126
|
+
export function processTask(input: string): string {
|
|
127
|
+
// TODO: Implement actual logic
|
|
128
|
+
console.log('Processing:', input);
|
|
129
|
+
return \`Processed: \${input}\`;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
export function validateInput(input: unknown): boolean {
|
|
133
|
+
return typeof input === 'string' && input.length > 0;
|
|
134
|
+
}
|
|
135
|
+
`.trim();
|
|
136
|
+
}
|
|
137
|
+
mockTestingResponse(prompt) {
|
|
138
|
+
return `
|
|
139
|
+
import { describe, test, expect } from 'vitest';
|
|
140
|
+
import { processTask, validateInput } from './implementation';
|
|
141
|
+
|
|
142
|
+
describe('processTask', () => {
|
|
143
|
+
test('should process valid input', () => {
|
|
144
|
+
const result = processTask('test input');
|
|
145
|
+
expect(result).toBe('Processed: test input');
|
|
146
|
+
});
|
|
147
|
+
|
|
148
|
+
test('should handle empty input', () => {
|
|
149
|
+
const result = processTask('');
|
|
150
|
+
expect(result).toBe('Processed: ');
|
|
151
|
+
});
|
|
152
|
+
});
|
|
153
|
+
|
|
154
|
+
describe('validateInput', () => {
|
|
155
|
+
test('should validate string input', () => {
|
|
156
|
+
expect(validateInput('valid')).toBe(true);
|
|
157
|
+
expect(validateInput('')).toBe(false);
|
|
158
|
+
expect(validateInput(123)).toBe(false);
|
|
159
|
+
expect(validateInput(null)).toBe(false);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
`.trim();
|
|
163
|
+
}
|
|
164
|
+
mockReviewResponse(prompt) {
|
|
165
|
+
return JSON.stringify({
|
|
166
|
+
quality: 0.75,
|
|
167
|
+
issues: [
|
|
168
|
+
"Missing error handling in processTask function",
|
|
169
|
+
"No input validation before processing",
|
|
170
|
+
"Tests could cover more edge cases"
|
|
171
|
+
],
|
|
172
|
+
suggestions: [
|
|
173
|
+
"Add try-catch block in processTask",
|
|
174
|
+
"Validate input length and type",
|
|
175
|
+
"Add tests for special characters and long inputs",
|
|
176
|
+
"Consider adding performance tests"
|
|
177
|
+
],
|
|
178
|
+
improvements: [
|
|
179
|
+
{
|
|
180
|
+
file: "implementation.ts",
|
|
181
|
+
line: 3,
|
|
182
|
+
suggestion: "Add input validation",
|
|
183
|
+
priority: "high"
|
|
184
|
+
},
|
|
185
|
+
{
|
|
186
|
+
file: "tests.ts",
|
|
187
|
+
line: 15,
|
|
188
|
+
suggestion: "Add edge case tests",
|
|
189
|
+
priority: "medium"
|
|
190
|
+
}
|
|
191
|
+
]
|
|
192
|
+
}, null, 2);
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Create mock response object
|
|
196
|
+
*/
|
|
197
|
+
createMockResponse(request) {
|
|
198
|
+
const content = this.mockComplete(request).toString();
|
|
199
|
+
return {
|
|
200
|
+
content,
|
|
201
|
+
stopReason: "stop_sequence",
|
|
202
|
+
model: request.model,
|
|
203
|
+
usage: {
|
|
204
|
+
inputTokens: Math.ceil(request.prompt.length / 4),
|
|
205
|
+
outputTokens: Math.ceil(content.length / 4)
|
|
206
|
+
}
|
|
207
|
+
};
|
|
208
|
+
}
|
|
209
|
+
/**
|
|
210
|
+
* Check rate limiting
|
|
211
|
+
*/
|
|
212
|
+
async checkRateLimit() {
|
|
213
|
+
const now = Date.now();
|
|
214
|
+
const timeSinceReset = now - this.lastResetTime;
|
|
215
|
+
if (timeSinceReset >= 6e4) {
|
|
216
|
+
this.requestCount = 0;
|
|
217
|
+
this.lastResetTime = now;
|
|
218
|
+
}
|
|
219
|
+
if (this.requestCount >= this.rateLimitPerMinute) {
|
|
220
|
+
const waitTime = 6e4 - timeSinceReset;
|
|
221
|
+
logger.warn(`Rate limit reached, waiting ${waitTime}ms`);
|
|
222
|
+
await this.delay(waitTime);
|
|
223
|
+
this.requestCount = 0;
|
|
224
|
+
this.lastResetTime = Date.now();
|
|
225
|
+
}
|
|
226
|
+
this.requestCount++;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Stream completion response
|
|
230
|
+
*/
|
|
231
|
+
async *streamComplete(request) {
|
|
232
|
+
const response = await this.complete(request);
|
|
233
|
+
const words = response.split(" ");
|
|
234
|
+
for (const word of words) {
|
|
235
|
+
yield word + " ";
|
|
236
|
+
await this.delay(50);
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
/**
|
|
240
|
+
* Utility delay function
|
|
241
|
+
*/
|
|
242
|
+
delay(ms) {
|
|
243
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Get API usage statistics
|
|
247
|
+
*/
|
|
248
|
+
getUsageStats() {
|
|
249
|
+
return {
|
|
250
|
+
requestCount: this.requestCount,
|
|
251
|
+
rateLimitRemaining: this.rateLimitPerMinute - this.requestCount,
|
|
252
|
+
resetTime: new Date(this.lastResetTime + 6e4).toISOString()
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
export {
|
|
257
|
+
AnthropicClient
|
|
258
|
+
};
|
|
259
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../src/integrations/anthropic/client.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Anthropic API Client for Claude Integration\n * \n * Manages API calls to Claude with retry logic, rate limiting,\n * and response streaming\n */\n\nimport { logger } from '../../core/monitoring/logger.js';\n\nexport interface CompletionRequest {\n model: string;\n systemPrompt: string;\n prompt: string;\n maxTokens: number;\n temperature: number;\n stream?: boolean;\n}\n\nexport interface CompletionResponse {\n content: string;\n stopReason: string;\n model: string;\n usage: {\n inputTokens: number;\n outputTokens: number;\n };\n}\n\nexport interface AnthropicClientConfig {\n apiKey?: string;\n baseURL?: string;\n maxRetries?: number;\n timeout?: number;\n}\n\n/**\n * Anthropic API Client\n * \n * NOTE: This is a mock implementation. In production, you would:\n * 1. Install @anthropic-ai/sdk: npm install @anthropic-ai/sdk\n * 2. Use the actual SDK methods\n * 3. Handle real API responses\n */\nexport class AnthropicClient {\n private apiKey: string;\n private baseURL: string;\n private maxRetries: number;\n private timeout: number;\n \n // Rate limiting\n private requestCount: number = 0;\n private lastResetTime: number = Date.now();\n private rateLimitPerMinute: number = 60;\n \n constructor(config?: AnthropicClientConfig) {\n this.apiKey = config?.apiKey || process.env['ANTHROPIC_API_KEY'] || '';\n this.baseURL = config?.baseURL || 'https://api.anthropic.com';\n this.maxRetries = config?.maxRetries || 3;\n this.timeout = config?.timeout || 60000;\n \n if (!this.apiKey) {\n logger.warn('Anthropic API key not configured. Using mock mode.');\n }\n \n logger.info('Anthropic client initialized', {\n baseURL: this.baseURL,\n maxRetries: this.maxRetries,\n timeout: this.timeout,\n mockMode: !this.apiKey,\n });\n }\n \n /**\n * Send completion request to Claude\n */\n async complete(request: CompletionRequest): Promise<string> {\n // Rate limiting check\n await this.checkRateLimit();\n \n logger.debug('Sending completion request', {\n model: request.model,\n promptLength: request.prompt.length,\n maxTokens: request.maxTokens,\n });\n \n // Mock implementation for development\n if (!this.apiKey) {\n return this.mockComplete(request);\n }\n \n // Real implementation would use Anthropic SDK\n try {\n const response = await this.sendRequest(request);\n return response.content;\n } catch (error) {\n logger.error('Anthropic API error', { error });\n throw error;\n }\n }\n \n /**\n * Send request with retry logic\n */\n private async sendRequest(\n request: CompletionRequest,\n attempt: number = 1\n ): Promise<CompletionResponse> {\n try {\n // In production, use actual Anthropic SDK:\n /*\n import Anthropic from '@anthropic-ai/sdk';\n \n const anthropic = new Anthropic({\n apiKey: this.apiKey,\n });\n \n const response = await anthropic.messages.create({\n model: request.model,\n system: request.systemPrompt,\n messages: [{ role: 'user', content: request.prompt }],\n max_tokens: request.maxTokens,\n temperature: request.temperature,\n });\n \n return {\n content: response.content[0].text,\n stopReason: response.stop_reason,\n model: response.model,\n usage: {\n inputTokens: response.usage.input_tokens,\n outputTokens: response.usage.output_tokens,\n },\n };\n */\n \n // Mock response for now\n return this.createMockResponse(request);\n \n } catch (error: any) {\n if (attempt < this.maxRetries) {\n const delay = Math.pow(2, attempt) * 1000;\n logger.warn(`Retrying after ${delay}ms (attempt ${attempt}/${this.maxRetries})`);\n await this.delay(delay);\n return this.sendRequest(request, attempt + 1);\n }\n throw error;\n }\n }\n \n /**\n * Mock completion for development/testing\n */\n private async mockComplete(request: CompletionRequest): Promise<string> {\n // Simulate API delay\n await this.delay(500 + Math.random() * 1500);\n \n // Generate mock response based on agent type\n if (request.systemPrompt.includes('Planning Agent')) {\n return this.mockPlanningResponse(request.prompt);\n } else if (request.systemPrompt.includes('Code Agent')) {\n return this.mockCodeResponse(request.prompt);\n } else if (request.systemPrompt.includes('Testing Agent')) {\n return this.mockTestingResponse(request.prompt);\n } else if (request.systemPrompt.includes('Review Agent')) {\n return this.mockReviewResponse(request.prompt);\n } else {\n return `Mock response for: ${request.prompt.slice(0, 100)}...`;\n }\n }\n \n /**\n * Mock response generators\n */\n \n private mockPlanningResponse(prompt: string): string {\n return JSON.stringify({\n plan: {\n type: 'sequential',\n tasks: [\n {\n id: 'task-1',\n description: 'Analyze requirements',\n agent: 'context',\n dependencies: [],\n },\n {\n id: 'task-2',\n type: 'parallel',\n description: 'Implementation phase',\n children: [\n {\n id: 'task-2a',\n description: 'Write core logic',\n agent: 'code',\n dependencies: ['task-1'],\n },\n {\n id: 'task-2b',\n description: 'Write tests',\n agent: 'testing',\n dependencies: ['task-1'],\n },\n ],\n },\n {\n id: 'task-3',\n description: 'Review and improve',\n agent: 'review',\n dependencies: ['task-2'],\n },\n ],\n },\n }, null, 2);\n }\n \n private mockCodeResponse(prompt: string): string {\n return `\n// Mock implementation\nexport function processTask(input: string): string {\n // TODO: Implement actual logic\n console.log('Processing:', input);\n return \\`Processed: \\${input}\\`;\n}\n\nexport function validateInput(input: unknown): boolean {\n return typeof input === 'string' && input.length > 0;\n}\n `.trim();\n }\n \n private mockTestingResponse(prompt: string): string {\n return `\nimport { describe, test, expect } from 'vitest';\nimport { processTask, validateInput } from './implementation';\n\ndescribe('processTask', () => {\n test('should process valid input', () => {\n const result = processTask('test input');\n expect(result).toBe('Processed: test input');\n });\n \n test('should handle empty input', () => {\n const result = processTask('');\n expect(result).toBe('Processed: ');\n });\n});\n\ndescribe('validateInput', () => {\n test('should validate string input', () => {\n expect(validateInput('valid')).toBe(true);\n expect(validateInput('')).toBe(false);\n expect(validateInput(123)).toBe(false);\n expect(validateInput(null)).toBe(false);\n });\n});\n `.trim();\n }\n \n private mockReviewResponse(prompt: string): string {\n return JSON.stringify({\n quality: 0.75,\n issues: [\n 'Missing error handling in processTask function',\n 'No input validation before processing',\n 'Tests could cover more edge cases',\n ],\n suggestions: [\n 'Add try-catch block in processTask',\n 'Validate input length and type',\n 'Add tests for special characters and long inputs',\n 'Consider adding performance tests',\n ],\n improvements: [\n {\n file: 'implementation.ts',\n line: 3,\n suggestion: 'Add input validation',\n priority: 'high',\n },\n {\n file: 'tests.ts',\n line: 15,\n suggestion: 'Add edge case tests',\n priority: 'medium',\n },\n ],\n }, null, 2);\n }\n \n /**\n * Create mock response object\n */\n private createMockResponse(request: CompletionRequest): CompletionResponse {\n const content = this.mockComplete(request).toString();\n \n return {\n content,\n stopReason: 'stop_sequence',\n model: request.model,\n usage: {\n inputTokens: Math.ceil(request.prompt.length / 4),\n outputTokens: Math.ceil(content.length / 4),\n },\n };\n }\n \n /**\n * Check rate limiting\n */\n private async checkRateLimit(): Promise<void> {\n const now = Date.now();\n const timeSinceReset = now - this.lastResetTime;\n \n if (timeSinceReset >= 60000) {\n this.requestCount = 0;\n this.lastResetTime = now;\n }\n \n if (this.requestCount >= this.rateLimitPerMinute) {\n const waitTime = 60000 - timeSinceReset;\n logger.warn(`Rate limit reached, waiting ${waitTime}ms`);\n await this.delay(waitTime);\n this.requestCount = 0;\n this.lastResetTime = Date.now();\n }\n \n this.requestCount++;\n }\n \n /**\n * Stream completion response\n */\n async *streamComplete(request: CompletionRequest): AsyncGenerator<string> {\n // Mock streaming implementation\n const response = await this.complete(request);\n const words = response.split(' ');\n \n for (const word of words) {\n yield word + ' ';\n await this.delay(50); // Simulate streaming delay\n }\n }\n \n /**\n * Utility delay function\n */\n private delay(ms: number): Promise<void> {\n return new Promise(resolve => setTimeout(resolve, ms));\n }\n \n /**\n * Get API usage statistics\n */\n getUsageStats() {\n return {\n requestCount: this.requestCount,\n rateLimitRemaining: this.rateLimitPerMinute - this.requestCount,\n resetTime: new Date(this.lastResetTime + 60000).toISOString(),\n };\n }\n}"],
|
|
5
|
+
"mappings": "AAOA,SAAS,cAAc;AAoChB,MAAM,gBAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA,eAAuB;AAAA,EACvB,gBAAwB,KAAK,IAAI;AAAA,EACjC,qBAA6B;AAAA,EAErC,YAAY,QAAgC;AAC1C,SAAK,SAAS,QAAQ,UAAU,QAAQ,IAAI,mBAAmB,KAAK;AACpE,SAAK,UAAU,QAAQ,WAAW;AAClC,SAAK,aAAa,QAAQ,cAAc;AACxC,SAAK,UAAU,QAAQ,WAAW;AAElC,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,KAAK,oDAAoD;AAAA,IAClE;AAEA,WAAO,KAAK,gCAAgC;AAAA,MAC1C,SAAS,KAAK;AAAA,MACd,YAAY,KAAK;AAAA,MACjB,SAAS,KAAK;AAAA,MACd,UAAU,CAAC,KAAK;AAAA,IAClB,CAAC;AAAA,EACH;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,SAAS,SAA6C;AAE1D,UAAM,KAAK,eAAe;AAE1B,WAAO,MAAM,8BAA8B;AAAA,MACzC,OAAO,QAAQ;AAAA,MACf,cAAc,QAAQ,OAAO;AAAA,MAC7B,WAAW,QAAQ;AAAA,IACrB,CAAC;AAGD,QAAI,CAAC,KAAK,QAAQ;AAChB,aAAO,KAAK,aAAa,OAAO;AAAA,IAClC;AAGA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,YAAY,OAAO;AAC/C,aAAO,SAAS;AAAA,IAClB,SAAS,OAAO;AACd,aAAO,MAAM,uBAAuB,EAAE,MAAM,CAAC;AAC7C,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,YACZ,SACA,UAAkB,GACW;AAC7B,QAAI;AA6BF,aAAO,KAAK,mBAAmB,OAAO;AAAA,IAExC,SAAS,OAAY;AACnB,UAAI,UAAU,KAAK,YAAY;AAC7B,cAAM,QAAQ,KAAK,IAAI,GAAG,OAAO,IAAI;AACrC,eAAO,KAAK,kBAAkB,KAAK,eAAe,OAAO,IAAI,KAAK,UAAU,GAAG;AAC/E,cAAM,KAAK,MAAM,KAAK;AACtB,eAAO,KAAK,YAAY,SAAS,UAAU,CAAC;AAAA,MAC9C;AACA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,aAAa,SAA6C;AAEtE,UAAM,KAAK,MAAM,MAAM,KAAK,OAAO,IAAI,IAAI;AAG3C,QAAI,QAAQ,aAAa,SAAS,gBAAgB,GAAG;AACnD,aAAO,KAAK,qBAAqB,QAAQ,MAAM;AAAA,IACjD,WAAW,QAAQ,aAAa,SAAS,YAAY,GAAG;AACtD,aAAO,KAAK,iBAAiB,QAAQ,MAAM;AAAA,IAC7C,WAAW,QAAQ,aAAa,SAAS,eAAe,GAAG;AACzD,aAAO,KAAK,oBAAoB,QAAQ,MAAM;AAAA,IAChD,WAAW,QAAQ,aAAa,SAAS,cAAc,GAAG;AACxD,aAAO,KAAK,mBAAmB,QAAQ,MAAM;AAAA,IAC/C,OAAO;AACL,aAAO,sBAAsB,QAAQ,OAAO,MAAM,GAAG,GAAG,CAAC;AAAA,IAC3D;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAMQ,qBAAqB,QAAwB;AACnD,WAAO,KAAK,UAAU;AAAA,MACpB,MAAM;AAAA,QACJ,MAAM;AAAA,QACN,OAAO;AAAA,UACL;AAAA,YACE,IAAI;AAAA,YACJ,aAAa;AAAA,YACb,OAAO;AAAA,YACP,cAAc,CAAC;AAAA,UACjB;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,MAAM;AAAA,YACN,aAAa;AAAA,YACb,UAAU;AAAA,cACR;AAAA,gBACE,IAAI;AAAA,gBACJ,aAAa;AAAA,gBACb,OAAO;AAAA,gBACP,cAAc,CAAC,QAAQ;AAAA,cACzB;AAAA,cACA;AAAA,gBACE,IAAI;AAAA,gBACJ,aAAa;AAAA,gBACb,OAAO;AAAA,gBACP,cAAc,CAAC,QAAQ;AAAA,cACzB;AAAA,YACF;AAAA,UACF;AAAA,UACA;AAAA,YACE,IAAI;AAAA,YACJ,aAAa;AAAA,YACb,OAAO;AAAA,YACP,cAAc,CAAC,QAAQ;AAAA,UACzB;AAAA,QACF;AAAA,MACF;AAAA,IACF,GAAG,MAAM,CAAC;AAAA,EACZ;AAAA,EAEQ,iBAAiB,QAAwB;AAC/C,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAWL,KAAK;AAAA,EACT;AAAA,EAEQ,oBAAoB,QAAwB;AAClD,WAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAwBL,KAAK;AAAA,EACT;AAAA,EAEQ,mBAAmB,QAAwB;AACjD,WAAO,KAAK,UAAU;AAAA,MACpB,SAAS;AAAA,MACT,QAAQ;AAAA,QACN;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,aAAa;AAAA,QACX;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AAAA,MACA,cAAc;AAAA,QACZ;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,QACZ;AAAA,QACA;AAAA,UACE,MAAM;AAAA,UACN,MAAM;AAAA,UACN,YAAY;AAAA,UACZ,UAAU;AAAA,QACZ;AAAA,MACF;AAAA,IACF,GAAG,MAAM,CAAC;AAAA,EACZ;AAAA;AAAA;AAAA;AAAA,EAKQ,mBAAmB,SAAgD;AACzE,UAAM,UAAU,KAAK,aAAa,OAAO,EAAE,SAAS;AAEpD,WAAO;AAAA,MACL;AAAA,MACA,YAAY;AAAA,MACZ,OAAO,QAAQ;AAAA,MACf,OAAO;AAAA,QACL,aAAa,KAAK,KAAK,QAAQ,OAAO,SAAS,CAAC;AAAA,QAChD,cAAc,KAAK,KAAK,QAAQ,SAAS,CAAC;AAAA,MAC5C;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAc,iBAAgC;AAC5C,UAAM,MAAM,KAAK,IAAI;AACrB,UAAM,iBAAiB,MAAM,KAAK;AAElC,QAAI,kBAAkB,KAAO;AAC3B,WAAK,eAAe;AACpB,WAAK,gBAAgB;AAAA,IACvB;AAEA,QAAI,KAAK,gBAAgB,KAAK,oBAAoB;AAChD,YAAM,WAAW,MAAQ;AACzB,aAAO,KAAK,+BAA+B,QAAQ,IAAI;AACvD,YAAM,KAAK,MAAM,QAAQ;AACzB,WAAK,eAAe;AACpB,WAAK,gBAAgB,KAAK,IAAI;AAAA,IAChC;AAEA,SAAK;AAAA,EACP;AAAA;AAAA;AAAA;AAAA,EAKA,OAAO,eAAe,SAAoD;AAExE,UAAM,WAAW,MAAM,KAAK,SAAS,OAAO;AAC5C,UAAM,QAAQ,SAAS,MAAM,GAAG;AAEhC,eAAW,QAAQ,OAAO;AACxB,YAAM,OAAO;AACb,YAAM,KAAK,MAAM,EAAE;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKQ,MAAM,IAA2B;AACvC,WAAO,IAAI,QAAQ,aAAW,WAAW,SAAS,EAAE,CAAC;AAAA,EACvD;AAAA;AAAA;AAAA;AAAA,EAKA,gBAAgB;AACd,WAAO;AAAA,MACL,cAAc,KAAK;AAAA,MACnB,oBAAoB,KAAK,qBAAqB,KAAK;AAAA,MACnD,WAAW,IAAI,KAAK,KAAK,gBAAgB,GAAK,EAAE,YAAY;AAAA,IAC9D;AAAA,EACF;AACF;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|