@riotprompt/riotprompt 0.0.21 → 1.0.1-dev.0

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 (69) hide show
  1. package/CHANGELOG.md +74 -0
  2. package/MIGRATION.md +235 -0
  3. package/README.md +2 -0
  4. package/SECURITY.md +132 -0
  5. package/dist/builder.js +6 -0
  6. package/dist/builder.js.map +1 -1
  7. package/dist/cli.js +481 -22
  8. package/dist/context-manager.js +1 -1
  9. package/dist/conversation-logger.d.ts +17 -1
  10. package/dist/conversation-logger.js +21 -17
  11. package/dist/conversation-logger.js.map +1 -1
  12. package/dist/conversation.js +1 -1
  13. package/dist/error-handling.d.ts +52 -0
  14. package/dist/error-handling.js +132 -0
  15. package/dist/error-handling.js.map +1 -0
  16. package/dist/formatter.js +1 -1
  17. package/dist/iteration-strategy.js +1 -1
  18. package/dist/loader.js +60 -12
  19. package/dist/loader.js.map +1 -1
  20. package/dist/logger.d.ts +52 -0
  21. package/dist/logger.js +114 -14
  22. package/dist/logger.js.map +1 -1
  23. package/dist/logging-config.d.ts +84 -0
  24. package/dist/logging-config.js +116 -0
  25. package/dist/logging-config.js.map +1 -0
  26. package/dist/message-builder.js +1 -1
  27. package/dist/model-config.js +1 -1
  28. package/dist/override.js +10 -4
  29. package/dist/override.js.map +1 -1
  30. package/dist/recipes.js +6 -0
  31. package/dist/recipes.js.map +1 -1
  32. package/dist/reflection.js +1 -1
  33. package/dist/riotprompt.d.ts +9 -0
  34. package/dist/riotprompt.js +8 -0
  35. package/dist/riotprompt.js.map +1 -1
  36. package/dist/security/audit-logger.d.ts +61 -0
  37. package/dist/security/audit-logger.js +281 -0
  38. package/dist/security/audit-logger.js.map +1 -0
  39. package/dist/security/cli-security.d.ts +143 -0
  40. package/dist/security/cli-security.js +302 -0
  41. package/dist/security/cli-security.js.map +1 -0
  42. package/dist/security/defaults.d.ts +31 -0
  43. package/dist/security/defaults.js +72 -0
  44. package/dist/security/defaults.js.map +1 -0
  45. package/dist/security/events.d.ts +8 -0
  46. package/dist/security/index.d.ts +27 -0
  47. package/dist/security/index.js +22 -0
  48. package/dist/security/index.js.map +1 -0
  49. package/dist/security/path-guard.d.ts +161 -0
  50. package/dist/security/path-guard.js +327 -0
  51. package/dist/security/path-guard.js.map +1 -0
  52. package/dist/security/rate-limiter.d.ts +117 -0
  53. package/dist/security/rate-limiter.js +165 -0
  54. package/dist/security/rate-limiter.js.map +1 -0
  55. package/dist/security/serialization-schemas.d.ts +183 -0
  56. package/dist/security/serialization-schemas.js +174 -0
  57. package/dist/security/serialization-schemas.js.map +1 -0
  58. package/dist/security/timeout-guard.d.ts +123 -0
  59. package/dist/security/timeout-guard.js +223 -0
  60. package/dist/security/timeout-guard.js.map +1 -0
  61. package/dist/security/types.d.ts +86 -0
  62. package/dist/security/types.js +80 -0
  63. package/dist/security/types.js.map +1 -0
  64. package/dist/token-budget.js +1 -1
  65. package/dist/tools.js +1 -1
  66. package/guide/index.md +2 -0
  67. package/guide/integration.md +1109 -0
  68. package/guide/security.md +237 -0
  69. package/package.json +18 -11
