@riotprompt/riotprompt 0.0.8 → 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.
Files changed (59) hide show
  1. package/.kodrdriv-test-cache.json +6 -0
  2. package/BUG-ANALYSIS.md +523 -0
  3. package/CODE-REVIEW-SUMMARY.md +330 -0
  4. package/FIXES-APPLIED.md +437 -0
  5. package/README.md +2 -2
  6. package/dist/builder.js +3 -0
  7. package/dist/builder.js.map +1 -1
  8. package/dist/chat.d.ts +1 -1
  9. package/dist/chat.js +2 -5
  10. package/dist/chat.js.map +1 -1
  11. package/dist/constants.js +1 -2
  12. package/dist/constants.js.map +1 -1
  13. package/dist/context-manager.d.ts +136 -0
  14. package/dist/context-manager.js +243 -0
  15. package/dist/context-manager.js.map +1 -0
  16. package/dist/conversation-logger.d.ts +285 -0
  17. package/dist/conversation-logger.js +491 -0
  18. package/dist/conversation-logger.js.map +1 -0
  19. package/dist/conversation.d.ts +277 -0
  20. package/dist/conversation.js +649 -0
  21. package/dist/conversation.js.map +1 -0
  22. package/dist/formatter.js.map +1 -1
  23. package/dist/items/section.js +3 -3
  24. package/dist/items/section.js.map +1 -1
  25. package/dist/iteration-strategy.d.ts +233 -0
  26. package/dist/iteration-strategy.js +520 -0
  27. package/dist/iteration-strategy.js.map +1 -0
  28. package/dist/loader.js +21 -3
  29. package/dist/loader.js.map +1 -1
  30. package/dist/message-builder.d.ts +156 -0
  31. package/dist/message-builder.js +256 -0
  32. package/dist/message-builder.js.map +1 -0
  33. package/dist/model-config.d.ts +115 -0
  34. package/dist/model-config.js +205 -0
  35. package/dist/model-config.js.map +1 -0
  36. package/dist/override.js +8 -1
  37. package/dist/override.js.map +1 -1
  38. package/dist/parser.js +3 -3
  39. package/dist/parser.js.map +1 -1
  40. package/dist/recipes.d.ts +42 -0
  41. package/dist/recipes.js +189 -4
  42. package/dist/recipes.js.map +1 -1
  43. package/dist/reflection.d.ts +250 -0
  44. package/dist/reflection.js +419 -0
  45. package/dist/reflection.js.map +1 -0
  46. package/dist/riotprompt.cjs +3854 -178
  47. package/dist/riotprompt.cjs.map +1 -1
  48. package/dist/riotprompt.d.ts +20 -2
  49. package/dist/riotprompt.js +10 -1
  50. package/dist/riotprompt.js.map +1 -1
  51. package/dist/token-budget.d.ts +177 -0
  52. package/dist/token-budget.js +401 -0
  53. package/dist/token-budget.js.map +1 -0
  54. package/dist/tools.d.ts +239 -0
  55. package/dist/tools.js +324 -0
  56. package/dist/tools.js.map +1 -0
  57. package/dist/util/general.js +1 -1
  58. package/dist/util/general.js.map +1 -1
  59. package/package.json +23 -20
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Dynamic content item with enhanced tracking and lifecycle
3
+ */
4
+ export interface DynamicContentItem {
5
+ content: string;
6
+ title?: string;
7
+ weight?: number;
8
+ id?: string;
9
+ category?: string;
10
+ source?: string;
11
+ priority?: 'high' | 'medium' | 'low';
12
+ timestamp?: Date;
13
+ }
14
+ /**
15
+ * Tracked context item with metadata
16
+ */
17
+ export interface TrackedContextItem extends DynamicContentItem {
18
+ id: string;
19
+ hash: string;
20
+ position: number;
21
+ injectedAt: Date;
22
+ }
23
+ /**
24
+ * Context statistics
25
+ */
26
+ export interface ContextStats {
27
+ totalItems: number;
28
+ byCategory: Map<string, number>;
29
+ byPriority: Map<string, number>;
30
+ bySource: Map<string, number>;
31
+ oldestTimestamp?: Date;
32
+ newestTimestamp?: Date;
33
+ }
34
+ /**
35
+ * ContextManager tracks and manages dynamically injected context.
36
+ *
37
+ * Features:
38
+ * - Track all injected context with metadata
39
+ * - Deduplication by ID, hash, or content
40
+ * - Category-based organization
41
+ * - Query context state
42
+ * - Context statistics
43
+ *
44
+ * @example
45
+ * ```typescript
46
+ * const manager = new ContextManager();
47
+ *
48
+ * // Track injected context
49
+ * manager.track({
50
+ * id: 'file:main.ts',
51
+ * content: fileContent,
52
+ * title: 'Main File',
53
+ * category: 'source-code'
54
+ * }, 5);
55
+ *
56
+ * // Check for duplicates
57
+ * if (manager.hasContext('file:main.ts')) {
58
+ * console.log('Already provided');
59
+ * }
60
+ *
61
+ * // Query by category
62
+ * const sourceFiles = manager.getByCategory('source-code');
63
+ * ```
64
+ */
65
+ export declare class ContextManager {
66
+ private items;
67
+ private hashes;
68
+ private logger;
69
+ constructor(logger?: any);
70
+ /**
71
+ * Track a context item (with deduplication by content hash for items without ID)
72
+ */
73
+ track(item: DynamicContentItem, position: number): void;
74
+ /**
75
+ * Check if context with given ID exists
76
+ */
77
+ hasContext(id: string): boolean;
78
+ /**
79
+ * Check if content with given hash exists
80
+ */
81
+ hasContentHash(content: string): boolean;
82
+ /**
83
+ * Check if similar content exists (fuzzy match)
84
+ * Uses similarity threshold to avoid overly aggressive deduplication
85
+ */
86
+ hasSimilarContent(content: string, similarityThreshold?: number): boolean;
87
+ /**
88
+ * Get context item by ID
89
+ */
90
+ get(id: string): TrackedContextItem | undefined;
91
+ /**
92
+ * Get all tracked context items
93
+ */
94
+ getAll(): TrackedContextItem[];
95
+ /**
96
+ * Get context items by category
97
+ */
98
+ getByCategory(category: string): TrackedContextItem[];
99
+ /**
100
+ * Get context items by priority
101
+ */
102
+ getByPriority(priority: 'high' | 'medium' | 'low'): TrackedContextItem[];
103
+ /**
104
+ * Get context items by source
105
+ */
106
+ getBySource(source: string): TrackedContextItem[];
107
+ /**
108
+ * Get all categories
109
+ */
110
+ getCategories(): string[];
111
+ /**
112
+ * Get context statistics
113
+ */
114
+ getStats(): ContextStats;
115
+ /**
116
+ * Remove context item by ID
117
+ */
118
+ remove(id: string): boolean;
119
+ /**
120
+ * Clear all tracked context
121
+ */
122
+ clear(): void;
123
+ /**
124
+ * Generate unique ID for context item
125
+ */
126
+ private generateId;
127
+ /**
128
+ * Hash content for deduplication
129
+ */
130
+ private hashContent;
131
+ /**
132
+ * Normalize content for comparison
133
+ */
134
+ private normalizeContent;
135
+ }
136
+ export default ContextManager;
@@ -0,0 +1,243 @@
1
+ import crypto from 'crypto';
2
+ import { wrapLogger, DEFAULT_LOGGER } from './logger.js';
3
+
4
+ function _define_property(obj, key, value) {
5
+ if (key in obj) {
6
+ Object.defineProperty(obj, key, {
7
+ value: value,
8
+ enumerable: true,
9
+ configurable: true,
10
+ writable: true
11
+ });
12
+ } else {
13
+ obj[key] = value;
14
+ }
15
+ return obj;
16
+ }
17
+ /**
18
+ * ContextManager tracks and manages dynamically injected context.
19
+ *
20
+ * Features:
21
+ * - Track all injected context with metadata
22
+ * - Deduplication by ID, hash, or content
23
+ * - Category-based organization
24
+ * - Query context state
25
+ * - Context statistics
26
+ *
27
+ * @example
28
+ * ```typescript
29
+ * const manager = new ContextManager();
30
+ *
31
+ * // Track injected context
32
+ * manager.track({
33
+ * id: 'file:main.ts',
34
+ * content: fileContent,
35
+ * title: 'Main File',
36
+ * category: 'source-code'
37
+ * }, 5);
38
+ *
39
+ * // Check for duplicates
40
+ * if (manager.hasContext('file:main.ts')) {
41
+ * console.log('Already provided');
42
+ * }
43
+ *
44
+ * // Query by category
45
+ * const sourceFiles = manager.getByCategory('source-code');
46
+ * ```
47
+ */ class ContextManager {
48
+ /**
49
+ * Track a context item (with deduplication by content hash for items without ID)
50
+ */ track(item, position) {
51
+ const hash = this.hashContent(item.content);
52
+ // If item has no ID and we already have this content hash, skip tracking
53
+ if (!item.id && this.hashes.has(hash)) {
54
+ this.logger.debug('Skipping duplicate context item by hash', {
55
+ hash
56
+ });
57
+ return;
58
+ }
59
+ const id = item.id || this.generateId();
60
+ const trackedItem = {
61
+ ...item,
62
+ id,
63
+ hash,
64
+ position,
65
+ injectedAt: new Date(),
66
+ timestamp: item.timestamp || new Date(),
67
+ priority: item.priority || 'medium'
68
+ };
69
+ this.items.set(id, trackedItem);
70
+ this.hashes.add(hash);
71
+ this.logger.debug('Tracked context item', {
72
+ id,
73
+ category: item.category,
74
+ position
75
+ });
76
+ }
77
+ /**
78
+ * Check if context with given ID exists
79
+ */ hasContext(id) {
80
+ return this.items.has(id);
81
+ }
82
+ /**
83
+ * Check if content with given hash exists
84
+ */ hasContentHash(content) {
85
+ const hash = this.hashContent(content);
86
+ return this.hashes.has(hash);
87
+ }
88
+ /**
89
+ * Check if similar content exists (fuzzy match)
90
+ * Uses similarity threshold to avoid overly aggressive deduplication
91
+ */ hasSimilarContent(content, similarityThreshold = 0.9) {
92
+ // Warn if checking against a large number of items (performance consideration)
93
+ const MAX_ITEMS_WARNING = 1000;
94
+ if (this.items.size > MAX_ITEMS_WARNING) {
95
+ this.logger.warn('Large number of context items, similarity check may be slow', {
96
+ count: this.items.size,
97
+ threshold: MAX_ITEMS_WARNING
98
+ });
99
+ }
100
+ const normalized = this.normalizeContent(content);
101
+ for (const item of this.items.values()){
102
+ const itemNormalized = this.normalizeContent(item.content || '');
103
+ // Exact match
104
+ if (normalized === itemNormalized) {
105
+ return true;
106
+ }
107
+ // Calculate similarity ratio (Jaccard-like)
108
+ const longer = normalized.length > itemNormalized.length ? normalized : itemNormalized;
109
+ const shorter = normalized.length <= itemNormalized.length ? normalized : itemNormalized;
110
+ // Only consider substring match if the shorter is at least 90% of longer
111
+ const lengthRatio = shorter.length / longer.length;
112
+ if (lengthRatio >= similarityThreshold) {
113
+ // Check if one is contained in the other
114
+ if (longer.includes(shorter)) {
115
+ return true;
116
+ }
117
+ }
118
+ }
119
+ return false;
120
+ }
121
+ /**
122
+ * Get context item by ID
123
+ */ get(id) {
124
+ return this.items.get(id);
125
+ }
126
+ /**
127
+ * Get all tracked context items
128
+ */ getAll() {
129
+ return Array.from(this.items.values());
130
+ }
131
+ /**
132
+ * Get context items by category
133
+ */ getByCategory(category) {
134
+ return this.getAll().filter((item)=>item.category === category);
135
+ }
136
+ /**
137
+ * Get context items by priority
138
+ */ getByPriority(priority) {
139
+ return this.getAll().filter((item)=>item.priority === priority);
140
+ }
141
+ /**
142
+ * Get context items by source
143
+ */ getBySource(source) {
144
+ return this.getAll().filter((item)=>item.source === source);
145
+ }
146
+ /**
147
+ * Get all categories
148
+ */ getCategories() {
149
+ const categories = new Set();
150
+ this.items.forEach((item)=>{
151
+ if (item.category) {
152
+ categories.add(item.category);
153
+ }
154
+ });
155
+ return Array.from(categories).sort();
156
+ }
157
+ /**
158
+ * Get context statistics
159
+ */ getStats() {
160
+ const byCategory = new Map();
161
+ const byPriority = new Map();
162
+ const bySource = new Map();
163
+ let oldestTimestamp;
164
+ let newestTimestamp;
165
+ this.items.forEach((item)=>{
166
+ // Category stats
167
+ if (item.category) {
168
+ byCategory.set(item.category, (byCategory.get(item.category) || 0) + 1);
169
+ }
170
+ // Priority stats
171
+ const priority = item.priority || 'medium';
172
+ byPriority.set(priority, (byPriority.get(priority) || 0) + 1);
173
+ // Source stats
174
+ if (item.source) {
175
+ bySource.set(item.source, (bySource.get(item.source) || 0) + 1);
176
+ }
177
+ // Timestamp stats
178
+ if (item.timestamp) {
179
+ if (!oldestTimestamp || item.timestamp < oldestTimestamp) {
180
+ oldestTimestamp = item.timestamp;
181
+ }
182
+ if (!newestTimestamp || item.timestamp > newestTimestamp) {
183
+ newestTimestamp = item.timestamp;
184
+ }
185
+ }
186
+ });
187
+ return {
188
+ totalItems: this.items.size,
189
+ byCategory,
190
+ byPriority,
191
+ bySource,
192
+ oldestTimestamp,
193
+ newestTimestamp
194
+ };
195
+ }
196
+ /**
197
+ * Remove context item by ID
198
+ */ remove(id) {
199
+ const item = this.items.get(id);
200
+ if (item) {
201
+ this.items.delete(id);
202
+ this.hashes.delete(item.hash);
203
+ this.logger.debug('Removed context item', {
204
+ id
205
+ });
206
+ return true;
207
+ }
208
+ return false;
209
+ }
210
+ /**
211
+ * Clear all tracked context
212
+ */ clear() {
213
+ this.items.clear();
214
+ this.hashes.clear();
215
+ this.logger.debug('Cleared all context');
216
+ }
217
+ /**
218
+ * Generate unique ID for context item
219
+ */ generateId() {
220
+ return `ctx-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;
221
+ }
222
+ /**
223
+ * Hash content for deduplication
224
+ */ hashContent(content) {
225
+ return crypto.createHash('sha256').update(content).digest('hex').substring(0, 16);
226
+ }
227
+ /**
228
+ * Normalize content for comparison
229
+ */ normalizeContent(content) {
230
+ return content.replace(/\s+/g, ' ').trim().toLowerCase();
231
+ }
232
+ constructor(logger){
233
+ _define_property(this, "items", void 0);
234
+ _define_property(this, "hashes", void 0);
235
+ _define_property(this, "logger", void 0);
236
+ this.items = new Map();
237
+ this.hashes = new Set();
238
+ this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ContextManager');
239
+ }
240
+ }
241
+
242
+ export { ContextManager, ContextManager as default };
243
+ //# sourceMappingURL=context-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"context-manager.js","sources":["../src/context-manager.ts"],"sourcesContent":["import crypto from 'crypto';\nimport { DEFAULT_LOGGER, wrapLogger } from \"./logger\";\n\n// ===== TYPE DEFINITIONS =====\n\n/**\n * Dynamic content item with enhanced tracking and lifecycle\n */\nexport interface DynamicContentItem {\n content: string;\n title?: string;\n weight?: number;\n\n // Unique identifier for deduplication\n id?: string;\n\n // Category for grouping\n category?: string;\n\n // Source of context\n source?: string;\n\n // Priority level\n priority?: 'high' | 'medium' | 'low';\n\n // Timestamp\n timestamp?: Date;\n}\n\n/**\n * Tracked context item with metadata\n */\nexport interface TrackedContextItem extends DynamicContentItem {\n id: string;\n hash: string;\n position: number;\n injectedAt: Date;\n}\n\n/**\n * Context statistics\n */\nexport interface ContextStats {\n totalItems: number;\n byCategory: Map<string, number>;\n byPriority: Map<string, number>;\n bySource: Map<string, number>;\n oldestTimestamp?: Date;\n newestTimestamp?: Date;\n}\n\n/**\n * ContextManager tracks and manages dynamically injected context.\n *\n * Features:\n * - Track all injected context with metadata\n * - Deduplication by ID, hash, or content\n * - Category-based organization\n * - Query context state\n * - Context statistics\n *\n * @example\n * ```typescript\n * const manager = new ContextManager();\n *\n * // Track injected context\n * manager.track({\n * id: 'file:main.ts',\n * content: fileContent,\n * title: 'Main File',\n * category: 'source-code'\n * }, 5);\n *\n * // Check for duplicates\n * if (manager.hasContext('file:main.ts')) {\n * console.log('Already provided');\n * }\n *\n * // Query by category\n * const sourceFiles = manager.getByCategory('source-code');\n * ```\n */\nexport class ContextManager {\n private items: Map<string, TrackedContextItem>;\n private hashes: Set<string>;\n private logger: any;\n\n constructor(logger?: any) {\n this.items = new Map();\n this.hashes = new Set();\n this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ContextManager');\n }\n\n /**\n * Track a context item (with deduplication by content hash for items without ID)\n */\n track(item: DynamicContentItem, position: number): void {\n const hash = this.hashContent(item.content);\n\n // If item has no ID and we already have this content hash, skip tracking\n if (!item.id && this.hashes.has(hash)) {\n this.logger.debug('Skipping duplicate context item by hash', { hash });\n return;\n }\n\n const id = item.id || this.generateId();\n\n const trackedItem: TrackedContextItem = {\n ...item,\n id,\n hash,\n position,\n injectedAt: new Date(),\n timestamp: item.timestamp || new Date(),\n priority: item.priority || 'medium',\n };\n\n this.items.set(id, trackedItem);\n this.hashes.add(hash);\n\n this.logger.debug('Tracked context item', { id, category: item.category, position });\n }\n\n /**\n * Check if context with given ID exists\n */\n hasContext(id: string): boolean {\n return this.items.has(id);\n }\n\n /**\n * Check if content with given hash exists\n */\n hasContentHash(content: string): boolean {\n const hash = this.hashContent(content);\n return this.hashes.has(hash);\n }\n\n /**\n * Check if similar content exists (fuzzy match)\n * Uses similarity threshold to avoid overly aggressive deduplication\n */\n hasSimilarContent(content: string, similarityThreshold: number = 0.9): boolean {\n // Warn if checking against a large number of items (performance consideration)\n const MAX_ITEMS_WARNING = 1000;\n if (this.items.size > MAX_ITEMS_WARNING) {\n this.logger.warn('Large number of context items, similarity check may be slow', {\n count: this.items.size,\n threshold: MAX_ITEMS_WARNING\n });\n }\n\n const normalized = this.normalizeContent(content);\n\n for (const item of this.items.values()) {\n const itemNormalized = this.normalizeContent(item.content || '');\n\n // Exact match\n if (normalized === itemNormalized) {\n return true;\n }\n\n // Calculate similarity ratio (Jaccard-like)\n const longer = normalized.length > itemNormalized.length ? normalized : itemNormalized;\n const shorter = normalized.length <= itemNormalized.length ? normalized : itemNormalized;\n\n // Only consider substring match if the shorter is at least 90% of longer\n const lengthRatio = shorter.length / longer.length;\n\n if (lengthRatio >= similarityThreshold) {\n // Check if one is contained in the other\n if (longer.includes(shorter)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Get context item by ID\n */\n get(id: string): TrackedContextItem | undefined {\n return this.items.get(id);\n }\n\n /**\n * Get all tracked context items\n */\n getAll(): TrackedContextItem[] {\n return Array.from(this.items.values());\n }\n\n /**\n * Get context items by category\n */\n getByCategory(category: string): TrackedContextItem[] {\n return this.getAll().filter(item => item.category === category);\n }\n\n /**\n * Get context items by priority\n */\n getByPriority(priority: 'high' | 'medium' | 'low'): TrackedContextItem[] {\n return this.getAll().filter(item => item.priority === priority);\n }\n\n /**\n * Get context items by source\n */\n getBySource(source: string): TrackedContextItem[] {\n return this.getAll().filter(item => item.source === source);\n }\n\n /**\n * Get all categories\n */\n getCategories(): string[] {\n const categories = new Set<string>();\n this.items.forEach(item => {\n if (item.category) {\n categories.add(item.category);\n }\n });\n return Array.from(categories).sort();\n }\n\n /**\n * Get context statistics\n */\n getStats(): ContextStats {\n const byCategory = new Map<string, number>();\n const byPriority = new Map<string, number>();\n const bySource = new Map<string, number>();\n let oldestTimestamp: Date | undefined;\n let newestTimestamp: Date | undefined;\n\n this.items.forEach(item => {\n // Category stats\n if (item.category) {\n byCategory.set(item.category, (byCategory.get(item.category) || 0) + 1);\n }\n\n // Priority stats\n const priority = item.priority || 'medium';\n byPriority.set(priority, (byPriority.get(priority) || 0) + 1);\n\n // Source stats\n if (item.source) {\n bySource.set(item.source, (bySource.get(item.source) || 0) + 1);\n }\n\n // Timestamp stats\n if (item.timestamp) {\n if (!oldestTimestamp || item.timestamp < oldestTimestamp) {\n oldestTimestamp = item.timestamp;\n }\n if (!newestTimestamp || item.timestamp > newestTimestamp) {\n newestTimestamp = item.timestamp;\n }\n }\n });\n\n return {\n totalItems: this.items.size,\n byCategory,\n byPriority,\n bySource,\n oldestTimestamp,\n newestTimestamp,\n };\n }\n\n /**\n * Remove context item by ID\n */\n remove(id: string): boolean {\n const item = this.items.get(id);\n if (item) {\n this.items.delete(id);\n this.hashes.delete(item.hash);\n this.logger.debug('Removed context item', { id });\n return true;\n }\n return false;\n }\n\n /**\n * Clear all tracked context\n */\n clear(): void {\n this.items.clear();\n this.hashes.clear();\n this.logger.debug('Cleared all context');\n }\n\n /**\n * Generate unique ID for context item\n */\n private generateId(): string {\n return `ctx-${Date.now()}-${Math.random().toString(36).substring(2, 9)}`;\n }\n\n /**\n * Hash content for deduplication\n */\n private hashContent(content: string): string {\n return crypto\n .createHash('sha256')\n .update(content)\n .digest('hex')\n .substring(0, 16);\n }\n\n /**\n * Normalize content for comparison\n */\n private normalizeContent(content: string): string {\n return content.replace(/\\s+/g, ' ').trim().toLowerCase();\n }\n}\n\nexport default ContextManager;\n\n"],"names":["ContextManager","track","item","position","hash","hashContent","content","id","hashes","has","logger","debug","generateId","trackedItem","injectedAt","Date","timestamp","priority","items","set","add","category","hasContext","hasContentHash","hasSimilarContent","similarityThreshold","MAX_ITEMS_WARNING","size","warn","count","threshold","normalized","normalizeContent","values","itemNormalized","longer","length","shorter","lengthRatio","includes","get","getAll","Array","from","getByCategory","filter","getByPriority","getBySource","source","getCategories","categories","Set","forEach","sort","getStats","byCategory","Map","byPriority","bySource","oldestTimestamp","newestTimestamp","totalItems","remove","delete","clear","now","Math","random","toString","substring","crypto","createHash","update","digest","replace","trim","toLowerCase","wrapLogger","DEFAULT_LOGGER"],"mappings":"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"}
@@ -0,0 +1,285 @@
1
+ import { ConversationMessage, ToolCall } from './conversation';
2
+ /**
3
+ * Log format
4
+ */
5
+ export type LogFormat = 'json' | 'markdown' | 'jsonl';
6
+ /**
7
+ * Log configuration
8
+ */
9
+ export interface LogConfig {
10
+ enabled: boolean;
11
+ outputPath?: string;
12
+ format?: LogFormat;
13
+ filenameTemplate?: string;
14
+ includeMetadata?: boolean;
15
+ includePrompt?: boolean;
16
+ redactSensitive?: boolean;
17
+ redactPatterns?: RegExp[];
18
+ onSaved?: (path: string) => void;
19
+ onError?: (error: Error) => void;
20
+ }
21
+ /**
22
+ * Logged conversation structure
23
+ */
24
+ export interface LoggedConversation {
25
+ id: string;
26
+ metadata: ConversationLogMetadata;
27
+ prompt?: PromptSnapshot;
28
+ messages: LoggedMessage[];
29
+ summary: ConversationSummary;
30
+ }
31
+ /**
32
+ * Conversation metadata for logging
33
+ */
34
+ export interface ConversationLogMetadata {
35
+ startTime: Date;
36
+ endTime?: Date;
37
+ duration?: number;
38
+ model: string;
39
+ template?: string;
40
+ userContext?: Record<string, any>;
41
+ }
42
+ /**
43
+ * Snapshot of prompt configuration
44
+ */
45
+ export interface PromptSnapshot {
46
+ persona?: string;
47
+ instructions?: string;
48
+ content?: string[];
49
+ context?: string[];
50
+ }
51
+ /**
52
+ * Logged message with metadata
53
+ */
54
+ export interface LoggedMessage {
55
+ index: number;
56
+ timestamp: string;
57
+ role: string;
58
+ content: string | null;
59
+ tool_calls?: ToolCall[];
60
+ tool_call_id?: string;
61
+ metadata?: MessageLogMetadata;
62
+ }
63
+ /**
64
+ * Message metadata for logging
65
+ */
66
+ export interface MessageLogMetadata {
67
+ tokens?: number;
68
+ source?: string;
69
+ latency?: number;
70
+ tool?: string;
71
+ duration?: number;
72
+ success?: boolean;
73
+ [key: string]: any;
74
+ }
75
+ /**
76
+ * Conversation summary
77
+ */
78
+ export interface ConversationSummary {
79
+ totalMessages: number;
80
+ totalTokens?: number;
81
+ toolCallsExecuted: number;
82
+ iterations: number;
83
+ finalOutput?: string;
84
+ success: boolean;
85
+ }
86
+ /**
87
+ * Tool call log entry
88
+ */
89
+ export interface ToolCallLog {
90
+ callId: string;
91
+ toolName: string;
92
+ timestamp: string;
93
+ iteration: number;
94
+ arguments: any;
95
+ result: any;
96
+ duration: number;
97
+ success: boolean;
98
+ error?: string;
99
+ }
100
+ /**
101
+ * ConversationLogger logs conversations to various formats.
102
+ *
103
+ * Features:
104
+ * - Multiple formats (JSON, Markdown, JSONL)
105
+ * - Automatic timestamping
106
+ * - Metadata tracking
107
+ * - Sensitive data redaction
108
+ * - Streaming support (JSONL)
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const logger = new ConversationLogger({
113
+ * enabled: true,
114
+ * outputPath: 'logs/conversations',
115
+ * format: 'json',
116
+ * includeMetadata: true
117
+ * });
118
+ *
119
+ * logger.onConversationStart({ model: 'gpt-4o', startTime: new Date() });
120
+ * logger.onMessageAdded(message);
121
+ * const path = await logger.save();
122
+ * ```
123
+ */
124
+ export declare class ConversationLogger {
125
+ private config;
126
+ private conversationId;
127
+ private metadata;
128
+ private messages;
129
+ private toolCalls;
130
+ private startTime;
131
+ private logger;
132
+ private messageIndex;
133
+ private cachedOutputPath?;
134
+ private writeQueue;
135
+ constructor(config: LogConfig, logger?: any);
136
+ /**
137
+ * Start conversation logging
138
+ */
139
+ onConversationStart(metadata: Partial<ConversationLogMetadata>): void;
140
+ /**
141
+ * Log a message
142
+ */
143
+ onMessageAdded(message: ConversationMessage, metadata?: MessageLogMetadata): void;
144
+ /**
145
+ * Log a tool call
146
+ */
147
+ onToolCall(callId: string, toolName: string, iteration: number, args: any, result: any, duration: number, success: boolean, error?: string): void;
148
+ /**
149
+ * End conversation logging
150
+ */
151
+ onConversationEnd(_summary: ConversationSummary): void;
152
+ /**
153
+ * Save conversation to disk
154
+ */
155
+ save(): Promise<string>;
156
+ /**
157
+ * Get logged conversation object
158
+ */
159
+ getConversation(): LoggedConversation;
160
+ /**
161
+ * Generate unique conversation ID
162
+ */
163
+ private generateId;
164
+ /**
165
+ * Get output file path (cached for JSONL to avoid recalculation)
166
+ */
167
+ private getOutputPath;
168
+ /**
169
+ * Save as JSON
170
+ */
171
+ private saveAsJSON;
172
+ /**
173
+ * Save as Markdown
174
+ */
175
+ private saveAsMarkdown;
176
+ /**
177
+ * Append to JSONL file (streaming)
178
+ */
179
+ private appendToJSONL;
180
+ /**
181
+ * Redact sensitive content
182
+ */
183
+ private redactContent;
184
+ }
185
+ /**
186
+ * Replay options
187
+ */
188
+ export interface ReplayOptions {
189
+ model?: string;
190
+ maxIterations?: number;
191
+ retryFailedTools?: boolean;
192
+ toolTimeout?: number;
193
+ expectSimilarOutput?: boolean;
194
+ }
195
+ /**
196
+ * Replay result
197
+ */
198
+ export interface ReplayResult {
199
+ success: boolean;
200
+ conversation: LoggedConversation;
201
+ errors?: Error[];
202
+ }
203
+ /**
204
+ * Comparison result
205
+ */
206
+ export interface ComparisonResult {
207
+ messageDiff: number;
208
+ toolCallDiff: number;
209
+ tokenDiff?: number;
210
+ outputSimilarity: number;
211
+ costSavings?: number;
212
+ }
213
+ /**
214
+ * ConversationReplayer loads and replays logged conversations.
215
+ *
216
+ * Features:
217
+ * - Load from various formats
218
+ * - Replay conversations
219
+ * - Compare replays with originals
220
+ * - Export to different formats
221
+ *
222
+ * @example
223
+ * ```typescript
224
+ * const replayer = await ConversationReplayer.load('logs/conv.json');
225
+ *
226
+ * console.log('Messages:', replayer.messages.length);
227
+ * console.log('Tool calls:', replayer.getToolCalls().length);
228
+ *
229
+ * const timeline = replayer.getTimeline();
230
+ * console.log('Events:', timeline.length);
231
+ * ```
232
+ */
233
+ export declare class ConversationReplayer {
234
+ private conversation;
235
+ private logger;
236
+ private constructor();
237
+ /**
238
+ * Load conversation from file
239
+ */
240
+ static load(filePath: string, logger?: any): Promise<ConversationReplayer>;
241
+ /**
242
+ * Load latest conversation from directory
243
+ */
244
+ static loadLatest(directory: string, logger?: any): Promise<ConversationReplayer>;
245
+ /**
246
+ * Get all messages
247
+ */
248
+ get messages(): LoggedMessage[];
249
+ /**
250
+ * Get conversation metadata
251
+ */
252
+ getMetadata(): ConversationLogMetadata;
253
+ /**
254
+ * Get tool calls
255
+ */
256
+ getToolCalls(): ToolCallLog[];
257
+ /**
258
+ * Get message at index
259
+ */
260
+ getMessageAt(index: number): LoggedMessage | undefined;
261
+ /**
262
+ * Get timeline of events
263
+ */
264
+ getTimeline(): TimelineEvent[];
265
+ /**
266
+ * Export to format
267
+ */
268
+ exportToFormat(format: LogFormat, outputPath: string): Promise<string>;
269
+ /**
270
+ * Export as markdown
271
+ */
272
+ private exportMarkdown;
273
+ }
274
+ /**
275
+ * Timeline event interface
276
+ */
277
+ interface TimelineEvent {
278
+ timestamp: string;
279
+ iteration: number;
280
+ type: string;
281
+ description: string;
282
+ duration?: number;
283
+ success?: boolean;
284
+ }
285
+ export default ConversationLogger;