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.
Files changed (153) 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 +130 -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/commands/login.d.ts +20 -0
  14. package/dist/commands/login.js +60 -0
  15. package/dist/commands/login.js.map +1 -0
  16. package/dist/core/assess.d.ts +25 -0
  17. package/dist/core/assess.js +142 -0
  18. package/dist/core/assess.js.map +1 -0
  19. package/dist/core/classify.d.ts +19 -0
  20. package/dist/core/classify.js +80 -0
  21. package/dist/core/classify.js.map +1 -0
  22. package/dist/core/escalate.d.ts +32 -0
  23. package/dist/core/escalate.js +57 -0
  24. package/dist/core/escalate.js.map +1 -0
  25. package/dist/core/index.d.ts +13 -0
  26. package/dist/core/index.js +12 -0
  27. package/dist/core/index.js.map +1 -0
  28. package/dist/core/orchestrate.d.ts +42 -0
  29. package/dist/core/orchestrate.js +439 -0
  30. package/dist/core/orchestrate.js.map +1 -0
  31. package/dist/core/policy.d.ts +9 -0
  32. package/dist/core/policy.js +27 -0
  33. package/dist/core/policy.js.map +1 -0
  34. package/dist/core/prompt.d.ts +26 -0
  35. package/dist/core/prompt.js +125 -0
  36. package/dist/core/prompt.js.map +1 -0
  37. package/dist/core/review.d.ts +46 -0
  38. package/dist/core/review.js +148 -0
  39. package/dist/core/review.js.map +1 -0
  40. package/dist/core/route.d.ts +28 -0
  41. package/dist/core/route.js +52 -0
  42. package/dist/core/route.js.map +1 -0
  43. package/dist/core/types.d.ts +141 -0
  44. package/dist/core/types.js +14 -0
  45. package/dist/core/types.js.map +1 -0
  46. package/dist/infra/atomic.d.ts +53 -0
  47. package/dist/infra/atomic.js +171 -0
  48. package/dist/infra/atomic.js.map +1 -0
  49. package/dist/infra/clock.d.ts +9 -0
  50. package/dist/infra/clock.js +15 -0
  51. package/dist/infra/clock.js.map +1 -0
  52. package/dist/infra/index.d.ts +9 -0
  53. package/dist/infra/index.js +7 -0
  54. package/dist/infra/index.js.map +1 -0
  55. package/dist/infra/ledger.d.ts +49 -0
  56. package/dist/infra/ledger.js +90 -0
  57. package/dist/infra/ledger.js.map +1 -0
  58. package/dist/infra/paths.d.ts +28 -0
  59. package/dist/infra/paths.js +38 -0
  60. package/dist/infra/paths.js.map +1 -0
  61. package/dist/infra/pricing.d.ts +47 -0
  62. package/dist/infra/pricing.js +151 -0
  63. package/dist/infra/pricing.js.map +1 -0
  64. package/dist/infra/session.d.ts +28 -0
  65. package/dist/infra/session.js +61 -0
  66. package/dist/infra/session.js.map +1 -0
  67. package/dist/interface/render.d.ts +27 -0
  68. package/dist/interface/render.js +134 -0
  69. package/dist/interface/render.js.map +1 -0
  70. package/dist/interface/repl.d.ts +23 -0
  71. package/dist/interface/repl.js +90 -0
  72. package/dist/interface/repl.js.map +1 -0
  73. package/dist/interface/run.d.ts +20 -0
  74. package/dist/interface/run.js +31 -0
  75. package/dist/interface/run.js.map +1 -0
  76. package/dist/providers/claude-parse.d.ts +24 -0
  77. package/dist/providers/claude-parse.js +113 -0
  78. package/dist/providers/claude-parse.js.map +1 -0
  79. package/dist/providers/claude.d.ts +45 -0
  80. package/dist/providers/claude.js +122 -0
  81. package/dist/providers/claude.js.map +1 -0
  82. package/dist/providers/codex-parse.d.ts +32 -0
  83. package/dist/providers/codex-parse.js +145 -0
  84. package/dist/providers/codex-parse.js.map +1 -0
  85. package/dist/providers/codex.d.ts +44 -0
  86. package/dist/providers/codex.js +124 -0
  87. package/dist/providers/codex.js.map +1 -0
  88. package/dist/providers/detect.d.ts +49 -0
  89. package/dist/providers/detect.js +125 -0
  90. package/dist/providers/detect.js.map +1 -0
  91. package/dist/providers/errors.d.ts +49 -0
  92. package/dist/providers/errors.js +189 -0
  93. package/dist/providers/errors.js.map +1 -0
  94. package/dist/providers/index.d.ts +9 -0
  95. package/dist/providers/index.js +7 -0
  96. package/dist/providers/index.js.map +1 -0
  97. package/dist/providers/port.d.ts +74 -0
  98. package/dist/providers/port.js +16 -0
  99. package/dist/providers/port.js.map +1 -0
  100. package/dist/providers/registry.d.ts +21 -0
  101. package/dist/providers/registry.js +34 -0
  102. package/dist/providers/registry.js.map +1 -0
  103. package/dist/ui/banner.d.ts +19 -0
  104. package/dist/ui/banner.js +32 -0
  105. package/dist/ui/banner.js.map +1 -0
  106. package/dist/ui/spinner.d.ts +27 -0
  107. package/dist/ui/spinner.js +67 -0
  108. package/dist/ui/spinner.js.map +1 -0
  109. package/dist/ui/theme.d.ts +32 -0
  110. package/dist/ui/theme.js +56 -0
  111. package/dist/ui/theme.js.map +1 -0
  112. package/package.json +55 -49
  113. package/data/orchestrator.json +0 -113
  114. package/src/auth/recovery.mjs +0 -328
  115. package/src/auth/refresh.mjs +0 -373
  116. package/src/chef.mjs +0 -348
  117. package/src/cli/doctor.mjs +0 -568
  118. package/src/cli/reset.mjs +0 -447
  119. package/src/cli/status.mjs +0 -379
  120. package/src/cli.mjs +0 -429
  121. package/src/commands/doctor.mjs +0 -375
  122. package/src/commands/help.mjs +0 -324
  123. package/src/commands/status.mjs +0 -331
  124. package/src/monitor/health.mjs +0 -486
  125. package/src/monitor/performance.mjs +0 -442
  126. package/src/monitor/report.mjs +0 -535
  127. package/src/orchestrator/classify.mjs +0 -391
  128. package/src/orchestrator/confidence.mjs +0 -151
  129. package/src/orchestrator/handoffs.mjs +0 -231
  130. package/src/orchestrator/review.mjs +0 -222
  131. package/src/providers/balance.mjs +0 -201
  132. package/src/providers/claude.mjs +0 -236
  133. package/src/providers/codex.mjs +0 -255
  134. package/src/providers/detect.mjs +0 -185
  135. package/src/providers/errors.mjs +0 -373
  136. package/src/providers/select.mjs +0 -162
  137. package/src/repl-enhanced.mjs +0 -417
  138. package/src/repl.mjs +0 -321
  139. package/src/state/archive.mjs +0 -366
  140. package/src/state/atomic.mjs +0 -116
  141. package/src/state/cleanup.mjs +0 -440
  142. package/src/state/recovery.mjs +0 -461
  143. package/src/state/session.mjs +0 -147
  144. package/src/ui/errors.mjs +0 -456
  145. package/src/ui/formatter.mjs +0 -327
  146. package/src/ui/icons.mjs +0 -318
  147. package/src/ui/progress.mjs +0 -468
  148. package/templates/prompts/confidence-format.txt +0 -14
  149. package/templates/prompts/ic-with-feedback.txt +0 -41
  150. package/templates/prompts/ic.txt +0 -13
  151. package/templates/prompts/manager-review.txt +0 -40
  152. package/templates/prompts/manager.txt +0 -14
  153. package/templates/prompts/worker.txt +0 -12
