@eldrforge/kodrdriv 1.2.131 → 1.2.132

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.
@@ -13,174 +13,32 @@ import { sanitizeDirection } from '../util/validation.js';
13
13
  import { filterContent } from '../util/stopContext.js';
14
14
  import { getOutputPath, getTimestampedResponseFilename, getTimestampedRequestFilename, getTimestampedCommitFilename } from '../util/general.js';
15
15
  import { getRecentClosedIssuesForCommit } from '@eldrforge/github-tools';
16
- import { runAgenticCommit, createCommitPrompt, createCompletionWithRetry, requireTTY, getUserChoice, STANDARD_CHOICES, getLLMFeedbackInEditor, editContentInEditor } from '@eldrforge/ai-service';
16
+ import { runAgenticCommit, createCommitPrompt, createCompletionWithRetry, requireTTY, generateReflectionReport, getUserChoice, STANDARD_CHOICES, getLLMFeedbackInEditor, editContentInEditor } from '@eldrforge/ai-service';
17
17
  import { improveContentWithLLM } from '../util/interactive.js';
18
18
  import { toAIConfig } from '../util/aiAdapter.js';
19
19
  import { createStorageAdapter } from '../util/storageAdapter.js';
20
20
  import { createLoggerAdapter } from '../util/loggerAdapter.js';
21
21
 
