erosolar-cli 1.7.405 ā 1.7.407
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/core/contextManager.d.ts +20 -0
- package/dist/core/contextManager.d.ts.map +1 -1
- package/dist/core/contextManager.js +69 -5
- package/dist/core/contextManager.js.map +1 -1
- package/dist/core/contextWindow.d.ts +4 -4
- package/dist/core/contextWindow.js +9 -9
- package/dist/core/contextWindow.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +3 -0
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +167 -22
- package/dist/shell/interactiveShell.js.map +1 -1
- package/dist/subagents/parallelAgentManager.d.ts.map +1 -1
- package/dist/subagents/parallelAgentManager.js +1 -2
- package/dist/subagents/parallelAgentManager.js.map +1 -1
- package/dist/tools/buildTools.d.ts.map +1 -1
- package/dist/tools/buildTools.js +19 -76
- package/dist/tools/buildTools.js.map +1 -1
- package/dist/tools/detectCommands.d.ts +8 -0
- package/dist/tools/detectCommands.d.ts.map +1 -0
- package/dist/tools/detectCommands.js +183 -0
- package/dist/tools/detectCommands.js.map +1 -0
- package/dist/ui/ShellUIAdapter.d.ts +10 -2
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +26 -14
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/theme.d.ts +100 -99
- package/dist/ui/theme.d.ts.map +1 -1
- package/dist/ui/theme.js.map +1 -1
- package/dist/ui/toolDisplay.d.ts +3 -3
- package/dist/ui/toolDisplay.d.ts.map +1 -1
- package/dist/ui/toolDisplay.js +5 -6
- package/dist/ui/toolDisplay.js.map +1 -1
- package/package.json +1 -1
|
@@ -5,7 +5,7 @@ import { createInterface } from 'node:readline/promises';
|
|
|
5
5
|
import { AssistantBlockRenderer } from '../ui/assistantBlockRenderer.js';
|
|
6
6
|
import { display } from '../ui/display.js';
|
|
7
7
|
import { compactRenderer } from '../ui/compactRenderer.js';
|
|
8
|
-
import { theme } from '../ui/theme.js';
|
|
8
|
+
import { theme, icons } from '../ui/theme.js';
|
|
9
9
|
import { getContextWindowTokens } from '../core/contextWindow.js';
|
|
10
10
|
import { ensureSecretForProvider, getSecretDefinitionForProvider, getSecretValue, listSecretDefinitions, MissingSecretError, maskSecret, setSecretValue, } from '../core/secretStore.js';
|
|
11
11
|
import { saveActiveProfilePreference, saveModelPreference, loadToolSettings, saveToolSettings, clearToolSettings, clearActiveProfilePreference, loadSessionPreferences, saveSessionPreferences, loadFeatureFlags, saveFeatureFlags, toggleFeatureFlag, FEATURE_FLAG_INFO, } from '../core/preferences.js';
|
|
@@ -43,6 +43,7 @@ import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js'
|
|
|
43
43
|
import { setGlobalAIEnhancer } from '../tools/localExplore.js';
|
|
44
44
|
import { createProvider } from '../providers/providerFactory.js';
|
|
45
45
|
import { getParallelAgentManager } from '../subagents/parallelAgentManager.js';
|
|
46
|
+
import { formatThinkingContent } from '../ui/textHighlighter.js';
|
|
46
47
|
const execAsync = promisify(exec);
|
|
47
48
|
const DROPDOWN_COLORS = [
|
|
48
49
|
theme.primary,
|
|
@@ -147,6 +148,7 @@ export class InteractiveShell {
|
|
|
147
148
|
customCommandMap;
|
|
148
149
|
sessionRestoreConfig;
|
|
149
150
|
_enabledPlugins;
|
|
151
|
+
autoVerificationInFlight = false;
|
|
150
152
|
// Auto-test tracking
|
|
151
153
|
autoTestInFlight = false;
|
|
152
154
|
// AlphaZero learning tracking
|
|
@@ -254,6 +256,11 @@ export class InteractiveShell {
|
|
|
254
256
|
description: 'Show available and loaded plugins',
|
|
255
257
|
category: 'configuration',
|
|
256
258
|
});
|
|
259
|
+
this.slashCommands.push({
|
|
260
|
+
command: '/contextlog',
|
|
261
|
+
description: 'Show recent context compaction summaries',
|
|
262
|
+
category: 'context',
|
|
263
|
+
});
|
|
257
264
|
this.slashCommands.push({
|
|
258
265
|
command: '/offsec',
|
|
259
266
|
description: 'AlphaZero offensive security run (start/status/next)',
|
|
@@ -1374,13 +1381,14 @@ export class InteractiveShell {
|
|
|
1374
1381
|
return;
|
|
1375
1382
|
}
|
|
1376
1383
|
this.assistantStreamActive = true;
|
|
1377
|
-
|
|
1384
|
+
// Default to thought phase so the first output after a prompt is the assistant's thinking.
|
|
1385
|
+
this.assistantStreamPhase = 'thought';
|
|
1378
1386
|
this.assistantStreamHeaderShown = false;
|
|
1379
1387
|
this.assistantStreamBuffer = '';
|
|
1380
1388
|
this.assistantStreamMetadata = metadata;
|
|
1381
1389
|
this.assistantStreamHadContent = false;
|
|
1382
1390
|
}
|
|
1383
|
-
streamAssistantChunk(chunk,
|
|
1391
|
+
streamAssistantChunk(chunk, channel) {
|
|
1384
1392
|
if (!chunk) {
|
|
1385
1393
|
return;
|
|
1386
1394
|
}
|
|
@@ -1389,6 +1397,9 @@ export class InteractiveShell {
|
|
|
1389
1397
|
contextWindowTokens: this.activeContextWindowTokens,
|
|
1390
1398
|
});
|
|
1391
1399
|
}
|
|
1400
|
+
// Route chunks based on channel for proper phase tracking
|
|
1401
|
+
// The agent sends 'thought' channel for reasoning chunks already wrapped in <thinking> tags
|
|
1402
|
+
// The tag parsing in processAssistantStreamChunk will handle phase transitions
|
|
1392
1403
|
this.processAssistantStreamChunk(chunk);
|
|
1393
1404
|
}
|
|
1394
1405
|
finalizeAssistantStream() {
|
|
@@ -1445,13 +1456,17 @@ export class InteractiveShell {
|
|
|
1445
1456
|
if (content.trim().length > 0) {
|
|
1446
1457
|
this.assistantStreamHadContent = true;
|
|
1447
1458
|
}
|
|
1448
|
-
|
|
1449
|
-
|
|
1450
|
-
|
|
1459
|
+
// If no explicit phase has been set yet, keep the stream labeled as "thought"
|
|
1460
|
+
// until a <response> tag arrives so operators see thinking first.
|
|
1461
|
+
this.setAssistantStreamPhase(this.assistantStreamPhase ?? 'thought');
|
|
1451
1462
|
if (this.assistantStreamPhase) {
|
|
1452
1463
|
this.renderAssistantStreamHeader(this.assistantStreamPhase);
|
|
1453
1464
|
}
|
|
1454
|
-
|
|
1465
|
+
let output = content;
|
|
1466
|
+
if (this.assistantStreamPhase === 'thought') {
|
|
1467
|
+
output = this.formatThoughtDisplay(content, { streaming: true });
|
|
1468
|
+
}
|
|
1469
|
+
this.enqueueAssistantStream(output);
|
|
1455
1470
|
}
|
|
1456
1471
|
setAssistantStreamPhase(phase) {
|
|
1457
1472
|
if (this.assistantStreamPhase === phase) {
|
|
@@ -1530,11 +1545,12 @@ export class InteractiveShell {
|
|
|
1530
1545
|
if (!normalized) {
|
|
1531
1546
|
return;
|
|
1532
1547
|
}
|
|
1548
|
+
const formatted = type === 'thought' ? this.formatThoughtDisplay(normalized) : normalized;
|
|
1533
1549
|
if (this.assistantBlocksEnabled && this.assistantBlockRenderer) {
|
|
1534
|
-
this.renderAssistantBlock(type,
|
|
1550
|
+
this.renderAssistantBlock(type, formatted, metadata);
|
|
1535
1551
|
return;
|
|
1536
1552
|
}
|
|
1537
|
-
this.renderAssistantFallback(type,
|
|
1553
|
+
this.renderAssistantFallback(type, formatted, metadata);
|
|
1538
1554
|
}
|
|
1539
1555
|
renderAssistantFallback(type, content, metadata) {
|
|
1540
1556
|
const header = this.formatAssistantHeader(type, metadata);
|
|
@@ -1542,6 +1558,21 @@ export class InteractiveShell {
|
|
|
1542
1558
|
const block = `\n${header}\n${compact}\n\n`;
|
|
1543
1559
|
this.enqueueAssistantStream(block);
|
|
1544
1560
|
}
|
|
1561
|
+
formatThoughtDisplay(content, options = {}) {
|
|
1562
|
+
const normalized = content.replace(/\r\n/g, '\n');
|
|
1563
|
+
if (options.streaming) {
|
|
1564
|
+
return formatThinkingContent(normalized);
|
|
1565
|
+
}
|
|
1566
|
+
const lines = normalized.split('\n');
|
|
1567
|
+
return lines
|
|
1568
|
+
.map((line, index) => {
|
|
1569
|
+
const prefix = index === 0 ? theme.info(icons.action) : theme.ui.muted(icons.subaction);
|
|
1570
|
+
const trimmed = line.trim();
|
|
1571
|
+
const body = trimmed ? formatThinkingContent(trimmed) : '';
|
|
1572
|
+
return body ? `${prefix} ${body}` : `${prefix}`;
|
|
1573
|
+
})
|
|
1574
|
+
.join('\n');
|
|
1575
|
+
}
|
|
1545
1576
|
formatAssistantHeader(type, metadata) {
|
|
1546
1577
|
if (this.assistantBlocksEnabled && this.assistantBlockRenderer) {
|
|
1547
1578
|
return this.assistantBlockRenderer.formatHeader(type, metadata);
|
|
@@ -2241,6 +2272,9 @@ export class InteractiveShell {
|
|
|
2241
2272
|
case '/context':
|
|
2242
2273
|
await this.refreshWorkspaceContextCommand(input);
|
|
2243
2274
|
break;
|
|
2275
|
+
case '/contextlog':
|
|
2276
|
+
this.showContextSummaryLog(input);
|
|
2277
|
+
break;
|
|
2244
2278
|
case '/agents':
|
|
2245
2279
|
this.showAgentsMenu();
|
|
2246
2280
|
break;
|
|
@@ -2539,6 +2573,66 @@ export class InteractiveShell {
|
|
|
2539
2573
|
display.showWarning('Workspace snapshot refreshed, but the agent failed to rebuild. Run /doctor for details.');
|
|
2540
2574
|
}
|
|
2541
2575
|
}
|
|
2576
|
+
showContextSummaryLog(input) {
|
|
2577
|
+
const agent = this.agent;
|
|
2578
|
+
if (!agent) {
|
|
2579
|
+
display.showWarning('No active agent session. Start one to inspect context summaries.');
|
|
2580
|
+
return;
|
|
2581
|
+
}
|
|
2582
|
+
const contextManager = agent.getContextManager();
|
|
2583
|
+
if (!contextManager?.getSummaryLog) {
|
|
2584
|
+
display.showWarning('Context summary logging is unavailable in this session.');
|
|
2585
|
+
return;
|
|
2586
|
+
}
|
|
2587
|
+
const tokens = input.trim().split(/\s+/).slice(1);
|
|
2588
|
+
let limit = 5;
|
|
2589
|
+
for (const token of tokens) {
|
|
2590
|
+
if (!token)
|
|
2591
|
+
continue;
|
|
2592
|
+
const normalized = token.toLowerCase();
|
|
2593
|
+
if (/^\d+$/.test(token)) {
|
|
2594
|
+
limit = Math.min(Math.max(parseInt(token, 10), 1), 20);
|
|
2595
|
+
}
|
|
2596
|
+
else if (normalized.startsWith('limit=')) {
|
|
2597
|
+
const value = parseInt(normalized.split('=')[1] ?? '', 10);
|
|
2598
|
+
if (!Number.isNaN(value)) {
|
|
2599
|
+
limit = Math.min(Math.max(value, 1), 20);
|
|
2600
|
+
}
|
|
2601
|
+
}
|
|
2602
|
+
}
|
|
2603
|
+
const entries = contextManager.getSummaryLog(limit);
|
|
2604
|
+
if (!entries.length) {
|
|
2605
|
+
display.showInfo('No context summaries captured yet.');
|
|
2606
|
+
return;
|
|
2607
|
+
}
|
|
2608
|
+
const lines = [];
|
|
2609
|
+
lines.push(`${theme.primary('Context summaries')} ${theme.ui.muted(`(latest ${entries.length})`)}`);
|
|
2610
|
+
for (const entry of entries) {
|
|
2611
|
+
const timestamp = new Date(entry.timestamp).toLocaleString();
|
|
2612
|
+
const headerParts = [
|
|
2613
|
+
theme.ui.muted(timestamp),
|
|
2614
|
+
theme.info(entry.method),
|
|
2615
|
+
`removed ${theme.error(String(entry.removed))}`,
|
|
2616
|
+
`kept ${theme.success(String(entry.preserved))}`,
|
|
2617
|
+
];
|
|
2618
|
+
if (entry.reason) {
|
|
2619
|
+
headerParts.push(theme.ui.muted(entry.reason));
|
|
2620
|
+
}
|
|
2621
|
+
if (entry.model) {
|
|
2622
|
+
headerParts.push(theme.ui.muted(`model=${entry.model}`));
|
|
2623
|
+
}
|
|
2624
|
+
lines.push(headerParts.join(' Ā· '));
|
|
2625
|
+
if (entry.summary) {
|
|
2626
|
+
const trimmed = entry.summary.length > 600 ? `${entry.summary.slice(0, 600)}ā¦` : entry.summary;
|
|
2627
|
+
lines.push(trimmed);
|
|
2628
|
+
}
|
|
2629
|
+
else {
|
|
2630
|
+
lines.push(theme.ui.muted('(no summary text ā simple prune)'));
|
|
2631
|
+
}
|
|
2632
|
+
lines.push(''); // spacer
|
|
2633
|
+
}
|
|
2634
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2635
|
+
}
|
|
2542
2636
|
parseContextOverrideTokens(input) {
|
|
2543
2637
|
const overrides = {};
|
|
2544
2638
|
let hasOverride = false;
|
|
@@ -5815,7 +5909,25 @@ What's the next action?`;
|
|
|
5815
5909
|
}
|
|
5816
5910
|
if (name === 'bash' || name === 'execute_bash') {
|
|
5817
5911
|
const command = String(entry.args['command'] ?? '').toLowerCase();
|
|
5818
|
-
|
|
5912
|
+
const patterns = [
|
|
5913
|
+
'npm test',
|
|
5914
|
+
'yarn test',
|
|
5915
|
+
'pnpm test',
|
|
5916
|
+
'bun test',
|
|
5917
|
+
'go test',
|
|
5918
|
+
'cargo test',
|
|
5919
|
+
'pytest',
|
|
5920
|
+
'python -m pytest',
|
|
5921
|
+
'tox',
|
|
5922
|
+
'mvn test',
|
|
5923
|
+
'./mvnw test',
|
|
5924
|
+
'gradle test',
|
|
5925
|
+
'./gradlew test',
|
|
5926
|
+
'dotnet test',
|
|
5927
|
+
'make test',
|
|
5928
|
+
'swift test',
|
|
5929
|
+
];
|
|
5930
|
+
return patterns.some((pattern) => command.includes(pattern));
|
|
5819
5931
|
}
|
|
5820
5932
|
return false;
|
|
5821
5933
|
}
|
|
@@ -5892,10 +6004,31 @@ What's the next action?`;
|
|
|
5892
6004
|
}
|
|
5893
6005
|
if (name === 'bash' || name === 'execute_bash') {
|
|
5894
6006
|
const command = String(entry.args['command'] ?? '').toLowerCase();
|
|
5895
|
-
|
|
5896
|
-
|
|
5897
|
-
|
|
5898
|
-
|
|
6007
|
+
const makeBuild = command.startsWith('make') && !command.includes('make test') && !command.includes('make lint');
|
|
6008
|
+
const patterns = [
|
|
6009
|
+
'npm run build',
|
|
6010
|
+
'yarn build',
|
|
6011
|
+
'pnpm build',
|
|
6012
|
+
'bun run build',
|
|
6013
|
+
'bun build',
|
|
6014
|
+
'tsc',
|
|
6015
|
+
'cargo build',
|
|
6016
|
+
'go build',
|
|
6017
|
+
'python -m build',
|
|
6018
|
+
'mvn -b -dskiptests package',
|
|
6019
|
+
'mvn package',
|
|
6020
|
+
'mvn install',
|
|
6021
|
+
'./mvnw -b -dskiptests package',
|
|
6022
|
+
'./mvnw package',
|
|
6023
|
+
'./mvnw install',
|
|
6024
|
+
'gradle build',
|
|
6025
|
+
'gradle assemble',
|
|
6026
|
+
'./gradlew build',
|
|
6027
|
+
'./gradlew assemble',
|
|
6028
|
+
'dotnet build',
|
|
6029
|
+
'swift build',
|
|
6030
|
+
];
|
|
6031
|
+
return makeBuild || patterns.some((pattern) => command.includes(pattern));
|
|
5899
6032
|
}
|
|
5900
6033
|
return false;
|
|
5901
6034
|
}
|
|
@@ -6083,8 +6216,8 @@ What's the next action?`;
|
|
|
6083
6216
|
this.requestPromptRefresh();
|
|
6084
6217
|
},
|
|
6085
6218
|
onContextSquishing: (message) => {
|
|
6086
|
-
//
|
|
6087
|
-
display.
|
|
6219
|
+
// Stream notification in UI when auto context squishing occurs
|
|
6220
|
+
display.stream(`\nš ${message}\n`);
|
|
6088
6221
|
this.statusTracker.pushOverride('context-squish', 'Auto-squishing context', {
|
|
6089
6222
|
detail: 'Reducing conversation history to fit within token limits',
|
|
6090
6223
|
tone: 'warning',
|
|
@@ -6092,7 +6225,7 @@ What's the next action?`;
|
|
|
6092
6225
|
},
|
|
6093
6226
|
onContextRecovery: (attempt, maxAttempts, message) => {
|
|
6094
6227
|
// Show recovery progress in UI
|
|
6095
|
-
display.
|
|
6228
|
+
display.stream(`\nā” Context Recovery (${attempt}/${maxAttempts}): ${message}\n`);
|
|
6096
6229
|
},
|
|
6097
6230
|
onContextPruned: (removedCount, stats) => {
|
|
6098
6231
|
// Clear squish overlay if active
|
|
@@ -6100,19 +6233,23 @@ What's the next action?`;
|
|
|
6100
6233
|
// Show notification that context was pruned
|
|
6101
6234
|
const method = stats['method'];
|
|
6102
6235
|
const percentage = stats['percentage'];
|
|
6236
|
+
const summarized = stats['summarized'] === true;
|
|
6103
6237
|
if (method === 'emergency-recovery') {
|
|
6104
|
-
display.
|
|
6238
|
+
display.stream(`\nā
Context recovery complete. Removed ${removedCount} messages. Context now at ${percentage ?? 'unknown'}%\n`);
|
|
6105
6239
|
}
|
|
6106
6240
|
// Update context usage in UI
|
|
6107
6241
|
if (typeof percentage === 'number') {
|
|
6108
6242
|
this.updateContextUsage(percentage);
|
|
6109
6243
|
}
|
|
6244
|
+
if (summarized) {
|
|
6245
|
+
display.showSystemMessage('Context summary captured. View the latest summaries with /contextlog.');
|
|
6246
|
+
}
|
|
6110
6247
|
// Ensure prompt remains visible at bottom after context messages
|
|
6111
6248
|
this.renderPromptArea();
|
|
6112
6249
|
},
|
|
6113
6250
|
onContinueAfterRecovery: () => {
|
|
6114
6251
|
// Update UI to show we're continuing after context recovery
|
|
6115
|
-
display.
|
|
6252
|
+
display.stream(`\nš Continuing after context recovery...\n`);
|
|
6116
6253
|
this.updateStatusMessage('Retrying with reduced context...');
|
|
6117
6254
|
this.renderPromptArea();
|
|
6118
6255
|
},
|
|
@@ -6244,8 +6381,8 @@ What's the next action?`;
|
|
|
6244
6381
|
].join('\n');
|
|
6245
6382
|
case 'balanced':
|
|
6246
6383
|
default:
|
|
6247
|
-
// Balanced
|
|
6248
|
-
return
|
|
6384
|
+
// Balanced mode: show thinking for complex reasoning, planning, or multi-step tasks
|
|
6385
|
+
return 'When reasoning through complex tasks, planning approaches, or making decisions, wrap your thought process in <thinking> tags before your response. Keep thinking concise and focused on the decision-making process.';
|
|
6249
6386
|
}
|
|
6250
6387
|
}
|
|
6251
6388
|
buildDisplayMetadata(metadata) {
|
|
@@ -6279,10 +6416,18 @@ What's the next action?`;
|
|
|
6279
6416
|
if (!operations.length) {
|
|
6280
6417
|
return;
|
|
6281
6418
|
}
|
|
6282
|
-
|
|
6419
|
+
let summaryLine = compactRenderer.formatCompactLine(operations, {
|
|
6283
6420
|
showIcons: true,
|
|
6284
6421
|
showTimings: true,
|
|
6285
6422
|
});
|
|
6423
|
+
const warnings = this.uiAdapter.getRecentWarnings(since);
|
|
6424
|
+
if (warnings.length) {
|
|
6425
|
+
const limited = warnings.slice(0, 3);
|
|
6426
|
+
const formattedWarnings = limited
|
|
6427
|
+
.map((warning) => `${icons.warning} ${warning.tool}: ${warning.text}`)
|
|
6428
|
+
.join(' ⢠');
|
|
6429
|
+
summaryLine = `${summaryLine} ${theme.warning('[warnings]')} ${formattedWarnings}`;
|
|
6430
|
+
}
|
|
6286
6431
|
if (!summaryLine.trim()) {
|
|
6287
6432
|
this.lastToolSummaryRenderedAt = Date.now();
|
|
6288
6433
|
return;
|