@riotprompt/riotprompt 0.0.7 → 0.0.9
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.kodrdriv-test-cache.json +6 -0
- package/README.md +2 -2
- package/dist/builder.d.ts +3 -15
- package/dist/builder.js +3 -0
- package/dist/builder.js.map +1 -1
- package/dist/context-manager.d.ts +135 -0
- package/dist/context-manager.js +220 -0
- package/dist/context-manager.js.map +1 -0
- package/dist/conversation-logger.d.ts +283 -0
- package/dist/conversation-logger.js +454 -0
- package/dist/conversation-logger.js.map +1 -0
- package/dist/conversation.d.ts +271 -0
- package/dist/conversation.js +622 -0
- package/dist/conversation.js.map +1 -0
- package/dist/formatter.d.ts +27 -57
- package/dist/formatter.js +2 -2
- package/dist/formatter.js.map +1 -1
- package/dist/items/parameters.d.ts +1 -1
- package/dist/items/section.d.ts +2 -12
- package/dist/items/weighted.d.ts +3 -15
- package/dist/iteration-strategy.d.ts +231 -0
- package/dist/iteration-strategy.js +486 -0
- package/dist/iteration-strategy.js.map +1 -0
- package/dist/loader.d.ts +3 -11
- package/dist/loader.js +3 -0
- package/dist/loader.js.map +1 -1
- package/dist/message-builder.d.ts +156 -0
- package/dist/message-builder.js +254 -0
- package/dist/message-builder.js.map +1 -0
- package/dist/override.d.ts +3 -13
- package/dist/override.js +3 -0
- package/dist/override.js.map +1 -1
- package/dist/parser.d.ts +2 -8
- package/dist/recipes.d.ts +70 -268
- package/dist/recipes.js +189 -4
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.d.ts +250 -0
- package/dist/reflection.js +416 -0
- package/dist/reflection.js.map +1 -0
- package/dist/riotprompt.cjs +3551 -220
- package/dist/riotprompt.cjs.map +1 -1
- package/dist/riotprompt.d.ts +18 -2
- package/dist/riotprompt.js +9 -1
- package/dist/riotprompt.js.map +1 -1
- package/dist/token-budget.d.ts +177 -0
- package/dist/token-budget.js +404 -0
- package/dist/token-budget.js.map +1 -0
- package/dist/tools.d.ts +239 -0
- package/dist/tools.js +324 -0
- package/dist/tools.js.map +1 -0
- package/package.json +35 -36
- package/.cursor/rules/focus-on-prompt.mdc +0 -5
|
@@ -0,0 +1,454 @@
|
|
|
1
|
+
import fs__default from 'fs/promises';
|
|
2
|
+
import path__default from 'path';
|
|
3
|
+
import { wrapLogger, DEFAULT_LOGGER } from './logger.js';
|
|
4
|
+
|
|
5
|
+
function _define_property(obj, key, value) {
|
|
6
|
+
if (key in obj) {
|
|
7
|
+
Object.defineProperty(obj, key, {
|
|
8
|
+
value: value,
|
|
9
|
+
enumerable: true,
|
|
10
|
+
configurable: true,
|
|
11
|
+
writable: true
|
|
12
|
+
});
|
|
13
|
+
} else {
|
|
14
|
+
obj[key] = value;
|
|
15
|
+
}
|
|
16
|
+
return obj;
|
|
17
|
+
}
|
|
18
|
+
// ===== CONVERSATION LOGGER =====
|
|
19
|
+
/**
|
|
20
|
+
* ConversationLogger logs conversations to various formats.
|
|
21
|
+
*
|
|
22
|
+
* Features:
|
|
23
|
+
* - Multiple formats (JSON, Markdown, JSONL)
|
|
24
|
+
* - Automatic timestamping
|
|
25
|
+
* - Metadata tracking
|
|
26
|
+
* - Sensitive data redaction
|
|
27
|
+
* - Streaming support (JSONL)
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* const logger = new ConversationLogger({
|
|
32
|
+
* enabled: true,
|
|
33
|
+
* outputPath: 'logs/conversations',
|
|
34
|
+
* format: 'json',
|
|
35
|
+
* includeMetadata: true
|
|
36
|
+
* });
|
|
37
|
+
*
|
|
38
|
+
* logger.onConversationStart({ model: 'gpt-4o', startTime: new Date() });
|
|
39
|
+
* logger.onMessageAdded(message);
|
|
40
|
+
* const path = await logger.save();
|
|
41
|
+
* ```
|
|
42
|
+
*/ class ConversationLogger {
|
|
43
|
+
/**
|
|
44
|
+
* Start conversation logging
|
|
45
|
+
*/ onConversationStart(metadata) {
|
|
46
|
+
this.metadata = {
|
|
47
|
+
...this.metadata,
|
|
48
|
+
...metadata,
|
|
49
|
+
startTime: this.startTime
|
|
50
|
+
};
|
|
51
|
+
this.logger.debug('Conversation logging started', {
|
|
52
|
+
id: this.conversationId
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Log a message
|
|
57
|
+
*/ onMessageAdded(message, metadata) {
|
|
58
|
+
let content = message.content;
|
|
59
|
+
// Redact sensitive data if enabled
|
|
60
|
+
if (this.config.redactSensitive && content && typeof content === 'string') {
|
|
61
|
+
content = this.redactContent(content);
|
|
62
|
+
}
|
|
63
|
+
const loggedMessage = {
|
|
64
|
+
index: this.messageIndex++,
|
|
65
|
+
timestamp: new Date().toISOString(),
|
|
66
|
+
role: message.role,
|
|
67
|
+
content,
|
|
68
|
+
tool_calls: message.tool_calls,
|
|
69
|
+
tool_call_id: message.tool_call_id,
|
|
70
|
+
metadata
|
|
71
|
+
};
|
|
72
|
+
this.messages.push(loggedMessage);
|
|
73
|
+
// For JSONL format, append immediately
|
|
74
|
+
if (this.config.format === 'jsonl') {
|
|
75
|
+
this.appendToJSONL(loggedMessage).catch(this.config.onError);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Log a tool call
|
|
80
|
+
*/ onToolCall(callId, toolName, iteration, args, result, duration, success, error) {
|
|
81
|
+
this.toolCalls.push({
|
|
82
|
+
callId,
|
|
83
|
+
toolName,
|
|
84
|
+
timestamp: new Date().toISOString(),
|
|
85
|
+
iteration,
|
|
86
|
+
arguments: args,
|
|
87
|
+
result,
|
|
88
|
+
duration,
|
|
89
|
+
success,
|
|
90
|
+
error
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* End conversation logging
|
|
95
|
+
*/ onConversationEnd(_summary) {
|
|
96
|
+
this.metadata.endTime = new Date();
|
|
97
|
+
this.metadata.duration = this.metadata.endTime.getTime() - this.startTime.getTime();
|
|
98
|
+
this.logger.debug('Conversation logging ended', {
|
|
99
|
+
messages: this.messages.length,
|
|
100
|
+
duration: this.metadata.duration
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Save conversation to disk
|
|
105
|
+
*/ async save() {
|
|
106
|
+
if (!this.config.enabled) {
|
|
107
|
+
return '';
|
|
108
|
+
}
|
|
109
|
+
try {
|
|
110
|
+
const outputPath = await this.getOutputPath();
|
|
111
|
+
switch(this.config.format){
|
|
112
|
+
case 'json':
|
|
113
|
+
await this.saveAsJSON(outputPath);
|
|
114
|
+
break;
|
|
115
|
+
case 'markdown':
|
|
116
|
+
await this.saveAsMarkdown(outputPath);
|
|
117
|
+
break;
|
|
118
|
+
case 'jsonl':
|
|
119
|
+
break;
|
|
120
|
+
}
|
|
121
|
+
this.config.onSaved(outputPath);
|
|
122
|
+
this.logger.info('Conversation saved', {
|
|
123
|
+
path: outputPath
|
|
124
|
+
});
|
|
125
|
+
return outputPath;
|
|
126
|
+
} catch (error) {
|
|
127
|
+
this.config.onError(error);
|
|
128
|
+
this.logger.error('Failed to save conversation', {
|
|
129
|
+
error
|
|
130
|
+
});
|
|
131
|
+
throw error;
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Get logged conversation object
|
|
136
|
+
*/ getConversation() {
|
|
137
|
+
return {
|
|
138
|
+
id: this.conversationId,
|
|
139
|
+
metadata: this.metadata,
|
|
140
|
+
messages: this.messages,
|
|
141
|
+
summary: {
|
|
142
|
+
totalMessages: this.messages.length,
|
|
143
|
+
toolCallsExecuted: this.toolCalls.length,
|
|
144
|
+
iterations: 0,
|
|
145
|
+
success: true
|
|
146
|
+
}
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Generate unique conversation ID
|
|
151
|
+
*/ generateId() {
|
|
152
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
153
|
+
const random = Math.random().toString(36).substring(2, 8);
|
|
154
|
+
return `conv-${timestamp}-${random}`;
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Get output file path
|
|
158
|
+
*/ async getOutputPath() {
|
|
159
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
160
|
+
const filename = this.config.filenameTemplate.replace('{timestamp}', timestamp).replace('{id}', this.conversationId).replace('{template}', this.metadata.template || 'default');
|
|
161
|
+
const ext = this.config.format === 'markdown' ? '.md' : '.json';
|
|
162
|
+
const fullPath = path__default.join(this.config.outputPath, filename + ext);
|
|
163
|
+
// Ensure directory exists
|
|
164
|
+
await fs__default.mkdir(path__default.dirname(fullPath), {
|
|
165
|
+
recursive: true
|
|
166
|
+
});
|
|
167
|
+
return fullPath;
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* Save as JSON
|
|
171
|
+
*/ async saveAsJSON(outputPath) {
|
|
172
|
+
const data = {
|
|
173
|
+
id: this.conversationId,
|
|
174
|
+
metadata: this.metadata,
|
|
175
|
+
messages: this.messages,
|
|
176
|
+
summary: {
|
|
177
|
+
totalMessages: this.messages.length,
|
|
178
|
+
toolCallsExecuted: this.toolCalls.length,
|
|
179
|
+
iterations: 0,
|
|
180
|
+
success: true
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
await fs__default.writeFile(outputPath, JSON.stringify(data, null, 2), 'utf-8');
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Save as Markdown
|
|
187
|
+
*/ async saveAsMarkdown(outputPath) {
|
|
188
|
+
let markdown = `# Conversation Log\n\n`;
|
|
189
|
+
markdown += `**ID**: ${this.conversationId}\n`;
|
|
190
|
+
markdown += `**Started**: ${this.metadata.startTime.toISOString()}\n`;
|
|
191
|
+
if (this.metadata.duration) {
|
|
192
|
+
markdown += `**Duration**: ${(this.metadata.duration / 1000).toFixed(1)}s\n`;
|
|
193
|
+
}
|
|
194
|
+
markdown += `**Model**: ${this.metadata.model}\n`;
|
|
195
|
+
if (this.metadata.template) {
|
|
196
|
+
markdown += `**Template**: ${this.metadata.template}\n`;
|
|
197
|
+
}
|
|
198
|
+
markdown += `\n## Conversation\n\n`;
|
|
199
|
+
for (const msg of this.messages){
|
|
200
|
+
const time = new Date(msg.timestamp).toLocaleTimeString();
|
|
201
|
+
markdown += `### Message ${msg.index + 1} (${time}) - ${msg.role}\n\n`;
|
|
202
|
+
if (msg.content) {
|
|
203
|
+
markdown += `\`\`\`\n${msg.content}\n\`\`\`\n\n`;
|
|
204
|
+
}
|
|
205
|
+
if (msg.tool_calls) {
|
|
206
|
+
markdown += `**Tool Calls:**\n`;
|
|
207
|
+
for (const call of msg.tool_calls){
|
|
208
|
+
markdown += `- ${call.function.name}: \`${call.function.arguments}\`\n`;
|
|
209
|
+
}
|
|
210
|
+
markdown += `\n`;
|
|
211
|
+
}
|
|
212
|
+
if (msg.metadata) {
|
|
213
|
+
markdown += `*Metadata: ${JSON.stringify(msg.metadata)}*\n\n`;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
markdown += `## Summary\n\n`;
|
|
217
|
+
markdown += `- **Total Messages**: ${this.messages.length}\n`;
|
|
218
|
+
markdown += `- **Tool Calls**: ${this.toolCalls.length}\n`;
|
|
219
|
+
await fs__default.writeFile(outputPath, markdown, 'utf-8');
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Append to JSONL file (streaming)
|
|
223
|
+
*/ async appendToJSONL(message) {
|
|
224
|
+
const outputPath = await this.getOutputPath();
|
|
225
|
+
const line = JSON.stringify(message) + '\n';
|
|
226
|
+
await fs__default.appendFile(outputPath, line, 'utf-8');
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Redact sensitive content
|
|
230
|
+
*/ redactContent(content) {
|
|
231
|
+
let redacted = content;
|
|
232
|
+
// Apply custom patterns
|
|
233
|
+
for (const pattern of this.config.redactPatterns){
|
|
234
|
+
redacted = redacted.replace(pattern, '[REDACTED]');
|
|
235
|
+
}
|
|
236
|
+
// Default patterns
|
|
237
|
+
const defaultPatterns = [
|
|
238
|
+
/api[_-]?key[\s:="']+[\w-]+/gi,
|
|
239
|
+
/password[\s:="']+[\w-]+/gi,
|
|
240
|
+
/Bearer\s+[\w-]+/gi,
|
|
241
|
+
/sk-[a-zA-Z0-9]{48}/g
|
|
242
|
+
];
|
|
243
|
+
for (const pattern of defaultPatterns){
|
|
244
|
+
redacted = redacted.replace(pattern, '[REDACTED]');
|
|
245
|
+
}
|
|
246
|
+
return redacted;
|
|
247
|
+
}
|
|
248
|
+
constructor(config, logger){
|
|
249
|
+
_define_property(this, "config", void 0);
|
|
250
|
+
_define_property(this, "conversationId", void 0);
|
|
251
|
+
_define_property(this, "metadata", void 0);
|
|
252
|
+
_define_property(this, "messages", void 0);
|
|
253
|
+
_define_property(this, "toolCalls", void 0);
|
|
254
|
+
_define_property(this, "startTime", void 0);
|
|
255
|
+
_define_property(this, "logger", void 0);
|
|
256
|
+
_define_property(this, "messageIndex", void 0);
|
|
257
|
+
this.config = {
|
|
258
|
+
outputPath: 'logs/conversations',
|
|
259
|
+
format: 'json',
|
|
260
|
+
filenameTemplate: 'conversation-{timestamp}',
|
|
261
|
+
includeMetadata: true,
|
|
262
|
+
includePrompt: false,
|
|
263
|
+
redactSensitive: false,
|
|
264
|
+
redactPatterns: [],
|
|
265
|
+
onSaved: ()=>{},
|
|
266
|
+
onError: ()=>{},
|
|
267
|
+
...config
|
|
268
|
+
};
|
|
269
|
+
this.conversationId = this.generateId();
|
|
270
|
+
this.messages = [];
|
|
271
|
+
this.toolCalls = [];
|
|
272
|
+
this.startTime = new Date();
|
|
273
|
+
this.messageIndex = 0;
|
|
274
|
+
this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationLogger');
|
|
275
|
+
this.metadata = {
|
|
276
|
+
startTime: this.startTime,
|
|
277
|
+
model: 'unknown'
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* ConversationReplayer loads and replays logged conversations.
|
|
283
|
+
*
|
|
284
|
+
* Features:
|
|
285
|
+
* - Load from various formats
|
|
286
|
+
* - Replay conversations
|
|
287
|
+
* - Compare replays with originals
|
|
288
|
+
* - Export to different formats
|
|
289
|
+
*
|
|
290
|
+
* @example
|
|
291
|
+
* ```typescript
|
|
292
|
+
* const replayer = await ConversationReplayer.load('logs/conv.json');
|
|
293
|
+
*
|
|
294
|
+
* console.log('Messages:', replayer.messages.length);
|
|
295
|
+
* console.log('Tool calls:', replayer.getToolCalls().length);
|
|
296
|
+
*
|
|
297
|
+
* const timeline = replayer.getTimeline();
|
|
298
|
+
* console.log('Events:', timeline.length);
|
|
299
|
+
* ```
|
|
300
|
+
*/ class ConversationReplayer {
|
|
301
|
+
/**
|
|
302
|
+
* Load conversation from file
|
|
303
|
+
*/ static async load(filePath, logger) {
|
|
304
|
+
const wlogger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');
|
|
305
|
+
wlogger.debug('Loading conversation', {
|
|
306
|
+
path: filePath
|
|
307
|
+
});
|
|
308
|
+
try {
|
|
309
|
+
const content = await fs__default.readFile(filePath, 'utf-8');
|
|
310
|
+
// Determine format by extension
|
|
311
|
+
if (filePath.endsWith('.json')) {
|
|
312
|
+
const data = JSON.parse(content);
|
|
313
|
+
return new ConversationReplayer(data, logger);
|
|
314
|
+
} else if (filePath.endsWith('.jsonl')) {
|
|
315
|
+
const lines = content.trim().split('\n');
|
|
316
|
+
const messages = lines.map((line)=>JSON.parse(line));
|
|
317
|
+
const conversation = {
|
|
318
|
+
id: `replayer-${Date.now()}`,
|
|
319
|
+
metadata: {
|
|
320
|
+
startTime: new Date(),
|
|
321
|
+
model: 'unknown'
|
|
322
|
+
},
|
|
323
|
+
messages,
|
|
324
|
+
summary: {
|
|
325
|
+
totalMessages: messages.length,
|
|
326
|
+
toolCallsExecuted: 0,
|
|
327
|
+
iterations: 0,
|
|
328
|
+
success: true
|
|
329
|
+
}
|
|
330
|
+
};
|
|
331
|
+
return new ConversationReplayer(conversation, logger);
|
|
332
|
+
} else {
|
|
333
|
+
throw new Error(`Unsupported format: ${filePath}`);
|
|
334
|
+
}
|
|
335
|
+
} catch (error) {
|
|
336
|
+
wlogger.error('Failed to load conversation', {
|
|
337
|
+
path: filePath,
|
|
338
|
+
error
|
|
339
|
+
});
|
|
340
|
+
throw error;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
/**
|
|
344
|
+
* Load latest conversation from directory
|
|
345
|
+
*/ static async loadLatest(directory, logger) {
|
|
346
|
+
const files = await fs__default.readdir(directory);
|
|
347
|
+
const jsonFiles = files.filter((f)=>f.endsWith('.json')).sort().reverse();
|
|
348
|
+
if (jsonFiles.length === 0) {
|
|
349
|
+
throw new Error(`No conversation logs found in ${directory}`);
|
|
350
|
+
}
|
|
351
|
+
const latestPath = path__default.join(directory, jsonFiles[0]);
|
|
352
|
+
return ConversationReplayer.load(latestPath, logger);
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* Get all messages
|
|
356
|
+
*/ get messages() {
|
|
357
|
+
return this.conversation.messages;
|
|
358
|
+
}
|
|
359
|
+
/**
|
|
360
|
+
* Get conversation metadata
|
|
361
|
+
*/ getMetadata() {
|
|
362
|
+
return {
|
|
363
|
+
...this.conversation.metadata
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
/**
|
|
367
|
+
* Get tool calls
|
|
368
|
+
*/ getToolCalls() {
|
|
369
|
+
const toolCalls = [];
|
|
370
|
+
for (const msg of this.conversation.messages){
|
|
371
|
+
if (msg.tool_calls) {
|
|
372
|
+
for (const call of msg.tool_calls){
|
|
373
|
+
toolCalls.push({
|
|
374
|
+
callId: call.id,
|
|
375
|
+
toolName: call.function.name,
|
|
376
|
+
timestamp: msg.timestamp,
|
|
377
|
+
iteration: 0,
|
|
378
|
+
arguments: JSON.parse(call.function.arguments),
|
|
379
|
+
result: null,
|
|
380
|
+
duration: 0,
|
|
381
|
+
success: true
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
return toolCalls;
|
|
387
|
+
}
|
|
388
|
+
/**
|
|
389
|
+
* Get message at index
|
|
390
|
+
*/ getMessageAt(index) {
|
|
391
|
+
return this.conversation.messages[index];
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Get timeline of events
|
|
395
|
+
*/ getTimeline() {
|
|
396
|
+
const events = [];
|
|
397
|
+
for (const msg of this.conversation.messages){
|
|
398
|
+
events.push({
|
|
399
|
+
timestamp: msg.timestamp,
|
|
400
|
+
iteration: 0,
|
|
401
|
+
type: 'message',
|
|
402
|
+
description: `${msg.role} message`
|
|
403
|
+
});
|
|
404
|
+
}
|
|
405
|
+
return events;
|
|
406
|
+
}
|
|
407
|
+
/**
|
|
408
|
+
* Export to format
|
|
409
|
+
*/ async exportToFormat(format, outputPath) {
|
|
410
|
+
this.logger.debug('Exporting to format', {
|
|
411
|
+
format,
|
|
412
|
+
path: outputPath
|
|
413
|
+
});
|
|
414
|
+
switch(format){
|
|
415
|
+
case 'json':
|
|
416
|
+
await fs__default.writeFile(outputPath, JSON.stringify(this.conversation, null, 2), 'utf-8');
|
|
417
|
+
break;
|
|
418
|
+
case 'markdown':
|
|
419
|
+
await this.exportMarkdown(outputPath);
|
|
420
|
+
break;
|
|
421
|
+
case 'jsonl':
|
|
422
|
+
{
|
|
423
|
+
const lines = this.messages.map((m)=>JSON.stringify(m)).join('\n');
|
|
424
|
+
await fs__default.writeFile(outputPath, lines, 'utf-8');
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
return outputPath;
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Export as markdown
|
|
432
|
+
*/ async exportMarkdown(outputPath) {
|
|
433
|
+
let markdown = `# Conversation Log\n\n`;
|
|
434
|
+
markdown += `**ID**: ${this.conversation.id}\n`;
|
|
435
|
+
const startTime = typeof this.conversation.metadata.startTime === 'string' ? this.conversation.metadata.startTime : this.conversation.metadata.startTime.toISOString();
|
|
436
|
+
markdown += `**Started**: ${startTime}\n\n`;
|
|
437
|
+
for (const msg of this.conversation.messages){
|
|
438
|
+
markdown += `## ${msg.role.toUpperCase()} (${msg.index})\n\n`;
|
|
439
|
+
if (msg.content) {
|
|
440
|
+
markdown += `${msg.content}\n\n`;
|
|
441
|
+
}
|
|
442
|
+
}
|
|
443
|
+
await fs__default.writeFile(outputPath, markdown, 'utf-8');
|
|
444
|
+
}
|
|
445
|
+
constructor(conversation, logger){
|
|
446
|
+
_define_property(this, "conversation", void 0);
|
|
447
|
+
_define_property(this, "logger", void 0);
|
|
448
|
+
this.conversation = conversation;
|
|
449
|
+
this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
export { ConversationLogger, ConversationReplayer, ConversationLogger as default };
|
|
454
|
+
//# sourceMappingURL=conversation-logger.js.map
|
|
@@ -0,0 +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":"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"}
|