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,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
- }