@riotprompt/riotprompt 0.0.21 → 1.0.1-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/MIGRATION.md +235 -0
  3. package/README.md +2 -0
  4. package/SECURITY.md +132 -0
  5. package/dist/builder.js +6 -0
  6. package/dist/builder.js.map +1 -1
  7. package/dist/cli.js +481 -22
  8. package/dist/context-manager.js +1 -1
  9. package/dist/conversation-logger.d.ts +17 -1
  10. package/dist/conversation-logger.js +21 -17
  11. package/dist/conversation-logger.js.map +1 -1
  12. package/dist/conversation.js +1 -1
  13. package/dist/error-handling.d.ts +52 -0
  14. package/dist/error-handling.js +132 -0
  15. package/dist/error-handling.js.map +1 -0
  16. package/dist/formatter.js +1 -1
  17. package/dist/iteration-strategy.js +1 -1
  18. package/dist/loader.js +60 -12
  19. package/dist/loader.js.map +1 -1
  20. package/dist/logger.d.ts +52 -0
  21. package/dist/logger.js +114 -14
  22. package/dist/logger.js.map +1 -1
  23. package/dist/logging-config.d.ts +84 -0
  24. package/dist/logging-config.js +116 -0
  25. package/dist/logging-config.js.map +1 -0
  26. package/dist/message-builder.js +1 -1
  27. package/dist/model-config.js +1 -1
  28. package/dist/override.js +10 -4
  29. package/dist/override.js.map +1 -1
  30. package/dist/recipes.js +6 -0
  31. package/dist/recipes.js.map +1 -1
  32. package/dist/reflection.js +1 -1
  33. package/dist/riotprompt.d.ts +9 -0
  34. package/dist/riotprompt.js +8 -0
  35. package/dist/riotprompt.js.map +1 -1
  36. package/dist/security/audit-logger.d.ts +61 -0
  37. package/dist/security/audit-logger.js +281 -0
  38. package/dist/security/audit-logger.js.map +1 -0
  39. package/dist/security/cli-security.d.ts +143 -0
  40. package/dist/security/cli-security.js +302 -0
  41. package/dist/security/cli-security.js.map +1 -0
  42. package/dist/security/defaults.d.ts +31 -0
  43. package/dist/security/defaults.js +72 -0
  44. package/dist/security/defaults.js.map +1 -0
  45. package/dist/security/events.d.ts +8 -0
  46. package/dist/security/index.d.ts +27 -0
  47. package/dist/security/index.js +22 -0
  48. package/dist/security/index.js.map +1 -0
  49. package/dist/security/path-guard.d.ts +161 -0
  50. package/dist/security/path-guard.js +327 -0
  51. package/dist/security/path-guard.js.map +1 -0
  52. package/dist/security/rate-limiter.d.ts +117 -0
  53. package/dist/security/rate-limiter.js +165 -0
  54. package/dist/security/rate-limiter.js.map +1 -0
  55. package/dist/security/serialization-schemas.d.ts +183 -0
  56. package/dist/security/serialization-schemas.js +174 -0
  57. package/dist/security/serialization-schemas.js.map +1 -0
  58. package/dist/security/timeout-guard.d.ts +123 -0
  59. package/dist/security/timeout-guard.js +223 -0
  60. package/dist/security/timeout-guard.js.map +1 -0
  61. package/dist/security/types.d.ts +86 -0
  62. package/dist/security/types.js +80 -0
  63. package/dist/security/types.js.map +1 -0
  64. package/dist/token-budget.js +1 -1
  65. package/dist/tools.js +1 -1
  66. package/guide/index.md +2 -0
  67. package/guide/integration.md +1109 -0
  68. package/guide/security.md +237 -0
  69. package/package.json +18 -11