@@ -1,486 +0,0 @@
1
- /**
2
- * health.mjs — System health checks and monitoring
3
- */
4
-
5
- import { spawnSync } from 'child_process';
6
- import { existsSync } from 'fs';
7
- import { join } from 'path';
8
- import { atomicAppendJSONL, lockedReadModifyWrite } from '../state/atomic.mjs';
9
-
10
- /**
11
- * Health monitoring class
12
- */
13
- export class HealthMonitor {
14
- constructor(workspace = process.cwd()) {
15
- this.workspace = workspace;
16
- this.healthDir = join(workspace, '.cortex', 'health');
17
- this.startTime = Date.now();
18
- this.checks = new Map();
19
- }
20
-
21
- /**
22
- * Ensure health directory exists
23
- */
24
- ensureHealthDir() {
25
- if (!existsSync(this.healthDir)) {
26
- require('fs').mkdirSync(this.healthDir, { recursive: true });
27
- }
28
- return this.healthDir;
29
- }
30
-
31
- /**
32
- * Check CLI availability and response time
33
- */
34
- async checkCliHealth(provider, command, args = ['--version']) {
35
- const startTime = Date.now();
36
-
37
- try {
38
- const result = spawnSync(command, args, {
39
- encoding: 'utf8',
40
- stdio: 'pipe',
41
- timeout: 10000 // 10 second timeout
42
- });
43
-
44
- const responseTime = Date.now() - startTime;
45
-
46
- const healthData = {
47
- provider,
48
- command,
49
- timestamp: Date.now(),
50
- available: result.status === 0,
51
- responseTime,
52
- version: result.status === 0 ? result.stdout.trim().split('\n')[0] : null,
53
- error: result.status !== 0 ? (result.stderr || 'Command failed') : null
54
- };
55
-
56
- this.recordHealthCheck(provider, healthData);
57
- return healthData;
58
-
59
- } catch (error) {
60
- const responseTime = Date.now() - startTime;
61
-
62
- const healthData = {
63
- provider,
64
- command,
65
- timestamp: Date.now(),
66
- available: false,
67
- responseTime,
68
- version: null,
69
- error: error.code === 'ENOENT' ? 'Command not found' : error.message
70
- };
71
-
72
- this.recordHealthCheck(provider, healthData);
73
- return healthData;
74
- }
75
- }
76
-
77
- /**
78
- * Check network connectivity to provider APIs
79
- */
80
- async checkNetworkHealth(provider, endpoint) {
81
- return new Promise((resolve) => {
82
- const startTime = Date.now();
83
-
84
- try {
85
- const https = require('https');
86
- const url = new URL(endpoint);
87
-
88
- const req = https.request({
89
- hostname: url.hostname,
90
- port: url.port || 443,
91
- path: url.pathname,
92
- method: 'HEAD',
93
- timeout: 5000
94
- }, (res) => {
95
- const responseTime = Date.now() - startTime;
96
-
97
- const healthData = {
98
- provider,
99
- endpoint,
100
- timestamp: Date.now(),
101
- available: res.statusCode < 400,
102
- responseTime,
103
- statusCode: res.statusCode,
104
- error: res.statusCode >= 400 ? `HTTP ${res.statusCode}` : null
105
- };
106
-
107
- this.recordHealthCheck(`${provider}_network`, healthData);
108
- resolve(healthData);
109
- });
110
-
111
- req.on('error', (error) => {
112
- const responseTime = Date.now() - startTime;
113
-
114
- const healthData = {
115
- provider,
116
- endpoint,
117
- timestamp: Date.now(),
118
- available: false,
119
- responseTime,
120
- statusCode: null,
121
- error: error.message
122
- };
123
-
124
- this.recordHealthCheck(`${provider}_network`, healthData);
125
- resolve(healthData);
126
- });
127
-
128
- req.on('timeout', () => {
129
- const responseTime = Date.now() - startTime;
130
-
131
- const healthData = {
132
- provider,
133
- endpoint,
134
- timestamp: Date.now(),
135
- available: false,
136
- responseTime,
137
- statusCode: null,
138
- error: 'Timeout'
139
- };
140
-
141
- this.recordHealthCheck(`${provider}_network`, healthData);
142
- resolve(healthData);
143
- req.destroy();
144
- });
145
-
146
- req.end();
147
- } catch (error) {
148
- const responseTime = Date.now() - startTime;
149
-
150
- const healthData = {
151
- provider,
152
- endpoint,
153
- timestamp: Date.now(),
154
- available: false,
155
- responseTime,
156
- statusCode: null,
157
- error: error.message
158
- };
159
-
160
- this.recordHealthCheck(`${provider}_network`, healthData);
161
- resolve(healthData);
162
- }
163
- });
164
- }
165
-
166
- /**
167
- * Check system resources
168
- */
169
- checkSystemHealth() {
170
- const memUsage = process.memoryUsage();
171
-
172
- const healthData = {
173
- timestamp: Date.now(),
174
- memory: {
175
- heapUsed: Math.round(memUsage.heapUsed / 1024 / 1024), // MB
176
- heapTotal: Math.round(memUsage.heapTotal / 1024 / 1024),
177
- external: Math.round(memUsage.external / 1024 / 1024),
178
- rss: Math.round(memUsage.rss / 1024 / 1024)
179
- },
180
- uptime: Math.round(process.uptime() * 1000), // ms
181
- loadAverage: process.platform !== 'win32' ? process.loadavg() : null,
182
- platform: process.platform,
183
- arch: process.arch,
184
- nodeVersion: process.version
185
- };
186
-
187
- this.recordHealthCheck('system', healthData);
188
- return healthData;
189
- }
190
-
191
- /**
192
- * Record health check result
193
- */
194
- recordHealthCheck(component, data) {
195
- this.checks.set(component, data);
196
-
197
- // Persist to file
198
- this.ensureHealthDir();
199
- const logPath = join(this.healthDir, `${component}-health.jsonl`);
200
-
201
- try {
202
- atomicAppendJSONL(logPath, data);
203
- } catch (error) {
204
- console.warn(`Failed to log health check for ${component}:`, error.message);
205
- }
206
- }
207
-
208
- /**
209
- * Get recent health status for a component
210
- */
211
- getRecentHealth(component, timeWindowMs = 5 * 60 * 1000) {
212
- const logPath = join(this.healthDir, `${component}-health.jsonl`);
213
-
214
- if (!existsSync(logPath)) {
215
- return [];
216
- }
217
-
218
- try {
219
- const content = require('fs').readFileSync(logPath, 'utf8');
220
- const cutoff = Date.now() - timeWindowMs;
221
-
222
- return content
223
- .trim()
224
- .split('\n')
225
- .filter(line => line.trim())
226
- .map(line => {
227
- try {
228
- return JSON.parse(line);
229
- } catch {
230
- return null;
231
- }
232
- })
233
- .filter(Boolean)
234
- .filter(entry => entry.timestamp > cutoff)
235
- .sort((a, b) => a.timestamp - b.timestamp);
236
- } catch {
237
- return [];
238
- }
239
- }
240
-
241
- /**
242
- * Calculate component health score
243
- */
244
- calculateHealthScore(component, timeWindowMs = 15 * 60 * 1000) {
245
- const recent = this.getRecentHealth(component, timeWindowMs);
246
-
247
- if (recent.length === 0) {
248
- return { score: 0, status: 'unknown', message: 'No recent data' };
249
- }
250
-
251
- const availabilityRatio = recent.filter(entry => entry.available).length / recent.length;
252
- const avgResponseTime = recent
253
- .filter(entry => entry.available && entry.responseTime)
254
- .reduce((sum, entry) => sum + entry.responseTime, 0) / Math.max(recent.length, 1);
255
-
256
- let score = availabilityRatio * 100;
257
-
258
- // Penalize high response times
259
- if (avgResponseTime > 5000) {
260
- score *= 0.7; // High latency
261
- } else if (avgResponseTime > 2000) {
262
- score *= 0.9; // Moderate latency
263
- }
264
-
265
- const status = score >= 90 ? 'healthy' :
266
- score >= 70 ? 'degraded' :
267
- score >= 50 ? 'unhealthy' : 'critical';
268
-
269
- return {
270
- score: Math.round(score),
271
- status,
272
- availabilityRatio,
273
- avgResponseTime: Math.round(avgResponseTime),
274
- recentChecks: recent.length,
275
- message: this.getHealthMessage(status, availabilityRatio, avgResponseTime)
276
- };
277
- }
278
-
279
- /**
280
- * Get health status message
281
- */
282
- getHealthMessage(status, availability, responseTime) {
283
- switch (status) {
284
- case 'healthy':
285
- return `Healthy - ${(availability * 100).toFixed(1)}% availability`;
286
-
287
- case 'degraded':
288
- if (availability < 0.8) {
289
- return `Degraded - ${(availability * 100).toFixed(1)}% availability`;
290
- } else {
291
- return `Degraded - High latency (${responseTime}ms)`;
292
- }
293
-
294
- case 'unhealthy':
295
- return `Unhealthy - ${(availability * 100).toFixed(1)}% availability, ${responseTime}ms latency`;
296
-
297
- case 'critical':
298
- return `Critical - ${(availability * 100).toFixed(1)}% availability`;
299
-
300
- default:
301
- return 'Unknown status';
302
- }
303
- }
304
-
305
- /**
306
- * Comprehensive health check
307
- */
308
- async runComprehensiveCheck() {
309
- const results = {
310
- timestamp: Date.now(),
311
- workspace: this.workspace,
312
- components: {},
313
- overall: { score: 0, status: 'unknown' }
314
- };
315
-
316
- // Check CLI health
317
- results.components.claude = await this.checkCliHealth('claude', 'claude');
318
- results.components.codex = await this.checkCliHealth('codex', 'codex');
319
-
320
- // Check network health
321
- results.components.claude_network = await this.checkNetworkHealth('claude', 'https://console.anthropic.com');
322
- results.components.openai_network = await this.checkNetworkHealth('openai', 'https://api.openai.com');
323
-
324
- // Check system health
325
- results.components.system = this.checkSystemHealth();
326
-
327
- // Calculate health scores
328
- for (const [component, data] of Object.entries(results.components)) {
329
- if (data.timestamp) {
330
- const score = this.calculateHealthScore(component);
331
- results.components[component].healthScore = score;
332
- }
333
- }
334
-
335
- // Calculate overall score
336
- const scores = Object.values(results.components)
337
- .map(comp => comp.healthScore?.score || 0)
338
- .filter(score => score > 0);
339
-
340
- if (scores.length > 0) {
341
- results.overall.score = Math.round(scores.reduce((sum, score) => sum + score, 0) / scores.length);
342
- results.overall.status = results.overall.score >= 80 ? 'healthy' :
343
- results.overall.score >= 60 ? 'degraded' :
344
- results.overall.score >= 40 ? 'unhealthy' : 'critical';
345
- }
346
-
347
- // Update running health statistics
348
- this.updateHealthStats(results);
349
-
350
- return results;
351
- }
352
-
353
- /**
354
- * Update running health statistics
355
- */
356
- updateHealthStats(results) {
357
- const statsPath = join(this.healthDir, 'running-health-stats.json');
358
-
359
- try {
360
- return lockedReadModifyWrite(statsPath, (stats) => {
361
- const updated = stats || {
362
- totalChecks: 0,
363
- averageScore: 0,
364
- downtimeEvents: 0,
365
- lastCheck: null,
366
- components: {}
367
- };
368
-
369
- updated.totalChecks++;
370
- updated.lastCheck = results.timestamp;
371
-
372
- // Update overall average
373
- const newScore = results.overall.score;
374
- updated.averageScore = ((updated.averageScore * (updated.totalChecks - 1)) + newScore) / updated.totalChecks;
375
-
376
- // Track component statistics
377
- for (const [component, data] of Object.entries(results.components)) {
378
- if (!updated.components[component]) {
379
- updated.components[component] = {
380
- checks: 0,
381
- averageScore: 0,
382
- downtimeEvents: 0,
383
- lastDowntime: null
384
- };
385
- }
386
-
387
- const compStats = updated.components[component];
388
- compStats.checks++;
389
-
390
- if (data.healthScore) {
391
- compStats.averageScore = ((compStats.averageScore * (compStats.checks - 1)) + data.healthScore.score) / compStats.checks;
392
-
393
- // Track downtime events
394
- if (data.healthScore.status === 'critical' || data.healthScore.status === 'unhealthy') {
395
- if (compStats.lastDowntime === null || (results.timestamp - compStats.lastDowntime) > 60 * 60 * 1000) {
396
- compStats.downtimeEvents++;
397
- compStats.lastDowntime = results.timestamp;
398
- }
399
- }
400
- }
401
- }
402
-
403
- return updated;
404
- });
405
- } catch (error) {
406
- console.warn('Failed to update health stats:', error.message);
407
- return null;
408
- }
409
- }
410
-
411
- /**
412
- * Get health trends
413
- */
414
- getHealthTrends(component, timeWindowMs = 24 * 60 * 60 * 1000) {
415
- const recent = this.getRecentHealth(component, timeWindowMs);
416
-
417
- if (recent.length < 2) {
418
- return { trend: 'insufficient_data', slope: 0 };
419
- }
420
-
421
- // Calculate availability trend over time
422
- const dataPoints = recent.map((entry, index) => ({
423
- x: index,
424
- y: entry.available ? 1 : 0
425
- }));
426
-
427
- // Simple linear regression to determine trend
428
- const n = dataPoints.length;
429
- const sumX = dataPoints.reduce((sum, p) => sum + p.x, 0);
430
- const sumY = dataPoints.reduce((sum, p) => sum + p.y, 0);
431
- const sumXY = dataPoints.reduce((sum, p) => sum + (p.x * p.y), 0);
432
- const sumXX = dataPoints.reduce((sum, p) => sum + (p.x * p.x), 0);
433
-
434
- const slope = (n * sumXY - sumX * sumY) / (n * sumXX - sumX * sumX);
435
-
436
- const trend = slope > 0.01 ? 'improving' :
437
- slope < -0.01 ? 'declining' : 'stable';
438
-
439
- return {
440
- trend,
441
- slope: slope.toFixed(4),
442
- dataPoints: dataPoints.length,
443
- availability: (sumY / n).toFixed(3)
444
- };
445
- }
446
- }
447
-
448
- /**
449
- * Global health monitor instance
450
- */
451
- let globalHealthMonitor = null;
452
-
453
- /**
454
- * Get or create global health monitor
455
- */
456
- export function getHealthMonitor(workspace = process.cwd()) {
457
- if (!globalHealthMonitor) {
458
- globalHealthMonitor = new HealthMonitor(workspace);
459
- }
460
- return globalHealthMonitor;
461
- }
462
-
463
- /**
464
- * Run health check
465
- */
466
- export async function runHealthCheck(workspace = process.cwd()) {
467
- const monitor = getHealthMonitor(workspace);
468
- return await monitor.runComprehensiveCheck();
469
- }
470
-
471
- /**
472
- * Get component health score
473
- */
474
- export function getComponentHealth(component, workspace = process.cwd()) {
475
- const monitor = getHealthMonitor(workspace);
476
- return monitor.calculateHealthScore(component);
477
- }
478
-
479
- /**
480
- * Check if a provider is healthy
481
- */
482
- export function isProviderHealthy(provider, workspace = process.cwd()) {
483
- const monitor = getHealthMonitor(workspace);
484
- const health = monitor.calculateHealthScore(provider);
485
- return health.status === 'healthy' || health.status === 'degraded';
486
- }