@riotprompt/riotprompt 0.0.12 → 0.0.13

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 (52) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +121 -21
  3. package/dist/builder.js +3 -0
  4. package/dist/builder.js.map +1 -1
  5. package/dist/cli.cjs +1519 -0
  6. package/dist/cli.d.ts +8 -0
  7. package/dist/config.d.ts +7 -0
  8. package/dist/conversation-logger.js +6 -1
  9. package/dist/conversation-logger.js.map +1 -1
  10. package/dist/execution/anthropic.d.ts +5 -0
  11. package/dist/execution/anthropic.js +46 -0
  12. package/dist/execution/anthropic.js.map +1 -0
  13. package/dist/execution/gemini.d.ts +5 -0
  14. package/dist/execution/gemini.js +78 -0
  15. package/dist/execution/gemini.js.map +1 -0
  16. package/dist/execution/index.d.ts +10 -0
  17. package/dist/execution/index.js +53 -0
  18. package/dist/execution/index.js.map +1 -0
  19. package/dist/execution/openai.d.ts +5 -0
  20. package/dist/execution/openai.js +44 -0
  21. package/dist/execution/openai.js.map +1 -0
  22. package/dist/execution/provider.d.ts +18 -0
  23. package/dist/loader.js +3 -0
  24. package/dist/loader.js.map +1 -1
  25. package/dist/model-config.d.ts +1 -0
  26. package/dist/model-config.js +19 -18
  27. package/dist/model-config.js.map +1 -1
  28. package/dist/override.js +3 -0
  29. package/dist/override.js.map +1 -1
  30. package/dist/recipes.js +3 -0
  31. package/dist/recipes.js.map +1 -1
  32. package/dist/riotprompt.cjs +612 -77
  33. package/dist/riotprompt.cjs.map +1 -1
  34. package/dist/riotprompt.d.ts +3 -0
  35. package/dist/riotprompt.js +6 -0
  36. package/dist/riotprompt.js.map +1 -1
  37. package/dist/serializer.d.ts +5 -0
  38. package/dist/serializer.js +220 -0
  39. package/dist/serializer.js.map +1 -0
  40. package/dist/writer.d.ts +2 -0
  41. package/dist/writer.js +91 -0
  42. package/dist/writer.js.map +1 -0
  43. package/guide/architecture.md +51 -0
  44. package/guide/configuration.md +51 -0
  45. package/guide/development.md +62 -0
  46. package/guide/index.md +55 -0
  47. package/guide/usage.md +99 -0
  48. package/package.json +13 -2
  49. package/vite.config.cli.ts +49 -0
  50. package/BUG-ANALYSIS.md +0 -523
  51. package/CODE-REVIEW-SUMMARY.md +0 -330
  52. package/FIXES-APPLIED.md +0 -437
@@ -7,8 +7,12 @@ const fs = require('fs/promises');
7
7
  const path = require('path');
8
8
  const crypto = require('crypto');
9
9
  const tiktoken = require('tiktoken');
10
+ const OpenAI = require('openai');
11
+ const Anthropic = require('@anthropic-ai/sdk');
12
+ const generativeAi = require('@google/generative-ai');
10
13
  const fs$1 = require('fs');
11
14
  const glob = require('glob');
15
+ const fastXmlParser = require('fast-xml-parser');
12
16
 
13
17
  function _interopNamespaceDefault(e) {
14
18
  const n = Object.create(null, { [Symbol.toStringTag]: { value: 'Module' } });
@@ -305,7 +309,7 @@ const wrapLogger = (toWrap, name)=>{
305
309
  };
306
310
  };
307
311
 