@@ -1 +1 @@
1
- {"version":3,"file":"conversation-logger.js","sources":["../src/conversation-logger.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport { DEFAULT_LOGGER, wrapLogger } from \"./logger\";\nimport type { ConversationMessage, ToolCall } from \"./conversation\";\n\n// ===== TYPE DEFINITIONS =====\n\n/**\n * Log format\n */\nexport type LogFormat = 'json' | 'markdown' | 'jsonl';\n\n/**\n * Log configuration\n */\nexport interface LogConfig {\n enabled: boolean;\n outputPath?: string;\n format?: LogFormat;\n filenameTemplate?: string;\n includeMetadata?: boolean;\n includePrompt?: boolean;\n redactSensitive?: boolean;\n redactPatterns?: RegExp[];\n onSaved?: (path: string) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Logged conversation structure\n */\nexport interface LoggedConversation {\n id: string;\n metadata: ConversationLogMetadata;\n prompt?: PromptSnapshot;\n messages: LoggedMessage[];\n summary: ConversationSummary;\n}\n\n/**\n * Conversation metadata for logging\n */\nexport interface ConversationLogMetadata {\n startTime: Date;\n endTime?: Date;\n duration?: number;\n model: string;\n template?: string;\n userContext?: Record<string, any>;\n}\n\n/**\n * Snapshot of prompt configuration\n */\nexport interface PromptSnapshot {\n persona?: string;\n instructions?: string;\n content?: string[];\n context?: string[];\n}\n\n/**\n * Logged message with metadata\n */\nexport interface LoggedMessage {\n index: number;\n timestamp: string;\n role: string;\n content: string | null;\n tool_calls?: ToolCall[];\n tool_call_id?: string;\n metadata?: MessageLogMetadata;\n}\n\n/**\n * Message metadata for logging\n */\nexport interface MessageLogMetadata {\n tokens?: number;\n source?: string;\n latency?: number;\n tool?: string;\n duration?: number;\n success?: boolean;\n [key: string]: any;\n}\n\n/**\n * Conversation summary\n */\nexport interface ConversationSummary {\n totalMessages: number;\n totalTokens?: number;\n toolCallsExecuted: number;\n iterations: number;\n finalOutput?: string;\n success: boolean;\n}\n\n/**\n * Tool call log entry\n */\nexport interface ToolCallLog {\n callId: string;\n toolName: string;\n timestamp: string;\n iteration: number;\n arguments: any;\n result: any;\n duration: number;\n success: boolean;\n error?: string;\n}\n\n// ===== CONVERSATION LOGGER =====\n\n/**\n * ConversationLogger logs conversations to various formats.\n *\n * Features:\n * - Multiple formats (JSON, Markdown, JSONL)\n * - Automatic timestamping\n * - Metadata tracking\n * - Sensitive data redaction\n * - Streaming support (JSONL)\n *\n * @example\n * ```typescript\n * const logger = new ConversationLogger({\n * enabled: true,\n * outputPath: 'logs/conversations',\n * format: 'json',\n * includeMetadata: true\n * });\n *\n * logger.onConversationStart({ model: 'gpt-4o', startTime: new Date() });\n * logger.onMessageAdded(message);\n * const path = await logger.save();\n * ```\n */\nexport class ConversationLogger {\n private config: Required<LogConfig>;\n private conversationId: string;\n private metadata: ConversationLogMetadata;\n private messages: LoggedMessage[];\n private toolCalls: ToolCallLog[];\n private startTime: Date;\n private logger: any;\n private messageIndex: number;\n private cachedOutputPath?: string;\n private writeQueue: Promise<void> = Promise.resolve();\n\n constructor(config: LogConfig, logger?: any) {\n this.config = {\n outputPath: 'logs/conversations',\n format: 'json',\n filenameTemplate: 'conversation-{timestamp}',\n includeMetadata: true,\n includePrompt: false,\n redactSensitive: false,\n redactPatterns: [],\n onSaved: () => {},\n onError: () => {},\n ...config,\n } as Required<LogConfig>;\n\n this.conversationId = this.generateId();\n this.messages = [];\n this.toolCalls = [];\n this.startTime = new Date();\n this.messageIndex = 0;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationLogger');\n\n this.metadata = {\n startTime: this.startTime,\n model: 'unknown',\n };\n }\n\n /**\n * Start conversation logging\n */\n onConversationStart(metadata: Partial<ConversationLogMetadata>): void {\n this.metadata = {\n ...this.metadata,\n ...metadata,\n startTime: this.startTime,\n };\n\n // Reset cached output path to prevent file collision if logger is reused\n this.cachedOutputPath = undefined;\n\n this.logger.debug('Conversation logging started', { id: this.conversationId });\n }\n\n /**\n * Log a message\n */\n onMessageAdded(message: ConversationMessage, metadata?: MessageLogMetadata): void {\n let content = message.content;\n\n // Redact sensitive data if enabled\n if (this.config.redactSensitive && content && typeof content === 'string') {\n content = this.redactContent(content);\n }\n\n const loggedMessage: LoggedMessage = {\n index: this.messageIndex++,\n timestamp: new Date().toISOString(),\n role: message.role,\n content,\n tool_calls: message.tool_calls,\n tool_call_id: message.tool_call_id,\n metadata,\n };\n\n this.messages.push(loggedMessage);\n\n // For JSONL format, append immediately with write queue\n if (this.config.format === 'jsonl') {\n this.writeQueue = this.writeQueue\n .then(() => this.appendToJSONL(loggedMessage))\n .catch((error) => {\n this.logger.error('Failed to write JSONL message', { error });\n try {\n this.config.onError?.(error);\n } catch (callbackError) {\n this.logger.error('onError callback failed', { callbackError });\n }\n });\n }\n }\n\n /**\n * Log a tool call\n */\n onToolCall(\n callId: string,\n toolName: string,\n iteration: number,\n args: any,\n result: any,\n duration: number,\n success: boolean,\n error?: string\n ): void {\n this.toolCalls.push({\n callId,\n toolName,\n timestamp: new Date().toISOString(),\n iteration,\n arguments: args,\n result,\n duration,\n success,\n error,\n });\n }\n\n /**\n * End conversation logging\n */\n onConversationEnd(_summary: ConversationSummary): void {\n this.metadata.endTime = new Date();\n this.metadata.duration = this.metadata.endTime.getTime() - this.startTime.getTime();\n\n this.logger.debug('Conversation logging ended', {\n messages: this.messages.length,\n duration: this.metadata.duration\n });\n }\n\n /**\n * Save conversation to disk\n */\n async save(): Promise<string> {\n if (!this.config.enabled) {\n return '';\n }\n\n try {\n const outputPath = await this.getOutputPath();\n\n switch (this.config.format) {\n case 'json':\n await this.saveAsJSON(outputPath);\n break;\n case 'markdown':\n await this.saveAsMarkdown(outputPath);\n break;\n case 'jsonl':\n // Already saved during execution\n break;\n }\n\n this.config.onSaved(outputPath);\n this.logger.info('Conversation saved', { path: outputPath });\n\n return outputPath;\n } catch (error) {\n this.config.onError(error as Error);\n this.logger.error('Failed to save conversation', { error });\n throw error;\n }\n }\n\n /**\n * Get logged conversation object\n */\n getConversation(): LoggedConversation {\n return {\n id: this.conversationId,\n metadata: this.metadata,\n messages: this.messages,\n summary: {\n totalMessages: this.messages.length,\n toolCallsExecuted: this.toolCalls.length,\n iterations: 0, // Would need to be tracked externally\n success: true,\n },\n };\n }\n\n /**\n * Generate unique conversation ID\n */\n private generateId(): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const random = Math.random().toString(36).substring(2, 8);\n return `conv-${timestamp}-${random}`;\n }\n\n /**\n * Get output file path (cached for JSONL to avoid recalculation)\n */\n private async getOutputPath(): Promise<string> {\n if (this.cachedOutputPath) {\n return this.cachedOutputPath;\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = this.config.filenameTemplate\n .replace('{timestamp}', timestamp)\n .replace('{id}', this.conversationId)\n .replace('{template}', this.metadata.template || 'default');\n\n let ext = '.json';\n if (this.config.format === 'markdown') {\n ext = '.md';\n } else if (this.config.format === 'jsonl') {\n ext = '.jsonl';\n }\n \n const fullPath = path.join(this.config.outputPath, filename + ext);\n\n // Ensure directory exists\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n\n // Cache path for JSONL format to ensure consistent file writes\n if (this.config.format === 'jsonl') {\n this.cachedOutputPath = fullPath;\n }\n\n return fullPath;\n }\n\n /**\n * Save as JSON\n */\n private async saveAsJSON(outputPath: string): Promise<void> {\n const data: LoggedConversation = {\n id: this.conversationId,\n metadata: this.metadata,\n messages: this.messages,\n summary: {\n totalMessages: this.messages.length,\n toolCallsExecuted: this.toolCalls.length,\n iterations: 0,\n success: true,\n },\n };\n\n await fs.writeFile(outputPath, JSON.stringify(data, null, 2), 'utf-8');\n }\n\n /**\n * Save as Markdown\n */\n private async saveAsMarkdown(outputPath: string): Promise<void> {\n let markdown = `# Conversation Log\\n\\n`;\n markdown += `**ID**: ${this.conversationId}\\n`;\n markdown += `**Started**: ${this.metadata.startTime.toISOString()}\\n`;\n if (this.metadata.duration) {\n markdown += `**Duration**: ${(this.metadata.duration / 1000).toFixed(1)}s\\n`;\n }\n markdown += `**Model**: ${this.metadata.model}\\n`;\n if (this.metadata.template) {\n markdown += `**Template**: ${this.metadata.template}\\n`;\n }\n markdown += `\\n## Conversation\\n\\n`;\n\n for (const msg of this.messages) {\n const time = new Date(msg.timestamp).toLocaleTimeString();\n markdown += `### Message ${msg.index + 1} (${time}) - ${msg.role}\\n\\n`;\n\n if (msg.content) {\n markdown += `\\`\\`\\`\\n${msg.content}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (msg.tool_calls) {\n markdown += `**Tool Calls:**\\n`;\n for (const call of msg.tool_calls) {\n markdown += `- ${call.function.name}: \\`${call.function.arguments}\\`\\n`;\n }\n markdown += `\\n`;\n }\n\n if (msg.metadata) {\n markdown += `*Metadata: ${JSON.stringify(msg.metadata)}*\\n\\n`;\n }\n }\n\n markdown += `## Summary\\n\\n`;\n markdown += `- **Total Messages**: ${this.messages.length}\\n`;\n markdown += `- **Tool Calls**: ${this.toolCalls.length}\\n`;\n\n await fs.writeFile(outputPath, markdown, 'utf-8');\n }\n\n /**\n * Append to JSONL file (streaming)\n */\n private async appendToJSONL(message: LoggedMessage): Promise<void> {\n const outputPath = await this.getOutputPath();\n const line = JSON.stringify(message) + '\\n';\n await fs.appendFile(outputPath, line, 'utf-8');\n }\n\n /**\n * Redact sensitive content\n */\n private redactContent(content: string): string {\n let redacted = content;\n\n // Apply custom patterns\n for (const pattern of this.config.redactPatterns) {\n redacted = redacted.replace(pattern, '[REDACTED]');\n }\n\n // Default patterns\n const defaultPatterns = [\n /api[_-]?key[\\s:=\"']+[\\w-]+/gi,\n /password[\\s:=\"']+[\\w-]+/gi,\n /Bearer\\s+[\\w-]+/gi,\n /sk-[a-zA-Z0-9]{48}/g,\n ];\n\n for (const pattern of defaultPatterns) {\n redacted = redacted.replace(pattern, '[REDACTED]');\n }\n\n return redacted;\n }\n}\n\n// ===== CONVERSATION REPLAYER =====\n\n/**\n * Replay options\n */\nexport interface ReplayOptions {\n model?: string;\n maxIterations?: number;\n retryFailedTools?: boolean;\n toolTimeout?: number;\n expectSimilarOutput?: boolean;\n}\n\n/**\n * Replay result\n */\nexport interface ReplayResult {\n success: boolean;\n conversation: LoggedConversation;\n errors?: Error[];\n}\n\n/**\n * Comparison result\n */\nexport interface ComparisonResult {\n messageDiff: number;\n toolCallDiff: number;\n tokenDiff?: number;\n outputSimilarity: number;\n costSavings?: number;\n}\n\n/**\n * ConversationReplayer loads and replays logged conversations.\n *\n * Features:\n * - Load from various formats\n * - Replay conversations\n * - Compare replays with originals\n * - Export to different formats\n *\n * @example\n * ```typescript\n * const replayer = await ConversationReplayer.load('logs/conv.json');\n *\n * console.log('Messages:', replayer.messages.length);\n * console.log('Tool calls:', replayer.getToolCalls().length);\n *\n * const timeline = replayer.getTimeline();\n * console.log('Events:', timeline.length);\n * ```\n */\nexport class ConversationReplayer {\n private conversation: LoggedConversation;\n private logger: any;\n\n private constructor(conversation: LoggedConversation, logger?: any) {\n this.conversation = conversation;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');\n }\n\n /**\n * Load conversation from file\n */\n static async load(filePath: string, logger?: any): Promise<ConversationReplayer> {\n const wlogger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');\n wlogger.debug('Loading conversation', { path: filePath });\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n\n // Determine format by extension\n if (filePath.endsWith('.json')) {\n const data: LoggedConversation = JSON.parse(content);\n return new ConversationReplayer(data, logger);\n } else if (filePath.endsWith('.jsonl')) {\n const lines = content.trim().split('\\n');\n const messages = lines.map(line => JSON.parse(line));\n\n const conversation: LoggedConversation = {\n id: `replayer-${Date.now()}`,\n metadata: {\n startTime: new Date(),\n model: 'unknown'\n },\n messages,\n summary: {\n totalMessages: messages.length,\n toolCallsExecuted: 0,\n iterations: 0,\n success: true\n }\n };\n\n return new ConversationReplayer(conversation, logger);\n } else {\n throw new Error(`Unsupported format: ${filePath}`);\n }\n } catch (error) {\n wlogger.error('Failed to load conversation', { path: filePath, error });\n throw error;\n }\n }\n\n /**\n * Load latest conversation from directory\n */\n static async loadLatest(directory: string, logger?: any): Promise<ConversationReplayer> {\n const files = await fs.readdir(directory);\n const jsonFiles = files.filter(f => f.endsWith('.json')).sort().reverse();\n\n if (jsonFiles.length === 0) {\n throw new Error(`No conversation logs found in ${directory}`);\n }\n\n const latestPath = path.join(directory, jsonFiles[0]);\n return ConversationReplayer.load(latestPath, logger);\n }\n\n /**\n * Get all messages\n */\n get messages(): LoggedMessage[] {\n return this.conversation.messages;\n }\n\n /**\n * Get conversation metadata\n */\n getMetadata(): ConversationLogMetadata {\n return { ...this.conversation.metadata };\n }\n\n /**\n * Get tool calls\n */\n getToolCalls(): ToolCallLog[] {\n const toolCalls: ToolCallLog[] = [];\n\n for (const msg of this.conversation.messages) {\n if (msg.tool_calls) {\n for (const call of msg.tool_calls) {\n // Parse arguments with error handling\n let parsedArgs: any;\n try {\n parsedArgs = JSON.parse(call.function.arguments);\n } catch (error) {\n this.logger.warn('Failed to parse tool call arguments', {\n callId: call.id,\n error: error instanceof Error ? error.message : String(error)\n });\n parsedArgs = { __parse_error: true, raw: call.function.arguments };\n }\n\n toolCalls.push({\n callId: call.id,\n toolName: call.function.name,\n timestamp: msg.timestamp,\n iteration: 0, // Would need to be calculated\n arguments: parsedArgs,\n result: null, // Would need to find corresponding tool message\n duration: 0,\n success: true,\n });\n }\n }\n }\n\n return toolCalls;\n }\n\n /**\n * Get message at index\n */\n getMessageAt(index: number): LoggedMessage | undefined {\n return this.conversation.messages[index];\n }\n\n /**\n * Get timeline of events\n */\n getTimeline(): TimelineEvent[] {\n const events: TimelineEvent[] = [];\n\n for (const msg of this.conversation.messages) {\n events.push({\n timestamp: msg.timestamp,\n iteration: 0, // Would need iteration tracking\n type: 'message',\n description: `${msg.role} message`,\n });\n }\n\n return events;\n }\n\n /**\n * Export to format\n */\n async exportToFormat(format: LogFormat, outputPath: string): Promise<string> {\n this.logger.debug('Exporting to format', { format, path: outputPath });\n\n switch (format) {\n case 'json':\n await fs.writeFile(outputPath, JSON.stringify(this.conversation, null, 2), 'utf-8');\n break;\n case 'markdown':\n await this.exportMarkdown(outputPath);\n break;\n case 'jsonl': {\n const lines = this.messages.map(m => JSON.stringify(m)).join('\\n');\n await fs.writeFile(outputPath, lines, 'utf-8');\n break;\n }\n }\n\n return outputPath;\n }\n\n /**\n * Export as markdown\n */\n private async exportMarkdown(outputPath: string): Promise<void> {\n let markdown = `# Conversation Log\\n\\n`;\n markdown += `**ID**: ${this.conversation.id}\\n`;\n\n const startTime = typeof this.conversation.metadata.startTime === 'string'\n ? this.conversation.metadata.startTime\n : this.conversation.metadata.startTime.toISOString();\n\n markdown += `**Started**: ${startTime}\\n\\n`;\n\n for (const msg of this.conversation.messages) {\n markdown += `## ${msg.role.toUpperCase()} (${msg.index})\\n\\n`;\n if (msg.content) {\n markdown += `${msg.content}\\n\\n`;\n }\n }\n\n await fs.writeFile(outputPath, markdown, 'utf-8');\n }\n}\n\n/**\n * Timeline event interface\n */\ninterface TimelineEvent {\n timestamp: string;\n iteration: number;\n type: string;\n description: string;\n duration?: number;\n success?: boolean;\n}\n\nexport default ConversationLogger;\n\n"],"names":["ConversationLogger","onConversationStart","metadata","startTime","cachedOutputPath","undefined","logger","debug","id","conversationId","onMessageAdded","message","content","config","redactSensitive","redactContent","loggedMessage","index","messageIndex","timestamp","Date","toISOString","role","tool_calls","tool_call_id","messages","push","format","writeQueue","then","appendToJSONL","catch","error","onError","callbackError","onToolCall","callId","toolName","iteration","args","result","duration","success","toolCalls","arguments","onConversationEnd","_summary","endTime","getTime","length","save","enabled","outputPath","getOutputPath","saveAsJSON","saveAsMarkdown","onSaved","info","path","getConversation","summary","totalMessages","toolCallsExecuted","iterations","generateId","replace","random","Math","toString","substring","filename","filenameTemplate","template","ext","fullPath","join","fs","mkdir","dirname","recursive","data","writeFile","JSON","stringify","markdown","toFixed","model","msg","time","toLocaleTimeString","call","function","name","line","appendFile","redacted","pattern","redactPatterns","defaultPatterns","Promise","resolve","includeMetadata","includePrompt","wrapLogger","DEFAULT_LOGGER","ConversationReplayer","load","filePath","wlogger","readFile","endsWith","parse","lines","trim","split","map","conversation","now","Error","loadLatest","directory","files","readdir","jsonFiles","filter","f","sort","reverse","latestPath","getMetadata","getToolCalls","parsedArgs","warn","String","__parse_error","raw","getMessageAt","getTimeline","events","type","description","exportToFormat","exportMarkdown","m","toUpperCase"],"mappings":";;;;;;;;;;;;;;;;;AAkHA;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBC,IACM,MAAMA,kBAAAA,CAAAA;AAuCT;;QAGAC,mBAAAA,CAAoBC,QAA0C,EAAQ;QAClE,IAAI,CAACA,QAAQ,GAAG;YACZ,GAAG,IAAI,CAACA,QAAQ;AAChB,YAAA,GAAGA,QAAQ;YACXC,SAAAA,EAAW,IAAI,CAACA;AACpB,SAAA;;QAGA,IAAI,CAACC,gBAAgB,GAAGC,SAAAA;AAExB,QAAA,IAAI,CAACC,MAAM,CAACC,KAAK,CAAC,8BAAA,EAAgC;YAAEC,EAAAA,EAAI,IAAI,CAACC;AAAe,SAAA,CAAA;AAChF,IAAA;AAEA;;AAEC,QACDC,cAAAA,CAAeC,OAA4B,EAAET,QAA6B,EAAQ;QAC9E,IAAIU,OAAAA,GAAUD,QAAQC,OAAO;;QAG7B,IAAI,IAAI,CAACC,MAAM,CAACC,eAAe,IAAIF,OAAAA,IAAW,OAAOA,OAAAA,KAAY,QAAA,EAAU;YACvEA,OAAAA,GAAU,IAAI,CAACG,aAAa,CAACH,OAAAA,CAAAA;AACjC,QAAA;AAEA,QAAA,MAAMI,aAAAA,GAA+B;YACjCC,KAAAA,EAAO,IAAI,CAACC,YAAY,EAAA;YACxBC,SAAAA,EAAW,IAAIC,OAAOC,WAAW,EAAA;AACjCC,YAAAA,IAAAA,EAAMX,QAAQW,IAAI;AAClBV,YAAAA,OAAAA;AACAW,YAAAA,UAAAA,EAAYZ,QAAQY,UAAU;AAC9BC,YAAAA,YAAAA,EAAcb,QAAQa,YAAY;AAClCtB,YAAAA;AACJ,SAAA;AAEA,QAAA,IAAI,CAACuB,QAAQ,CAACC,IAAI,CAACV,aAAAA,CAAAA;;AAGnB,QAAA,IAAI,IAAI,CAACH,MAAM,CAACc,MAAM,KAAK,OAAA,EAAS;AAChC,YAAA,IAAI,CAACC,UAAU,GAAG,IAAI,CAACA,UAAU,CAC5BC,IAAI,CAAC,IAAM,IAAI,CAACC,aAAa,CAACd,aAAAA,CAAAA,CAAAA,CAC9Be,KAAK,CAAC,CAACC,KAAAA,GAAAA;AACJ,gBAAA,IAAI,CAAC1B,MAAM,CAAC0B,KAAK,CAAC,+BAAA,EAAiC;AAAEA,oBAAAA;AAAM,iBAAA,CAAA;gBAC3D,IAAI;wBACA,oBAAA,EAAA,YAAA;qBAAA,oBAAA,GAAA,CAAA,YAAA,GAAA,IAAI,CAACnB,MAAM,EAACoB,OAAO,MAAA,IAAA,IAAnB,oBAAA,KAAA,KAAA,CAAA,GAAA,KAAA,CAAA,GAAA,oBAAA,CAAA,IAAA,CAAA,YAAA,EAAsBD,KAAAA,CAAAA;AAC1B,gBAAA,CAAA,CAAE,OAAOE,aAAAA,EAAe;AACpB,oBAAA,IAAI,CAAC5B,MAAM,CAAC0B,KAAK,CAAC,yBAAA,EAA2B;AAAEE,wBAAAA;AAAc,qBAAA,CAAA;AACjE,gBAAA;AACJ,YAAA,CAAA,CAAA;AACR,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDC,WACIC,MAAc,EACdC,QAAgB,EAChBC,SAAiB,EACjBC,IAAS,EACTC,MAAW,EACXC,QAAgB,EAChBC,OAAgB,EAChBV,KAAc,EACV;AACJ,QAAA,IAAI,CAACW,SAAS,CAACjB,IAAI,CAAC;AAChBU,YAAAA,MAAAA;AACAC,YAAAA,QAAAA;YACAlB,SAAAA,EAAW,IAAIC,OAAOC,WAAW,EAAA;AACjCiB,YAAAA,SAAAA;YACAM,SAAAA,EAAWL,IAAAA;AACXC,YAAAA,MAAAA;AACAC,YAAAA,QAAAA;AACAC,YAAAA,OAAAA;AACAV,YAAAA;AACJ,SAAA,CAAA;AACJ,IAAA;AAEA;;QAGAa,iBAAAA,CAAkBC,QAA6B,EAAQ;AACnD,QAAA,IAAI,CAAC5C,QAAQ,CAAC6C,OAAO,GAAG,IAAI3B,IAAAA,EAAAA;AAC5B,QAAA,IAAI,CAAClB,QAAQ,CAACuC,QAAQ,GAAG,IAAI,CAACvC,QAAQ,CAAC6C,OAAO,CAACC,OAAO,EAAA,GAAK,IAAI,CAAC7C,SAAS,CAAC6C,OAAO,EAAA;AAEjF,QAAA,IAAI,CAAC1C,MAAM,CAACC,KAAK,CAAC,4BAAA,EAA8B;AAC5CkB,YAAAA,QAAAA,EAAU,IAAI,CAACA,QAAQ,CAACwB,MAAM;AAC9BR,YAAAA,QAAAA,EAAU,IAAI,CAACvC,QAAQ,CAACuC;AAC5B,SAAA,CAAA;AACJ,IAAA;AAEA;;AAEC,QACD,MAAMS,IAAAA,GAAwB;AAC1B,QAAA,IAAI,CAAC,IAAI,CAACrC,MAAM,CAACsC,OAAO,EAAE;YACtB,OAAO,EAAA;AACX,QAAA;QAEA,IAAI;AACA,YAAA,MAAMC,UAAAA,GAAa,MAAM,IAAI,CAACC,aAAa,EAAA;AAE3C,YAAA,OAAQ,IAAI,CAACxC,MAAM,CAACc,MAAM;gBACtB,KAAK,MAAA;oBACD,MAAM,IAAI,CAAC2B,UAAU,CAACF,UAAAA,CAAAA;AACtB,oBAAA;gBACJ,KAAK,UAAA;oBACD,MAAM,IAAI,CAACG,cAAc,CAACH,UAAAA,CAAAA;AAC1B,oBAAA;gBACJ,KAAK,OAAA;AAED,oBAAA;AACR;AAEA,YAAA,IAAI,CAACvC,MAAM,CAAC2C,OAAO,CAACJ,UAAAA,CAAAA;AACpB,YAAA,IAAI,CAAC9C,MAAM,CAACmD,IAAI,CAAC,oBAAA,EAAsB;gBAAEC,IAAAA,EAAMN;AAAW,aAAA,CAAA;YAE1D,OAAOA,UAAAA;AACX,QAAA,CAAA,CAAE,OAAOpB,KAAAA,EAAO;AACZ,YAAA,IAAI,CAACnB,MAAM,CAACoB,OAAO,CAACD,KAAAA,CAAAA;AACpB,YAAA,IAAI,CAAC1B,MAAM,CAAC0B,KAAK,CAAC,6BAAA,EAA+B;AAAEA,gBAAAA;AAAM,aAAA,CAAA;YACzD,MAAMA,KAAAA;AACV,QAAA;AACJ,IAAA;AAEA;;AAEC,QACD2B,eAAAA,GAAsC;QAClC,OAAO;YACHnD,EAAAA,EAAI,IAAI,CAACC,cAAc;YACvBP,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBuB,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBmC,OAAAA,EAAS;AACLC,gBAAAA,aAAAA,EAAe,IAAI,CAACpC,QAAQ,CAACwB,MAAM;AACnCa,gBAAAA,iBAAAA,EAAmB,IAAI,CAACnB,SAAS,CAACM,MAAM;gBACxCc,UAAAA,EAAY,CAAA;gBACZrB,OAAAA,EAAS;AACb;AACJ,SAAA;AACJ,IAAA;AAEA;;AAEC,QACD,UAAQsB,GAAqB;AACzB,QAAA,MAAM7C,YAAY,IAAIC,IAAAA,EAAAA,CAAOC,WAAW,EAAA,CAAG4C,OAAO,CAAC,OAAA,EAAS,GAAA,CAAA;QAC5D,MAAMC,MAAAA,GAASC,KAAKD,MAAM,EAAA,CAAGE,QAAQ,CAAC,EAAA,CAAA,CAAIC,SAAS,CAAC,CAAA,EAAG,CAAA,CAAA;AACvD,QAAA,OAAO,CAAC,KAAK,EAAElD,SAAAA,CAAU,CAAC,EAAE+C,MAAAA,CAAAA,CAAQ;AACxC,IAAA;AAEA;;AAEC,QACD,MAAcb,aAAAA,GAAiC;QAC3C,IAAI,IAAI,CAACjD,gBAAgB,EAAE;YACvB,OAAO,IAAI,CAACA,gBAAgB;AAChC,QAAA;AAEA,QAAA,MAAMe,YAAY,IAAIC,IAAAA,EAAAA,CAAOC,WAAW,EAAA,CAAG4C,OAAO,CAAC,OAAA,EAAS,GAAA,CAAA;QAC5D,MAAMK,QAAAA,GAAW,IAAI,CAACzD,MAAM,CAAC0D,gBAAgB,CACxCN,OAAO,CAAC,aAAA,EAAe9C,SAAAA,CAAAA,CACvB8C,OAAO,CAAC,QAAQ,IAAI,CAACxD,cAAc,CAAA,CACnCwD,OAAO,CAAC,YAAA,EAAc,IAAI,CAAC/D,QAAQ,CAACsE,QAAQ,IAAI,SAAA,CAAA;AAErD,QAAA,IAAIC,GAAAA,GAAM,OAAA;AACV,QAAA,IAAI,IAAI,CAAC5D,MAAM,CAACc,MAAM,KAAK,UAAA,EAAY;YACnC8C,GAAAA,GAAM,KAAA;AACV,QAAA,CAAA,MAAO,IAAI,IAAI,CAAC5D,MAAM,CAACc,MAAM,KAAK,OAAA,EAAS;YACvC8C,GAAAA,GAAM,QAAA;AACV,QAAA;QAEA,MAAMC,QAAAA,GAAWhB,aAAAA,CAAKiB,IAAI,CAAC,IAAI,CAAC9D,MAAM,CAACuC,UAAU,EAAEkB,QAAAA,GAAWG,GAAAA,CAAAA;;AAG9D,QAAA,MAAMG,YAAGC,KAAK,CAACnB,aAAAA,CAAKoB,OAAO,CAACJ,QAAAA,CAAAA,EAAW;YAAEK,SAAAA,EAAW;AAAK,SAAA,CAAA;;AAGzD,QAAA,IAAI,IAAI,CAAClE,MAAM,CAACc,MAAM,KAAK,OAAA,EAAS;YAChC,IAAI,CAACvB,gBAAgB,GAAGsE,QAAAA;AAC5B,QAAA;QAEA,OAAOA,QAAAA;AACX,IAAA;AAEA;;QAGA,MAAcpB,UAAAA,CAAWF,UAAkB,EAAiB;AACxD,QAAA,MAAM4B,IAAAA,GAA2B;YAC7BxE,EAAAA,EAAI,IAAI,CAACC,cAAc;YACvBP,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBuB,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBmC,OAAAA,EAAS;AACLC,gBAAAA,aAAAA,EAAe,IAAI,CAACpC,QAAQ,CAACwB,MAAM;AACnCa,gBAAAA,iBAAAA,EAAmB,IAAI,CAACnB,SAAS,CAACM,MAAM;gBACxCc,UAAAA,EAAY,CAAA;gBACZrB,OAAAA,EAAS;AACb;AACJ,SAAA;QAEA,MAAMkC,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAY8B,KAAKC,SAAS,CAACH,IAAAA,EAAM,IAAA,EAAM,CAAA,CAAA,EAAI,OAAA,CAAA;AAClE,IAAA;AAEA;;QAGA,MAAczB,cAAAA,CAAeH,UAAkB,EAAiB;QAC5D,IAAIgC,QAAAA,GAAW,CAAC,sBAAsB,CAAC;QACvCA,QAAAA,IAAY,CAAC,QAAQ,EAAE,IAAI,CAAC3E,cAAc,CAAC,EAAE,CAAC;AAC9C2E,QAAAA,QAAAA,IAAY,CAAC,aAAa,EAAE,IAAI,CAAClF,QAAQ,CAACC,SAAS,CAACkB,WAAW,EAAA,CAAG,EAAE,CAAC;AACrE,QAAA,IAAI,IAAI,CAACnB,QAAQ,CAACuC,QAAQ,EAAE;AACxB2C,YAAAA,QAAAA,IAAY,CAAC,cAAc,EAAE,CAAC,IAAI,CAAClF,QAAQ,CAACuC,QAAQ,GAAG,IAAG,EAAG4C,OAAO,CAAC,CAAA,CAAA,CAAG,GAAG,CAAC;AAChF,QAAA;QACAD,QAAAA,IAAY,CAAC,WAAW,EAAE,IAAI,CAAClF,QAAQ,CAACoF,KAAK,CAAC,EAAE,CAAC;AACjD,QAAA,IAAI,IAAI,CAACpF,QAAQ,CAACsE,QAAQ,EAAE;YACxBY,QAAAA,IAAY,CAAC,cAAc,EAAE,IAAI,CAAClF,QAAQ,CAACsE,QAAQ,CAAC,EAAE,CAAC;AAC3D,QAAA;QACAY,QAAAA,IAAY,CAAC,qBAAqB,CAAC;AAEnC,QAAA,KAAK,MAAMG,GAAAA,IAAO,IAAI,CAAC9D,QAAQ,CAAE;AAC7B,YAAA,MAAM+D,OAAO,IAAIpE,IAAAA,CAAKmE,GAAAA,CAAIpE,SAAS,EAAEsE,kBAAkB,EAAA;AACvDL,YAAAA,QAAAA,IAAY,CAAC,YAAY,EAAEG,GAAAA,CAAItE,KAAK,GAAG,CAAA,CAAE,EAAE,EAAEuE,IAAAA,CAAK,IAAI,EAAED,GAAAA,CAAIjE,IAAI,CAAC,IAAI,CAAC;YAEtE,IAAIiE,GAAAA,CAAI3E,OAAO,EAAE;AACbwE,gBAAAA,QAAAA,IAAY,CAAC,QAAQ,EAAEG,IAAI3E,OAAO,CAAC,YAAY,CAAC;AACpD,YAAA;YAEA,IAAI2E,GAAAA,CAAIhE,UAAU,EAAE;gBAChB6D,QAAAA,IAAY,CAAC,iBAAiB,CAAC;AAC/B,gBAAA,KAAK,MAAMM,IAAAA,IAAQH,GAAAA,CAAIhE,UAAU,CAAE;AAC/B6D,oBAAAA,QAAAA,IAAY,CAAC,EAAE,EAAEM,IAAAA,CAAKC,QAAQ,CAACC,IAAI,CAAC,IAAI,EAAEF,KAAKC,QAAQ,CAAC/C,SAAS,CAAC,IAAI,CAAC;AAC3E,gBAAA;gBACAwC,QAAAA,IAAY,CAAC,EAAE,CAAC;AACpB,YAAA;YAEA,IAAIG,GAAAA,CAAIrF,QAAQ,EAAE;gBACdkF,QAAAA,IAAY,CAAC,WAAW,EAAEF,IAAAA,CAAKC,SAAS,CAACI,GAAAA,CAAIrF,QAAQ,CAAA,CAAE,KAAK,CAAC;AACjE,YAAA;AACJ,QAAA;QAEAkF,QAAAA,IAAY,CAAC,cAAc,CAAC;QAC5BA,QAAAA,IAAY,CAAC,sBAAsB,EAAE,IAAI,CAAC3D,QAAQ,CAACwB,MAAM,CAAC,EAAE,CAAC;QAC7DmC,QAAAA,IAAY,CAAC,kBAAkB,EAAE,IAAI,CAACzC,SAAS,CAACM,MAAM,CAAC,EAAE,CAAC;AAE1D,QAAA,MAAM2B,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAYgC,QAAAA,EAAU,OAAA,CAAA;AAC7C,IAAA;AAEA;;QAGA,MAActD,aAAAA,CAAcnB,OAAsB,EAAiB;AAC/D,QAAA,MAAMyC,UAAAA,GAAa,MAAM,IAAI,CAACC,aAAa,EAAA;AAC3C,QAAA,MAAMwC,IAAAA,GAAOX,IAAAA,CAAKC,SAAS,CAACxE,OAAAA,CAAAA,GAAW,IAAA;AACvC,QAAA,MAAMiE,WAAAA,CAAGkB,UAAU,CAAC1C,UAAAA,EAAYyC,IAAAA,EAAM,OAAA,CAAA;AAC1C,IAAA;AAEA;;QAGQ9E,aAAAA,CAAcH,OAAe,EAAU;AAC3C,QAAA,IAAImF,QAAAA,GAAWnF,OAAAA;;AAGf,QAAA,KAAK,MAAMoF,OAAAA,IAAW,IAAI,CAACnF,MAAM,CAACoF,cAAc,CAAE;YAC9CF,QAAAA,GAAWA,QAAAA,CAAS9B,OAAO,CAAC+B,OAAAA,EAAS,YAAA,CAAA;AACzC,QAAA;;AAGA,QAAA,MAAME,eAAAA,GAAkB;AACpB,YAAA,8BAAA;AACA,YAAA,2BAAA;AACA,YAAA,mBAAA;AACA,YAAA;AACH,SAAA;QAED,KAAK,MAAMF,WAAWE,eAAAA,CAAiB;YACnCH,QAAAA,GAAWA,QAAAA,CAAS9B,OAAO,CAAC+B,OAAAA,EAAS,YAAA,CAAA;AACzC,QAAA;QAEA,OAAOD,QAAAA;AACX,IAAA;IAtTA,WAAA,CAAYlF,MAAiB,EAAEP,MAAY,CAAE;AAX7C,QAAA,gBAAA,CAAA,IAAA,EAAQO,UAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQJ,kBAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQP,YAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQuB,YAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQkB,aAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQxC,aAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQG,UAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQY,gBAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQd,oBAAR,MAAA,CAAA;QACA,gBAAA,CAAA,IAAA,EAAQwB,YAAAA,EAA4BuE,QAAQC,OAAO,EAAA,CAAA;QAG/C,IAAI,CAACvF,MAAM,GAAG;YACVuC,UAAAA,EAAY,oBAAA;YACZzB,MAAAA,EAAQ,MAAA;YACR4C,gBAAAA,EAAkB,0BAAA;YAClB8B,eAAAA,EAAiB,IAAA;YACjBC,aAAAA,EAAe,KAAA;YACfxF,eAAAA,EAAiB,KAAA;AACjBmF,YAAAA,cAAAA,EAAgB,EAAE;AAClBzC,YAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;AAChBvB,YAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;AAChB,YAAA,GAAGpB;AACP,SAAA;AAEA,QAAA,IAAI,CAACJ,cAAc,GAAG,IAAI,CAACuD,UAAU,EAAA;QACrC,IAAI,CAACvC,QAAQ,GAAG,EAAE;QAClB,IAAI,CAACkB,SAAS,GAAG,EAAE;QACnB,IAAI,CAACxC,SAAS,GAAG,IAAIiB,IAAAA,EAAAA;QACrB,IAAI,CAACF,YAAY,GAAG,CAAA;AACpB,QAAA,IAAI,CAACZ,MAAM,GAAGiG,UAAAA,CAAWjG,UAAUkG,cAAAA,EAAgB,oBAAA,CAAA;QAEnD,IAAI,CAACtG,QAAQ,GAAG;YACZC,SAAAA,EAAW,IAAI,CAACA,SAAS;YACzBmF,KAAAA,EAAO;AACX,SAAA;AACJ,IAAA;AA8RJ;AAmCA;;;;;;;;;;;;;;;;;;;AAmBC,IACM,MAAMmB,oBAAAA,CAAAA;AAST;;AAEC,QACD,aAAaC,IAAAA,CAAKC,QAAgB,EAAErG,MAAY,EAAiC;QAC7E,MAAMsG,OAAAA,GAAUL,UAAAA,CAAWjG,MAAAA,IAAUkG,cAAAA,EAAgB,sBAAA,CAAA;QACrDI,OAAAA,CAAQrG,KAAK,CAAC,sBAAA,EAAwB;YAAEmD,IAAAA,EAAMiD;AAAS,SAAA,CAAA;QAEvD,IAAI;AACA,YAAA,MAAM/F,OAAAA,GAAU,MAAMgE,WAAAA,CAAGiC,QAAQ,CAACF,QAAAA,EAAU,OAAA,CAAA;;YAG5C,IAAIA,QAAAA,CAASG,QAAQ,CAAC,OAAA,CAAA,EAAU;gBAC5B,MAAM9B,IAAAA,GAA2BE,IAAAA,CAAK6B,KAAK,CAACnG,OAAAA,CAAAA;gBAC5C,OAAO,IAAI6F,qBAAqBzB,IAAAA,EAAM1E,MAAAA,CAAAA;AAC1C,YAAA,CAAA,MAAO,IAAIqG,QAAAA,CAASG,QAAQ,CAAC,QAAA,CAAA,EAAW;AACpC,gBAAA,MAAME,KAAAA,GAAQpG,OAAAA,CAAQqG,IAAI,EAAA,CAAGC,KAAK,CAAC,IAAA,CAAA;gBACnC,MAAMzF,QAAAA,GAAWuF,MAAMG,GAAG,CAACtB,CAAAA,IAAAA,GAAQX,IAAAA,CAAK6B,KAAK,CAAClB,IAAAA,CAAAA,CAAAA;AAE9C,gBAAA,MAAMuB,YAAAA,GAAmC;AACrC5G,oBAAAA,EAAAA,EAAI,CAAC,SAAS,EAAEY,IAAAA,CAAKiG,GAAG,EAAA,CAAA,CAAI;oBAC5BnH,QAAAA,EAAU;AACNC,wBAAAA,SAAAA,EAAW,IAAIiB,IAAAA,EAAAA;wBACfkE,KAAAA,EAAO;AACX,qBAAA;AACA7D,oBAAAA,QAAAA;oBACAmC,OAAAA,EAAS;AACLC,wBAAAA,aAAAA,EAAepC,SAASwB,MAAM;wBAC9Ba,iBAAAA,EAAmB,CAAA;wBACnBC,UAAAA,EAAY,CAAA;wBACZrB,OAAAA,EAAS;AACb;AACJ,iBAAA;gBAEA,OAAO,IAAI+D,qBAAqBW,YAAAA,EAAc9G,MAAAA,CAAAA;YAClD,CAAA,MAAO;AACH,gBAAA,MAAM,IAAIgH,KAAAA,CAAM,CAAC,oBAAoB,EAAEX,QAAAA,CAAAA,CAAU,CAAA;AACrD,YAAA;AACJ,QAAA,CAAA,CAAE,OAAO3E,KAAAA,EAAO;YACZ4E,OAAAA,CAAQ5E,KAAK,CAAC,6BAAA,EAA+B;gBAAE0B,IAAAA,EAAMiD,QAAAA;AAAU3E,gBAAAA;AAAM,aAAA,CAAA;YACrE,MAAMA,KAAAA;AACV,QAAA;AACJ,IAAA;AAEA;;AAEC,QACD,aAAauF,UAAAA,CAAWC,SAAiB,EAAElH,MAAY,EAAiC;AACpF,QAAA,MAAMmH,KAAAA,GAAQ,MAAM7C,WAAAA,CAAG8C,OAAO,CAACF,SAAAA,CAAAA;AAC/B,QAAA,MAAMG,SAAAA,GAAYF,KAAAA,CAAMG,MAAM,CAACC,CAAAA,CAAAA,GAAKA,CAAAA,CAAEf,QAAQ,CAAC,OAAA,CAAA,CAAA,CAAUgB,IAAI,EAAA,CAAGC,OAAO,EAAA;QAEvE,IAAIJ,SAAAA,CAAU1E,MAAM,KAAK,CAAA,EAAG;AACxB,YAAA,MAAM,IAAIqE,KAAAA,CAAM,CAAC,8BAA8B,EAAEE,SAAAA,CAAAA,CAAW,CAAA;AAChE,QAAA;AAEA,QAAA,MAAMQ,aAAatE,aAAAA,CAAKiB,IAAI,CAAC6C,SAAAA,EAAWG,SAAS,CAAC,CAAA,CAAE,CAAA;QACpD,OAAOlB,oBAAAA,CAAqBC,IAAI,CAACsB,UAAAA,EAAY1H,MAAAA,CAAAA;AACjD,IAAA;AAEA;;AAEC,QACD,IAAImB,QAAAA,GAA4B;AAC5B,QAAA,OAAO,IAAI,CAAC2F,YAAY,CAAC3F,QAAQ;AACrC,IAAA;AAEA;;AAEC,QACDwG,WAAAA,GAAuC;QACnC,OAAO;AAAE,YAAA,GAAG,IAAI,CAACb,YAAY,CAAClH;AAAS,SAAA;AAC3C,IAAA;AAEA;;AAEC,QACDgI,YAAAA,GAA8B;AAC1B,QAAA,MAAMvF,YAA2B,EAAE;AAEnC,QAAA,KAAK,MAAM4C,GAAAA,IAAO,IAAI,CAAC6B,YAAY,CAAC3F,QAAQ,CAAE;YAC1C,IAAI8D,GAAAA,CAAIhE,UAAU,EAAE;AAChB,gBAAA,KAAK,MAAMmE,IAAAA,IAAQH,GAAAA,CAAIhE,UAAU,CAAE;;oBAE/B,IAAI4G,UAAAA;oBACJ,IAAI;AACAA,wBAAAA,UAAAA,GAAajD,KAAK6B,KAAK,CAACrB,IAAAA,CAAKC,QAAQ,CAAC/C,SAAS,CAAA;AACnD,oBAAA,CAAA,CAAE,OAAOZ,KAAAA,EAAO;AACZ,wBAAA,IAAI,CAAC1B,MAAM,CAAC8H,IAAI,CAAC,qCAAA,EAAuC;AACpDhG,4BAAAA,MAAAA,EAAQsD,KAAKlF,EAAE;AACfwB,4BAAAA,KAAAA,EAAOA,KAAAA,YAAiBsF,KAAAA,GAAQtF,KAAAA,CAAMrB,OAAO,GAAG0H,MAAAA,CAAOrG,KAAAA;AAC3D,yBAAA,CAAA;wBACAmG,UAAAA,GAAa;4BAAEG,aAAAA,EAAe,IAAA;4BAAMC,GAAAA,EAAK7C,IAAAA,CAAKC,QAAQ,CAAC/C;AAAU,yBAAA;AACrE,oBAAA;AAEAD,oBAAAA,SAAAA,CAAUjB,IAAI,CAAC;AACXU,wBAAAA,MAAAA,EAAQsD,KAAKlF,EAAE;wBACf6B,QAAAA,EAAUqD,IAAAA,CAAKC,QAAQ,CAACC,IAAI;AAC5BzE,wBAAAA,SAAAA,EAAWoE,IAAIpE,SAAS;wBACxBmB,SAAAA,EAAW,CAAA;wBACXM,SAAAA,EAAWuF,UAAAA;wBACX3F,MAAAA,EAAQ,IAAA;wBACRC,QAAAA,EAAU,CAAA;wBACVC,OAAAA,EAAS;AACb,qBAAA,CAAA;AACJ,gBAAA;AACJ,YAAA;AACJ,QAAA;QAEA,OAAOC,SAAAA;AACX,IAAA;AAEA;;QAGA6F,YAAAA,CAAavH,KAAa,EAA6B;AACnD,QAAA,OAAO,IAAI,CAACmG,YAAY,CAAC3F,QAAQ,CAACR,KAAAA,CAAM;AAC5C,IAAA;AAEA;;AAEC,QACDwH,WAAAA,GAA+B;AAC3B,QAAA,MAAMC,SAA0B,EAAE;AAElC,QAAA,KAAK,MAAMnD,GAAAA,IAAO,IAAI,CAAC6B,YAAY,CAAC3F,QAAQ,CAAE;AAC1CiH,YAAAA,MAAAA,CAAOhH,IAAI,CAAC;AACRP,gBAAAA,SAAAA,EAAWoE,IAAIpE,SAAS;gBACxBmB,SAAAA,EAAW,CAAA;gBACXqG,IAAAA,EAAM,SAAA;AACNC,gBAAAA,WAAAA,EAAa,CAAA,EAAGrD,GAAAA,CAAIjE,IAAI,CAAC,QAAQ;AACrC,aAAA,CAAA;AACJ,QAAA;QAEA,OAAOoH,MAAAA;AACX,IAAA;AAEA;;AAEC,QACD,MAAMG,cAAAA,CAAelH,MAAiB,EAAEyB,UAAkB,EAAmB;AACzE,QAAA,IAAI,CAAC9C,MAAM,CAACC,KAAK,CAAC,qBAAA,EAAuB;AAAEoB,YAAAA,MAAAA;YAAQ+B,IAAAA,EAAMN;AAAW,SAAA,CAAA;QAEpE,OAAQzB,MAAAA;YACJ,KAAK,MAAA;AACD,gBAAA,MAAMiD,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAY8B,IAAAA,CAAKC,SAAS,CAAC,IAAI,CAACiC,YAAY,EAAE,IAAA,EAAM,CAAA,CAAA,EAAI,OAAA,CAAA;AAC3E,gBAAA;YACJ,KAAK,UAAA;gBACD,MAAM,IAAI,CAAC0B,cAAc,CAAC1F,UAAAA,CAAAA;AAC1B,gBAAA;YACJ,KAAK,OAAA;AAAS,gBAAA;AACV,oBAAA,MAAM4D,KAAAA,GAAQ,IAAI,CAACvF,QAAQ,CAAC0F,GAAG,CAAC4B,CAAAA,CAAAA,GAAK7D,IAAAA,CAAKC,SAAS,CAAC4D,CAAAA,CAAAA,CAAAA,CAAIpE,IAAI,CAAC,IAAA,CAAA;AAC7D,oBAAA,MAAMC,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAY4D,KAAAA,EAAO,OAAA,CAAA;AACtC,oBAAA;AACJ,gBAAA;AACJ;QAEA,OAAO5D,UAAAA;AACX,IAAA;AAEA;;QAGA,MAAc0F,cAAAA,CAAe1F,UAAkB,EAAiB;QAC5D,IAAIgC,QAAAA,GAAW,CAAC,sBAAsB,CAAC;QACvCA,QAAAA,IAAY,CAAC,QAAQ,EAAE,IAAI,CAACgC,YAAY,CAAC5G,EAAE,CAAC,EAAE,CAAC;QAE/C,MAAML,SAAAA,GAAY,OAAO,IAAI,CAACiH,YAAY,CAAClH,QAAQ,CAACC,SAAS,KAAK,QAAA,GAC5D,IAAI,CAACiH,YAAY,CAAClH,QAAQ,CAACC,SAAS,GACpC,IAAI,CAACiH,YAAY,CAAClH,QAAQ,CAACC,SAAS,CAACkB,WAAW,EAAA;AAEtD+D,QAAAA,QAAAA,IAAY,CAAC,aAAa,EAAEjF,SAAAA,CAAU,IAAI,CAAC;AAE3C,QAAA,KAAK,MAAMoF,GAAAA,IAAO,IAAI,CAAC6B,YAAY,CAAC3F,QAAQ,CAAE;AAC1C2D,YAAAA,QAAAA,IAAY,CAAC,GAAG,EAAEG,GAAAA,CAAIjE,IAAI,CAAC0H,WAAW,EAAA,CAAG,EAAE,EAAEzD,GAAAA,CAAItE,KAAK,CAAC,KAAK,CAAC;YAC7D,IAAIsE,GAAAA,CAAI3E,OAAO,EAAE;AACbwE,gBAAAA,QAAAA,IAAY,CAAA,EAAGG,GAAAA,CAAI3E,OAAO,CAAC,IAAI,CAAC;AACpC,YAAA;AACJ,QAAA;AAEA,QAAA,MAAMgE,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAYgC,QAAAA,EAAU,OAAA,CAAA;AAC7C,IAAA;IAxLA,WAAA,CAAoBgC,YAAgC,EAAE9G,MAAY,CAAE;AAHpE,QAAA,gBAAA,CAAA,IAAA,EAAQ8G,gBAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQ9G,UAAR,MAAA,CAAA;QAGI,IAAI,CAAC8G,YAAY,GAAGA,YAAAA;AACpB,QAAA,IAAI,CAAC9G,MAAM,GAAGiG,UAAAA,CAAWjG,UAAUkG,cAAAA,EAAgB,sBAAA,CAAA;AACvD,IAAA;AAsLJ;;;;"}
1
+ {"version":3,"file":"conversation-logger.js","sources":["../src/conversation-logger.ts"],"sourcesContent":["import fs from 'fs/promises';\nimport path from 'path';\nimport { DEFAULT_LOGGER, wrapLogger } from \"./logger\";\nimport { maskSensitive, type MaskingConfig } from \"./logging-config\";\nimport type { ConversationMessage, ToolCall } from \"./conversation\";\n\n// ===== TYPE DEFINITIONS =====\n\n/**\n * Log format\n */\nexport type LogFormat = 'json' | 'markdown' | 'jsonl';\n\n/**\n * Log configuration\n */\nexport interface LogConfig {\n enabled: boolean;\n outputPath?: string;\n format?: LogFormat;\n filenameTemplate?: string;\n includeMetadata?: boolean;\n includePrompt?: boolean;\n /** Enable sensitive data redaction (defaults to true) */\n redactSensitive?: boolean;\n /** \n * @deprecated Use maskingConfig instead. Custom regex patterns for redaction.\n */\n redactPatterns?: RegExp[];\n /** Masking configuration for @fjell/logging integration */\n maskingConfig?: MaskingConfig;\n onSaved?: (path: string) => void;\n onError?: (error: Error) => void;\n}\n\n/**\n * Logged conversation structure\n */\nexport interface LoggedConversation {\n id: string;\n metadata: ConversationLogMetadata;\n prompt?: PromptSnapshot;\n messages: LoggedMessage[];\n summary: ConversationSummary;\n}\n\n/**\n * Conversation metadata for logging\n */\nexport interface ConversationLogMetadata {\n startTime: Date;\n endTime?: Date;\n duration?: number;\n model: string;\n template?: string;\n userContext?: Record<string, any>;\n}\n\n/**\n * Snapshot of prompt configuration\n */\nexport interface PromptSnapshot {\n persona?: string;\n instructions?: string;\n content?: string[];\n context?: string[];\n}\n\n/**\n * Logged message with metadata\n */\nexport interface LoggedMessage {\n index: number;\n timestamp: string;\n role: string;\n content: string | null;\n tool_calls?: ToolCall[];\n tool_call_id?: string;\n metadata?: MessageLogMetadata;\n}\n\n/**\n * Message metadata for logging\n */\nexport interface MessageLogMetadata {\n tokens?: number;\n source?: string;\n latency?: number;\n tool?: string;\n duration?: number;\n success?: boolean;\n [key: string]: any;\n}\n\n/**\n * Conversation summary\n */\nexport interface ConversationSummary {\n totalMessages: number;\n totalTokens?: number;\n toolCallsExecuted: number;\n iterations: number;\n finalOutput?: string;\n success: boolean;\n}\n\n/**\n * Tool call log entry\n */\nexport interface ToolCallLog {\n callId: string;\n toolName: string;\n timestamp: string;\n iteration: number;\n arguments: any;\n result: any;\n duration: number;\n success: boolean;\n error?: string;\n}\n\n// ===== CONVERSATION LOGGER =====\n\n/**\n * ConversationLogger logs conversations to various formats.\n *\n * Features:\n * - Multiple formats (JSON, Markdown, JSONL)\n * - Automatic timestamping\n * - Metadata tracking\n * - Sensitive data redaction\n * - Streaming support (JSONL)\n *\n * @example\n * ```typescript\n * const logger = new ConversationLogger({\n * enabled: true,\n * outputPath: 'logs/conversations',\n * format: 'json',\n * includeMetadata: true\n * });\n *\n * logger.onConversationStart({ model: 'gpt-4o', startTime: new Date() });\n * logger.onMessageAdded(message);\n * const path = await logger.save();\n * ```\n */\nexport class ConversationLogger {\n private config: Required<LogConfig>;\n private conversationId: string;\n private metadata: ConversationLogMetadata;\n private messages: LoggedMessage[];\n private toolCalls: ToolCallLog[];\n private startTime: Date;\n private logger: any;\n private messageIndex: number;\n private cachedOutputPath?: string;\n private writeQueue: Promise<void> = Promise.resolve();\n\n constructor(config: LogConfig, logger?: any) {\n this.config = {\n outputPath: 'logs/conversations',\n format: 'json',\n filenameTemplate: 'conversation-{timestamp}',\n includeMetadata: true,\n includePrompt: false,\n redactSensitive: true, // Now defaults to true for security\n redactPatterns: [],\n maskingConfig: undefined,\n onSaved: () => {},\n onError: () => {},\n ...config,\n } as Required<LogConfig>;\n\n this.conversationId = this.generateId();\n this.messages = [];\n this.toolCalls = [];\n this.startTime = new Date();\n this.messageIndex = 0;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationLogger');\n\n this.metadata = {\n startTime: this.startTime,\n model: 'unknown',\n };\n }\n\n /**\n * Start conversation logging\n */\n onConversationStart(metadata: Partial<ConversationLogMetadata>): void {\n this.metadata = {\n ...this.metadata,\n ...metadata,\n startTime: this.startTime,\n };\n\n // Reset cached output path to prevent file collision if logger is reused\n this.cachedOutputPath = undefined;\n\n this.logger.debug('Conversation logging started', { id: this.conversationId });\n }\n\n /**\n * Log a message\n */\n onMessageAdded(message: ConversationMessage, metadata?: MessageLogMetadata): void {\n let content = message.content;\n\n // Redact sensitive data if enabled\n if (this.config.redactSensitive && content && typeof content === 'string') {\n content = this.redactContent(content);\n }\n\n const loggedMessage: LoggedMessage = {\n index: this.messageIndex++,\n timestamp: new Date().toISOString(),\n role: message.role,\n content,\n tool_calls: message.tool_calls,\n tool_call_id: message.tool_call_id,\n metadata,\n };\n\n this.messages.push(loggedMessage);\n\n // For JSONL format, append immediately with write queue\n if (this.config.format === 'jsonl') {\n this.writeQueue = this.writeQueue\n .then(() => this.appendToJSONL(loggedMessage))\n .catch((error) => {\n this.logger.error('Failed to write JSONL message', { error });\n try {\n this.config.onError?.(error);\n } catch (callbackError) {\n this.logger.error('onError callback failed', { callbackError });\n }\n });\n }\n }\n\n /**\n * Log a tool call\n */\n onToolCall(\n callId: string,\n toolName: string,\n iteration: number,\n args: any,\n result: any,\n duration: number,\n success: boolean,\n error?: string\n ): void {\n this.toolCalls.push({\n callId,\n toolName,\n timestamp: new Date().toISOString(),\n iteration,\n arguments: args,\n result,\n duration,\n success,\n error,\n });\n }\n\n /**\n * End conversation logging\n */\n onConversationEnd(_summary: ConversationSummary): void {\n this.metadata.endTime = new Date();\n this.metadata.duration = this.metadata.endTime.getTime() - this.startTime.getTime();\n\n this.logger.debug('Conversation logging ended', {\n messages: this.messages.length,\n duration: this.metadata.duration\n });\n }\n\n /**\n * Save conversation to disk\n */\n async save(): Promise<string> {\n if (!this.config.enabled) {\n return '';\n }\n\n try {\n const outputPath = await this.getOutputPath();\n\n switch (this.config.format) {\n case 'json':\n await this.saveAsJSON(outputPath);\n break;\n case 'markdown':\n await this.saveAsMarkdown(outputPath);\n break;\n case 'jsonl':\n // Already saved during execution\n break;\n }\n\n this.config.onSaved(outputPath);\n this.logger.info('Conversation saved', { path: outputPath });\n\n return outputPath;\n } catch (error) {\n this.config.onError(error as Error);\n this.logger.error('Failed to save conversation', { error });\n throw error;\n }\n }\n\n /**\n * Get logged conversation object\n */\n getConversation(): LoggedConversation {\n return {\n id: this.conversationId,\n metadata: this.metadata,\n messages: this.messages,\n summary: {\n totalMessages: this.messages.length,\n toolCallsExecuted: this.toolCalls.length,\n iterations: 0, // Would need to be tracked externally\n success: true,\n },\n };\n }\n\n /**\n * Generate unique conversation ID\n */\n private generateId(): string {\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const random = Math.random().toString(36).substring(2, 8);\n return `conv-${timestamp}-${random}`;\n }\n\n /**\n * Get output file path (cached for JSONL to avoid recalculation)\n */\n private async getOutputPath(): Promise<string> {\n if (this.cachedOutputPath) {\n return this.cachedOutputPath;\n }\n\n const timestamp = new Date().toISOString().replace(/[:.]/g, '-');\n const filename = this.config.filenameTemplate\n .replace('{timestamp}', timestamp)\n .replace('{id}', this.conversationId)\n .replace('{template}', this.metadata.template || 'default');\n\n let ext = '.json';\n if (this.config.format === 'markdown') {\n ext = '.md';\n } else if (this.config.format === 'jsonl') {\n ext = '.jsonl';\n }\n \n const fullPath = path.join(this.config.outputPath, filename + ext);\n\n // Ensure directory exists\n await fs.mkdir(path.dirname(fullPath), { recursive: true });\n\n // Cache path for JSONL format to ensure consistent file writes\n if (this.config.format === 'jsonl') {\n this.cachedOutputPath = fullPath;\n }\n\n return fullPath;\n }\n\n /**\n * Save as JSON\n */\n private async saveAsJSON(outputPath: string): Promise<void> {\n const data: LoggedConversation = {\n id: this.conversationId,\n metadata: this.metadata,\n messages: this.messages,\n summary: {\n totalMessages: this.messages.length,\n toolCallsExecuted: this.toolCalls.length,\n iterations: 0,\n success: true,\n },\n };\n\n await fs.writeFile(outputPath, JSON.stringify(data, null, 2), 'utf-8');\n }\n\n /**\n * Save as Markdown\n */\n private async saveAsMarkdown(outputPath: string): Promise<void> {\n let markdown = `# Conversation Log\\n\\n`;\n markdown += `**ID**: ${this.conversationId}\\n`;\n markdown += `**Started**: ${this.metadata.startTime.toISOString()}\\n`;\n if (this.metadata.duration) {\n markdown += `**Duration**: ${(this.metadata.duration / 1000).toFixed(1)}s\\n`;\n }\n markdown += `**Model**: ${this.metadata.model}\\n`;\n if (this.metadata.template) {\n markdown += `**Template**: ${this.metadata.template}\\n`;\n }\n markdown += `\\n## Conversation\\n\\n`;\n\n for (const msg of this.messages) {\n const time = new Date(msg.timestamp).toLocaleTimeString();\n markdown += `### Message ${msg.index + 1} (${time}) - ${msg.role}\\n\\n`;\n\n if (msg.content) {\n markdown += `\\`\\`\\`\\n${msg.content}\\n\\`\\`\\`\\n\\n`;\n }\n\n if (msg.tool_calls) {\n markdown += `**Tool Calls:**\\n`;\n for (const call of msg.tool_calls) {\n markdown += `- ${call.function.name}: \\`${call.function.arguments}\\`\\n`;\n }\n markdown += `\\n`;\n }\n\n if (msg.metadata) {\n markdown += `*Metadata: ${JSON.stringify(msg.metadata)}*\\n\\n`;\n }\n }\n\n markdown += `## Summary\\n\\n`;\n markdown += `- **Total Messages**: ${this.messages.length}\\n`;\n markdown += `- **Tool Calls**: ${this.toolCalls.length}\\n`;\n\n await fs.writeFile(outputPath, markdown, 'utf-8');\n }\n\n /**\n * Append to JSONL file (streaming)\n */\n private async appendToJSONL(message: LoggedMessage): Promise<void> {\n const outputPath = await this.getOutputPath();\n const line = JSON.stringify(message) + '\\n';\n await fs.appendFile(outputPath, line, 'utf-8');\n }\n\n /**\n * Redact sensitive content using @fjell/logging masking\n * \n * Automatically masks:\n * - API keys (OpenAI, Anthropic, AWS, GitHub, etc.)\n * - Passwords and secrets\n * - Email addresses\n * - SSNs\n * - Private keys\n * - JWTs\n * - Large base64 blobs\n */\n private redactContent(content: string): string {\n // Use Fjell's comprehensive masking\n let redacted = maskSensitive(content, this.config.maskingConfig);\n\n // Also apply any legacy custom patterns for backwards compatibility\n if (this.config.redactPatterns && this.config.redactPatterns.length > 0) {\n for (const pattern of this.config.redactPatterns) {\n redacted = redacted.replace(pattern, '[REDACTED]');\n }\n }\n\n return redacted;\n }\n}\n\n// ===== CONVERSATION REPLAYER =====\n\n/**\n * Replay options\n */\nexport interface ReplayOptions {\n model?: string;\n maxIterations?: number;\n retryFailedTools?: boolean;\n toolTimeout?: number;\n expectSimilarOutput?: boolean;\n}\n\n/**\n * Replay result\n */\nexport interface ReplayResult {\n success: boolean;\n conversation: LoggedConversation;\n errors?: Error[];\n}\n\n/**\n * Comparison result\n */\nexport interface ComparisonResult {\n messageDiff: number;\n toolCallDiff: number;\n tokenDiff?: number;\n outputSimilarity: number;\n costSavings?: number;\n}\n\n/**\n * ConversationReplayer loads and replays logged conversations.\n *\n * Features:\n * - Load from various formats\n * - Replay conversations\n * - Compare replays with originals\n * - Export to different formats\n *\n * @example\n * ```typescript\n * const replayer = await ConversationReplayer.load('logs/conv.json');\n *\n * console.log('Messages:', replayer.messages.length);\n * console.log('Tool calls:', replayer.getToolCalls().length);\n *\n * const timeline = replayer.getTimeline();\n * console.log('Events:', timeline.length);\n * ```\n */\nexport class ConversationReplayer {\n private conversation: LoggedConversation;\n private logger: any;\n\n private constructor(conversation: LoggedConversation, logger?: any) {\n this.conversation = conversation;\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');\n }\n\n /**\n * Load conversation from file\n */\n static async load(filePath: string, logger?: any): Promise<ConversationReplayer> {\n const wlogger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');\n wlogger.debug('Loading conversation', { path: filePath });\n\n try {\n const content = await fs.readFile(filePath, 'utf-8');\n\n // Determine format by extension\n if (filePath.endsWith('.json')) {\n const data: LoggedConversation = JSON.parse(content);\n return new ConversationReplayer(data, logger);\n } else if (filePath.endsWith('.jsonl')) {\n const lines = content.trim().split('\\n');\n const messages = lines.map(line => JSON.parse(line));\n\n const conversation: LoggedConversation = {\n id: `replayer-${Date.now()}`,\n metadata: {\n startTime: new Date(),\n model: 'unknown'\n },\n messages,\n summary: {\n totalMessages: messages.length,\n toolCallsExecuted: 0,\n iterations: 0,\n success: true\n }\n };\n\n return new ConversationReplayer(conversation, logger);\n } else {\n throw new Error(`Unsupported format: ${filePath}`);\n }\n } catch (error) {\n wlogger.error('Failed to load conversation', { path: filePath, error });\n throw error;\n }\n }\n\n /**\n * Load latest conversation from directory\n */\n static async loadLatest(directory: string, logger?: any): Promise<ConversationReplayer> {\n const files = await fs.readdir(directory);\n const jsonFiles = files.filter(f => f.endsWith('.json')).sort().reverse();\n\n if (jsonFiles.length === 0) {\n throw new Error(`No conversation logs found in ${directory}`);\n }\n\n const latestPath = path.join(directory, jsonFiles[0]);\n return ConversationReplayer.load(latestPath, logger);\n }\n\n /**\n * Get all messages\n */\n get messages(): LoggedMessage[] {\n return this.conversation.messages;\n }\n\n /**\n * Get conversation metadata\n */\n getMetadata(): ConversationLogMetadata {\n return { ...this.conversation.metadata };\n }\n\n /**\n * Get tool calls\n */\n getToolCalls(): ToolCallLog[] {\n const toolCalls: ToolCallLog[] = [];\n\n for (const msg of this.conversation.messages) {\n if (msg.tool_calls) {\n for (const call of msg.tool_calls) {\n // Parse arguments with error handling\n let parsedArgs: any;\n try {\n parsedArgs = JSON.parse(call.function.arguments);\n } catch (error) {\n this.logger.warn('Failed to parse tool call arguments', {\n callId: call.id,\n error: error instanceof Error ? error.message : String(error)\n });\n parsedArgs = { __parse_error: true, raw: call.function.arguments };\n }\n\n toolCalls.push({\n callId: call.id,\n toolName: call.function.name,\n timestamp: msg.timestamp,\n iteration: 0, // Would need to be calculated\n arguments: parsedArgs,\n result: null, // Would need to find corresponding tool message\n duration: 0,\n success: true,\n });\n }\n }\n }\n\n return toolCalls;\n }\n\n /**\n * Get message at index\n */\n getMessageAt(index: number): LoggedMessage | undefined {\n return this.conversation.messages[index];\n }\n\n /**\n * Get timeline of events\n */\n getTimeline(): TimelineEvent[] {\n const events: TimelineEvent[] = [];\n\n for (const msg of this.conversation.messages) {\n events.push({\n timestamp: msg.timestamp,\n iteration: 0, // Would need iteration tracking\n type: 'message',\n description: `${msg.role} message`,\n });\n }\n\n return events;\n }\n\n /**\n * Export to format\n */\n async exportToFormat(format: LogFormat, outputPath: string): Promise<string> {\n this.logger.debug('Exporting to format', { format, path: outputPath });\n\n switch (format) {\n case 'json':\n await fs.writeFile(outputPath, JSON.stringify(this.conversation, null, 2), 'utf-8');\n break;\n case 'markdown':\n await this.exportMarkdown(outputPath);\n break;\n case 'jsonl': {\n const lines = this.messages.map(m => JSON.stringify(m)).join('\\n');\n await fs.writeFile(outputPath, lines, 'utf-8');\n break;\n }\n }\n\n return outputPath;\n }\n\n /**\n * Export as markdown\n */\n private async exportMarkdown(outputPath: string): Promise<void> {\n let markdown = `# Conversation Log\\n\\n`;\n markdown += `**ID**: ${this.conversation.id}\\n`;\n\n const startTime = typeof this.conversation.metadata.startTime === 'string'\n ? this.conversation.metadata.startTime\n : this.conversation.metadata.startTime.toISOString();\n\n markdown += `**Started**: ${startTime}\\n\\n`;\n\n for (const msg of this.conversation.messages) {\n markdown += `## ${msg.role.toUpperCase()} (${msg.index})\\n\\n`;\n if (msg.content) {\n markdown += `${msg.content}\\n\\n`;\n }\n }\n\n await fs.writeFile(outputPath, markdown, 'utf-8');\n }\n}\n\n/**\n * Timeline event interface\n */\ninterface TimelineEvent {\n timestamp: string;\n iteration: number;\n type: string;\n description: string;\n duration?: number;\n success?: boolean;\n}\n\nexport default ConversationLogger;\n\n"],"names":["ConversationLogger","onConversationStart","metadata","startTime","cachedOutputPath","undefined","logger","debug","id","conversationId","onMessageAdded","message","content","config","redactSensitive","redactContent","loggedMessage","index","messageIndex","timestamp","Date","toISOString","role","tool_calls","tool_call_id","messages","push","format","writeQueue","then","appendToJSONL","catch","error","onError","callbackError","onToolCall","callId","toolName","iteration","args","result","duration","success","toolCalls","arguments","onConversationEnd","_summary","endTime","getTime","length","save","enabled","outputPath","getOutputPath","saveAsJSON","saveAsMarkdown","onSaved","info","path","getConversation","summary","totalMessages","toolCallsExecuted","iterations","generateId","replace","random","Math","toString","substring","filename","filenameTemplate","template","ext","fullPath","join","fs","mkdir","dirname","recursive","data","writeFile","JSON","stringify","markdown","toFixed","model","msg","time","toLocaleTimeString","call","function","name","line","appendFile","redacted","maskSensitive","maskingConfig","redactPatterns","pattern","Promise","resolve","includeMetadata","includePrompt","wrapLogger","DEFAULT_LOGGER","ConversationReplayer","load","filePath","wlogger","readFile","endsWith","parse","lines","trim","split","map","conversation","now","Error","loadLatest","directory","files","readdir","jsonFiles","filter","f","sort","reverse","latestPath","getMetadata","getToolCalls","parsedArgs","warn","String","__parse_error","raw","getMessageAt","getTimeline","events","type","description","exportToFormat","exportMarkdown","m","toUpperCase"],"mappings":"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"}
@@ -645,5 +645,5 @@ const ConversationBuilderConfigSchema = z.object({
645
645
  }
646
646
  }
