@riotprompt/riotprompt 0.0.9 → 0.0.10
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/BUG-ANALYSIS.md +523 -0
- package/CODE-REVIEW-SUMMARY.md +330 -0
- package/FIXES-APPLIED.md +437 -0
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +2 -5
- package/dist/chat.js.map +1 -1
- package/dist/constants.js +1 -2
- package/dist/constants.js.map +1 -1
- package/dist/context-manager.d.ts +3 -2
- package/dist/context-manager.js +29 -6
- package/dist/context-manager.js.map +1 -1
- package/dist/conversation-logger.d.ts +3 -1
- package/dist/conversation-logger.js +41 -4
- package/dist/conversation-logger.js.map +1 -1
- package/dist/conversation.d.ts +8 -2
- package/dist/conversation.js +36 -9
- package/dist/conversation.js.map +1 -1
- package/dist/items/section.js +3 -3
- package/dist/items/section.js.map +1 -1
- package/dist/iteration-strategy.d.ts +2 -0
- package/dist/iteration-strategy.js +40 -6
- package/dist/iteration-strategy.js.map +1 -1
- package/dist/loader.js +18 -3
- package/dist/loader.js.map +1 -1
- package/dist/message-builder.js +4 -2
- package/dist/message-builder.js.map +1 -1
- package/dist/model-config.d.ts +115 -0
- package/dist/model-config.js +205 -0
- package/dist/model-config.js.map +1 -0
- package/dist/override.js +5 -1
- package/dist/override.js.map +1 -1
- package/dist/parser.js +3 -3
- package/dist/parser.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.js +4 -4
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.js +5 -2
- package/dist/reflection.js.map +1 -1
- package/dist/riotprompt.cjs +439 -94
- package/dist/riotprompt.cjs.map +1 -1
- package/dist/riotprompt.d.ts +2 -0
- package/dist/riotprompt.js +1 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/token-budget.d.ts +2 -2
- package/dist/token-budget.js +23 -26
- package/dist/token-budget.js.map +1 -1
- package/dist/util/general.js +1 -1
- package/dist/util/general.js.map +1 -1
- package/package.json +1 -1
package/dist/riotprompt.d.ts
CHANGED
|
@@ -22,6 +22,7 @@ export { ConversationLogger, ConversationReplayer } from './conversation-logger'
|
|
|
22
22
|
export { ToolRegistry } from './tools';
|
|
23
23
|
export { StrategyExecutor, IterationStrategyFactory } from './iteration-strategy';
|
|
24
24
|
export { MetricsCollector, ReflectionReportGenerator } from './reflection';
|
|
25
|
+
export { ModelRegistry, getModelRegistry, resetModelRegistry, getPersonaRole, getEncoding, supportsToolCalls, getModelFamily, configureModel } from './model-config';
|
|
25
26
|
export type { Content } from './items/content';
|
|
26
27
|
export type { Context } from './items/context';
|
|
27
28
|
export type { Instruction } from './items/instruction';
|
|
@@ -42,3 +43,4 @@ export type { IterationStrategy, StrategyPhase, StrategyState, StrategyResult, S
|
|
|
42
43
|
export type { ReflectionReport, ReflectionConfig, AgenticExecutionMetrics, ToolExecutionMetric, ToolStats, Recommendation, ToolEffectivenessAnalysis, PerformanceInsights, QualityAssessment } from './reflection';
|
|
43
44
|
export type { LogConfig, LogFormat, LoggedConversation, ConversationLogMetadata, LoggedMessage, ToolCallLog, ConversationSummary, ReplayOptions, ReplayResult } from './conversation-logger';
|
|
44
45
|
export type { Tool, ToolParameter, ToolContext, ToolExample, ToolCost, OpenAITool, AnthropicTool, ToolDefinition, ToolUsageStats } from './tools';
|
|
46
|
+
export type { ModelConfig, PersonaRole, TokenizerEncoding } from './model-config';
|
package/dist/riotprompt.js
CHANGED
|
@@ -29,4 +29,5 @@ export { ConversationLogger, ConversationReplayer } from './conversation-logger.
|
|
|
29
29
|
export { ToolRegistry } from './tools.js';
|
|
30
30
|
export { IterationStrategyFactory, StrategyExecutor } from './iteration-strategy.js';
|
|
31
31
|
export { MetricsCollector, ReflectionReportGenerator } from './reflection.js';
|
|
32
|
+
export { ModelRegistry, configureModel, getEncoding, getModelFamily, getModelRegistry, getPersonaRole, resetModelRegistry, supportsToolCalls } from './model-config.js';
|
|
32
33
|
//# sourceMappingURL=riotprompt.js.map
|
package/dist/riotprompt.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"riotprompt.js","sources":[],"sourcesContent":[],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"riotprompt.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;"}
|
package/dist/token-budget.d.ts
CHANGED
|
@@ -87,7 +87,7 @@ export declare class TokenCounter {
|
|
|
87
87
|
*/
|
|
88
88
|
estimateResponseTokens(messages: ConversationMessage[]): number;
|
|
89
89
|
/**
|
|
90
|
-
* Map RiotPrompt model to Tiktoken model
|
|
90
|
+
* Map RiotPrompt model to Tiktoken model using model registry
|
|
91
91
|
*/
|
|
92
92
|
private mapToTiktokenModel;
|
|
93
93
|
/**
|
|
@@ -154,7 +154,7 @@ export declare class TokenBudgetManager {
|
|
|
154
154
|
*/
|
|
155
155
|
private compressByPriority;
|
|
156
156
|
/**
|
|
157
|
-
* Compress using FIFO (remove oldest first)
|
|
157
|
+
* Compress using FIFO (remove oldest first) - optimized with Set
|
|
158
158
|
*/
|
|
159
159
|
private compressFIFO;
|
|
160
160
|
/**
|
package/dist/token-budget.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { encoding_for_model } from 'tiktoken';
|
|
2
2
|
import { wrapLogger, DEFAULT_LOGGER } from './logger.js';
|
|
3
|
+
import { getEncoding } from './model-config.js';
|
|
3
4
|
|
|
4
5
|
function _define_property(obj, key, value) {
|
|
5
6
|
if (key in obj) {
|
|
@@ -97,19 +98,16 @@ function _define_property(obj, key, value) {
|
|
|
97
98
|
return Math.max(500, Math.floor(inputTokens * 0.2));
|
|
98
99
|
}
|
|
99
100
|
/**
|
|
100
|
-
* Map RiotPrompt model to Tiktoken model
|
|
101
|
+
* Map RiotPrompt model to Tiktoken model using model registry
|
|
101
102
|
*/ mapToTiktokenModel(model) {
|
|
102
|
-
|
|
103
|
+
const encoding = getEncoding(model);
|
|
104
|
+
// Map our encoding types to tiktoken models
|
|
105
|
+
switch(encoding){
|
|
103
106
|
case 'gpt-4o':
|
|
104
|
-
case '
|
|
105
|
-
return 'gpt-4o';
|
|
106
|
-
case 'o1-preview':
|
|
107
|
-
case 'o1-mini':
|
|
108
|
-
case 'o1':
|
|
109
|
-
case 'o3-mini':
|
|
110
|
-
case 'o1-pro':
|
|
111
|
-
// O1 models use gpt-4o tokenization
|
|
107
|
+
case 'o200k_base':
|
|
112
108
|
return 'gpt-4o';
|
|
109
|
+
case 'cl100k_base':
|
|
110
|
+
return 'gpt-3.5-turbo';
|
|
113
111
|
default:
|
|
114
112
|
return 'gpt-4o';
|
|
115
113
|
}
|
|
@@ -276,16 +274,16 @@ function _define_property(obj, key, value) {
|
|
|
276
274
|
return kept.map((item)=>item.message);
|
|
277
275
|
}
|
|
278
276
|
/**
|
|
279
|
-
* Compress using FIFO (remove oldest first)
|
|
277
|
+
* Compress using FIFO (remove oldest first) - optimized with Set
|
|
280
278
|
*/ compressFIFO(messages, targetTokens) {
|
|
281
279
|
var _this_config_preserveRecent;
|
|
282
|
-
const
|
|
280
|
+
const preservedSet = new Set();
|
|
283
281
|
let totalTokens = 0;
|
|
284
282
|
// Always preserve system messages if configured
|
|
285
283
|
const systemMessages = messages.filter((m)=>m.role === 'system');
|
|
286
284
|
if (this.config.preserveSystem) {
|
|
287
285
|
for (const msg of systemMessages){
|
|
288
|
-
|
|
286
|
+
preservedSet.add(msg);
|
|
289
287
|
totalTokens += this.counter.countMessage(msg);
|
|
290
288
|
}
|
|
291
289
|
}
|
|
@@ -293,28 +291,28 @@ function _define_property(obj, key, value) {
|
|
|
293
291
|
const recentCount = (_this_config_preserveRecent = this.config.preserveRecent) !== null && _this_config_preserveRecent !== void 0 ? _this_config_preserveRecent : 3;
|
|
294
292
|
const recentMessages = messages.slice(-recentCount).filter((m)=>m.role !== 'system');
|
|
295
293
|
for (const msg of recentMessages){
|
|
296
|
-
if (!
|
|
294
|
+
if (!preservedSet.has(msg)) {
|
|
297
295
|
const tokens = this.counter.countMessage(msg);
|
|
298
296
|
if (totalTokens + tokens <= targetTokens) {
|
|
299
|
-
|
|
297
|
+
preservedSet.add(msg);
|
|
300
298
|
totalTokens += tokens;
|
|
301
299
|
}
|
|
302
300
|
}
|
|
303
301
|
}
|
|
304
302
|
// Add older messages if space available
|
|
305
|
-
const otherMessages = messages.filter((m)=>!
|
|
303
|
+
const otherMessages = messages.filter((m)=>!preservedSet.has(m) && m.role !== 'system');
|
|
306
304
|
for(let i = otherMessages.length - 1; i >= 0; i--){
|
|
307
305
|
const msg = otherMessages[i];
|
|
308
306
|
const tokens = this.counter.countMessage(msg);
|
|
309
307
|
if (totalTokens + tokens <= targetTokens) {
|
|
310
|
-
|
|
308
|
+
preservedSet.add(msg);
|
|
311
309
|
totalTokens += tokens;
|
|
312
310
|
} else {
|
|
313
311
|
break;
|
|
314
312
|
}
|
|
315
313
|
}
|
|
316
|
-
// Sort to maintain conversation order
|
|
317
|
-
return messages.filter((m)=>
|
|
314
|
+
// Sort to maintain conversation order - use Set for O(1) lookup
|
|
315
|
+
return messages.filter((m)=>preservedSet.has(m));
|
|
318
316
|
}
|
|
319
317
|
/**
|
|
320
318
|
* Adaptive compression based on conversation phase
|
|
@@ -326,13 +324,12 @@ function _define_property(obj, key, value) {
|
|
|
326
324
|
}
|
|
327
325
|
// Mid phase: moderate compression
|
|
328
326
|
if (messageCount <= 15) {
|
|
329
|
-
//
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
return tempManager.compressFIFO(messages, targetTokens);
|
|
327
|
+
// Temporarily modify preserveRecent, then restore
|
|
328
|
+
const originalPreserveRecent = this.config.preserveRecent;
|
|
329
|
+
this.config.preserveRecent = 5;
|
|
330
|
+
const result = this.compressFIFO(messages, targetTokens);
|
|
331
|
+
this.config.preserveRecent = originalPreserveRecent;
|
|
332
|
+
return result;
|
|
336
333
|
}
|
|
337
334
|
// Late phase: aggressive compression (priority-based)
|
|
338
335
|
return this.compressByPriority(messages, targetTokens);
|
package/dist/token-budget.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"token-budget.js","sources":["../src/token-budget.ts"],"sourcesContent":["import { encoding_for_model, Tiktoken, TiktokenModel } from 'tiktoken';\nimport type { ConversationMessage } from './conversation';\nimport { Model } from './chat';\nimport { DEFAULT_LOGGER, wrapLogger } from './logger';\n\n// ===== TYPE DEFINITIONS =====\n\n/**\n * Token usage information\n */\nexport interface TokenUsage {\n used: number;\n max: number;\n remaining: number;\n percentage: number;\n}\n\n/**\n * Compression statistics\n */\nexport interface CompressionStats {\n messagesBefore: number;\n messagesAfter: number;\n tokensBefore: number;\n tokensAfter: number;\n tokensSaved: number;\n strategy: CompressionStrategy;\n}\n\n/**\n * Compression strategy\n */\nexport type CompressionStrategy = 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n\n/**\n * Token budget configuration\n */\nexport interface TokenBudgetConfig {\n // Hard limits\n max: number;\n reserveForResponse: number;\n warningThreshold?: number; // Default: 0.8 (80%)\n\n // Compression strategy\n strategy: CompressionStrategy;\n\n // Behavior when budget exceeded\n onBudgetExceeded: 'compress' | 'error' | 'warn' | 'truncate';\n\n // What to preserve\n preserveRecent?: number;\n preserveSystem?: boolean; // Default: true\n preserveHighPriority?: boolean; // Default: true\n\n // Monitoring\n onWarning?: (usage: TokenUsage) => void;\n onCompression?: (stats: CompressionStats) => void;\n}\n\n// ===== TOKEN COUNTER =====\n\n/**\n * TokenCounter counts tokens using tiktoken for accurate model-specific counting.\n *\n * Features:\n * - Model-specific token counting\n * - Message overhead calculation\n * - Tool call token estimation\n * - Response token estimation\n *\n * @example\n * ```typescript\n * const counter = new TokenCounter('gpt-4o');\n *\n * const tokens = counter.count('Hello, world!');\n * console.log(`Text uses ${tokens} tokens`);\n *\n * const messageTokens = counter.countMessage({\n * role: 'user',\n * content: 'What is the weather?'\n * });\n * ```\n */\nexport class TokenCounter {\n private encoder: Tiktoken;\n private model: Model;\n private logger: any;\n\n constructor(model: Model, logger?: any) {\n this.model = model;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'TokenCounter');\n\n // Map RiotPrompt models to Tiktoken models\n const tiktokenModel = this.mapToTiktokenModel(model);\n this.encoder = encoding_for_model(tiktokenModel);\n\n this.logger.debug('Created TokenCounter', { model });\n }\n\n /**\n * Count tokens in text\n */\n count(text: string): number {\n if (!text) return 0;\n return this.encoder.encode(text).length;\n }\n\n /**\n * Count tokens in a single message\n */\n countMessage(message: ConversationMessage): number {\n let tokens = 4; // Base overhead per message\n\n // Content tokens\n if (message.content) {\n tokens += this.count(message.content);\n }\n\n // Role tokens\n tokens += 1;\n\n // Tool call tokens\n if (message.tool_calls) {\n for (const toolCall of message.tool_calls) {\n tokens += this.count(JSON.stringify(toolCall));\n tokens += 3; // Tool call overhead\n }\n }\n\n // Tool result tokens\n if (message.tool_call_id) {\n tokens += this.count(message.tool_call_id);\n tokens += 2; // Tool result overhead\n }\n\n return tokens;\n }\n\n /**\n * Count tokens in entire conversation\n */\n countConversation(messages: ConversationMessage[]): number {\n let total = 3; // Conversation start overhead\n\n for (const message of messages) {\n total += this.countMessage(message);\n }\n\n return total;\n }\n\n /**\n * Count with additional overhead estimation\n */\n countWithOverhead(\n messages: ConversationMessage[],\n includeToolOverhead: boolean = false\n ): number {\n let total = this.countConversation(messages);\n\n // Add tool definition overhead if tools are present\n if (includeToolOverhead) {\n const hasTools = messages.some(m => m.tool_calls && m.tool_calls.length > 0);\n if (hasTools) {\n total += 100; // Estimated tool definition overhead\n }\n }\n\n return total;\n }\n\n /**\n * Estimate tokens needed for response\n */\n estimateResponseTokens(messages: ConversationMessage[]): number {\n // Heuristic: average response is about 20% of input\n const inputTokens = this.countConversation(messages);\n return Math.max(500, Math.floor(inputTokens * 0.2));\n }\n\n /**\n * Map RiotPrompt model to Tiktoken model\n */\n private mapToTiktokenModel(model: Model): TiktokenModel {\n switch (model) {\n case 'gpt-4o':\n case 'gpt-4o-mini':\n return 'gpt-4o';\n case 'o1-preview':\n case 'o1-mini':\n case 'o1':\n case 'o3-mini':\n case 'o1-pro':\n // O1 models use gpt-4o tokenization\n return 'gpt-4o';\n default:\n return 'gpt-4o';\n }\n }\n\n /**\n * Free encoder resources\n */\n dispose(): void {\n this.encoder.free();\n }\n}\n\n// ===== TOKEN BUDGET MANAGER =====\n\n/**\n * TokenBudgetManager manages token budgets and compression strategies.\n *\n * Features:\n * - Monitor token usage\n * - Automatic compression when budget exceeded\n * - Multiple compression strategies\n * - Priority-based message retention\n * - Usage statistics and callbacks\n *\n * @example\n * ```typescript\n * const manager = new TokenBudgetManager({\n * max: 8000,\n * reserveForResponse: 1000,\n * strategy: 'priority-based',\n * onBudgetExceeded: 'compress'\n * }, 'gpt-4o');\n *\n * // Check if message can be added\n * if (manager.canAddMessage(message)) {\n * messages.push(message);\n * } else {\n * // Compress conversation\n * messages = manager.compress(messages);\n * messages.push(message);\n * }\n * ```\n */\nexport class TokenBudgetManager {\n private config: Required<TokenBudgetConfig>;\n private counter: TokenCounter;\n private logger: any;\n\n constructor(config: TokenBudgetConfig, model: Model, logger?: any) {\n this.config = {\n warningThreshold: 0.8,\n preserveRecent: 3,\n preserveSystem: true,\n preserveHighPriority: true,\n onWarning: () => {},\n onCompression: () => {},\n ...config,\n } as Required<TokenBudgetConfig>;\n\n this.counter = new TokenCounter(model, logger);\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'TokenBudgetManager');\n\n this.logger.debug('Created TokenBudgetManager', {\n max: this.config.max,\n strategy: this.config.strategy\n });\n }\n\n /**\n * Get current token usage\n */\n getCurrentUsage(messages: ConversationMessage[]): TokenUsage {\n const used = this.counter.countConversation(messages);\n const max = this.config.max;\n const remaining = Math.max(0, max - used - this.config.reserveForResponse);\n const percentage = (used / max) * 100;\n\n return { used, max, remaining, percentage };\n }\n\n /**\n * Get remaining tokens available\n */\n getRemainingTokens(messages: ConversationMessage[]): number {\n return this.getCurrentUsage(messages).remaining;\n }\n\n /**\n * Check if near token limit\n */\n isNearLimit(messages: ConversationMessage[], threshold?: number): boolean {\n const usage = this.getCurrentUsage(messages);\n const checkThreshold = threshold ?? this.config.warningThreshold;\n\n const isNear = usage.percentage >= (checkThreshold * 100);\n\n if (isNear) {\n this.config.onWarning?.(usage);\n }\n\n return isNear;\n }\n\n /**\n * Check if a message can be added without exceeding budget\n */\n canAddMessage(message: ConversationMessage, currentMessages: ConversationMessage[]): boolean {\n const currentTokens = this.counter.countConversation(currentMessages);\n const messageTokens = this.counter.countMessage(message);\n const total = currentTokens + messageTokens + this.config.reserveForResponse;\n\n return total <= this.config.max;\n }\n\n /**\n * Compress messages according to strategy\n */\n compress(messages: ConversationMessage[]): ConversationMessage[] {\n const before = messages.length;\n const tokensBefore = this.counter.countConversation(messages);\n const targetTokens = this.config.max - this.config.reserveForResponse;\n\n this.logger.debug('Compressing messages', {\n before,\n tokensBefore,\n targetTokens,\n strategy: this.config.strategy\n });\n\n // No compression needed\n if (tokensBefore <= targetTokens) {\n return messages;\n }\n\n let compressed: ConversationMessage[];\n\n switch (this.config.strategy) {\n case 'priority-based':\n compressed = this.compressByPriority(messages, targetTokens);\n break;\n case 'fifo':\n compressed = this.compressFIFO(messages, targetTokens);\n break;\n case 'adaptive':\n compressed = this.compressAdaptive(messages, targetTokens);\n break;\n case 'summarize':\n // For now, fall back to FIFO (summarization would require LLM call)\n compressed = this.compressFIFO(messages, targetTokens);\n break;\n default:\n compressed = this.compressFIFO(messages, targetTokens);\n }\n\n const tokensAfter = this.counter.countConversation(compressed);\n\n const stats: CompressionStats = {\n messagesBefore: before,\n messagesAfter: compressed.length,\n tokensBefore,\n tokensAfter,\n tokensSaved: tokensBefore - tokensAfter,\n strategy: this.config.strategy,\n };\n\n this.config.onCompression?.(stats);\n\n this.logger.info('Compressed conversation', stats);\n\n return compressed;\n }\n\n /**\n * Compress by priority (keep high-priority messages)\n */\n private compressByPriority(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n // Calculate priority for each message\n const withPriority = messages.map((msg, idx) => ({\n message: msg,\n priority: this.calculatePriority(msg, idx, messages.length),\n tokens: this.counter.countMessage(msg),\n index: idx,\n }));\n\n // Sort by priority (descending)\n withPriority.sort((a, b) => b.priority - a.priority);\n\n // Keep highest priority messages that fit in budget\n const kept: typeof withPriority = [];\n let totalTokens = 0;\n\n for (const item of withPriority) {\n if (totalTokens + item.tokens <= targetTokens) {\n kept.push(item);\n totalTokens += item.tokens;\n }\n }\n\n // Sort back to original order\n kept.sort((a, b) => a.index - b.index);\n\n return kept.map(item => item.message);\n }\n\n /**\n * Compress using FIFO (remove oldest first)\n */\n private compressFIFO(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n const preserved: ConversationMessage[] = [];\n let totalTokens = 0;\n\n // Always preserve system messages if configured\n const systemMessages = messages.filter(m => m.role === 'system');\n if (this.config.preserveSystem) {\n for (const msg of systemMessages) {\n preserved.push(msg);\n totalTokens += this.counter.countMessage(msg);\n }\n }\n\n // Preserve recent messages\n const recentCount = this.config.preserveRecent ?? 3;\n const recentMessages = messages.slice(-recentCount).filter(m => m.role !== 'system');\n for (const msg of recentMessages) {\n if (!preserved.includes(msg)) {\n const tokens = this.counter.countMessage(msg);\n if (totalTokens + tokens <= targetTokens) {\n preserved.push(msg);\n totalTokens += tokens;\n }\n }\n }\n\n // Add older messages if space available\n const otherMessages = messages.filter(\n m => !preserved.includes(m) && m.role !== 'system'\n );\n\n for (let i = otherMessages.length - 1; i >= 0; i--) {\n const msg = otherMessages[i];\n const tokens = this.counter.countMessage(msg);\n\n if (totalTokens + tokens <= targetTokens) {\n preserved.unshift(msg);\n totalTokens += tokens;\n } else {\n break;\n }\n }\n\n // Sort to maintain conversation order\n return messages.filter(m => preserved.includes(m));\n }\n\n /**\n * Adaptive compression based on conversation phase\n */\n private compressAdaptive(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n const messageCount = messages.length;\n\n // Early phase: minimal compression (keep most messages)\n if (messageCount <= 5) {\n return this.compressFIFO(messages, targetTokens);\n }\n\n // Mid phase: moderate compression\n if (messageCount <= 15) {\n // Use FIFO but preserve more recent messages\n const modifiedConfig = { ...this.config, preserveRecent: 5 };\n const tempManager = new TokenBudgetManager(\n modifiedConfig,\n 'gpt-4o', // Model doesn't matter here\n this.logger\n );\n return tempManager.compressFIFO(messages, targetTokens);\n }\n\n // Late phase: aggressive compression (priority-based)\n return this.compressByPriority(messages, targetTokens);\n }\n\n /**\n * Calculate message priority for compression\n */\n private calculatePriority(\n message: ConversationMessage,\n index: number,\n total: number\n ): number {\n let priority = 1.0;\n\n // System messages: highest priority\n if (message.role === 'system') {\n priority = 10.0;\n }\n\n // Recent messages: higher priority\n const recencyBonus = index / total;\n priority += recencyBonus * 2;\n\n // Tool results: moderate priority\n if (message.role === 'tool') {\n priority += 0.5;\n }\n\n // Messages with tool calls: keep for context\n if (message.tool_calls && message.tool_calls.length > 0) {\n priority += 0.8;\n }\n\n return priority;\n }\n\n /**\n * Truncate to exact number of messages\n */\n truncate(messages: ConversationMessage[], maxMessages: number): ConversationMessage[] {\n if (messages.length <= maxMessages) {\n return messages;\n }\n\n // Keep system messages + recent messages\n const systemMessages = messages.filter(m => m.role === 'system');\n const otherMessages = messages.filter(m => m.role !== 'system');\n\n const recentOther = otherMessages.slice(-(maxMessages - systemMessages.length));\n\n return [...systemMessages, ...recentOther];\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.counter.dispose();\n }\n}\n\nexport default TokenBudgetManager;\n\n"],"names":["TokenCounter","count","text","encoder","encode","length","countMessage","message","tokens","content","tool_calls","toolCall","JSON","stringify","tool_call_id","countConversation","messages","total","countWithOverhead","includeToolOverhead","hasTools","some","m","estimateResponseTokens","inputTokens","Math","max","floor","mapToTiktokenModel","model","dispose","free","logger","wrapLogger","DEFAULT_LOGGER","tiktokenModel","encoding_for_model","debug","TokenBudgetManager","getCurrentUsage","used","counter","config","remaining","reserveForResponse","percentage","getRemainingTokens","isNearLimit","threshold","usage","checkThreshold","warningThreshold","isNear","onWarning","canAddMessage","currentMessages","currentTokens","messageTokens","compress","before","tokensBefore","targetTokens","strategy","compressed","compressByPriority","compressFIFO","compressAdaptive","tokensAfter","stats","messagesBefore","messagesAfter","tokensSaved","onCompression","info","withPriority","map","msg","idx","priority","calculatePriority","index","sort","a","b","kept","totalTokens","item","push","preserved","systemMessages","filter","role","preserveSystem","recentCount","preserveRecent","recentMessages","slice","includes","otherMessages","i","unshift","messageCount","modifiedConfig","tempManager","recencyBonus","truncate","maxMessages","recentOther","preserveHighPriority"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"token-budget.js","sources":["../src/token-budget.ts"],"sourcesContent":["import { encoding_for_model, Tiktoken, TiktokenModel } from 'tiktoken';\nimport type { ConversationMessage } from './conversation';\nimport { Model } from './chat';\nimport { DEFAULT_LOGGER, wrapLogger } from './logger';\nimport { getEncoding } from './model-config';\n\n// ===== TYPE DEFINITIONS =====\n\n/**\n * Token usage information\n */\nexport interface TokenUsage {\n used: number;\n max: number;\n remaining: number;\n percentage: number;\n}\n\n/**\n * Compression statistics\n */\nexport interface CompressionStats {\n messagesBefore: number;\n messagesAfter: number;\n tokensBefore: number;\n tokensAfter: number;\n tokensSaved: number;\n strategy: CompressionStrategy;\n}\n\n/**\n * Compression strategy\n */\nexport type CompressionStrategy = 'priority-based' | 'fifo' | 'summarize' | 'adaptive';\n\n/**\n * Token budget configuration\n */\nexport interface TokenBudgetConfig {\n // Hard limits\n max: number;\n reserveForResponse: number;\n warningThreshold?: number; // Default: 0.8 (80%)\n\n // Compression strategy\n strategy: CompressionStrategy;\n\n // Behavior when budget exceeded\n onBudgetExceeded: 'compress' | 'error' | 'warn' | 'truncate';\n\n // What to preserve\n preserveRecent?: number;\n preserveSystem?: boolean; // Default: true\n preserveHighPriority?: boolean; // Default: true\n\n // Monitoring\n onWarning?: (usage: TokenUsage) => void;\n onCompression?: (stats: CompressionStats) => void;\n}\n\n// ===== TOKEN COUNTER =====\n\n/**\n * TokenCounter counts tokens using tiktoken for accurate model-specific counting.\n *\n * Features:\n * - Model-specific token counting\n * - Message overhead calculation\n * - Tool call token estimation\n * - Response token estimation\n *\n * @example\n * ```typescript\n * const counter = new TokenCounter('gpt-4o');\n *\n * const tokens = counter.count('Hello, world!');\n * console.log(`Text uses ${tokens} tokens`);\n *\n * const messageTokens = counter.countMessage({\n * role: 'user',\n * content: 'What is the weather?'\n * });\n * ```\n */\nexport class TokenCounter {\n private encoder: Tiktoken;\n private model: Model;\n private logger: any;\n\n constructor(model: Model, logger?: any) {\n this.model = model;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'TokenCounter');\n\n // Map RiotPrompt models to Tiktoken models\n const tiktokenModel = this.mapToTiktokenModel(model);\n this.encoder = encoding_for_model(tiktokenModel);\n\n this.logger.debug('Created TokenCounter', { model });\n }\n\n /**\n * Count tokens in text\n */\n count(text: string): number {\n if (!text) return 0;\n return this.encoder.encode(text).length;\n }\n\n /**\n * Count tokens in a single message\n */\n countMessage(message: ConversationMessage): number {\n let tokens = 4; // Base overhead per message\n\n // Content tokens\n if (message.content) {\n tokens += this.count(message.content);\n }\n\n // Role tokens\n tokens += 1;\n\n // Tool call tokens\n if (message.tool_calls) {\n for (const toolCall of message.tool_calls) {\n tokens += this.count(JSON.stringify(toolCall));\n tokens += 3; // Tool call overhead\n }\n }\n\n // Tool result tokens\n if (message.tool_call_id) {\n tokens += this.count(message.tool_call_id);\n tokens += 2; // Tool result overhead\n }\n\n return tokens;\n }\n\n /**\n * Count tokens in entire conversation\n */\n countConversation(messages: ConversationMessage[]): number {\n let total = 3; // Conversation start overhead\n\n for (const message of messages) {\n total += this.countMessage(message);\n }\n\n return total;\n }\n\n /**\n * Count with additional overhead estimation\n */\n countWithOverhead(\n messages: ConversationMessage[],\n includeToolOverhead: boolean = false\n ): number {\n let total = this.countConversation(messages);\n\n // Add tool definition overhead if tools are present\n if (includeToolOverhead) {\n const hasTools = messages.some(m => m.tool_calls && m.tool_calls.length > 0);\n if (hasTools) {\n total += 100; // Estimated tool definition overhead\n }\n }\n\n return total;\n }\n\n /**\n * Estimate tokens needed for response\n */\n estimateResponseTokens(messages: ConversationMessage[]): number {\n // Heuristic: average response is about 20% of input\n const inputTokens = this.countConversation(messages);\n return Math.max(500, Math.floor(inputTokens * 0.2));\n }\n\n /**\n * Map RiotPrompt model to Tiktoken model using model registry\n */\n private mapToTiktokenModel(model: Model): TiktokenModel {\n const encoding = getEncoding(model);\n\n // Map our encoding types to tiktoken models\n switch (encoding) {\n case 'gpt-4o':\n case 'o200k_base':\n return 'gpt-4o';\n case 'cl100k_base':\n return 'gpt-3.5-turbo';\n default:\n return 'gpt-4o';\n }\n }\n\n /**\n * Free encoder resources\n */\n dispose(): void {\n this.encoder.free();\n }\n}\n\n// ===== TOKEN BUDGET MANAGER =====\n\n/**\n * TokenBudgetManager manages token budgets and compression strategies.\n *\n * Features:\n * - Monitor token usage\n * - Automatic compression when budget exceeded\n * - Multiple compression strategies\n * - Priority-based message retention\n * - Usage statistics and callbacks\n *\n * @example\n * ```typescript\n * const manager = new TokenBudgetManager({\n * max: 8000,\n * reserveForResponse: 1000,\n * strategy: 'priority-based',\n * onBudgetExceeded: 'compress'\n * }, 'gpt-4o');\n *\n * // Check if message can be added\n * if (manager.canAddMessage(message)) {\n * messages.push(message);\n * } else {\n * // Compress conversation\n * messages = manager.compress(messages);\n * messages.push(message);\n * }\n * ```\n */\nexport class TokenBudgetManager {\n private config: Required<TokenBudgetConfig>;\n private counter: TokenCounter;\n private logger: any;\n\n constructor(config: TokenBudgetConfig, model: Model, logger?: any) {\n this.config = {\n warningThreshold: 0.8,\n preserveRecent: 3,\n preserveSystem: true,\n preserveHighPriority: true,\n onWarning: () => {},\n onCompression: () => {},\n ...config,\n } as Required<TokenBudgetConfig>;\n\n this.counter = new TokenCounter(model, logger);\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'TokenBudgetManager');\n\n this.logger.debug('Created TokenBudgetManager', {\n max: this.config.max,\n strategy: this.config.strategy\n });\n }\n\n /**\n * Get current token usage\n */\n getCurrentUsage(messages: ConversationMessage[]): TokenUsage {\n const used = this.counter.countConversation(messages);\n const max = this.config.max;\n const remaining = Math.max(0, max - used - this.config.reserveForResponse);\n const percentage = (used / max) * 100;\n\n return { used, max, remaining, percentage };\n }\n\n /**\n * Get remaining tokens available\n */\n getRemainingTokens(messages: ConversationMessage[]): number {\n return this.getCurrentUsage(messages).remaining;\n }\n\n /**\n * Check if near token limit\n */\n isNearLimit(messages: ConversationMessage[], threshold?: number): boolean {\n const usage = this.getCurrentUsage(messages);\n const checkThreshold = threshold ?? this.config.warningThreshold;\n\n const isNear = usage.percentage >= (checkThreshold * 100);\n\n if (isNear) {\n this.config.onWarning?.(usage);\n }\n\n return isNear;\n }\n\n /**\n * Check if a message can be added without exceeding budget\n */\n canAddMessage(message: ConversationMessage, currentMessages: ConversationMessage[]): boolean {\n const currentTokens = this.counter.countConversation(currentMessages);\n const messageTokens = this.counter.countMessage(message);\n const total = currentTokens + messageTokens + this.config.reserveForResponse;\n\n return total <= this.config.max;\n }\n\n /**\n * Compress messages according to strategy\n */\n compress(messages: ConversationMessage[]): ConversationMessage[] {\n const before = messages.length;\n const tokensBefore = this.counter.countConversation(messages);\n const targetTokens = this.config.max - this.config.reserveForResponse;\n\n this.logger.debug('Compressing messages', {\n before,\n tokensBefore,\n targetTokens,\n strategy: this.config.strategy\n });\n\n // No compression needed\n if (tokensBefore <= targetTokens) {\n return messages;\n }\n\n let compressed: ConversationMessage[];\n\n switch (this.config.strategy) {\n case 'priority-based':\n compressed = this.compressByPriority(messages, targetTokens);\n break;\n case 'fifo':\n compressed = this.compressFIFO(messages, targetTokens);\n break;\n case 'adaptive':\n compressed = this.compressAdaptive(messages, targetTokens);\n break;\n case 'summarize':\n // For now, fall back to FIFO (summarization would require LLM call)\n compressed = this.compressFIFO(messages, targetTokens);\n break;\n default:\n compressed = this.compressFIFO(messages, targetTokens);\n }\n\n const tokensAfter = this.counter.countConversation(compressed);\n\n const stats: CompressionStats = {\n messagesBefore: before,\n messagesAfter: compressed.length,\n tokensBefore,\n tokensAfter,\n tokensSaved: tokensBefore - tokensAfter,\n strategy: this.config.strategy,\n };\n\n this.config.onCompression?.(stats);\n\n this.logger.info('Compressed conversation', stats);\n\n return compressed;\n }\n\n /**\n * Compress by priority (keep high-priority messages)\n */\n private compressByPriority(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n // Calculate priority for each message\n const withPriority = messages.map((msg, idx) => ({\n message: msg,\n priority: this.calculatePriority(msg, idx, messages.length),\n tokens: this.counter.countMessage(msg),\n index: idx,\n }));\n\n // Sort by priority (descending)\n withPriority.sort((a, b) => b.priority - a.priority);\n\n // Keep highest priority messages that fit in budget\n const kept: typeof withPriority = [];\n let totalTokens = 0;\n\n for (const item of withPriority) {\n if (totalTokens + item.tokens <= targetTokens) {\n kept.push(item);\n totalTokens += item.tokens;\n }\n }\n\n // Sort back to original order\n kept.sort((a, b) => a.index - b.index);\n\n return kept.map(item => item.message);\n }\n\n /**\n * Compress using FIFO (remove oldest first) - optimized with Set\n */\n private compressFIFO(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n const preserved: ConversationMessage[] = [];\n const preservedSet = new Set<ConversationMessage>();\n let totalTokens = 0;\n\n // Always preserve system messages if configured\n const systemMessages = messages.filter(m => m.role === 'system');\n if (this.config.preserveSystem) {\n for (const msg of systemMessages) {\n preserved.push(msg);\n preservedSet.add(msg);\n totalTokens += this.counter.countMessage(msg);\n }\n }\n\n // Preserve recent messages\n const recentCount = this.config.preserveRecent ?? 3;\n const recentMessages = messages.slice(-recentCount).filter(m => m.role !== 'system');\n for (const msg of recentMessages) {\n if (!preservedSet.has(msg)) {\n const tokens = this.counter.countMessage(msg);\n if (totalTokens + tokens <= targetTokens) {\n preserved.push(msg);\n preservedSet.add(msg);\n totalTokens += tokens;\n }\n }\n }\n\n // Add older messages if space available\n const otherMessages = messages.filter(\n m => !preservedSet.has(m) && m.role !== 'system'\n );\n\n for (let i = otherMessages.length - 1; i >= 0; i--) {\n const msg = otherMessages[i];\n const tokens = this.counter.countMessage(msg);\n\n if (totalTokens + tokens <= targetTokens) {\n preserved.unshift(msg);\n preservedSet.add(msg);\n totalTokens += tokens;\n } else {\n break;\n }\n }\n\n // Sort to maintain conversation order - use Set for O(1) lookup\n return messages.filter(m => preservedSet.has(m));\n }\n\n /**\n * Adaptive compression based on conversation phase\n */\n private compressAdaptive(\n messages: ConversationMessage[],\n targetTokens: number\n ): ConversationMessage[] {\n const messageCount = messages.length;\n\n // Early phase: minimal compression (keep most messages)\n if (messageCount <= 5) {\n return this.compressFIFO(messages, targetTokens);\n }\n\n // Mid phase: moderate compression\n if (messageCount <= 15) {\n // Temporarily modify preserveRecent, then restore\n const originalPreserveRecent = this.config.preserveRecent;\n this.config.preserveRecent = 5;\n const result = this.compressFIFO(messages, targetTokens);\n this.config.preserveRecent = originalPreserveRecent;\n return result;\n }\n\n // Late phase: aggressive compression (priority-based)\n return this.compressByPriority(messages, targetTokens);\n }\n\n /**\n * Calculate message priority for compression\n */\n private calculatePriority(\n message: ConversationMessage,\n index: number,\n total: number\n ): number {\n let priority = 1.0;\n\n // System messages: highest priority\n if (message.role === 'system') {\n priority = 10.0;\n }\n\n // Recent messages: higher priority\n const recencyBonus = index / total;\n priority += recencyBonus * 2;\n\n // Tool results: moderate priority\n if (message.role === 'tool') {\n priority += 0.5;\n }\n\n // Messages with tool calls: keep for context\n if (message.tool_calls && message.tool_calls.length > 0) {\n priority += 0.8;\n }\n\n return priority;\n }\n\n /**\n * Truncate to exact number of messages\n */\n truncate(messages: ConversationMessage[], maxMessages: number): ConversationMessage[] {\n if (messages.length <= maxMessages) {\n return messages;\n }\n\n // Keep system messages + recent messages\n const systemMessages = messages.filter(m => m.role === 'system');\n const otherMessages = messages.filter(m => m.role !== 'system');\n\n const recentOther = otherMessages.slice(-(maxMessages - systemMessages.length));\n\n return [...systemMessages, ...recentOther];\n }\n\n /**\n * Dispose resources\n */\n dispose(): void {\n this.counter.dispose();\n }\n}\n\nexport default TokenBudgetManager;\n\n"],"names":["TokenCounter","count","text","encoder","encode","length","countMessage","message","tokens","content","tool_calls","toolCall","JSON","stringify","tool_call_id","countConversation","messages","total","countWithOverhead","includeToolOverhead","hasTools","some","m","estimateResponseTokens","inputTokens","Math","max","floor","mapToTiktokenModel","model","encoding","getEncoding","dispose","free","logger","wrapLogger","DEFAULT_LOGGER","tiktokenModel","encoding_for_model","debug","TokenBudgetManager","getCurrentUsage","used","counter","config","remaining","reserveForResponse","percentage","getRemainingTokens","isNearLimit","threshold","usage","checkThreshold","warningThreshold","isNear","onWarning","canAddMessage","currentMessages","currentTokens","messageTokens","compress","before","tokensBefore","targetTokens","strategy","compressed","compressByPriority","compressFIFO","compressAdaptive","tokensAfter","stats","messagesBefore","messagesAfter","tokensSaved","onCompression","info","withPriority","map","msg","idx","priority","calculatePriority","index","sort","a","b","kept","totalTokens","item","push","preservedSet","Set","systemMessages","filter","role","preserveSystem","add","recentCount","preserveRecent","recentMessages","slice","has","otherMessages","i","messageCount","originalPreserveRecent","result","recencyBonus","truncate","maxMessages","recentOther","preserveHighPriority"],"mappings":";;;;;;;;;;;;;;;;;AA4DA;AAEA;;;;;;;;;;;;;;;;;;;;;AAqBC,IACM,MAAMA,YAAAA,CAAAA;AAgBT;;QAGAC,KAAAA,CAAMC,IAAY,EAAU;QACxB,IAAI,CAACA,MAAM,OAAO,CAAA;AAClB,QAAA,OAAO,IAAI,CAACC,OAAO,CAACC,MAAM,CAACF,MAAMG,MAAM;AAC3C,IAAA;AAEA;;QAGAC,YAAAA,CAAaC,OAA4B,EAAU;QAC/C,IAAIC,MAAAA,GAAS;;QAGb,IAAID,OAAAA,CAAQE,OAAO,EAAE;AACjBD,YAAAA,MAAAA,IAAU,IAAI,CAACP,KAAK,CAACM,QAAQE,OAAO,CAAA;AACxC,QAAA;;QAGAD,MAAAA,IAAU,CAAA;;QAGV,IAAID,OAAAA,CAAQG,UAAU,EAAE;AACpB,YAAA,KAAK,MAAMC,QAAAA,IAAYJ,OAAAA,CAAQG,UAAU,CAAE;AACvCF,gBAAAA,MAAAA,IAAU,IAAI,CAACP,KAAK,CAACW,IAAAA,CAAKC,SAAS,CAACF,QAAAA,CAAAA,CAAAA;AACpCH,gBAAAA,MAAAA,IAAU;AACd,YAAA;AACJ,QAAA;;QAGA,IAAID,OAAAA,CAAQO,YAAY,EAAE;AACtBN,YAAAA,MAAAA,IAAU,IAAI,CAACP,KAAK,CAACM,QAAQO,YAAY,CAAA;AACzCN,YAAAA,MAAAA,IAAU;AACd,QAAA;QAEA,OAAOA,MAAAA;AACX,IAAA;AAEA;;QAGAO,iBAAAA,CAAkBC,QAA+B,EAAU;QACvD,IAAIC,KAAAA,GAAQ;QAEZ,KAAK,MAAMV,WAAWS,QAAAA,CAAU;YAC5BC,KAAAA,IAAS,IAAI,CAACX,YAAY,CAACC,OAAAA,CAAAA;AAC/B,QAAA;QAEA,OAAOU,KAAAA;AACX,IAAA;AAEA;;AAEC,QACDC,iBAAAA,CACIF,QAA+B,EAC/BG,mBAAAA,GAA+B,KAAK,EAC9B;AACN,QAAA,IAAIF,KAAAA,GAAQ,IAAI,CAACF,iBAAiB,CAACC,QAAAA,CAAAA;;AAGnC,QAAA,IAAIG,mBAAAA,EAAqB;AACrB,YAAA,MAAMC,QAAAA,GAAWJ,QAAAA,CAASK,IAAI,CAACC,CAAAA,CAAAA,GAAKA,CAAAA,CAAEZ,UAAU,IAAIY,CAAAA,CAAEZ,UAAU,CAACL,MAAM,GAAG,CAAA,CAAA;AAC1E,YAAA,IAAIe,QAAAA,EAAU;AACVH,gBAAAA,KAAAA,IAAS;AACb,YAAA;AACJ,QAAA;QAEA,OAAOA,KAAAA;AACX,IAAA;AAEA;;QAGAM,sBAAAA,CAAuBP,QAA+B,EAAU;;AAE5D,QAAA,MAAMQ,WAAAA,GAAc,IAAI,CAACT,iBAAiB,CAACC,QAAAA,CAAAA;AAC3C,QAAA,OAAOS,KAAKC,GAAG,CAAC,KAAKD,IAAAA,CAAKE,KAAK,CAACH,WAAAA,GAAc,GAAA,CAAA,CAAA;AAClD,IAAA;AAEA;;QAGQI,kBAAAA,CAAmBC,KAAY,EAAiB;AACpD,QAAA,MAAMC,WAAWC,WAAAA,CAAYF,KAAAA,CAAAA;;QAG7B,OAAQC,QAAAA;YACJ,KAAK,QAAA;YACL,KAAK,YAAA;gBACD,OAAO,QAAA;YACX,KAAK,aAAA;gBACD,OAAO,eAAA;AACX,YAAA;gBACI,OAAO,QAAA;AACf;AACJ,IAAA;AAEA;;AAEC,QACDE,OAAAA,GAAgB;QACZ,IAAI,CAAC7B,OAAO,CAAC8B,IAAI,EAAA;AACrB,IAAA;IAnHA,WAAA,CAAYJ,KAAY,EAAEK,MAAY,CAAE;AAJxC,QAAA,gBAAA,CAAA,IAAA,EAAQ/B,WAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQ0B,SAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQK,UAAR,MAAA,CAAA;QAGI,IAAI,CAACL,KAAK,GAAGA,KAAAA;AACb,QAAA,IAAI,CAACK,MAAM,GAAGC,UAAAA,CAAWD,UAAUE,cAAAA,EAAgB,cAAA,CAAA;;AAGnD,QAAA,MAAMC,aAAAA,GAAgB,IAAI,CAACT,kBAAkB,CAACC,KAAAA,CAAAA;QAC9C,IAAI,CAAC1B,OAAO,GAAGmC,kBAAAA,CAAmBD,aAAAA,CAAAA;AAElC,QAAA,IAAI,CAACH,MAAM,CAACK,KAAK,CAAC,sBAAA,EAAwB;AAAEV,YAAAA;AAAM,SAAA,CAAA;AACtD,IAAA;AA2GJ;AAEA;AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BC,IACM,MAAMW,kBAAAA,CAAAA;AAyBT;;QAGAC,eAAAA,CAAgBzB,QAA+B,EAAc;AACzD,QAAA,MAAM0B,OAAO,IAAI,CAACC,OAAO,CAAC5B,iBAAiB,CAACC,QAAAA,CAAAA;AAC5C,QAAA,MAAMU,GAAAA,GAAM,IAAI,CAACkB,MAAM,CAAClB,GAAG;QAC3B,MAAMmB,SAAAA,GAAYpB,IAAAA,CAAKC,GAAG,CAAC,CAAA,EAAGA,GAAAA,GAAMgB,IAAAA,GAAO,IAAI,CAACE,MAAM,CAACE,kBAAkB,CAAA;QACzE,MAAMC,UAAAA,GAAa,IAACL,GAAOhB,GAAAA,GAAO,GAAA;QAElC,OAAO;AAAEgB,YAAAA,IAAAA;AAAMhB,YAAAA,GAAAA;AAAKmB,YAAAA,SAAAA;AAAWE,YAAAA;AAAW,SAAA;AAC9C,IAAA;AAEA;;QAGAC,kBAAAA,CAAmBhC,QAA+B,EAAU;AACxD,QAAA,OAAO,IAAI,CAACyB,eAAe,CAACzB,UAAU6B,SAAS;AACnD,IAAA;AAEA;;AAEC,QACDI,WAAAA,CAAYjC,QAA+B,EAAEkC,SAAkB,EAAW;AACtE,QAAA,MAAMC,KAAAA,GAAQ,IAAI,CAACV,eAAe,CAACzB,QAAAA,CAAAA;QACnC,MAAMoC,cAAAA,GAAiBF,sBAAAA,SAAAA,KAAAA,MAAAA,GAAAA,SAAAA,GAAa,IAAI,CAACN,MAAM,CAACS,gBAAgB;AAEhE,QAAA,MAAMC,MAAAA,GAASH,KAAAA,CAAMJ,UAAU,IAAKK,cAAAA,GAAiB,GAAA;AAErD,QAAA,IAAIE,MAAAA,EAAQ;gBACR,sBAAA,EAAA,YAAA;aAAA,sBAAA,GAAA,CAAA,YAAA,GAAA,IAAI,CAACV,MAAM,EAACW,SAAS,MAAA,IAAA,IAArB,sBAAA,KAAA,MAAA,GAAA,MAAA,GAAA,sBAAA,CAAA,IAAA,CAAA,YAAA,EAAwBJ,KAAAA,CAAAA;AAC5B,QAAA;QAEA,OAAOG,MAAAA;AACX,IAAA;AAEA;;AAEC,QACDE,aAAAA,CAAcjD,OAA4B,EAAEkD,eAAsC,EAAW;AACzF,QAAA,MAAMC,gBAAgB,IAAI,CAACf,OAAO,CAAC5B,iBAAiB,CAAC0C,eAAAA,CAAAA;AACrD,QAAA,MAAME,gBAAgB,IAAI,CAAChB,OAAO,CAACrC,YAAY,CAACC,OAAAA,CAAAA;AAChD,QAAA,MAAMU,QAAQyC,aAAAA,GAAgBC,aAAAA,GAAgB,IAAI,CAACf,MAAM,CAACE,kBAAkB;AAE5E,QAAA,OAAO7B,KAAAA,IAAS,IAAI,CAAC2B,MAAM,CAAClB,GAAG;AACnC,IAAA;AAEA;;QAGAkC,QAAAA,CAAS5C,QAA+B,EAAyB;YAgD7D,0BAAA,EAAA,YAAA;QA/CA,MAAM6C,MAAAA,GAAS7C,SAASX,MAAM;AAC9B,QAAA,MAAMyD,eAAe,IAAI,CAACnB,OAAO,CAAC5B,iBAAiB,CAACC,QAAAA,CAAAA;QACpD,MAAM+C,YAAAA,GAAe,IAAI,CAACnB,MAAM,CAAClB,GAAG,GAAG,IAAI,CAACkB,MAAM,CAACE,kBAAkB;AAErE,QAAA,IAAI,CAACZ,MAAM,CAACK,KAAK,CAAC,sBAAA,EAAwB;AACtCsB,YAAAA,MAAAA;AACAC,YAAAA,YAAAA;AACAC,YAAAA,YAAAA;AACAC,YAAAA,QAAAA,EAAU,IAAI,CAACpB,MAAM,CAACoB;AAC1B,SAAA,CAAA;;AAGA,QAAA,IAAIF,gBAAgBC,YAAAA,EAAc;YAC9B,OAAO/C,QAAAA;AACX,QAAA;QAEA,IAAIiD,UAAAA;AAEJ,QAAA,OAAQ,IAAI,CAACrB,MAAM,CAACoB,QAAQ;YACxB,KAAK,gBAAA;AACDC,gBAAAA,UAAAA,GAAa,IAAI,CAACC,kBAAkB,CAAClD,QAAAA,EAAU+C,YAAAA,CAAAA;AAC/C,gBAAA;YACJ,KAAK,MAAA;AACDE,gBAAAA,UAAAA,GAAa,IAAI,CAACE,YAAY,CAACnD,QAAAA,EAAU+C,YAAAA,CAAAA;AACzC,gBAAA;YACJ,KAAK,UAAA;AACDE,gBAAAA,UAAAA,GAAa,IAAI,CAACG,gBAAgB,CAACpD,QAAAA,EAAU+C,YAAAA,CAAAA;AAC7C,gBAAA;YACJ,KAAK,WAAA;;AAEDE,gBAAAA,UAAAA,GAAa,IAAI,CAACE,YAAY,CAACnD,QAAAA,EAAU+C,YAAAA,CAAAA;AACzC,gBAAA;AACJ,YAAA;AACIE,gBAAAA,UAAAA,GAAa,IAAI,CAACE,YAAY,CAACnD,QAAAA,EAAU+C,YAAAA,CAAAA;AACjD;AAEA,QAAA,MAAMM,cAAc,IAAI,CAAC1B,OAAO,CAAC5B,iBAAiB,CAACkD,UAAAA,CAAAA;AAEnD,QAAA,MAAMK,KAAAA,GAA0B;YAC5BC,cAAAA,EAAgBV,MAAAA;AAChBW,YAAAA,aAAAA,EAAeP,WAAW5D,MAAM;AAChCyD,YAAAA,YAAAA;AACAO,YAAAA,WAAAA;AACAI,YAAAA,WAAAA,EAAaX,YAAAA,GAAeO,WAAAA;AAC5BL,YAAAA,QAAAA,EAAU,IAAI,CAACpB,MAAM,CAACoB;AAC1B,SAAA;SAEA,0BAAA,GAAA,CAAA,YAAA,GAAA,IAAI,CAACpB,MAAM,EAAC8B,aAAa,MAAA,IAAA,IAAzB,0BAAA,KAAA,MAAA,GAAA,MAAA,GAAA,0BAAA,CAAA,IAAA,CAAA,YAAA,EAA4BJ,KAAAA,CAAAA;AAE5B,QAAA,IAAI,CAACpC,MAAM,CAACyC,IAAI,CAAC,yBAAA,EAA2BL,KAAAA,CAAAA;QAE5C,OAAOL,UAAAA;AACX,IAAA;AAEA;;AAEC,QACD,kBAAQC,CACJlD,QAA+B,EAC/B+C,YAAoB,EACC;;AAErB,QAAA,MAAMa,eAAe5D,QAAAA,CAAS6D,GAAG,CAAC,CAACC,GAAAA,EAAKC,OAAS;gBAC7CxE,OAAAA,EAASuE,GAAAA;AACTE,gBAAAA,QAAAA,EAAU,IAAI,CAACC,iBAAiB,CAACH,GAAAA,EAAKC,GAAAA,EAAK/D,SAASX,MAAM,CAAA;AAC1DG,gBAAAA,MAAAA,EAAQ,IAAI,CAACmC,OAAO,CAACrC,YAAY,CAACwE,GAAAA,CAAAA;gBAClCI,KAAAA,EAAOH;aACX,CAAA,CAAA;;QAGAH,YAAAA,CAAaO,IAAI,CAAC,CAACC,CAAAA,EAAGC,IAAMA,CAAAA,CAAEL,QAAQ,GAAGI,CAAAA,CAAEJ,QAAQ,CAAA;;AAGnD,QAAA,MAAMM,OAA4B,EAAE;AACpC,QAAA,IAAIC,WAAAA,GAAc,CAAA;QAElB,KAAK,MAAMC,QAAQZ,YAAAA,CAAc;AAC7B,YAAA,IAAIW,WAAAA,GAAcC,IAAAA,CAAKhF,MAAM,IAAIuD,YAAAA,EAAc;AAC3CuB,gBAAAA,IAAAA,CAAKG,IAAI,CAACD,IAAAA,CAAAA;AACVD,gBAAAA,WAAAA,IAAeC,KAAKhF,MAAM;AAC9B,YAAA;AACJ,QAAA;;QAGA8E,IAAAA,CAAKH,IAAI,CAAC,CAACC,CAAAA,EAAGC,IAAMD,CAAAA,CAAEF,KAAK,GAAGG,CAAAA,CAAEH,KAAK,CAAA;AAErC,QAAA,OAAOI,KAAKT,GAAG,CAACW,CAAAA,IAAAA,GAAQA,KAAKjF,OAAO,CAAA;AACxC,IAAA;AAEA;;AAEC,QACD,YAAQ4D,CACJnD,QAA+B,EAC/B+C,YAAoB,EACC;AAgBD,QAAA,IAAA,2BAAA;AAdpB,QAAA,MAAM2B,eAAe,IAAIC,GAAAA,EAAAA;AACzB,QAAA,IAAIJ,WAAAA,GAAc,CAAA;;QAGlB,MAAMK,cAAAA,GAAiB5E,SAAS6E,MAAM,CAACvE,CAAAA,CAAAA,GAAKA,CAAAA,CAAEwE,IAAI,KAAK,QAAA,CAAA;AACvD,QAAA,IAAI,IAAI,CAAClD,MAAM,CAACmD,cAAc,EAAE;YAC5B,KAAK,MAAMjB,OAAOc,cAAAA,CAAgB;AAE9BF,gBAAAA,YAAAA,CAAaM,GAAG,CAAClB,GAAAA,CAAAA;AACjBS,gBAAAA,WAAAA,IAAe,IAAI,CAAC5C,OAAO,CAACrC,YAAY,CAACwE,GAAAA,CAAAA;AAC7C,YAAA;AACJ,QAAA;;QAGA,MAAMmB,WAAAA,GAAAA,CAAc,8BAAA,IAAI,CAACrD,MAAM,CAACsD,cAAc,MAAA,IAAA,IAA1B,2BAAA,KAAA,MAAA,GAAA,2BAAA,GAA8B,CAAA;AAClD,QAAA,MAAMC,cAAAA,GAAiBnF,QAAAA,CAASoF,KAAK,CAAC,CAACH,WAAAA,CAAAA,CAAaJ,MAAM,CAACvE,CAAAA,CAAAA,GAAKA,CAAAA,CAAEwE,IAAI,KAAK,QAAA,CAAA;QAC3E,KAAK,MAAMhB,OAAOqB,cAAAA,CAAgB;AAC9B,YAAA,IAAI,CAACT,YAAAA,CAAaW,GAAG,CAACvB,GAAAA,CAAAA,EAAM;AACxB,gBAAA,MAAMtE,SAAS,IAAI,CAACmC,OAAO,CAACrC,YAAY,CAACwE,GAAAA,CAAAA;gBACzC,IAAIS,WAAAA,GAAc/E,UAAUuD,YAAAA,EAAc;AAEtC2B,oBAAAA,YAAAA,CAAaM,GAAG,CAAClB,GAAAA,CAAAA;oBACjBS,WAAAA,IAAe/E,MAAAA;AACnB,gBAAA;AACJ,YAAA;AACJ,QAAA;;AAGA,QAAA,MAAM8F,aAAAA,GAAgBtF,QAAAA,CAAS6E,MAAM,CACjCvE,CAAAA,CAAAA,GAAK,CAACoE,YAAAA,CAAaW,GAAG,CAAC/E,CAAAA,CAAAA,IAAMA,CAAAA,CAAEwE,IAAI,KAAK,QAAA,CAAA;QAG5C,IAAK,IAAIS,IAAID,aAAAA,CAAcjG,MAAM,GAAG,CAAA,EAAGkG,CAAAA,IAAK,GAAGA,CAAAA,EAAAA,CAAK;YAChD,MAAMzB,GAAAA,GAAMwB,aAAa,CAACC,CAAAA,CAAE;AAC5B,YAAA,MAAM/F,SAAS,IAAI,CAACmC,OAAO,CAACrC,YAAY,CAACwE,GAAAA,CAAAA;YAEzC,IAAIS,WAAAA,GAAc/E,UAAUuD,YAAAA,EAAc;AAEtC2B,gBAAAA,YAAAA,CAAaM,GAAG,CAAClB,GAAAA,CAAAA;gBACjBS,WAAAA,IAAe/E,MAAAA;YACnB,CAAA,MAAO;AACH,gBAAA;AACJ,YAAA;AACJ,QAAA;;AAGA,QAAA,OAAOQ,SAAS6E,MAAM,CAACvE,CAAAA,CAAAA,GAAKoE,YAAAA,CAAaW,GAAG,CAAC/E,CAAAA,CAAAA,CAAAA;AACjD,IAAA;AAEA;;AAEC,QACD,gBAAQ8C,CACJpD,QAA+B,EAC/B+C,YAAoB,EACC;QACrB,MAAMyC,YAAAA,GAAexF,SAASX,MAAM;;AAGpC,QAAA,IAAImG,gBAAgB,CAAA,EAAG;AACnB,YAAA,OAAO,IAAI,CAACrC,YAAY,CAACnD,QAAAA,EAAU+C,YAAAA,CAAAA;AACvC,QAAA;;AAGA,QAAA,IAAIyC,gBAAgB,EAAA,EAAI;;AAEpB,YAAA,MAAMC,sBAAAA,GAAyB,IAAI,CAAC7D,MAAM,CAACsD,cAAc;AACzD,YAAA,IAAI,CAACtD,MAAM,CAACsD,cAAc,GAAG,CAAA;AAC7B,YAAA,MAAMQ,MAAAA,GAAS,IAAI,CAACvC,YAAY,CAACnD,QAAAA,EAAU+C,YAAAA,CAAAA;AAC3C,YAAA,IAAI,CAACnB,MAAM,CAACsD,cAAc,GAAGO,sBAAAA;YAC7B,OAAOC,MAAAA;AACX,QAAA;;AAGA,QAAA,OAAO,IAAI,CAACxC,kBAAkB,CAAClD,QAAAA,EAAU+C,YAAAA,CAAAA;AAC7C,IAAA;AAEA;;AAEC,QACD,iBAAQkB,CACJ1E,OAA4B,EAC5B2E,KAAa,EACbjE,KAAa,EACP;AACN,QAAA,IAAI+D,QAAAA,GAAW,GAAA;;QAGf,IAAIzE,OAAAA,CAAQuF,IAAI,KAAK,QAAA,EAAU;YAC3Bd,QAAAA,GAAW,IAAA;AACf,QAAA;;AAGA,QAAA,MAAM2B,eAAezB,KAAAA,GAAQjE,KAAAA;AAC7B+D,QAAAA,QAAAA,IAAY2B,YAAAA,GAAe,CAAA;;QAG3B,IAAIpG,OAAAA,CAAQuF,IAAI,KAAK,MAAA,EAAQ;YACzBd,QAAAA,IAAY,GAAA;AAChB,QAAA;;QAGA,IAAIzE,OAAAA,CAAQG,UAAU,IAAIH,OAAAA,CAAQG,UAAU,CAACL,MAAM,GAAG,CAAA,EAAG;YACrD2E,QAAAA,IAAY,GAAA;AAChB,QAAA;QAEA,OAAOA,QAAAA;AACX,IAAA;AAEA;;AAEC,QACD4B,QAAAA,CAAS5F,QAA+B,EAAE6F,WAAmB,EAAyB;QAClF,IAAI7F,QAAAA,CAASX,MAAM,IAAIwG,WAAAA,EAAa;YAChC,OAAO7F,QAAAA;AACX,QAAA;;QAGA,MAAM4E,cAAAA,GAAiB5E,SAAS6E,MAAM,CAACvE,CAAAA,CAAAA,GAAKA,CAAAA,CAAEwE,IAAI,KAAK,QAAA,CAAA;QACvD,MAAMQ,aAAAA,GAAgBtF,SAAS6E,MAAM,CAACvE,CAAAA,CAAAA,GAAKA,CAAAA,CAAEwE,IAAI,KAAK,QAAA,CAAA;QAEtD,MAAMgB,WAAAA,GAAcR,cAAcF,KAAK,CAAC,EAAES,WAAAA,GAAcjB,cAAAA,CAAevF,MAAM,CAAD,CAAA;QAE5E,OAAO;AAAIuF,YAAAA,GAAAA,cAAAA;AAAmBkB,YAAAA,GAAAA;AAAY,SAAA;AAC9C,IAAA;AAEA;;AAEC,QACD9E,OAAAA,GAAgB;QACZ,IAAI,CAACW,OAAO,CAACX,OAAO,EAAA;AACxB,IAAA;AA1SA,IAAA,WAAA,CAAYY,MAAyB,EAAEf,KAAY,EAAEK,MAAY,CAAE;AAJnE,QAAA,gBAAA,CAAA,IAAA,EAAQU,UAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQD,WAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQT,UAAR,MAAA,CAAA;QAGI,IAAI,CAACU,MAAM,GAAG;YACVS,gBAAAA,EAAkB,GAAA;YAClB6C,cAAAA,EAAgB,CAAA;YAChBH,cAAAA,EAAgB,IAAA;YAChBgB,oBAAAA,EAAsB,IAAA;AACtBxD,YAAAA,SAAAA,EAAW,IAAA,CAAO,CAAA;AAClBmB,YAAAA,aAAAA,EAAe,IAAA,CAAO,CAAA;AACtB,YAAA,GAAG9B;AACP,SAAA;AAEA,QAAA,IAAI,CAACD,OAAO,GAAG,IAAI3C,aAAa6B,KAAAA,EAAOK,MAAAA,CAAAA;AACvC,QAAA,IAAI,CAACA,MAAM,GAAGC,UAAAA,CAAWD,UAAUE,cAAAA,EAAgB,oBAAA,CAAA;AAEnD,QAAA,IAAI,CAACF,MAAM,CAACK,KAAK,CAAC,4BAAA,EAA8B;AAC5Cb,YAAAA,GAAAA,EAAK,IAAI,CAACkB,MAAM,CAAClB,GAAG;AACpBsC,YAAAA,QAAAA,EAAU,IAAI,CAACpB,MAAM,CAACoB;AAC1B,SAAA,CAAA;AACJ,IAAA;AAyRJ;;;;"}
|
package/dist/util/general.js
CHANGED
|
@@ -12,7 +12,7 @@ const stringifyJSON = function(obj, visited = new Set()) {
|
|
|
12
12
|
return '"(circular)"';
|
|
13
13
|
} else if (Array.isArray(obj)) {
|
|
14
14
|
//check for empty array
|
|
15
|
-
if (obj
|
|
15
|
+
if (obj.length === 0) return '[]';
|
|
16
16
|
else {
|
|
17
17
|
// Add array to visited before processing its elements
|
|
18
18
|
visited.add(obj);
|
package/dist/util/general.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"general.js","sources":["../../src/util/general.ts"],"sourcesContent":["export const clean = (obj: any) => {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n );\n}\n\n//Recursive implementation of jSON.stringify;\nexport const stringifyJSON = function (obj: any, visited: Set<any> = new Set()): string {\n const arrOfKeyVals: string[] = [];\n const arrVals: string[] = [];\n let objKeys: string[] = [];\n\n /*********CHECK FOR PRIMITIVE TYPES**********/\n if (typeof obj === 'number' || typeof obj === 'boolean' || obj === null)\n return '' + obj;\n else if (typeof obj === 'string')\n return '\"' + obj + '\"';\n\n /*********DETECT CIRCULAR REFERENCES**********/\n if (obj instanceof Object && visited.has(obj)) {\n return '\"(circular)\"';\n }\n\n /*********CHECK FOR ARRAY**********/\n else if (Array.isArray(obj)) {\n //check for empty array\n if (obj
|
|
1
|
+
{"version":3,"file":"general.js","sources":["../../src/util/general.ts"],"sourcesContent":["export const clean = (obj: any) => {\n return Object.fromEntries(\n Object.entries(obj).filter(([_, v]) => v !== undefined)\n );\n}\n\n//Recursive implementation of jSON.stringify;\nexport const stringifyJSON = function (obj: any, visited: Set<any> = new Set()): string {\n const arrOfKeyVals: string[] = [];\n const arrVals: string[] = [];\n let objKeys: string[] = [];\n\n /*********CHECK FOR PRIMITIVE TYPES**********/\n if (typeof obj === 'number' || typeof obj === 'boolean' || obj === null)\n return '' + obj;\n else if (typeof obj === 'string')\n return '\"' + obj + '\"';\n\n /*********DETECT CIRCULAR REFERENCES**********/\n if (obj instanceof Object && visited.has(obj)) {\n return '\"(circular)\"';\n }\n\n /*********CHECK FOR ARRAY**********/\n else if (Array.isArray(obj)) {\n //check for empty array\n if (obj.length === 0)\n return '[]';\n else {\n // Add array to visited before processing its elements\n visited.add(obj);\n obj.forEach(function (el) {\n arrVals.push(stringifyJSON(el, visited));\n });\n return '[' + arrVals + ']';\n }\n }\n /*********CHECK FOR OBJECT**********/\n else if (obj instanceof Object) {\n // Add object to visited before processing its properties\n visited.add(obj);\n //get object keys\n objKeys = Object.keys(obj);\n //set key output;\n objKeys.forEach(function (key) {\n const keyOut = '\"' + key + '\":';\n const keyValOut = obj[key];\n //skip functions and undefined properties\n if (keyValOut instanceof Function || keyValOut === undefined)\n return; // Skip this entry entirely instead of pushing an empty string\n else if (typeof keyValOut === 'string')\n arrOfKeyVals.push(keyOut + '\"' + keyValOut + '\"');\n else if (typeof keyValOut === 'boolean' || typeof keyValOut === 'number' || keyValOut === null)\n arrOfKeyVals.push(keyOut + keyValOut);\n //check for nested objects, call recursively until no more objects\n else if (keyValOut instanceof Object) {\n arrOfKeyVals.push(keyOut + stringifyJSON(keyValOut, visited));\n }\n });\n return '{' + arrOfKeyVals + '}';\n }\n return '';\n};\n"],"names":["clean","obj","Object","fromEntries","entries","filter","_","v","undefined","stringifyJSON","visited","Set","arrOfKeyVals","arrVals","objKeys","has","Array","isArray","length","add","forEach","el","push","keys","key","keyOut","keyValOut","Function"],"mappings":"AAAO,MAAMA,QAAQ,CAACC,GAAAA,GAAAA;AAClB,IAAA,OAAOC,MAAAA,CAAOC,WAAW,CACrBD,MAAAA,CAAOE,OAAO,CAACH,GAAAA,CAAAA,CAAKI,MAAM,CAAC,CAAC,CAACC,CAAAA,EAAGC,CAAAA,CAAE,GAAKA,CAAAA,KAAMC,SAAAA,CAAAA,CAAAA;AAErD;AAEA;MACaC,aAAAA,GAAgB,SAAUR,GAAQ,EAAES,OAAAA,GAAoB,IAAIC,GAAAA,EAAK,EAAA;AAC1E,IAAA,MAAMC,eAAyB,EAAE;AACjC,IAAA,MAAMC,UAAoB,EAAE;AAC5B,IAAA,IAAIC,UAAoB,EAAE;mDAG1B,IAAI,OAAOb,GAAAA,KAAQ,QAAA,IAAY,OAAOA,GAAAA,KAAQ,SAAA,IAAaA,GAAAA,KAAQ,IAAA,EAC/D,OAAO,EAAA,GAAKA,GAAAA;AACX,SAAA,IAAI,OAAOA,GAAAA,KAAQ,QAAA,EACpB,OAAO,MAAMA,GAAAA,GAAM,GAAA;AAEvB,oDACA,IAAIA,GAAAA,YAAeC,UAAUQ,OAAAA,CAAQK,GAAG,CAACd,GAAAA,CAAAA,EAAM;QAC3C,OAAO,cAAA;AACX,IAAA,CAAA,MAGK,IAAIe,KAAAA,CAAMC,OAAO,CAAChB,GAAAA,CAAAA,EAAM;;AAEzB,QAAA,IAAIA,GAAAA,CAAIiB,MAAM,KAAK,CAAA,EACf,OAAO,IAAA;AACN,aAAA;;AAEDR,YAAAA,OAAAA,CAAQS,GAAG,CAAClB,GAAAA,CAAAA;YACZA,GAAAA,CAAImB,OAAO,CAAC,SAAUC,EAAE,EAAA;gBACpBR,OAAAA,CAAQS,IAAI,CAACb,aAAAA,CAAcY,EAAAA,EAAIX,OAAAA,CAAAA,CAAAA;AACnC,YAAA,CAAA,CAAA;AACA,YAAA,OAAO,MAAMG,OAAAA,GAAU,GAAA;AAC3B,QAAA;IACJ,CAAA,MAEK,IAAIZ,eAAeC,MAAAA,EAAQ;;AAE5BQ,QAAAA,OAAAA,CAAQS,GAAG,CAAClB,GAAAA,CAAAA;;QAEZa,OAAAA,GAAUZ,MAAAA,CAAOqB,IAAI,CAACtB,GAAAA,CAAAA;;QAEtBa,OAAAA,CAAQM,OAAO,CAAC,SAAUI,GAAG,EAAA;YACzB,MAAMC,MAAAA,GAAS,MAAMD,GAAAA,GAAM,IAAA;YAC3B,MAAME,SAAAA,GAAYzB,GAAG,CAACuB,GAAAA,CAAI;;AAE1B,YAAA,IAAIE,SAAAA,YAAqBC,QAAAA,IAAYD,SAAAA,KAAclB,SAAAA,EAC/C;iBACC,IAAI,OAAOkB,cAAc,QAAA,EAC1Bd,YAAAA,CAAaU,IAAI,CAACG,MAAAA,GAAS,MAAMC,SAAAA,GAAY,GAAA,CAAA;iBAC5C,IAAI,OAAOA,SAAAA,KAAc,SAAA,IAAa,OAAOA,SAAAA,KAAc,QAAA,IAAYA,SAAAA,KAAc,IAAA,EACtFd,YAAAA,CAAaU,IAAI,CAACG,MAAAA,GAASC,SAAAA,CAAAA;AAE1B,iBAAA,IAAIA,qBAAqBxB,MAAAA,EAAQ;AAClCU,gBAAAA,YAAAA,CAAaU,IAAI,CAACG,MAAAA,GAAShB,aAAAA,CAAciB,SAAAA,EAAWhB,OAAAA,CAAAA,CAAAA;AACxD,YAAA;AACJ,QAAA,CAAA,CAAA;AACA,QAAA,OAAO,MAAME,YAAAA,GAAe,GAAA;AAChC,IAAA;IACA,OAAO,EAAA;AACX;;;;"}
|