myshell-tools 1.0.0 → 2.0.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.
- package/CHANGELOG.md +44 -69
- package/LICENSE +21 -21
- package/README.md +178 -318
- package/dist/cli.d.ts +8 -0
- package/dist/cli.js +130 -0
- package/dist/cli.js.map +1 -0
- package/dist/commands/cost.d.ts +36 -0
- package/dist/commands/cost.js +103 -0
- package/dist/commands/cost.js.map +1 -0
- package/dist/commands/doctor.d.ts +36 -0
- package/dist/commands/doctor.js +115 -0
- package/dist/commands/doctor.js.map +1 -0
- package/dist/commands/login.d.ts +20 -0
- package/dist/commands/login.js +60 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/core/assess.d.ts +25 -0
- package/dist/core/assess.js +142 -0
- package/dist/core/assess.js.map +1 -0
- package/dist/core/classify.d.ts +19 -0
- package/dist/core/classify.js +80 -0
- package/dist/core/classify.js.map +1 -0
- package/dist/core/escalate.d.ts +32 -0
- package/dist/core/escalate.js +57 -0
- package/dist/core/escalate.js.map +1 -0
- package/dist/core/index.d.ts +13 -0
- package/dist/core/index.js +12 -0
- package/dist/core/index.js.map +1 -0
- package/dist/core/orchestrate.d.ts +42 -0
- package/dist/core/orchestrate.js +439 -0
- package/dist/core/orchestrate.js.map +1 -0
- package/dist/core/policy.d.ts +9 -0
- package/dist/core/policy.js +27 -0
- package/dist/core/policy.js.map +1 -0
- package/dist/core/prompt.d.ts +26 -0
- package/dist/core/prompt.js +125 -0
- package/dist/core/prompt.js.map +1 -0
- package/dist/core/review.d.ts +46 -0
- package/dist/core/review.js +148 -0
- package/dist/core/review.js.map +1 -0
- package/dist/core/route.d.ts +28 -0
- package/dist/core/route.js +52 -0
- package/dist/core/route.js.map +1 -0
- package/dist/core/types.d.ts +141 -0
- package/dist/core/types.js +14 -0
- package/dist/core/types.js.map +1 -0
- package/dist/infra/atomic.d.ts +53 -0
- package/dist/infra/atomic.js +171 -0
- package/dist/infra/atomic.js.map +1 -0
- package/dist/infra/clock.d.ts +9 -0
- package/dist/infra/clock.js +15 -0
- package/dist/infra/clock.js.map +1 -0
- package/dist/infra/index.d.ts +9 -0
- package/dist/infra/index.js +7 -0
- package/dist/infra/index.js.map +1 -0
- package/dist/infra/ledger.d.ts +49 -0
- package/dist/infra/ledger.js +90 -0
- package/dist/infra/ledger.js.map +1 -0
- package/dist/infra/paths.d.ts +28 -0
- package/dist/infra/paths.js +38 -0
- package/dist/infra/paths.js.map +1 -0
- package/dist/infra/pricing.d.ts +47 -0
- package/dist/infra/pricing.js +151 -0
- package/dist/infra/pricing.js.map +1 -0
- package/dist/infra/session.d.ts +28 -0
- package/dist/infra/session.js +61 -0
- package/dist/infra/session.js.map +1 -0
- package/dist/interface/render.d.ts +27 -0
- package/dist/interface/render.js +134 -0
- package/dist/interface/render.js.map +1 -0
- package/dist/interface/repl.d.ts +23 -0
- package/dist/interface/repl.js +90 -0
- package/dist/interface/repl.js.map +1 -0
- package/dist/interface/run.d.ts +20 -0
- package/dist/interface/run.js +31 -0
- package/dist/interface/run.js.map +1 -0
- package/dist/providers/claude-parse.d.ts +24 -0
- package/dist/providers/claude-parse.js +113 -0
- package/dist/providers/claude-parse.js.map +1 -0
- package/dist/providers/claude.d.ts +45 -0
- package/dist/providers/claude.js +122 -0
- package/dist/providers/claude.js.map +1 -0
- package/dist/providers/codex-parse.d.ts +32 -0
- package/dist/providers/codex-parse.js +145 -0
- package/dist/providers/codex-parse.js.map +1 -0
- package/dist/providers/codex.d.ts +44 -0
- package/dist/providers/codex.js +124 -0
- package/dist/providers/codex.js.map +1 -0
- package/dist/providers/detect.d.ts +49 -0
- package/dist/providers/detect.js +125 -0
- package/dist/providers/detect.js.map +1 -0
- package/dist/providers/errors.d.ts +49 -0
- package/dist/providers/errors.js +189 -0
- package/dist/providers/errors.js.map +1 -0
- package/dist/providers/index.d.ts +9 -0
- package/dist/providers/index.js +7 -0
- package/dist/providers/index.js.map +1 -0
- package/dist/providers/port.d.ts +74 -0
- package/dist/providers/port.js +16 -0
- package/dist/providers/port.js.map +1 -0
- package/dist/providers/registry.d.ts +21 -0
- package/dist/providers/registry.js +34 -0
- package/dist/providers/registry.js.map +1 -0
- package/dist/ui/banner.d.ts +19 -0
- package/dist/ui/banner.js +32 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/spinner.d.ts +27 -0
- package/dist/ui/spinner.js +67 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/theme.d.ts +32 -0
- package/dist/ui/theme.js +56 -0
- package/dist/ui/theme.js.map +1 -0
- package/package.json +55 -49
- package/data/orchestrator.json +0 -113
- package/src/auth/recovery.mjs +0 -328
- package/src/auth/refresh.mjs +0 -373
- package/src/chef.mjs +0 -348
- package/src/cli/doctor.mjs +0 -568
- package/src/cli/reset.mjs +0 -447
- package/src/cli/status.mjs +0 -379
- package/src/cli.mjs +0 -429
- package/src/commands/doctor.mjs +0 -375
- package/src/commands/help.mjs +0 -324
- package/src/commands/status.mjs +0 -331
- package/src/monitor/health.mjs +0 -486
- package/src/monitor/performance.mjs +0 -442
- package/src/monitor/report.mjs +0 -535
- package/src/orchestrator/classify.mjs +0 -391
- package/src/orchestrator/confidence.mjs +0 -151
- package/src/orchestrator/handoffs.mjs +0 -231
- package/src/orchestrator/review.mjs +0 -222
- package/src/providers/balance.mjs +0 -201
- package/src/providers/claude.mjs +0 -236
- package/src/providers/codex.mjs +0 -255
- package/src/providers/detect.mjs +0 -185
- package/src/providers/errors.mjs +0 -373
- package/src/providers/select.mjs +0 -162
- package/src/repl-enhanced.mjs +0 -417
- package/src/repl.mjs +0 -321
- package/src/state/archive.mjs +0 -366
- package/src/state/atomic.mjs +0 -116
- package/src/state/cleanup.mjs +0 -440
- package/src/state/recovery.mjs +0 -461
- package/src/state/session.mjs +0 -147
- package/src/ui/errors.mjs +0 -456
- package/src/ui/formatter.mjs +0 -327
- package/src/ui/icons.mjs +0 -318
- package/src/ui/progress.mjs +0 -468
- package/templates/prompts/confidence-format.txt +0 -14
- package/templates/prompts/ic-with-feedback.txt +0 -41
- package/templates/prompts/ic.txt +0 -13
- package/templates/prompts/manager-review.txt +0 -40
- package/templates/prompts/manager.txt +0 -14
- package/templates/prompts/worker.txt +0 -12
package/src/monitor/report.mjs
DELETED
|
@@ -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
|
-
}
|