myshell-tools 1.0.0 → 2.0.0-alpha.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 (150) hide show
  1. package/CHANGELOG.md +44 -69
  2. package/LICENSE +21 -21
  3. package/README.md +178 -318
  4. package/dist/cli.d.ts +8 -0
  5. package/dist/cli.js +106 -0
  6. package/dist/cli.js.map +1 -0
  7. package/dist/commands/cost.d.ts +36 -0
  8. package/dist/commands/cost.js +103 -0
  9. package/dist/commands/cost.js.map +1 -0
  10. package/dist/commands/doctor.d.ts +36 -0
  11. package/dist/commands/doctor.js +115 -0
  12. package/dist/commands/doctor.js.map +1 -0
  13. package/dist/core/assess.d.ts +25 -0
  14. package/dist/core/assess.js +142 -0
  15. package/dist/core/assess.js.map +1 -0
  16. package/dist/core/classify.d.ts +19 -0
  17. package/dist/core/classify.js +80 -0
  18. package/dist/core/classify.js.map +1 -0
  19. package/dist/core/escalate.d.ts +32 -0
  20. package/dist/core/escalate.js +57 -0
  21. package/dist/core/escalate.js.map +1 -0
  22. package/dist/core/index.d.ts +13 -0
  23. package/dist/core/index.js +12 -0
  24. package/dist/core/index.js.map +1 -0
  25. package/dist/core/orchestrate.d.ts +42 -0
  26. package/dist/core/orchestrate.js +439 -0
  27. package/dist/core/orchestrate.js.map +1 -0
  28. package/dist/core/policy.d.ts +9 -0
  29. package/dist/core/policy.js +27 -0
  30. package/dist/core/policy.js.map +1 -0
  31. package/dist/core/prompt.d.ts +26 -0
  32. package/dist/core/prompt.js +125 -0
  33. package/dist/core/prompt.js.map +1 -0
  34. package/dist/core/review.d.ts +46 -0
  35. package/dist/core/review.js +148 -0
  36. package/dist/core/review.js.map +1 -0
  37. package/dist/core/route.d.ts +28 -0
  38. package/dist/core/route.js +52 -0
  39. package/dist/core/route.js.map +1 -0
  40. package/dist/core/types.d.ts +141 -0
  41. package/dist/core/types.js +14 -0
  42. package/dist/core/types.js.map +1 -0
  43. package/dist/infra/atomic.d.ts +53 -0
  44. package/dist/infra/atomic.js +171 -0
  45. package/dist/infra/atomic.js.map +1 -0
  46. package/dist/infra/clock.d.ts +9 -0
  47. package/dist/infra/clock.js +15 -0
  48. package/dist/infra/clock.js.map +1 -0
  49. package/dist/infra/index.d.ts +9 -0
  50. package/dist/infra/index.js +7 -0
  51. package/dist/infra/index.js.map +1 -0
  52. package/dist/infra/ledger.d.ts +49 -0
  53. package/dist/infra/ledger.js +90 -0
  54. package/dist/infra/ledger.js.map +1 -0
  55. package/dist/infra/paths.d.ts +28 -0
  56. package/dist/infra/paths.js +38 -0
  57. package/dist/infra/paths.js.map +1 -0
  58. package/dist/infra/pricing.d.ts +47 -0
  59. package/dist/infra/pricing.js +151 -0
  60. package/dist/infra/pricing.js.map +1 -0
  61. package/dist/infra/session.d.ts +28 -0
  62. package/dist/infra/session.js +61 -0
  63. package/dist/infra/session.js.map +1 -0
  64. package/dist/interface/render.d.ts +27 -0
  65. package/dist/interface/render.js +134 -0
  66. package/dist/interface/render.js.map +1 -0
  67. package/dist/interface/repl.d.ts +23 -0
  68. package/dist/interface/repl.js +90 -0
  69. package/dist/interface/repl.js.map +1 -0
  70. package/dist/interface/run.d.ts +20 -0
  71. package/dist/interface/run.js +31 -0
  72. package/dist/interface/run.js.map +1 -0
  73. package/dist/providers/claude-parse.d.ts +24 -0
  74. package/dist/providers/claude-parse.js +113 -0
  75. package/dist/providers/claude-parse.js.map +1 -0
  76. package/dist/providers/claude.d.ts +45 -0
  77. package/dist/providers/claude.js +122 -0
  78. package/dist/providers/claude.js.map +1 -0
  79. package/dist/providers/codex-parse.d.ts +32 -0
  80. package/dist/providers/codex-parse.js +145 -0
  81. package/dist/providers/codex-parse.js.map +1 -0
  82. package/dist/providers/codex.d.ts +44 -0
  83. package/dist/providers/codex.js +124 -0
  84. package/dist/providers/codex.js.map +1 -0
  85. package/dist/providers/detect.d.ts +49 -0
  86. package/dist/providers/detect.js +125 -0
  87. package/dist/providers/detect.js.map +1 -0
  88. package/dist/providers/errors.d.ts +49 -0
  89. package/dist/providers/errors.js +189 -0
  90. package/dist/providers/errors.js.map +1 -0
  91. package/dist/providers/index.d.ts +9 -0
  92. package/dist/providers/index.js +7 -0
  93. package/dist/providers/index.js.map +1 -0
  94. package/dist/providers/port.d.ts +74 -0
  95. package/dist/providers/port.js +16 -0
  96. package/dist/providers/port.js.map +1 -0
  97. package/dist/providers/registry.d.ts +21 -0
  98. package/dist/providers/registry.js +34 -0
  99. package/dist/providers/registry.js.map +1 -0
  100. package/dist/ui/banner.d.ts +19 -0
  101. package/dist/ui/banner.js +32 -0
  102. package/dist/ui/banner.js.map +1 -0
  103. package/dist/ui/spinner.d.ts +27 -0
  104. package/dist/ui/spinner.js +67 -0
  105. package/dist/ui/spinner.js.map +1 -0
  106. package/dist/ui/theme.d.ts +32 -0
  107. package/dist/ui/theme.js +56 -0
  108. package/dist/ui/theme.js.map +1 -0
  109. package/package.json +55 -49
  110. package/data/orchestrator.json +0 -113
  111. package/src/auth/recovery.mjs +0 -328
  112. package/src/auth/refresh.mjs +0 -373
  113. package/src/chef.mjs +0 -348
  114. package/src/cli/doctor.mjs +0 -568
  115. package/src/cli/reset.mjs +0 -447
  116. package/src/cli/status.mjs +0 -379
  117. package/src/cli.mjs +0 -429
  118. package/src/commands/doctor.mjs +0 -375
  119. package/src/commands/help.mjs +0 -324
  120. package/src/commands/status.mjs +0 -331
  121. package/src/monitor/health.mjs +0 -486
  122. package/src/monitor/performance.mjs +0 -442
  123. package/src/monitor/report.mjs +0 -535
  124. package/src/orchestrator/classify.mjs +0 -391
  125. package/src/orchestrator/confidence.mjs +0 -151
  126. package/src/orchestrator/handoffs.mjs +0 -231
  127. package/src/orchestrator/review.mjs +0 -222
  128. package/src/providers/balance.mjs +0 -201
  129. package/src/providers/claude.mjs +0 -236
  130. package/src/providers/codex.mjs +0 -255
  131. package/src/providers/detect.mjs +0 -185
  132. package/src/providers/errors.mjs +0 -373
  133. package/src/providers/select.mjs +0 -162
  134. package/src/repl-enhanced.mjs +0 -417
  135. package/src/repl.mjs +0 -321
  136. package/src/state/archive.mjs +0 -366
  137. package/src/state/atomic.mjs +0 -116
  138. package/src/state/cleanup.mjs +0 -440
  139. package/src/state/recovery.mjs +0 -461
  140. package/src/state/session.mjs +0 -147
  141. package/src/ui/errors.mjs +0 -456
  142. package/src/ui/formatter.mjs +0 -327
  143. package/src/ui/icons.mjs +0 -318
  144. package/src/ui/progress.mjs +0 -468
  145. package/templates/prompts/confidence-format.txt +0 -14
  146. package/templates/prompts/ic-with-feedback.txt +0 -41
  147. package/templates/prompts/ic.txt +0 -13
  148. package/templates/prompts/manager-review.txt +0 -40
  149. package/templates/prompts/manager.txt +0 -14
  150. package/templates/prompts/worker.txt +0 -12