22
- // Helper function to generate self-reflection output
22
+ // Helper function to generate self-reflection output using observability module
23
23
  async function generateSelfReflection(agenticResult, outputDirectory, storage, logger) {
24
24
  try {
25
25
  const timestamp = new Date().toISOString().replace(/[:.]/g, '-').split('.')[0];
26
26
  const reflectionPath = getOutputPath(outputDirectory, `agentic-reflection-commit-${timestamp}.md`);
27
- // Calculate tool effectiveness metrics
28
- const toolMetrics = agenticResult.toolMetrics || [];
29
- const toolStats = new Map();
30
- for (const metric of toolMetrics){
31
- if (!toolStats.has(metric.name)) {
32
- toolStats.set(metric.name, {
33
- total: 0,
34
- success: 0,
35
- failures: 0,
36
- totalDuration: 0
37
- });
38
- }
39
- const stats = toolStats.get(metric.name);
40
- stats.total++;
41
- stats.totalDuration += metric.duration;
42
- if (metric.success) {
43
- stats.success++;
44
- } else {
45
- stats.failures++;
46
- }
47
- }
48
- // Build reflection document
49
- const sections = [];
50
- sections.push('# Agentic Commit - Self-Reflection Report');
51
- sections.push('');
52
- sections.push(`Generated: ${new Date().toISOString()}`);
53
- sections.push('');
54
- sections.push('## Execution Summary');
55
- sections.push('');
56
- sections.push(`- **Iterations**: ${agenticResult.iterations}`);
57
- sections.push(`- **Tool Calls**: ${agenticResult.toolCallsExecuted}`);
58
- sections.push(`- **Unique Tools Used**: ${toolStats.size}`);
59
- sections.push('');
60
- sections.push('## Tool Effectiveness Analysis');
61
- sections.push('');
62
- if (toolStats.size === 0) {
63
- sections.push('*No tools were executed during this run.*');
64
- } else {
65
- sections.push('| Tool | Calls | Success | Failures | Success Rate | Avg Duration |');
66
- sections.push('|------|-------|---------|----------|--------------|--------------|');
67
- for (const [toolName, stats] of Array.from(toolStats.entries()).sort((a, b)=>b[1].total - a[1].total)){
68
- const successRate = (stats.success / stats.total * 100).toFixed(1);
69
- const avgDuration = (stats.totalDuration / stats.total).toFixed(0);
70
- sections.push(`| ${toolName} | ${stats.total} | ${stats.success} | ${stats.failures} | ${successRate}% | ${avgDuration}ms |`);
71
- }
72
- sections.push('');
73
- sections.push('### Tool Performance Insights');
74
- sections.push('');
75
- // Identify problematic tools
76
- const failedTools = Array.from(toolStats.entries()).filter(([_, stats])=>stats.failures > 0);
77
- if (failedTools.length > 0) {
78
- sections.push('**Tools with Failures:**');
79
- for (const [toolName, stats] of failedTools){
80
- const failureRate = (stats.failures / stats.total * 100).toFixed(1);
81
- sections.push(`- ${toolName}: ${stats.failures}/${stats.total} failures (${failureRate}%)`);
82
- }
83
- sections.push('');
84
- }
85
- // Identify slow tools
86
- const slowTools = Array.from(toolStats.entries()).filter(([_, stats])=>stats.totalDuration / stats.total > 1000).sort((a, b)=>b[1].totalDuration / b[1].total - a[1].totalDuration / a[1].total);
87
- if (slowTools.length > 0) {
88
- sections.push('**Slow Tools (>1s average):**');
89
- for (const [toolName, stats] of slowTools){
90
- const avgDuration = (stats.totalDuration / stats.total / 1000).toFixed(2);
91
- sections.push(`- ${toolName}: ${avgDuration}s average`);
92
- }
93
- sections.push('');
94
- }
95
- // Identify most useful tools
96
- sections.push('**Most Frequently Used:**');
97
- const topTools = Array.from(toolStats.entries()).slice(0, 3);
98
- for (const [toolName, stats] of topTools){
99
- sections.push(`- ${toolName}: ${stats.total} calls`);
100
- }
101
- sections.push('');
102
- }
103
- sections.push('## Detailed Execution Timeline');
104
- sections.push('');
105
- if (toolMetrics.length === 0) {
106
- sections.push('*No tool execution timeline available.*');
107
- } else {
108
- sections.push('| Time | Iteration | Tool | Result | Duration |');
109
- sections.push('|------|-----------|------|--------|----------|');
110
- for (const metric of toolMetrics){
111
- const time = new Date(metric.timestamp).toLocaleTimeString();
112
- const result = metric.success ? '✅ Success' : `❌ ${metric.error || 'Failed'}`;
113
- sections.push(`| ${time} | ${metric.iteration} | ${metric.name} | ${result} | ${metric.duration}ms |`);
114
- }
115
- sections.push('');
116
- }
117
- sections.push('## Conversation History');
118
- sections.push('');
119
- sections.push('<details>');
120
- sections.push('<summary>Click to expand full agentic interaction</summary>');
121
- sections.push('');
122
- sections.push('```json');
123
- sections.push(JSON.stringify(agenticResult.conversationHistory, null, 2));
124
- sections.push('```');
125
- sections.push('');
126
- sections.push('</details>');
127
- sections.push('');
128
- sections.push('## Generated Commit Message');
129
- sections.push('');
130
- sections.push('```');
131
- sections.push(agenticResult.commitMessage);
132
- sections.push('```');
133
- sections.push('');
134
- if (agenticResult.suggestedSplits && agenticResult.suggestedSplits.length > 1) {
135
- sections.push('## Suggested Commit Splits');
136
- sections.push('');
137
- for(let i = 0; i < agenticResult.suggestedSplits.length; i++){
138
- const split = agenticResult.suggestedSplits[i];
139
- sections.push(`### Split ${i + 1}`);
140
- sections.push('');
141
- sections.push(`**Files**: ${split.files.join(', ')}`);
142
- sections.push('');
143
- sections.push(`**Rationale**: ${split.rationale}`);
144
- sections.push('');
145
- sections.push(`**Message**:`);
146
- sections.push('```');
147
- sections.push(split.message);
148
- sections.push('```');
149
- sections.push('');
150
- }
151
- }
152
- sections.push('## Recommendations for Improvement');
153
- sections.push('');
154
- // Generate recommendations based on metrics
155
- const recommendations = [];
156
- // Recalculate failed tools for recommendations
157
- const toolsWithFailures = Array.from(toolStats.entries()).filter(([_, stats])=>stats.failures > 0);
158
- if (toolsWithFailures.length > 0) {
159
- recommendations.push('- **Tool Failures**: Investigate and fix tools that are failing. This may indicate issues with error handling or tool implementation.');
160
- }
161
- // Recalculate slow tools for recommendations
162
- const slowToolsForRecs = Array.from(toolStats.entries()).filter(([_, stats])=>stats.totalDuration / stats.total > 1000);
163
- if (slowToolsForRecs.length > 0) {
164
- recommendations.push('- **Performance**: Consider optimizing slow tools or caching results to improve execution speed.');
165
- }
166
- if (agenticResult.iterations >= (agenticResult.maxIterations || 10)) {
167
- recommendations.push('- **Max Iterations Reached**: The agent reached maximum iterations. Consider increasing the limit or improving tool efficiency to allow the agent to complete naturally.');
168
- }
169
- const underutilizedTools = Array.from(toolStats.entries()).filter(([_, stats])=>stats.total === 1);
170
- if (underutilizedTools.length > 3) {
171
- recommendations.push('- **Underutilized Tools**: Many tools were called only once. Consider whether all tools are necessary or if the agent needs better guidance on when to use them.');
172
- }
173
- if (recommendations.length === 0) {
174
- sections.push('*No specific recommendations at this time. Execution appears optimal.*');
175
- } else {
176
- for (const rec of recommendations){
177
- sections.push(rec);
178
- }
179
- }
180
- sections.push('');
181
- // Write the reflection file
182
- const reflectionContent = sections.join('\n');
183
- await storage.writeFile(reflectionPath, reflectionContent, 'utf-8');
27
+ // Use new observability reflection generator
28
+ const report = await generateReflectionReport({
29
+ iterations: agenticResult.iterations || 0,
30
+ toolCallsExecuted: agenticResult.toolCallsExecuted || 0,
31
+ maxIterations: agenticResult.maxIterations || 10,
32
+ toolMetrics: agenticResult.toolMetrics || [],
33
+ conversationHistory: agenticResult.conversationHistory || [],
34
+ commitMessage: agenticResult.commitMessage,
35
+ suggestedSplits: agenticResult.suggestedSplits || [],
36
+ logger
37
+ });
38
+ // Save the report
39
+ const storageAdapter = createStorageAdapter();
40
+ const filename = `agentic-reflection-commit-${timestamp}.md`;
41
+ await storageAdapter.writeOutput(filename, report);
184
42
  logger.info('');
185
43
  logger.info('═'.repeat(80));
186
44
  logger.info('📊 SELF-REFLECTION REPORT GENERATED');
@@ -189,9 +47,12 @@ async function generateSelfReflection(agenticResult, outputDirectory, storage, l
189
47
  logger.info('📁 Location: %s', reflectionPath);
190
48
  logger.info('');
191
49
  logger.info('📈 Report Summary:');
192
- logger.info(' • %d iterations completed', agenticResult.iterations);
193
- logger.info(' • %d tool calls executed', agenticResult.toolCallsExecuted);
194
- logger.info(' • %d unique tools used', toolStats.size);
50
+ const iterations = agenticResult.iterations || 0;
51
+ const toolCalls = agenticResult.toolCallsExecuted || 0;
52
+ const uniqueTools = new Set((agenticResult.toolMetrics || []).map((m)=>m.name)).size;
53
+ logger.info(` • ${iterations} iterations completed`);
54
+ logger.info(` • ${toolCalls} tool calls executed`);
55
+ logger.info(` • ${uniqueTools} unique tools used`);
195
56
  logger.info('');
196
57
  logger.info('💡 Use this report to:');
197
58
  logger.info(' • Understand which tools were most effective');
@@ -632,7 +493,9 @@ const executeInternal = async (runConfig)=>{
632
493
  logger: aiLogger,
633
494
  openaiReasoning: ((_aiConfig_commands1 = aiConfig.commands) === null || _aiConfig_commands1 === void 0 ? void 0 : (_aiConfig_commands_commit1 = _aiConfig_commands1.commit) === null || _aiConfig_commands_commit1 === void 0 ? void 0 : _aiConfig_commands_commit1.reasoning) || aiConfig.reasoning
634
495
  });
635
- logger.info('🔍 Agentic analysis complete: %d iterations, %d tool calls', agenticResult.iterations, agenticResult.toolCallsExecuted);
496
+ const iterations = agenticResult.iterations || 0;
497
+ const toolCalls = agenticResult.toolCallsExecuted || 0;
498
+ logger.info(`🔍 Agentic analysis complete: ${iterations} iterations, ${toolCalls} tool calls`);
636
499
  // Generate self-reflection output if enabled
637
500
  if ((_runConfig_commit16 = runConfig.commit) === null || _runConfig_commit16 === void 0 ? void 0 : _runConfig_commit16.selfReflection) {
638
501
  await generateSelfReflection(agenticResult, outputDirectory, storage, logger);