@@ -0,0 +1,1109 @@
1
+ # Integration Guide
2
+
3
+ **Purpose**: Comprehensive guide for integrating RiotPrompt into your application as a library.
4
+
5
+ This guide covers the core concepts, configuration options, and code patterns for using RiotPrompt programmatically. It is intended for developers building LLM-powered applications who want to leverage RiotPrompt's structured prompt engineering capabilities.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @riotprompt/riotprompt
11
+ ```
12
+
13
+ For lighter installs, you can use individual packages:
14
+
15
+ ```bash
16
+ # Core prompt engineering (no SDK dependencies)
17
+ npm install @riotprompt/riotprompt
18
+
19
+ # Provider-specific execution
20
+ npm install @riotprompt/execution-openai
21
+ npm install @riotprompt/execution-anthropic
22
+ npm install @riotprompt/execution-gemini
23
+
24
+ # Agentic features (tool registry, context management)
25
+ npm install @riotprompt/agentic
26
+ ```
27
+
28
+ ## Core Concepts
29
+
30
+ ### Prompts as Structured Objects
31
+
32
+ RiotPrompt treats prompts as structured data objects rather than simple strings. A `Prompt` contains multiple specialized sections:
33
+
34
+ | Section | Purpose | Example |
35
+ |---------|---------|---------|
36
+ | `persona` | Who the AI is (system prompt) | "You are a senior code reviewer" |
37
+ | `instructions` | What the AI should do | "Review this pull request" |
38
+ | `content` | Input data to process | The actual PR diff |
39
+ | `context` | Background information | Project guidelines, coding standards |
40
+ | `constraints` | Hard rules and limitations | "Do not suggest refactoring" |
41
+ | `tone` | Style guidelines | "Be constructive and empathetic" |
42
+ | `examples` | Few-shot examples | Sample reviews |
43
+ | `reasoning` | Thinking instructions | "Think step-by-step" |
44
+ | `responseFormat` | Output structure | "Return as JSON" |
45
+ | `recap` | Final reminders | "Remember to check for security issues" |
46
+ | `safeguards` | Safety guidelines | "Do not execute code" |
47
+
48
+ ### Section System
49
+
50
+ Sections are hierarchical containers that can hold items and nested sections:
51
+
52
+ ```typescript
53
+ import { createSection, createInstruction } from '@riotprompt/riotprompt';
54
+
55
+ const instructions = createSection<Instruction>('Instructions');
56
+ instructions.add(createInstruction('Analyze the code for bugs'));
57
+ instructions.add(createInstruction('Check for security vulnerabilities'));
58
+
59
+ // Nested sections
60
+ const advanced = createSection<Instruction>('Advanced Checks');
61
+ advanced.add(createInstruction('Review performance implications'));
62
+ instructions.addSection(advanced);
63
+ ```
64
+
65
+ ### Weighted Items
66
+
67
+ Items can have weights for prioritization:
68
+
69
+ ```typescript
70
+ import { createWeighted } from '@riotprompt/riotprompt';
71
+
72
+ const highPriority = createWeighted('Critical security check', { weight: 1.0 });
73
+ const lowPriority = createWeighted('Style suggestions', { weight: 0.3 });
74
+ ```
75
+
76
+ ## Creating Prompts
77
+
78
+ ### Using the Recipes API (Recommended)
79
+
80
+ The `cook` function is the primary entry point for creating prompts:
81
+
82
+ ```typescript
83
+ import { cook } from '@riotprompt/riotprompt';
84
+
85
+ const prompt = await cook({
86
+ basePath: __dirname,
87
+ persona: { content: 'You are a helpful AI assistant.' },
88
+ instructions: [
89
+ { content: 'Summarize the provided text.' },
90
+ { content: 'Extract key points.' }
91
+ ],
92
+ content: [
93
+ { content: 'Text to summarize goes here...' }
94
+ ]
95
+ });
96
+ ```
97
+
98
+ ### Content Items
99
+
100
+ Content items can be specified in multiple ways:
101
+
102
+ ```typescript
103
+ const prompt = await cook({
104
+ basePath: __dirname,
105
+ persona: { content: 'You are an analyst.' },
106
+
107
+ // Simple string content
108
+ instructions: [
109
+ { content: 'Analyze this data' }
110
+ ],
111
+
112
+ // Content with title and weight
113
+ context: [
114
+ { content: 'Background info', title: 'Context', weight: 0.8 }
115
+ ],
116
+
117
+ // Load from file
118
+ examples: [
119
+ { path: './examples/good-analysis.md', title: 'Example' }
120
+ ],
121
+
122
+ // Load from directories
123
+ content: [
124
+ { directories: ['./data'], title: 'Input Data' }
125
+ ]
126
+ });
127
+ ```
128
+
129
+ ### Using the Fluent Builder API
130
+
131
+ For more dynamic prompt construction:
132
+
133
+ ```typescript
134
+ import { recipe } from '@riotprompt/riotprompt';
135
+
136
+ const prompt = await recipe(__dirname)
137
+ .persona({ content: 'You are a code reviewer' })
138
+ .instructions({ content: 'Review this code' })
139
+ .constraints({ content: 'Focus on security' })
140
+ .content({ content: codeToReview })
141
+ .cook();
142
+ ```
143
+
144
+ ### Using Templates
145
+
146
+ Register reusable templates for consistency:
147
+
148
+ ```typescript
149
+ import { registerTemplates, cook, getTemplates, clearTemplates } from '@riotprompt/riotprompt';
150
+
151
+ // Register templates
152
+ registerTemplates({
153
+ 'code-review': {
154
+ persona: { content: 'You are a senior code reviewer.' },
155
+ constraints: [{ content: 'Be constructive.' }],
156
+ tone: [{ content: 'Professional and helpful.' }]
157
+ },
158
+ 'security-audit': {
159
+ persona: { content: 'You are a security auditor.' },
160
+ constraints: [{ content: 'Report only high-severity issues.' }]
161
+ }
162
+ });
163
+
164
+ // Use a template
165
+ const prompt = await cook({
166
+ basePath: __dirname,
167
+ template: 'code-review',
168
+ content: [{ content: prDiff }]
169
+ });
170
+
171
+ // Extend a template
172
+ const prompt2 = await cook({
173
+ basePath: __dirname,
174
+ extends: 'security-audit',
175
+ instructions: [{ content: 'Focus on SQL injection vulnerabilities.' }],
176
+ content: [{ content: sourceCode }]
177
+ });
178
+
179
+ // List registered templates
180
+ const templates = getTemplates();
181
+
182
+ // Clear all templates
183
+ clearTemplates();
184
+ ```
185
+
186
+ ## Structured Outputs
187
+
188
+ RiotPrompt supports portable structured outputs using Zod schemas:
189
+
190
+ ```typescript
191
+ import { cook } from '@riotprompt/riotprompt';
192
+ import { z } from 'zod';
193
+
194
+ // Define your schema
195
+ const AnalysisSchema = z.object({
196
+ sentiment: z.enum(['positive', 'negative', 'neutral']),
197
+ keyPoints: z.array(z.string()),
198
+ confidence: z.number().min(0).max(1),
199
+ summary: z.string()
200
+ });
201
+
202
+ // Pass to cook
203
+ const prompt = await cook({
204
+ basePath: __dirname,
205
+ persona: { content: 'You are a sentiment analyzer.' },
206
+ content: [{ content: textToAnalyze }],
207
+ schema: AnalysisSchema
208
+ });
209
+
210
+ // The schema is automatically adapted for different providers
211
+ // (JSON Schema for OpenAI, Tool Use for Anthropic, etc.)
212
+ ```
213
+
214
+ ## Model Configuration
215
+
216
+ ### Default Model Mappings
217
+
218
+ RiotPrompt automatically handles model-specific formatting:
219
+
220
+ | Model Family | Persona Role | Encoding |
221
+ |--------------|--------------|----------|
222
+ | Claude | `system` | `cl100k_base` |
223
+ | GPT-4 | `system` | `gpt-4o` |
224
+ | O-series (o1, o2) | `developer` | `gpt-4o` |
225
+
226
+ ### Custom Model Configuration
227
+
228
+ Register custom models:
229
+
230
+ ```typescript
231
+ import { configureModel, getModelRegistry } from '@riotprompt/riotprompt';
232
+
233
+ // Register a custom model
234
+ configureModel({
235
+ exactMatch: 'my-local-llama',
236
+ personaRole: 'system',
237
+ encoding: 'cl100k_base',
238
+ family: 'llama',
239
+ supportsToolCalls: true
240
+ });
241
+
242
+ // Pattern-based matching
243
+ configureModel({
244
+ pattern: /^llama-\d+/,
245
+ personaRole: 'system',
246
+ encoding: 'cl100k_base',
247
+ family: 'llama'
248
+ });
249
+
250
+ // Access the registry
251
+ const registry = getModelRegistry();
252
+ ```
253
+
254
+ ## Formatting Prompts
255
+
256
+ ### For Different Models
257
+
258
+ ```typescript
259
+ import { Formatter, cook } from '@riotprompt/riotprompt';
260
+
261
+ const prompt = await cook({
262
+ basePath: __dirname,
263
+ persona: { content: 'You are a helpful assistant.' },
264
+ instructions: [{ content: 'Help the user.' }]
265
+ });
266
+
267
+ // Create formatter
268
+ const formatter = Formatter.create();
269
+
270
+ // Format for specific model (handles role mapping automatically)
271
+ const openaiRequest = formatter.formatPrompt('gpt-4o', prompt);
272
+ const claudeRequest = formatter.formatPrompt('claude-3-opus', prompt);
273
+ const o1Request = formatter.formatPrompt('o1', prompt); // Uses 'developer' role
274
+ ```
275
+
276
+ ### Custom Format Options
277
+
278
+ ```typescript
279
+ const formatter = Formatter.create({
280
+ sectionSeparator: '\n\n---\n\n',
281
+ sectionTitleProperty: 'header',
282
+ includeWeights: true
283
+ });
284
+ ```
285
+
286
+ ## Serialization
287
+
288
+ ### Export and Import Prompts
289
+
290
+ ```typescript
291
+ import { Serializer, cook } from '@riotprompt/riotprompt';
292
+
293
+ const prompt = await cook({
294
+ basePath: __dirname,
295
+ persona: { content: 'You are an assistant.' },
296
+ instructions: [{ content: 'Help users.' }]
297
+ });
298
+
299
+ // Export to JSON
300
+ const json = Serializer.toJSON(prompt);
301
+
302
+ // Export to XML
303
+ const xml = Serializer.toXML(prompt);
304
+
305
+ // Import from JSON
306
+ const restored = Serializer.fromJSON(json);
307
+
308
+ // Import from XML
309
+ const restoredXml = Serializer.fromXML(xml);
310
+ ```
311
+
312
+ ## Loading from Filesystem
313
+
314
+ ### Directory Structure
315
+
316
+ RiotPrompt can load prompts from a structured directory:
317
+
318
+ ```
319
+ my-prompt/
320
+ ├── persona.md # OR persona/ directory
321
+ ├── instructions.md # OR instructions/ directory
322
+ ├── context/ # Reference files
323
+ │ ├── data.json
324
+ │ └── background.md
325
+ ├── constraints.md
326
+ ├── tone.md
327
+ └── examples.md
328
+ ```
329
+
330
+ ### Using the Loader
331
+
332
+ ```typescript
333
+ import { Loader } from '@riotprompt/riotprompt';
334
+
335
+ // Create loader
336
+ const loader = Loader.create({
337
+ basePath: './prompts/my-prompt',
338
+ ignorePatterns: ['*.test.md', 'drafts/**']
339
+ });
340
+
341
+ // Load context from directories
342
+ const context = await loader.load(['./context', './reference']);
343
+ ```
344
+
345
+ ## Conversation Management
346
+
347
+ ### ConversationBuilder
348
+
349
+ Manage multi-turn conversations:
350
+
351
+ ```typescript
352
+ import { ConversationBuilder, cook } from '@riotprompt/riotprompt';
353
+
354
+ // Create from prompt
355
+ const prompt = await cook({
356
+ basePath: __dirname,
357
+ persona: { content: 'You are a helpful assistant.' },
358
+ instructions: [{ content: 'Help users with their questions.' }]
359
+ });
360
+
361
+ const conversation = ConversationBuilder.create({ model: 'gpt-4o' })
362
+ .fromPrompt(prompt, 'gpt-4o')
363
+ .build();
364
+
365
+ // Add messages
366
+ conversation.addUserMessage('What is TypeScript?');
367
+ conversation.addAssistantMessage('TypeScript is a typed superset of JavaScript...');
368
+ conversation.addUserMessage('How do I install it?');
369
+
370
+ // Get messages for API call
371
+ const messages = conversation.toMessages();
372
+ ```
373
+
374
+ ### Semantic Message Methods
375
+
376
+ Use semantic methods for clearer code:
377
+
378
+ ```typescript
379
+ const conversation = ConversationBuilder.create({ model: 'gpt-4o' })
380
+ .fromPrompt(prompt, 'gpt-4o')
381
+ .asUser('Analyze this code')
382
+ .asAssistant('I see several issues...')
383
+ .asUser('Can you fix them?')
384
+ .build();
385
+ ```
386
+
387
+ ### Context Injection
388
+
389
+ Inject dynamic context into conversations:
390
+
391
+ ```typescript
392
+ conversation.injectContext([
393
+ {
394
+ id: 'file-1',
395
+ content: 'Contents of main.ts...',
396
+ title: 'Source File',
397
+ category: 'code',
398
+ priority: 'high'
399
+ },
400
+ {
401
+ id: 'docs-1',
402
+ content: 'API documentation...',
403
+ title: 'Documentation',
404
+ category: 'reference',
405
+ priority: 'medium'
406
+ }
407
+ ], {
408
+ position: 'after-system',
409
+ format: 'structured',
410
+ deduplicate: true,
411
+ deduplicateBy: 'id'
412
+ });
413
+ ```
414
+
415
+ ### Token Budget Management
416
+
417
+ Manage token usage:
418
+
419
+ ```typescript
420
+ const conversation = ConversationBuilder.create({ model: 'gpt-4o' })
421
+ .fromPrompt(prompt, 'gpt-4o')
422
+ .withTokenBudget({
423
+ max: 100000,
424
+ reserve: 4000, // Reserve for response
425
+ compressionStrategy: 'summarize'
426
+ })
427
+ .build();
428
+
429
+ // Check usage
430
+ const usage = conversation.getTokenUsage();
431
+ console.log(`Used: ${usage.used}/${usage.max} (${usage.percentage}%)`);
432
+
433
+ // Manually compress if needed
434
+ conversation.compress();
435
+ ```
436
+
437
+ ### Conversation Logging
438
+
439
+ Log conversations for debugging and replay:
440
+
441
+ ```typescript
442
+ const conversation = ConversationBuilder.create({ model: 'gpt-4o' })
443
+ .fromPrompt(prompt, 'gpt-4o')
444
+ .withLogging({
445
+ outputPath: './logs',
446
+ format: 'json',
447
+ includeMetadata: true
448
+ })
449
+ .build();
450
+
451
+ // ... use conversation ...
452
+
453
+ // Save log
454
+ const logPath = await conversation.saveLog();
455
+ ```
456
+
457
+ ### Serialization and Cloning
458
+
459
+ ```typescript
460
+ // Serialize for persistence
461
+ const json = conversation.toJSON();
462
+
463
+ // Restore later
464
+ const restored = ConversationBuilder.fromJSON(json, { model: 'gpt-4o' });
465
+
466
+ // Clone for parallel exploration
467
+ const branch = conversation.clone();
468
+ branch.addUserMessage('What if we tried a different approach?');
469
+ ```
470
+
471
+ ## Tool Integration
472
+
473
+ ### ToolRegistry
474
+
475
+ Register and manage tools:
476
+
477
+ ```typescript
478
+ import { ToolRegistry } from '@riotprompt/riotprompt';
479
+
480
+ const registry = ToolRegistry.create({
481
+ workingDirectory: process.cwd()
482
+ });
483
+
484
+ // Register a tool
485
+ registry.register({
486
+ name: 'read_file',
487
+ description: 'Read contents of a file',
488
+ category: 'filesystem',
489
+ cost: 'cheap',
490
+ parameters: {
491
+ type: 'object',
492
+ properties: {
493
+ path: {
494
+ type: 'string',
495
+ description: 'Path to the file'
496
+ }
497
+ },
498
+ required: ['path']
499
+ },
500
+ execute: async ({ path }) => {
501
+ const fs = await import('fs/promises');
502
+ return await fs.readFile(path, 'utf-8');
503
+ }
504
+ });
505
+
506
+ // Register multiple tools
507
+ registry.registerAll([tool1, tool2, tool3]);
508
+ ```
509
+
510
+ ### Executing Tools
511
+
512
+ ```typescript
513
+ // Execute a single tool
514
+ const content = await registry.execute('read_file', { path: 'README.md' });
515
+
516
+ // Execute batch
517
+ const results = await registry.executeBatch([
518
+ { name: 'read_file', params: { path: 'file1.ts' } },
519
+ { name: 'read_file', params: { path: 'file2.ts' } }
520
+ ]);
521
+
522
+ // Get usage statistics
523
+ const stats = registry.getUsageStats();
524
+ console.log(stats.get('read_file'));
525
+ // { calls: 3, failures: 0, successRate: 1, averageDuration: 5 }
526
+ ```
527
+
528
+ ### Export for Providers
529
+
530
+ ```typescript
531
+ // Export for OpenAI
532
+ const openaiTools = registry.toOpenAIFormat();
533
+
534
+ // Export for Anthropic
535
+ const anthropicTools = registry.toAnthropicFormat();
536
+
537
+ // Get definitions (without execute functions)
538
+ const definitions = registry.getDefinitions();
539
+ ```
540
+
541
+ ### Tool Guidance Generation
542
+
543
+ Generate tool usage instructions for prompts:
544
+
545
+ ```typescript
546
+ import { generateToolGuidance, cook } from '@riotprompt/riotprompt';
547
+
548
+ const guidance = generateToolGuidance(registry.getAll(), {
549
+ style: 'detailed', // 'minimal' | 'detailed' | 'auto'
550
+ includeExamples: true
551
+ });
552
+
553
+ const prompt = await cook({
554
+ basePath: __dirname,
555
+ persona: { content: 'You are an assistant with tools.' },
556
+ instructions: [{ content: guidance }],
557
+ tools: registry
558
+ });
559
+ ```
560
+
561
+ ## Agentic Interactions
562
+
563
+ ### Iteration Strategies
564
+
565
+ Execute multi-step agentic workflows:
566
+
567
+ ```typescript
568
+ import {
569
+ StrategyExecutor,
570
+ IterationStrategyFactory,
571
+ ConversationBuilder,
572
+ ToolRegistry
573
+ } from '@riotprompt/riotprompt';
574
+
575
+ // Create LLM client (provider-specific)
576
+ const llmClient = {
577
+ async complete(messages, tools) {
578
+ // Call your LLM provider
579
+ const response = await openai.chat.completions.create({
580
+ model: 'gpt-4o',
581
+ messages,
582
+ tools
583
+ });
584
+ return {
585
+ content: response.choices[0].message.content,
586
+ tool_calls: response.choices[0].message.tool_calls
587
+ };
588
+ }
589
+ };
590
+
591
+ // Create executor
592
+ const executor = new StrategyExecutor(llmClient);
593
+
594
+ // Execute with a strategy
595
+ const result = await executor.execute(
596
+ conversation,
597
+ toolRegistry,
598
+ IterationStrategyFactory.investigateThenRespond({
599
+ maxInvestigationSteps: 5,
600
+ requireMinimumTools: 1,
601
+ finalSynthesis: true
602
+ })
603
+ );
604
+
605
+ console.log('Completed in', result.totalIterations, 'iterations');
606
+ console.log('Used', result.toolCallsExecuted, 'tool calls');
607
+ ```
608
+
609
+ ### Pre-built Strategies
610
+
611
+ ```typescript
612
+ // Investigate then respond (gather info, then synthesize)
613
+ const strategy1 = IterationStrategyFactory.investigateThenRespond({
614
+ maxInvestigationSteps: 5,
615
+ requireMinimumTools: 1
616
+ });
617
+
618
+ // Multi-pass refinement (generate, critique, refine)
619
+ const strategy2 = IterationStrategyFactory.multiPassRefinement({
620
+ passes: 3,
621
+ critiqueBetweenPasses: true
622
+ });
623
+
624
+ // Breadth-first (explore broadly before going deep)
625
+ const strategy3 = IterationStrategyFactory.breadthFirst({
626
+ levelsDeep: 3,
627
+ toolsPerLevel: 4
628
+ });
629
+
630
+ // Depth-first (deep dive immediately)
631
+ const strategy4 = IterationStrategyFactory.depthFirst({
632
+ maxDepth: 5,
633
+ backtrackOnFailure: true
634
+ });
635
+
636
+ // Simple loop (basic tool-use iteration)
637
+ const strategy5 = IterationStrategyFactory.simple({
638
+ maxIterations: 10,
639
+ allowTools: true
640
+ });
641
+
642
+ // Adaptive (changes behavior based on progress)
643
+ const strategy6 = IterationStrategyFactory.adaptive();
644
+ ```
645
+
646
+ ### Custom Strategies
647
+
648
+ Create custom iteration strategies:
649
+
650
+ ```typescript
651
+ import type { IterationStrategy, StrategyPhase } from '@riotprompt/riotprompt';
652
+
653
+ const customStrategy: IterationStrategy = {
654
+ name: 'custom-workflow',
655
+ description: 'My custom agentic workflow',
656
+ maxIterations: 15,
657
+
658
+ phases: [
659
+ {
660
+ name: 'discovery',
661
+ maxIterations: 5,
662
+ toolUsage: 'encouraged',
663
+ allowedTools: ['search', 'read_file'],
664
+ minToolCalls: 2
665
+ },
666
+ {
667
+ name: 'analysis',
668
+ maxIterations: 3,
669
+ toolUsage: 'optional',
670
+ instructions: 'Analyze what you discovered'
671
+ },
672
+ {
673
+ name: 'synthesis',
674
+ maxIterations: 1,
675
+ toolUsage: 'forbidden',
676
+ requireFinalAnswer: true
677
+ }
678
+ ],
679
+
680
+ // Lifecycle hooks
681
+ onStart: async (context) => {
682
+ console.log('Starting workflow...');
683
+ },
684
+
685
+ onIteration: async (iteration, state) => {
686
+ if (state.errors.length > 3) {
687
+ return 'stop';
688
+ }
689
+ return 'continue';
690
+ },
691
+
692
+ onToolCall: async (toolCall, state) => {
693
+ // Skip expensive tools after 10 calls
694
+ if (state.toolCallsExecuted > 10) {
695
+ const tool = toolCall.function.name;
696
+ if (tool === 'expensive_operation') {
697
+ return 'skip';
698
+ }
699
+ }
700
+ return 'execute';
701
+ },
702
+
703
+ onToolResult: async (result, state) => {
704
+ // Track insights from tool results
705
+ if (result.result?.important) {
706
+ state.insights.push({
707
+ source: result.toolName,
708
+ content: result.result.important,
709
+ confidence: 0.8
710
+ });
711
+ }
712
+ },
713
+
714
+ onComplete: async (result) => {
715
+ console.log('Workflow complete:', result.success);
716
+ }
717
+ };
718
+ ```
719
+
720
+ ### Reflection and Metrics
721
+
722
+ Generate execution reports:
723
+
724
+ ```typescript
725
+ const executor = new StrategyExecutor(llmClient)
726
+ .withReflection({
727
+ enabled: true,
728
+ outputPath: './reflections',
729
+ format: 'markdown', // or 'json'
730
+ includeRecommendations: true
731
+ });
732
+
733
+ const result = await executor.execute(conversation, tools, strategy);
734
+
735
+ // Access reflection report
736
+ if (result.reflection) {
737
+ console.log('Tool Effectiveness:', result.reflection.toolEffectiveness);
738
+ console.log('Recommendations:', result.reflection.recommendations);
739
+ console.log('Quality Assessment:', result.reflection.qualityAssessment);
740
+ }
741
+ ```
742
+
743
+ ## Security Features
744
+
745
+ ### Path Security
746
+
747
+ Prevent path traversal attacks:
748
+
749
+ ```typescript
750
+ import { Security } from '@riotprompt/riotprompt';
751
+
752
+ const pathGuard = Security.createPathGuard({
753
+ allowedPaths: ['/app/data', '/app/uploads'],
754
+ blockedPatterns: ['..', '~'],
755
+ maxPathLength: 255
756
+ });
757
+
758
+ // Validate paths
759
+ const isValid = pathGuard.validate('/app/data/file.txt'); // true
760
+ const isInvalid = pathGuard.validate('../etc/passwd'); // false
761
+ ```
762
+
763
+ ### Secret Redaction
764
+
765
+ Protect sensitive data in logs:
766
+
767
+ ```typescript
768
+ import { configureSecureLogging, maskSensitive } from '@riotprompt/riotprompt';
769
+
770
+ // Configure secure logging
771
+ configureSecureLogging({
772
+ maskPatterns: [
773
+ /api[_-]?key/i,
774
+ /password/i,
775
+ /secret/i,
776
+ /token/i
777
+ ],
778
+ replacement: '[REDACTED]'
779
+ });
780
+
781
+ // Mask sensitive data
782
+ const safe = maskSensitive({
783
+ apiKey: 'sk-1234567890',
784
+ data: 'normal data'
785
+ });
786
+ // { apiKey: '[REDACTED]', data: 'normal data' }
787
+ ```
788
+
789
+ ### Error Handling
790
+
791
+ Sanitize errors before logging:
792
+
793
+ ```typescript
794
+ import {
795
+ initializeErrorHandling,
796
+ withErrorHandling,
797
+ formatErrorForDisplay
798
+ } from '@riotprompt/riotprompt';
799
+
800
+ // Initialize
801
+ initializeErrorHandling({
802
+ sanitizePaths: true,
803
+ redactSecrets: true
804
+ });
805
+
806
+ // Wrap async functions
807
+ const safeFunction = withErrorHandling(async () => {
808
+ // Your code here
809
+ });
810
+
811
+ // Format errors for display
812
+ try {
813
+ await riskyOperation();
814
+ } catch (error) {
815
+ const displayError = formatErrorForDisplay(error);
816
+ console.error(displayError); // Sanitized error message
817
+ }
818
+ ```
819
+
820
+ ## Logging
821
+
822
+ ### Secure Logging
823
+
824
+ ```typescript
825
+ import {
826
+ configureSecureLogging,
827
+ executeWithCorrelation,
828
+ RiotPromptLogger
829
+ } from '@riotprompt/riotprompt';
830
+
831
+ // Configure
832
+ configureSecureLogging({
833
+ level: 'info',
834
+ maskSecrets: true,
835
+ includeCorrelationId: true
836
+ });
837
+
838
+ // Execute with correlation ID
839
+ await executeWithCorrelation(async (correlationId) => {
840
+ const logger = new RiotPromptLogger({ correlationId });
841
+ logger.info('Processing request', { userId: '123' });
842
+ // All logs in this context share the correlation ID
843
+ });
844
+ ```
845
+
846
+ ### Custom Logger Integration
847
+
848
+ ```typescript
849
+ import { createConsoleLogger, wrapLogger } from '@riotprompt/riotprompt';
850
+
851
+ // Use built-in console logger
852
+ const logger = createConsoleLogger({ level: 'debug' });
853
+
854
+ // Wrap existing logger
855
+ const wrapped = wrapLogger(myExistingLogger, 'MyComponent');
856
+
857
+ // Pass to components
858
+ const conversation = ConversationBuilder.create(
859
+ { model: 'gpt-4o' },
860
+ logger
861
+ );
862
+ ```
863
+
864
+ ## Complete Integration Example
865
+
866
+ Here's a complete example showing how to integrate RiotPrompt into an application:
867
+
868
+ ```typescript
869
+ import {
870
+ cook,
871
+ registerTemplates,
872
+ ConversationBuilder,
873
+ ToolRegistry,
874
+ StrategyExecutor,
875
+ IterationStrategyFactory,
876
+ configureModel,
877
+ configureSecureLogging
878
+ } from '@riotprompt/riotprompt';
879
+ import { z } from 'zod';
880
+
881
+ // 1. Configure security
882
+ configureSecureLogging({
883
+ maskSecrets: true,
884
+ level: 'info'
885
+ });
886
+
887
+ // 2. Register custom models (if needed)
888
+ configureModel({
889
+ exactMatch: 'my-custom-model',
890
+ personaRole: 'system',
891
+ encoding: 'cl100k_base',
892
+ family: 'custom'
893
+ });
894
+
895
+ // 3. Register templates
896
+ registerTemplates({
897
+ 'code-assistant': {
898
+ persona: { content: 'You are an expert software engineer.' },
899
+ constraints: [{ content: 'Write clean, maintainable code.' }],
900
+ tone: [{ content: 'Be helpful and educational.' }]
901
+ }
902
+ });
903
+
904
+ // 4. Define output schema
905
+ const CodeReviewSchema = z.object({
906
+ issues: z.array(z.object({
907
+ severity: z.enum(['critical', 'warning', 'info']),
908
+ line: z.number().optional(),
909
+ message: z.string(),
910
+ suggestion: z.string().optional()
911
+ })),
912
+ summary: z.string(),
913
+ score: z.number().min(0).max(100)
914
+ });
915
+
916
+ // 5. Create tools
917
+ const toolRegistry = ToolRegistry.create({ workingDirectory: process.cwd() });
918
+
919
+ toolRegistry.register({
920
+ name: 'read_file',
921
+ description: 'Read a source file',
922
+ category: 'filesystem',
923
+ parameters: {
924
+ type: 'object',
925
+ properties: {
926
+ path: { type: 'string', description: 'File path' }
927
+ },
928
+ required: ['path']
929
+ },
930
+ execute: async ({ path }) => {
931
+ const fs = await import('fs/promises');
932
+ return await fs.readFile(path, 'utf-8');
933
+ }
934
+ });
935
+
936
+ toolRegistry.register({
937
+ name: 'list_files',
938
+ description: 'List files in a directory',
939
+ category: 'filesystem',
940
+ parameters: {
941
+ type: 'object',
942
+ properties: {
943
+ directory: { type: 'string', description: 'Directory path' }
944
+ },
945
+ required: ['directory']
946
+ },
947
+ execute: async ({ directory }) => {
948
+ const fs = await import('fs/promises');
949
+ return await fs.readdir(directory);
950
+ }
951
+ });
952
+
953
+ // 6. Create prompt
954
+ async function createCodeReviewPrompt(prDescription: string) {
955
+ return await cook({
956
+ basePath: __dirname,
957
+ template: 'code-assistant',
958
+ instructions: [
959
+ { content: 'Review the code changes in this pull request.' },
960
+ { content: 'Use tools to read the relevant files.' },
961
+ { content: 'Identify bugs, security issues, and improvements.' }
962
+ ],
963
+ content: [
964
+ { content: prDescription, title: 'Pull Request' }
965
+ ],
966
+ schema: CodeReviewSchema,
967
+ tools: toolRegistry,
968
+ toolGuidance: 'detailed'
969
+ });
970
+ }
971
+
972
+ // 7. Create LLM client
973
+ function createLLMClient(apiKey: string) {
974
+ return {
975
+ async complete(messages: any[], tools?: any[]) {
976
+ // Your LLM provider integration
977
+ const response = await fetch('https://api.openai.com/v1/chat/completions', {
978
+ method: 'POST',
979
+ headers: {
980
+ 'Authorization': `Bearer ${apiKey}`,
981
+ 'Content-Type': 'application/json'
982
+ },
983
+ body: JSON.stringify({
984
+ model: 'gpt-4o',
985
+ messages,
986
+ tools
987
+ })
988
+ });
989
+
990
+ const data = await response.json();
991
+ return {
992
+ content: data.choices[0].message.content,
993
+ tool_calls: data.choices[0].message.tool_calls
994
+ };
995
+ }
996
+ };
997
+ }
998
+
999
+ // 8. Execute agentic workflow
1000
+ async function reviewPullRequest(prDescription: string, apiKey: string) {
1001
+ const prompt = await createCodeReviewPrompt(prDescription);
1002
+
1003
+ const conversation = ConversationBuilder.create({ model: 'gpt-4o' })
1004
+ .fromPrompt(prompt, 'gpt-4o')
1005
+ .withTokenBudget({ max: 100000, reserve: 4000 })
1006
+ .withLogging({ outputPath: './logs', format: 'json' })
1007
+ .build();
1008
+
1009
+ const llmClient = createLLMClient(apiKey);
1010
+
1011
+ const executor = new StrategyExecutor(llmClient)
1012
+ .withReflection({
1013
+ enabled: true,
1014
+ outputPath: './reflections',
1015
+ format: 'markdown'
1016
+ });
1017
+
1018
+ const result = await executor.execute(
1019
+ conversation,
1020
+ toolRegistry,
1021
+ IterationStrategyFactory.investigateThenRespond({
1022
+ maxInvestigationSteps: 10,
1023
+ requireMinimumTools: 2
1024
+ })
1025
+ );
1026
+
1027
+ // Save conversation log
1028
+ await conversation.saveLog();
1029
+
1030
+ return {
1031
+ review: result.finalMessage?.content,
1032
+ iterations: result.totalIterations,
1033
+ toolsUsed: result.toolCallsExecuted,
1034
+ reflection: result.reflection
1035
+ };
1036
+ }
1037
+
1038
+ // Usage
1039
+ const result = await reviewPullRequest(
1040
+ 'Add user authentication with JWT tokens',
1041
+ process.env.OPENAI_API_KEY!
1042
+ );
1043
+
1044
+ console.log('Review:', result.review);
1045
+ console.log('Completed in', result.iterations, 'iterations');
1046
+ ```
1047
+
1048
+ ## Type Reference
1049
+
1050
+ ### Core Types
1051
+
1052
+ ```typescript
1053
+ import type {
1054
+ // Prompt structure
1055
+ Prompt,
1056
+ Section,
1057
+ Content,
1058
+ Context,
1059
+ Instruction,
1060
+ Weighted,
1061
+ Parameters,
1062
+
1063
+ // Recipes
1064
+ RecipeConfig,
1065
+ ContentItem,
1066
+ TemplateConfig,
1067
+ ToolGuidanceConfig,
1068
+
1069
+ // Conversation
1070
+ ConversationMessage,
1071
+ ConversationBuilderConfig,
1072
+ ConversationMetadata,
1073
+ ToolCall,
1074
+ InjectOptions,
1075
+
1076
+ // Tools
1077
+ Tool,
1078
+ ToolParameter,
1079
+ ToolContext,
1080
+ ToolDefinition,
1081
+ ToolUsageStats,
1082
+
1083
+ // Strategies
1084
+ IterationStrategy,
1085
+ StrategyPhase,
1086
+ StrategyState,
1087
+ StrategyResult,
1088
+ ToolUsagePolicy,
1089
+
1090
+ // Reflection
1091
+ ReflectionReport,
1092
+ ReflectionConfig,
1093
+
1094
+ // Model config
1095
+ ModelConfig,
1096
+ PersonaRole,
1097
+
1098
+ // Security
1099
+ SecurityConfig,
1100
+ PathSecurityConfig
1101
+ } from '@riotprompt/riotprompt';
1102
+ ```
1103
+
1104
+ ## Next Steps
1105
+
1106
+ - [Architecture](./architecture.md): Understand the internal design
1107
+ - [Configuration](./configuration.md): Deep dive into configuration options
1108
+ - [Security](./security.md): Security best practices
1109
+ - [Usage Patterns](./usage.md): CLI and common patterns