@riotprompt/riotprompt 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUG-ANALYSIS.md +523 -0
- package/CODE-REVIEW-SUMMARY.md +330 -0
- package/FIXES-APPLIED.md +437 -0
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +2 -5
- package/dist/chat.js.map +1 -1
- package/dist/constants.js +1 -2
- package/dist/constants.js.map +1 -1
- package/dist/context-manager.d.ts +3 -2
- package/dist/context-manager.js +29 -6
- package/dist/context-manager.js.map +1 -1
- package/dist/conversation-logger.d.ts +3 -1
- package/dist/conversation-logger.js +41 -4
- package/dist/conversation-logger.js.map +1 -1
- package/dist/conversation.d.ts +8 -2
- package/dist/conversation.js +36 -9
- package/dist/conversation.js.map +1 -1
- package/dist/items/section.js +3 -3
- package/dist/items/section.js.map +1 -1
- package/dist/iteration-strategy.d.ts +2 -0
- package/dist/iteration-strategy.js +40 -6
- package/dist/iteration-strategy.js.map +1 -1
- package/dist/loader.js +18 -3
- package/dist/loader.js.map +1 -1
- package/dist/message-builder.js +4 -2
- package/dist/message-builder.js.map +1 -1
- package/dist/model-config.d.ts +115 -0
- package/dist/model-config.js +205 -0
- package/dist/model-config.js.map +1 -0
- package/dist/override.js +5 -1
- package/dist/override.js.map +1 -1
- package/dist/parser.js +3 -3
- package/dist/parser.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.js +4 -4
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.js +5 -2
- package/dist/reflection.js.map +1 -1
- package/dist/riotprompt.cjs +439 -94
- package/dist/riotprompt.cjs.map +1 -1
- package/dist/riotprompt.d.ts +2 -0
- package/dist/riotprompt.js +1 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/token-budget.d.ts +2 -2
- package/dist/token-budget.js +23 -26
- package/dist/token-budget.js.map +1 -1
- package/dist/util/general.js +1 -1
- package/dist/util/general.js.map +1 -1
- package/package.json +1 -1
|
@@ -48,6 +48,8 @@ function _define_property(obj, key, value) {
|
|
|
48
48
|
...metadata,
|
|
49
49
|
startTime: this.startTime
|
|
50
50
|
};
|
|
51
|
+
// Reset cached output path to prevent file collision if logger is reused
|
|
52
|
+
this.cachedOutputPath = undefined;
|
|
51
53
|
this.logger.debug('Conversation logging started', {
|
|
52
54
|
id: this.conversationId
|
|
53
55
|
});
|
|
@@ -70,9 +72,21 @@ function _define_property(obj, key, value) {
|
|
|
70
72
|
metadata
|
|
71
73
|
};
|
|
72
74
|
this.messages.push(loggedMessage);
|
|
73
|
-
// For JSONL format, append immediately
|
|
75
|
+
// For JSONL format, append immediately with write queue
|
|
74
76
|
if (this.config.format === 'jsonl') {
|
|
75
|
-
this.appendToJSONL(loggedMessage).catch(
|
|
77
|
+
this.writeQueue = this.writeQueue.then(()=>this.appendToJSONL(loggedMessage)).catch((error)=>{
|
|
78
|
+
this.logger.error('Failed to write JSONL message', {
|
|
79
|
+
error
|
|
80
|
+
});
|
|
81
|
+
try {
|
|
82
|
+
var _this_config_onError, _this_config;
|
|
83
|
+
(_this_config_onError = (_this_config = this.config).onError) === null || _this_config_onError === void 0 ? void 0 : _this_config_onError.call(_this_config, error);
|
|
84
|
+
} catch (callbackError) {
|
|
85
|
+
this.logger.error('onError callback failed', {
|
|
86
|
+
callbackError
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
});
|
|
76
90
|
}
|
|
77
91
|
}
|
|
78
92
|
/**
|
|
@@ -154,8 +168,11 @@ function _define_property(obj, key, value) {
|
|
|
154
168
|
return `conv-${timestamp}-${random}`;
|
|
155
169
|
}
|
|
156
170
|
/**
|
|
157
|
-
* Get output file path
|
|
171
|
+
* Get output file path (cached for JSONL to avoid recalculation)
|
|
158
172
|
*/ async getOutputPath() {
|
|
173
|
+
if (this.cachedOutputPath) {
|
|
174
|
+
return this.cachedOutputPath;
|
|
175
|
+
}
|
|
159
176
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
160
177
|
const filename = this.config.filenameTemplate.replace('{timestamp}', timestamp).replace('{id}', this.conversationId).replace('{template}', this.metadata.template || 'default');
|
|
161
178
|
const ext = this.config.format === 'markdown' ? '.md' : '.json';
|
|
@@ -164,6 +181,10 @@ function _define_property(obj, key, value) {
|
|
|
164
181
|
await fs__default.mkdir(path__default.dirname(fullPath), {
|
|
165
182
|
recursive: true
|
|
166
183
|
});
|
|
184
|
+
// Cache path for JSONL format to ensure consistent file writes
|
|
185
|
+
if (this.config.format === 'jsonl') {
|
|
186
|
+
this.cachedOutputPath = fullPath;
|
|
187
|
+
}
|
|
167
188
|
return fullPath;
|
|
168
189
|
}
|
|
169
190
|
/**
|
|
@@ -254,6 +275,8 @@ function _define_property(obj, key, value) {
|
|
|
254
275
|
_define_property(this, "startTime", void 0);
|
|
255
276
|
_define_property(this, "logger", void 0);
|
|
256
277
|
_define_property(this, "messageIndex", void 0);
|
|
278
|
+
_define_property(this, "cachedOutputPath", void 0);
|
|
279
|
+
_define_property(this, "writeQueue", Promise.resolve());
|
|
257
280
|
this.config = {
|
|
258
281
|
outputPath: 'logs/conversations',
|
|
259
282
|
format: 'json',
|
|
@@ -370,12 +393,26 @@ function _define_property(obj, key, value) {
|
|
|
370
393
|
for (const msg of this.conversation.messages){
|
|
371
394
|
if (msg.tool_calls) {
|
|
372
395
|
for (const call of msg.tool_calls){
|
|
396
|
+
// Parse arguments with error handling
|
|
397
|
+
let parsedArgs;
|
|
398
|
+
try {
|
|
399
|
+
parsedArgs = JSON.parse(call.function.arguments);
|
|
400
|
+
} catch (error) {
|
|
401
|
+
this.logger.warn('Failed to parse tool call arguments', {
|
|
402
|
+
callId: call.id,
|
|
403
|
+
error: error instanceof Error ? error.message : String(error)
|
|
404
|
+
});
|
|
405
|
+
parsedArgs = {
|
|
406
|
+
__parse_error: true,
|
|
407
|
+
raw: call.function.arguments
|
|
408
|
+
};
|
|
409
|
+
}
|
|
373
410
|
toolCalls.push({
|
|
374
411
|
callId: call.id,
|
|
375
412
|
toolName: call.function.name,
|
|
376
413
|
timestamp: msg.timestamp,
|
|
377
414
|
iteration: 0,
|
|
378
|
-
arguments:
|
|
415
|
+
arguments: parsedArgs,
|
|
379
416
|
result: null,
|
|
380
417
|
duration: 0,
|
|
381
418
|
success: true
|
|
@@ -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\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 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\n if (this.config.format === 'jsonl') {\n this.appendToJSONL(loggedMessage).catch(this.config.onError);\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\n */\n private async getOutputPath(): Promise<string> {\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 const ext = this.config.format === 'markdown' ? '.md' : '.json';\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 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 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: JSON.parse(call.function.arguments),\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","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","appendToJSONL","catch","onError","onToolCall","callId","toolName","iteration","args","result","duration","success","error","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","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","getMessageAt","getTimeline","events","type","description","exportToFormat","exportMarkdown","m","toUpperCase"],"mappings":";;;;;;;;;;;;;;;;;AAkHA;AAEA;;;;;;;;;;;;;;;;;;;;;;;AAuBC,IACM,MAAMA,kBAAAA,CAAAA;AAqCT;;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;AAEA,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,EAAEP,QAA6B,EAAQ;QAC9E,IAAIQ,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;AAClCpB,YAAAA;AACJ,SAAA;AAEA,QAAA,IAAI,CAACqB,QAAQ,CAACC,IAAI,CAACV,aAAAA,CAAAA;;AAGnB,QAAA,IAAI,IAAI,CAACH,MAAM,CAACc,MAAM,KAAK,OAAA,EAAS;YAChC,IAAI,CAACC,aAAa,CAACZ,aAAAA,CAAAA,CAAea,KAAK,CAAC,IAAI,CAAChB,MAAM,CAACiB,OAAO,CAAA;AAC/D,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDC,WACIC,MAAc,EACdC,QAAgB,EAChBC,SAAiB,EACjBC,IAAS,EACTC,MAAW,EACXC,QAAgB,EAChBC,OAAgB,EAChBC,KAAc,EACV;AACJ,QAAA,IAAI,CAACC,SAAS,CAACd,IAAI,CAAC;AAChBM,YAAAA,MAAAA;AACAC,YAAAA,QAAAA;YACAd,SAAAA,EAAW,IAAIC,OAAOC,WAAW,EAAA;AACjCa,YAAAA,SAAAA;YACAO,SAAAA,EAAWN,IAAAA;AACXC,YAAAA,MAAAA;AACAC,YAAAA,QAAAA;AACAC,YAAAA,OAAAA;AACAC,YAAAA;AACJ,SAAA,CAAA;AACJ,IAAA;AAEA;;QAGAG,iBAAAA,CAAkBC,QAA6B,EAAQ;AACnD,QAAA,IAAI,CAACvC,QAAQ,CAACwC,OAAO,GAAG,IAAIxB,IAAAA,EAAAA;AAC5B,QAAA,IAAI,CAAChB,QAAQ,CAACiC,QAAQ,GAAG,IAAI,CAACjC,QAAQ,CAACwC,OAAO,CAACC,OAAO,EAAA,GAAK,IAAI,CAACxC,SAAS,CAACwC,OAAO,EAAA;AAEjF,QAAA,IAAI,CAACvC,MAAM,CAACC,KAAK,CAAC,4BAAA,EAA8B;AAC5CkB,YAAAA,QAAAA,EAAU,IAAI,CAACA,QAAQ,CAACqB,MAAM;AAC9BT,YAAAA,QAAAA,EAAU,IAAI,CAACjC,QAAQ,CAACiC;AAC5B,SAAA,CAAA;AACJ,IAAA;AAEA;;AAEC,QACD,MAAMU,IAAAA,GAAwB;AAC1B,QAAA,IAAI,CAAC,IAAI,CAAClC,MAAM,CAACmC,OAAO,EAAE;YACtB,OAAO,EAAA;AACX,QAAA;QAEA,IAAI;AACA,YAAA,MAAMC,UAAAA,GAAa,MAAM,IAAI,CAACC,aAAa,EAAA;AAE3C,YAAA,OAAQ,IAAI,CAACrC,MAAM,CAACc,MAAM;gBACtB,KAAK,MAAA;oBACD,MAAM,IAAI,CAACwB,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,CAACpC,MAAM,CAACwC,OAAO,CAACJ,UAAAA,CAAAA;AACpB,YAAA,IAAI,CAAC3C,MAAM,CAACgD,IAAI,CAAC,oBAAA,EAAsB;gBAAEC,IAAAA,EAAMN;AAAW,aAAA,CAAA;YAE1D,OAAOA,UAAAA;AACX,QAAA,CAAA,CAAE,OAAOV,KAAAA,EAAO;AACZ,YAAA,IAAI,CAAC1B,MAAM,CAACiB,OAAO,CAACS,KAAAA,CAAAA;AACpB,YAAA,IAAI,CAACjC,MAAM,CAACiC,KAAK,CAAC,6BAAA,EAA+B;AAAEA,gBAAAA;AAAM,aAAA,CAAA;YACzD,MAAMA,KAAAA;AACV,QAAA;AACJ,IAAA;AAEA;;AAEC,QACDiB,eAAAA,GAAsC;QAClC,OAAO;YACHhD,EAAAA,EAAI,IAAI,CAACC,cAAc;YACvBL,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBqB,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBgC,OAAAA,EAAS;AACLC,gBAAAA,aAAAA,EAAe,IAAI,CAACjC,QAAQ,CAACqB,MAAM;AACnCa,gBAAAA,iBAAAA,EAAmB,IAAI,CAACnB,SAAS,CAACM,MAAM;gBACxCc,UAAAA,EAAY,CAAA;gBACZtB,OAAAA,EAAS;AACb;AACJ,SAAA;AACJ,IAAA;AAEA;;AAEC,QACD,UAAQuB,GAAqB;AACzB,QAAA,MAAM1C,YAAY,IAAIC,IAAAA,EAAAA,CAAOC,WAAW,EAAA,CAAGyC,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,EAAE/C,SAAAA,CAAU,CAAC,EAAE4C,MAAAA,CAAAA,CAAQ;AACxC,IAAA;AAEA;;AAEC,QACD,MAAcb,aAAAA,GAAiC;AAC3C,QAAA,MAAM/B,YAAY,IAAIC,IAAAA,EAAAA,CAAOC,WAAW,EAAA,CAAGyC,OAAO,CAAC,OAAA,EAAS,GAAA,CAAA;QAC5D,MAAMK,QAAAA,GAAW,IAAI,CAACtD,MAAM,CAACuD,gBAAgB,CACxCN,OAAO,CAAC,aAAA,EAAe3C,SAAAA,CAAAA,CACvB2C,OAAO,CAAC,QAAQ,IAAI,CAACrD,cAAc,CAAA,CACnCqD,OAAO,CAAC,YAAA,EAAc,IAAI,CAAC1D,QAAQ,CAACiE,QAAQ,IAAI,SAAA,CAAA;QAErD,MAAMC,GAAAA,GAAM,IAAI,CAACzD,MAAM,CAACc,MAAM,KAAK,aAAa,KAAA,GAAQ,OAAA;QACxD,MAAM4C,QAAAA,GAAWhB,aAAAA,CAAKiB,IAAI,CAAC,IAAI,CAAC3D,MAAM,CAACoC,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;QAEzD,OAAOL,QAAAA;AACX,IAAA;AAEA;;QAGA,MAAcpB,UAAAA,CAAWF,UAAkB,EAAiB;AACxD,QAAA,MAAM4B,IAAAA,GAA2B;YAC7BrE,EAAAA,EAAI,IAAI,CAACC,cAAc;YACvBL,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBqB,QAAAA,EAAU,IAAI,CAACA,QAAQ;YACvBgC,OAAAA,EAAS;AACLC,gBAAAA,aAAAA,EAAe,IAAI,CAACjC,QAAQ,CAACqB,MAAM;AACnCa,gBAAAA,iBAAAA,EAAmB,IAAI,CAACnB,SAAS,CAACM,MAAM;gBACxCc,UAAAA,EAAY,CAAA;gBACZtB,OAAAA,EAAS;AACb;AACJ,SAAA;QAEA,MAAMmC,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,CAACxE,cAAc,CAAC,EAAE,CAAC;AAC9CwE,QAAAA,QAAAA,IAAY,CAAC,aAAa,EAAE,IAAI,CAAC7E,QAAQ,CAACC,SAAS,CAACgB,WAAW,EAAA,CAAG,EAAE,CAAC;AACrE,QAAA,IAAI,IAAI,CAACjB,QAAQ,CAACiC,QAAQ,EAAE;AACxB4C,YAAAA,QAAAA,IAAY,CAAC,cAAc,EAAE,CAAC,IAAI,CAAC7E,QAAQ,CAACiC,QAAQ,GAAG,IAAG,EAAG6C,OAAO,CAAC,CAAA,CAAA,CAAG,GAAG,CAAC;AAChF,QAAA;QACAD,QAAAA,IAAY,CAAC,WAAW,EAAE,IAAI,CAAC7E,QAAQ,CAAC+E,KAAK,CAAC,EAAE,CAAC;AACjD,QAAA,IAAI,IAAI,CAAC/E,QAAQ,CAACiE,QAAQ,EAAE;YACxBY,QAAAA,IAAY,CAAC,cAAc,EAAE,IAAI,CAAC7E,QAAQ,CAACiE,QAAQ,CAAC,EAAE,CAAC;AAC3D,QAAA;QACAY,QAAAA,IAAY,CAAC,qBAAqB,CAAC;AAEnC,QAAA,KAAK,MAAMG,GAAAA,IAAO,IAAI,CAAC3D,QAAQ,CAAE;AAC7B,YAAA,MAAM4D,OAAO,IAAIjE,IAAAA,CAAKgE,GAAAA,CAAIjE,SAAS,EAAEmE,kBAAkB,EAAA;AACvDL,YAAAA,QAAAA,IAAY,CAAC,YAAY,EAAEG,GAAAA,CAAInE,KAAK,GAAG,CAAA,CAAE,EAAE,EAAEoE,IAAAA,CAAK,IAAI,EAAED,GAAAA,CAAI9D,IAAI,CAAC,IAAI,CAAC;YAEtE,IAAI8D,GAAAA,CAAIxE,OAAO,EAAE;AACbqE,gBAAAA,QAAAA,IAAY,CAAC,QAAQ,EAAEG,IAAIxE,OAAO,CAAC,YAAY,CAAC;AACpD,YAAA;YAEA,IAAIwE,GAAAA,CAAI7D,UAAU,EAAE;gBAChB0D,QAAAA,IAAY,CAAC,iBAAiB,CAAC;AAC/B,gBAAA,KAAK,MAAMM,IAAAA,IAAQH,GAAAA,CAAI7D,UAAU,CAAE;AAC/B0D,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,CAAIhF,QAAQ,EAAE;gBACd6E,QAAAA,IAAY,CAAC,WAAW,EAAEF,IAAAA,CAAKC,SAAS,CAACI,GAAAA,CAAIhF,QAAQ,CAAA,CAAE,KAAK,CAAC;AACjE,YAAA;AACJ,QAAA;QAEA6E,QAAAA,IAAY,CAAC,cAAc,CAAC;QAC5BA,QAAAA,IAAY,CAAC,sBAAsB,EAAE,IAAI,CAACxD,QAAQ,CAACqB,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,MAAcrD,aAAAA,CAAcjB,OAAsB,EAAiB;AAC/D,QAAA,MAAMsC,UAAAA,GAAa,MAAM,IAAI,CAACC,aAAa,EAAA;AAC3C,QAAA,MAAMwC,IAAAA,GAAOX,IAAAA,CAAKC,SAAS,CAACrE,OAAAA,CAAAA,GAAW,IAAA;AACvC,QAAA,MAAM8D,WAAAA,CAAGkB,UAAU,CAAC1C,UAAAA,EAAYyC,IAAAA,EAAM,OAAA,CAAA;AAC1C,IAAA;AAEA;;QAGQ3E,aAAAA,CAAcH,OAAe,EAAU;AAC3C,QAAA,IAAIgF,QAAAA,GAAWhF,OAAAA;;AAGf,QAAA,KAAK,MAAMiF,OAAAA,IAAW,IAAI,CAAChF,MAAM,CAACiF,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;IA3RA,WAAA,CAAY/E,MAAiB,EAAEP,MAAY,CAAE;AAT7C,QAAA,gBAAA,CAAA,IAAA,EAAQO,UAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQJ,kBAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQL,YAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQqB,YAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQe,aAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQnC,aAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQC,UAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQY,gBAAR,MAAA,CAAA;QAGI,IAAI,CAACL,MAAM,GAAG;YACVoC,UAAAA,EAAY,oBAAA;YACZtB,MAAAA,EAAQ,MAAA;YACRyC,gBAAAA,EAAkB,0BAAA;YAClB4B,eAAAA,EAAiB,IAAA;YACjBC,aAAAA,EAAe,KAAA;YACfnF,eAAAA,EAAiB,KAAA;AACjBgF,YAAAA,cAAAA,EAAgB,EAAE;AAClBzC,YAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;AAChBvB,YAAAA,OAAAA,EAAS,IAAA,CAAO,CAAA;AAChB,YAAA,GAAGjB;AACP,SAAA;AAEA,QAAA,IAAI,CAACJ,cAAc,GAAG,IAAI,CAACoD,UAAU,EAAA;QACrC,IAAI,CAACpC,QAAQ,GAAG,EAAE;QAClB,IAAI,CAACe,SAAS,GAAG,EAAE;QACnB,IAAI,CAACnC,SAAS,GAAG,IAAIe,IAAAA,EAAAA;QACrB,IAAI,CAACF,YAAY,GAAG,CAAA;AACpB,QAAA,IAAI,CAACZ,MAAM,GAAG4F,UAAAA,CAAW5F,UAAU6F,cAAAA,EAAgB,oBAAA,CAAA;QAEnD,IAAI,CAAC/F,QAAQ,GAAG;YACZC,SAAAA,EAAW,IAAI,CAACA,SAAS;YACzB8E,KAAAA,EAAO;AACX,SAAA;AACJ,IAAA;AAmQJ;AAmCA;;;;;;;;;;;;;;;;;;;AAmBC,IACM,MAAMiB,oBAAAA,CAAAA;AAST;;AAEC,QACD,aAAaC,IAAAA,CAAKC,QAAgB,EAAEhG,MAAY,EAAiC;QAC7E,MAAMiG,OAAAA,GAAUL,UAAAA,CAAW5F,MAAAA,IAAU6F,cAAAA,EAAgB,sBAAA,CAAA;QACrDI,OAAAA,CAAQhG,KAAK,CAAC,sBAAA,EAAwB;YAAEgD,IAAAA,EAAM+C;AAAS,SAAA,CAAA;QAEvD,IAAI;AACA,YAAA,MAAM1F,OAAAA,GAAU,MAAM6D,WAAAA,CAAG+B,QAAQ,CAACF,QAAAA,EAAU,OAAA,CAAA;;YAG5C,IAAIA,QAAAA,CAASG,QAAQ,CAAC,OAAA,CAAA,EAAU;gBAC5B,MAAM5B,IAAAA,GAA2BE,IAAAA,CAAK2B,KAAK,CAAC9F,OAAAA,CAAAA;gBAC5C,OAAO,IAAIwF,qBAAqBvB,IAAAA,EAAMvE,MAAAA,CAAAA;AAC1C,YAAA,CAAA,MAAO,IAAIgG,QAAAA,CAASG,QAAQ,CAAC,QAAA,CAAA,EAAW;AACpC,gBAAA,MAAME,KAAAA,GAAQ/F,OAAAA,CAAQgG,IAAI,EAAA,CAAGC,KAAK,CAAC,IAAA,CAAA;gBACnC,MAAMpF,QAAAA,GAAWkF,MAAMG,GAAG,CAACpB,CAAAA,IAAAA,GAAQX,IAAAA,CAAK2B,KAAK,CAAChB,IAAAA,CAAAA,CAAAA;AAE9C,gBAAA,MAAMqB,YAAAA,GAAmC;AACrCvG,oBAAAA,EAAAA,EAAI,CAAC,SAAS,EAAEY,IAAAA,CAAK4F,GAAG,EAAA,CAAA,CAAI;oBAC5B5G,QAAAA,EAAU;AACNC,wBAAAA,SAAAA,EAAW,IAAIe,IAAAA,EAAAA;wBACf+D,KAAAA,EAAO;AACX,qBAAA;AACA1D,oBAAAA,QAAAA;oBACAgC,OAAAA,EAAS;AACLC,wBAAAA,aAAAA,EAAejC,SAASqB,MAAM;wBAC9Ba,iBAAAA,EAAmB,CAAA;wBACnBC,UAAAA,EAAY,CAAA;wBACZtB,OAAAA,EAAS;AACb;AACJ,iBAAA;gBAEA,OAAO,IAAI8D,qBAAqBW,YAAAA,EAAczG,MAAAA,CAAAA;YAClD,CAAA,MAAO;AACH,gBAAA,MAAM,IAAI2G,KAAAA,CAAM,CAAC,oBAAoB,EAAEX,QAAAA,CAAAA,CAAU,CAAA;AACrD,YAAA;AACJ,QAAA,CAAA,CAAE,OAAO/D,KAAAA,EAAO;YACZgE,OAAAA,CAAQhE,KAAK,CAAC,6BAAA,EAA+B;gBAAEgB,IAAAA,EAAM+C,QAAAA;AAAU/D,gBAAAA;AAAM,aAAA,CAAA;YACrE,MAAMA,KAAAA;AACV,QAAA;AACJ,IAAA;AAEA;;AAEC,QACD,aAAa2E,UAAAA,CAAWC,SAAiB,EAAE7G,MAAY,EAAiC;AACpF,QAAA,MAAM8G,KAAAA,GAAQ,MAAM3C,WAAAA,CAAG4C,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,CAAUxE,MAAM,KAAK,CAAA,EAAG;AACxB,YAAA,MAAM,IAAImE,KAAAA,CAAM,CAAC,8BAA8B,EAAEE,SAAAA,CAAAA,CAAW,CAAA;AAChE,QAAA;AAEA,QAAA,MAAMQ,aAAapE,aAAAA,CAAKiB,IAAI,CAAC2C,SAAAA,EAAWG,SAAS,CAAC,CAAA,CAAE,CAAA;QACpD,OAAOlB,oBAAAA,CAAqBC,IAAI,CAACsB,UAAAA,EAAYrH,MAAAA,CAAAA;AACjD,IAAA;AAEA;;AAEC,QACD,IAAImB,QAAAA,GAA4B;AAC5B,QAAA,OAAO,IAAI,CAACsF,YAAY,CAACtF,QAAQ;AACrC,IAAA;AAEA;;AAEC,QACDmG,WAAAA,GAAuC;QACnC,OAAO;AAAE,YAAA,GAAG,IAAI,CAACb,YAAY,CAAC3G;AAAS,SAAA;AAC3C,IAAA;AAEA;;AAEC,QACDyH,YAAAA,GAA8B;AAC1B,QAAA,MAAMrF,YAA2B,EAAE;AAEnC,QAAA,KAAK,MAAM4C,GAAAA,IAAO,IAAI,CAAC2B,YAAY,CAACtF,QAAQ,CAAE;YAC1C,IAAI2D,GAAAA,CAAI7D,UAAU,EAAE;AAChB,gBAAA,KAAK,MAAMgE,IAAAA,IAAQH,GAAAA,CAAI7D,UAAU,CAAE;AAC/BiB,oBAAAA,SAAAA,CAAUd,IAAI,CAAC;AACXM,wBAAAA,MAAAA,EAAQuD,KAAK/E,EAAE;wBACfyB,QAAAA,EAAUsD,IAAAA,CAAKC,QAAQ,CAACC,IAAI;AAC5BtE,wBAAAA,SAAAA,EAAWiE,IAAIjE,SAAS;wBACxBe,SAAAA,EAAW,CAAA;AACXO,wBAAAA,SAAAA,EAAWsC,KAAK2B,KAAK,CAACnB,IAAAA,CAAKC,QAAQ,CAAC/C,SAAS,CAAA;wBAC7CL,MAAAA,EAAQ,IAAA;wBACRC,QAAAA,EAAU,CAAA;wBACVC,OAAAA,EAAS;AACb,qBAAA,CAAA;AACJ,gBAAA;AACJ,YAAA;AACJ,QAAA;QAEA,OAAOE,SAAAA;AACX,IAAA;AAEA;;QAGAsF,YAAAA,CAAa7G,KAAa,EAA6B;AACnD,QAAA,OAAO,IAAI,CAAC8F,YAAY,CAACtF,QAAQ,CAACR,KAAAA,CAAM;AAC5C,IAAA;AAEA;;AAEC,QACD8G,WAAAA,GAA+B;AAC3B,QAAA,MAAMC,SAA0B,EAAE;AAElC,QAAA,KAAK,MAAM5C,GAAAA,IAAO,IAAI,CAAC2B,YAAY,CAACtF,QAAQ,CAAE;AAC1CuG,YAAAA,MAAAA,CAAOtG,IAAI,CAAC;AACRP,gBAAAA,SAAAA,EAAWiE,IAAIjE,SAAS;gBACxBe,SAAAA,EAAW,CAAA;gBACX+F,IAAAA,EAAM,SAAA;AACNC,gBAAAA,WAAAA,EAAa,CAAA,EAAG9C,GAAAA,CAAI9D,IAAI,CAAC,QAAQ;AACrC,aAAA,CAAA;AACJ,QAAA;QAEA,OAAO0G,MAAAA;AACX,IAAA;AAEA;;AAEC,QACD,MAAMG,cAAAA,CAAexG,MAAiB,EAAEsB,UAAkB,EAAmB;AACzE,QAAA,IAAI,CAAC3C,MAAM,CAACC,KAAK,CAAC,qBAAA,EAAuB;AAAEoB,YAAAA,MAAAA;YAAQ4B,IAAAA,EAAMN;AAAW,SAAA,CAAA;QAEpE,OAAQtB,MAAAA;YACJ,KAAK,MAAA;AACD,gBAAA,MAAM8C,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAY8B,IAAAA,CAAKC,SAAS,CAAC,IAAI,CAAC+B,YAAY,EAAE,IAAA,EAAM,CAAA,CAAA,EAAI,OAAA,CAAA;AAC3E,gBAAA;YACJ,KAAK,UAAA;gBACD,MAAM,IAAI,CAACqB,cAAc,CAACnF,UAAAA,CAAAA;AAC1B,gBAAA;YACJ,KAAK,OAAA;AAAS,gBAAA;AACV,oBAAA,MAAM0D,KAAAA,GAAQ,IAAI,CAAClF,QAAQ,CAACqF,GAAG,CAACuB,CAAAA,CAAAA,GAAKtD,IAAAA,CAAKC,SAAS,CAACqD,CAAAA,CAAAA,CAAAA,CAAI7D,IAAI,CAAC,IAAA,CAAA;AAC7D,oBAAA,MAAMC,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAY0D,KAAAA,EAAO,OAAA,CAAA;AACtC,oBAAA;AACJ,gBAAA;AACJ;QAEA,OAAO1D,UAAAA;AACX,IAAA;AAEA;;QAGA,MAAcmF,cAAAA,CAAenF,UAAkB,EAAiB;QAC5D,IAAIgC,QAAAA,GAAW,CAAC,sBAAsB,CAAC;QACvCA,QAAAA,IAAY,CAAC,QAAQ,EAAE,IAAI,CAAC8B,YAAY,CAACvG,EAAE,CAAC,EAAE,CAAC;QAE/C,MAAMH,SAAAA,GAAY,OAAO,IAAI,CAAC0G,YAAY,CAAC3G,QAAQ,CAACC,SAAS,KAAK,QAAA,GAC5D,IAAI,CAAC0G,YAAY,CAAC3G,QAAQ,CAACC,SAAS,GACpC,IAAI,CAAC0G,YAAY,CAAC3G,QAAQ,CAACC,SAAS,CAACgB,WAAW,EAAA;AAEtD4D,QAAAA,QAAAA,IAAY,CAAC,aAAa,EAAE5E,SAAAA,CAAU,IAAI,CAAC;AAE3C,QAAA,KAAK,MAAM+E,GAAAA,IAAO,IAAI,CAAC2B,YAAY,CAACtF,QAAQ,CAAE;AAC1CwD,YAAAA,QAAAA,IAAY,CAAC,GAAG,EAAEG,GAAAA,CAAI9D,IAAI,CAACgH,WAAW,EAAA,CAAG,EAAE,EAAElD,GAAAA,CAAInE,KAAK,CAAC,KAAK,CAAC;YAC7D,IAAImE,GAAAA,CAAIxE,OAAO,EAAE;AACbqE,gBAAAA,QAAAA,IAAY,CAAA,EAAGG,GAAAA,CAAIxE,OAAO,CAAC,IAAI,CAAC;AACpC,YAAA;AACJ,QAAA;AAEA,QAAA,MAAM6D,WAAAA,CAAGK,SAAS,CAAC7B,UAAAA,EAAYgC,QAAAA,EAAU,OAAA,CAAA;AAC7C,IAAA;IA5KA,WAAA,CAAoB8B,YAAgC,EAAEzG,MAAY,CAAE;AAHpE,QAAA,gBAAA,CAAA,IAAA,EAAQyG,gBAAR,MAAA,CAAA;AACA,QAAA,gBAAA,CAAA,IAAA,EAAQzG,UAAR,MAAA,CAAA;QAGI,IAAI,CAACyG,YAAY,GAAGA,YAAAA;AACpB,QAAA,IAAI,CAACzG,MAAM,GAAG4F,UAAAA,CAAW5F,UAAU6F,cAAAA,EAAgB,sBAAA,CAAA;AACvD,IAAA;AA0KJ;;;;"}
|
|
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 const ext = this.config.format === 'markdown' ? '.md' : '.json';\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":"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"}
|
package/dist/conversation.d.ts
CHANGED
|
@@ -181,7 +181,7 @@ export declare class ConversationBuilder {
|
|
|
181
181
|
*/
|
|
182
182
|
getMetadata(): ConversationMetadata;
|
|
183
183
|
/**
|
|
184
|
-
* Export messages in OpenAI format
|
|
184
|
+
* Export messages in OpenAI format (deep copy to prevent shared state)
|
|
185
185
|
*/
|
|
186
186
|
toMessages(): ConversationMessage[];
|
|
187
187
|
/**
|
|
@@ -193,7 +193,7 @@ export declare class ConversationBuilder {
|
|
|
193
193
|
*/
|
|
194
194
|
static fromJSON(json: string, config?: Partial<ConversationBuilderConfig>, logger?: any): ConversationBuilder;
|
|
195
195
|
/**
|
|
196
|
-
* Clone the conversation for parallel exploration
|
|
196
|
+
* Clone the conversation for parallel exploration (deep copy to prevent shared state)
|
|
197
197
|
*/
|
|
198
198
|
clone(): ConversationBuilder;
|
|
199
199
|
/**
|
|
@@ -254,6 +254,12 @@ export declare class ConversationBuilder {
|
|
|
254
254
|
build(): this;
|
|
255
255
|
/**
|
|
256
256
|
* Calculate position for context injection
|
|
257
|
+
*
|
|
258
|
+
* Positions:
|
|
259
|
+
* - 'end': After all messages
|
|
260
|
+
* - 'before-last': Before the last message
|
|
261
|
+
* - 'after-system': After the LAST system message (useful for models with multiple system messages)
|
|
262
|
+
* - number: Specific index (clamped to valid range)
|
|
257
263
|
*/
|
|
258
264
|
private calculatePosition;
|
|
259
265
|
/**
|
package/dist/conversation.js
CHANGED
|
@@ -127,6 +127,12 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
127
127
|
if (!this.budgetManager.canAddMessage(message, this.state.messages)) {
|
|
128
128
|
this.logger.warn('Budget exceeded, compressing conversation');
|
|
129
129
|
this.state.messages = this.budgetManager.compress(this.state.messages);
|
|
130
|
+
// Re-check after compression and warn if still over budget
|
|
131
|
+
if (!this.budgetManager.canAddMessage(message, this.state.messages)) {
|
|
132
|
+
this.logger.warn('Token budget still exceeded after compression, adding message anyway');
|
|
133
|
+
// Note: We add the message anyway to maintain backward compatibility
|
|
134
|
+
// Consider setting onBudgetExceeded: 'error' in config if strict enforcement is needed
|
|
135
|
+
}
|
|
130
136
|
}
|
|
131
137
|
}
|
|
132
138
|
this.state.messages.push(message);
|
|
@@ -254,15 +260,18 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
254
260
|
// Calculate position
|
|
255
261
|
const position = this.calculatePosition(opts.position);
|
|
256
262
|
// Format and inject
|
|
257
|
-
for
|
|
263
|
+
for(let i = 0; i < itemsToAdd.length; i++){
|
|
264
|
+
const item = itemsToAdd[i];
|
|
258
265
|
const formatted = this.formatContextItem(item, opts.format);
|
|
259
266
|
const contextMessage = {
|
|
260
267
|
role: 'user',
|
|
261
268
|
content: formatted
|
|
262
269
|
};
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
this.state.
|
|
270
|
+
// Each item is inserted at position + index to maintain order
|
|
271
|
+
const actualPosition = position + i;
|
|
272
|
+
this.state.messages.splice(actualPosition, 0, contextMessage);
|
|
273
|
+
// Track in context manager with correct position
|
|
274
|
+
this.state.contextManager.track(item, actualPosition);
|
|
266
275
|
}
|
|
267
276
|
this.updateMetadata();
|
|
268
277
|
return this;
|
|
@@ -315,10 +324,16 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
315
324
|
};
|
|
316
325
|
}
|
|
317
326
|
/**
|
|
318
|
-
* Export messages in OpenAI format
|
|
327
|
+
* Export messages in OpenAI format (deep copy to prevent shared state)
|
|
319
328
|
*/ toMessages() {
|
|
320
329
|
return this.state.messages.map((msg)=>({
|
|
321
|
-
...msg
|
|
330
|
+
...msg,
|
|
331
|
+
tool_calls: msg.tool_calls ? msg.tool_calls.map((tc)=>({
|
|
332
|
+
...tc,
|
|
333
|
+
function: {
|
|
334
|
+
...tc.function
|
|
335
|
+
}
|
|
336
|
+
})) : undefined
|
|
322
337
|
}));
|
|
323
338
|
}
|
|
324
339
|
/**
|
|
@@ -354,7 +369,7 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
354
369
|
return builder;
|
|
355
370
|
}
|
|
356
371
|
/**
|
|
357
|
-
* Clone the conversation for parallel exploration
|
|
372
|
+
* Clone the conversation for parallel exploration (deep copy to prevent shared state)
|
|
358
373
|
*/ clone() {
|
|
359
374
|
this.logger.debug('Cloning conversation');
|
|
360
375
|
const cloned = ConversationBuilder.create({
|
|
@@ -362,7 +377,13 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
362
377
|
}, this.logger);
|
|
363
378
|
// Deep copy state (note: contextManager is already created in constructor)
|
|
364
379
|
cloned.state.messages = this.state.messages.map((msg)=>({
|
|
365
|
-
...msg
|
|
380
|
+
...msg,
|
|
381
|
+
tool_calls: msg.tool_calls ? msg.tool_calls.map((tc)=>({
|
|
382
|
+
...tc,
|
|
383
|
+
function: {
|
|
384
|
+
...tc.function
|
|
385
|
+
}
|
|
386
|
+
})) : undefined
|
|
366
387
|
}));
|
|
367
388
|
cloned.state.metadata = {
|
|
368
389
|
...this.state.metadata
|
|
@@ -533,6 +554,12 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
533
554
|
}
|
|
534
555
|
/**
|
|
535
556
|
* Calculate position for context injection
|
|
557
|
+
*
|
|
558
|
+
* Positions:
|
|
559
|
+
* - 'end': After all messages
|
|
560
|
+
* - 'before-last': Before the last message
|
|
561
|
+
* - 'after-system': After the LAST system message (useful for models with multiple system messages)
|
|
562
|
+
* - number: Specific index (clamped to valid range)
|
|
536
563
|
*/ calculatePosition(position) {
|
|
537
564
|
if (typeof position === 'number') {
|
|
538
565
|
return Math.max(0, Math.min(position, this.state.messages.length));
|
|
@@ -544,7 +571,7 @@ const ConversationBuilderConfigSchema = z.object({
|
|
|
544
571
|
return Math.max(0, this.state.messages.length - 1);
|
|
545
572
|
case 'after-system':
|
|
546
573
|
{
|
|
547
|
-
// Find last system message (reverse search
|
|
574
|
+
// Find last system message (uses reverse search to find most recent system message)
|
|
548
575
|
let lastSystemIdx = -1;
|
|
549
576
|
for(let i = this.state.messages.length - 1; i >= 0; i--){
|
|
550
577
|
if (this.state.messages[i].role === 'system') {
|