@riotprompt/riotprompt 0.0.9 → 0.0.10
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/BUG-ANALYSIS.md +523 -0
- package/CODE-REVIEW-SUMMARY.md +330 -0
- package/FIXES-APPLIED.md +437 -0
- package/dist/chat.d.ts +1 -1
- package/dist/chat.js +2 -5
- package/dist/chat.js.map +1 -1
- package/dist/constants.js +1 -2
- package/dist/constants.js.map +1 -1
- package/dist/context-manager.d.ts +3 -2
- package/dist/context-manager.js +29 -6
- package/dist/context-manager.js.map +1 -1
- package/dist/conversation-logger.d.ts +3 -1
- package/dist/conversation-logger.js +41 -4
- package/dist/conversation-logger.js.map +1 -1
- package/dist/conversation.d.ts +8 -2
- package/dist/conversation.js +36 -9
- package/dist/conversation.js.map +1 -1
- package/dist/items/section.js +3 -3
- package/dist/items/section.js.map +1 -1
- package/dist/iteration-strategy.d.ts +2 -0
- package/dist/iteration-strategy.js +40 -6
- package/dist/iteration-strategy.js.map +1 -1
- package/dist/loader.js +18 -3
- package/dist/loader.js.map +1 -1
- package/dist/message-builder.js +4 -2
- package/dist/message-builder.js.map +1 -1
- package/dist/model-config.d.ts +115 -0
- package/dist/model-config.js +205 -0
- package/dist/model-config.js.map +1 -0
- package/dist/override.js +5 -1
- package/dist/override.js.map +1 -1
- package/dist/parser.js +3 -3
- package/dist/parser.js.map +1 -1
- package/dist/recipes.d.ts +1 -1
- package/dist/recipes.js +4 -4
- package/dist/recipes.js.map +1 -1
- package/dist/reflection.js +5 -2
- package/dist/reflection.js.map +1 -1
- package/dist/riotprompt.cjs +439 -94
- package/dist/riotprompt.cjs.map +1 -1
- package/dist/riotprompt.d.ts +2 -0
- package/dist/riotprompt.js +1 -0
- package/dist/riotprompt.js.map +1 -1
- package/dist/token-budget.d.ts +2 -2
- package/dist/token-budget.js +23 -26
- package/dist/token-budget.js.map +1 -1
- package/dist/util/general.js +1 -1
- package/dist/util/general.js.map +1 -1
- package/package.json +1 -1
package/dist/riotprompt.cjs
CHANGED
|
@@ -128,7 +128,7 @@ const create$8 = (options = {})=>{
|
|
|
128
128
|
};
|
|
129
129
|
if (Array.isArray(item)) {
|
|
130
130
|
item.forEach((item)=>{
|
|
131
|
-
append(item);
|
|
131
|
+
append(item, options); // Propagate options to array items
|
|
132
132
|
});
|
|
133
133
|
} else {
|
|
134
134
|
if (typeof item === 'string') {
|
|
@@ -147,7 +147,7 @@ const create$8 = (options = {})=>{
|
|
|
147
147
|
};
|
|
148
148
|
if (Array.isArray(item)) {
|
|
149
149
|
item.forEach((item)=>{
|
|
150
|
-
prepend(item);
|
|
150
|
+
prepend(item, options); // Propagate options to array items
|
|
151
151
|
});
|
|
152
152
|
} else {
|
|
153
153
|
if (typeof item === 'string') {
|
|
@@ -166,7 +166,7 @@ const create$8 = (options = {})=>{
|
|
|
166
166
|
};
|
|
167
167
|
if (Array.isArray(item)) {
|
|
168
168
|
item.forEach((item)=>{
|
|
169
|
-
insert(index, item);
|
|
169
|
+
insert(index, item, options); // Propagate options to array items
|
|
170
170
|
});
|
|
171
171
|
} else {
|
|
172
172
|
if (typeof item === 'string') {
|
|
@@ -243,7 +243,6 @@ const create$6 = ({ persona, instructions, contents, contexts })=>{
|
|
|
243
243
|
|
|
244
244
|
const DEFAULT_CHARACTER_ENCODING = "utf8";
|
|
245
245
|
const LIBRARY_NAME = "riotprompt";
|
|
246
|
-
const DEFAULT_PERSONA_ROLE = "developer";
|
|
247
246
|
const DEFAULT_IGNORE_PATTERNS = [
|
|
248
247
|
"^\\..*",
|
|
249
248
|
"\\.(jpg|jpeg|png|gif|bmp|svg|webp|ico)$",
|
|
@@ -262,29 +261,6 @@ const DEFAULT_FORMAT_OPTIONS = {
|
|
|
262
261
|
sectionDepth: 0
|
|
263
262
|
};
|
|
264
263
|
|
|
265
|
-
const getPersonaRole = (model)=>{
|
|
266
|
-
if (model === "gpt-4o" || model === "gpt-4o-mini") {
|
|
267
|
-
return "system";
|
|
268
|
-
}
|
|
269
|
-
return DEFAULT_PERSONA_ROLE;
|
|
270
|
-
};
|
|
271
|
-
const createRequest = (model)=>{
|
|
272
|
-
const messages = [];
|
|
273
|
-
return {
|
|
274
|
-
model,
|
|
275
|
-
messages,
|
|
276
|
-
addMessage: (message)=>{
|
|
277
|
-
messages.push(message);
|
|
278
|
-
}
|
|
279
|
-
};
|
|
280
|
-
};
|
|
281
|
-
|
|
282
|
-
const chat = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
283
|
-
__proto__: null,
|
|
284
|
-
createRequest,
|
|
285
|
-
getPersonaRole
|
|
286
|
-
}, Symbol.toStringTag, { value: 'Module' }));
|
|
287
|
-
|
|
288
264
|
const DEFAULT_LOGGER = {
|
|
289
265
|
name: 'default',
|
|
290
266
|
debug: (message, ...args)=>console.debug(message, ...args),
|
|
@@ -329,6 +305,227 @@ const wrapLogger = (toWrap, name)=>{
|
|
|
329
305
|
};
|
|
330
306
|
};
|
|
331
307
|
|
|
308
|
+
function _define_property$8(obj, key, value) {
|
|
309
|
+
if (key in obj) {
|
|
310
|
+
Object.defineProperty(obj, key, {
|
|
311
|
+
value: value,
|
|
312
|
+
enumerable: true,
|
|
313
|
+
configurable: true,
|
|
314
|
+
writable: true
|
|
315
|
+
});
|
|
316
|
+
} else {
|
|
317
|
+
obj[key] = value;
|
|
318
|
+
}
|
|
319
|
+
return obj;
|
|
320
|
+
}
|
|
321
|
+
/**
|
|
322
|
+
* Model registry for managing model configurations
|
|
323
|
+
*/ class ModelRegistry {
|
|
324
|
+
/**
|
|
325
|
+
* Register default model configurations
|
|
326
|
+
*/ registerDefaults() {
|
|
327
|
+
// GPT-4 family (uses 'system' role)
|
|
328
|
+
this.register({
|
|
329
|
+
pattern: /^gpt-4/i,
|
|
330
|
+
personaRole: 'system',
|
|
331
|
+
encoding: 'gpt-4o',
|
|
332
|
+
supportsToolCalls: true,
|
|
333
|
+
family: 'gpt-4',
|
|
334
|
+
description: 'GPT-4 family models'
|
|
335
|
+
});
|
|
336
|
+
// O-series models (uses 'developer' role)
|
|
337
|
+
this.register({
|
|
338
|
+
pattern: /^o\d+/i,
|
|
339
|
+
personaRole: 'developer',
|
|
340
|
+
encoding: 'gpt-4o',
|
|
341
|
+
supportsToolCalls: true,
|
|
342
|
+
family: 'o-series',
|
|
343
|
+
description: 'O-series reasoning models'
|
|
344
|
+
});
|
|
345
|
+
// Claude family (uses 'system' role)
|
|
346
|
+
this.register({
|
|
347
|
+
pattern: /^claude/i,
|
|
348
|
+
personaRole: 'system',
|
|
349
|
+
encoding: 'cl100k_base',
|
|
350
|
+
supportsToolCalls: true,
|
|
351
|
+
family: 'claude',
|
|
352
|
+
description: 'Claude family models'
|
|
353
|
+
});
|
|
354
|
+
// Default fallback
|
|
355
|
+
this.register({
|
|
356
|
+
pattern: /.*/,
|
|
357
|
+
personaRole: 'system',
|
|
358
|
+
encoding: 'gpt-4o',
|
|
359
|
+
supportsToolCalls: true,
|
|
360
|
+
family: 'unknown',
|
|
361
|
+
description: 'Default fallback configuration'
|
|
362
|
+
});
|
|
363
|
+
this.logger.debug('Registered default model configurations');
|
|
364
|
+
}
|
|
365
|
+
/**
|
|
366
|
+
* Register a model configuration
|
|
367
|
+
* Configs are checked in registration order (first match wins)
|
|
368
|
+
*/ register(config) {
|
|
369
|
+
var _config_pattern;
|
|
370
|
+
// Validate config
|
|
371
|
+
if (!config.pattern && !config.exactMatch) {
|
|
372
|
+
throw new Error('Model config must have either pattern or exactMatch');
|
|
373
|
+
}
|
|
374
|
+
this.configs.push(config);
|
|
375
|
+
this.cache.clear(); // Clear cache when new config is added
|
|
376
|
+
this.logger.debug('Registered model config', {
|
|
377
|
+
family: config.family,
|
|
378
|
+
pattern: (_config_pattern = config.pattern) === null || _config_pattern === void 0 ? void 0 : _config_pattern.source,
|
|
379
|
+
exactMatch: config.exactMatch
|
|
380
|
+
});
|
|
381
|
+
}
|
|
382
|
+
/**
|
|
383
|
+
* Get configuration for a model
|
|
384
|
+
*/ getConfig(model) {
|
|
385
|
+
// Check cache first
|
|
386
|
+
if (this.cache.has(model)) {
|
|
387
|
+
return this.cache.get(model);
|
|
388
|
+
}
|
|
389
|
+
// Find matching config (first match wins)
|
|
390
|
+
for (const config of this.configs){
|
|
391
|
+
if (config.exactMatch && config.exactMatch === model) {
|
|
392
|
+
this.cache.set(model, config);
|
|
393
|
+
return config;
|
|
394
|
+
}
|
|
395
|
+
if (config.pattern && config.pattern.test(model)) {
|
|
396
|
+
this.cache.set(model, config);
|
|
397
|
+
return config;
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
// Should never happen due to default fallback, but just in case
|
|
401
|
+
throw new Error(`No configuration found for model: ${model}`);
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Get persona role for a model
|
|
405
|
+
*/ getPersonaRole(model) {
|
|
406
|
+
return this.getConfig(model).personaRole;
|
|
407
|
+
}
|
|
408
|
+
/**
|
|
409
|
+
* Get tokenizer encoding for a model
|
|
410
|
+
*/ getEncoding(model) {
|
|
411
|
+
return this.getConfig(model).encoding;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Check if model supports tool calls
|
|
415
|
+
*/ supportsToolCalls(model) {
|
|
416
|
+
var _this_getConfig_supportsToolCalls;
|
|
417
|
+
return (_this_getConfig_supportsToolCalls = this.getConfig(model).supportsToolCalls) !== null && _this_getConfig_supportsToolCalls !== void 0 ? _this_getConfig_supportsToolCalls : true;
|
|
418
|
+
}
|
|
419
|
+
/**
|
|
420
|
+
* Get model family
|
|
421
|
+
*/ getFamily(model) {
|
|
422
|
+
return this.getConfig(model).family;
|
|
423
|
+
}
|
|
424
|
+
/**
|
|
425
|
+
* Clear all registered configs and reset to defaults
|
|
426
|
+
*/ reset() {
|
|
427
|
+
this.configs = [];
|
|
428
|
+
this.cache.clear();
|
|
429
|
+
this.registerDefaults();
|
|
430
|
+
this.logger.debug('Reset model configurations to defaults');
|
|
431
|
+
}
|
|
432
|
+
/**
|
|
433
|
+
* Clear cache (useful if configs are modified)
|
|
434
|
+
*/ clearCache() {
|
|
435
|
+
this.cache.clear();
|
|
436
|
+
this.logger.debug('Cleared model configuration cache');
|
|
437
|
+
}
|
|
438
|
+
/**
|
|
439
|
+
* Get all registered configurations
|
|
440
|
+
*/ getAllConfigs() {
|
|
441
|
+
return [
|
|
442
|
+
...this.configs
|
|
443
|
+
];
|
|
444
|
+
}
|
|
445
|
+
constructor(logger){
|
|
446
|
+
_define_property$8(this, "configs", void 0);
|
|
447
|
+
_define_property$8(this, "cache", void 0);
|
|
448
|
+
_define_property$8(this, "logger", void 0);
|
|
449
|
+
this.configs = [];
|
|
450
|
+
this.cache = new Map();
|
|
451
|
+
this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ModelRegistry');
|
|
452
|
+
// Register default configurations
|
|
453
|
+
this.registerDefaults();
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
// Global registry instance
|
|
457
|
+
let globalRegistry = null;
|
|
458
|
+
/**
|
|
459
|
+
* Get the global model registry
|
|
460
|
+
*/ function getModelRegistry(logger) {
|
|
461
|
+
if (!globalRegistry) {
|
|
462
|
+
globalRegistry = new ModelRegistry(logger);
|
|
463
|
+
}
|
|
464
|
+
return globalRegistry;
|
|
465
|
+
}
|
|
466
|
+
/**
|
|
467
|
+
* Reset the global registry (useful for testing)
|
|
468
|
+
*/ function resetModelRegistry() {
|
|
469
|
+
globalRegistry = null;
|
|
470
|
+
}
|
|
471
|
+
/**
|
|
472
|
+
* Helper functions using global registry
|
|
473
|
+
*/ function getPersonaRole$1(model) {
|
|
474
|
+
return getModelRegistry().getPersonaRole(model);
|
|
475
|
+
}
|
|
476
|
+
function getEncoding(model) {
|
|
477
|
+
return getModelRegistry().getEncoding(model);
|
|
478
|
+
}
|
|
479
|
+
function supportsToolCalls(model) {
|
|
480
|
+
return getModelRegistry().supportsToolCalls(model);
|
|
481
|
+
}
|
|
482
|
+
function getModelFamily(model) {
|
|
483
|
+
return getModelRegistry().getFamily(model);
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Configure a custom model
|
|
487
|
+
*
|
|
488
|
+
* @example
|
|
489
|
+
* ```typescript
|
|
490
|
+
* // Add support for a new model family
|
|
491
|
+
* configureModel({
|
|
492
|
+
* pattern: /^gemini/i,
|
|
493
|
+
* personaRole: 'system',
|
|
494
|
+
* encoding: 'cl100k_base',
|
|
495
|
+
* family: 'gemini'
|
|
496
|
+
* });
|
|
497
|
+
*
|
|
498
|
+
* // Add specific model override
|
|
499
|
+
* configureModel({
|
|
500
|
+
* exactMatch: 'custom-model-v1',
|
|
501
|
+
* personaRole: 'developer',
|
|
502
|
+
* encoding: 'gpt-4o'
|
|
503
|
+
* });
|
|
504
|
+
* ```
|
|
505
|
+
*/ function configureModel(config) {
|
|
506
|
+
getModelRegistry().register(config);
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
const getPersonaRole = (model)=>{
|
|
510
|
+
return getPersonaRole$1(model);
|
|
511
|
+
};
|
|
512
|
+
const createRequest = (model)=>{
|
|
513
|
+
const messages = [];
|
|
514
|
+
return {
|
|
515
|
+
model,
|
|
516
|
+
messages,
|
|
517
|
+
addMessage: (message)=>{
|
|
518
|
+
messages.push(message);
|
|
519
|
+
}
|
|
520
|
+
};
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
const chat = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
|
|
524
|
+
__proto__: null,
|
|
525
|
+
createRequest,
|
|
526
|
+
getPersonaRole
|
|
527
|
+
}, Symbol.toStringTag, { value: 'Module' }));
|
|
528
|
+
|
|
332
529
|
const clean = (obj)=>{
|
|
333
530
|
return Object.fromEntries(Object.entries(obj).filter(([_, v])=>v !== undefined));
|
|
334
531
|
};
|
|
@@ -343,7 +540,7 @@ const stringifyJSON = function(obj, visited = new Set()) {
|
|
|
343
540
|
return '"(circular)"';
|
|
344
541
|
} else if (Array.isArray(obj)) {
|
|
345
542
|
//check for empty array
|
|
346
|
-
if (obj
|
|
543
|
+
if (obj.length === 0) return '[]';
|
|
347
544
|
else {
|
|
348
545
|
// Add array to visited before processing its elements
|
|
349
546
|
visited.add(obj);
|
|
@@ -807,13 +1004,13 @@ const create$4 = (parserOptions)=>{
|
|
|
807
1004
|
});
|
|
808
1005
|
} catch (error) {
|
|
809
1006
|
// Log the error or handle it appropriately
|
|
810
|
-
logger.error(`Error reading or parsing file
|
|
811
|
-
throw new Error(`Failed to parse
|
|
1007
|
+
logger.error(`Error reading or parsing file at ${filePath}:`, error);
|
|
1008
|
+
throw new Error(`Failed to parse content from ${filePath}: ${error instanceof Error ? error.message : String(error)}`);
|
|
812
1009
|
}
|
|
813
1010
|
};
|
|
814
1011
|
/**
|
|
815
1012
|
* Reads Markdown content and parses it into a single Section.
|
|
816
|
-
*
|
|
1013
|
+
*
|
|
817
1014
|
* - If the content starts with a heading, that becomes the title of the returned Section
|
|
818
1015
|
* - If no heading at the start, creates a Section with no title
|
|
819
1016
|
* - Headers within the content create nested sections based on their depth
|
|
@@ -1017,7 +1214,7 @@ const create$2 = (loaderOptions)=>{
|
|
|
1017
1214
|
};
|
|
1018
1215
|
/**
|
|
1019
1216
|
* Loads context from the provided directories and returns instruction sections
|
|
1020
|
-
*
|
|
1217
|
+
*
|
|
1021
1218
|
* @param contextDirectories Directories containing context files
|
|
1022
1219
|
* @returns Array of instruction sections loaded from context directories
|
|
1023
1220
|
*/ const load = async (contextDirectories = [], options = {})=>{
|
|
@@ -1069,8 +1266,22 @@ const create$2 = (loaderOptions)=>{
|
|
|
1069
1266
|
}
|
|
1070
1267
|
// Get all other files in the directory
|
|
1071
1268
|
const files = await storage.listFiles(contextDir);
|
|
1072
|
-
const ignorePatternsRegex = ignorePatterns.map((pattern)=>
|
|
1073
|
-
|
|
1269
|
+
const ignorePatternsRegex = ignorePatterns.map((pattern)=>{
|
|
1270
|
+
try {
|
|
1271
|
+
return new RegExp(pattern, 'i');
|
|
1272
|
+
} catch (error) {
|
|
1273
|
+
logger.error(`Invalid ignore pattern: ${pattern}`, {
|
|
1274
|
+
error
|
|
1275
|
+
});
|
|
1276
|
+
// Return a pattern that matches nothing
|
|
1277
|
+
return /(?!)/; // Negative lookahead that always fails
|
|
1278
|
+
}
|
|
1279
|
+
});
|
|
1280
|
+
const filteredFiles = files.filter((file)=>{
|
|
1281
|
+
const fullPath = path.join(contextDir, file);
|
|
1282
|
+
// Test against both filename and full path for flexibility
|
|
1283
|
+
return !ignorePatternsRegex.some((regex)=>regex.test(file) || regex.test(fullPath));
|
|
1284
|
+
});
|
|
1074
1285
|
for (const file of filteredFiles){
|
|
1075
1286
|
// Skip the context.md file as it's already processed
|
|
1076
1287
|
if (file === 'context.md') continue;
|
|
@@ -1098,6 +1309,7 @@ const create$2 = (loaderOptions)=>{
|
|
|
1098
1309
|
...sectionOptions
|
|
1099
1310
|
});
|
|
1100
1311
|
// Add this file section to the main context section
|
|
1312
|
+
// Type is correct - Section.add() accepts Section<T>
|
|
1101
1313
|
mainContextSection.add(fileSection, {
|
|
1102
1314
|
...sectionOptions
|
|
1103
1315
|
});
|
|
@@ -1213,7 +1425,11 @@ const create$1 = (overrideOptions = {})=>{
|
|
|
1213
1425
|
finalSection = finalSection.prepend(prepend);
|
|
1214
1426
|
}
|
|
1215
1427
|
// Apply appends in reverse order (furthest layers first, then closest)
|
|
1216
|
-
|
|
1428
|
+
// Create a copy to avoid mutating the original array
|
|
1429
|
+
const reversedAppends = [
|
|
1430
|
+
...appends
|
|
1431
|
+
].reverse();
|
|
1432
|
+
for (const append of reversedAppends){
|
|
1217
1433
|
logger.silly('Append found, adding to content from file %s', append);
|
|
1218
1434
|
finalSection = finalSection.append(append);
|
|
1219
1435
|
}
|
|
@@ -1422,10 +1638,17 @@ function _define_property$7(obj, key, value) {
|
|
|
1422
1638
|
* ```
|
|
1423
1639
|
*/ class ContextManager {
|
|
1424
1640
|
/**
|
|
1425
|
-
* Track a context item
|
|
1641
|
+
* Track a context item (with deduplication by content hash for items without ID)
|
|
1426
1642
|
*/ track(item, position) {
|
|
1427
|
-
const id = item.id || this.generateId();
|
|
1428
1643
|
const hash = this.hashContent(item.content);
|
|
1644
|
+
// If item has no ID and we already have this content hash, skip tracking
|
|
1645
|
+
if (!item.id && this.hashes.has(hash)) {
|
|
1646
|
+
this.logger.debug('Skipping duplicate context item by hash', {
|
|
1647
|
+
hash
|
|
1648
|
+
});
|
|
1649
|
+
return;
|
|
1650
|
+
}
|
|
1651
|
+
const id = item.id || this.generateId();
|
|
1429
1652
|
const trackedItem = {
|
|
1430
1653
|
...item,
|
|
1431
1654
|
id,
|
|
@@ -1456,7 +1679,16 @@ function _define_property$7(obj, key, value) {
|
|
|
1456
1679
|
}
|
|
1457
1680
|
/**
|
|
1458
1681
|
* Check if similar content exists (fuzzy match)
|
|
1459
|
-
|
|
1682
|
+
* Uses similarity threshold to avoid overly aggressive deduplication
|
|
1683
|
+
*/ hasSimilarContent(content, similarityThreshold = 0.9) {
|
|
1684
|
+
// Warn if checking against a large number of items (performance consideration)
|
|
1685
|
+
const MAX_ITEMS_WARNING = 1000;
|
|
1686
|
+
if (this.items.size > MAX_ITEMS_WARNING) {
|
|
1687
|
+
this.logger.warn('Large number of context items, similarity check may be slow', {
|
|
1688
|
+
count: this.items.size,
|
|
1689
|
+
threshold: MAX_ITEMS_WARNING
|
|
1690
|
+
});
|
|
1691
|
+
}
|
|
1460
1692
|
const normalized = this.normalizeContent(content);
|
|
1461
1693
|
for (const item of this.items.values()){
|
|
1462
1694
|
const itemNormalized = this.normalizeContent(item.content || '');
|
|
@@ -1464,9 +1696,16 @@ function _define_property$7(obj, key, value) {
|
|
|
1464
1696
|
if (normalized === itemNormalized) {
|
|
1465
1697
|
return true;
|
|
1466
1698
|
}
|
|
1467
|
-
//
|
|
1468
|
-
|
|
1469
|
-
|
|
1699
|
+
// Calculate similarity ratio (Jaccard-like)
|
|
1700
|
+
const longer = normalized.length > itemNormalized.length ? normalized : itemNormalized;
|
|
1701
|
+
const shorter = normalized.length <= itemNormalized.length ? normalized : itemNormalized;
|
|
1702
|
+
// Only consider substring match if the shorter is at least 90% of longer
|
|
1703
|
+
const lengthRatio = shorter.length / longer.length;
|
|
1704
|
+
if (lengthRatio >= similarityThreshold) {
|
|
1705
|
+
// Check if one is contained in the other
|
|
1706
|
+
if (longer.includes(shorter)) {
|
|
1707
|
+
return true;
|
|
1708
|
+
}
|
|
1470
1709
|
}
|
|
1471
1710
|
}
|
|
1472
1711
|
return false;
|
|
@@ -1638,6 +1877,8 @@ function _define_property$6(obj, key, value) {
|
|
|
1638
1877
|
...metadata,
|
|
1639
1878
|
startTime: this.startTime
|
|
1640
1879
|
};
|
|
1880
|
+
// Reset cached output path to prevent file collision if logger is reused
|
|
1881
|
+
this.cachedOutputPath = undefined;
|
|
1641
1882
|
this.logger.debug('Conversation logging started', {
|
|
1642
1883
|
id: this.conversationId
|
|
1643
1884
|
});
|
|
@@ -1660,9 +1901,21 @@ function _define_property$6(obj, key, value) {
|
|
|
1660
1901
|
metadata
|
|
1661
1902
|
};
|
|
1662
1903
|
this.messages.push(loggedMessage);
|
|
1663
|
-
// For JSONL format, append immediately
|
|
1904
|
+
// For JSONL format, append immediately with write queue
|
|
1664
1905
|
if (this.config.format === 'jsonl') {
|
|
1665
|
-
this.appendToJSONL(loggedMessage).catch(
|
|
1906
|
+
this.writeQueue = this.writeQueue.then(()=>this.appendToJSONL(loggedMessage)).catch((error)=>{
|
|
1907
|
+
this.logger.error('Failed to write JSONL message', {
|
|
1908
|
+
error
|
|
1909
|
+
});
|
|
1910
|
+
try {
|
|
1911
|
+
var _this_config_onError, _this_config;
|
|
1912
|
+
(_this_config_onError = (_this_config = this.config).onError) === null || _this_config_onError === void 0 ? void 0 : _this_config_onError.call(_this_config, error);
|
|
1913
|
+
} catch (callbackError) {
|
|
1914
|
+
this.logger.error('onError callback failed', {
|
|
1915
|
+
callbackError
|
|
1916
|
+
});
|
|
1917
|
+
}
|
|
1918
|
+
});
|
|
1666
1919
|
}
|
|
1667
1920
|
}
|
|
1668
1921
|
/**
|
|
@@ -1744,8 +1997,11 @@ function _define_property$6(obj, key, value) {
|
|
|
1744
1997
|
return `conv-${timestamp}-${random}`;
|
|
1745
1998
|
}
|
|
1746
1999
|
/**
|
|
1747
|
-
* Get output file path
|
|
2000
|
+
* Get output file path (cached for JSONL to avoid recalculation)
|
|
1748
2001
|
*/ async getOutputPath() {
|
|
2002
|
+
if (this.cachedOutputPath) {
|
|
2003
|
+
return this.cachedOutputPath;
|
|
2004
|
+
}
|
|
1749
2005
|
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
|
|
1750
2006
|
const filename = this.config.filenameTemplate.replace('{timestamp}', timestamp).replace('{id}', this.conversationId).replace('{template}', this.metadata.template || 'default');
|
|
1751
2007
|
const ext = this.config.format === 'markdown' ? '.md' : '.json';
|
|
@@ -1754,6 +2010,10 @@ function _define_property$6(obj, key, value) {
|
|
|
1754
2010
|
await fs.mkdir(path.dirname(fullPath), {
|
|
1755
2011
|
recursive: true
|
|
1756
2012
|
});
|
|
2013
|
+
// Cache path for JSONL format to ensure consistent file writes
|
|
2014
|
+
if (this.config.format === 'jsonl') {
|
|
2015
|
+
this.cachedOutputPath = fullPath;
|
|
2016
|
+
}
|
|
1757
2017
|
return fullPath;
|
|
1758
2018
|
}
|
|
1759
2019
|
/**
|
|
@@ -1844,6 +2104,8 @@ function _define_property$6(obj, key, value) {
|
|
|
1844
2104
|
_define_property$6(this, "startTime", void 0);
|
|
1845
2105
|
_define_property$6(this, "logger", void 0);
|
|
1846
2106
|
_define_property$6(this, "messageIndex", void 0);
|
|
2107
|
+
_define_property$6(this, "cachedOutputPath", void 0);
|
|
2108
|
+
_define_property$6(this, "writeQueue", Promise.resolve());
|
|
1847
2109
|
this.config = {
|
|
1848
2110
|
outputPath: 'logs/conversations',
|
|
1849
2111
|
format: 'json',
|
|
@@ -1960,12 +2222,26 @@ function _define_property$6(obj, key, value) {
|
|
|
1960
2222
|
for (const msg of this.conversation.messages){
|
|
1961
2223
|
if (msg.tool_calls) {
|
|
1962
2224
|
for (const call of msg.tool_calls){
|
|
2225
|
+
// Parse arguments with error handling
|
|
2226
|
+
let parsedArgs;
|
|
2227
|
+
try {
|
|
2228
|
+
parsedArgs = JSON.parse(call.function.arguments);
|
|
2229
|
+
} catch (error) {
|
|
2230
|
+
this.logger.warn('Failed to parse tool call arguments', {
|
|
2231
|
+
callId: call.id,
|
|
2232
|
+
error: error instanceof Error ? error.message : String(error)
|
|
2233
|
+
});
|
|
2234
|
+
parsedArgs = {
|
|
2235
|
+
__parse_error: true,
|
|
2236
|
+
raw: call.function.arguments
|
|
2237
|
+
};
|
|
2238
|
+
}
|
|
1963
2239
|
toolCalls.push({
|
|
1964
2240
|
callId: call.id,
|
|
1965
2241
|
toolName: call.function.name,
|
|
1966
2242
|
timestamp: msg.timestamp,
|
|
1967
2243
|
iteration: 0,
|
|
1968
|
-
arguments:
|
|
2244
|
+
arguments: parsedArgs,
|
|
1969
2245
|
result: null,
|
|
1970
2246
|
duration: 0,
|
|
1971
2247
|
success: true
|
|
@@ -2214,8 +2490,9 @@ function _define_property$5(obj, key, value) {
|
|
|
2214
2490
|
const message = this.build();
|
|
2215
2491
|
// Handle model-specific role requirements
|
|
2216
2492
|
if (this.semanticRole === 'system') {
|
|
2217
|
-
//
|
|
2218
|
-
|
|
2493
|
+
// Use model registry to determine correct role
|
|
2494
|
+
const personaRole = getPersonaRole$1(model);
|
|
2495
|
+
if (personaRole === 'developer') {
|
|
2219
2496
|
message.role = 'developer';
|
|
2220
2497
|
}
|
|
2221
2498
|
}
|
|
@@ -2385,19 +2662,16 @@ function _define_property$4(obj, key, value) {
|
|
|
2385
2662
|
return Math.max(500, Math.floor(inputTokens * 0.2));
|
|
2386
2663
|
}
|
|
2387
2664
|
/**
|
|
2388
|
-
* Map RiotPrompt model to Tiktoken model
|
|
2665
|
+
* Map RiotPrompt model to Tiktoken model using model registry
|
|
2389
2666
|
*/ mapToTiktokenModel(model) {
|
|
2390
|
-
|
|
2667
|
+
const encoding = getEncoding(model);
|
|
2668
|
+
// Map our encoding types to tiktoken models
|
|
2669
|
+
switch(encoding){
|
|
2391
2670
|
case 'gpt-4o':
|
|
2392
|
-
case '
|
|
2393
|
-
return 'gpt-4o';
|
|
2394
|
-
case 'o1-preview':
|
|
2395
|
-
case 'o1-mini':
|
|
2396
|
-
case 'o1':
|
|
2397
|
-
case 'o3-mini':
|
|
2398
|
-
case 'o1-pro':
|
|
2399
|
-
// O1 models use gpt-4o tokenization
|
|
2671
|
+
case 'o200k_base':
|
|
2400
2672
|
return 'gpt-4o';
|
|
2673
|
+
case 'cl100k_base':
|
|
2674
|
+
return 'gpt-3.5-turbo';
|
|
2401
2675
|
default:
|
|
2402
2676
|
return 'gpt-4o';
|
|
2403
2677
|
}
|
|
@@ -2564,16 +2838,16 @@ function _define_property$4(obj, key, value) {
|
|
|
2564
2838
|
return kept.map((item)=>item.message);
|
|
2565
2839
|
}
|
|
2566
2840
|
/**
|
|
2567
|
-
* Compress using FIFO (remove oldest first)
|
|
2841
|
+
* Compress using FIFO (remove oldest first) - optimized with Set
|
|
2568
2842
|
*/ compressFIFO(messages, targetTokens) {
|
|
2569
2843
|
var _this_config_preserveRecent;
|
|
2570
|
-
const
|
|
2844
|
+
const preservedSet = new Set();
|
|
2571
2845
|
let totalTokens = 0;
|
|
2572
2846
|
// Always preserve system messages if configured
|
|
2573
2847
|
const systemMessages = messages.filter((m)=>m.role === 'system');
|
|
2574
2848
|
if (this.config.preserveSystem) {
|
|
2575
2849
|
for (const msg of systemMessages){
|
|
2576
|
-
|
|
2850
|
+
preservedSet.add(msg);
|
|
2577
2851
|
totalTokens += this.counter.countMessage(msg);
|
|
2578
2852
|
}
|
|
2579
2853
|
}
|
|
@@ -2581,28 +2855,28 @@ function _define_property$4(obj, key, value) {
|
|
|
2581
2855
|
const recentCount = (_this_config_preserveRecent = this.config.preserveRecent) !== null && _this_config_preserveRecent !== void 0 ? _this_config_preserveRecent : 3;
|
|
2582
2856
|
const recentMessages = messages.slice(-recentCount).filter((m)=>m.role !== 'system');
|
|
2583
2857
|
for (const msg of recentMessages){
|
|
2584
|
-
if (!
|
|
2858
|
+
if (!preservedSet.has(msg)) {
|
|
2585
2859
|
const tokens = this.counter.countMessage(msg);
|
|
2586
2860
|
if (totalTokens + tokens <= targetTokens) {
|
|
2587
|
-
|
|
2861
|
+
preservedSet.add(msg);
|
|
2588
2862
|
totalTokens += tokens;
|
|
2589
2863
|
}
|
|
2590
2864
|
}
|
|
2591
2865
|
}
|
|
2592
2866
|
// Add older messages if space available
|
|
2593
|
-
const otherMessages = messages.filter((m)=>!
|
|
2867
|
+
const otherMessages = messages.filter((m)=>!preservedSet.has(m) && m.role !== 'system');
|
|
2594
2868
|
for(let i = otherMessages.length - 1; i >= 0; i--){
|
|
2595
2869
|
const msg = otherMessages[i];
|
|
2596
2870
|
const tokens = this.counter.countMessage(msg);
|
|
2597
2871
|
if (totalTokens + tokens <= targetTokens) {
|
|
2598
|
-
|
|
2872
|
+
preservedSet.add(msg);
|
|
2599
2873
|
totalTokens += tokens;
|
|
2600
2874
|
} else {
|
|
2601
2875
|
break;
|
|
2602
2876
|
}
|
|
2603
2877
|
}
|
|
2604
|
-
// Sort to maintain conversation order
|
|
2605
|
-
return messages.filter((m)=>
|
|
2878
|
+
// Sort to maintain conversation order - use Set for O(1) lookup
|
|
2879
|
+
return messages.filter((m)=>preservedSet.has(m));
|
|
2606
2880
|
}
|
|
2607
2881
|
/**
|
|
2608
2882
|
* Adaptive compression based on conversation phase
|
|
@@ -2614,13 +2888,12 @@ function _define_property$4(obj, key, value) {
|
|
|
2614
2888
|
}
|
|
2615
2889
|
// Mid phase: moderate compression
|
|
2616
2890
|
if (messageCount <= 15) {
|
|
2617
|
-
//
|
|
2618
|
-
const
|
|
2619
|
-
|
|
2620
|
-
|
|
2621
|
-
|
|
2622
|
-
|
|
2623
|
-
return tempManager.compressFIFO(messages, targetTokens);
|
|
2891
|
+
// Temporarily modify preserveRecent, then restore
|
|
2892
|
+
const originalPreserveRecent = this.config.preserveRecent;
|
|
2893
|
+
this.config.preserveRecent = 5;
|
|
2894
|
+
const result = this.compressFIFO(messages, targetTokens);
|
|
2895
|
+
this.config.preserveRecent = originalPreserveRecent;
|
|
2896
|
+
return result;
|
|
2624
2897
|
}
|
|
2625
2898
|
// Late phase: aggressive compression (priority-based)
|
|
2626
2899
|
return this.compressByPriority(messages, targetTokens);
|
|
@@ -2809,6 +3082,12 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
2809
3082
|
if (!this.budgetManager.canAddMessage(message, this.state.messages)) {
|
|
2810
3083
|
this.logger.warn('Budget exceeded, compressing conversation');
|
|
2811
3084
|
this.state.messages = this.budgetManager.compress(this.state.messages);
|
|
3085
|
+
// Re-check after compression and warn if still over budget
|
|
3086
|
+
if (!this.budgetManager.canAddMessage(message, this.state.messages)) {
|
|
3087
|
+
this.logger.warn('Token budget still exceeded after compression, adding message anyway');
|
|
3088
|
+
// Note: We add the message anyway to maintain backward compatibility
|
|
3089
|
+
// Consider setting onBudgetExceeded: 'error' in config if strict enforcement is needed
|
|
3090
|
+
}
|
|
2812
3091
|
}
|
|
2813
3092
|
}
|
|
2814
3093
|
this.state.messages.push(message);
|
|
@@ -2936,15 +3215,18 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
2936
3215
|
// Calculate position
|
|
2937
3216
|
const position = this.calculatePosition(opts.position);
|
|
2938
3217
|
// Format and inject
|
|
2939
|
-
for
|
|
3218
|
+
for(let i = 0; i < itemsToAdd.length; i++){
|
|
3219
|
+
const item = itemsToAdd[i];
|
|
2940
3220
|
const formatted = this.formatContextItem(item, opts.format);
|
|
2941
3221
|
const contextMessage = {
|
|
2942
3222
|
role: 'user',
|
|
2943
3223
|
content: formatted
|
|
2944
3224
|
};
|
|
2945
|
-
|
|
2946
|
-
|
|
2947
|
-
this.state.
|
|
3225
|
+
// Each item is inserted at position + index to maintain order
|
|
3226
|
+
const actualPosition = position + i;
|
|
3227
|
+
this.state.messages.splice(actualPosition, 0, contextMessage);
|
|
3228
|
+
// Track in context manager with correct position
|
|
3229
|
+
this.state.contextManager.track(item, actualPosition);
|
|
2948
3230
|
}
|
|
2949
3231
|
this.updateMetadata();
|
|
2950
3232
|
return this;
|
|
@@ -2997,10 +3279,16 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
2997
3279
|
};
|
|
2998
3280
|
}
|
|
2999
3281
|
/**
|
|
3000
|
-
* Export messages in OpenAI format
|
|
3282
|
+
* Export messages in OpenAI format (deep copy to prevent shared state)
|
|
3001
3283
|
*/ toMessages() {
|
|
3002
3284
|
return this.state.messages.map((msg)=>({
|
|
3003
|
-
...msg
|
|
3285
|
+
...msg,
|
|
3286
|
+
tool_calls: msg.tool_calls ? msg.tool_calls.map((tc)=>({
|
|
3287
|
+
...tc,
|
|
3288
|
+
function: {
|
|
3289
|
+
...tc.function
|
|
3290
|
+
}
|
|
3291
|
+
})) : undefined
|
|
3004
3292
|
}));
|
|
3005
3293
|
}
|
|
3006
3294
|
/**
|
|
@@ -3036,7 +3324,7 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
3036
3324
|
return builder;
|
|
3037
3325
|
}
|
|
3038
3326
|
/**
|
|
3039
|
-
* Clone the conversation for parallel exploration
|
|
3327
|
+
* Clone the conversation for parallel exploration (deep copy to prevent shared state)
|
|
3040
3328
|
*/ clone() {
|
|
3041
3329
|
this.logger.debug('Cloning conversation');
|
|
3042
3330
|
const cloned = ConversationBuilder.create({
|
|
@@ -3044,7 +3332,13 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
3044
3332
|
}, this.logger);
|
|
3045
3333
|
// Deep copy state (note: contextManager is already created in constructor)
|
|
3046
3334
|
cloned.state.messages = this.state.messages.map((msg)=>({
|
|
3047
|
-
...msg
|
|
3335
|
+
...msg,
|
|
3336
|
+
tool_calls: msg.tool_calls ? msg.tool_calls.map((tc)=>({
|
|
3337
|
+
...tc,
|
|
3338
|
+
function: {
|
|
3339
|
+
...tc.function
|
|
3340
|
+
}
|
|
3341
|
+
})) : undefined
|
|
3048
3342
|
}));
|
|
3049
3343
|
cloned.state.metadata = {
|
|
3050
3344
|
...this.state.metadata
|
|
@@ -3215,6 +3509,12 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
3215
3509
|
}
|
|
3216
3510
|
/**
|
|
3217
3511
|
* Calculate position for context injection
|
|
3512
|
+
*
|
|
3513
|
+
* Positions:
|
|
3514
|
+
* - 'end': After all messages
|
|
3515
|
+
* - 'before-last': Before the last message
|
|
3516
|
+
* - 'after-system': After the LAST system message (useful for models with multiple system messages)
|
|
3517
|
+
* - number: Specific index (clamped to valid range)
|
|
3218
3518
|
*/ calculatePosition(position) {
|
|
3219
3519
|
if (typeof position === 'number') {
|
|
3220
3520
|
return Math.max(0, Math.min(position, this.state.messages.length));
|
|
@@ -3226,7 +3526,7 @@ const ConversationBuilderConfigSchema = zod.z.object({
|
|
|
3226
3526
|
return Math.max(0, this.state.messages.length - 1);
|
|
3227
3527
|
case 'after-system':
|
|
3228
3528
|
{
|
|
3229
|
-
// Find last system message (reverse search
|
|
3529
|
+
// Find last system message (uses reverse search to find most recent system message)
|
|
3230
3530
|
let lastSystemIdx = -1;
|
|
3231
3531
|
for(let i = this.state.messages.length - 1; i >= 0; i--){
|
|
3232
3532
|
if (this.state.messages[i].role === 'system') {
|
|
@@ -3682,10 +3982,10 @@ function _define_property$1(obj, key, value) {
|
|
|
3682
3982
|
// Calculate token usage if model provided
|
|
3683
3983
|
let tokenUsage;
|
|
3684
3984
|
if (model) {
|
|
3985
|
+
let counter;
|
|
3685
3986
|
try {
|
|
3686
|
-
|
|
3987
|
+
counter = new TokenCounter(model);
|
|
3687
3988
|
const total = counter.countConversation(messages);
|
|
3688
|
-
counter.dispose();
|
|
3689
3989
|
tokenUsage = {
|
|
3690
3990
|
total,
|
|
3691
3991
|
systemPrompt: 0,
|
|
@@ -3697,6 +3997,9 @@ function _define_property$1(obj, key, value) {
|
|
|
3697
3997
|
this.logger.warn('Could not calculate token usage', {
|
|
3698
3998
|
error
|
|
3699
3999
|
});
|
|
4000
|
+
} finally{
|
|
4001
|
+
// Always dispose of the counter to prevent resource leaks
|
|
4002
|
+
counter === null || counter === void 0 ? void 0 : counter.dispose();
|
|
3700
4003
|
}
|
|
3701
4004
|
}
|
|
3702
4005
|
return {
|
|
@@ -4090,7 +4393,8 @@ function _define_property(obj, key, value) {
|
|
|
4090
4393
|
startTime,
|
|
4091
4394
|
insights: [],
|
|
4092
4395
|
findings: [],
|
|
4093
|
-
errors: []
|
|
4396
|
+
errors: [],
|
|
4397
|
+
toolFailures: new Map()
|
|
4094
4398
|
};
|
|
4095
4399
|
this.logger.info('Starting strategy execution', {
|
|
4096
4400
|
strategy: strategy.name
|
|
@@ -4130,10 +4434,6 @@ function _define_property(obj, key, value) {
|
|
|
4130
4434
|
});
|
|
4131
4435
|
const phaseResult = await this.executePhase(conversation, tools, phase, state, strategy);
|
|
4132
4436
|
phaseResults.push(phaseResult);
|
|
4133
|
-
// Track iteration for metrics
|
|
4134
|
-
if (this.metricsCollector) {
|
|
4135
|
-
this.metricsCollector.incrementIteration();
|
|
4136
|
-
}
|
|
4137
4437
|
await ((_strategy_onPhaseComplete = strategy.onPhaseComplete) === null || _strategy_onPhaseComplete === void 0 ? void 0 : _strategy_onPhaseComplete.call(strategy, phaseResult, state));
|
|
4138
4438
|
// Check if should continue
|
|
4139
4439
|
if (strategy.shouldContinue && !strategy.shouldContinue(state)) {
|
|
@@ -4228,6 +4528,10 @@ function _define_property(obj, key, value) {
|
|
|
4228
4528
|
for(let i = 0; i < phase.maxIterations; i++){
|
|
4229
4529
|
var _strategy_onIteration;
|
|
4230
4530
|
state.iteration++;
|
|
4531
|
+
// Track iteration for metrics
|
|
4532
|
+
if (this.metricsCollector) {
|
|
4533
|
+
this.metricsCollector.incrementIteration();
|
|
4534
|
+
}
|
|
4231
4535
|
this.logger.debug('Iteration', {
|
|
4232
4536
|
phase: phase.name,
|
|
4233
4537
|
iteration: i + 1
|
|
@@ -4253,6 +4557,7 @@ function _define_property(obj, key, value) {
|
|
|
4253
4557
|
conversation.asAssistant(response.content, response.tool_calls);
|
|
4254
4558
|
// Execute tools
|
|
4255
4559
|
for (const toolCall of response.tool_calls){
|
|
4560
|
+
var _phase_maxConsecutiveToolFailures;
|
|
4256
4561
|
var _strategy_onToolCall;
|
|
4257
4562
|
// Check if tool is allowed in this phase
|
|
4258
4563
|
if (phase.allowedTools && !phase.allowedTools.includes(toolCall.function.name)) {
|
|
@@ -4261,6 +4566,22 @@ function _define_property(obj, key, value) {
|
|
|
4261
4566
|
});
|
|
4262
4567
|
continue;
|
|
4263
4568
|
}
|
|
4569
|
+
// Circuit breaker: Check if tool has exceeded failure threshold
|
|
4570
|
+
const maxFailures = (_phase_maxConsecutiveToolFailures = phase.maxConsecutiveToolFailures) !== null && _phase_maxConsecutiveToolFailures !== void 0 ? _phase_maxConsecutiveToolFailures : 3;
|
|
4571
|
+
const consecutiveFailures = state.toolFailures.get(toolCall.function.name) || 0;
|
|
4572
|
+
if (consecutiveFailures >= maxFailures) {
|
|
4573
|
+
this.logger.warn('Tool circuit breaker triggered', {
|
|
4574
|
+
tool: toolCall.function.name,
|
|
4575
|
+
failures: consecutiveFailures
|
|
4576
|
+
});
|
|
4577
|
+
conversation.asTool(toolCall.id, {
|
|
4578
|
+
error: `Tool temporarily disabled due to ${consecutiveFailures} consecutive failures`
|
|
4579
|
+
}, {
|
|
4580
|
+
success: false,
|
|
4581
|
+
circuitBreakerTriggered: true
|
|
4582
|
+
});
|
|
4583
|
+
continue;
|
|
4584
|
+
}
|
|
4264
4585
|
// Check tool call hook
|
|
4265
4586
|
const toolAction = await ((_strategy_onToolCall = strategy.onToolCall) === null || _strategy_onToolCall === void 0 ? void 0 : _strategy_onToolCall.call(strategy, toolCall, state));
|
|
4266
4587
|
if (toolAction === 'skip') {
|
|
@@ -4270,7 +4591,18 @@ function _define_property(obj, key, value) {
|
|
|
4270
4591
|
const toolStart = Date.now();
|
|
4271
4592
|
try {
|
|
4272
4593
|
var _strategy_onToolResult;
|
|
4273
|
-
|
|
4594
|
+
// Parse tool arguments with error handling
|
|
4595
|
+
let toolArgs;
|
|
4596
|
+
try {
|
|
4597
|
+
toolArgs = JSON.parse(toolCall.function.arguments);
|
|
4598
|
+
} catch (parseError) {
|
|
4599
|
+
const error = new Error(`Invalid JSON in tool arguments for ${toolCall.function.name}: ${parseError instanceof Error ? parseError.message : String(parseError)}`);
|
|
4600
|
+
if (parseError instanceof Error) {
|
|
4601
|
+
error.cause = parseError; // Preserve original error
|
|
4602
|
+
}
|
|
4603
|
+
throw error;
|
|
4604
|
+
}
|
|
4605
|
+
const result = await tools.execute(toolCall.function.name, toolArgs);
|
|
4274
4606
|
const toolDuration = Date.now() - toolStart;
|
|
4275
4607
|
const toolResult = {
|
|
4276
4608
|
callId: toolCall.id,
|
|
@@ -4283,6 +4615,8 @@ function _define_property(obj, key, value) {
|
|
|
4283
4615
|
success: true
|
|
4284
4616
|
});
|
|
4285
4617
|
state.toolCallsExecuted++;
|
|
4618
|
+
// Reset failure counter on success
|
|
4619
|
+
state.toolFailures.set(toolCall.function.name, 0);
|
|
4286
4620
|
// Record metrics
|
|
4287
4621
|
if (this.metricsCollector) {
|
|
4288
4622
|
this.metricsCollector.recordToolCall(toolCall.function.name, state.iteration, toolDuration, true);
|
|
@@ -4309,6 +4643,9 @@ function _define_property(obj, key, value) {
|
|
|
4309
4643
|
errorName: error.name
|
|
4310
4644
|
});
|
|
4311
4645
|
state.errors.push(error);
|
|
4646
|
+
// Increment failure counter for circuit breaker
|
|
4647
|
+
const failures = (state.toolFailures.get(toolCall.function.name) || 0) + 1;
|
|
4648
|
+
state.toolFailures.set(toolCall.function.name, failures);
|
|
4312
4649
|
// Record metrics
|
|
4313
4650
|
if (this.metricsCollector) {
|
|
4314
4651
|
this.metricsCollector.recordToolCall(toolCall.function.name, state.iteration, toolDuration, false, error.message);
|
|
@@ -4786,7 +5123,7 @@ const cook = async (config)=>{
|
|
|
4786
5123
|
if (finalConfig.tools) {
|
|
4787
5124
|
const tools = Array.isArray(finalConfig.tools) ? finalConfig.tools : finalConfig.tools.getAll();
|
|
4788
5125
|
// Filter by categories if specified
|
|
4789
|
-
const filteredTools = finalConfig.toolCategories ? tools.filter((tool)=>finalConfig.toolCategories.includes(tool.category
|
|
5126
|
+
const filteredTools = finalConfig.toolCategories ? tools.filter((tool)=>tool.category && finalConfig.toolCategories.includes(tool.category)) : tools;
|
|
4790
5127
|
if (filteredTools.length > 0 && finalConfig.toolGuidance) {
|
|
4791
5128
|
const guidance = generateToolGuidance(filteredTools, finalConfig.toolGuidance);
|
|
4792
5129
|
const toolSection = await parser$1.parse(guidance, {
|
|
@@ -4950,12 +5287,12 @@ const recipe = (basePath)=>{
|
|
|
4950
5287
|
}
|
|
4951
5288
|
return undefined;
|
|
4952
5289
|
},
|
|
4953
|
-
executeWith: async (llm, strategy, tokenBudget)=>{
|
|
5290
|
+
executeWith: async (llm, strategy, model = 'gpt-4o', tokenBudget)=>{
|
|
4954
5291
|
const prompt = await cook(config);
|
|
4955
5292
|
const conversation = ConversationBuilder.create({
|
|
4956
|
-
model
|
|
5293
|
+
model
|
|
4957
5294
|
}, config.logger);
|
|
4958
|
-
conversation.fromPrompt(prompt,
|
|
5295
|
+
conversation.fromPrompt(prompt, model);
|
|
4959
5296
|
if (tokenBudget) {
|
|
4960
5297
|
conversation.withTokenBudget(tokenBudget);
|
|
4961
5298
|
}
|
|
@@ -4992,6 +5329,7 @@ exports.Loader = loader;
|
|
|
4992
5329
|
exports.MessageBuilder = MessageBuilder;
|
|
4993
5330
|
exports.MessageTemplates = MessageTemplates;
|
|
4994
5331
|
exports.MetricsCollector = MetricsCollector;
|
|
5332
|
+
exports.ModelRegistry = ModelRegistry;
|
|
4995
5333
|
exports.Override = override;
|
|
4996
5334
|
exports.Parser = parser;
|
|
4997
5335
|
exports.Recipes = recipes;
|
|
@@ -5001,6 +5339,7 @@ exports.TokenBudgetManager = TokenBudgetManager;
|
|
|
5001
5339
|
exports.TokenCounter = TokenCounter;
|
|
5002
5340
|
exports.ToolRegistry = ToolRegistry;
|
|
5003
5341
|
exports.clearTemplates = clearTemplates;
|
|
5342
|
+
exports.configureModel = configureModel;
|
|
5004
5343
|
exports.cook = cook;
|
|
5005
5344
|
exports.createContent = create$b;
|
|
5006
5345
|
exports.createContext = create$a;
|
|
@@ -5011,7 +5350,13 @@ exports.createSection = create$8;
|
|
|
5011
5350
|
exports.createTrait = create$7;
|
|
5012
5351
|
exports.createWeighted = create$c;
|
|
5013
5352
|
exports.generateToolGuidance = generateToolGuidance;
|
|
5353
|
+
exports.getEncoding = getEncoding;
|
|
5354
|
+
exports.getModelFamily = getModelFamily;
|
|
5355
|
+
exports.getModelRegistry = getModelRegistry;
|
|
5356
|
+
exports.getPersonaRole = getPersonaRole$1;
|
|
5014
5357
|
exports.getTemplates = getTemplates;
|
|
5015
5358
|
exports.recipe = recipe;
|
|
5016
5359
|
exports.registerTemplates = registerTemplates;
|
|
5360
|
+
exports.resetModelRegistry = resetModelRegistry;
|
|
5361
|
+
exports.supportsToolCalls = supportsToolCalls;
|
|
5017
5362
|
//# sourceMappingURL=riotprompt.cjs.map
|