647
647
 
648
- export { ConversationBuilder, ConversationBuilder as default };
648
+ export { ConversationBuilder };
649
649
  //# sourceMappingURL=conversation.js.map
@@ -0,0 +1,52 @@
1
+ import { configureErrorSanitizer, configurePathSanitizer, configureSecretGuard, ErrorSanitizerConfig, SanitizedErrorResult, Logger as SpotcleanLogger, ErrorHandlingOptions } from '@theunwalked/spotclean';
2
+ export { configureErrorSanitizer, configurePathSanitizer, configureSecretGuard, type ErrorSanitizerConfig, type SanitizedErrorResult, type ErrorHandlingOptions, };
3
+ /**
4
+ * Initialize error handling with secure defaults.
5
+ * Call this at application startup.
6
+ */
7
+ export declare function initializeErrorHandling(options?: {
8
+ basePaths?: string[];
9
+ environment?: 'production' | 'development' | 'test';
10
+ }): void;
11
+ /**
12
+ * Sanitize an error for safe external exposure.
13
+ *
14
+ * @param error - The error to sanitize
15
+ * @param context - Optional context for debugging
16
+ * @returns Sanitized error result with external and internal details
17
+ */
18
+ export declare function sanitize(error: unknown, context?: Record<string, unknown>): SanitizedErrorResult;
19
+ /**
20
+ * Create a safe error that can be thrown externally.
21
+ *
22
+ * @param error - The error to make safe
23
+ * @param context - Optional context for debugging
24
+ * @returns New Error with sanitized message
25
+ */
26
+ export declare function createSafeError(error: unknown, context?: Record<string, unknown>): Error & {
27
+ correlationId?: string;
28
+ };
29
+ /**
30
+ * Wrap an async function with automatic error handling.
31
+ *
32
+ * @param fn - The async function to wrap
33
+ * @param options - Error handling options
34
+ * @returns Wrapped function that sanitizes errors
35
+ */
36
+ export declare function withErrorHandling<T extends (...args: any[]) => Promise<any>>(fn: T, options?: ErrorHandlingOptions): T;
37
+ /**
38
+ * Handle an error by logging internally and throwing a sanitized version.
39
+ *
40
+ * @param error - The error that occurred
41
+ * @param context - Optional context for debugging
42
+ * @param logger - Optional logger for internal logging
43
+ */
44
+ export declare function handleError(error: unknown, context?: Record<string, unknown>, logger?: SpotcleanLogger): never;
45
+ /**
46
+ * Format an error for display to users.
47
+ * Returns a user-friendly message with optional correlation ID.
48
+ *
49
+ * @param error - The error to format
50
+ * @returns User-friendly error string
51
+ */
52
+ export declare function formatErrorForDisplay(error: unknown): string;
@@ -0,0 +1,132 @@
1
+ import { createSafeError as createSafeError$1, configureErrorSanitizer, configurePathSanitizer, configureSecretGuard, sanitize as sanitize$1, withErrorHandling as withErrorHandling$1 } from '@theunwalked/spotclean';
2
+ export { configureErrorSanitizer, configurePathSanitizer, configureSecretGuard } from '@theunwalked/spotclean';
3
+
4
+ /**
5
+ * Initialize error handling with secure defaults.
6
+ * Call this at application startup.
7
+ */ function initializeErrorHandling(options = {}) {
8
+ const isProduction = options.environment === 'production' || process.env.NODE_ENV === 'production';
9
+ // Configure the error sanitizer
10
+ configureErrorSanitizer({
11
+ enabled: true,
12
+ environment: isProduction ? 'production' : 'development',
13
+ includeCorrelationId: true,
14
+ sanitizeStackTraces: isProduction,
15
+ maxMessageLength: 500
16
+ });
17
+ // Configure path sanitization
18
+ configurePathSanitizer({
19
+ enabled: true,
20
+ basePaths: options.basePaths || [
21
+ process.cwd()
22
+ ],
23
+ redactSystemPaths: isProduction
24
+ });
25
+ // Configure secret guard with kjerneverk-specific patterns
26
+ configureSecretGuard({
27
+ enabled: true,
28
+ redactionText: '[REDACTED]',
29
+ preservePartial: false,
30
+ preserveLength: 0,
31
+ customPatterns: [
32
+ // OpenAI API keys
33
+ {
34
+ name: 'openai',
35
+ pattern: /sk-[a-zA-Z0-9]{20,}/g,
36
+ description: 'OpenAI API key'
37
+ },
38
+ {
39
+ name: 'openai-proj',
40
+ pattern: /sk-proj-[a-zA-Z0-9_-]+/g,
41
+ description: 'OpenAI project key'
42
+ },
43
+ // Anthropic API keys
44
+ {
45
+ name: 'anthropic',
46
+ pattern: /sk-ant-[a-zA-Z0-9_-]+/g,
47
+ description: 'Anthropic API key'
48
+ },
49
+ // Gemini API keys
50
+ {
51
+ name: 'gemini',
52
+ pattern: /AIza[a-zA-Z0-9_-]{35}/g,
53
+ description: 'Google Gemini API key'
54
+ }
55
+ ]
56
+ });
57
+ }
58
+ /**
59
+ * Sanitize an error for safe external exposure.
60
+ *
61
+ * @param error - The error to sanitize
62
+ * @param context - Optional context for debugging
63
+ * @returns Sanitized error result with external and internal details
64
+ */ function sanitize(error, context) {
65
+ const err = error instanceof Error ? error : new Error(String(error));
66
+ return sanitize$1(err, context);
67
+ }
68
+ /**
69
+ * Create a safe error that can be thrown externally.
70
+ *
71
+ * @param error - The error to make safe
72
+ * @param context - Optional context for debugging
73
+ * @returns New Error with sanitized message
74
+ */ function createSafeError(error, context) {
75
+ const err = error instanceof Error ? error : new Error(String(error));
76
+ return createSafeError$1(err, context);
77
+ }
78
+ /**
79
+ * Wrap an async function with automatic error handling.
80
+ *
81
+ * @param fn - The async function to wrap
82
+ * @param options - Error handling options
83
+ * @returns Wrapped function that sanitizes errors
84
+ */ function withErrorHandling(fn, options) {
85
+ return withErrorHandling$1(fn, options);
86
+ }
87
+ /**
88
+ * Handle an error by logging internally and throwing a sanitized version.
89
+ *
90
+ * @param error - The error that occurred
91
+ * @param context - Optional context for debugging
92
+ * @param logger - Optional logger for internal logging
93
+ */ function handleError(error, context, logger) {
94
+ const { external, internal } = sanitize(error, context);
95
+ // Log internal details
96
+ if (logger) {
97
+ logger.error('Error occurred', {
98
+ correlationId: internal.correlationId,
99
+ message: internal.originalMessage,
100
+ context: internal.context,
101
+ timestamp: internal.timestamp
102
+ });
103
+ } else if (process.env.NODE_ENV !== 'production') {
104
+ // Fallback to console in development
105
+ // eslint-disable-next-line no-console
106
+ console.error('Error occurred', {
107
+ correlationId: internal.correlationId,
108
+ message: internal.originalMessage,
109
+ context: internal.context
110
+ });
111
+ }
112
+ // Throw sanitized error
113
+ const safeError = new Error(external.message);
114
+ safeError.correlationId = external.correlationId;
115
+ throw safeError;
116
+ }
117
+ /**
118
+ * Format an error for display to users.
119
+ * Returns a user-friendly message with optional correlation ID.
120
+ *
121
+ * @param error - The error to format
122
+ * @returns User-friendly error string
123
+ */ function formatErrorForDisplay(error) {
124
+ const { external } = sanitize(error);
125
+ if (external.correlationId) {
126
+ return `${external.message}\nReference: ${external.correlationId}`;
127
+ }
128
+ return external.message;
129
+ }
130
+
131
+ export { createSafeError, formatErrorForDisplay, handleError, initializeErrorHandling, sanitize, withErrorHandling };
132
+ //# sourceMappingURL=error-handling.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-handling.js","sources":["../src/error-handling.ts"],"sourcesContent":["/**\n * Error Handling Utilities\n * \n * Provides centralized error sanitization using @theunwalked/spotclean\n * to prevent information disclosure in error messages.\n * \n * @packageDocumentation\n */\n\nimport {\n sanitize as spotcleanSanitize,\n createSafeError as spotcleanCreateSafeError,\n configureErrorSanitizer,\n configurePathSanitizer,\n configureSecretGuard,\n withErrorHandling as spotcleanWithErrorHandling,\n type ErrorSanitizerConfig,\n type SanitizedErrorResult,\n type Logger as SpotcleanLogger,\n type ErrorHandlingOptions,\n} from '@theunwalked/spotclean';\n\n// Re-export spotclean types and functions for convenience\nexport {\n configureErrorSanitizer,\n configurePathSanitizer,\n configureSecretGuard,\n type ErrorSanitizerConfig,\n type SanitizedErrorResult,\n type ErrorHandlingOptions,\n};\n\n/**\n * Initialize error handling with secure defaults.\n * Call this at application startup.\n */\nexport function initializeErrorHandling(options: {\n basePaths?: string[];\n environment?: 'production' | 'development' | 'test';\n} = {}): void {\n const isProduction = options.environment === 'production' || \n process.env.NODE_ENV === 'production';\n\n // Configure the error sanitizer\n configureErrorSanitizer({\n enabled: true,\n environment: isProduction ? 'production' : 'development',\n includeCorrelationId: true,\n sanitizeStackTraces: isProduction,\n maxMessageLength: 500,\n });\n\n // Configure path sanitization\n configurePathSanitizer({\n enabled: true,\n basePaths: options.basePaths || [process.cwd()],\n redactSystemPaths: isProduction,\n });\n\n // Configure secret guard with kjerneverk-specific patterns\n configureSecretGuard({\n enabled: true,\n redactionText: '[REDACTED]',\n preservePartial: false,\n preserveLength: 0,\n customPatterns: [\n // OpenAI API keys\n { name: 'openai', pattern: /sk-[a-zA-Z0-9]{20,}/g, description: 'OpenAI API key' },\n { name: 'openai-proj', pattern: /sk-proj-[a-zA-Z0-9_-]+/g, description: 'OpenAI project key' },\n // Anthropic API keys\n { name: 'anthropic', pattern: /sk-ant-[a-zA-Z0-9_-]+/g, description: 'Anthropic API key' },\n // Gemini API keys\n { name: 'gemini', pattern: /AIza[a-zA-Z0-9_-]{35}/g, description: 'Google Gemini API key' },\n ],\n });\n}\n\n/**\n * Sanitize an error for safe external exposure.\n * \n * @param error - The error to sanitize\n * @param context - Optional context for debugging\n * @returns Sanitized error result with external and internal details\n */\nexport function sanitize(error: unknown, context?: Record<string, unknown>): SanitizedErrorResult {\n const err = error instanceof Error ? error : new Error(String(error));\n return spotcleanSanitize(err, context);\n}\n\n/**\n * Create a safe error that can be thrown externally.\n * \n * @param error - The error to make safe\n * @param context - Optional context for debugging\n * @returns New Error with sanitized message\n */\nexport function createSafeError(error: unknown, context?: Record<string, unknown>): Error & { correlationId?: string } {\n const err = error instanceof Error ? error : new Error(String(error));\n return spotcleanCreateSafeError(err, context);\n}\n\n/**\n * Wrap an async function with automatic error handling.\n * \n * @param fn - The async function to wrap\n * @param options - Error handling options\n * @returns Wrapped function that sanitizes errors\n */\nexport function withErrorHandling<T extends (...args: any[]) => Promise<any>>(\n fn: T,\n options?: ErrorHandlingOptions\n): T {\n return spotcleanWithErrorHandling(fn, options);\n}\n\n/**\n * Handle an error by logging internally and throwing a sanitized version.\n * \n * @param error - The error that occurred\n * @param context - Optional context for debugging\n * @param logger - Optional logger for internal logging\n */\nexport function handleError(\n error: unknown,\n context?: Record<string, unknown>,\n logger?: SpotcleanLogger\n): never {\n const { external, internal } = sanitize(error, context);\n\n // Log internal details\n if (logger) {\n logger.error('Error occurred', {\n correlationId: internal.correlationId,\n message: internal.originalMessage,\n context: internal.context,\n timestamp: internal.timestamp,\n });\n } else if (process.env.NODE_ENV !== 'production') {\n // Fallback to console in development\n // eslint-disable-next-line no-console\n console.error('Error occurred', {\n correlationId: internal.correlationId,\n message: internal.originalMessage,\n context: internal.context,\n });\n }\n\n // Throw sanitized error\n const safeError = new Error(external.message) as Error & { correlationId?: string };\n safeError.correlationId = external.correlationId;\n throw safeError;\n}\n\n/**\n * Format an error for display to users.\n * Returns a user-friendly message with optional correlation ID.\n * \n * @param error - The error to format\n * @returns User-friendly error string\n */\nexport function formatErrorForDisplay(error: unknown): string {\n const { external } = sanitize(error);\n \n if (external.correlationId) {\n return `${external.message}\\nReference: ${external.correlationId}`;\n }\n \n return external.message;\n}\n\n"],"names":["initializeErrorHandling","options","isProduction","environment","process","env","NODE_ENV","configureErrorSanitizer","enabled","includeCorrelationId","sanitizeStackTraces","maxMessageLength","configurePathSanitizer","basePaths","cwd","redactSystemPaths","configureSecretGuard","redactionText","preservePartial","preserveLength","customPatterns","name","pattern","description","sanitize","error","context","err","Error","String","spotcleanSanitize","createSafeError","spotcleanCreateSafeError","withErrorHandling","fn","spotcleanWithErrorHandling","handleError","logger","external","internal","correlationId","message","originalMessage","timestamp","console","safeError","formatErrorForDisplay"],"mappings":"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"}
package/dist/formatter.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { z } from 'zod';
2
- import { createRequest, getPersonaRole } from './chat.js';
2
+ import { getPersonaRole, createRequest } from './chat.js';
3
3
  import { DEFAULT_FORMAT_OPTIONS } from './constants.js';