308
- function _define_property$8(obj, key, value) {
312
+ function _define_property$9(obj, key, value) {
309
313
  if (key in obj) {
310
314
  Object.defineProperty(obj, key, {
311
315
  value: value,
@@ -324,23 +328,14 @@ function _define_property$8(obj, key, value) {
324
328
  /**
325
329
  * Register default model configurations
326
330
  */ registerDefaults() {
327
- // GPT-4 family (uses 'system' role)
331
+ // Default fallback (Registered first so it ends up last with unshift)
328
332
  this.register({
329
- pattern: /^gpt-4/i,
333
+ pattern: /.*/,
330
334
  personaRole: 'system',
331
335
  encoding: 'gpt-4o',
332
336
  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'
337
+ family: 'unknown',
338
+ description: 'Default fallback configuration'
344
339
  });
345
340
  // Claude family (uses 'system' role)
346
341
  this.register({
@@ -351,27 +346,37 @@ function _define_property$8(obj, key, value) {
351
346
  family: 'claude',
352
347
  description: 'Claude family models'
353
348
  });
354
- // Default fallback
349
+ // O-series models (uses 'developer' role)
355
350
  this.register({
356
- pattern: /.*/,
351
+ pattern: /^o\d+/i,
352
+ personaRole: 'developer',
353
+ encoding: 'gpt-4o',
354
+ supportsToolCalls: true,
355
+ family: 'o-series',
356
+ description: 'O-series reasoning models'
357
+ });
358
+ // GPT-4 family (uses 'system' role)
359
+ this.register({
360
+ pattern: /^gpt-4/i,
357
361
  personaRole: 'system',
358
362
  encoding: 'gpt-4o',
359
363
  supportsToolCalls: true,
360
- family: 'unknown',
361
- description: 'Default fallback configuration'
364
+ family: 'gpt-4',
365
+ description: 'GPT-4 family models'
362
366
  });
363
367
  this.logger.debug('Registered default model configurations');
364
368
  }
365
369
  /**
366
370
  * Register a model configuration
367
371
  * Configs are checked in registration order (first match wins)
372
+ * New configs are added to the beginning of the list (high priority)
368
373
  */ register(config) {
369
374
  var _config_pattern;
370
375
  // Validate config
371
376
  if (!config.pattern && !config.exactMatch) {
372
377
  throw new Error('Model config must have either pattern or exactMatch');
373
378
  }
374
- this.configs.push(config);
379
+ this.configs.unshift(config);
375
380
  this.cache.clear(); // Clear cache when new config is added
376
381
  this.logger.debug('Registered model config', {
377
382
  family: config.family,
@@ -443,9 +448,9 @@ function _define_property$8(obj, key, value) {
443
448
  ];
444
449
  }
445
450
  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);
451
+ _define_property$9(this, "configs", void 0);
452
+ _define_property$9(this, "cache", void 0);
453
+ _define_property$9(this, "logger", void 0);
449
454
  this.configs = [];
450
455
  this.cache = new Map();
451
456
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ModelRegistry');
@@ -1593,7 +1598,7 @@ const builder = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
1593
1598
  create
1594
1599
  }, Symbol.toStringTag, { value: 'Module' }));
1595
1600
 
1596
- function _define_property$7(obj, key, value) {
1601
+ function _define_property$8(obj, key, value) {
1597
1602
  if (key in obj) {
1598
1603
  Object.defineProperty(obj, key, {
1599
1604
  value: value,
@@ -1822,16 +1827,16 @@ function _define_property$7(obj, key, value) {
1822
1827
  return content.replace(/\s+/g, ' ').trim().toLowerCase();
1823
1828
  }
1824
1829
  constructor(logger){
1825
- _define_property$7(this, "items", void 0);
1826
- _define_property$7(this, "hashes", void 0);
1827
- _define_property$7(this, "logger", void 0);
1830
+ _define_property$8(this, "items", void 0);
1831
+ _define_property$8(this, "hashes", void 0);
1832
+ _define_property$8(this, "logger", void 0);
1828
1833
  this.items = new Map();
1829
1834
  this.hashes = new Set();
1830
1835
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ContextManager');
1831
1836
  }
1832
1837
  }
1833
1838
 
1834
- function _define_property$6(obj, key, value) {
1839
+ function _define_property$7(obj, key, value) {
1835
1840
  if (key in obj) {
1836
1841
  Object.defineProperty(obj, key, {
1837
1842
  value: value,
@@ -2004,7 +2009,12 @@ function _define_property$6(obj, key, value) {
2004
2009
  }
2005
2010
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
2006
2011
  const filename = this.config.filenameTemplate.replace('{timestamp}', timestamp).replace('{id}', this.conversationId).replace('{template}', this.metadata.template || 'default');
2007
- const ext = this.config.format === 'markdown' ? '.md' : '.json';
2012
+ let ext = '.json';
2013
+ if (this.config.format === 'markdown') {
2014
+ ext = '.md';
2015
+ } else if (this.config.format === 'jsonl') {
2016
+ ext = '.jsonl';
2017
+ }
2008
2018
  const fullPath = path.join(this.config.outputPath, filename + ext);
2009
2019
  // Ensure directory exists
2010
2020
  await fs.mkdir(path.dirname(fullPath), {
@@ -2096,16 +2106,16 @@ function _define_property$6(obj, key, value) {
2096
2106
  return redacted;
2097
2107
  }
2098
2108
  constructor(config, logger){
2099
- _define_property$6(this, "config", void 0);
2100
- _define_property$6(this, "conversationId", void 0);
2101
- _define_property$6(this, "metadata", void 0);
2102
- _define_property$6(this, "messages", void 0);
2103
- _define_property$6(this, "toolCalls", void 0);
2104
- _define_property$6(this, "startTime", void 0);
2105
- _define_property$6(this, "logger", void 0);
2106
- _define_property$6(this, "messageIndex", void 0);
2107
- _define_property$6(this, "cachedOutputPath", void 0);
2108
- _define_property$6(this, "writeQueue", Promise.resolve());
2109
+ _define_property$7(this, "config", void 0);
2110
+ _define_property$7(this, "conversationId", void 0);
2111
+ _define_property$7(this, "metadata", void 0);
2112
+ _define_property$7(this, "messages", void 0);
2113
+ _define_property$7(this, "toolCalls", void 0);
2114
+ _define_property$7(this, "startTime", void 0);
2115
+ _define_property$7(this, "logger", void 0);
2116
+ _define_property$7(this, "messageIndex", void 0);
2117
+ _define_property$7(this, "cachedOutputPath", void 0);
2118
+ _define_property$7(this, "writeQueue", Promise.resolve());
2109
2119
  this.config = {
2110
2120
  outputPath: 'logs/conversations',
2111
2121
  format: 'json',
@@ -2309,14 +2319,14 @@ function _define_property$6(obj, key, value) {
2309
2319
  await fs.writeFile(outputPath, markdown, 'utf-8');
2310
2320
  }
2311
2321
  constructor(conversation, logger){
2312
- _define_property$6(this, "conversation", void 0);
2313
- _define_property$6(this, "logger", void 0);
2322
+ _define_property$7(this, "conversation", void 0);
2323
+ _define_property$7(this, "logger", void 0);
2314
2324
  this.conversation = conversation;
2315
2325
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationReplayer');
2316
2326
  }
2317
2327
  }
2318
2328
 
2319
- function _define_property$5(obj, key, value) {
2329
+ function _define_property$6(obj, key, value) {
2320
2330
  if (key in obj) {
2321
2331
  Object.defineProperty(obj, key, {
2322
2332
  value: value,
@@ -2499,13 +2509,13 @@ function _define_property$5(obj, key, value) {
2499
2509
  return message;
2500
2510
  }
2501
2511
  constructor(role, logger){
2502
- _define_property$5(this, "semanticRole", void 0);
2503
- _define_property$5(this, "contentParts", void 0);
2504
- _define_property$5(this, "metadata", void 0);
2505
- _define_property$5(this, "formatter", void 0);
2506
- _define_property$5(this, "toolCallId", void 0);
2507
- _define_property$5(this, "toolCalls", void 0);
2508
- _define_property$5(this, "logger", void 0);
2512
+ _define_property$6(this, "semanticRole", void 0);
2513
+ _define_property$6(this, "contentParts", void 0);
2514
+ _define_property$6(this, "metadata", void 0);
2515
+ _define_property$6(this, "formatter", void 0);
2516
+ _define_property$6(this, "toolCallId", void 0);
2517
+ _define_property$6(this, "toolCalls", void 0);
2518
+ _define_property$6(this, "logger", void 0);
2509
2519
  this.semanticRole = role;
2510
2520
  this.contentParts = [];
2511
2521
  this.metadata = {};
@@ -2566,7 +2576,7 @@ function _define_property$5(obj, key, value) {
2566
2576
  }
2567
2577
  };
2568
2578
 
2569
- function _define_property$4(obj, key, value) {
2579
+ function _define_property$5(obj, key, value) {
2570
2580
  if (key in obj) {
2571
2581
  Object.defineProperty(obj, key, {
2572
2582
  value: value,
@@ -2682,9 +2692,9 @@ function _define_property$4(obj, key, value) {
2682
2692
  this.encoder.free();
2683
2693
  }
2684
2694
  constructor(model, logger){
2685
- _define_property$4(this, "encoder", void 0);
2686
- _define_property$4(this, "model", void 0);
2687
- _define_property$4(this, "logger", void 0);
2695
+ _define_property$5(this, "encoder", void 0);
2696
+ _define_property$5(this, "model", void 0);
2697
+ _define_property$5(this, "logger", void 0);
2688
2698
  this.model = model;
2689
2699
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'TokenCounter');
2690
2700
  // Map RiotPrompt models to Tiktoken models
@@ -2940,9 +2950,9 @@ function _define_property$4(obj, key, value) {
2940
2950
  this.counter.dispose();
2941
2951
  }
2942
2952
  constructor(config, model, logger){
2943
- _define_property$4(this, "config", void 0);
2944
- _define_property$4(this, "counter", void 0);
2945
- _define_property$4(this, "logger", void 0);
2953
+ _define_property$5(this, "config", void 0);
2954
+ _define_property$5(this, "counter", void 0);
2955
+ _define_property$5(this, "logger", void 0);
2946
2956
  this.config = {
2947
2957
  warningThreshold: 0.8,
2948
2958
  preserveRecent: 3,
@@ -2961,7 +2971,7 @@ function _define_property$4(obj, key, value) {
2961
2971
  }
2962
2972
  }
2963
2973
 
2964
- function _define_property$3(obj, key, value) {
2974
+ function _define_property$4(obj, key, value) {
2965
2975
  if (key in obj) {
2966
2976
  Object.defineProperty(obj, key, {
2967
2977
  value: value,
@@ -3575,11 +3585,11 @@ const ConversationBuilderConfigSchema = zod.z.object({
3575
3585
  this.state.metadata.lastModified = new Date();
3576
3586
  }
3577
3587
  constructor(config, logger){
3578
- _define_property$3(this, "state", void 0);
3579
- _define_property$3(this, "config", void 0);
3580
- _define_property$3(this, "logger", void 0);
3581
- _define_property$3(this, "budgetManager", void 0);
3582
- _define_property$3(this, "conversationLogger", void 0);
3588
+ _define_property$4(this, "state", void 0);
3589
+ _define_property$4(this, "config", void 0);
3590
+ _define_property$4(this, "logger", void 0);
3591
+ _define_property$4(this, "budgetManager", void 0);
3592
+ _define_property$4(this, "conversationLogger", void 0);
3583
3593
  this.config = ConversationBuilderConfigSchema.parse(config);
3584
3594
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ConversationBuilder');
3585
3595
  this.state = {
@@ -3600,7 +3610,7 @@ const ConversationBuilderConfigSchema = zod.z.object({
3600
3610
  }
3601
3611
  }
3602
3612
 
3603
- function _define_property$2(obj, key, value) {
3613
+ function _define_property$3(obj, key, value) {
3604
3614
  if (key in obj) {
3605
3615
  Object.defineProperty(obj, key, {
3606
3616
  value: value,
@@ -3907,10 +3917,10 @@ const ToolSchema = zod.z.object({
3907
3917
  });
3908
3918
  }
3909
3919
  constructor(context = {}, logger){
3910
- _define_property$2(this, "tools", void 0);
3911
- _define_property$2(this, "context", void 0);
3912
- _define_property$2(this, "logger", void 0);
3913
- _define_property$2(this, "usageStats", void 0);
3920
+ _define_property$3(this, "tools", void 0);
3921
+ _define_property$3(this, "context", void 0);
3922
+ _define_property$3(this, "logger", void 0);
3923
+ _define_property$3(this, "usageStats", void 0);
3914
3924
  this.tools = new Map();
3915
3925
  this.context = context;
3916
3926
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ToolRegistry');
@@ -3919,7 +3929,7 @@ const ToolSchema = zod.z.object({
3919
3929
  }
3920
3930
  }
3921
3931
 
3922
- function _define_property$1(obj, key, value) {
3932
+ function _define_property$2(obj, key, value) {
3923
3933
  if (key in obj) {
3924
3934
  Object.defineProperty(obj, key, {
3925
3935
  value: value,
@@ -4050,10 +4060,10 @@ function _define_property$1(obj, key, value) {
4050
4060
  return stats;
4051
4061
  }
4052
4062
  constructor(logger){
4053
- _define_property$1(this, "startTime", void 0);
4054
- _define_property$1(this, "toolMetrics", void 0);
4055
- _define_property$1(this, "iterationCount", void 0);
4056
- _define_property$1(this, "logger", void 0);
4063
+ _define_property$2(this, "startTime", void 0);
4064
+ _define_property$2(this, "toolMetrics", void 0);
4065
+ _define_property$2(this, "iterationCount", void 0);
4066
+ _define_property$2(this, "logger", void 0);
4057
4067
  this.startTime = new Date();
4058
4068
  this.toolMetrics = [];
4059
4069
  this.iterationCount = 0;
@@ -4328,12 +4338,12 @@ function _define_property$1(obj, key, value) {
4328
4338
  return markdown;
4329
4339
  }
4330
4340
  constructor(logger){
4331
- _define_property$1(this, "logger", void 0);
4341
+ _define_property$2(this, "logger", void 0);
4332
4342
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'ReflectionReportGenerator');
4333
4343
  }
4334
4344
  }
4335
4345
 
4336
- function _define_property(obj, key, value) {
4346
+ function _define_property$1(obj, key, value) {
4337
4347
  if (key in obj) {
4338
4348
  Object.defineProperty(obj, key, {
4339
4349
  value: value,
@@ -4685,10 +4695,10 @@ function _define_property(obj, key, value) {
4685
4695
  };
4686
4696
  }
4687
4697
  constructor(llm, logger){
4688
- _define_property(this, "llm", void 0);
4689
- _define_property(this, "logger", void 0);
4690
- _define_property(this, "metricsCollector", void 0);
4691
- _define_property(this, "reflectionConfig", void 0);
4698
+ _define_property$1(this, "llm", void 0);
4699
+ _define_property$1(this, "logger", void 0);
4700
+ _define_property$1(this, "metricsCollector", void 0);
4701
+ _define_property$1(this, "reflectionConfig", void 0);
4692
4702
  this.llm = llm;
4693
4703
  this.logger = wrapLogger(logger || DEFAULT_LOGGER, 'StrategyExecutor');
4694
4704
  }
@@ -5317,12 +5327,535 @@ const recipes = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
5317
5327
  registerTemplates
5318
5328
  }, Symbol.toStringTag, { value: 'Module' }));
5319
5329
 
5330
+ const toJSON = (prompt)=>{
5331
+ return JSON.stringify(prompt, null, 2);
5332
+ };
5333
+ const escapeXML = (str)=>{
5334
+ return str.replace(/[<>&'"]/g, (c)=>{
5335
+ switch(c){
5336
+ case '<':
5337
+ return '&lt;';
5338
+ case '>':
5339
+ return '&gt;';
5340
+ case '&':
5341
+ return '&amp;';
5342
+ case '\'':
5343
+ return '&apos;';
5344
+ case '"':
5345
+ return '&quot;';
5346
+ default:
5347
+ return c;
5348
+ }
5349
+ });
5350
+ };
5351
+ const itemToXML = (item)=>{
5352
+ if (typeof item === 'string') {
5353
+ return `<item>${escapeXML(item)}</item>`;
5354
+ }
5355
+ // Check if it's a section
5356
+ if (item && typeof item === 'object' && 'items' in item) {
5357
+ return sectionToXML(item);
5358
+ }
5359
+ // Check if it's a weighted item
5360
+ if (item && typeof item === 'object' && 'text' in item) {
5361
+ const weightAttr = item.weight !== undefined && item.weight !== null ? ` weight="${item.weight}"` : '';
5362
+ return `<item${weightAttr}>${escapeXML(item.text)}</item>`;
5363
+ }
5364
+ return '';
5365
+ };
5366
+ const sectionToXML = (section, tagName = 'section')=>{
5367
+ const titleAttr = section.title ? ` title="${escapeXML(section.title)}"` : '';
5368
+ const weightAttr = section.weight ? ` weight="${section.weight}"` : '';
5369
+ let xml = `<${tagName}${titleAttr}${weightAttr}>`;
5370
+ if (section.items && Array.isArray(section.items)) {
5371
+ xml += section.items.map((item)=>itemToXML(item)).join('');
5372
+ }
5373
+ xml += `</${tagName}>`;
5374
+ return xml;
5375
+ };
5376
+ const toXML = (prompt)=>{
5377
+ let xml = '<?xml version="1.0" encoding="UTF-8"?>\n<prompt>';
5378
+ if (prompt.persona) {
5379
+ xml += sectionToXML(prompt.persona, 'persona');
5380
+ }
5381
+ if (prompt.instructions) {
5382
+ xml += sectionToXML(prompt.instructions, 'instructions');
5383
+ }
5384
+ if (prompt.contents) {
5385
+ xml += sectionToXML(prompt.contents, 'contents');
5386
+ }
5387
+ if (prompt.contexts) {
5388
+ xml += sectionToXML(prompt.contexts, 'contexts');
5389
+ }
5390
+ xml += '</prompt>';
5391
+ return xml;
5392
+ };
5393
+ // ============================================================================
5394
+ // DESERIALIZATION
5395
+ // ============================================================================
5396
+ // --- JSON Parsing ---
5397
+ const parseSectionFromJSON = (jsonSection)=>{
5398
+ if (!jsonSection || !jsonSection.items) {
5399
+ throw new Error("Invalid section structure");
5400
+ }
5401
+ const section = create$8({
5402
+ title: jsonSection.title,
5403
+ weight: jsonSection.weight
5404
+ });
5405
+ for (const item of jsonSection.items){
5406
+ if (typeof item === 'object' && 'items' in item) {
5407
+ // It's a nested section
5408
+ section.add(parseSectionFromJSON(item));
5409
+ } else if (typeof item === 'object' && 'text' in item) {
5410
+ section.add({
5411
+ text: item.text,
5412
+ weight: item.weight
5413
+ });
5414
+ } else if (typeof item === 'string') {
5415
+ section.add(item);
5416
+ }
5417
+ }
5418
+ return section;
5419
+ };
5420
+ const fromJSON = (jsonString)=>{
5421
+ const json = JSON.parse(jsonString);
5422
+ // We treat the root json object as matching Prompt interface
5423
+ // But we need to convert plain objects back to Section instances with methods
5424
+ const persona = json.persona ? parseSectionFromJSON(json.persona) : undefined;
5425
+ const instructions = json.instructions ? parseSectionFromJSON(json.instructions) : create$8({
5426
+ title: 'Instructions'
5427
+ });
5428
+ const contents = json.contents ? parseSectionFromJSON(json.contents) : undefined;
5429
+ const contexts = json.contexts ? parseSectionFromJSON(json.contexts) : undefined;
5430
+ return create$6({
5431
+ persona,
5432
+ instructions,
5433
+ contents,
5434
+ contexts
5435
+ });
5436
+ };
5437
+ // --- XML Parsing ---
5438
+ const parseNodeToSection = (node)=>{
5439
+ // Node structure with preserveOrder: true
5440
+ // It seems attributes can be a sibling property ":@" OR inside the children array depending on version/config/content.
5441
+ // Children are in the array value of the key "section", "persona", etc.
5442
+ const children = node.section || node.persona || node.instructions || node.contents || node.contexts || [];
5443
+ let attributes = node[":@"] || {};
5444
+ // Fallback: check if attributes are inside the children array (as seen in some tests/mocks)
5445
+ if (!node[":@"] && Array.isArray(children)) {
5446
+ for (const child of children){
5447
+ if (child[":@"]) {
5448
+ attributes = child[":@"];
5449
+ break;
5450
+ }
5451
+ }
5452
+ }
5453
+ const title = attributes["@_title"];
5454
+ const weight = attributes["@_weight"] ? Number(attributes["@_weight"]) : undefined;
5455
+ const section = create$8({
5456
+ title,
5457
+ weight
5458
+ });
5459
+ if (Array.isArray(children)) {
5460
+ for (const child of children){
5461
+ const key = Object.keys(child)[0]; // "item" or "section" or ":@"
5462
+ // console.log(`Processing child key: ${key}`);
5463
+ if (key === ":@") continue; // Already handled or just attributes
5464
+ if (key === "item") {
5465
+ // Item structure: [ { "#text": "Value" }, { ":@": ... } ]
5466
+ const itemContent = child.item;
5467
+ let text = "";
5468
+ let itemWeight = undefined;
5469
+ for (const part of itemContent){
5470
+ const keys = Object.keys(part);
5471
+ // console.log('Processing item part keys:', keys);
5472
+ if (keys.includes("#text")) {
5473
+ text = part["#text"];
5474
+ } else if (keys.includes(":@")) {
5475
+ const attrs = part[":@"];
5476
+ // console.log('Found attributes:', attrs);
5477
+ // Check both with and without prefix just in case
5478
+ const w = attrs["@_weight"] || attrs["weight"];
5479
+ if (w !== undefined) itemWeight = Number(w);
5480
+ } else {
5481
+ // Fallback for cases where attributes might be directly on the part (unexpected but possible)
5482
+ const w = part["@_weight"] || part["weight"];
5483
+ if (w !== undefined) itemWeight = Number(w);
5484
+ }
5485
+ }
5486
+ // console.log(`Adding item: ${text}`);
5487
+ section.add({
5488
+ text,
5489
+ weight: itemWeight
5490
+ });
5491
+ } else if (key === "section") {
5492
+ section.add(parseNodeToSection(child));
5493
+ }
5494
+ }
5495
+ }
5496
+ return section;
5497
+ };
5498
+ const fromXML = (xmlString)=>{
5499
+ const parser = new fastXmlParser.XMLParser({
5500
+ ignoreAttributes: false,
5501
+ attributeNamePrefix: "@_",
5502
+ preserveOrder: true,
5503
+ trimValues: true
5504
+ });
5505
+ const parsed = parser.parse(xmlString);
5506
+ // parsed is [ { "?xml": ... }, { "prompt": [ ... ] } ]
5507
+ let promptNode = null;
5508
+ for (const node of parsed){
5509
+ if (node.prompt) {
5510
+ promptNode = node.prompt;
5511
+ break;
5512
+ }
5513
+ }
5514
+ if (!promptNode) throw new Error("Invalid XML: missing <prompt> root");
5515
+ let persona;
5516
+ let instructions = create$8({
5517
+ title: "Instructions"
5518
+ });
5519
+ let contents;
5520
+ let contexts;
5521
+ for (const child of promptNode){
5522
+ if (child.persona) {
5523
+ persona = parseNodeToSection(child);
5524
+ persona.title = "Persona"; // Force title for standard sections?
5525
+ } else if (child.instructions) {
5526
+ instructions = parseNodeToSection(child);
5527
+ instructions.title = "Instructions";
5528
+ } else if (child.contents) {
5529
+ contents = parseNodeToSection(child);
5530
+ contents.title = "Contents";
5531
+ } else if (child.contexts) {
5532
+ contexts = parseNodeToSection(child);
5533
+ contexts.title = "Contexts";
5534
+ }
5535
+ }
5536
+ return create$6({
5537
+ persona,
5538
+ instructions,
5539
+ contents,
5540
+ contexts
5541
+ });
5542
+ };
5543
+
5544
+ const serializer = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
5545
+ __proto__: null,
5546
+ fromJSON,
5547
+ fromXML,
5548
+ toJSON,
5549
+ toXML
5550
+ }, Symbol.toStringTag, { value: 'Module' }));
5551
+
5552
+ const saveToDirectory = async (prompt, basePath)=>{
5553
+ // Ensure base directory exists
5554
+ await fs__namespace.mkdir(basePath, {
5555
+ recursive: true
5556
+ });
5557
+ // 1. Save Persona
5558
+ if (prompt.persona) {
5559
+ await saveSection(prompt.persona, path__namespace.join(basePath, 'persona'));
5560
+ }
5561
+ // 2. Save Instructions
5562
+ if (prompt.instructions) {
5563
+ await saveSection(prompt.instructions, path__namespace.join(basePath, 'instructions'));
5564
+ }
5565
+ // 3. Save Context
5566
+ if (prompt.contexts) {
5567
+ await saveSection(prompt.contexts, path__namespace.join(basePath, 'context'));
5568
+ }
5569
+ // 4. Save Content (if any)
5570
+ if (prompt.contents) {
5571
+ await saveSection(prompt.contents, path__namespace.join(basePath, 'content'));
5572
+ }
5573
+ };
5574
+ const saveSection = async (section, targetPath)=>{
5575
+ // If section has subsections, create a directory and recurse
5576
+ // If section only has items, check if we can save as single file (e.g. name of section + .md)
5577
+ // Simplification: We will use a mixed approach.
5578
+ // If the section is "flat" (only items), we can write it to a file.
5579
+ // If the section is "nested" (has subsections), we create a directory.
5580
+ // However, to be consistent with Loader logic:
5581
+ // Loader reads files in a directory as subsections.
5582
+ // So if we have a section "Instructions", and we save it as a directory "instructions":
5583
+ // Its items become content of files?
5584
+ // Strategy:
5585
+ // 1. Create directory `targetPath`.
5586
+ // 2. If the section has items (text), verify if they have titles (subsections).
5587
+ // 3. For each item:
5588
+ // - If it's a string/Instruction/Content/Context (leaf):
5589
+ // - If the parent section is the ROOT (e.g. 'persona'), and it's just text, maybe we prefer `persona.md`.
5590
+ // - If it's a subsection:
5591
+ // - Recurse into subdirectory.
5592
+ // Let's refine based on typical usage:
5593
+ // - Persona: usually one big text. -> `persona.md`
5594
+ // - Instructions: usually one big text or list of files. -> `instructions.md` or `instructions/part1.md`
5595
+ // - Context: usually list of files. -> `context/data.json`, `context/info.md`
5596
+ // We need to differentiate based on the targetPath provided by caller.
5597
+ // If targetPath ends in "persona" (directory name), we can choose to write `targetPath.md` instead if it's flat.
5598
+ // But `saveToDirectory` created `basePath/persona` (directory path string).
5599
+ // Let's check complexity:
5600
+ const hasSubsections = section.items.some((item)=>typeof item === 'object' && 'items' in item);
5601
+ if (!hasSubsections) {
5602
+ // Flat section.
5603
+ // If it has multiple items, we can join them? Or write as numbered files?
5604
+ // Usually, a flat section implies content for a single file.
5605
+ // We prefer to write to `targetPath.md`.
5606
+ const content = section.items.map((item)=>{
5607
+ if (typeof item === 'string') return item;
5608
+ return item.text;
5609
+ }).join('\n\n');
5610
+ // Check if we should write to .md file instead of directory
5611
+ // targetPath is e.g. ".../persona". We want ".../persona.md".
5612
+ await fs__namespace.writeFile(`${targetPath}.md`, content);
5613
+ return;
5614
+ }
5615
+ // Nested section
5616
+ await fs__namespace.mkdir(targetPath, {
5617
+ recursive: true
5618
+ });
5619
+ for(let i = 0; i < section.items.length; i++){
5620
+ const item = section.items[i];
5621
+ if (typeof item === 'object' && 'items' in item) {
5622
+ // Subsection
5623
+ // Use title as filename/dirname
5624
+ const subTitle = item.title || `part-${i + 1}`;
5625
+ const subPath = path__namespace.join(targetPath, subTitle);
5626
+ await saveSection(item, subPath);
5627
+ } else {
5628
+ // Leaf item mixed with subsections.
5629
+ // Write to a file.
5630
+ // If it's just text, we need a filename.
5631
+ const fileName = `item-${i + 1}.md`;
5632
+ const content = typeof item === 'string' ? item : item.text;
5633
+ await fs__namespace.writeFile(path__namespace.join(targetPath, fileName), content);
5634
+ }
5635
+ }
5636
+ };
5637
+
5638
+ const writer = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
5639
+ __proto__: null,
5640
+ saveToDirectory
5641
+ }, Symbol.toStringTag, { value: 'Module' }));
5642
+
5643
+ class OpenAIProvider {
5644
+ async execute(request, options = {}) {
5645
+ const apiKey = options.apiKey || process.env.OPENAI_API_KEY;
5646
+ if (!apiKey) throw new Error('OpenAI API key is required');
5647
+ const client = new OpenAI({
5648
+ apiKey
5649
+ });
5650
+ const model = options.model || request.model || 'gpt-4';
5651
+ // Convert RiotPrompt messages to OpenAI messages
5652
+ const messages = request.messages.map((msg)=>{
5653
+ const role = msg.role === 'developer' ? 'system' : msg.role; // OpenAI uses system, not developer usually (except o1)
5654
+ // But wait, o1 uses developer. Let's respect what formatter gave us if valid.
5655
+ // OpenAI Node SDK types expect specific roles.
5656
+ // RiotPrompt roles: "user" | "assistant" | "system" | "developer"
5657
+ // OpenAI roles: "system" | "user" | "assistant" | "tool" | "function" | "developer" (recent versions)
5658
+ // We'll cast to any to avoid strict type issues with older/newer SDK versions mismatch
5659
+ return {
5660
+ role: role,
5661
+ content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content),
5662
+ name: msg.name
5663
+ };
5664
+ });
5665
+ const response = await client.chat.completions.create({
5666
+ model: model,
5667
+ messages: messages,
5668
+ temperature: options.temperature,
5669
+ max_tokens: options.maxTokens
5670
+ });
5671
+ const choice = response.choices[0];
5672
+ return {
5673
+ content: choice.message.content || '',
5674
+ model: response.model,
5675
+ usage: response.usage ? {
5676
+ inputTokens: response.usage.prompt_tokens,
5677
+ outputTokens: response.usage.completion_tokens
5678
+ } : undefined
5679
+ };
5680
+ }
5681
+ }
5682
+
5683
+ class AnthropicProvider {
5684
+ async execute(request, options = {}) {
5685
+ const apiKey = options.apiKey || process.env.ANTHROPIC_API_KEY;
5686
+ if (!apiKey) throw new Error('Anthropic API key is required');
5687
+ const client = new Anthropic({
5688
+ apiKey
5689
+ });
5690
+ const model = options.model || request.model || 'claude-3-opus-20240229';
5691
+ // Anthropic separates system prompt from messages
5692
+ let systemPrompt = '';
5693
+ const messages = [];
5694
+ for (const msg of request.messages){
5695
+ if (msg.role === 'system' || msg.role === 'developer') {
5696
+ systemPrompt += (typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)) + '\n\n';
5697
+ } else {
5698
+ messages.push({
5699
+ role: msg.role,
5700
+ content: typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)
5701
+ });
5702
+ }
5703
+ }
5704
+ const response = await client.messages.create({
5705
+ model: model,
5706
+ system: systemPrompt.trim() || undefined,
5707
+ messages: messages,
5708
+ max_tokens: options.maxTokens || 4096,
5709
+ temperature: options.temperature
5710
+ });
5711
+ // Handle ContentBlock
5712
+ const contentBlock = response.content[0];
5713
+ const text = contentBlock.type === 'text' ? contentBlock.text : '';
5714
+ return {
5715
+ content: text,
5716
+ model: response.model,
5717
+ usage: {
5718
+ inputTokens: response.usage.input_tokens,
5719
+ outputTokens: response.usage.output_tokens
5720
+ }
5721
+ };
5722
+ }
5723
+ }
5724
+
5725
+ class GeminiProvider {
5726
+ async execute(request, options = {}) {
5727
+ const apiKey = options.apiKey || process.env.GEMINI_API_KEY; // or GOOGLE_API_KEY
5728
+ if (!apiKey) throw new Error('Gemini API key is required');
5729
+ const genAI = new generativeAi.GoogleGenerativeAI(apiKey);
5730
+ const modelName = options.model || request.model || 'gemini-1.5-pro';
5731
+ // Gemini format: system instruction is separate, history is separate from last message
5732
+ // generateContent accepts a string or parts.
5733
+ // We need to construct the prompt.
5734
+ // Simple approach: Concat system instructions + chat history
5735
+ let systemInstruction = '';
5736
+ // Extract system prompt
5737
+ for (const msg of request.messages){
5738
+ if (msg.role === 'system' || msg.role === 'developer') {
5739
+ systemInstruction += (typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content)) + '\n\n';
5740
+ }
5741
+ }
5742
+ // Configure model with system instruction if available (newer Gemini versions support this)
5743
+ // Or just prepend to first user message.
5744
+ // Let's try to prepend for compatibility if needed, but 'systemInstruction' param exists in getGenerativeModel config.
5745
+ const configuredModel = genAI.getGenerativeModel({
5746
+ model: modelName,
5747
+ systemInstruction: systemInstruction ? systemInstruction.trim() : undefined
5748
+ });
5749
+ // Build history/messages
5750
+ // Gemini `generateContent` takes the *last* user message.
5751
+ // `startChat` takes history.
5752
+ const chatHistory = [];
5753
+ let lastUserMessage = '';
5754
+ for (const msg of request.messages){
5755
+ if (msg.role === 'system' || msg.role === 'developer') continue;
5756
+ const content = typeof msg.content === 'string' ? msg.content : JSON.stringify(msg.content);
5757
+ if (msg.role === 'user') {
5758
+ lastUserMessage = content; // Assuming strictly alternating or we just want the prompt?
5759
+ // If there are multiple messages, we should build a chat.
5760
+ }
5761
+ chatHistory.push({
5762
+ role: msg.role === 'assistant' ? 'model' : 'user',
5763
+ parts: [
5764
+ {
5765
+ text: content
5766
+ }
5767
+ ]
5768
+ });
5769
+ }
5770
+ // If we are just running a prompt (single turn), we can use generateContent with the full text.
5771
+ // But let's support multi-turn by using startChat if history > 1.
5772
+ // If it's a typical "Prompt" execution, it's usually System + 1 User message.
5773
+ let result;
5774
+ if (chatHistory.length > 1) {
5775
+ // Remove last message from history to send it
5776
+ const lastMsg = chatHistory.pop();
5777
+ const chat = configuredModel.startChat({
5778
+ history: chatHistory
5779
+ });
5780
+ result = await chat.sendMessage((lastMsg === null || lastMsg === void 0 ? void 0 : lastMsg.parts[0].text) || '');
5781
+ } else {
5782
+ // Just one message (or none?)
5783
+ result = await configuredModel.generateContent(lastUserMessage || ' ');
5784
+ }
5785
+ const response = await result.response;
5786
+ const text = response.text();
5787
+ return {
5788
+ content: text,
5789
+ model: modelName,
5790
+ // Gemini usage metadata usageMetadata
5791
+ usage: response.usageMetadata ? {
5792
+ inputTokens: response.usageMetadata.promptTokenCount,
5793
+ outputTokens: response.usageMetadata.candidatesTokenCount
5794
+ } : undefined
5795
+ };
5796
+ }
5797
+ }
5798
+
5799
+ function _define_property(obj, key, value) {
5800
+ if (key in obj) {
5801
+ Object.defineProperty(obj, key, {
5802
+ value: value,
5803
+ enumerable: true,
5804
+ configurable: true,
5805
+ writable: true
5806
+ });
5807
+ } else {
5808
+ obj[key] = value;
5809
+ }
5810
+ return obj;
5811
+ }
5812
+ class ExecutionManager {
5813
+ getProvider(model) {
5814
+ if (!model) {
5815
+ // Default to OpenAI if model is undefined
5816
+ return this.providers.get('openai');
5817
+ }
5818
+ if (model.startsWith('gpt') || model.startsWith('o1')) {
5819
+ return this.providers.get('openai');
5820
+ } else if (model.startsWith('claude')) {
5821
+ return this.providers.get('anthropic');
5822
+ } else if (model.startsWith('gemini')) {
5823
+ return this.providers.get('gemini');
5824
+ }
5825
+ // Fallback or default?
5826
+ return this.providers.get('openai');
5827
+ }
5828
+ async execute(request, options = {}) {
5829
+ const model = options.model || request.model;
5830
+ const provider = this.getProvider(model);
5831
+ return provider.execute(request, options);
5832
+ }
5833
+ constructor(){
5834
+ _define_property(this, "providers", void 0);
5835
+ this.providers = new Map();
5836
+ this.providers.set('openai', new OpenAIProvider());
5837
+ this.providers.set('anthropic', new AnthropicProvider());
5838
+ this.providers.set('gemini', new GeminiProvider());
5839
+ }
5840
+ }
5841
+ const execute = async (request, options = {})=>{
5842
+ const manager = new ExecutionManager();
5843
+ return manager.execute(request, options);
5844
+ };
5845
+
5846
+ const index = /*#__PURE__*/Object.freeze(/*#__PURE__*/Object.defineProperty({
5847
+ __proto__: null,
5848
+ ExecutionManager,
5849
+ execute
5850
+ }, Symbol.toStringTag, { value: 'Module' }));
5851
+
5320
5852
  exports.Builder = builder;
5321
5853
  exports.Chat = chat;
5322
5854
  exports.ContextManager = ContextManager;
5323
5855
  exports.ConversationBuilder = ConversationBuilder;
5324
5856
  exports.ConversationLogger = ConversationLogger;
5325
5857
  exports.ConversationReplayer = ConversationReplayer;
5858
+ exports.Execution = index;
5326
5859
  exports.Formatter = formatter;
5327
5860
  exports.IterationStrategyFactory = IterationStrategyFactory;
5328
5861
  exports.Loader = loader;
@@ -5334,10 +5867,12 @@ exports.Override = override;
5334
5867
  exports.Parser = parser;
5335
5868
  exports.Recipes = recipes;
5336
5869
  exports.ReflectionReportGenerator = ReflectionReportGenerator;
5870
+ exports.Serializer = serializer;
5337
5871
  exports.StrategyExecutor = StrategyExecutor;
5338
5872
  exports.TokenBudgetManager = TokenBudgetManager;
5339
5873
  exports.TokenCounter = TokenCounter;
5340
5874
  exports.ToolRegistry = ToolRegistry;
5875
+ exports.Writer = writer;
5341
5876
  exports.clearTemplates = clearTemplates;
5342
5877
  exports.configureModel = configureModel;
5343
5878
  exports.cook = cook;