erosolar-cli 1.7.406 → 1.7.408
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 +64 -0
- package/dist/core/contextManager.js.map +1 -1
- package/dist/shell/interactiveShell.d.ts +5 -1
- package/dist/shell/interactiveShell.d.ts.map +1 -1
- package/dist/shell/interactiveShell.js +212 -38
- 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 +2 -2
- package/dist/ui/ShellUIAdapter.d.ts.map +1 -1
- package/dist/ui/ShellUIAdapter.js +11 -13
- package/dist/ui/ShellUIAdapter.js.map +1 -1
- package/dist/ui/shortcutsHelp.d.ts +1 -1
- package/dist/ui/shortcutsHelp.js +2 -2
- package/dist/ui/shortcutsHelp.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 +7 -8
- package/dist/ui/toolDisplay.js.map +1 -1
- package/package.json +1 -1
|
@@ -13,6 +13,7 @@ import { getLearningSummary, getRecentLearning, commitLearning, exportAllLearnin
|
|
|
13
13
|
import { buildEnabledToolSet, evaluateToolPermissions, getToolToggleOptions, } from '../capabilities/toolRegistry.js';
|
|
14
14
|
import { detectApiKeyError } from '../core/errors/apiKeyErrors.js';
|
|
15
15
|
import { buildWorkspaceContext } from '../workspace.js';
|
|
16
|
+
import { detectBuildCommand, detectTestCommand } from '../tools/detectCommands.js';
|
|
16
17
|
import { buildInteractiveSystemPrompt } from './systemPrompt.js';
|
|
17
18
|
import { getTaskCompletionDetector, resetTaskCompletionDetector, } from './taskCompletionDetector.js';
|
|
18
19
|
import { discoverAllModels, quickCheckProviders, getCachedDiscoveredModels, sortModelsByPriority } from '../core/modelDiscovery.js';
|
|
@@ -43,6 +44,7 @@ import { enterStreamingMode, exitStreamingMode } from '../ui/globalWriteLock.js'
|
|
|
43
44
|
import { setGlobalAIEnhancer } from '../tools/localExplore.js';
|
|
44
45
|
import { createProvider } from '../providers/providerFactory.js';
|
|
45
46
|
import { getParallelAgentManager } from '../subagents/parallelAgentManager.js';
|
|
47
|
+
import { formatThinkingContent } from '../ui/textHighlighter.js';
|
|
46
48
|
const execAsync = promisify(exec);
|
|
47
49
|
const DROPDOWN_COLORS = [
|
|
48
50
|
theme.primary,
|
|
@@ -147,6 +149,7 @@ export class InteractiveShell {
|
|
|
147
149
|
customCommandMap;
|
|
148
150
|
sessionRestoreConfig;
|
|
149
151
|
_enabledPlugins;
|
|
152
|
+
autoVerificationInFlight = false;
|
|
150
153
|
// Auto-test tracking
|
|
151
154
|
autoTestInFlight = false;
|
|
152
155
|
// AlphaZero learning tracking
|
|
@@ -254,6 +257,11 @@ export class InteractiveShell {
|
|
|
254
257
|
description: 'Show available and loaded plugins',
|
|
255
258
|
category: 'configuration',
|
|
256
259
|
});
|
|
260
|
+
this.slashCommands.push({
|
|
261
|
+
command: '/contextlog',
|
|
262
|
+
description: 'Show recent context compaction summaries',
|
|
263
|
+
category: 'context',
|
|
264
|
+
});
|
|
257
265
|
this.slashCommands.push({
|
|
258
266
|
command: '/offsec',
|
|
259
267
|
description: 'AlphaZero offensive security run (start/status/next)',
|
|
@@ -1430,7 +1438,9 @@ export class InteractiveShell {
|
|
|
1430
1438
|
// Advance buffer past the tag
|
|
1431
1439
|
this.assistantStreamBuffer = this.assistantStreamBuffer.slice(tagIndex + match[0].length);
|
|
1432
1440
|
const isClosing = match[1] === '/';
|
|
1433
|
-
const
|
|
1441
|
+
const rawTagType = (match[2] ?? '').toLowerCase();
|
|
1442
|
+
// Map 'thinking' to 'thought' for AssistantBlockType compatibility
|
|
1443
|
+
const tagType = (rawTagType === 'thinking' ? 'thought' : rawTagType);
|
|
1434
1444
|
if (isClosing) {
|
|
1435
1445
|
if (this.assistantStreamPhase === tagType) {
|
|
1436
1446
|
this.assistantStreamPhase = null;
|
|
@@ -1455,7 +1465,11 @@ export class InteractiveShell {
|
|
|
1455
1465
|
if (this.assistantStreamPhase) {
|
|
1456
1466
|
this.renderAssistantStreamHeader(this.assistantStreamPhase);
|
|
1457
1467
|
}
|
|
1458
|
-
|
|
1468
|
+
let output = content;
|
|
1469
|
+
if (this.assistantStreamPhase === 'thought') {
|
|
1470
|
+
output = this.formatThoughtDisplay(content, { streaming: true });
|
|
1471
|
+
}
|
|
1472
|
+
this.enqueueAssistantStream(output);
|
|
1459
1473
|
}
|
|
1460
1474
|
setAssistantStreamPhase(phase) {
|
|
1461
1475
|
if (this.assistantStreamPhase === phase) {
|
|
@@ -1534,11 +1548,12 @@ export class InteractiveShell {
|
|
|
1534
1548
|
if (!normalized) {
|
|
1535
1549
|
return;
|
|
1536
1550
|
}
|
|
1551
|
+
const formatted = type === 'thought' ? this.formatThoughtDisplay(normalized) : normalized;
|
|
1537
1552
|
if (this.assistantBlocksEnabled && this.assistantBlockRenderer) {
|
|
1538
|
-
this.renderAssistantBlock(type,
|
|
1553
|
+
this.renderAssistantBlock(type, formatted, metadata);
|
|
1539
1554
|
return;
|
|
1540
1555
|
}
|
|
1541
|
-
this.renderAssistantFallback(type,
|
|
1556
|
+
this.renderAssistantFallback(type, formatted, metadata);
|
|
1542
1557
|
}
|
|
1543
1558
|
renderAssistantFallback(type, content, metadata) {
|
|
1544
1559
|
const header = this.formatAssistantHeader(type, metadata);
|
|
@@ -1546,6 +1561,21 @@ export class InteractiveShell {
|
|
|
1546
1561
|
const block = `\n${header}\n${compact}\n\n`;
|
|
1547
1562
|
this.enqueueAssistantStream(block);
|
|
1548
1563
|
}
|
|
1564
|
+
formatThoughtDisplay(content, options = {}) {
|
|
1565
|
+
const normalized = content.replace(/\r\n/g, '\n');
|
|
1566
|
+
if (options.streaming) {
|
|
1567
|
+
return formatThinkingContent(normalized);
|
|
1568
|
+
}
|
|
1569
|
+
const lines = normalized.split('\n');
|
|
1570
|
+
return lines
|
|
1571
|
+
.map((line, index) => {
|
|
1572
|
+
const prefix = index === 0 ? theme.info(icons.action) : theme.ui.muted(icons.subaction);
|
|
1573
|
+
const trimmed = line.trim();
|
|
1574
|
+
const body = trimmed ? formatThinkingContent(trimmed) : '';
|
|
1575
|
+
return body ? `${prefix} ${body}` : `${prefix}`;
|
|
1576
|
+
})
|
|
1577
|
+
.join('\n');
|
|
1578
|
+
}
|
|
1549
1579
|
formatAssistantHeader(type, metadata) {
|
|
1550
1580
|
if (this.assistantBlocksEnabled && this.assistantBlockRenderer) {
|
|
1551
1581
|
return this.assistantBlockRenderer.formatHeader(type, metadata);
|
|
@@ -2245,6 +2275,9 @@ export class InteractiveShell {
|
|
|
2245
2275
|
case '/context':
|
|
2246
2276
|
await this.refreshWorkspaceContextCommand(input);
|
|
2247
2277
|
break;
|
|
2278
|
+
case '/contextlog':
|
|
2279
|
+
this.showContextSummaryLog(input);
|
|
2280
|
+
break;
|
|
2248
2281
|
case '/agents':
|
|
2249
2282
|
this.showAgentsMenu();
|
|
2250
2283
|
break;
|
|
@@ -2543,6 +2576,66 @@ export class InteractiveShell {
|
|
|
2543
2576
|
display.showWarning('Workspace snapshot refreshed, but the agent failed to rebuild. Run /doctor for details.');
|
|
2544
2577
|
}
|
|
2545
2578
|
}
|
|
2579
|
+
showContextSummaryLog(input) {
|
|
2580
|
+
const agent = this.agent;
|
|
2581
|
+
if (!agent) {
|
|
2582
|
+
display.showWarning('No active agent session. Start one to inspect context summaries.');
|
|
2583
|
+
return;
|
|
2584
|
+
}
|
|
2585
|
+
const contextManager = agent.getContextManager();
|
|
2586
|
+
if (!contextManager?.getSummaryLog) {
|
|
2587
|
+
display.showWarning('Context summary logging is unavailable in this session.');
|
|
2588
|
+
return;
|
|
2589
|
+
}
|
|
2590
|
+
const tokens = input.trim().split(/\s+/).slice(1);
|
|
2591
|
+
let limit = 5;
|
|
2592
|
+
for (const token of tokens) {
|
|
2593
|
+
if (!token)
|
|
2594
|
+
continue;
|
|
2595
|
+
const normalized = token.toLowerCase();
|
|
2596
|
+
if (/^\d+$/.test(token)) {
|
|
2597
|
+
limit = Math.min(Math.max(parseInt(token, 10), 1), 20);
|
|
2598
|
+
}
|
|
2599
|
+
else if (normalized.startsWith('limit=')) {
|
|
2600
|
+
const value = parseInt(normalized.split('=')[1] ?? '', 10);
|
|
2601
|
+
if (!Number.isNaN(value)) {
|
|
2602
|
+
limit = Math.min(Math.max(value, 1), 20);
|
|
2603
|
+
}
|
|
2604
|
+
}
|
|
2605
|
+
}
|
|
2606
|
+
const entries = contextManager.getSummaryLog(limit);
|
|
2607
|
+
if (!entries.length) {
|
|
2608
|
+
display.showInfo('No context summaries captured yet.');
|
|
2609
|
+
return;
|
|
2610
|
+
}
|
|
2611
|
+
const lines = [];
|
|
2612
|
+
lines.push(`${theme.primary('Context summaries')} ${theme.ui.muted(`(latest ${entries.length})`)}`);
|
|
2613
|
+
for (const entry of entries) {
|
|
2614
|
+
const timestamp = new Date(entry.timestamp).toLocaleString();
|
|
2615
|
+
const headerParts = [
|
|
2616
|
+
theme.ui.muted(timestamp),
|
|
2617
|
+
theme.info(entry.method),
|
|
2618
|
+
`removed ${theme.error(String(entry.removed))}`,
|
|
2619
|
+
`kept ${theme.success(String(entry.preserved))}`,
|
|
2620
|
+
];
|
|
2621
|
+
if (entry.reason) {
|
|
2622
|
+
headerParts.push(theme.ui.muted(entry.reason));
|
|
2623
|
+
}
|
|
2624
|
+
if (entry.model) {
|
|
2625
|
+
headerParts.push(theme.ui.muted(`model=${entry.model}`));
|
|
2626
|
+
}
|
|
2627
|
+
lines.push(headerParts.join(' · '));
|
|
2628
|
+
if (entry.summary) {
|
|
2629
|
+
const trimmed = entry.summary.length > 600 ? `${entry.summary.slice(0, 600)}…` : entry.summary;
|
|
2630
|
+
lines.push(trimmed);
|
|
2631
|
+
}
|
|
2632
|
+
else {
|
|
2633
|
+
lines.push(theme.ui.muted('(no summary text — simple prune)'));
|
|
2634
|
+
}
|
|
2635
|
+
lines.push(''); // spacer
|
|
2636
|
+
}
|
|
2637
|
+
display.showSystemMessage(lines.join('\n'));
|
|
2638
|
+
}
|
|
2546
2639
|
parseContextOverrideTokens(input) {
|
|
2547
2640
|
const overrides = {};
|
|
2548
2641
|
let hasOverride = false;
|
|
@@ -5819,7 +5912,25 @@ What's the next action?`;
|
|
|
5819
5912
|
}
|
|
5820
5913
|
if (name === 'bash' || name === 'execute_bash') {
|
|
5821
5914
|
const command = String(entry.args['command'] ?? '').toLowerCase();
|
|
5822
|
-
|
|
5915
|
+
const patterns = [
|
|
5916
|
+
'npm test',
|
|
5917
|
+
'yarn test',
|
|
5918
|
+
'pnpm test',
|
|
5919
|
+
'bun test',
|
|
5920
|
+
'go test',
|
|
5921
|
+
'cargo test',
|
|
5922
|
+
'pytest',
|
|
5923
|
+
'python -m pytest',
|
|
5924
|
+
'tox',
|
|
5925
|
+
'mvn test',
|
|
5926
|
+
'./mvnw test',
|
|
5927
|
+
'gradle test',
|
|
5928
|
+
'./gradlew test',
|
|
5929
|
+
'dotnet test',
|
|
5930
|
+
'make test',
|
|
5931
|
+
'swift test',
|
|
5932
|
+
];
|
|
5933
|
+
return patterns.some((pattern) => command.includes(pattern));
|
|
5823
5934
|
}
|
|
5824
5935
|
return false;
|
|
5825
5936
|
}
|
|
@@ -5837,24 +5948,28 @@ What's the next action?`;
|
|
|
5837
5948
|
const parts = [error?.stdout, error?.stderr, error?.message].filter((part) => typeof part === 'string' && part.trim());
|
|
5838
5949
|
return parts.join('\n').trim();
|
|
5839
5950
|
}
|
|
5840
|
-
async enforceAutoTests(trigger) {
|
|
5841
|
-
if (this.autoTestInFlight) {
|
|
5842
|
-
return;
|
|
5843
|
-
}
|
|
5844
|
-
if (!this.verificationEnabled) {
|
|
5845
|
-
return;
|
|
5951
|
+
async enforceAutoTests(trigger, commandInfo) {
|
|
5952
|
+
if (this.autoTestInFlight || !this.verificationEnabled) {
|
|
5953
|
+
return 'skipped';
|
|
5846
5954
|
}
|
|
5847
5955
|
const latestChange = this.getLatestFileChangeTimestamp();
|
|
5848
5956
|
if (!latestChange) {
|
|
5849
|
-
return;
|
|
5957
|
+
return 'skipped';
|
|
5850
5958
|
}
|
|
5851
5959
|
const latestTest = this.getLatestTestTimestamp();
|
|
5852
5960
|
if (latestTest && latestChange <= latestTest) {
|
|
5853
|
-
return;
|
|
5961
|
+
return 'skipped';
|
|
5962
|
+
}
|
|
5963
|
+
const detected = commandInfo ?? detectTestCommand(this.workingDir);
|
|
5964
|
+
if (!detected) {
|
|
5965
|
+
this.lastAutoTestRun = Date.now();
|
|
5966
|
+
display.showSystemMessage('ℹ️ Skipping auto-tests: no test command detected for this repo.');
|
|
5967
|
+
return 'skipped';
|
|
5854
5968
|
}
|
|
5855
5969
|
this.autoTestInFlight = true;
|
|
5856
|
-
const command =
|
|
5857
|
-
|
|
5970
|
+
const command = detected.command;
|
|
5971
|
+
const reasonSuffix = detected.reason ? ` [${detected.reason}]` : '';
|
|
5972
|
+
display.showSystemMessage(`🧪 Auto-testing recent changes (${trigger}) with "${command}"${reasonSuffix}...`);
|
|
5858
5973
|
this.updateStatusMessage('Running tests automatically...');
|
|
5859
5974
|
try {
|
|
5860
5975
|
const { stdout, stderr } = await execAsync(command, {
|
|
@@ -5869,6 +5984,7 @@ What's the next action?`;
|
|
|
5869
5984
|
this.writeLocked(`${outputText}\n`);
|
|
5870
5985
|
}
|
|
5871
5986
|
this.statusTracker.clearOverride('tests');
|
|
5987
|
+
return 'success';
|
|
5872
5988
|
}
|
|
5873
5989
|
catch (error) {
|
|
5874
5990
|
this.lastAutoTestRun = Date.now();
|
|
@@ -5878,9 +5994,10 @@ What's the next action?`;
|
|
|
5878
5994
|
this.writeLocked(`${message}\n`);
|
|
5879
5995
|
}
|
|
5880
5996
|
this.statusTracker.pushOverride('tests', 'Tests failing', {
|
|
5881
|
-
detail:
|
|
5997
|
+
detail: `Auto-run ${command} failed`,
|
|
5882
5998
|
tone: 'danger',
|
|
5883
5999
|
});
|
|
6000
|
+
return 'failed';
|
|
5884
6001
|
}
|
|
5885
6002
|
finally {
|
|
5886
6003
|
this.updateStatusMessage(null);
|
|
@@ -5896,10 +6013,31 @@ What's the next action?`;
|
|
|
5896
6013
|
}
|
|
5897
6014
|
if (name === 'bash' || name === 'execute_bash') {
|
|
5898
6015
|
const command = String(entry.args['command'] ?? '').toLowerCase();
|
|
5899
|
-
|
|
5900
|
-
|
|
5901
|
-
|
|
5902
|
-
|
|
6016
|
+
const makeBuild = command.startsWith('make') && !command.includes('make test') && !command.includes('make lint');
|
|
6017
|
+
const patterns = [
|
|
6018
|
+
'npm run build',
|
|
6019
|
+
'yarn build',
|
|
6020
|
+
'pnpm build',
|
|
6021
|
+
'bun run build',
|
|
6022
|
+
'bun build',
|
|
6023
|
+
'tsc',
|
|
6024
|
+
'cargo build',
|
|
6025
|
+
'go build',
|
|
6026
|
+
'python -m build',
|
|
6027
|
+
'mvn -b -dskiptests package',
|
|
6028
|
+
'mvn package',
|
|
6029
|
+
'mvn install',
|
|
6030
|
+
'./mvnw -b -dskiptests package',
|
|
6031
|
+
'./mvnw package',
|
|
6032
|
+
'./mvnw install',
|
|
6033
|
+
'gradle build',
|
|
6034
|
+
'gradle assemble',
|
|
6035
|
+
'./gradlew build',
|
|
6036
|
+
'./gradlew assemble',
|
|
6037
|
+
'dotnet build',
|
|
6038
|
+
'swift build',
|
|
6039
|
+
];
|
|
6040
|
+
return makeBuild || patterns.some((pattern) => command.includes(pattern));
|
|
5903
6041
|
}
|
|
5904
6042
|
return false;
|
|
5905
6043
|
}
|
|
@@ -5915,26 +6053,30 @@ What's the next action?`;
|
|
|
5915
6053
|
}
|
|
5916
6054
|
/**
|
|
5917
6055
|
* Auto-build verification after file edits.
|
|
5918
|
-
*
|
|
6056
|
+
* Detects the build command for the current repo and feeds failures back to the agent.
|
|
5919
6057
|
*/
|
|
5920
|
-
async enforceAutoBuild(trigger) {
|
|
5921
|
-
if (this.autoBuildInFlight) {
|
|
5922
|
-
return;
|
|
5923
|
-
}
|
|
5924
|
-
if (!this.verificationEnabled) {
|
|
5925
|
-
return;
|
|
6058
|
+
async enforceAutoBuild(trigger, commandInfo) {
|
|
6059
|
+
if (this.autoBuildInFlight || !this.verificationEnabled) {
|
|
6060
|
+
return 'skipped';
|
|
5926
6061
|
}
|
|
5927
6062
|
const latestChange = this.getLatestFileChangeTimestamp();
|
|
5928
6063
|
if (!latestChange) {
|
|
5929
|
-
return;
|
|
6064
|
+
return 'skipped';
|
|
5930
6065
|
}
|
|
5931
6066
|
const latestBuild = this.getLatestBuildTimestamp();
|
|
5932
6067
|
if (latestBuild && latestChange <= latestBuild) {
|
|
5933
|
-
return;
|
|
6068
|
+
return 'skipped';
|
|
6069
|
+
}
|
|
6070
|
+
const detected = commandInfo ?? detectBuildCommand(this.workingDir);
|
|
6071
|
+
if (!detected) {
|
|
6072
|
+
this.lastAutoBuildRun = Date.now();
|
|
6073
|
+
display.showSystemMessage('ℹ️ Skipping auto-build: no build command detected for this repo.');
|
|
6074
|
+
return 'skipped';
|
|
5934
6075
|
}
|
|
5935
6076
|
this.autoBuildInFlight = true;
|
|
5936
|
-
const command =
|
|
5937
|
-
|
|
6077
|
+
const command = detected.command;
|
|
6078
|
+
const reasonSuffix = detected.reason ? ` [${detected.reason}]` : '';
|
|
6079
|
+
display.showSystemMessage(`🔨 Auto-building to verify changes (${trigger}) with "${command}"${reasonSuffix}...`);
|
|
5938
6080
|
this.updateStatusMessage('Running build automatically...');
|
|
5939
6081
|
try {
|
|
5940
6082
|
const { stdout, stderr } = await execAsync(command, {
|
|
@@ -5949,6 +6091,7 @@ What's the next action?`;
|
|
|
5949
6091
|
this.writeLocked(`${outputText}\n`);
|
|
5950
6092
|
}
|
|
5951
6093
|
this.statusTracker.clearOverride('build');
|
|
6094
|
+
return 'success';
|
|
5952
6095
|
}
|
|
5953
6096
|
catch (error) {
|
|
5954
6097
|
this.lastAutoBuildRun = Date.now();
|
|
@@ -5958,11 +6101,12 @@ What's the next action?`;
|
|
|
5958
6101
|
this.writeLocked(`${errorOutput}\n`);
|
|
5959
6102
|
}
|
|
5960
6103
|
this.statusTracker.pushOverride('build', 'Build failing', {
|
|
5961
|
-
detail:
|
|
6104
|
+
detail: `Auto-run ${command} failed`,
|
|
5962
6105
|
tone: 'danger',
|
|
5963
6106
|
});
|
|
5964
6107
|
// Feed build errors back to the agent so it can fix them
|
|
5965
6108
|
await this.feedBuildErrorsToAgent(errorOutput);
|
|
6109
|
+
return 'failed';
|
|
5966
6110
|
}
|
|
5967
6111
|
finally {
|
|
5968
6112
|
this.updateStatusMessage(null);
|
|
@@ -6004,6 +6148,34 @@ What's the next action?`;
|
|
|
6004
6148
|
display.showWarning('Agent could not automatically fix build errors. Please review manually.');
|
|
6005
6149
|
}
|
|
6006
6150
|
}
|
|
6151
|
+
async enforceAutoVerification(trigger) {
|
|
6152
|
+
if (this.autoVerificationInFlight || !this.verificationEnabled) {
|
|
6153
|
+
return;
|
|
6154
|
+
}
|
|
6155
|
+
const latestChange = this.getLatestFileChangeTimestamp();
|
|
6156
|
+
if (!latestChange) {
|
|
6157
|
+
return;
|
|
6158
|
+
}
|
|
6159
|
+
this.autoVerificationInFlight = true;
|
|
6160
|
+
try {
|
|
6161
|
+
const buildInfo = detectBuildCommand(this.workingDir);
|
|
6162
|
+
const testInfo = detectTestCommand(this.workingDir);
|
|
6163
|
+
const buildResult = await this.enforceAutoBuild(trigger, buildInfo);
|
|
6164
|
+
if (buildResult === 'failed') {
|
|
6165
|
+
return;
|
|
6166
|
+
}
|
|
6167
|
+
if (testInfo) {
|
|
6168
|
+
await this.enforceAutoTests(trigger, testInfo);
|
|
6169
|
+
}
|
|
6170
|
+
else {
|
|
6171
|
+
this.lastAutoTestRun = Date.now();
|
|
6172
|
+
display.showSystemMessage('ℹ️ Skipping auto-tests: no test command detected for this repo.');
|
|
6173
|
+
}
|
|
6174
|
+
}
|
|
6175
|
+
finally {
|
|
6176
|
+
this.autoVerificationInFlight = false;
|
|
6177
|
+
}
|
|
6178
|
+
}
|
|
6007
6179
|
rebuildAgent() {
|
|
6008
6180
|
const previousHistory = this.agent ? this.agent.getHistory() : this.cachedHistory;
|
|
6009
6181
|
try {
|
|
@@ -6059,8 +6231,7 @@ What's the next action?`;
|
|
|
6059
6231
|
}
|
|
6060
6232
|
}
|
|
6061
6233
|
// Auto-verify changes: build first (catches type errors), then tests
|
|
6062
|
-
void this.
|
|
6063
|
-
void this.enforceAutoTests('final-response');
|
|
6234
|
+
void this.enforceAutoVerification('final-response');
|
|
6064
6235
|
}
|
|
6065
6236
|
else {
|
|
6066
6237
|
// Non-final message = narrative text before tool calls (Claude Code style)
|
|
@@ -6104,6 +6275,7 @@ What's the next action?`;
|
|
|
6104
6275
|
// Show notification that context was pruned
|
|
6105
6276
|
const method = stats['method'];
|
|
6106
6277
|
const percentage = stats['percentage'];
|
|
6278
|
+
const summarized = stats['summarized'] === true;
|
|
6107
6279
|
if (method === 'emergency-recovery') {
|
|
6108
6280
|
display.stream(`\n✅ Context recovery complete. Removed ${removedCount} messages. Context now at ${percentage ?? 'unknown'}%\n`);
|
|
6109
6281
|
}
|
|
@@ -6111,6 +6283,9 @@ What's the next action?`;
|
|
|
6111
6283
|
if (typeof percentage === 'number') {
|
|
6112
6284
|
this.updateContextUsage(percentage);
|
|
6113
6285
|
}
|
|
6286
|
+
if (summarized) {
|
|
6287
|
+
display.showSystemMessage('Context summary captured. View the latest summaries with /contextlog.');
|
|
6288
|
+
}
|
|
6114
6289
|
// Ensure prompt remains visible at bottom after context messages
|
|
6115
6290
|
this.renderPromptArea();
|
|
6116
6291
|
},
|
|
@@ -6136,8 +6311,7 @@ What's the next action?`;
|
|
|
6136
6311
|
this.renderPromptArea();
|
|
6137
6312
|
},
|
|
6138
6313
|
onVerificationNeeded: () => {
|
|
6139
|
-
void this.
|
|
6140
|
-
void this.enforceAutoTests('verification');
|
|
6314
|
+
void this.enforceAutoVerification('verification');
|
|
6141
6315
|
},
|
|
6142
6316
|
});
|
|
6143
6317
|
// Register global AI enhancer for explore tool - uses active model by default
|
|
@@ -6248,8 +6422,8 @@ What's the next action?`;
|
|
|
6248
6422
|
].join('\n');
|
|
6249
6423
|
case 'balanced':
|
|
6250
6424
|
default:
|
|
6251
|
-
// Balanced
|
|
6252
|
-
return
|
|
6425
|
+
// Balanced mode: show thinking for complex reasoning, planning, or multi-step tasks
|
|
6426
|
+
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.';
|
|
6253
6427
|
}
|
|
6254
6428
|
}
|
|
6255
6429
|
buildDisplayMetadata(metadata) {
|