4
4
  import { DEFAULT_LOGGER, wrapLogger } from './logger.js';
5
5
  import { clean, stringifyJSON } from './util/general.js';
@@ -516,5 +516,5 @@ function _define_property(obj, key, value) {
516
516
  }
517
517
  }
518
518
 
519
- export { IterationStrategyFactory, StrategyExecutor, IterationStrategyFactory as default };
519
+ export { IterationStrategyFactory, StrategyExecutor };
520
520
  //# sourceMappingURL=iteration-strategy.js.map
package/dist/loader.js CHANGED
@@ -1,5 +1,6 @@
1
1
  import path__default from 'path';
2
2
  import { z } from 'zod';
3
+ import { SafeRegex } from '@theunwalked/pressurelid';
3
4
  import { DEFAULT_IGNORE_PATTERNS } from './constants.js';
4
5
  import { ParametersSchema } from './items/parameters.js';
5
6
  import { create as create$2, SectionOptionsSchema } from './items/section.js';
@@ -12,10 +13,16 @@ import './builder.js';
12
13
  import './recipes.js';
13
14
  import './conversation.js';
14
15
  import 'tiktoken';
16
+ import './logging-config.js';
15
17
  import './tools.js';
16
18
  import 'openai';
17
19
  import '@anthropic-ai/sdk';