@@ -1,535 +0,0 @@
1
- /**
2
- * report.mjs — Usage reporting and analytics
3
- */
4
-
5
- import { existsSync, readFileSync } from 'fs';
6
- import { join } from 'path';
7
- import { generatePerformanceReport } from './performance.mjs';
8
- import { runHealthCheck } from './health.mjs';
9
- import { getSessionSummary } from '../state/session.mjs';
10
- import { getStorageStats } from '../state/cleanup.mjs';
11
-
12
- /**
13
- * Colors for terminal output
14
- */
15
- const colors = {
16
- red: '\x1b[31m',
17
- green: '\x1b[32m',
18
- yellow: '\x1b[33m',
19
- blue: '\x1b[34m',
20
- magenta: '\x1b[35m',
21
- cyan: '\x1b[36m',
22
- white: '\x1b[37m',
23
- reset: '\x1b[0m',
24
- bold: '\x1b[1m',
25
- dim: '\x1b[2m'
26
- };
27
-
28
- /**
29
- * Generate comprehensive session report
30
- */
31
- export async function generateSessionReport(workspace = process.cwd()) {
32
- const timestamp = new Date().toISOString();
33
-
34
- console.log(`${colors.bold}${colors.blue}📊 Cortex Session Report${colors.reset}\n`);
35
- console.log(`${colors.dim}Generated: ${new Date().toLocaleString()}${colors.reset}\n`);
36
-
37
- // Gather data from all monitoring sources
38
- const performance = generatePerformanceReport(workspace);
39
- const session = getSessionSummary(workspace);
40
- const health = await runHealthCheck(workspace);
41
- const storage = getStorageStats(workspace);
42
-
43
- const report = {
44
- timestamp,
45
- workspace,
46
- session,
47
- performance,
48
- health,
49
- storage
50
- };
51
-
52
- // Display session overview
53
- displaySessionOverview(session);
54
-
55
- // Display performance metrics
56
- displayPerformanceMetrics(performance);
57
-
58
- // Display efficiency analysis
59
- displayEfficiencyAnalysis(performance);
60
-
61
- // Display system health
62
- displayHealthStatus(health);
63
-
64
- // Display recommendations
65
- displayRecommendations(performance, health);
66
-
67
- return report;
68
- }
69
-
70
- /**
71
- * Display session overview
72
- */
73
- function displaySessionOverview(session) {
74
- console.log(`${colors.bold}Session Overview${colors.reset}`);
75
-
76
- if (session.messageCount === 0) {
77
- console.log(` ${colors.dim}No active session${colors.reset}\n`);
78
- return;
79
- }
80
-
81
- const duration = session.duration ? formatDuration(session.duration) : 'ongoing';
82
- const avgResponseTime = session.duration && session.assistantMessageCount > 0 ?
83
- formatDuration(session.duration / session.assistantMessageCount) : 'N/A';
84
-
85
- console.log(` 📝 Messages: ${session.messageCount} (${session.userMessageCount} user, ${session.assistantMessageCount} assistant)`);
86
- console.log(` ⏱️ Duration: ${duration}`);
87
- console.log(` 📊 Avg Response: ${avgResponseTime}`);
88
-
89
- if (session.lastMessage) {
90
- const lastTime = new Date(session.lastMessage.timestamp).toLocaleString();
91
- console.log(` 🕐 Last Activity: ${lastTime}`);
92
- }
93
-
94
- console.log();
95
- }
96
-
97
- /**
98
- * Display performance metrics
99
- */
100
- function displayPerformanceMetrics(performance) {
101
- console.log(`${colors.bold}Performance Metrics${colors.reset}`);
102
-
103
- if (!performance.taskCount) {
104
- console.log(` ${colors.dim}No tasks completed in this session${colors.reset}\n`);
105
- return;
106
- }
107
-
108
- console.log(` 📋 Tasks Completed: ${performance.taskCount}`);
109
- console.log(` 🔄 Total Handoffs: ${performance.totalHandoffs}`);
110
- console.log(` 📈 Escalations: ${performance.escalationCount} (${performance.escalationRate})`);
111
-
112
- if (performance.averageConfidence) {
113
- const confidenceColor = parseFloat(performance.averageConfidence) >= 75 ? colors.green :
114
- parseFloat(performance.averageConfidence) >= 60 ? colors.yellow : colors.red;
115
- console.log(` 🎯 Avg Confidence: ${confidenceColor}${performance.averageConfidence}%${colors.reset}`);
116
- }
117
-
118
- // Cost metrics
119
- if (performance.totalCostUSD) {
120
- console.log(` 💰 Total Cost: $${performance.totalCostUSD}`);
121
- if (performance.averageCostPerTask) {
122
- console.log(` 💵 Avg Cost/Task: $${performance.averageCostPerTask}`);
123
- }
124
- }
125
-
126
- // Tier distribution
127
- if (performance.tierDistribution) {
128
- console.log(` 🏗️ Tier Usage:`);
129
- ['worker', 'ic', 'manager'].forEach(tier => {
130
- const dist = performance.tierDistribution[tier];
131
- if (dist && dist.count > 0) {
132
- const tierColor = tier === 'worker' ? colors.blue :
133
- tier === 'ic' ? colors.yellow : colors.red;
134
- console.log(` ${tierColor}${tier.toUpperCase()}${colors.reset}: ${dist.count} (${dist.percentage}%)`);
135
- }
136
- });
137
- }
138
-
139
- console.log();
140
- }
141
-
142
- /**
143
- * Display efficiency analysis
144
- */
145
- function displayEfficiencyAnalysis(performance) {
146
- console.log(`${colors.bold}Efficiency Analysis${colors.reset}`);
147
-
148
- if (!performance.efficiency) {
149
- console.log(` ${colors.dim}Insufficient data for efficiency analysis${colors.reset}\n`);
150
- return;
151
- }
152
-
153
- const efficiency = performance.efficiency;
154
-
155
- // Token savings
156
- const savingsPercentage = parseFloat(efficiency.tokenSavingsPercentage);
157
- const savingsColor = savingsPercentage >= 50 ? colors.green :
158
- savingsPercentage >= 25 ? colors.yellow : colors.red;
159
- console.log(` 💾 Token Savings: ${savingsColor}${efficiency.tokenSavingsPercentage}% vs dual-verification${colors.reset}`);
160
-
161
- if (efficiency.costSavingsUSD) {
162
- console.log(` 💰 Cost Savings: ${savingsColor}$${efficiency.costSavingsUSD}${colors.reset}`);
163
- }
164
-
165
- // Escalation efficiency
166
- const escalationRate = parseFloat(efficiency.escalationRate);
167
- const escalationColor = escalationRate <= 25 ? colors.green :
168
- escalationRate <= 40 ? colors.yellow : colors.red;
169
- console.log(` 📈 Escalation Rate: ${escalationColor}${efficiency.escalationRate}%${colors.reset}`);
170
-
171
- // Performance indicators
172
- if (performance.indicators && performance.indicators.length > 0) {
173
- console.log(`\n ${colors.bold}Key Insights:${colors.reset}`);
174
- performance.indicators.forEach(indicator => {
175
- const indicatorColor = indicator.type === 'excellent' ? colors.green :
176
- indicator.type === 'good' ? colors.yellow :
177
- indicator.type === 'warning' ? colors.red : colors.white;
178
-
179
- const icon = indicator.type === 'excellent' ? '✅' :
180
- indicator.type === 'good' ? '👍' :
181
- indicator.type === 'warning' ? '⚠️' : 'ℹ️';
182
-
183
- console.log(` ${icon} ${indicatorColor}${indicator.message}${colors.reset}`);
184
- if (indicator.recommendation) {
185
- console.log(` ${colors.dim}→ ${indicator.recommendation}${colors.reset}`);
186
- }
187
- });
188
- }
189
-
190
- console.log();
191
- }
192
-
193
- /**
194
- * Display health status
195
- */
196
- function displayHealthStatus(health) {
197
- console.log(`${colors.bold}System Health${colors.reset}`);
198
-
199
- const overallColor = health.overall.status === 'healthy' ? colors.green :
200
- health.overall.status === 'degraded' ? colors.yellow : colors.red;
201
-
202
- console.log(` 🏥 Overall: ${overallColor}${health.overall.status.toUpperCase()} (${health.overall.score}/100)${colors.reset}`);
203
-
204
- // Component health
205
- const healthyComponents = Object.entries(health.components)
206
- .filter(([_, comp]) => comp.healthScore?.status === 'healthy').length;
207
- const totalComponents = Object.keys(health.components).length;
208
-
209
- console.log(` 🧩 Components: ${healthyComponents}/${totalComponents} healthy`);
210
-
211
- // Show critical issues
212
- const criticalComponents = Object.entries(health.components)
213
- .filter(([_, comp]) => comp.healthScore?.status === 'critical' || comp.healthScore?.status === 'unhealthy')
214
- .map(([name, _]) => name);
215
-
216
- if (criticalComponents.length > 0) {
217
- console.log(` ${colors.red}⚠️ Issues: ${criticalComponents.join(', ')}${colors.reset}`);
218
- }
219
-
220
- console.log();
221
- }
222
-
223
- /**
224
- * Display recommendations
225
- */
226
- function displayRecommendations(performance, health) {
227
- console.log(`${colors.bold}Recommendations${colors.reset}`);
228
-
229
- const recommendations = [];
230
-
231
- // Performance recommendations
232
- if (performance.efficiency) {
233
- const savingsPercentage = parseFloat(performance.efficiency.tokenSavingsPercentage);
234
- const escalationRate = parseFloat(performance.efficiency.escalationRate);
235
-
236
- if (savingsPercentage < 25) {
237
- recommendations.push({
238
- priority: 'high',
239
- type: 'efficiency',
240
- message: 'Low token efficiency detected',
241
- action: 'Review task routing and tier assignment logic'
242
- });
243
- }
244
-
245
- if (escalationRate > 40) {
246
- recommendations.push({
247
- priority: 'medium',
248
- type: 'escalation',
249
- message: 'High escalation rate',
250
- action: 'Consider starting complex tasks at higher tiers'
251
- });
252
- }
253
-
254
- if (performance.averageConfidence && parseFloat(performance.averageConfidence) < 60) {
255
- recommendations.push({
256
- priority: 'medium',
257
- type: 'confidence',
258
- message: 'Low average confidence scores',
259
- action: 'Review task complexity vs model capabilities'
260
- });
261
- }
262
- }
263
-
264
- // Health recommendations
265
- const unhealthyComponents = Object.entries(health.components)
266
- .filter(([_, comp]) => comp.healthScore?.status !== 'healthy')
267
- .map(([name, comp]) => ({ name, status: comp.healthScore?.status }));
268
-
269
- unhealthyComponents.forEach(({ name, status }) => {
270
- recommendations.push({
271
- priority: status === 'critical' ? 'critical' : 'medium',
272
- type: 'health',
273
- message: `${name} component is ${status}`,
274
- action: 'Run --doctor for detailed diagnostics'
275
- });
276
- });
277
-
278
- // Cost recommendations
279
- if (performance.totalCostUSD && parseFloat(performance.totalCostUSD) > 1.0) {
280
- recommendations.push({
281
- priority: 'low',
282
- type: 'cost',
283
- message: 'High session cost detected',
284
- action: 'Consider using lower tiers for simple tasks'
285
- });
286
- }
287
-
288
- // Display recommendations
289
- if (recommendations.length === 0) {
290
- console.log(` ${colors.green}✅ No issues found - system is performing well${colors.reset}`);
291
- } else {
292
- recommendations
293
- .sort((a, b) => {
294
- const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
295
- return priorityOrder[a.priority] - priorityOrder[b.priority];
296
- })
297
- .forEach((rec, index) => {
298
- const priorityColor = rec.priority === 'critical' ? colors.red :
299
- rec.priority === 'high' ? colors.red :
300
- rec.priority === 'medium' ? colors.yellow : colors.cyan;
301
-
302
- console.log(` ${index + 1}. ${priorityColor}[${rec.priority.toUpperCase()}]${colors.reset} ${rec.message}`);
303
- console.log(` ${colors.dim}→ ${rec.action}${colors.reset}`);
304
- });
305
- }
306
-
307
- console.log();
308
- }
309
-
310
- /**
311
- * Generate historical trends report
312
- */
313
- export async function generateTrendsReport(workspace = process.cwd(), days = 7) {
314
- console.log(`${colors.bold}${colors.blue}📈 Trends Report (${days} days)${colors.reset}\n`);
315
-
316
- const metricsDir = join(workspace, '.cortex', 'metrics');
317
- const reportsPath = join(metricsDir, 'session-reports.jsonl');
318
-
319
- if (!existsSync(reportsPath)) {
320
- console.log(`${colors.dim}No historical data available${colors.reset}\n`);
321
- return null;
322
- }
323
-
324
- try {
325
- const content = readFileSync(reportsPath, 'utf8');
326
- const cutoff = Date.now() - (days * 24 * 60 * 60 * 1000);
327
-
328
- const reports = content
329
- .trim()
330
- .split('\n')
331
- .filter(line => line.trim())
332
- .map(line => {
333
- try {
334
- return JSON.parse(line);
335
- } catch {
336
- return null;
337
- }
338
- })
339
- .filter(Boolean)
340
- .filter(report => new Date(report.timestamp).getTime() > cutoff)
341
- .sort((a, b) => new Date(a.timestamp) - new Date(b.timestamp));
342
-
343
- if (reports.length === 0) {
344
- console.log(`${colors.dim}No data available for the last ${days} days${colors.reset}\n`);
345
- return null;
346
- }
347
-
348
- // Analyze trends
349
- const trends = analyzeTrends(reports);
350
-
351
- displayTrends(trends, days);
352
-
353
- return trends;
354
-
355
- } catch (error) {
356
- console.log(`${colors.red}Error loading historical data: ${error.message}${colors.reset}\n`);
357
- return null;
358
- }
359
- }
360
-
361
- /**
362
- * Analyze trends from historical reports
363
- */
364
- function analyzeTrends(reports) {
365
- const trends = {
366
- sessions: reports.length,
367
- totalTasks: reports.reduce((sum, r) => sum + (r.taskCount || 0), 0),
368
- totalCost: reports.reduce((sum, r) => sum + parseFloat(r.totalCostUSD || 0), 0),
369
-
370
- efficiency: {
371
- average: calculateAverage(reports, 'efficiency.tokenSavingsPercentage'),
372
- trend: calculateTrend(reports, 'efficiency.tokenSavingsPercentage')
373
- },
374
-
375
- escalationRate: {
376
- average: calculateAverage(reports, 'escalationRate'),
377
- trend: calculateTrend(reports, 'escalationRate')
378
- },
379
-
380
- confidence: {
381
- average: calculateAverage(reports, 'averageConfidence'),
382
- trend: calculateTrend(reports, 'averageConfidence')
383
- },
384
-
385
- costPerTask: {
386
- average: calculateAverage(reports, 'averageCostPerTask'),
387
- trend: calculateTrend(reports, 'averageCostPerTask')
388
- }
389
- };
390
-
391
- return trends;
392
- }
393
-
394
- /**
395
- * Calculate average of a metric across reports
396
- */
397
- function calculateAverage(reports, metricPath) {
398
- const values = reports
399
- .map(report => getNestedValue(report, metricPath))
400
- .filter(val => val !== null && !isNaN(parseFloat(val)))
401
- .map(val => parseFloat(val));
402
-
403
- return values.length > 0 ? values.reduce((sum, val) => sum + val, 0) / values.length : null;
404
- }
405
-
406
- /**
407
- * Calculate trend direction for a metric
408
- */
409
- function calculateTrend(reports, metricPath) {
410
- const values = reports
411
- .map(report => getNestedValue(report, metricPath))
412
- .filter(val => val !== null && !isNaN(parseFloat(val)))
413
- .map(val => parseFloat(val));
414
-
415
- if (values.length < 2) return 'insufficient_data';
416
-
417
- const firstHalf = values.slice(0, Math.floor(values.length / 2));
418
- const secondHalf = values.slice(Math.floor(values.length / 2));
419
-
420
- const firstAvg = firstHalf.reduce((sum, val) => sum + val, 0) / firstHalf.length;
421
- const secondAvg = secondHalf.reduce((sum, val) => sum + val, 0) / secondHalf.length;
422
-
423
- const change = ((secondAvg - firstAvg) / firstAvg) * 100;
424
-
425
- return change > 5 ? 'improving' :
426
- change < -5 ? 'declining' : 'stable';
427
- }
428
-
429
- /**
430
- * Get nested object value by path
431
- */
432
- function getNestedValue(obj, path) {
433
- return path.split('.').reduce((current, key) => current?.[key], obj);
434
- }
435
-
436
- /**
437
- * Display trends
438
- */
439
- function displayTrends(trends, days) {
440
- console.log(`${colors.bold}Summary${colors.reset}`);
441
- console.log(` 📊 Sessions: ${trends.sessions}`);
442
- console.log(` 📋 Total Tasks: ${trends.totalTasks}`);
443
- console.log(` 💰 Total Cost: $${trends.totalCost.toFixed(4)}`);
444
- console.log();
445
-
446
- console.log(`${colors.bold}Performance Trends${colors.reset}`);
447
-
448
- if (trends.efficiency.average !== null) {
449
- const trendIcon = getTrendIcon(trends.efficiency.trend);
450
- console.log(` 💾 Token Efficiency: ${trends.efficiency.average.toFixed(1)}% ${trendIcon}`);
451
- }
452
-
453
- if (trends.escalationRate.average !== null) {
454
- const trendIcon = getTrendIcon(trends.escalationRate.trend);
455
- console.log(` 📈 Escalation Rate: ${trends.escalationRate.average.toFixed(1)}% ${trendIcon}`);
456
- }
457
-
458
- if (trends.confidence.average !== null) {
459
- const trendIcon = getTrendIcon(trends.confidence.trend);
460
- console.log(` 🎯 Avg Confidence: ${trends.confidence.average.toFixed(1)}% ${trendIcon}`);
461
- }
462
-
463
- if (trends.costPerTask.average !== null) {
464
- const trendIcon = getTrendIcon(trends.costPerTask.trend);
465
- console.log(` 💵 Cost/Task: $${trends.costPerTask.average.toFixed(4)} ${trendIcon}`);
466
- }
467
-
468
- console.log();
469
- }
470
-
471
- /**
472
- * Get trend icon
473
- */
474
- function getTrendIcon(trend) {
475
- switch (trend) {
476
- case 'improving':
477
- return `${colors.green}📈 improving${colors.reset}`;
478
- case 'declining':
479
- return `${colors.red}📉 declining${colors.reset}`;
480
- case 'stable':
481
- return `${colors.yellow}➡️ stable${colors.reset}`;
482
- default:
483
- return `${colors.dim}❓ unknown${colors.reset}`;
484
- }
485
- }
486
-
487
- /**
488
- * Format duration for display
489
- */
490
- function formatDuration(ms) {
491
- const seconds = Math.floor(ms / 1000);
492
- const minutes = Math.floor(seconds / 60);
493
- const hours = Math.floor(minutes / 60);
494
-
495
- if (hours > 0) {
496
- return `${hours}h ${minutes % 60}m`;
497
- } else if (minutes > 0) {
498
- return `${minutes}m ${seconds % 60}s`;
499
- } else {
500
- return `${seconds}s`;
501
- }
502
- }
503
-
504
- /**
505
- * Quick status summary
506
- */
507
- export function displayQuickSummary(workspace = process.cwd()) {
508
- const performance = generatePerformanceReport(workspace);
509
- const session = getSessionSummary(workspace);
510
-
511
- if (session.messageCount === 0) {
512
- console.log(`${colors.dim}No active session${colors.reset}`);
513
- return;
514
- }
515
-
516
- let status = `📊 ${session.messageCount} msgs`;
517
-
518
- if (performance.taskCount > 0) {
519
- status += ` | 📋 ${performance.taskCount} tasks`;
520
-
521
- if (performance.efficiency?.tokenSavingsPercentage) {
522
- const savings = parseFloat(performance.efficiency.tokenSavingsPercentage);
523
- const savingsColor = savings >= 50 ? colors.green : savings >= 25 ? colors.yellow : colors.red;
524
- status += ` | ${savingsColor}💾 ${performance.efficiency.tokenSavingsPercentage}%${colors.reset}`;
525
- }
526
-
527
- if (performance.escalationRate) {
528
- const escalations = parseFloat(performance.escalationRate);
529
- const escalationColor = escalations <= 25 ? colors.green : escalations <= 40 ? colors.yellow : colors.red;
530
- status += ` | ${escalationColor}📈 ${performance.escalationRate}${colors.reset}`;
531
- }
532
- }
533
-
534
- console.log(status);
535
- }