minovative-mind-cli 2.14.2 → 2.14.3
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/README.md +5 -5
- package/dist/services/agent/slashCommands.js +109 -12
- package/dist/services/agent/toolLoop.js +9 -2
- package/dist/services/agent/types.d.ts +9 -2
- package/dist/services/agent-tools.d.ts +2 -1
- package/dist/services/agent-tools.js +52 -4
- package/dist/services/agent.js +37 -15
- package/dist/services/ai.d.ts +6 -0
- package/dist/services/ai.js +8 -2
- package/dist/services/chatHistoryService.d.ts +5 -0
- package/dist/services/contextAgent.d.ts +4 -2
- package/dist/services/contextAgent.js +3 -1
- package/dist/services/sessionSettings.d.ts +66 -0
- package/dist/services/sessionSettings.js +126 -0
- package/dist/services/verificationService.js +24 -2
- package/dist/utils/antiCheatingGuard.d.ts +21 -0
- package/dist/utils/antiCheatingGuard.js +554 -0
- package/dist/utils/dependencyTracer.d.ts +15 -2
- package/dist/utils/dependencyTracer.js +61 -3
- package/dist/utils/fileReadCache.d.ts +58 -0
- package/dist/utils/fileReadCache.js +162 -0
- package/dist/utils/projectStorage.js +2 -1
- package/dist/utils/symbolExtractor.d.ts +12 -0
- package/dist/utils/symbolExtractor.js +111 -15
- package/dist/utils/systemPrompts.d.ts +3 -2
- package/dist/utils/systemPrompts.js +53 -6
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/dist/services/agent.js
CHANGED
|
@@ -26,7 +26,7 @@ const execAsync = promisify(exec);
|
|
|
26
26
|
import { debugLog, isDebugOn } from '../utils/logger.js';
|
|
27
27
|
import { ensureProjectStorage, ensureIgnored, readCache, writeCache, invalidateCacheForDependents, } from '../utils/projectStorage.js';
|
|
28
28
|
import { GEMINI_MODELS, TPM_COOLING_DELAYS } from '../utils/config.js';
|
|
29
|
-
import { createSharedChatSession, getGeneralChatConfig, getPlanExecutionConfig, compressTextUsingFlashLite, generateChatTitle, getGlobalActiveModel, getModelThinkingLevel, summarizeChatHistory, } from './ai.js';
|
|
29
|
+
import { createSharedChatSession, getGeneralChatConfig, getPlanExecutionConfig, getResearchConfig, compressTextUsingFlashLite, generateChatTitle, getGlobalActiveModel, getModelThinkingLevel, summarizeChatHistory, } from './ai.js';
|
|
30
30
|
import { getAndResetTurnUsage } from './proxyClient.js';
|
|
31
31
|
import { changeLogger } from './changeLogger.js';
|
|
32
32
|
import { chatHistoryService } from './chatHistoryService.js';
|
|
@@ -43,6 +43,8 @@ import { handleSlashCommand } from './agent/slashCommands.js';
|
|
|
43
43
|
import { getMetricCollector } from './metrics.js';
|
|
44
44
|
import { Orchestrator } from './orchestration/orchestrator.js';
|
|
45
45
|
import { isSubAgentsEnabled, getApprovalMode } from './agent-tools.js';
|
|
46
|
+
import { resetSessionSettingsToDefault } from './sessionSettings.js';
|
|
47
|
+
import { clearFileReadCache } from '../utils/fileReadCache.js';
|
|
46
48
|
import { runWithAgentId } from '../utils/asyncContext.js';
|
|
47
49
|
// Export submodules for potential external uses if required
|
|
48
50
|
export { AsyncInputHandler } from './agent/inputHandler.js';
|
|
@@ -117,6 +119,8 @@ export async function startAgentLoop(workspaceRoot, version) {
|
|
|
117
119
|
changeLogger.init(workspaceRoot);
|
|
118
120
|
chatHistoryService.init(workspaceRoot);
|
|
119
121
|
const chat = createSharedChatSession();
|
|
122
|
+
resetSessionSettingsToDefault(chat);
|
|
123
|
+
clearFileReadCache();
|
|
120
124
|
const inputHandler = new AsyncInputHandler();
|
|
121
125
|
const chatSessionState = {
|
|
122
126
|
id: crypto.randomUUID(),
|
|
@@ -160,6 +164,7 @@ export async function startAgentLoop(workspaceRoot, version) {
|
|
|
160
164
|
chatSessionState.modelUsageCounts = {};
|
|
161
165
|
chatSessionState.latestUsageMetadata = undefined;
|
|
162
166
|
chatSessionState.previousUsageMetadata = undefined;
|
|
167
|
+
resetSessionSettingsToDefault(chat);
|
|
163
168
|
chat.setSessionInfo(chatSessionState.id, workspaceRoot);
|
|
164
169
|
}
|
|
165
170
|
inputHandler.stop();
|
|
@@ -359,21 +364,22 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
359
364
|
if (gatherRes.chainedMessages.length > 0) {
|
|
360
365
|
const chainedContent = gatherRes.chainedMessages.join('\n');
|
|
361
366
|
const newIntent = await routeIntent(chainedContent, '', ac.signal);
|
|
362
|
-
if (gatherRes.
|
|
363
|
-
//
|
|
364
|
-
effectiveTargetAgent =
|
|
367
|
+
if (gatherRes.targetAgent === 'EXECUTE') {
|
|
368
|
+
// EXECUTE permission sets are immutable during follow-ups to prevent downgrades
|
|
369
|
+
effectiveTargetAgent = 'EXECUTE';
|
|
370
|
+
}
|
|
371
|
+
else if (gatherRes.targetAgent === 'RESEARCH') {
|
|
372
|
+
// RESEARCH sessions stay in RESEARCH mode during chained requests
|
|
373
|
+
// Chained requests are incorporated into the research context for comprehensive investigation
|
|
374
|
+
effectiveTargetAgent = 'RESEARCH';
|
|
365
375
|
}
|
|
366
376
|
else {
|
|
367
|
-
// If
|
|
368
|
-
if (
|
|
369
|
-
// EXECUTE permission sets are immutable during follow-ups to prevent downgrades
|
|
377
|
+
// If in CHAT mode, escalate if chained instructions dictate
|
|
378
|
+
if (newIntent.targetAgent === 'EXECUTE') {
|
|
370
379
|
effectiveTargetAgent = 'EXECUTE';
|
|
371
380
|
}
|
|
372
|
-
else {
|
|
373
|
-
|
|
374
|
-
if (newIntent.targetAgent === 'EXECUTE' || newIntent.needsContext) {
|
|
375
|
-
effectiveTargetAgent = 'EXECUTE';
|
|
376
|
-
}
|
|
381
|
+
else if (newIntent.targetAgent === 'RESEARCH') {
|
|
382
|
+
effectiveTargetAgent = 'RESEARCH';
|
|
377
383
|
}
|
|
378
384
|
}
|
|
379
385
|
finalInput += `\n\n[USER FOLLOW-UP INSTRUCTIONS SENT DURING INVESTIGATION]:\n${chainedContent}\n\nPlease incorporate these instructions into your work. Address them appropriately, but ensure you do not lose track of the original request's primary objective.`;
|
|
@@ -383,9 +389,13 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
383
389
|
process.stdout.write('\x1b[2K\r');
|
|
384
390
|
return;
|
|
385
391
|
}
|
|
386
|
-
// Hot-swap the underlying LLM system instruction context depending on intent (conversational vs execution)
|
|
392
|
+
// Hot-swap the underlying LLM system instruction context depending on intent (conversational vs research vs execution)
|
|
387
393
|
debugLog(`Intent Router output: original targetAgent = ${gatherRes.targetAgent}, effective = ${effectiveTargetAgent}`);
|
|
388
|
-
const config = effectiveTargetAgent === 'CHAT'
|
|
394
|
+
const config = effectiveTargetAgent === 'CHAT'
|
|
395
|
+
? getGeneralChatConfig()
|
|
396
|
+
: effectiveTargetAgent === 'RESEARCH'
|
|
397
|
+
? getResearchConfig()
|
|
398
|
+
: getPlanExecutionConfig();
|
|
389
399
|
let dynamicSystemInstruction = config.systemInstruction;
|
|
390
400
|
// Inject gathered workspace directories, dependency configurations, and matching search patterns
|
|
391
401
|
if (gatherRes.contextResult) {
|
|
@@ -495,6 +505,9 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
495
505
|
if (effectiveTargetAgent === 'CHAT') {
|
|
496
506
|
selectedModel = GEMINI_MODELS.FLASH_LITE;
|
|
497
507
|
}
|
|
508
|
+
else if (effectiveTargetAgent === 'RESEARCH') {
|
|
509
|
+
selectedModel = GEMINI_MODELS.FLASH;
|
|
510
|
+
}
|
|
498
511
|
else {
|
|
499
512
|
spinner.stop(); // MUST clear the investigation spinner first to prevent leaking the setInterval
|
|
500
513
|
spinner.start(pc.blue('🧠 Evaluating execution complexity...'));
|
|
@@ -661,6 +674,8 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
661
674
|
creditsRemaining: usage.remainingBalance,
|
|
662
675
|
lastTurnDuration: turnDuration,
|
|
663
676
|
modelName: chat.getModel(),
|
|
677
|
+
thinkingLevel: (typeof chat.getThinkingLevel === 'function' ? chat.getThinkingLevel() : undefined) ||
|
|
678
|
+
getModelThinkingLevel(chat.getModel()),
|
|
664
679
|
totalTokens: chatSessionState.totalTokens,
|
|
665
680
|
totalInputTokens: chatSessionState.totalInputTokens,
|
|
666
681
|
totalOutputTokens: chatSessionState.totalOutputTokens,
|
|
@@ -668,6 +683,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
668
683
|
gitBranch: gitBranch || undefined,
|
|
669
684
|
autoApprove: getApprovalMode() === 'skip-all',
|
|
670
685
|
subAgents: isSubAgentsEnabled(),
|
|
686
|
+
debugMode: isDebugOn(),
|
|
671
687
|
latestUsageMetadata: chatSessionState.latestUsageMetadata,
|
|
672
688
|
previousUsageMetadata: chatSessionState.previousUsageMetadata,
|
|
673
689
|
modelUsageCounts: chatSessionState.modelUsageCounts,
|
|
@@ -825,6 +841,8 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
825
841
|
creditsRemaining: latestUsage?.remainingBalance,
|
|
826
842
|
lastTurnDuration: turnDuration,
|
|
827
843
|
modelName: chat.getModel(),
|
|
844
|
+
thinkingLevel: (typeof chat.getThinkingLevel === 'function' ? chat.getThinkingLevel() : undefined) ||
|
|
845
|
+
getModelThinkingLevel(chat.getModel()),
|
|
828
846
|
totalTokens: chatSessionState.totalTokens,
|
|
829
847
|
totalInputTokens: chatSessionState.totalInputTokens,
|
|
830
848
|
totalOutputTokens: chatSessionState.totalOutputTokens,
|
|
@@ -832,6 +850,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
832
850
|
gitBranch: gitBranch || undefined,
|
|
833
851
|
autoApprove: getApprovalMode() === 'skip-all',
|
|
834
852
|
subAgents: isSubAgentsEnabled(),
|
|
853
|
+
debugMode: isDebugOn(),
|
|
835
854
|
latestUsageMetadata: chatSessionState.latestUsageMetadata,
|
|
836
855
|
previousUsageMetadata: chatSessionState.previousUsageMetadata,
|
|
837
856
|
modelUsageCounts: chatSessionState.modelUsageCounts,
|
|
@@ -850,6 +869,8 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
850
869
|
creditsRemaining: latestUsage?.remainingBalance,
|
|
851
870
|
lastTurnDuration: turnDuration,
|
|
852
871
|
modelName: chat.getModel(),
|
|
872
|
+
thinkingLevel: (typeof chat.getThinkingLevel === 'function' ? chat.getThinkingLevel() : undefined) ||
|
|
873
|
+
getModelThinkingLevel(chat.getModel()),
|
|
853
874
|
totalTokens: chatSessionState.totalTokens,
|
|
854
875
|
totalInputTokens: chatSessionState.totalInputTokens,
|
|
855
876
|
totalOutputTokens: chatSessionState.totalOutputTokens,
|
|
@@ -857,6 +878,7 @@ export async function executeSingleTurn(workspaceRoot, userInput, chat, inputHan
|
|
|
857
878
|
gitBranch: gitBranch || undefined,
|
|
858
879
|
autoApprove: getApprovalMode() === 'skip-all',
|
|
859
880
|
subAgents: isSubAgentsEnabled(),
|
|
881
|
+
debugMode: isDebugOn(),
|
|
860
882
|
latestUsageMetadata: chatSessionState.latestUsageMetadata,
|
|
861
883
|
previousUsageMetadata: chatSessionState.previousUsageMetadata,
|
|
862
884
|
modelUsageCounts: chatSessionState.modelUsageCounts,
|
|
@@ -1204,7 +1226,7 @@ If you are not done, please continue working using your other tools.`;
|
|
|
1204
1226
|
.join('\n\n');
|
|
1205
1227
|
debugLog(`Verification failed on attempt ${correctionAttempts}/${MAX_CORRECTIONS}. Issues:\n${combinedIssuesForAI}`);
|
|
1206
1228
|
// Compile compilation and syntax diagnostic warnings into an auto-correction prompt
|
|
1207
|
-
const correctionPrompt = `AUTOMATED SYSTEM CHECK: Your previous changes resulted in the following issues:\n\n${combinedIssuesForAI}\n\
|
|
1229
|
+
const correctionPrompt = `AUTOMATED SYSTEM CHECK: Your previous changes resulted in the following issues:\n\n${combinedIssuesForAI}\n\nCRITICAL ANTI-CHEATING RULE: You MUST fix these issues head-on in the application source code. You are STRICTLY FORBIDDEN from modifying build configurations (e.g. next.config.*, tsconfig.json, vite.config.*, .eslintrc*, package.json scripts) to ignore, disable, or bypass build, compile, type, or lint errors (such as ignoreBuildErrors, ignoreDuringBuilds, or turning off checks). You are also forbidden from adding blanket suppressions like @ts-ignore, @ts-nocheck, or eslint-disable to silence errors. Fix the underlying root cause in the actual code.`;
|
|
1208
1230
|
// Cooling-off delay before initiating the self-correction turn
|
|
1209
1231
|
await new Promise((resolve) => setTimeout(resolve, TPM_COOLING_DELAYS.CORRECTION_TURN_MS));
|
|
1210
1232
|
if (signal.aborted)
|
package/dist/services/ai.d.ts
CHANGED
|
@@ -117,6 +117,12 @@ export declare function getPlanExecutionConfig(): {
|
|
|
117
117
|
functionDeclarations: import("@google/generative-ai").FunctionDeclaration[];
|
|
118
118
|
}[];
|
|
119
119
|
};
|
|
120
|
+
export declare function getResearchConfig(): {
|
|
121
|
+
systemInstruction: string;
|
|
122
|
+
tools: {
|
|
123
|
+
functionDeclarations: import("@google/generative-ai").FunctionDeclaration[];
|
|
124
|
+
}[];
|
|
125
|
+
};
|
|
120
126
|
/**
|
|
121
127
|
* Compresses a large string of text using Gemini Flash.
|
|
122
128
|
* Used for shrinking context payloads to prevent OOM/choking.
|
package/dist/services/ai.js
CHANGED
|
@@ -5,7 +5,7 @@ import { getMetricCollector } from './metrics.js';
|
|
|
5
5
|
import { getAuthorizedIdToken, checkByokSubscription } from './auth.js';
|
|
6
6
|
import { debugLog } from '../utils/logger.js';
|
|
7
7
|
import { readCache, writeCache } from '../utils/projectStorage.js';
|
|
8
|
-
import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, TRIVIAL_MESSAGE_CLASSIFIER_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
|
|
8
|
+
import { GENERAL_CHAT_INSTRUCTION, PLAN_EXECUTION_INSTRUCTION, RESEARCH_AGENT_SYSTEM_INSTRUCTION, CONTEXT_SYSTEM_INSTRUCTION, INTENT_ROUTER_SYSTEM_INSTRUCTION, WEB_SEARCH_SYSTEM_INSTRUCTION, EXECUTION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_COMPLEXITY_SYSTEM_INSTRUCTION, INVESTIGATION_SEMANTIC_SYSTEM_INSTRUCTION, HISTORY_SUMMARIZER_SYSTEM_INSTRUCTION, USER_PROFILE_EXTRACTOR_SYSTEM_INSTRUCTION, TRIVIAL_MESSAGE_CLASSIFIER_SYSTEM_INSTRUCTION, } from '../utils/systemPrompts.js';
|
|
9
9
|
import { workspaceRegistry } from './workspaceRegistry.js';
|
|
10
10
|
import { loadCredentials } from '../utils/credentialStore.js';
|
|
11
11
|
import { ProxyClient } from './proxyClient.js';
|
|
@@ -534,6 +534,12 @@ export function getPlanExecutionConfig() {
|
|
|
534
534
|
tools: [{ functionDeclarations: getToolDeclarations({ isExecutionAgent: true }) }],
|
|
535
535
|
};
|
|
536
536
|
}
|
|
537
|
+
export function getResearchConfig() {
|
|
538
|
+
return {
|
|
539
|
+
systemInstruction: RESEARCH_AGENT_SYSTEM_INSTRUCTION.replace('{{MULTI_WORKSPACE_BLOCK}}', getMultiWorkspaceBlock()),
|
|
540
|
+
tools: [{ functionDeclarations: getToolDeclarations({ isResearchAgent: true }) }],
|
|
541
|
+
};
|
|
542
|
+
}
|
|
537
543
|
/**
|
|
538
544
|
* Compresses a large string of text using Gemini Flash.
|
|
539
545
|
* Used for shrinking context payloads to prevent OOM/choking.
|
|
@@ -794,7 +800,7 @@ export function createIntentRouterSession() {
|
|
|
794
800
|
},
|
|
795
801
|
agent: {
|
|
796
802
|
type: SchemaType.STRING,
|
|
797
|
-
enum: ['CHAT', 'EXECUTE'],
|
|
803
|
+
enum: ['CHAT', 'RESEARCH', 'EXECUTE'],
|
|
798
804
|
description: 'Target agent to route the request to',
|
|
799
805
|
},
|
|
800
806
|
},
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Content } from '@google/generative-ai';
|
|
2
|
+
import type { ThinkingLevel } from '../utils/config.js';
|
|
2
3
|
/**
|
|
3
4
|
* Options for configuring dynamic history pruning.
|
|
4
5
|
*/
|
|
@@ -32,6 +33,8 @@ export interface ChatSessionData {
|
|
|
32
33
|
lastTurnDuration?: string;
|
|
33
34
|
/** Optional name of the AI model used during this session (e.g., "gemini-1.5-pro"). */
|
|
34
35
|
modelName?: string;
|
|
36
|
+
/** Optional thinking reasoning level used during this session (e.g., "LOW", "MEDIUM", "HIGH"). */
|
|
37
|
+
thinkingLevel?: ThinkingLevel;
|
|
35
38
|
/** Optional total cumulative tokens consumed during the session. */
|
|
36
39
|
totalTokens?: number;
|
|
37
40
|
/** Optional total cumulative input tokens (prompt + cached) consumed during the session. */
|
|
@@ -46,6 +49,8 @@ export interface ChatSessionData {
|
|
|
46
49
|
autoApprove?: boolean;
|
|
47
50
|
/** Optional flag indicating whether sub-agents were enabled or active during this session. */
|
|
48
51
|
subAgents?: boolean;
|
|
52
|
+
/** Optional flag indicating whether debug diagnostic logging was enabled in this session. */
|
|
53
|
+
debugMode?: boolean;
|
|
49
54
|
/** Optional metadata about the token usage from the very last turn. */
|
|
50
55
|
latestUsageMetadata?: any;
|
|
51
56
|
/** Optional metadata about the token usage from the turn prior to the last turn. */
|
|
@@ -17,9 +17,11 @@ export interface ContextAgentResult {
|
|
|
17
17
|
tierPartition?: TierPartitionResult;
|
|
18
18
|
}
|
|
19
19
|
export declare function detectProjectType(workspaceRoot: string): Promise<string>;
|
|
20
|
+
import type { TargetAgent } from './agent/types.js';
|
|
21
|
+
export type { TargetAgent } from './agent/types.js';
|
|
20
22
|
export interface IntentRoute {
|
|
21
23
|
needsContext: boolean;
|
|
22
|
-
targetAgent:
|
|
24
|
+
targetAgent: TargetAgent;
|
|
23
25
|
}
|
|
24
26
|
export declare function routeIntent(userRequest: string, chatHistory?: string, abortSignal?: AbortSignal): Promise<IntentRoute>;
|
|
25
27
|
export declare function evaluateExecutionComplexity(userRequest: string, investigationSummary: string | undefined, numRelevantFiles: number, chatHistory?: string, abortSignal?: AbortSignal): Promise<'EASY' | 'HARD'>;
|
|
@@ -28,6 +30,6 @@ export declare function gatherContext(workspaceRoot: string, userRequest: string
|
|
|
28
30
|
waitForPrompt: () => Promise<void>;
|
|
29
31
|
}, abortSignal: AbortSignal, onProgress?: (msg: string) => void, onToolCall?: (msg: string, label: string) => void): Promise<{
|
|
30
32
|
contextResult: ContextAgentResult | null;
|
|
31
|
-
targetAgent:
|
|
33
|
+
targetAgent: TargetAgent;
|
|
32
34
|
chainedMessages: string[];
|
|
33
35
|
}>;
|
|
@@ -219,9 +219,11 @@ export async function routeIntent(userRequest, chatHistory = '', abortSignal) {
|
|
|
219
219
|
const text = result.response.text()?.trim() || '{}';
|
|
220
220
|
const parsed = JSON.parse(text);
|
|
221
221
|
debugLog(`Intent Router Parsed: ${JSON.stringify(parsed)}`);
|
|
222
|
+
const rawAgent = parsed.agent?.toUpperCase?.() || parsed.agent;
|
|
223
|
+
const validAgent = rawAgent === 'CHAT' ? 'CHAT' : rawAgent === 'RESEARCH' ? 'RESEARCH' : 'EXECUTE';
|
|
222
224
|
return {
|
|
223
225
|
needsContext: parsed.context === 'SEARCH',
|
|
224
|
-
targetAgent:
|
|
226
|
+
targetAgent: validAgent,
|
|
225
227
|
};
|
|
226
228
|
}
|
|
227
229
|
catch (e) {
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file sessionSettings.ts
|
|
3
|
+
* @description Manages session-scoped slash command settings and operational toggles.
|
|
4
|
+
*
|
|
5
|
+
* Operational toggles scoped to an individual chat session include:
|
|
6
|
+
* - `autoApprove` : Whether automatic confirmation is enabled for shell execution commands (/auto-approve)
|
|
7
|
+
* - `subAgents` : Whether the MMAAK parallel multi-agent orchestration engine is enabled (/sub-agents)
|
|
8
|
+
* - `debugMode` : Whether internal diagnostic telemetry logging is visible (/debug)
|
|
9
|
+
* - `modelName` : The generative AI model selected for this session (/models)
|
|
10
|
+
* - `thinkingLevel`: The reasoning budget allocation level for the active model (/models)
|
|
11
|
+
*
|
|
12
|
+
* Safe Lifecycle:
|
|
13
|
+
* - On new chat sessions or CLI boot, settings automatically reset to safe defaults.
|
|
14
|
+
* - On resuming a saved session, previous settings are restored and verified.
|
|
15
|
+
*/
|
|
16
|
+
import { type ThinkingLevel } from '../utils/config.js';
|
|
17
|
+
import { type ProxyChatSession } from './ai.js';
|
|
18
|
+
import { type ChatSessionData } from './chatHistoryService.js';
|
|
19
|
+
/**
|
|
20
|
+
* Session-scoped operational settings container.
|
|
21
|
+
*/
|
|
22
|
+
export interface SessionSettings {
|
|
23
|
+
/** Whether auto-approval mode is enabled for command execution ('skip-all' vs 'ask'). */
|
|
24
|
+
autoApprove: boolean;
|
|
25
|
+
/** Whether MMAAK parallel sub-agent orchestration is enabled. */
|
|
26
|
+
subAgents: boolean;
|
|
27
|
+
/** Whether internal telemetry and diagnostic logging is enabled. */
|
|
28
|
+
debugMode: boolean;
|
|
29
|
+
/** Active generative AI model identifier for the session. */
|
|
30
|
+
modelName: string;
|
|
31
|
+
/** Active thinking/reasoning level for the model. */
|
|
32
|
+
thinkingLevel: ThinkingLevel;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Default safe settings used when creating a new chat session or resetting state.
|
|
36
|
+
*/
|
|
37
|
+
export declare const DEFAULT_SESSION_SETTINGS: Readonly<SessionSettings>;
|
|
38
|
+
/**
|
|
39
|
+
* Applies saved or specified settings to the active environment and chat session.
|
|
40
|
+
*
|
|
41
|
+
* @param session - A partial session object or settings container.
|
|
42
|
+
* @param chat - Optional active ProxyChatSession instance to update.
|
|
43
|
+
* @returns The resulting applied SessionSettings.
|
|
44
|
+
*/
|
|
45
|
+
export declare function applySessionSettings(session: Partial<ChatSessionData> | Partial<SessionSettings>, chat?: ProxyChatSession): SessionSettings;
|
|
46
|
+
/**
|
|
47
|
+
* Resets all session operational toggles back to default safe values.
|
|
48
|
+
*
|
|
49
|
+
* @param chat - Optional active ProxyChatSession instance to reset.
|
|
50
|
+
* @returns The default SessionSettings.
|
|
51
|
+
*/
|
|
52
|
+
export declare function resetSessionSettingsToDefault(chat?: ProxyChatSession): SessionSettings;
|
|
53
|
+
/**
|
|
54
|
+
* Inspects and retrieves the current operational settings across modules.
|
|
55
|
+
*
|
|
56
|
+
* @param chat - Optional active ProxyChatSession instance.
|
|
57
|
+
* @returns The current active SessionSettings.
|
|
58
|
+
*/
|
|
59
|
+
export declare function getCurrentSessionSettings(chat?: ProxyChatSession): SessionSettings;
|
|
60
|
+
/**
|
|
61
|
+
* Persists current operational settings to the saved session cache if the session exists on disk.
|
|
62
|
+
*
|
|
63
|
+
* @param sessionId - The unique identifier of the chat session to update.
|
|
64
|
+
* @param chat - Optional active ProxyChatSession instance.
|
|
65
|
+
*/
|
|
66
|
+
export declare function syncActiveSessionSettings(sessionId?: string, chat?: ProxyChatSession): Promise<void>;
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @file sessionSettings.ts
|
|
3
|
+
* @description Manages session-scoped slash command settings and operational toggles.
|
|
4
|
+
*
|
|
5
|
+
* Operational toggles scoped to an individual chat session include:
|
|
6
|
+
* - `autoApprove` : Whether automatic confirmation is enabled for shell execution commands (/auto-approve)
|
|
7
|
+
* - `subAgents` : Whether the MMAAK parallel multi-agent orchestration engine is enabled (/sub-agents)
|
|
8
|
+
* - `debugMode` : Whether internal diagnostic telemetry logging is visible (/debug)
|
|
9
|
+
* - `modelName` : The generative AI model selected for this session (/models)
|
|
10
|
+
* - `thinkingLevel`: The reasoning budget allocation level for the active model (/models)
|
|
11
|
+
*
|
|
12
|
+
* Safe Lifecycle:
|
|
13
|
+
* - On new chat sessions or CLI boot, settings automatically reset to safe defaults.
|
|
14
|
+
* - On resuming a saved session, previous settings are restored and verified.
|
|
15
|
+
*/
|
|
16
|
+
import { setApprovalMode, getApprovalMode, isSubAgentsEnabled, setSubAgentsEnabled } from './agent-tools.js';
|
|
17
|
+
import { isDebugOn, setDebugMode } from '../utils/logger.js';
|
|
18
|
+
import { DEFAULT_MODEL, DEFAULT_MODEL_THINKING_LEVELS, } from '../utils/config.js';
|
|
19
|
+
import { getGlobalActiveModel, setGlobalActiveModel, getModelThinkingLevel, setModelThinkingLevel, } from './ai.js';
|
|
20
|
+
import { chatHistoryService } from './chatHistoryService.js';
|
|
21
|
+
/**
|
|
22
|
+
* Default safe settings used when creating a new chat session or resetting state.
|
|
23
|
+
*/
|
|
24
|
+
export const DEFAULT_SESSION_SETTINGS = Object.freeze({
|
|
25
|
+
autoApprove: false,
|
|
26
|
+
subAgents: true,
|
|
27
|
+
debugMode: false,
|
|
28
|
+
modelName: DEFAULT_MODEL,
|
|
29
|
+
thinkingLevel: (DEFAULT_MODEL_THINKING_LEVELS[DEFAULT_MODEL] || 'MEDIUM'),
|
|
30
|
+
});
|
|
31
|
+
/**
|
|
32
|
+
* Applies saved or specified settings to the active environment and chat session.
|
|
33
|
+
*
|
|
34
|
+
* @param session - A partial session object or settings container.
|
|
35
|
+
* @param chat - Optional active ProxyChatSession instance to update.
|
|
36
|
+
* @returns The resulting applied SessionSettings.
|
|
37
|
+
*/
|
|
38
|
+
export function applySessionSettings(session, chat) {
|
|
39
|
+
// 1. Auto-approve mode
|
|
40
|
+
const autoApprove = session.autoApprove ?? DEFAULT_SESSION_SETTINGS.autoApprove;
|
|
41
|
+
setApprovalMode(autoApprove ? 'skip-all' : 'ask');
|
|
42
|
+
// 2. MMAAK sub-agents
|
|
43
|
+
const subAgents = session.subAgents ?? DEFAULT_SESSION_SETTINGS.subAgents;
|
|
44
|
+
setSubAgentsEnabled(subAgents);
|
|
45
|
+
// 3. Debug logging
|
|
46
|
+
const debugMode = session.debugMode ?? DEFAULT_SESSION_SETTINGS.debugMode;
|
|
47
|
+
setDebugMode(debugMode);
|
|
48
|
+
// 4. Model selection
|
|
49
|
+
const modelName = session.modelName ?? DEFAULT_SESSION_SETTINGS.modelName;
|
|
50
|
+
setGlobalActiveModel(modelName);
|
|
51
|
+
if (chat && typeof chat.setModel === 'function') {
|
|
52
|
+
chat.setModel(modelName);
|
|
53
|
+
}
|
|
54
|
+
// 5. Thinking level
|
|
55
|
+
const targetThinking = session.thinkingLevel ??
|
|
56
|
+
getModelThinkingLevel(modelName) ??
|
|
57
|
+
DEFAULT_MODEL_THINKING_LEVELS[modelName] ??
|
|
58
|
+
DEFAULT_SESSION_SETTINGS.thinkingLevel;
|
|
59
|
+
setModelThinkingLevel(modelName, targetThinking);
|
|
60
|
+
if (chat && typeof chat.setThinkingLevel === 'function') {
|
|
61
|
+
chat.setThinkingLevel(targetThinking);
|
|
62
|
+
}
|
|
63
|
+
return {
|
|
64
|
+
autoApprove,
|
|
65
|
+
subAgents,
|
|
66
|
+
debugMode,
|
|
67
|
+
modelName,
|
|
68
|
+
thinkingLevel: targetThinking,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
/**
|
|
72
|
+
* Resets all session operational toggles back to default safe values.
|
|
73
|
+
*
|
|
74
|
+
* @param chat - Optional active ProxyChatSession instance to reset.
|
|
75
|
+
* @returns The default SessionSettings.
|
|
76
|
+
*/
|
|
77
|
+
export function resetSessionSettingsToDefault(chat) {
|
|
78
|
+
return applySessionSettings(DEFAULT_SESSION_SETTINGS, chat);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Inspects and retrieves the current operational settings across modules.
|
|
82
|
+
*
|
|
83
|
+
* @param chat - Optional active ProxyChatSession instance.
|
|
84
|
+
* @returns The current active SessionSettings.
|
|
85
|
+
*/
|
|
86
|
+
export function getCurrentSessionSettings(chat) {
|
|
87
|
+
const autoApprove = getApprovalMode() === 'skip-all';
|
|
88
|
+
const subAgents = isSubAgentsEnabled();
|
|
89
|
+
const debugMode = isDebugOn();
|
|
90
|
+
const modelName = (chat && typeof chat.getModel === 'function' ? chat.getModel() : undefined) || getGlobalActiveModel();
|
|
91
|
+
const thinkingLevel = (chat && typeof chat.getThinkingLevel === 'function' ? chat.getThinkingLevel() : undefined) ||
|
|
92
|
+
getModelThinkingLevel(modelName) ||
|
|
93
|
+
'MEDIUM';
|
|
94
|
+
return {
|
|
95
|
+
autoApprove,
|
|
96
|
+
subAgents,
|
|
97
|
+
debugMode,
|
|
98
|
+
modelName,
|
|
99
|
+
thinkingLevel,
|
|
100
|
+
};
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Persists current operational settings to the saved session cache if the session exists on disk.
|
|
104
|
+
*
|
|
105
|
+
* @param sessionId - The unique identifier of the chat session to update.
|
|
106
|
+
* @param chat - Optional active ProxyChatSession instance.
|
|
107
|
+
*/
|
|
108
|
+
export async function syncActiveSessionSettings(sessionId, chat) {
|
|
109
|
+
if (!sessionId)
|
|
110
|
+
return;
|
|
111
|
+
try {
|
|
112
|
+
const session = chatHistoryService.getSession(sessionId);
|
|
113
|
+
if (!session)
|
|
114
|
+
return;
|
|
115
|
+
const current = getCurrentSessionSettings(chat);
|
|
116
|
+
session.autoApprove = current.autoApprove;
|
|
117
|
+
session.subAgents = current.subAgents;
|
|
118
|
+
session.debugMode = current.debugMode;
|
|
119
|
+
session.modelName = current.modelName;
|
|
120
|
+
session.thinkingLevel = current.thinkingLevel;
|
|
121
|
+
await chatHistoryService.saveSession(session);
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Non-blocking sync failure ignored
|
|
125
|
+
}
|
|
126
|
+
}
|
|
@@ -149,8 +149,13 @@ export async function runVerification(workspaceRoot, abortSignal) {
|
|
|
149
149
|
const MAX_VERIFY_OUTPUT = 50_000; // 50KB cap on verification output
|
|
150
150
|
debugLog(`Running project-level verification command: ${command}`);
|
|
151
151
|
try {
|
|
152
|
+
const cleanEnv = { ...process.env };
|
|
153
|
+
delete cleanEnv.NEXT_DISABLE_ESLINT;
|
|
154
|
+
delete cleanEnv.TSC_COMPILE_ON_ERROR;
|
|
155
|
+
delete cleanEnv.ESLINT_NO_DEV_ERRORS;
|
|
152
156
|
const { stdout, stderr } = await execAsync(command, {
|
|
153
157
|
cwd: workspaceRoot,
|
|
158
|
+
env: cleanEnv,
|
|
154
159
|
timeout: 120_000, // 120s (2 mins) - builds can take a while (e.g., Next.js, Gradle)
|
|
155
160
|
maxBuffer: 1024 * 1024, // 1 MB buffer
|
|
156
161
|
signal: abortSignal,
|
|
@@ -235,6 +240,7 @@ ${result.errors.join('\n')}
|
|
|
235
240
|
Please fix these errors using the modify_file tool.`;
|
|
236
241
|
}
|
|
237
242
|
import { auditFilePerformance, formatAuditForModel, formatAuditForTerminal, isAuditableFile, } from '../utils/performanceAuditor.js';
|
|
243
|
+
import { detectAntiCheatingViolations } from '../utils/antiCheatingGuard.js';
|
|
238
244
|
export async function verifyChangedFiles(workspaceRoot, filePaths, abortSignal) {
|
|
239
245
|
if (process.env.MMCLI_SKIP_VERIFICATION === 'true' || process.env.SKIP_VERIFICATION === '1') {
|
|
240
246
|
return { errors: null, warnings: null };
|
|
@@ -267,10 +273,26 @@ export async function verifyChangedFiles(workspaceRoot, filePaths, abortSignal)
|
|
|
267
273
|
if (buildResult.aborted) {
|
|
268
274
|
return '[Verification Aborted]';
|
|
269
275
|
}
|
|
270
|
-
const buildErrorMsg = `[Build Error: ${buildResult.command}]\n${buildResult.errors.join('\n').substring(0, 5000)}
|
|
276
|
+
const buildErrorMsg = `[Build Error: ${buildResult.command}]\n${buildResult.errors.join('\n').substring(0, 5000)}\n\nCRITICAL DIRECTIVE: Do NOT modify configuration files (such as next.config.*, tsconfig.json, or package.json) to disable, ignore, or bypass these errors (e.g. ignoreBuildErrors, ignoreDuringBuilds). You MUST fix these errors directly in the source code.`;
|
|
271
277
|
errors.push(buildErrorMsg);
|
|
272
278
|
}
|
|
273
|
-
// 2.
|
|
279
|
+
// 2. Anti-Cheating Invariant Scan: Ensure no modified files introduced bypass flags
|
|
280
|
+
for (const file of filePaths) {
|
|
281
|
+
if (abortSignal?.aborted)
|
|
282
|
+
return '[Verification Aborted]';
|
|
283
|
+
try {
|
|
284
|
+
const absolutePath = path.resolve(workspaceRoot, file);
|
|
285
|
+
const content = await fs.readFile(absolutePath, 'utf-8');
|
|
286
|
+
const antiCheatViolation = detectAntiCheatingViolations(file, content);
|
|
287
|
+
if (antiCheatViolation) {
|
|
288
|
+
errors.push(`[Verification Rejected - Anti-Cheating Violation in "${file}"]\n${antiCheatViolation}`);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
catch {
|
|
292
|
+
// File might have been deleted or inaccessible
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
// 3. Performance Audit
|
|
274
296
|
// We run this even if the build failed, so the model gets all feedback at once
|
|
275
297
|
for (const file of filePaths) {
|
|
276
298
|
if (abortSignal?.aborted)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Determines whether a given file path represents a critical project configuration
|
|
3
|
+
* file or root manifest that should never be deleted or renamed by the agent.
|
|
4
|
+
*
|
|
5
|
+
* @param filePath - Relative or absolute path to check
|
|
6
|
+
* @returns True if the file is a protected critical config file
|
|
7
|
+
*/
|
|
8
|
+
export declare function isCriticalConfigFile(filePath: string): boolean;
|
|
9
|
+
/**
|
|
10
|
+
* Evaluates whether a proposed file modification or write introduces anti-cheating violations
|
|
11
|
+
* by attempting to silence, ignore, or bypass build, compiler, type, or lint errors.
|
|
12
|
+
*
|
|
13
|
+
* This function is strictly diff-aware: if the existing file already had an error-ignoring flag,
|
|
14
|
+
* modifying unrelated sections of the file will not trigger a false positive.
|
|
15
|
+
*
|
|
16
|
+
* @param filePath - Path to the file being created or modified
|
|
17
|
+
* @param newContent - The proposed new content of the file
|
|
18
|
+
* @param existingContent - The previous content of the file (if it already existed on disk)
|
|
19
|
+
* @returns An error message string if an anti-cheating violation is detected, or null if clean.
|
|
20
|
+
*/
|
|
21
|
+
export declare function detectAntiCheatingViolations(filePath: string, newContent: string, existingContent?: string): string | null;
|