18
20
  import '@google/generative-ai';
21
+ import './security/types.js';
22
+ import './security/defaults.js';
23
+ import { getAuditLogger } from './security/audit-logger.js';
24
+ import './security/serialization-schemas.js';
25
+ import { createSafeError } from './error-handling.js';
19
26
  import { create as create$1 } from './util/storage.js';
20
27
 
21
28
  const OptionsSchema = z.object({
@@ -23,6 +30,52 @@ const OptionsSchema = z.object({
23
30
  ignorePatterns: z.array(z.string()).optional().default(DEFAULT_IGNORE_PATTERNS),
24
31
  parameters: ParametersSchema.optional().default({})
25
32
  });
33
+ /**
34
+ * Create safe regex patterns from ignore patterns using pressurelid
35
+ * to prevent ReDoS attacks from malicious patterns.
36
+ *
37
+ * @param patterns - Array of ignore patterns (can be regex or glob-like)
38
+ * @param logger - Logger instance for warnings
39
+ * @returns Array of safe RegExp objects
40
+ */ function createSafeIgnorePatterns(patterns, logger) {
41
+ const auditLogger = getAuditLogger();
42
+ // Create SafeRegex instance with security callbacks
43
+ const safeRegex = new SafeRegex({
44
+ maxLength: 500,
45
+ timeoutMs: 1000,
46
+ onBlock: (message, pattern)=>{
47
+ logger.warn(`Blocked unsafe ignore pattern: ${message}`, {
48
+ patternLength: pattern.length
49
+ });
50
+ auditLogger.log({
51
+ type: 'regex_blocked',
52
+ severity: 'warning',
53
+ message: `Blocked unsafe regex pattern: ${message}`,
54
+ context: {
55
+ patternLength: pattern.length
56
+ }
57
+ });
58
+ },
59
+ onWarning: (message, _pattern)=>{
60
+ logger.debug(`Regex warning: ${message}`);
61
+ }
62
+ });
63
+ return patterns.map((pattern)=>{
64
+ // Try to create a safe regex from the pattern
65
+ const result = safeRegex.create(pattern, 'i');
66
+ if (result.safe && result.regex) {
67
+ return result.regex;
68
+ }
69
+ // If direct regex fails, try as glob pattern
70
+ const globResult = safeRegex.globToRegex(pattern);
71
+ if (globResult.safe && globResult.regex) {
72
+ return globResult.regex;
73
+ }
74
+ // Log the failure and return a pattern that matches nothing
75
+ logger.warn(`Invalid or unsafe ignore pattern "${pattern}": ${result.error || globResult.error}`);
76
+ return null;
77
+ }).filter((regex)=>regex !== null);
78
+ }
26
79
  /**
27
80
  * Extracts the first header from Markdown text
28
81
  * @param markdownText The Markdown text to parse
@@ -118,17 +171,7 @@ const create = (loaderOptions)=>{
118
171
  }
119
172
  // Get all other files in the directory
120
173
  const files = await storage.listFiles(contextDir);
121
- const ignorePatternsRegex = ignorePatterns.map((pattern)=>{
122
- try {
123
- return new RegExp(pattern, 'i');
124
- } catch (error) {
125
- logger.error(`Invalid ignore pattern: ${pattern}`, {
126
- error
127
- });
128
- // Return a pattern that matches nothing
129
- return /(?!)/; // Negative lookahead that always fails
130
- }
131
- });
174
+ const ignorePatternsRegex = createSafeIgnorePatterns(ignorePatterns, logger);
132
175
  const filteredFiles = files.filter((file)=>{
133
176
  const fullPath = path__default.join(contextDir, file);
134
177
  // Test against both filename and full path for flexibility
@@ -169,7 +212,12 @@ const create = (loaderOptions)=>{
169
212
  }
170
213
  contextSections.push(mainContextSection);
171
214
  } catch (error) {
172
- logger.error(`Error processing context directory ${contextDir}: ${error}`);
215
+ // Create a safe error that doesn't leak path information
216
+ const safeError = createSafeError(error, {
217
+ operation: 'load',
218
+ directory: path__default.basename(contextDir)
219
+ });
220
+ logger.error(`Error processing context directory: ${safeError.message}`);
173
221
  }
174
222
  }
175
223
  return contextSections;
@@ -1 +1 @@
1
- {"version":3,"file":"loader.js","sources":["../src/loader.ts"],"sourcesContent":["import path from \"path\";\nimport { z } from \"zod\";\nimport { DEFAULT_IGNORE_PATTERNS } from \"./constants\";\nimport { ParametersSchema } from \"./items/parameters\";\nimport { SectionOptions, SectionOptionsSchema } from \"./items/section\";\nimport { DEFAULT_LOGGER, wrapLogger } from \"./logger\";\nimport { Section, Weighted, createSection } from \"./riotprompt\";\nimport * as Storage from \"./util/storage\";\n\nconst OptionsSchema = z.object({\n logger: z.any().optional().default(DEFAULT_LOGGER),\n ignorePatterns: z.array(z.string()).optional().default(DEFAULT_IGNORE_PATTERNS),\n parameters: ParametersSchema.optional().default({}),\n});\n\nexport type Options = z.infer<typeof OptionsSchema>;\n\nexport type OptionsParam = Partial<Options>;\n\nexport interface Instance {\n load: <T extends Weighted>(contextDirectories?: string[], options?: SectionOptions) => Promise<Section<T>[]>;\n}\n\n/**\n * Extracts the first header from Markdown text\n * @param markdownText The Markdown text to parse\n * @returns The first header found in the Markdown or null if none is found\n */\nexport function extractFirstHeader(markdownText: string): string | null {\n // Regular expression to match Markdown headers (# Header, ## Header, etc.)\n const headerRegex = /^(#{1,6})\\s+(.+?)(?:\\n|$)/m;\n const match = markdownText.match(headerRegex);\n\n if (match && match[2]) {\n return match[2].trim();\n }\n\n return null;\n}\n\n/**\n * Removes the first header from Markdown text\n * @param markdownText The Markdown text to process\n * @returns The Markdown text without the first header\n */\nexport function removeFirstHeader(markdownText: string): string {\n // Regular expression to match Markdown headers (# Header, ## Header, etc.)\n const headerRegex = /^(#{1,6})\\s+(.+?)(?:\\n|$)/m;\n const match = markdownText.match(headerRegex);\n\n if (match) {\n return markdownText.replace(headerRegex, '').trim();\n }\n\n return markdownText;\n}\n\nexport const create = (loaderOptions?: OptionsParam): Instance => {\n const options: Required<Options> = OptionsSchema.parse(loaderOptions || {}) as Required<Options>;\n const parameters = options.parameters;\n\n const logger = wrapLogger(options.logger, 'Loader');\n const ignorePatterns = options.ignorePatterns;\n\n const loadOptions = (sectionOptions: Partial<SectionOptions> = {}): SectionOptions => {\n const currentOptions = SectionOptionsSchema.parse(sectionOptions);\n return {\n ...currentOptions,\n parameters: {\n ...parameters,\n ...currentOptions.parameters\n }\n }\n }\n\n /**\n * Loads context from the provided directories and returns instruction sections\n *\n * @param contextDirectories Directories containing context files\n * @returns Array of instruction sections loaded from context directories\n */\n const load = async<T extends Weighted>(\n contextDirectories: string[] = [],\n options: Partial<SectionOptions> = {}\n ): Promise<Section<T>[]> => {\n const sectionOptions = loadOptions(options);\n\n logger.debug(`Loading context from ${contextDirectories}`);\n const contextSections: Section<T>[] = [];\n\n if (!contextDirectories || contextDirectories.length === 0) {\n logger.debug(`No context directories provided, returning empty context`);\n return contextSections;\n }\n\n const storage = Storage.create({ log: logger.debug });\n\n // Add context sections from each directory\n for (const contextDir of contextDirectories) {\n try {\n const dirName = path.basename(contextDir);\n logger.debug(`Processing context directory ${dirName}`);\n let mainContextSection: Section<T>;\n\n // First check if there's a context.md file\n const contextFile = path.join(contextDir, 'context.md');\n\n if (await storage.exists(contextFile)) {\n logger.debug(`Found context.md file in ${contextDir}`);\n const mainContextContent = await storage.readFile(contextFile, 'utf8');\n // Extract the first header from the Markdown content\n const firstHeader = extractFirstHeader(mainContextContent);\n\n // Use the header from context.md as the section title, or fallback to directory name\n const sectionTitle = firstHeader || dirName;\n mainContextSection = createSection<T>({ ...sectionOptions, title: sectionTitle });\n\n // Add content without the header\n if (firstHeader) {\n mainContextSection.add(removeFirstHeader(mainContextContent), { ...sectionOptions });\n } else {\n mainContextSection.add(mainContextContent, { ...sectionOptions });\n }\n } else {\n // If no context.md exists, use directory name as title\n mainContextSection = createSection<T>({ ...sectionOptions, title: dirName });\n }\n\n // Get all other files in the directory\n const files = await storage.listFiles(contextDir);\n const ignorePatternsRegex = ignorePatterns.map(pattern => {\n try {\n return new RegExp(pattern, 'i');\n } catch (error) {\n logger.error(`Invalid ignore pattern: ${pattern}`, { error });\n // Return a pattern that matches nothing\n return /(?!)/; // Negative lookahead that always fails\n }\n });\n\n const filteredFiles = files.filter(file => {\n const fullPath = path.join(contextDir, file);\n // Test against both filename and full path for flexibility\n return !ignorePatternsRegex.some(regex => regex.test(file) || regex.test(fullPath));\n });\n\n for (const file of filteredFiles) {\n // Skip the context.md file as it's already processed\n if (file === 'context.md') continue;\n\n logger.debug(`Processing file ${file} in ${contextDir}`);\n const filePath = path.join(contextDir, file);\n if (await storage.isFile(filePath)) {\n const fileContent = await storage.readFile(filePath, 'utf8');\n let sectionName = file;\n let contentToAdd = fileContent;\n\n // Extract header if it exists\n if (file.endsWith('.md')) {\n const fileHeader = extractFirstHeader(fileContent);\n if (fileHeader) {\n sectionName = fileHeader;\n // Remove the header from the content\n contentToAdd = removeFirstHeader(fileContent);\n }\n }\n\n // Create a subsection with the extracted name\n const fileSection = createSection<T>({ ...sectionOptions, title: sectionName });\n fileSection.add(contentToAdd, { ...sectionOptions });\n\n // Add this file section to the main context section\n // Type is correct - Section.add() accepts Section<T>\n mainContextSection.add(fileSection, { ...sectionOptions });\n }\n }\n\n contextSections.push(mainContextSection);\n } catch (error) {\n logger.error(`Error processing context directory ${contextDir}: ${error}`);\n }\n }\n\n return contextSections;\n }\n\n\n return {\n load\n }\n}\n"],"names":["OptionsSchema","z","object","logger","any","optional","default","DEFAULT_LOGGER","ignorePatterns","array","string","DEFAULT_IGNORE_PATTERNS","parameters","ParametersSchema","extractFirstHeader","markdownText","headerRegex","match","trim","removeFirstHeader","replace","create","loaderOptions","options","parse","wrapLogger","loadOptions","sectionOptions","currentOptions","SectionOptionsSchema","load","contextDirectories","debug","contextSections","length","storage","Storage","log","contextDir","dirName","path","basename","mainContextSection","contextFile","join","exists","mainContextContent","readFile","firstHeader","sectionTitle","createSection","title","add","files","listFiles","ignorePatternsRegex","map","pattern","RegExp","error","filteredFiles","filter","file","fullPath","some","regex","test","filePath","isFile","fileContent","sectionName","contentToAdd","endsWith","fileHeader","fileSection","push"],"mappings":"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"}
1
+ {"version":3,"file":"loader.js","sources":["../src/loader.ts"],"sourcesContent":["import path from \"path\";\nimport { z } from \"zod\";\nimport { SafeRegex } from \"@theunwalked/pressurelid\";\nimport { DEFAULT_IGNORE_PATTERNS } from \"./constants\";\nimport { ParametersSchema } from \"./items/parameters\";\nimport { SectionOptions, SectionOptionsSchema } from \"./items/section\";\nimport { DEFAULT_LOGGER, wrapLogger, type Logger } from \"./logger\";\nimport { Section, Weighted, createSection } from \"./riotprompt\";\nimport * as Storage from \"./util/storage\";\nimport { getAuditLogger } from \"./security/audit-logger\";\nimport { createSafeError } from \"./error-handling\";\n\nconst OptionsSchema = z.object({\n logger: z.any().optional().default(DEFAULT_LOGGER),\n ignorePatterns: z.array(z.string()).optional().default(DEFAULT_IGNORE_PATTERNS),\n parameters: ParametersSchema.optional().default({}),\n});\n\nexport type Options = z.infer<typeof OptionsSchema>;\n\nexport type OptionsParam = Partial<Options>;\n\n/**\n * Create safe regex patterns from ignore patterns using pressurelid\n * to prevent ReDoS attacks from malicious patterns.\n *\n * @param patterns - Array of ignore patterns (can be regex or glob-like)\n * @param logger - Logger instance for warnings\n * @returns Array of safe RegExp objects\n */\nfunction createSafeIgnorePatterns(patterns: string[], logger: Logger): RegExp[] {\n const auditLogger = getAuditLogger();\n\n // Create SafeRegex instance with security callbacks\n const safeRegex = new SafeRegex({\n maxLength: 500,\n timeoutMs: 1000,\n onBlock: (message, pattern) => {\n logger.warn(`Blocked unsafe ignore pattern: ${message}`, { patternLength: pattern.length });\n auditLogger.log({\n type: 'regex_blocked',\n severity: 'warning',\n message: `Blocked unsafe regex pattern: ${message}`,\n context: { patternLength: pattern.length },\n });\n },\n onWarning: (message, _pattern) => {\n logger.debug(`Regex warning: ${message}`);\n },\n });\n\n return patterns\n .map(pattern => {\n // Try to create a safe regex from the pattern\n const result = safeRegex.create(pattern, 'i');\n\n if (result.safe && result.regex) {\n return result.regex;\n }\n\n // If direct regex fails, try as glob pattern\n const globResult = safeRegex.globToRegex(pattern);\n if (globResult.safe && globResult.regex) {\n return globResult.regex;\n }\n\n // Log the failure and return a pattern that matches nothing\n logger.warn(`Invalid or unsafe ignore pattern \"${pattern}\": ${result.error || globResult.error}`);\n return null;\n })\n .filter((regex): regex is RegExp => regex !== null);\n}\n\nexport interface Instance {\n load: <T extends Weighted>(contextDirectories?: string[], options?: SectionOptions) => Promise<Section<T>[]>;\n}\n\n/**\n * Extracts the first header from Markdown text\n * @param markdownText The Markdown text to parse\n * @returns The first header found in the Markdown or null if none is found\n */\nexport function extractFirstHeader(markdownText: string): string | null {\n // Regular expression to match Markdown headers (# Header, ## Header, etc.)\n const headerRegex = /^(#{1,6})\\s+(.+?)(?:\\n|$)/m;\n const match = markdownText.match(headerRegex);\n\n if (match && match[2]) {\n return match[2].trim();\n }\n\n return null;\n}\n\n/**\n * Removes the first header from Markdown text\n * @param markdownText The Markdown text to process\n * @returns The Markdown text without the first header\n */\nexport function removeFirstHeader(markdownText: string): string {\n // Regular expression to match Markdown headers (# Header, ## Header, etc.)\n const headerRegex = /^(#{1,6})\\s+(.+?)(?:\\n|$)/m;\n const match = markdownText.match(headerRegex);\n\n if (match) {\n return markdownText.replace(headerRegex, '').trim();\n }\n\n return markdownText;\n}\n\nexport const create = (loaderOptions?: OptionsParam): Instance => {\n const options: Required<Options> = OptionsSchema.parse(loaderOptions || {}) as Required<Options>;\n const parameters = options.parameters;\n\n const logger = wrapLogger(options.logger, 'Loader');\n const ignorePatterns = options.ignorePatterns;\n\n const loadOptions = (sectionOptions: Partial<SectionOptions> = {}): SectionOptions => {\n const currentOptions = SectionOptionsSchema.parse(sectionOptions);\n return {\n ...currentOptions,\n parameters: {\n ...parameters,\n ...currentOptions.parameters\n }\n }\n }\n\n /**\n * Loads context from the provided directories and returns instruction sections\n *\n * @param contextDirectories Directories containing context files\n * @returns Array of instruction sections loaded from context directories\n */\n const load = async<T extends Weighted>(\n contextDirectories: string[] = [],\n options: Partial<SectionOptions> = {}\n ): Promise<Section<T>[]> => {\n const sectionOptions = loadOptions(options);\n\n logger.debug(`Loading context from ${contextDirectories}`);\n const contextSections: Section<T>[] = [];\n\n if (!contextDirectories || contextDirectories.length === 0) {\n logger.debug(`No context directories provided, returning empty context`);\n return contextSections;\n }\n\n const storage = Storage.create({ log: logger.debug });\n\n // Add context sections from each directory\n for (const contextDir of contextDirectories) {\n try {\n const dirName = path.basename(contextDir);\n logger.debug(`Processing context directory ${dirName}`);\n let mainContextSection: Section<T>;\n\n // First check if there's a context.md file\n const contextFile = path.join(contextDir, 'context.md');\n\n if (await storage.exists(contextFile)) {\n logger.debug(`Found context.md file in ${contextDir}`);\n const mainContextContent = await storage.readFile(contextFile, 'utf8');\n // Extract the first header from the Markdown content\n const firstHeader = extractFirstHeader(mainContextContent);\n\n // Use the header from context.md as the section title, or fallback to directory name\n const sectionTitle = firstHeader || dirName;\n mainContextSection = createSection<T>({ ...sectionOptions, title: sectionTitle });\n\n // Add content without the header\n if (firstHeader) {\n mainContextSection.add(removeFirstHeader(mainContextContent), { ...sectionOptions });\n } else {\n mainContextSection.add(mainContextContent, { ...sectionOptions });\n }\n } else {\n // If no context.md exists, use directory name as title\n mainContextSection = createSection<T>({ ...sectionOptions, title: dirName });\n }\n\n // Get all other files in the directory\n const files = await storage.listFiles(contextDir);\n const ignorePatternsRegex = createSafeIgnorePatterns(ignorePatterns, logger);\n\n const filteredFiles = files.filter(file => {\n const fullPath = path.join(contextDir, file);\n // Test against both filename and full path for flexibility\n return !ignorePatternsRegex.some(regex => regex.test(file) || regex.test(fullPath));\n });\n\n for (const file of filteredFiles) {\n // Skip the context.md file as it's already processed\n if (file === 'context.md') continue;\n\n logger.debug(`Processing file ${file} in ${contextDir}`);\n const filePath = path.join(contextDir, file);\n if (await storage.isFile(filePath)) {\n const fileContent = await storage.readFile(filePath, 'utf8');\n let sectionName = file;\n let contentToAdd = fileContent;\n\n // Extract header if it exists\n if (file.endsWith('.md')) {\n const fileHeader = extractFirstHeader(fileContent);\n if (fileHeader) {\n sectionName = fileHeader;\n // Remove the header from the content\n contentToAdd = removeFirstHeader(fileContent);\n }\n }\n\n // Create a subsection with the extracted name\n const fileSection = createSection<T>({ ...sectionOptions, title: sectionName });\n fileSection.add(contentToAdd, { ...sectionOptions });\n\n // Add this file section to the main context section\n // Type is correct - Section.add() accepts Section<T>\n mainContextSection.add(fileSection, { ...sectionOptions });\n }\n }\n\n contextSections.push(mainContextSection);\n } catch (error) {\n // Create a safe error that doesn't leak path information\n const safeError = createSafeError(error, { operation: 'load', directory: path.basename(contextDir) });\n logger.error(`Error processing context directory: ${safeError.message}`);\n }\n }\n\n return contextSections;\n }\n\n\n return {\n load\n }\n}\n"],"names":["OptionsSchema","z","object","logger","any","optional","default","DEFAULT_LOGGER","ignorePatterns","array","string","DEFAULT_IGNORE_PATTERNS","parameters","ParametersSchema","createSafeIgnorePatterns","patterns","auditLogger","getAuditLogger","safeRegex","SafeRegex","maxLength","timeoutMs","onBlock","message","pattern","warn","patternLength","length","log","type","severity","context","onWarning","_pattern","debug","map","result","create","safe","regex","globResult","globToRegex","error","filter","extractFirstHeader","markdownText","headerRegex","match","trim","removeFirstHeader","replace","loaderOptions","options","parse","wrapLogger","loadOptions","sectionOptions","currentOptions","SectionOptionsSchema","load","contextDirectories","contextSections","storage","Storage","contextDir","dirName","path","basename","mainContextSection","contextFile","join","exists","mainContextContent","readFile","firstHeader","sectionTitle","createSection","title","add","files","listFiles","ignorePatternsRegex","filteredFiles","file","fullPath","some","test","filePath","isFile","fileContent","sectionName","contentToAdd","endsWith","fileHeader","fileSection","push","safeError","createSafeError","operation","directory"],"mappings":"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"}