erosolar-cli 1.7.373 → 1.7.379
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/dist/capabilities/agentSpawningCapability.d.ts.map +1 -1
- package/dist/capabilities/agentSpawningCapability.js +29 -1
- package/dist/capabilities/agentSpawningCapability.js.map +1 -1
- package/dist/contracts/agent-schemas.json +105 -0
- package/dist/core/alphaZeroModular.d.ts +186 -0
- package/dist/core/alphaZeroModular.d.ts.map +1 -0
- package/dist/core/alphaZeroModular.js +755 -0
- package/dist/core/alphaZeroModular.js.map +1 -0
- package/dist/core/alphaZeroOrchestrator.d.ts +140 -0
- package/dist/core/alphaZeroOrchestrator.d.ts.map +1 -0
- package/dist/core/alphaZeroOrchestrator.js +418 -0
- package/dist/core/alphaZeroOrchestrator.js.map +1 -0
- package/dist/core/checkpoint.d.ts +76 -0
- package/dist/core/checkpoint.d.ts.map +1 -0
- package/dist/core/checkpoint.js +278 -0
- package/dist/core/checkpoint.js.map +1 -0
- package/dist/core/claudeCodeFeatures.d.ts +64 -0
- package/dist/core/claudeCodeFeatures.d.ts.map +1 -0
- package/dist/core/claudeCodeFeatures.js +163 -0
- package/dist/core/claudeCodeFeatures.js.map +1 -0
- package/dist/core/costTracker.d.ts +87 -0
- package/dist/core/costTracker.d.ts.map +1 -0
- package/dist/core/costTracker.js +285 -0
- package/dist/core/costTracker.js.map +1 -0
- package/dist/core/failureRecovery.d.ts +122 -0
- package/dist/core/failureRecovery.d.ts.map +1 -0
- package/dist/core/failureRecovery.js +477 -0
- package/dist/core/failureRecovery.js.map +1 -0
- package/dist/core/intelligentTestFlows.d.ts +126 -0
- package/dist/core/intelligentTestFlows.d.ts.map +1 -0
- package/dist/core/intelligentTestFlows.js +678 -0
- package/dist/core/intelligentTestFlows.js.map +1 -0
- package/dist/core/learningPersistence.d.ts +145 -0
- package/dist/core/learningPersistence.d.ts.map +1 -0
- package/dist/core/learningPersistence.js +477 -0
- package/dist/core/learningPersistence.js.map +1 -0
- package/dist/core/memorySystem.d.ts +67 -0
- package/dist/core/memorySystem.d.ts.map +1 -0
- package/dist/core/memorySystem.js +334 -0
- package/dist/core/memorySystem.js.map +1 -0
- package/dist/core/outputStyles.d.ts +48 -0
- package/dist/core/outputStyles.d.ts.map +1 -0
- package/dist/core/outputStyles.js +270 -0
- package/dist/core/outputStyles.js.map +1 -0
- package/dist/core/selfEvolution.d.ts +155 -0
- package/dist/core/selfEvolution.d.ts.map +1 -0
- package/dist/core/selfEvolution.js +1000 -0
- package/dist/core/selfEvolution.js.map +1 -0
- package/dist/core/selfImprovement.d.ts +141 -0
- package/dist/core/selfImprovement.d.ts.map +1 -0
- package/dist/core/selfImprovement.js +700 -0
- package/dist/core/selfImprovement.js.map +1 -0
- package/dist/core/updateManager.d.ts +62 -0
- package/dist/core/updateManager.d.ts.map +1 -0
- package/dist/core/updateManager.js +266 -0
- package/dist/core/updateManager.js.map +1 -0
- package/dist/shell/interactiveShell.d.ts +67 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +1546 -3
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/shell/keyboardShortcuts.d.ts +53 -0
- package/dist/shell/keyboardShortcuts.d.ts.map +1 -0
- package/dist/shell/keyboardShortcuts.js +163 -0
- package/dist/shell/keyboardShortcuts.js.map +1 -0
- package/dist/shell/terminalInput.d.ts +51 -1
- package/dist/shell/terminalInput.d.ts.map +1 -1
- package/dist/shell/terminalInput.js +223 -12
- package/dist/shell/terminalInput.js.map +1 -1
- package/dist/shell/terminalInputAdapter.d.ts +7 -1
- package/dist/shell/terminalInputAdapter.d.ts.map +1 -1
- package/dist/shell/terminalInputAdapter.js +7 -0
- package/dist/shell/terminalInputAdapter.js.map +1 -1
- package/dist/shell/vimMode.d.ts +66 -0
- package/dist/shell/vimMode.d.ts.map +1 -0
- package/dist/shell/vimMode.js +434 -0
- package/dist/shell/vimMode.js.map +1 -0
- package/dist/subagents/parallelAgentManager.d.ts +99 -0
- package/dist/subagents/parallelAgentManager.d.ts.map +1 -0
- package/dist/subagents/parallelAgentManager.js +249 -0
- package/dist/subagents/parallelAgentManager.js.map +1 -0
- package/dist/subagents/taskRunner.d.ts +6 -1
- package/dist/subagents/taskRunner.d.ts.map +1 -1
- package/dist/subagents/taskRunner.js +57 -2
- package/dist/subagents/taskRunner.js.map +1 -1
- package/dist/tools/planningTools.d.ts +9 -0
- package/dist/tools/planningTools.d.ts.map +1 -1
- package/dist/tools/planningTools.js +90 -0
- package/dist/tools/planningTools.js.map +1 -1
- package/dist/ui/display.d.ts +5 -0
- package/dist/ui/display.d.ts.map +1 -1
- package/dist/ui/display.js +14 -0
- package/dist/ui/display.js.map +1 -1
- package/dist/ui/shortcutsHelp.d.ts.map +1 -1
- package/dist/ui/shortcutsHelp.js +43 -12
- package/dist/ui/shortcutsHelp.js.map +1 -1
- package/dist/ui/unified/layout.d.ts.map +1 -1
- package/dist/ui/unified/layout.js +9 -9
- package/dist/ui/unified/layout.js.map +1 -1
- package/package.json +1 -1
|
@@ -6,6 +6,7 @@ import { theme } from '../ui/theme.js';
|
|
|
6
6
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
7
7
|
import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, maskSecret, setSecretValue, } from '../core/secretStore.js';
|
|
8
8
|
import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, loadFeatureFlags, saveFeatureFlags, toggleFeatureFlag, FEATURE_FLAG_INFO, } from '../core/preferences.js';
|
|
9
|
+
import { getLearningSummary, getRecentLearning, commitLearning, exportAllLearning, getLearningDir, } from '../core/learningPersistence.js';
|
|
9
10
|
import { buildEnabledToolSet, evaluateToolPermissions, getToolToggleOptions, } from '../capabilities/toolRegistry.js';
|
|
10
11
|
import { detectApiKeyError } from '../core/errors/apiKeyErrors.js';
|
|
11
12
|
import { buildWorkspaceContext } from '../workspace.js';
|
|
@@ -20,8 +21,16 @@ import { SkillRepository } from '../skills/skillRepository.js';
|
|
|
20
21
|
import { createSkillTools } from '../tools/skillTools.js';
|
|
21
22
|
import { FileChangeTracker } from './fileChangeTracker.js';
|
|
22
23
|
import { formatShortcutsHelp } from '../ui/shortcutsHelp.js';
|
|
24
|
+
import { setPlanApprovalCallback } from '../tools/planningTools.js';
|
|
23
25
|
import { MetricsTracker } from '../core/metricsTracker.js';
|
|
26
|
+
import { detectFailure, clearActionHistory, findRecoveryStrategy, } from '../core/failureRecovery.js';
|
|
27
|
+
import { addToolPattern } from '../core/learningPersistence.js';
|
|
28
|
+
import { classifyTaskType } from '../core/alphaZeroEngine.js';
|
|
29
|
+
import { analyzeImprovementOpportunities, runSelfImprovementCycle, getImprovementSummary, runAutonomousImprovement, requestAutoImprovementStop, getAutoImprovementState, emergencyRollback, } from '../core/selfImprovement.js';
|
|
24
30
|
import { listAvailablePlugins } from '../plugins/index.js';
|
|
31
|
+
import { isErosolarRepo, isValidSourceRepo, getRepoName, analyzeSource, runSelfEvolution, stopEvolution, getEvolutionStatus, emergencyEvolutionRollback, learnSourcePatterns, generateFix, } from '../core/selfEvolution.js';
|
|
32
|
+
import { analyzeTokenUsage, discoverModularTargets, getModularStatusDisplay, generateContextOptimizations, getGuidelines, deleteGuideline, getPendingActions, executeModularAction, } from '../core/alphaZeroModular.js';
|
|
33
|
+
import { generateTestFlows, detectBugs, detectUIUpdates, saveTestFlows, saveBugReports, saveUIUpdates, getTestFlowStatus, } from '../core/intelligentTestFlows.js';
|
|
25
34
|
import { TerminalInputAdapter } from './terminalInputAdapter.js';
|
|
26
35
|
import { renderSessionFrame } from '../ui/unified/layout.js';
|
|
27
36
|
import { isUpdateInProgress, maybeOfferCliUpdate } from './updateManager.js';
|
|
@@ -29,6 +38,7 @@ import { writeLock } from '../ui/writeLock.js';
|
|
|
29
38
|
import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js';
|
|
30
39
|
import { setGlobalAIEnhancer } from '../tools/localExplore.js';
|
|
31
40
|
import { createProvider } from '../providers/providerFactory.js';
|
|
41
|
+
import { getParallelAgentManager } from '../subagents/parallelAgentManager.js';
|
|
32
42
|
const execAsync = promisify(exec);
|
|
33
43
|
const DROPDOWN_COLORS = [
|
|
34
44
|
theme.primary,
|
|
@@ -125,6 +135,11 @@ export class InteractiveShell {
|
|
|
125
135
|
cachedProviderStatus = [];
|
|
126
136
|
// Auto-test tracking
|
|
127
137
|
autoTestInFlight = false;
|
|
138
|
+
// AlphaZero learning tracking
|
|
139
|
+
currentTaskType = 'general';
|
|
140
|
+
currentToolCalls = [];
|
|
141
|
+
lastUserQuery = '';
|
|
142
|
+
lastFailure = null;
|
|
128
143
|
lastAutoTestRun = null;
|
|
129
144
|
// Auto-build tracking
|
|
130
145
|
autoBuildInFlight = false;
|
|
@@ -240,6 +255,8 @@ export class InteractiveShell {
|
|
|
240
255
|
this.refreshContextGauge();
|
|
241
256
|
// Start terminal input (sets up handlers)
|
|
242
257
|
this.terminalInput.start();
|
|
258
|
+
// Set up command autocomplete with all slash commands
|
|
259
|
+
this.setupCommandAutocomplete();
|
|
243
260
|
// Enter alternate screen buffer when enabled, otherwise clear the main screen for layout
|
|
244
261
|
if (this.alternateScreenEnabled) {
|
|
245
262
|
this.terminalInput.enterAlternateScreen();
|
|
@@ -256,6 +273,37 @@ export class InteractiveShell {
|
|
|
256
273
|
this.rebuildAgent();
|
|
257
274
|
this.setupHandlers();
|
|
258
275
|
this.refreshBannerSessionInfo();
|
|
276
|
+
// Subscribe to parallel agent manager events
|
|
277
|
+
this.setupParallelAgentTracking();
|
|
278
|
+
}
|
|
279
|
+
parallelAgentDisplayLines = [];
|
|
280
|
+
setupParallelAgentTracking() {
|
|
281
|
+
const manager = getParallelAgentManager();
|
|
282
|
+
// Update display when agent status changes
|
|
283
|
+
const updateDisplay = () => {
|
|
284
|
+
this.parallelAgentDisplayLines = manager.formatDisplay();
|
|
285
|
+
// Trigger UI refresh if streaming
|
|
286
|
+
if (this.streamingHeartbeatStart) {
|
|
287
|
+
this.displayParallelAgents();
|
|
288
|
+
}
|
|
289
|
+
};
|
|
290
|
+
manager.on('agent:started', updateDisplay);
|
|
291
|
+
manager.on('agent:progress', updateDisplay);
|
|
292
|
+
manager.on('agent:completed', updateDisplay);
|
|
293
|
+
manager.on('agent:error', updateDisplay);
|
|
294
|
+
manager.on('batch:completed', () => {
|
|
295
|
+
// Clear after batch completes to show final summary
|
|
296
|
+
setTimeout(() => {
|
|
297
|
+
this.parallelAgentDisplayLines = [];
|
|
298
|
+
}, 2000);
|
|
299
|
+
});
|
|
300
|
+
}
|
|
301
|
+
displayParallelAgents() {
|
|
302
|
+
if (this.parallelAgentDisplayLines.length === 0)
|
|
303
|
+
return;
|
|
304
|
+
// Display parallel agent tree above the current output
|
|
305
|
+
const agentDisplay = this.parallelAgentDisplayLines.join('\n');
|
|
306
|
+
display.parallelAgentStatus(agentDisplay);
|
|
259
307
|
}
|
|
260
308
|
initializeSessionHistory() {
|
|
261
309
|
this.cachedHistory = [];
|
|
@@ -362,6 +410,18 @@ export class InteractiveShell {
|
|
|
362
410
|
this.shutdown();
|
|
363
411
|
return;
|
|
364
412
|
}
|
|
413
|
+
// Handle pending interactions (from /model, /secrets, etc.) immediately
|
|
414
|
+
if (this.pendingInteraction) {
|
|
415
|
+
this.terminalInput.dequeue();
|
|
416
|
+
void this.handlePendingInteraction(text);
|
|
417
|
+
return;
|
|
418
|
+
}
|
|
419
|
+
// Allow certain commands to run immediately during streaming
|
|
420
|
+
if (this.isImmediateCommand(text)) {
|
|
421
|
+
this.terminalInput.dequeue();
|
|
422
|
+
void this.executeImmediateCommand(text);
|
|
423
|
+
return;
|
|
424
|
+
}
|
|
365
425
|
// Keep adapter queue trimmed so hints stay accurate
|
|
366
426
|
this.terminalInput.dequeue();
|
|
367
427
|
this.followUpQueue.push({ type: 'request', text });
|
|
@@ -370,6 +430,51 @@ export class InteractiveShell {
|
|
|
370
430
|
this.scheduleQueueProcessing();
|
|
371
431
|
this.handleInputChange('');
|
|
372
432
|
}
|
|
433
|
+
/**
|
|
434
|
+
* Check if a command can execute immediately during streaming.
|
|
435
|
+
* These are configuration and info commands that don't interact with the AI.
|
|
436
|
+
*/
|
|
437
|
+
isImmediateCommand(text) {
|
|
438
|
+
const trimmed = text.trim().toLowerCase();
|
|
439
|
+
if (!trimmed.startsWith('/'))
|
|
440
|
+
return false;
|
|
441
|
+
// Commands that can run during streaming
|
|
442
|
+
const immediateCommands = [
|
|
443
|
+
'/help', '/?',
|
|
444
|
+
'/model', '/models',
|
|
445
|
+
'/secrets',
|
|
446
|
+
'/tools',
|
|
447
|
+
'/mcp',
|
|
448
|
+
'/provider', '/providers',
|
|
449
|
+
'/thinking',
|
|
450
|
+
'/autocontinue',
|
|
451
|
+
'/shortcuts', '/keys',
|
|
452
|
+
'/cost', '/usage',
|
|
453
|
+
'/context',
|
|
454
|
+
'/sessions',
|
|
455
|
+
'/features',
|
|
456
|
+
'/local', '/discover',
|
|
457
|
+
'/evolve', '/modular', '/a0',
|
|
458
|
+
'/learn',
|
|
459
|
+
'/test', '/tests',
|
|
460
|
+
'/plugins',
|
|
461
|
+
'/metrics', '/stats', '/perf',
|
|
462
|
+
'/terminal-setup',
|
|
463
|
+
'/permissions',
|
|
464
|
+
'/vim',
|
|
465
|
+
'/output-style',
|
|
466
|
+
];
|
|
467
|
+
const cmd = trimmed.split(/\s+/)[0];
|
|
468
|
+
return immediateCommands.includes(cmd);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Execute a command immediately during streaming.
|
|
472
|
+
*/
|
|
473
|
+
async executeImmediateCommand(text) {
|
|
474
|
+
// Pause streaming display briefly to show command output
|
|
475
|
+
display.showInfo(`Running command during stream: ${text}`);
|
|
476
|
+
await this.processSlashCommand(text);
|
|
477
|
+
}
|
|
373
478
|
/**
|
|
374
479
|
* TerminalInputAdapter change handler
|
|
375
480
|
*/
|
|
@@ -386,11 +491,22 @@ export class InteractiveShell {
|
|
|
386
491
|
handleEditModeChange(mode) {
|
|
387
492
|
this.editGuardMode = mode;
|
|
388
493
|
this.pendingPermissionInput = null;
|
|
389
|
-
if (mode === '
|
|
390
|
-
|
|
494
|
+
if (mode === 'plan') {
|
|
495
|
+
// Register plan approval callback for interactive UI
|
|
496
|
+
setPlanApprovalCallback((steps, explanation) => {
|
|
497
|
+
this.showPlanApproval(steps, explanation);
|
|
498
|
+
});
|
|
499
|
+
display.showSystemMessage('📋 Plan mode enabled. AI will create a plan and ask for approval before implementing.');
|
|
391
500
|
}
|
|
392
501
|
else {
|
|
393
|
-
|
|
502
|
+
// Unregister callback when not in plan mode
|
|
503
|
+
setPlanApprovalCallback(null);
|
|
504
|
+
if (mode === 'ask-permission') {
|
|
505
|
+
display.showSystemMessage('🛡️ Ask-to-edit mode enabled. Confirm each request before sending.');
|
|
506
|
+
}
|
|
507
|
+
else {
|
|
508
|
+
display.showSystemMessage('✏️ Display edits mode enabled.');
|
|
509
|
+
}
|
|
394
510
|
}
|
|
395
511
|
this.terminalInput.render();
|
|
396
512
|
}
|
|
@@ -757,6 +873,130 @@ export class InteractiveShell {
|
|
|
757
873
|
this.agentMenu.persistedProfile = profileName;
|
|
758
874
|
display.showInfo(`${this.agentMenuLabel(profileName)} will load the next time you start the CLI. Restart to switch now.`);
|
|
759
875
|
}
|
|
876
|
+
/**
|
|
877
|
+
* Show plan approval UI with interactive step selection
|
|
878
|
+
*/
|
|
879
|
+
showPlanApproval(steps, explanation) {
|
|
880
|
+
const planSteps = steps.map((step, idx) => ({
|
|
881
|
+
id: idx + 1,
|
|
882
|
+
description: step.description,
|
|
883
|
+
status: 'pending',
|
|
884
|
+
}));
|
|
885
|
+
this.pendingInteraction = {
|
|
886
|
+
type: 'plan-approval',
|
|
887
|
+
steps: planSteps,
|
|
888
|
+
selectedSteps: new Set(planSteps.map(s => s.id)), // All selected by default
|
|
889
|
+
explanation,
|
|
890
|
+
};
|
|
891
|
+
this.displayPlanApprovalUI();
|
|
892
|
+
}
|
|
893
|
+
displayPlanApprovalUI() {
|
|
894
|
+
const pending = this.pendingInteraction;
|
|
895
|
+
if (!pending || pending.type !== 'plan-approval')
|
|
896
|
+
return;
|
|
897
|
+
const lines = [];
|
|
898
|
+
lines.push('');
|
|
899
|
+
lines.push(theme.gradient.primary('═'.repeat(60)));
|
|
900
|
+
lines.push(theme.gradient.primary('📋 PLAN FOR APPROVAL'));
|
|
901
|
+
lines.push(theme.gradient.primary('═'.repeat(60)));
|
|
902
|
+
lines.push('');
|
|
903
|
+
if (pending.explanation) {
|
|
904
|
+
lines.push(theme.ui.muted(pending.explanation));
|
|
905
|
+
lines.push('');
|
|
906
|
+
}
|
|
907
|
+
lines.push(theme.info('Steps (toggle with number, or enter your own):'));
|
|
908
|
+
lines.push('');
|
|
909
|
+
for (const step of pending.steps) {
|
|
910
|
+
const isSelected = pending.selectedSteps.has(step.id);
|
|
911
|
+
const checkbox = isSelected ? theme.success('☑') : theme.ui.muted('☐');
|
|
912
|
+
const stepNum = theme.info(`${step.id}.`);
|
|
913
|
+
const desc = isSelected ? step.description : theme.ui.muted(step.description);
|
|
914
|
+
lines.push(` ${checkbox} ${stepNum} ${desc}`);
|
|
915
|
+
}
|
|
916
|
+
lines.push('');
|
|
917
|
+
lines.push(theme.ui.muted('─'.repeat(60)));
|
|
918
|
+
lines.push('');
|
|
919
|
+
lines.push(theme.info('Commands:'));
|
|
920
|
+
lines.push(` ${theme.primary('1-N')} Toggle step selection`);
|
|
921
|
+
lines.push(` ${theme.primary('all')} Select all steps`);
|
|
922
|
+
lines.push(` ${theme.primary('none')} Deselect all steps`);
|
|
923
|
+
lines.push(` ${theme.primary('go')} Execute selected steps`);
|
|
924
|
+
lines.push(` ${theme.primary('cancel')} Cancel planning`);
|
|
925
|
+
lines.push(` ${theme.primary('[text]')} Submit your own solution instead`);
|
|
926
|
+
lines.push('');
|
|
927
|
+
display.showSystemMessage(lines.join('\n'));
|
|
928
|
+
this.terminalInput.render();
|
|
929
|
+
}
|
|
930
|
+
async handlePlanApprovalInput(input) {
|
|
931
|
+
const pending = this.pendingInteraction;
|
|
932
|
+
if (!pending || pending.type !== 'plan-approval')
|
|
933
|
+
return;
|
|
934
|
+
const trimmed = input.trim();
|
|
935
|
+
if (!trimmed) {
|
|
936
|
+
display.showWarning('Enter a command or your own solution.');
|
|
937
|
+
this.terminalInput.render();
|
|
938
|
+
return;
|
|
939
|
+
}
|
|
940
|
+
const lower = trimmed.toLowerCase();
|
|
941
|
+
// Cancel
|
|
942
|
+
if (lower === 'cancel' || lower === 'c') {
|
|
943
|
+
this.pendingInteraction = null;
|
|
944
|
+
display.showInfo('Plan cancelled. You can continue with a different approach.');
|
|
945
|
+
this.terminalInput.render();
|
|
946
|
+
return;
|
|
947
|
+
}
|
|
948
|
+
// Select all
|
|
949
|
+
if (lower === 'all' || lower === 'a') {
|
|
950
|
+
pending.selectedSteps = new Set(pending.steps.map(s => s.id));
|
|
951
|
+
this.displayPlanApprovalUI();
|
|
952
|
+
return;
|
|
953
|
+
}
|
|
954
|
+
// Deselect all
|
|
955
|
+
if (lower === 'none' || lower === 'n') {
|
|
956
|
+
pending.selectedSteps.clear();
|
|
957
|
+
this.displayPlanApprovalUI();
|
|
958
|
+
return;
|
|
959
|
+
}
|
|
960
|
+
// Execute selected steps
|
|
961
|
+
if (lower === 'go' || lower === 'g' || lower === 'yes' || lower === 'y') {
|
|
962
|
+
const selectedSteps = pending.steps.filter(s => pending.selectedSteps.has(s.id));
|
|
963
|
+
if (selectedSteps.length === 0) {
|
|
964
|
+
display.showWarning('No steps selected. Select steps or enter your own solution.');
|
|
965
|
+
this.terminalInput.render();
|
|
966
|
+
return;
|
|
967
|
+
}
|
|
968
|
+
this.pendingInteraction = null;
|
|
969
|
+
// Build the implementation prompt with selected steps
|
|
970
|
+
const stepList = selectedSteps.map(s => `${s.id}. ${s.description}`).join('\n');
|
|
971
|
+
const implementPrompt = `Proceed with implementing the following steps:\n\n${stepList}\n\nStart implementing now. Use the appropriate tools.`;
|
|
972
|
+
// Queue the implementation request
|
|
973
|
+
await this.processInputBlock(implementPrompt);
|
|
974
|
+
return;
|
|
975
|
+
}
|
|
976
|
+
// Toggle step by number
|
|
977
|
+
const num = Number.parseInt(trimmed, 10);
|
|
978
|
+
if (Number.isFinite(num) && num >= 1 && num <= pending.steps.length) {
|
|
979
|
+
if (pending.selectedSteps.has(num)) {
|
|
980
|
+
pending.selectedSteps.delete(num);
|
|
981
|
+
}
|
|
982
|
+
else {
|
|
983
|
+
pending.selectedSteps.add(num);
|
|
984
|
+
}
|
|
985
|
+
this.displayPlanApprovalUI();
|
|
986
|
+
return;
|
|
987
|
+
}
|
|
988
|
+
// User submitted their own solution - treat as custom input
|
|
989
|
+
if (trimmed.length > 10) {
|
|
990
|
+
this.pendingInteraction = null;
|
|
991
|
+
display.showInfo('Using your custom solution...');
|
|
992
|
+
// Send the custom solution as the implementation request
|
|
993
|
+
const customPrompt = `The user has provided their own solution instead of the plan. Please implement this:\n\n${trimmed}`;
|
|
994
|
+
await this.processInputBlock(customPrompt);
|
|
995
|
+
return;
|
|
996
|
+
}
|
|
997
|
+
display.showWarning('Invalid input. Enter a step number, command (go/cancel/all/none), or your own solution.');
|
|
998
|
+
this.terminalInput.render();
|
|
999
|
+
}
|
|
760
1000
|
setupHandlers() {
|
|
761
1001
|
// Handle terminal resize
|
|
762
1002
|
output.on('resize', () => {
|
|
@@ -765,6 +1005,39 @@ export class InteractiveShell {
|
|
|
765
1005
|
// Show initial input UI
|
|
766
1006
|
this.terminalInput.render();
|
|
767
1007
|
}
|
|
1008
|
+
/**
|
|
1009
|
+
* Set up command autocomplete with all available slash commands.
|
|
1010
|
+
* Commands are loaded from agent-schemas.json and custom commands.
|
|
1011
|
+
*/
|
|
1012
|
+
setupCommandAutocomplete() {
|
|
1013
|
+
const commands = [];
|
|
1014
|
+
// Load built-in slash commands from schema
|
|
1015
|
+
const schemaCommands = getSlashCommands();
|
|
1016
|
+
for (const cmd of schemaCommands) {
|
|
1017
|
+
commands.push({
|
|
1018
|
+
command: cmd.command,
|
|
1019
|
+
description: cmd.description,
|
|
1020
|
+
category: cmd.category,
|
|
1021
|
+
});
|
|
1022
|
+
}
|
|
1023
|
+
// Load custom commands (if any)
|
|
1024
|
+
try {
|
|
1025
|
+
const customCommands = loadCustomSlashCommands(this.workingDir);
|
|
1026
|
+
for (const custom of customCommands) {
|
|
1027
|
+
commands.push({
|
|
1028
|
+
command: custom.command,
|
|
1029
|
+
description: custom.description || 'Custom command',
|
|
1030
|
+
category: custom.category || 'custom',
|
|
1031
|
+
});
|
|
1032
|
+
}
|
|
1033
|
+
}
|
|
1034
|
+
catch {
|
|
1035
|
+
// Custom commands are optional
|
|
1036
|
+
}
|
|
1037
|
+
// Sort commands alphabetically
|
|
1038
|
+
commands.sort((a, b) => a.command.localeCompare(b.command));
|
|
1039
|
+
this.terminalInput.setAvailableCommands(commands);
|
|
1040
|
+
}
|
|
768
1041
|
setupStatusTracking() {
|
|
769
1042
|
this.statusSubscription = this.statusTracker.subscribe((state) => {
|
|
770
1043
|
this.statusLineState = state;
|
|
@@ -1008,6 +1281,12 @@ export class InteractiveShell {
|
|
|
1008
1281
|
const frame = STREAMING_SPINNER_FRAMES[this.streamingHeartbeatFrame];
|
|
1009
1282
|
this.streamingStatusLabel = this.buildStreamingStatus(`${frame} ${label}`, elapsedSeconds);
|
|
1010
1283
|
display.updateStreamingStatus(this.streamingStatusLabel);
|
|
1284
|
+
// Update parallel agent display during streaming
|
|
1285
|
+
const manager = getParallelAgentManager();
|
|
1286
|
+
if (manager.isRunning()) {
|
|
1287
|
+
this.parallelAgentDisplayLines = manager.formatDisplay();
|
|
1288
|
+
this.displayParallelAgents();
|
|
1289
|
+
}
|
|
1011
1290
|
this.refreshStatusLine(true);
|
|
1012
1291
|
},
|
|
1013
1292
|
});
|
|
@@ -1219,6 +1498,9 @@ export class InteractiveShell {
|
|
|
1219
1498
|
case 'agent-selection':
|
|
1220
1499
|
await this.handleAgentSelectionInput(input);
|
|
1221
1500
|
return true;
|
|
1501
|
+
case 'plan-approval':
|
|
1502
|
+
await this.handlePlanApprovalInput(input);
|
|
1503
|
+
return true;
|
|
1222
1504
|
default:
|
|
1223
1505
|
return false;
|
|
1224
1506
|
}
|
|
@@ -1238,6 +1520,12 @@ export class InteractiveShell {
|
|
|
1238
1520
|
case '/features':
|
|
1239
1521
|
this.showFeaturesMenu(input);
|
|
1240
1522
|
break;
|
|
1523
|
+
case '/learn':
|
|
1524
|
+
this.showLearningStatus(input);
|
|
1525
|
+
break;
|
|
1526
|
+
case '/improve':
|
|
1527
|
+
void this.handleImprovementCommand(input);
|
|
1528
|
+
break;
|
|
1241
1529
|
case '/model':
|
|
1242
1530
|
this.showModelMenu();
|
|
1243
1531
|
break;
|
|
@@ -1299,6 +1587,17 @@ export class InteractiveShell {
|
|
|
1299
1587
|
case '/plugins':
|
|
1300
1588
|
this.showPluginStatus();
|
|
1301
1589
|
break;
|
|
1590
|
+
case '/evolve':
|
|
1591
|
+
void this.handleEvolveCommand(input);
|
|
1592
|
+
break;
|
|
1593
|
+
case '/modular':
|
|
1594
|
+
case '/a0':
|
|
1595
|
+
void this.handleModularCommand(input);
|
|
1596
|
+
break;
|
|
1597
|
+
case '/test':
|
|
1598
|
+
case '/tests':
|
|
1599
|
+
void this.handleTestCommand(input);
|
|
1600
|
+
break;
|
|
1302
1601
|
case '/provider':
|
|
1303
1602
|
await this.handleProviderCommand(input);
|
|
1304
1603
|
break;
|
|
@@ -1311,6 +1610,58 @@ export class InteractiveShell {
|
|
|
1311
1610
|
case '/discover':
|
|
1312
1611
|
await this.discoverModelsCommand();
|
|
1313
1612
|
break;
|
|
1613
|
+
// Claude Code style commands
|
|
1614
|
+
case '/rewind':
|
|
1615
|
+
await this.handleRewindCommand(input);
|
|
1616
|
+
break;
|
|
1617
|
+
case '/memory':
|
|
1618
|
+
this.handleMemoryCommand(input);
|
|
1619
|
+
break;
|
|
1620
|
+
case '/vim':
|
|
1621
|
+
this.handleVimCommand();
|
|
1622
|
+
break;
|
|
1623
|
+
case '/output-style':
|
|
1624
|
+
this.handleOutputStyleCommand(input);
|
|
1625
|
+
break;
|
|
1626
|
+
case '/cost':
|
|
1627
|
+
this.handleCostCommand();
|
|
1628
|
+
break;
|
|
1629
|
+
case '/usage':
|
|
1630
|
+
this.handleUsageCommand();
|
|
1631
|
+
break;
|
|
1632
|
+
case '/update':
|
|
1633
|
+
await this.handleUpdateCommand();
|
|
1634
|
+
break;
|
|
1635
|
+
case '/clear':
|
|
1636
|
+
this.handleClearCommand();
|
|
1637
|
+
break;
|
|
1638
|
+
case '/resume':
|
|
1639
|
+
await this.handleResumeCommand(input);
|
|
1640
|
+
break;
|
|
1641
|
+
case '/export':
|
|
1642
|
+
this.handleExportCommand(input);
|
|
1643
|
+
break;
|
|
1644
|
+
case '/review':
|
|
1645
|
+
await this.handleReviewCommand();
|
|
1646
|
+
break;
|
|
1647
|
+
case '/security-review':
|
|
1648
|
+
await this.handleSecurityReviewCommand();
|
|
1649
|
+
break;
|
|
1650
|
+
case '/bug':
|
|
1651
|
+
this.handleBugCommand();
|
|
1652
|
+
break;
|
|
1653
|
+
case '/terminal-setup':
|
|
1654
|
+
this.handleTerminalSetupCommand();
|
|
1655
|
+
break;
|
|
1656
|
+
case '/permissions':
|
|
1657
|
+
this.handlePermissionsCommand();
|
|
1658
|
+
break;
|
|
1659
|
+
case '/init':
|
|
1660
|
+
this.handleInitCommand();
|
|
1661
|
+
break;
|
|
1662
|
+
case '/compact':
|
|
1663
|
+
await this.handleCompactCommand();
|
|
1664
|
+
break;
|
|
1314
1665
|
default:
|
|
1315
1666
|
if (!(await this.tryCustomSlashCommand(command, input))) {
|
|
1316
1667
|
display.showWarning(`Unknown command "${command}".`);
|
|
@@ -1772,6 +2123,878 @@ export class InteractiveShell {
|
|
|
1772
2123
|
lines.push(theme.ui.muted('Feature changes take effect on next launch.'));
|
|
1773
2124
|
display.showSystemMessage(lines.join('\n'));
|
|
1774
2125
|
}
|
|
2126
|
+
showLearningStatus(input) {
|
|
2127
|
+
const args = input.split(/\s+/).slice(1);
|
|
2128
|
+
const subcommand = args[0]?.toLowerCase();
|
|
2129
|
+
// Handle subcommands
|
|
2130
|
+
if (subcommand === 'commit') {
|
|
2131
|
+
const result = commitLearning(args.slice(1).join(' ') || 'Manual learning checkpoint', this.workingDir);
|
|
2132
|
+
if (result.success) {
|
|
2133
|
+
display.showInfo(`Learning committed: ${result.commitHash}`);
|
|
2134
|
+
}
|
|
2135
|
+
else {
|
|
2136
|
+
display.showWarning(`Could not commit: ${result.error}`);
|
|
2137
|
+
}
|
|
2138
|
+
return;
|
|
2139
|
+
}
|
|
2140
|
+
if (subcommand === 'export') {
|
|
2141
|
+
const data = exportAllLearning();
|
|
2142
|
+
const json = JSON.stringify(data, null, 2);
|
|
2143
|
+
display.showSystemMessage(`Exported learning data:\n\n${json.slice(0, 2000)}${json.length > 2000 ? '\n...(truncated)' : ''}`);
|
|
2144
|
+
return;
|
|
2145
|
+
}
|
|
2146
|
+
if (subcommand === 'history') {
|
|
2147
|
+
const history = getRecentLearning(20);
|
|
2148
|
+
const lines = [];
|
|
2149
|
+
lines.push(theme.gradient.primary('Recent Learning History'));
|
|
2150
|
+
lines.push('');
|
|
2151
|
+
if (history.length === 0) {
|
|
2152
|
+
lines.push(theme.ui.muted('No learning history yet.'));
|
|
2153
|
+
}
|
|
2154
|
+
else {
|
|
2155
|
+
for (const entry of history) {
|
|
2156
|
+
const date = new Date(entry.timestamp).toLocaleString();
|
|
2157
|
+
const icon = entry.type === 'tool-pattern' ? '🔧' :
|
|
2158
|
+
entry.type === 'quality-threshold' ? '📊' :
|
|
2159
|
+
entry.type === 'failure-pattern' ? '⚠️' : '💡';
|
|
2160
|
+
lines.push(` ${icon} ${theme.ui.muted(date)}`);
|
|
2161
|
+
lines.push(` ${entry.description}`);
|
|
2162
|
+
}
|
|
2163
|
+
}
|
|
2164
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2165
|
+
return;
|
|
2166
|
+
}
|
|
2167
|
+
// Default: show summary
|
|
2168
|
+
const summary = getLearningSummary();
|
|
2169
|
+
const lines = [];
|
|
2170
|
+
lines.push(theme.gradient.primary('🧠 AlphaZero Learning Status'));
|
|
2171
|
+
lines.push('');
|
|
2172
|
+
// Tool patterns
|
|
2173
|
+
lines.push(theme.bold('Tool Patterns Learned:'));
|
|
2174
|
+
if (summary.toolPatterns.totalPatterns === 0) {
|
|
2175
|
+
lines.push(` ${theme.ui.muted('No patterns learned yet. Use the CLI to build up patterns.')}`);
|
|
2176
|
+
}
|
|
2177
|
+
else {
|
|
2178
|
+
lines.push(` Total: ${theme.info(String(summary.toolPatterns.totalPatterns))} patterns across ${summary.toolPatterns.taskTypes.length} task types`);
|
|
2179
|
+
if (summary.toolPatterns.bestPatterns.length > 0) {
|
|
2180
|
+
lines.push(' Best patterns:');
|
|
2181
|
+
for (const p of summary.toolPatterns.bestPatterns) {
|
|
2182
|
+
const rate = Math.round(p.successRate * 100);
|
|
2183
|
+
lines.push(` ${theme.success('•')} ${p.taskType}: ${theme.ui.muted(p.pattern)} (${rate}% success)`);
|
|
2184
|
+
}
|
|
2185
|
+
}
|
|
2186
|
+
}
|
|
2187
|
+
lines.push('');
|
|
2188
|
+
// Quality thresholds
|
|
2189
|
+
lines.push(theme.bold('Quality Thresholds:'));
|
|
2190
|
+
lines.push(` Min acceptable: ${theme.warning(String(Math.round(summary.qualityThresholds.avgMinAcceptable)))}/100`);
|
|
2191
|
+
lines.push(` Target quality: ${theme.success(String(Math.round(summary.qualityThresholds.avgTargetQuality)))}/100`);
|
|
2192
|
+
lines.push(` Task types: ${summary.qualityThresholds.taskTypes.join(', ')}`);
|
|
2193
|
+
lines.push('');
|
|
2194
|
+
// Failure patterns
|
|
2195
|
+
lines.push(theme.bold('Failure Patterns:'));
|
|
2196
|
+
if (summary.failurePatterns.totalPatterns === 0) {
|
|
2197
|
+
lines.push(` ${theme.ui.muted('No failure patterns recorded.')}`);
|
|
2198
|
+
}
|
|
2199
|
+
else {
|
|
2200
|
+
lines.push(` Total: ${theme.warning(String(summary.failurePatterns.totalPatterns))} patterns to avoid`);
|
|
2201
|
+
if (summary.failurePatterns.mostFrequent.length > 0) {
|
|
2202
|
+
for (const f of summary.failurePatterns.mostFrequent) {
|
|
2203
|
+
lines.push(` ${theme.error('✗')} ${f.description} (${f.occurrences}x)`);
|
|
2204
|
+
}
|
|
2205
|
+
}
|
|
2206
|
+
}
|
|
2207
|
+
lines.push('');
|
|
2208
|
+
// Prompt improvements
|
|
2209
|
+
lines.push(theme.bold('Prompt Improvements:'));
|
|
2210
|
+
if (summary.promptImprovements.totalImprovements === 0) {
|
|
2211
|
+
lines.push(` ${theme.ui.muted('No prompt improvements discovered yet.')}`);
|
|
2212
|
+
}
|
|
2213
|
+
else {
|
|
2214
|
+
lines.push(` Total: ${theme.info(String(summary.promptImprovements.totalImprovements))} improvements`);
|
|
2215
|
+
lines.push(` Categories: ${summary.promptImprovements.categories.join(', ')}`);
|
|
2216
|
+
lines.push(` Avg quality gain: ${theme.success(`+${Math.round(summary.promptImprovements.avgQualityGain)}%`)}`);
|
|
2217
|
+
}
|
|
2218
|
+
lines.push('');
|
|
2219
|
+
// Recent activity
|
|
2220
|
+
lines.push(theme.bold('Activity:'));
|
|
2221
|
+
lines.push(` Learning events (24h): ${summary.recentActivity}`);
|
|
2222
|
+
lines.push(` Storage: ${theme.ui.muted(getLearningDir())}`);
|
|
2223
|
+
lines.push('');
|
|
2224
|
+
// Commands
|
|
2225
|
+
lines.push(theme.bold('Commands:'));
|
|
2226
|
+
lines.push(` ${theme.primary('/learn')} - Show this summary`);
|
|
2227
|
+
lines.push(` ${theme.primary('/learn history')} - View recent learning events`);
|
|
2228
|
+
lines.push(` ${theme.primary('/learn commit')} - Commit learning to git`);
|
|
2229
|
+
lines.push(` ${theme.primary('/learn export')} - Export learning data as JSON`);
|
|
2230
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2231
|
+
}
|
|
2232
|
+
/**
|
|
2233
|
+
* Handle /improve command for self-improvement
|
|
2234
|
+
*/
|
|
2235
|
+
async handleImprovementCommand(input) {
|
|
2236
|
+
const args = input.split(/\s+/).slice(1);
|
|
2237
|
+
const subcommand = args[0]?.toLowerCase();
|
|
2238
|
+
if (subcommand === 'analyze') {
|
|
2239
|
+
const opportunities = analyzeImprovementOpportunities(this.workingDir);
|
|
2240
|
+
const lines = [];
|
|
2241
|
+
lines.push(theme.gradient.primary('🔍 Improvement Analysis'));
|
|
2242
|
+
lines.push('');
|
|
2243
|
+
if (opportunities.length === 0) {
|
|
2244
|
+
lines.push(theme.ui.muted('No improvement opportunities found. Keep using the CLI to build learning data.'));
|
|
2245
|
+
}
|
|
2246
|
+
else {
|
|
2247
|
+
lines.push(`Found ${theme.info(String(opportunities.length))} improvement opportunities:`);
|
|
2248
|
+
lines.push('');
|
|
2249
|
+
for (const opp of opportunities.slice(0, 10)) {
|
|
2250
|
+
const icon = opp.type === 'bug-fix' ? '🐛' : opp.type === 'refactor' ? '🔧' : '⚡';
|
|
2251
|
+
const priorityColor = opp.priority === 'critical' ? theme.error :
|
|
2252
|
+
opp.priority === 'high' ? theme.warning : theme.info;
|
|
2253
|
+
lines.push(` ${icon} ${priorityColor(`[${opp.priority}]`)} ${opp.description.slice(0, 60)}`);
|
|
2254
|
+
lines.push(` ${theme.ui.muted(`Confidence: ${Math.round(opp.confidence * 100)}%`)} | ${theme.ui.muted(`File: ${opp.sourceFile}`)}`);
|
|
2255
|
+
for (const ev of opp.evidence.slice(0, 2)) {
|
|
2256
|
+
lines.push(` ${theme.dim(`• ${ev}`)}`);
|
|
2257
|
+
}
|
|
2258
|
+
lines.push('');
|
|
2259
|
+
}
|
|
2260
|
+
if (opportunities.length > 10) {
|
|
2261
|
+
lines.push(theme.ui.muted(`... and ${opportunities.length - 10} more`));
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2265
|
+
return;
|
|
2266
|
+
}
|
|
2267
|
+
if (subcommand === 'apply') {
|
|
2268
|
+
display.showSystemMessage(theme.gradient.primary('🚀 Running Self-Improvement Cycle...'));
|
|
2269
|
+
display.showSystemMessage('');
|
|
2270
|
+
try {
|
|
2271
|
+
const result = await runSelfImprovementCycle(this.workingDir, {
|
|
2272
|
+
maxChanges: 3,
|
|
2273
|
+
minConfidence: 0.7,
|
|
2274
|
+
runTests: true,
|
|
2275
|
+
autoCommit: true,
|
|
2276
|
+
});
|
|
2277
|
+
const lines = [];
|
|
2278
|
+
lines.push(theme.bold('Results:'));
|
|
2279
|
+
lines.push(result.summary);
|
|
2280
|
+
lines.push('');
|
|
2281
|
+
if (result.applied > 0) {
|
|
2282
|
+
lines.push(theme.success(`✅ Applied ${result.applied} improvements!`));
|
|
2283
|
+
for (const r of result.results.filter(r => r.success)) {
|
|
2284
|
+
lines.push(` - Files: ${r.filesChanged.join(', ')}`);
|
|
2285
|
+
if (r.commitHash) {
|
|
2286
|
+
lines.push(` Commit: ${theme.ui.muted(r.commitHash)}`);
|
|
2287
|
+
lines.push(` Rollback: ${theme.dim(r.rollbackCommand ?? '')}`);
|
|
2288
|
+
}
|
|
2289
|
+
}
|
|
2290
|
+
}
|
|
2291
|
+
else {
|
|
2292
|
+
lines.push(theme.warning('No improvements were applied.'));
|
|
2293
|
+
for (const r of result.results.filter(r => !r.success)) {
|
|
2294
|
+
lines.push(` ${theme.error('✗')} ${r.error}`);
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2298
|
+
}
|
|
2299
|
+
catch (error) {
|
|
2300
|
+
display.showError(`Self-improvement failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2301
|
+
}
|
|
2302
|
+
return;
|
|
2303
|
+
}
|
|
2304
|
+
if (subcommand === 'dry-run') {
|
|
2305
|
+
const opportunities = analyzeImprovementOpportunities(this.workingDir);
|
|
2306
|
+
const filtered = opportunities.filter(o => o.confidence >= 0.7);
|
|
2307
|
+
const toApply = filtered.slice(0, 3);
|
|
2308
|
+
const lines = [];
|
|
2309
|
+
lines.push(theme.gradient.primary('🔮 Dry Run - Preview Changes'));
|
|
2310
|
+
lines.push('');
|
|
2311
|
+
if (toApply.length === 0) {
|
|
2312
|
+
lines.push(theme.ui.muted('No high-confidence improvements to apply.'));
|
|
2313
|
+
}
|
|
2314
|
+
else {
|
|
2315
|
+
lines.push(`Would apply ${theme.info(String(toApply.length))} improvements:`);
|
|
2316
|
+
lines.push('');
|
|
2317
|
+
for (const opp of toApply) {
|
|
2318
|
+
const icon = opp.type === 'bug-fix' ? '🐛' : opp.type === 'refactor' ? '🔧' : '⚡';
|
|
2319
|
+
lines.push(` ${icon} ${opp.description.slice(0, 60)}`);
|
|
2320
|
+
lines.push(` ${theme.ui.muted(`File: ${opp.sourceFile}`)}`);
|
|
2321
|
+
lines.push(` ${theme.dim(`Suggested: ${opp.suggestedChange.slice(0, 100)}...`)}`);
|
|
2322
|
+
lines.push('');
|
|
2323
|
+
}
|
|
2324
|
+
lines.push(theme.bold('Run `/improve apply` to execute these changes.'));
|
|
2325
|
+
}
|
|
2326
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2327
|
+
return;
|
|
2328
|
+
}
|
|
2329
|
+
if (subcommand === 'auto') {
|
|
2330
|
+
void this.runAutonomousImprovementMode();
|
|
2331
|
+
return;
|
|
2332
|
+
}
|
|
2333
|
+
if (subcommand === 'stop') {
|
|
2334
|
+
requestAutoImprovementStop();
|
|
2335
|
+
display.showInfo('Requested stop of autonomous improvement...');
|
|
2336
|
+
return;
|
|
2337
|
+
}
|
|
2338
|
+
if (subcommand === 'rollback') {
|
|
2339
|
+
const result = emergencyRollback(this.workingDir);
|
|
2340
|
+
if (result.success) {
|
|
2341
|
+
display.showSuccess(result.message);
|
|
2342
|
+
}
|
|
2343
|
+
else {
|
|
2344
|
+
display.showError(result.message);
|
|
2345
|
+
}
|
|
2346
|
+
return;
|
|
2347
|
+
}
|
|
2348
|
+
if (subcommand === 'status') {
|
|
2349
|
+
const state = getAutoImprovementState();
|
|
2350
|
+
const lines = [];
|
|
2351
|
+
lines.push(theme.gradient.primary('🤖 Auto-Improvement Status'));
|
|
2352
|
+
lines.push('');
|
|
2353
|
+
lines.push(`Running: ${state.isRunning ? theme.success('Yes') : theme.ui.muted('No')}`);
|
|
2354
|
+
if (state.startTime) {
|
|
2355
|
+
lines.push(`Started: ${theme.ui.muted(state.startTime)}`);
|
|
2356
|
+
}
|
|
2357
|
+
lines.push(`Iteration: ${state.iteration}`);
|
|
2358
|
+
lines.push(`Applied: ${theme.success(String(state.applied))}`);
|
|
2359
|
+
lines.push(`Failed: ${theme.warning(String(state.failed))}`);
|
|
2360
|
+
lines.push(`Rollbacks: ${theme.error(String(state.rollbacks))}`);
|
|
2361
|
+
if (state.lastError) {
|
|
2362
|
+
lines.push(`Last Error: ${theme.error(state.lastError)}`);
|
|
2363
|
+
}
|
|
2364
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2365
|
+
return;
|
|
2366
|
+
}
|
|
2367
|
+
// Default: show summary
|
|
2368
|
+
const summary = getImprovementSummary(this.workingDir);
|
|
2369
|
+
display.showSystemMessage(summary);
|
|
2370
|
+
}
|
|
2371
|
+
/**
|
|
2372
|
+
* Run autonomous improvement mode with self-relaunch capability
|
|
2373
|
+
*/
|
|
2374
|
+
async runAutonomousImprovementMode() {
|
|
2375
|
+
const isSelfImproving = this.workingDir.includes('erosolar');
|
|
2376
|
+
display.showSystemMessage(theme.gradient.primary('🤖 Starting Autonomous Improvement Mode'));
|
|
2377
|
+
display.showSystemMessage('');
|
|
2378
|
+
display.showSystemMessage(`${theme.bold('Safety Features:')}`);
|
|
2379
|
+
display.showSystemMessage(' • Git checkpoint created before starting');
|
|
2380
|
+
display.showSystemMessage(' • Each change validated with build + tests');
|
|
2381
|
+
display.showSystemMessage(' • Auto-rollback on failures');
|
|
2382
|
+
display.showSystemMessage(' • Press Ctrl+C to stop gracefully');
|
|
2383
|
+
if (isSelfImproving) {
|
|
2384
|
+
display.showSystemMessage(' • CLI will relaunch after improvements to run new code');
|
|
2385
|
+
}
|
|
2386
|
+
display.showSystemMessage('');
|
|
2387
|
+
display.showSystemMessage(`${theme.bold('Commands while running:')}`);
|
|
2388
|
+
display.showSystemMessage(' /improve stop - Request graceful stop');
|
|
2389
|
+
display.showSystemMessage(' /improve status - Check current status');
|
|
2390
|
+
display.showSystemMessage(' /improve rollback - Emergency rollback to checkpoint');
|
|
2391
|
+
display.showSystemMessage('');
|
|
2392
|
+
let stopRequested = false;
|
|
2393
|
+
// Set up Ctrl+C handler
|
|
2394
|
+
const originalSigintHandler = process.listeners('SIGINT');
|
|
2395
|
+
process.removeAllListeners('SIGINT');
|
|
2396
|
+
process.once('SIGINT', () => {
|
|
2397
|
+
display.showWarning('Ctrl+C pressed - stopping after current iteration...');
|
|
2398
|
+
stopRequested = true;
|
|
2399
|
+
requestAutoImprovementStop();
|
|
2400
|
+
});
|
|
2401
|
+
try {
|
|
2402
|
+
const result = await runAutonomousImprovement({
|
|
2403
|
+
workingDir: this.workingDir,
|
|
2404
|
+
minConfidence: 0.75,
|
|
2405
|
+
maxIterations: 100,
|
|
2406
|
+
delayBetweenMs: 3000,
|
|
2407
|
+
runTests: true,
|
|
2408
|
+
shouldStop: () => stopRequested,
|
|
2409
|
+
onProgress: (event) => {
|
|
2410
|
+
switch (event.type) {
|
|
2411
|
+
case 'start':
|
|
2412
|
+
display.showInfo(event.message);
|
|
2413
|
+
break;
|
|
2414
|
+
case 'iteration':
|
|
2415
|
+
display.showSystemMessage(`\n${theme.bold(`[Iteration ${event.iteration}]`)} ${event.message}`);
|
|
2416
|
+
break;
|
|
2417
|
+
case 'applied':
|
|
2418
|
+
display.showSuccess(event.message);
|
|
2419
|
+
display.showSystemMessage(` Total applied: ${event.totalApplied}`);
|
|
2420
|
+
break;
|
|
2421
|
+
case 'failed':
|
|
2422
|
+
display.showWarning(event.message);
|
|
2423
|
+
break;
|
|
2424
|
+
case 'rollback':
|
|
2425
|
+
display.showError(event.message);
|
|
2426
|
+
break;
|
|
2427
|
+
case 'no-opportunities':
|
|
2428
|
+
display.showInfo(event.message);
|
|
2429
|
+
break;
|
|
2430
|
+
case 'complete':
|
|
2431
|
+
display.showSystemMessage('');
|
|
2432
|
+
display.showSystemMessage(theme.gradient.primary('═══ Autonomous Improvement Complete ═══'));
|
|
2433
|
+
display.showSystemMessage(event.message);
|
|
2434
|
+
if (event.totalApplied !== undefined) {
|
|
2435
|
+
display.showSystemMessage(`Applied: ${theme.success(String(event.totalApplied))}`);
|
|
2436
|
+
}
|
|
2437
|
+
if (event.totalFailed !== undefined) {
|
|
2438
|
+
display.showSystemMessage(`Failed: ${theme.warning(String(event.totalFailed))}`);
|
|
2439
|
+
}
|
|
2440
|
+
break;
|
|
2441
|
+
}
|
|
2442
|
+
},
|
|
2443
|
+
});
|
|
2444
|
+
// Restore SIGINT handlers
|
|
2445
|
+
process.removeAllListeners('SIGINT');
|
|
2446
|
+
for (const handler of originalSigintHandler) {
|
|
2447
|
+
process.on('SIGINT', handler);
|
|
2448
|
+
}
|
|
2449
|
+
// Summary
|
|
2450
|
+
display.showSystemMessage('');
|
|
2451
|
+
display.showSystemMessage(theme.bold('Final Summary:'));
|
|
2452
|
+
display.showSystemMessage(` Iterations: ${result.iterations}`);
|
|
2453
|
+
display.showSystemMessage(` Applied: ${theme.success(String(result.totalApplied))}`);
|
|
2454
|
+
display.showSystemMessage(` Failed: ${theme.warning(String(result.totalFailed))}`);
|
|
2455
|
+
display.showSystemMessage(` Rollbacks: ${theme.error(String(result.totalRollbacks))}`);
|
|
2456
|
+
display.showSystemMessage(` Stopped: ${result.stoppedReason}`);
|
|
2457
|
+
// If we improved erosolar-cli itself and applied changes, offer to relaunch
|
|
2458
|
+
if (isSelfImproving && result.totalApplied > 0) {
|
|
2459
|
+
display.showSystemMessage('');
|
|
2460
|
+
display.showSystemMessage(theme.gradient.primary('🔄 CLI source code was updated!'));
|
|
2461
|
+
display.showSystemMessage('To run the improved version:');
|
|
2462
|
+
display.showSystemMessage(` ${theme.bold('npm run build && erosolar')}`);
|
|
2463
|
+
display.showSystemMessage('');
|
|
2464
|
+
display.showSystemMessage('Or to continue auto-improvement with new code:');
|
|
2465
|
+
display.showSystemMessage(` ${theme.bold('npm run build && erosolar -c "/improve auto"')}`);
|
|
2466
|
+
}
|
|
2467
|
+
}
|
|
2468
|
+
catch (error) {
|
|
2469
|
+
// Restore SIGINT handlers
|
|
2470
|
+
process.removeAllListeners('SIGINT');
|
|
2471
|
+
for (const handler of originalSigintHandler) {
|
|
2472
|
+
process.on('SIGINT', handler);
|
|
2473
|
+
}
|
|
2474
|
+
display.showError(`Autonomous improvement failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2475
|
+
display.showSystemMessage('');
|
|
2476
|
+
display.showSystemMessage('Run `/improve rollback` to restore to the checkpoint if needed.');
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
/**
|
|
2480
|
+
* Handle /evolve command for self-evolution (erosolar-cli source only)
|
|
2481
|
+
*/
|
|
2482
|
+
async handleEvolveCommand(input) {
|
|
2483
|
+
const args = input.split(/\s+/).slice(1);
|
|
2484
|
+
const subcommand = args[0]?.toLowerCase();
|
|
2485
|
+
// Check if we're in a valid source repository
|
|
2486
|
+
if (!isValidSourceRepo(this.workingDir)) {
|
|
2487
|
+
display.showWarning('Self-evolution requires a git repository with source code.');
|
|
2488
|
+
display.showSystemMessage('');
|
|
2489
|
+
display.showSystemMessage('Current directory: ' + this.workingDir);
|
|
2490
|
+
display.showSystemMessage('');
|
|
2491
|
+
display.showSystemMessage('Requirements:');
|
|
2492
|
+
display.showSystemMessage(' • Must be a git repository (.git folder)');
|
|
2493
|
+
display.showSystemMessage(' • Must have package.json or src/ directory');
|
|
2494
|
+
display.showSystemMessage('');
|
|
2495
|
+
display.showSystemMessage('Navigate to your project directory and try again.');
|
|
2496
|
+
return;
|
|
2497
|
+
}
|
|
2498
|
+
const repoName = getRepoName(this.workingDir);
|
|
2499
|
+
const isErosolar = isErosolarRepo(this.workingDir);
|
|
2500
|
+
if (subcommand === 'analyze') {
|
|
2501
|
+
display.showSystemMessage(theme.gradient.primary(`🔍 Analyzing ${repoName} Source Code...`));
|
|
2502
|
+
display.showSystemMessage('');
|
|
2503
|
+
const issues = analyzeSource(this.workingDir);
|
|
2504
|
+
const lines = [];
|
|
2505
|
+
if (issues.length === 0) {
|
|
2506
|
+
lines.push(theme.success('✅ No issues found! Source code looks clean.'));
|
|
2507
|
+
}
|
|
2508
|
+
else {
|
|
2509
|
+
const bySeverity = {
|
|
2510
|
+
critical: issues.filter(i => i.severity === 'critical'),
|
|
2511
|
+
high: issues.filter(i => i.severity === 'high'),
|
|
2512
|
+
medium: issues.filter(i => i.severity === 'medium'),
|
|
2513
|
+
low: issues.filter(i => i.severity === 'low'),
|
|
2514
|
+
};
|
|
2515
|
+
lines.push(`Found ${theme.bold(String(issues.length))} issues:`);
|
|
2516
|
+
lines.push('');
|
|
2517
|
+
if (bySeverity.critical.length > 0) {
|
|
2518
|
+
lines.push(theme.error(` 🔴 Critical: ${bySeverity.critical.length}`));
|
|
2519
|
+
}
|
|
2520
|
+
if (bySeverity.high.length > 0) {
|
|
2521
|
+
lines.push(theme.warning(` 🟠 High: ${bySeverity.high.length}`));
|
|
2522
|
+
}
|
|
2523
|
+
if (bySeverity.medium.length > 0) {
|
|
2524
|
+
lines.push(theme.info(` 🟡 Medium: ${bySeverity.medium.length}`));
|
|
2525
|
+
}
|
|
2526
|
+
if (bySeverity.low.length > 0) {
|
|
2527
|
+
lines.push(theme.dim(` ⚪ Low: ${bySeverity.low.length}`));
|
|
2528
|
+
}
|
|
2529
|
+
lines.push('');
|
|
2530
|
+
// Show top 10 issues
|
|
2531
|
+
lines.push(theme.bold('Top Issues:'));
|
|
2532
|
+
for (const issue of issues.slice(0, 10)) {
|
|
2533
|
+
const icon = issue.severity === 'critical' ? '🔴' :
|
|
2534
|
+
issue.severity === 'high' ? '🟠' :
|
|
2535
|
+
issue.severity === 'medium' ? '🟡' : '⚪';
|
|
2536
|
+
lines.push(` ${icon} ${issue.file}:${issue.line ?? '?'}`);
|
|
2537
|
+
lines.push(` ${theme.dim(issue.description.slice(0, 70))}`);
|
|
2538
|
+
lines.push(` ${theme.ui.muted(`Confidence: ${Math.round(issue.confidence * 100)}%`)}`);
|
|
2539
|
+
}
|
|
2540
|
+
if (issues.length > 10) {
|
|
2541
|
+
lines.push('');
|
|
2542
|
+
lines.push(theme.ui.muted(`... and ${issues.length - 10} more issues`));
|
|
2543
|
+
}
|
|
2544
|
+
}
|
|
2545
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2546
|
+
return;
|
|
2547
|
+
}
|
|
2548
|
+
if (subcommand === 'start') {
|
|
2549
|
+
display.showSystemMessage(theme.gradient.primary('🧬 Starting Self-Evolution Mode'));
|
|
2550
|
+
display.showSystemMessage('');
|
|
2551
|
+
display.showSystemMessage(theme.bold('Safety Features:'));
|
|
2552
|
+
display.showSystemMessage(' • Git checkpoint created before starting');
|
|
2553
|
+
display.showSystemMessage(' • Each change validated with build + tests');
|
|
2554
|
+
display.showSystemMessage(' • Auto-rollback on failures');
|
|
2555
|
+
display.showSystemMessage(' • Auto-relaunch with improved code');
|
|
2556
|
+
display.showSystemMessage(' • Press Ctrl+C to stop gracefully');
|
|
2557
|
+
display.showSystemMessage('');
|
|
2558
|
+
try {
|
|
2559
|
+
const result = await runSelfEvolution(this.workingDir, {
|
|
2560
|
+
maxIterations: 50,
|
|
2561
|
+
minConfidence: 0.8,
|
|
2562
|
+
runTests: true,
|
|
2563
|
+
autoRelaunch: true,
|
|
2564
|
+
}, {
|
|
2565
|
+
onStart: () => {
|
|
2566
|
+
display.showInfo('Evolution started. Creating checkpoint...');
|
|
2567
|
+
},
|
|
2568
|
+
onIteration: (iteration, issues) => {
|
|
2569
|
+
display.showSystemMessage(`\n[Iteration ${iteration}] Found ${issues.length} high-confidence issues`);
|
|
2570
|
+
},
|
|
2571
|
+
onFix: (issue, success) => {
|
|
2572
|
+
if (success) {
|
|
2573
|
+
display.showSuccess(`Fixed: ${issue.description.slice(0, 50)}`);
|
|
2574
|
+
}
|
|
2575
|
+
else {
|
|
2576
|
+
display.showWarning(`Failed: ${issue.description.slice(0, 50)}`);
|
|
2577
|
+
}
|
|
2578
|
+
},
|
|
2579
|
+
onRelaunch: () => {
|
|
2580
|
+
display.showSystemMessage('');
|
|
2581
|
+
display.showSystemMessage(theme.gradient.primary('🔄 Relaunching with improved code...'));
|
|
2582
|
+
},
|
|
2583
|
+
onComplete: (result) => {
|
|
2584
|
+
display.showSystemMessage('');
|
|
2585
|
+
display.showSuccess(`Evolution complete! Fixed ${result.issuesFixed} issues.`);
|
|
2586
|
+
},
|
|
2587
|
+
onError: (error) => {
|
|
2588
|
+
display.showError(`Evolution error: ${error}`);
|
|
2589
|
+
},
|
|
2590
|
+
});
|
|
2591
|
+
const lines = [];
|
|
2592
|
+
lines.push('');
|
|
2593
|
+
lines.push(theme.bold('Evolution Result:'));
|
|
2594
|
+
lines.push(` Success: ${result.success ? theme.success('Yes') : theme.error('No')}`);
|
|
2595
|
+
lines.push(` Iterations: ${result.iteration}`);
|
|
2596
|
+
lines.push(` Issues Found: ${result.issuesFound}`);
|
|
2597
|
+
lines.push(` Issues Fixed: ${result.issuesFixed}`);
|
|
2598
|
+
if (result.error) {
|
|
2599
|
+
lines.push(` Error: ${theme.error(result.error)}`);
|
|
2600
|
+
}
|
|
2601
|
+
lines.push(` Next Action: ${result.nextAction}`);
|
|
2602
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2603
|
+
}
|
|
2604
|
+
catch (error) {
|
|
2605
|
+
display.showError(`Evolution failed: ${error instanceof Error ? error.message : String(error)}`);
|
|
2606
|
+
}
|
|
2607
|
+
return;
|
|
2608
|
+
}
|
|
2609
|
+
if (subcommand === 'stop') {
|
|
2610
|
+
stopEvolution();
|
|
2611
|
+
display.showInfo('Requested stop of evolution...');
|
|
2612
|
+
return;
|
|
2613
|
+
}
|
|
2614
|
+
if (subcommand === 'rollback') {
|
|
2615
|
+
const result = emergencyEvolutionRollback(this.workingDir);
|
|
2616
|
+
if (result.success) {
|
|
2617
|
+
display.showSuccess(result.message);
|
|
2618
|
+
}
|
|
2619
|
+
else {
|
|
2620
|
+
display.showError(result.message);
|
|
2621
|
+
}
|
|
2622
|
+
return;
|
|
2623
|
+
}
|
|
2624
|
+
if (subcommand === 'status') {
|
|
2625
|
+
const status = getEvolutionStatus(this.workingDir);
|
|
2626
|
+
display.showSystemMessage(status);
|
|
2627
|
+
return;
|
|
2628
|
+
}
|
|
2629
|
+
if (subcommand === 'learn') {
|
|
2630
|
+
display.showSystemMessage(theme.gradient.primary(`📚 Learning from ${repoName} Source Code...`));
|
|
2631
|
+
display.showSystemMessage('');
|
|
2632
|
+
const patterns = learnSourcePatterns(this.workingDir);
|
|
2633
|
+
const lines = [];
|
|
2634
|
+
if (patterns.length === 0) {
|
|
2635
|
+
lines.push(theme.warning('No patterns could be extracted.'));
|
|
2636
|
+
}
|
|
2637
|
+
else {
|
|
2638
|
+
lines.push(`Learned ${theme.bold(String(patterns.length))} patterns from source code:`);
|
|
2639
|
+
lines.push('');
|
|
2640
|
+
const byCategory = {
|
|
2641
|
+
'tool-implementation': patterns.filter(p => p.category === 'tool-implementation'),
|
|
2642
|
+
'error-handling': patterns.filter(p => p.category === 'error-handling'),
|
|
2643
|
+
'type-pattern': patterns.filter(p => p.category === 'type-pattern'),
|
|
2644
|
+
'api-design': patterns.filter(p => p.category === 'api-design'),
|
|
2645
|
+
};
|
|
2646
|
+
for (const [category, catPatterns] of Object.entries(byCategory)) {
|
|
2647
|
+
if (catPatterns.length > 0) {
|
|
2648
|
+
const icon = category === 'tool-implementation' ? '🔧' :
|
|
2649
|
+
category === 'error-handling' ? '⚠️' :
|
|
2650
|
+
category === 'type-pattern' ? '📝' : '🏗️';
|
|
2651
|
+
lines.push(`${icon} ${theme.bold(category)}: ${catPatterns.length} patterns`);
|
|
2652
|
+
for (const pattern of catPatterns.slice(0, 3)) {
|
|
2653
|
+
lines.push(` • ${pattern.description}`);
|
|
2654
|
+
lines.push(` ${theme.dim(`Source: ${pattern.sourceFile}`)}`);
|
|
2655
|
+
}
|
|
2656
|
+
if (catPatterns.length > 3) {
|
|
2657
|
+
lines.push(` ${theme.ui.muted(`... and ${catPatterns.length - 3} more`)}`);
|
|
2658
|
+
}
|
|
2659
|
+
lines.push('');
|
|
2660
|
+
}
|
|
2661
|
+
}
|
|
2662
|
+
lines.push(theme.success('✅ Patterns saved to ~/.erosolar/source-patterns.json'));
|
|
2663
|
+
lines.push('');
|
|
2664
|
+
lines.push('These patterns help the system understand optimal code structures');
|
|
2665
|
+
lines.push('and can be used to guide future code generation.');
|
|
2666
|
+
}
|
|
2667
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2668
|
+
return;
|
|
2669
|
+
}
|
|
2670
|
+
if (subcommand === 'fix') {
|
|
2671
|
+
display.showSystemMessage(theme.gradient.primary('🔧 Generating Fixes for Source Issues...'));
|
|
2672
|
+
display.showSystemMessage('');
|
|
2673
|
+
const issues = analyzeSource(this.workingDir);
|
|
2674
|
+
const highConfidence = issues.filter(i => i.confidence >= 0.7);
|
|
2675
|
+
if (highConfidence.length === 0) {
|
|
2676
|
+
display.showInfo('No high-confidence issues found that need fixing.');
|
|
2677
|
+
return;
|
|
2678
|
+
}
|
|
2679
|
+
const lines = [];
|
|
2680
|
+
lines.push(`Found ${highConfidence.length} issues. Generating fixes...`);
|
|
2681
|
+
lines.push('');
|
|
2682
|
+
let fixCount = 0;
|
|
2683
|
+
for (const issue of highConfidence.slice(0, 5)) {
|
|
2684
|
+
const fix = generateFix(issue, this.workingDir);
|
|
2685
|
+
if (fix) {
|
|
2686
|
+
fixCount++;
|
|
2687
|
+
lines.push(`${theme.bold(`Fix ${fixCount}:`)} ${issue.file}:${issue.line}`);
|
|
2688
|
+
lines.push(` Issue: ${issue.description.slice(0, 60)}`);
|
|
2689
|
+
lines.push(` Fix: ${fix.explanation}`);
|
|
2690
|
+
lines.push(` Confidence: ${Math.round(fix.confidence * 100)}%`);
|
|
2691
|
+
lines.push(` ${fix.requiresManualReview ? theme.warning('⚠️ Requires review') : theme.success('✅ Auto-applicable')}`);
|
|
2692
|
+
lines.push('');
|
|
2693
|
+
}
|
|
2694
|
+
}
|
|
2695
|
+
if (fixCount === 0) {
|
|
2696
|
+
lines.push(theme.warning('No automatic fixes could be generated for these issues.'));
|
|
2697
|
+
}
|
|
2698
|
+
else {
|
|
2699
|
+
lines.push(`Generated ${fixCount} fix suggestions.`);
|
|
2700
|
+
lines.push('');
|
|
2701
|
+
lines.push(`Run ${theme.bold('/evolve start')} to apply fixes automatically with safety checks.`);
|
|
2702
|
+
}
|
|
2703
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2704
|
+
return;
|
|
2705
|
+
}
|
|
2706
|
+
// ========== MODULAR / TOKEN OPTIMIZATION COMMANDS ==========
|
|
2707
|
+
if (subcommand === 'tokens') {
|
|
2708
|
+
display.showSystemMessage(theme.gradient.primary('🔍 Analyzing Token Usage...'));
|
|
2709
|
+
display.showSystemMessage('');
|
|
2710
|
+
const analysis = analyzeTokenUsage(this.workingDir);
|
|
2711
|
+
const lines = [];
|
|
2712
|
+
lines.push(`Total Tokens: ${theme.bold(analysis.totalTokens.toLocaleString())}`);
|
|
2713
|
+
lines.push('');
|
|
2714
|
+
lines.push(theme.bold('By Category:'));
|
|
2715
|
+
for (const [category, tokens] of Object.entries(analysis.byCategory)) {
|
|
2716
|
+
const pct = ((tokens / analysis.totalTokens) * 100).toFixed(1);
|
|
2717
|
+
const bar = '█'.repeat(Math.floor(Number(pct) / 5)) + '░'.repeat(20 - Math.floor(Number(pct) / 5));
|
|
2718
|
+
lines.push(` ${category.padEnd(15)} ${bar} ${tokens.toLocaleString().padStart(8)} (${pct}%)`);
|
|
2719
|
+
}
|
|
2720
|
+
lines.push('');
|
|
2721
|
+
lines.push(theme.bold('Optimization Opportunities:'));
|
|
2722
|
+
for (const opp of analysis.optimizationOpportunities.slice(0, 10)) {
|
|
2723
|
+
lines.push(` ${opp.autoFixable ? '✅' : '⚠️'} ${opp.target}`);
|
|
2724
|
+
lines.push(` Save: ${opp.savings} tokens (${opp.savingsPercent}%)`);
|
|
2725
|
+
lines.push(` ${theme.dim(opp.strategy)}`);
|
|
2726
|
+
}
|
|
2727
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2728
|
+
return;
|
|
2729
|
+
}
|
|
2730
|
+
if (subcommand === 'targets') {
|
|
2731
|
+
const targets = discoverModularTargets(this.workingDir);
|
|
2732
|
+
const lines = [];
|
|
2733
|
+
lines.push(theme.gradient.primary('🎯 Modular Targets'));
|
|
2734
|
+
lines.push('');
|
|
2735
|
+
lines.push(`Found ${theme.bold(String(targets.length))} targets`);
|
|
2736
|
+
lines.push('');
|
|
2737
|
+
const byType = {};
|
|
2738
|
+
for (const target of targets) {
|
|
2739
|
+
if (!byType[target.type])
|
|
2740
|
+
byType[target.type] = [];
|
|
2741
|
+
byType[target.type].push(target);
|
|
2742
|
+
}
|
|
2743
|
+
for (const [type, typeTargets] of Object.entries(byType)) {
|
|
2744
|
+
lines.push(theme.bold(`${type} (${typeTargets.length}):`));
|
|
2745
|
+
for (const target of typeTargets.slice(0, 5)) {
|
|
2746
|
+
const issueCount = target.issues.length;
|
|
2747
|
+
const icon = issueCount === 0 ? '✅' : issueCount < 3 ? '⚠️' : '🔴';
|
|
2748
|
+
lines.push(` ${icon} ${target.name} (${target.tokenCount} tokens)`);
|
|
2749
|
+
if (target.issues.length > 0) {
|
|
2750
|
+
lines.push(` ${theme.dim(target.issues[0]?.description ?? '')}`);
|
|
2751
|
+
}
|
|
2752
|
+
}
|
|
2753
|
+
if (typeTargets.length > 5) {
|
|
2754
|
+
lines.push(` ${theme.dim(`... and ${typeTargets.length - 5} more`)}`);
|
|
2755
|
+
}
|
|
2756
|
+
lines.push('');
|
|
2757
|
+
}
|
|
2758
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2759
|
+
return;
|
|
2760
|
+
}
|
|
2761
|
+
if (subcommand === 'optimize') {
|
|
2762
|
+
const optimizations = generateContextOptimizations(this.workingDir);
|
|
2763
|
+
const lines = [];
|
|
2764
|
+
lines.push(theme.gradient.primary('⚡ Context Optimization Strategies'));
|
|
2765
|
+
lines.push('');
|
|
2766
|
+
const totalSavings = optimizations.reduce((sum, o) => sum + o.tokensSaved, 0);
|
|
2767
|
+
lines.push(`Total potential savings: ${theme.success(totalSavings.toLocaleString())} tokens`);
|
|
2768
|
+
lines.push('');
|
|
2769
|
+
for (const opt of optimizations) {
|
|
2770
|
+
const icon = opt.impact === 'high' ? '🔴' : opt.impact === 'medium' ? '🟡' : '⚪';
|
|
2771
|
+
lines.push(`${icon} ${theme.bold(opt.strategy)}`);
|
|
2772
|
+
lines.push(` ${opt.description}`);
|
|
2773
|
+
lines.push(` Savings: ${theme.success(opt.tokensSaved.toLocaleString())} tokens`);
|
|
2774
|
+
lines.push(` ${theme.dim(opt.implementation)}`);
|
|
2775
|
+
lines.push('');
|
|
2776
|
+
}
|
|
2777
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2778
|
+
return;
|
|
2779
|
+
}
|
|
2780
|
+
if (subcommand === 'guidelines') {
|
|
2781
|
+
const action = args[1]?.toLowerCase();
|
|
2782
|
+
if (action === 'add') {
|
|
2783
|
+
display.showInfo('Use: /evolve guidelines add <id> <category> <rule>');
|
|
2784
|
+
return;
|
|
2785
|
+
}
|
|
2786
|
+
if (action === 'delete' && args[2]) {
|
|
2787
|
+
const result = deleteGuideline(args[2]);
|
|
2788
|
+
if (result.success) {
|
|
2789
|
+
display.showSuccess(`Deleted guideline: ${args[2]}`);
|
|
2790
|
+
}
|
|
2791
|
+
else {
|
|
2792
|
+
display.showError(result.error ?? 'Failed to delete');
|
|
2793
|
+
}
|
|
2794
|
+
return;
|
|
2795
|
+
}
|
|
2796
|
+
const guidelines = getGuidelines();
|
|
2797
|
+
const lines = [];
|
|
2798
|
+
lines.push(theme.gradient.primary('📋 Active Guidelines'));
|
|
2799
|
+
lines.push('');
|
|
2800
|
+
for (const g of guidelines) {
|
|
2801
|
+
const icon = g.severity === 'must' ? '🔴' : g.severity === 'should' ? '🟡' : '⚪';
|
|
2802
|
+
lines.push(`${icon} [${g.category}] ${theme.bold(g.id)}`);
|
|
2803
|
+
lines.push(` ${g.rule}`);
|
|
2804
|
+
lines.push(` ${theme.dim(g.rationale)}`);
|
|
2805
|
+
lines.push('');
|
|
2806
|
+
}
|
|
2807
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2808
|
+
return;
|
|
2809
|
+
}
|
|
2810
|
+
if (subcommand === 'actions') {
|
|
2811
|
+
const actions = getPendingActions();
|
|
2812
|
+
const lines = [];
|
|
2813
|
+
lines.push(theme.gradient.primary('📝 Pending Actions'));
|
|
2814
|
+
lines.push('');
|
|
2815
|
+
if (actions.length === 0) {
|
|
2816
|
+
lines.push(theme.dim('No pending actions'));
|
|
2817
|
+
}
|
|
2818
|
+
else {
|
|
2819
|
+
for (let i = 0; i < actions.length; i++) {
|
|
2820
|
+
const action = actions[i];
|
|
2821
|
+
lines.push(`${i + 1}. [${action.type}] ${action.target.name}`);
|
|
2822
|
+
lines.push(` Impact: ${action.tokenImpact > 0 ? '+' : ''}${action.tokenImpact} tokens`);
|
|
2823
|
+
lines.push(` ${theme.dim(action.changes.slice(0, 60))}`);
|
|
2824
|
+
lines.push('');
|
|
2825
|
+
}
|
|
2826
|
+
lines.push('Run /evolve execute <number> to apply an action');
|
|
2827
|
+
}
|
|
2828
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2829
|
+
return;
|
|
2830
|
+
}
|
|
2831
|
+
if (subcommand === 'execute') {
|
|
2832
|
+
const actionIndex = parseInt(args[1] ?? '', 10) - 1;
|
|
2833
|
+
const result = executeModularAction(actionIndex, this.workingDir);
|
|
2834
|
+
if (result.success) {
|
|
2835
|
+
display.showSuccess('Action executed successfully');
|
|
2836
|
+
}
|
|
2837
|
+
else {
|
|
2838
|
+
display.showError(result.error ?? 'Failed to execute');
|
|
2839
|
+
}
|
|
2840
|
+
return;
|
|
2841
|
+
}
|
|
2842
|
+
// Default: show combined status
|
|
2843
|
+
const evolveStatus = getEvolutionStatus(this.workingDir);
|
|
2844
|
+
const modularStatus = getModularStatusDisplay(this.workingDir);
|
|
2845
|
+
display.showSystemMessage(evolveStatus);
|
|
2846
|
+
display.showSystemMessage('');
|
|
2847
|
+
display.showSystemMessage(modularStatus);
|
|
2848
|
+
}
|
|
2849
|
+
/**
|
|
2850
|
+
* Handle /modular command - redirects to /evolve (merged functionality)
|
|
2851
|
+
*/
|
|
2852
|
+
async handleModularCommand(input) {
|
|
2853
|
+
// Redirect /modular to /evolve with the same arguments
|
|
2854
|
+
const evolveInput = input.replace(/^\/(?:modular|a0)\s*/i, '/evolve ');
|
|
2855
|
+
display.showInfo('Note: /modular is now part of /evolve. Use /evolve tokens, /evolve targets, etc.');
|
|
2856
|
+
await this.handleEvolveCommand(evolveInput);
|
|
2857
|
+
}
|
|
2858
|
+
/**
|
|
2859
|
+
* Handle /test command for intelligent test flows
|
|
2860
|
+
*/
|
|
2861
|
+
async handleTestCommand(input) {
|
|
2862
|
+
const args = input.split(/\s+/).slice(1);
|
|
2863
|
+
const subcommand = args[0]?.toLowerCase();
|
|
2864
|
+
if (subcommand === 'status' || !subcommand) {
|
|
2865
|
+
const status = getTestFlowStatus(this.workingDir);
|
|
2866
|
+
display.showSystemMessage(status);
|
|
2867
|
+
return;
|
|
2868
|
+
}
|
|
2869
|
+
if (subcommand === 'generate') {
|
|
2870
|
+
const targetPath = args[1];
|
|
2871
|
+
if (!targetPath) {
|
|
2872
|
+
display.showWarning('Usage: /test generate <file-path>');
|
|
2873
|
+
return;
|
|
2874
|
+
}
|
|
2875
|
+
display.showSystemMessage(theme.gradient.primary(`🧪 Generating Test Flows for ${targetPath}...`));
|
|
2876
|
+
display.showSystemMessage('');
|
|
2877
|
+
const flows = generateTestFlows(this.workingDir, targetPath);
|
|
2878
|
+
saveTestFlows(flows);
|
|
2879
|
+
const lines = [];
|
|
2880
|
+
lines.push(`Generated ${theme.bold(String(flows.length))} test flows`);
|
|
2881
|
+
lines.push('');
|
|
2882
|
+
const byCategory = {};
|
|
2883
|
+
for (const flow of flows) {
|
|
2884
|
+
byCategory[flow.category] = (byCategory[flow.category] || 0) + 1;
|
|
2885
|
+
}
|
|
2886
|
+
for (const [category, count] of Object.entries(byCategory)) {
|
|
2887
|
+
lines.push(` ${category}: ${count}`);
|
|
2888
|
+
}
|
|
2889
|
+
lines.push('');
|
|
2890
|
+
lines.push(theme.bold('Generated flows:'));
|
|
2891
|
+
for (const flow of flows.slice(0, 10)) {
|
|
2892
|
+
const icon = flow.complexity === 'extreme' ? '🔴' :
|
|
2893
|
+
flow.complexity === 'complex' ? '🟠' :
|
|
2894
|
+
flow.complexity === 'moderate' ? '🟡' : '⚪';
|
|
2895
|
+
lines.push(` ${icon} ${flow.name}`);
|
|
2896
|
+
lines.push(` ${theme.dim(flow.description.slice(0, 60))}`);
|
|
2897
|
+
}
|
|
2898
|
+
if (flows.length > 10) {
|
|
2899
|
+
lines.push(` ${theme.dim(`... and ${flows.length - 10} more`)}`);
|
|
2900
|
+
}
|
|
2901
|
+
lines.push('');
|
|
2902
|
+
lines.push(`Saved to ~/.erosolar/test-flows/`);
|
|
2903
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2904
|
+
return;
|
|
2905
|
+
}
|
|
2906
|
+
if (subcommand === 'bugs') {
|
|
2907
|
+
display.showSystemMessage(theme.gradient.primary('🐛 Detecting Potential Bugs...'));
|
|
2908
|
+
display.showSystemMessage('');
|
|
2909
|
+
const bugs = detectBugs(this.workingDir);
|
|
2910
|
+
saveBugReports(bugs);
|
|
2911
|
+
const lines = [];
|
|
2912
|
+
lines.push(`Found ${theme.bold(String(bugs.length))} potential issues`);
|
|
2913
|
+
lines.push('');
|
|
2914
|
+
const bySeverity = {};
|
|
2915
|
+
for (const bug of bugs) {
|
|
2916
|
+
bySeverity[bug.severity] = (bySeverity[bug.severity] || 0) + 1;
|
|
2917
|
+
}
|
|
2918
|
+
if (bySeverity['critical'])
|
|
2919
|
+
lines.push(` 🔴 Critical: ${bySeverity['critical']}`);
|
|
2920
|
+
if (bySeverity['high'])
|
|
2921
|
+
lines.push(` 🟠 High: ${bySeverity['high']}`);
|
|
2922
|
+
if (bySeverity['medium'])
|
|
2923
|
+
lines.push(` 🟡 Medium: ${bySeverity['medium']}`);
|
|
2924
|
+
if (bySeverity['low'])
|
|
2925
|
+
lines.push(` ⚪ Low: ${bySeverity['low']}`);
|
|
2926
|
+
lines.push('');
|
|
2927
|
+
lines.push(theme.bold('Top Issues:'));
|
|
2928
|
+
for (const bug of bugs.slice(0, 10)) {
|
|
2929
|
+
const icon = bug.severity === 'critical' ? '🔴' :
|
|
2930
|
+
bug.severity === 'high' ? '🟠' :
|
|
2931
|
+
bug.severity === 'medium' ? '🟡' : '⚪';
|
|
2932
|
+
lines.push(` ${icon} ${bug.title}`);
|
|
2933
|
+
lines.push(` ${bug.file}:${bug.line ?? '?'}`);
|
|
2934
|
+
lines.push(` ${theme.dim(bug.description.slice(0, 50))}`);
|
|
2935
|
+
if (bug.suggestedFix) {
|
|
2936
|
+
lines.push(` ${theme.success('Fix:')} ${bug.suggestedFix.slice(0, 50)}`);
|
|
2937
|
+
}
|
|
2938
|
+
lines.push('');
|
|
2939
|
+
}
|
|
2940
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2941
|
+
return;
|
|
2942
|
+
}
|
|
2943
|
+
if (subcommand === 'ui') {
|
|
2944
|
+
display.showSystemMessage(theme.gradient.primary('🎨 Detecting UI Updates...'));
|
|
2945
|
+
display.showSystemMessage('');
|
|
2946
|
+
const updates = detectUIUpdates(this.workingDir);
|
|
2947
|
+
saveUIUpdates(updates);
|
|
2948
|
+
const lines = [];
|
|
2949
|
+
lines.push(`Found ${theme.bold(String(updates.length))} UI improvements`);
|
|
2950
|
+
lines.push('');
|
|
2951
|
+
const byType = {};
|
|
2952
|
+
for (const update of updates) {
|
|
2953
|
+
byType[update.type] = (byType[update.type] || 0) + 1;
|
|
2954
|
+
}
|
|
2955
|
+
for (const [type, count] of Object.entries(byType)) {
|
|
2956
|
+
const icon = type === 'accessibility' ? '♿' :
|
|
2957
|
+
type === 'performance' ? '⚡' :
|
|
2958
|
+
type === 'style' ? '🎨' : '🔧';
|
|
2959
|
+
lines.push(` ${icon} ${type}: ${count}`);
|
|
2960
|
+
}
|
|
2961
|
+
lines.push('');
|
|
2962
|
+
lines.push(theme.bold('Updates:'));
|
|
2963
|
+
for (const update of updates.slice(0, 10)) {
|
|
2964
|
+
lines.push(` 📦 ${update.component} [${update.type}]`);
|
|
2965
|
+
lines.push(` ${theme.dim(update.description)}`);
|
|
2966
|
+
lines.push(` Before: ${theme.error(update.before.slice(0, 40))}`);
|
|
2967
|
+
lines.push(` After: ${theme.success(update.after.slice(0, 40))}`);
|
|
2968
|
+
lines.push('');
|
|
2969
|
+
}
|
|
2970
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2971
|
+
return;
|
|
2972
|
+
}
|
|
2973
|
+
if (subcommand === 'edge') {
|
|
2974
|
+
display.showSystemMessage(theme.gradient.primary('🔬 Edge Case Analysis'));
|
|
2975
|
+
display.showSystemMessage('');
|
|
2976
|
+
const bugs = detectBugs(this.workingDir);
|
|
2977
|
+
const edgeCases = bugs.filter(b => b.type === 'edge-case');
|
|
2978
|
+
const lines = [];
|
|
2979
|
+
lines.push(`Found ${theme.bold(String(edgeCases.length))} edge case issues`);
|
|
2980
|
+
lines.push('');
|
|
2981
|
+
for (const bug of edgeCases.slice(0, 15)) {
|
|
2982
|
+
const icon = bug.severity === 'critical' ? '🔴' :
|
|
2983
|
+
bug.severity === 'high' ? '🟠' : '🟡';
|
|
2984
|
+
lines.push(` ${icon} ${bug.title}`);
|
|
2985
|
+
lines.push(` ${bug.file}:${bug.line ?? '?'}`);
|
|
2986
|
+
if (bug.suggestedFix) {
|
|
2987
|
+
lines.push(` ${theme.success('Fix:')} ${bug.suggestedFix}`);
|
|
2988
|
+
}
|
|
2989
|
+
lines.push('');
|
|
2990
|
+
}
|
|
2991
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2992
|
+
return;
|
|
2993
|
+
}
|
|
2994
|
+
// Default: show status
|
|
2995
|
+
const status = getTestFlowStatus(this.workingDir);
|
|
2996
|
+
display.showSystemMessage(status);
|
|
2997
|
+
}
|
|
1775
2998
|
showPluginStatus() {
|
|
1776
2999
|
const available = listAvailablePlugins();
|
|
1777
3000
|
const lines = [];
|
|
@@ -1956,6 +3179,277 @@ export class InteractiveShell {
|
|
|
1956
3179
|
}
|
|
1957
3180
|
this.setAutoContinueMode(value === 'on', 'command');
|
|
1958
3181
|
}
|
|
3182
|
+
// ==================== Claude Code Style Commands ====================
|
|
3183
|
+
async handleRewindCommand(input) {
|
|
3184
|
+
const lines = [];
|
|
3185
|
+
lines.push(theme.bold('Rewind / Checkpoint System'));
|
|
3186
|
+
lines.push('');
|
|
3187
|
+
lines.push('Use checkpoints to restore previous states of your code and conversation.');
|
|
3188
|
+
lines.push('');
|
|
3189
|
+
lines.push(theme.secondary('Usage:'));
|
|
3190
|
+
lines.push(' /rewind Show available checkpoints');
|
|
3191
|
+
lines.push(' /rewind list List all checkpoints');
|
|
3192
|
+
lines.push(' /rewind <id> Rewind to specific checkpoint');
|
|
3193
|
+
lines.push(' /rewind code Rewind code only (keep conversation)');
|
|
3194
|
+
lines.push(' /rewind conv Rewind conversation only (keep code)');
|
|
3195
|
+
lines.push('');
|
|
3196
|
+
lines.push(theme.ui.muted('Tip: Press Esc+Esc for quick access to rewind menu'));
|
|
3197
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3198
|
+
}
|
|
3199
|
+
handleMemoryCommand(input) {
|
|
3200
|
+
const lines = [];
|
|
3201
|
+
lines.push(theme.bold('Memory System (EROSOLAR.md)'));
|
|
3202
|
+
lines.push('');
|
|
3203
|
+
lines.push('Create EROSOLAR.md files to store persistent context and preferences.');
|
|
3204
|
+
lines.push('');
|
|
3205
|
+
lines.push(theme.secondary('Memory Locations:'));
|
|
3206
|
+
lines.push(` ~/.erosolar/EROSOLAR.md ${theme.ui.muted('User preferences (global)')}`);
|
|
3207
|
+
lines.push(` ./EROSOLAR.md ${theme.ui.muted('Project memory')}`);
|
|
3208
|
+
lines.push(` ./.erosolar/EROSOLAR.md ${theme.ui.muted('Project memory (alternative)')}`);
|
|
3209
|
+
lines.push('');
|
|
3210
|
+
lines.push(theme.secondary('Features:'));
|
|
3211
|
+
lines.push(' - Use @path/to/file in prompts to reference files');
|
|
3212
|
+
lines.push(' - Use # prefix to quickly add notes to project memory');
|
|
3213
|
+
lines.push(' - Import other files with @./relative/path syntax');
|
|
3214
|
+
lines.push('');
|
|
3215
|
+
lines.push(theme.ui.muted('Tip: Create EROSOLAR.md with project coding standards for better results'));
|
|
3216
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3217
|
+
}
|
|
3218
|
+
handleVimCommand() {
|
|
3219
|
+
const lines = [];
|
|
3220
|
+
lines.push(theme.bold('Vim Mode'));
|
|
3221
|
+
lines.push('');
|
|
3222
|
+
lines.push('Enable vim-style editing in the input area.');
|
|
3223
|
+
lines.push('');
|
|
3224
|
+
lines.push(theme.secondary('Basic Commands:'));
|
|
3225
|
+
lines.push(' h/j/k/l Move left/down/up/right');
|
|
3226
|
+
lines.push(' w/b Word forward/backward');
|
|
3227
|
+
lines.push(' 0/$ Line start/end');
|
|
3228
|
+
lines.push(' i/a Insert before/after cursor');
|
|
3229
|
+
lines.push(' I/A Insert at line start/end');
|
|
3230
|
+
lines.push(' o/O Open line below/above');
|
|
3231
|
+
lines.push(' x Delete character');
|
|
3232
|
+
lines.push(' dd Delete line');
|
|
3233
|
+
lines.push(' yy Yank (copy) line');
|
|
3234
|
+
lines.push(' p Paste');
|
|
3235
|
+
lines.push(' Escape Return to normal mode');
|
|
3236
|
+
lines.push('');
|
|
3237
|
+
lines.push(theme.ui.muted('Vim mode is experimental. Toggle with /vim'));
|
|
3238
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3239
|
+
}
|
|
3240
|
+
handleOutputStyleCommand(input) {
|
|
3241
|
+
const lines = [];
|
|
3242
|
+
lines.push(theme.bold('Output Styles'));
|
|
3243
|
+
lines.push('');
|
|
3244
|
+
lines.push('Change how the AI responds to your requests.');
|
|
3245
|
+
lines.push('');
|
|
3246
|
+
lines.push(theme.secondary('Built-in Styles:'));
|
|
3247
|
+
lines.push(` default ${theme.ui.muted('Standard efficient coding mode')}`);
|
|
3248
|
+
lines.push(` explanatory ${theme.ui.muted('Educational with detailed explanations')}`);
|
|
3249
|
+
lines.push(` learning ${theme.ui.muted('Collaborative with TODO(human) markers')}`);
|
|
3250
|
+
lines.push(` concise ${theme.ui.muted('Minimal output, code-focused only')}`);
|
|
3251
|
+
lines.push('');
|
|
3252
|
+
lines.push(theme.secondary('Custom Styles:'));
|
|
3253
|
+
lines.push(' Create custom styles in ~/.erosolar/output-styles/');
|
|
3254
|
+
lines.push(' or .erosolar/output-styles/ for project-specific styles.');
|
|
3255
|
+
lines.push('');
|
|
3256
|
+
lines.push(theme.secondary('Usage:'));
|
|
3257
|
+
lines.push(' /output-style <name> Switch to a style');
|
|
3258
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3259
|
+
}
|
|
3260
|
+
handleCostCommand() {
|
|
3261
|
+
const lines = [];
|
|
3262
|
+
lines.push(theme.bold('Cost & Token Usage'));
|
|
3263
|
+
lines.push('');
|
|
3264
|
+
// This will be populated with actual data from costTracker
|
|
3265
|
+
lines.push(theme.secondary('Session Statistics:'));
|
|
3266
|
+
lines.push(' Input tokens: (tracking enabled)');
|
|
3267
|
+
lines.push(' Output tokens: (tracking enabled)');
|
|
3268
|
+
lines.push(' Estimated cost: $0.00');
|
|
3269
|
+
lines.push('');
|
|
3270
|
+
lines.push(theme.ui.muted('Token usage is tracked automatically during the session.'));
|
|
3271
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3272
|
+
}
|
|
3273
|
+
handleUsageCommand() {
|
|
3274
|
+
const percentage = this.latestTokenUsage.limit && this.latestTokenUsage.used
|
|
3275
|
+
? Math.round((this.latestTokenUsage.used / this.latestTokenUsage.limit) * 100)
|
|
3276
|
+
: 0;
|
|
3277
|
+
const lines = [];
|
|
3278
|
+
lines.push(theme.bold('Context Usage'));
|
|
3279
|
+
lines.push('');
|
|
3280
|
+
lines.push(theme.secondary('Current Context:'));
|
|
3281
|
+
lines.push(` Used: ${this.latestTokenUsage.used?.toLocaleString() ?? '?'} tokens`);
|
|
3282
|
+
lines.push(` Limit: ${this.latestTokenUsage.limit?.toLocaleString() ?? '?'} tokens`);
|
|
3283
|
+
lines.push(` Usage: ${percentage}%`);
|
|
3284
|
+
lines.push('');
|
|
3285
|
+
if (percentage > 80) {
|
|
3286
|
+
lines.push(theme.warning('Context is getting full. Consider using /compact.'));
|
|
3287
|
+
}
|
|
3288
|
+
else if (percentage > 60) {
|
|
3289
|
+
lines.push(theme.secondary('Context usage is moderate.'));
|
|
3290
|
+
}
|
|
3291
|
+
else {
|
|
3292
|
+
lines.push(theme.success('Plenty of context available.'));
|
|
3293
|
+
}
|
|
3294
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3295
|
+
}
|
|
3296
|
+
async handleUpdateCommand() {
|
|
3297
|
+
display.showInfo('Checking for updates...');
|
|
3298
|
+
const lines = [];
|
|
3299
|
+
lines.push(theme.bold('Update Check'));
|
|
3300
|
+
lines.push('');
|
|
3301
|
+
lines.push(`Current version: ${this.version ?? 'unknown'}`);
|
|
3302
|
+
lines.push('');
|
|
3303
|
+
lines.push(theme.secondary('To update:'));
|
|
3304
|
+
lines.push(' npm install -g erosolar-cli@latest');
|
|
3305
|
+
lines.push(' or: npm update erosolar-cli');
|
|
3306
|
+
lines.push('');
|
|
3307
|
+
lines.push(theme.ui.muted('Auto-updates will be checked periodically.'));
|
|
3308
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3309
|
+
}
|
|
3310
|
+
handleClearCommand() {
|
|
3311
|
+
if (this.agent) {
|
|
3312
|
+
this.agent.clearHistory();
|
|
3313
|
+
this.cachedHistory = this.agent.getHistory();
|
|
3314
|
+
}
|
|
3315
|
+
display.clear();
|
|
3316
|
+
clearAutosaveSnapshot(this.profile);
|
|
3317
|
+
display.showInfo('Conversation cleared. Starting fresh.');
|
|
3318
|
+
this.terminalInput.render();
|
|
3319
|
+
}
|
|
3320
|
+
async handleResumeCommand(input) {
|
|
3321
|
+
const tokens = input.split(/\s+/).slice(1);
|
|
3322
|
+
const sessionId = tokens[0];
|
|
3323
|
+
if (sessionId) {
|
|
3324
|
+
await this.loadSessionCommand(sessionId);
|
|
3325
|
+
}
|
|
3326
|
+
else {
|
|
3327
|
+
// Show session list and auto-select the most recent
|
|
3328
|
+
const sessions = listSessions(this.profile);
|
|
3329
|
+
if (sessions.length > 0) {
|
|
3330
|
+
display.showInfo('Resuming most recent session...');
|
|
3331
|
+
await this.loadSessionCommand('1');
|
|
3332
|
+
}
|
|
3333
|
+
else {
|
|
3334
|
+
display.showWarning('No previous sessions found. Use /sessions to manage sessions.');
|
|
3335
|
+
}
|
|
3336
|
+
}
|
|
3337
|
+
}
|
|
3338
|
+
handleExportCommand(input) {
|
|
3339
|
+
const lines = [];
|
|
3340
|
+
lines.push(theme.bold('Export Conversation'));
|
|
3341
|
+
lines.push('');
|
|
3342
|
+
lines.push('Export your conversation history for sharing or documentation.');
|
|
3343
|
+
lines.push('');
|
|
3344
|
+
lines.push(theme.secondary('Usage:'));
|
|
3345
|
+
lines.push(' /export Export to default file');
|
|
3346
|
+
lines.push(' /export <filename> Export to specific file');
|
|
3347
|
+
lines.push('');
|
|
3348
|
+
lines.push(theme.ui.muted('Exports include conversation history and tool results.'));
|
|
3349
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3350
|
+
}
|
|
3351
|
+
async handleReviewCommand() {
|
|
3352
|
+
if (this.isProcessing) {
|
|
3353
|
+
display.showWarning('Wait for the current operation to finish.');
|
|
3354
|
+
return;
|
|
3355
|
+
}
|
|
3356
|
+
display.showInfo('Triggering code review of pending changes...');
|
|
3357
|
+
await this.processRequest('Please review all the code changes we made in this session. Look for bugs, security issues, and improvements.');
|
|
3358
|
+
}
|
|
3359
|
+
async handleSecurityReviewCommand() {
|
|
3360
|
+
if (this.isProcessing) {
|
|
3361
|
+
display.showWarning('Wait for the current operation to finish.');
|
|
3362
|
+
return;
|
|
3363
|
+
}
|
|
3364
|
+
display.showInfo('Running comprehensive security review...');
|
|
3365
|
+
await this.processRequest('Please perform a comprehensive security review of the codebase. Check for OWASP top 10 vulnerabilities, insecure patterns, and potential attack vectors.');
|
|
3366
|
+
}
|
|
3367
|
+
handleBugCommand() {
|
|
3368
|
+
const lines = [];
|
|
3369
|
+
lines.push(theme.bold('Report an Issue'));
|
|
3370
|
+
lines.push('');
|
|
3371
|
+
lines.push('Found a bug or have a suggestion?');
|
|
3372
|
+
lines.push('');
|
|
3373
|
+
lines.push(theme.secondary('Report issues at:'));
|
|
3374
|
+
lines.push(' https://github.com/erosolar/erosolar-cli/issues');
|
|
3375
|
+
lines.push('');
|
|
3376
|
+
lines.push(theme.secondary('Include:'));
|
|
3377
|
+
lines.push(' - Steps to reproduce');
|
|
3378
|
+
lines.push(' - Expected vs actual behavior');
|
|
3379
|
+
lines.push(' - Version info (erosolar --version)');
|
|
3380
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3381
|
+
}
|
|
3382
|
+
handleTerminalSetupCommand() {
|
|
3383
|
+
const lines = [];
|
|
3384
|
+
lines.push(theme.bold('Terminal Setup'));
|
|
3385
|
+
lines.push('');
|
|
3386
|
+
lines.push('Configure terminal keybindings for better experience.');
|
|
3387
|
+
lines.push('');
|
|
3388
|
+
lines.push(theme.secondary('Recommended Settings:'));
|
|
3389
|
+
lines.push('');
|
|
3390
|
+
lines.push(theme.bold(' iTerm2:'));
|
|
3391
|
+
lines.push(' Preferences > Keys > Key Bindings');
|
|
3392
|
+
lines.push(' Add: Shift+Enter → Send Escape Sequence: [13;2u');
|
|
3393
|
+
lines.push('');
|
|
3394
|
+
lines.push(theme.bold(' VS Code Terminal:'));
|
|
3395
|
+
lines.push(' Already supports Shift+Enter natively');
|
|
3396
|
+
lines.push('');
|
|
3397
|
+
lines.push(theme.bold(' Kitty/Wezterm:'));
|
|
3398
|
+
lines.push(' Modern terminals support extended keys automatically');
|
|
3399
|
+
lines.push('');
|
|
3400
|
+
lines.push(theme.ui.muted('Shift+Enter enables multi-line input.'));
|
|
3401
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3402
|
+
}
|
|
3403
|
+
handlePermissionsCommand() {
|
|
3404
|
+
const lines = [];
|
|
3405
|
+
lines.push(theme.bold('Tool Permissions'));
|
|
3406
|
+
lines.push('');
|
|
3407
|
+
lines.push('Configure which tools require confirmation before execution.');
|
|
3408
|
+
lines.push('');
|
|
3409
|
+
lines.push(theme.secondary('Current Mode:'));
|
|
3410
|
+
const editMode = this.editGuardMode;
|
|
3411
|
+
lines.push(` Edit Guard: ${editMode === 'ask-permission' ? 'Ask before edits' : editMode === 'plan' ? 'Plan mode' : 'Auto-accept'}`);
|
|
3412
|
+
lines.push('');
|
|
3413
|
+
lines.push(theme.secondary('Toggle with:'));
|
|
3414
|
+
lines.push(' Shift+Tab Cycle through modes');
|
|
3415
|
+
lines.push(' Option+E Toggle edit permission');
|
|
3416
|
+
lines.push('');
|
|
3417
|
+
lines.push(theme.ui.muted('Use /tools to manage which tool suites are enabled.'));
|
|
3418
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3419
|
+
}
|
|
3420
|
+
handleInitCommand() {
|
|
3421
|
+
const lines = [];
|
|
3422
|
+
lines.push(theme.bold('Initialize Project'));
|
|
3423
|
+
lines.push('');
|
|
3424
|
+
lines.push('Create EROSOLAR.md to configure project-specific settings.');
|
|
3425
|
+
lines.push('');
|
|
3426
|
+
lines.push(theme.secondary('This will create:'));
|
|
3427
|
+
lines.push(` ${this.workingDir}/EROSOLAR.md`);
|
|
3428
|
+
lines.push('');
|
|
3429
|
+
lines.push(theme.secondary('Template includes:'));
|
|
3430
|
+
lines.push(' - Project description');
|
|
3431
|
+
lines.push(' - Coding standards');
|
|
3432
|
+
lines.push(' - File conventions');
|
|
3433
|
+
lines.push(' - Testing requirements');
|
|
3434
|
+
lines.push('');
|
|
3435
|
+
lines.push(theme.ui.muted('Use /init confirm to create the file.'));
|
|
3436
|
+
display.showSystemMessage(lines.join('\n'));
|
|
3437
|
+
}
|
|
3438
|
+
async handleCompactCommand() {
|
|
3439
|
+
if (this.isProcessing) {
|
|
3440
|
+
display.showWarning('Wait for the current operation to finish.');
|
|
3441
|
+
return;
|
|
3442
|
+
}
|
|
3443
|
+
display.showInfo('Compacting conversation context...');
|
|
3444
|
+
// Check if compaction is needed based on tracked usage
|
|
3445
|
+
const { used, limit } = this.latestTokenUsage;
|
|
3446
|
+
if (used && limit && used / limit < 0.5) {
|
|
3447
|
+
display.showInfo('Context usage is low. No compaction needed.');
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
await this.processRequest('Please summarize our conversation so far in a concise way, preserving key decisions, code changes, and next steps. This will help compact the context.');
|
|
3451
|
+
}
|
|
3452
|
+
// ==================== End Claude Code Style Commands ====================
|
|
1959
3453
|
updateActiveSession(summary, remember = false) {
|
|
1960
3454
|
this.activeSessionId = summary?.id ?? null;
|
|
1961
3455
|
this.activeSessionTitle = summary?.title ?? null;
|
|
@@ -2631,6 +4125,14 @@ export class InteractiveShell {
|
|
|
2631
4125
|
// Keep the persistent input/control bar active as we transition into streaming.
|
|
2632
4126
|
this.terminalInput.forceRender();
|
|
2633
4127
|
const requestStartTime = Date.now(); // Alpha Zero 2 timing
|
|
4128
|
+
// Clear previous parallel agents and start fresh for new request
|
|
4129
|
+
const parallelManager = getParallelAgentManager();
|
|
4130
|
+
parallelManager.clear();
|
|
4131
|
+
parallelManager.startBatch();
|
|
4132
|
+
// AlphaZero: Track task for learning
|
|
4133
|
+
this.lastUserQuery = request;
|
|
4134
|
+
this.currentTaskType = classifyTaskType(request);
|
|
4135
|
+
this.currentToolCalls = [];
|
|
2634
4136
|
this.uiAdapter.startProcessing('Working on your request');
|
|
2635
4137
|
this.setProcessingStatus();
|
|
2636
4138
|
let responseText = '';
|
|
@@ -2647,6 +4149,43 @@ export class InteractiveShell {
|
|
|
2647
4149
|
if (!responseText?.trim()) {
|
|
2648
4150
|
display.showWarning('The provider returned an empty response. Check your API key/provider selection or retry the prompt.');
|
|
2649
4151
|
}
|
|
4152
|
+
// AlphaZero: Extract and track tool calls from response
|
|
4153
|
+
const toolsUsed = this.extractToolsFromResponse(responseText);
|
|
4154
|
+
this.currentToolCalls = toolsUsed.map(name => ({
|
|
4155
|
+
name,
|
|
4156
|
+
arguments: {},
|
|
4157
|
+
success: true, // Assume success if we got here
|
|
4158
|
+
duration: 0,
|
|
4159
|
+
}));
|
|
4160
|
+
// AlphaZero: Check for failure in response
|
|
4161
|
+
const failure = detectFailure(responseText, {
|
|
4162
|
+
toolCalls: this.currentToolCalls,
|
|
4163
|
+
userMessage: request,
|
|
4164
|
+
});
|
|
4165
|
+
if (failure) {
|
|
4166
|
+
this.lastFailure = failure;
|
|
4167
|
+
// Check if we have a recovery strategy
|
|
4168
|
+
const strategy = findRecoveryStrategy(failure);
|
|
4169
|
+
if (strategy) {
|
|
4170
|
+
display.showSystemMessage(`🔄 Found recovery strategy for this type of issue (success rate: ${Math.round(strategy.successRate * 100)}%)`);
|
|
4171
|
+
}
|
|
4172
|
+
}
|
|
4173
|
+
else {
|
|
4174
|
+
// Success - record the tool pattern for this task type
|
|
4175
|
+
if (this.currentToolCalls.length > 0) {
|
|
4176
|
+
const toolPattern = {
|
|
4177
|
+
taskType: this.currentTaskType,
|
|
4178
|
+
toolSequence: this.currentToolCalls.map(t => t.name),
|
|
4179
|
+
successRate: 1.0,
|
|
4180
|
+
avgDuration: elapsedMs,
|
|
4181
|
+
occurrences: 1,
|
|
4182
|
+
};
|
|
4183
|
+
addToolPattern(this.currentTaskType, toolPattern);
|
|
4184
|
+
}
|
|
4185
|
+
// Clear action history on success
|
|
4186
|
+
clearActionHistory();
|
|
4187
|
+
this.lastFailure = null;
|
|
4188
|
+
}
|
|
2650
4189
|
}
|
|
2651
4190
|
catch (error) {
|
|
2652
4191
|
const handled = this.handleProviderError(error, () => this.processRequest(request));
|
|
@@ -2704,6 +4243,10 @@ export class InteractiveShell {
|
|
|
2704
4243
|
this.uiUpdates.setMode('processing');
|
|
2705
4244
|
this.terminalInput.setStreaming(true);
|
|
2706
4245
|
const overallStartTime = Date.now();
|
|
4246
|
+
// Clear previous parallel agents and start fresh for continuous mode
|
|
4247
|
+
const parallelManager = getParallelAgentManager();
|
|
4248
|
+
parallelManager.clear();
|
|
4249
|
+
parallelManager.startBatch();
|
|
2707
4250
|
// Initialize the task completion detector
|
|
2708
4251
|
const completionDetector = getTaskCompletionDetector();
|
|
2709
4252
|
completionDetector.reset();
|