minovative-mind-cli 2.8.4 → 2.9.1
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 +2 -1
- package/dist/services/agent/inputHandler.d.ts +18 -3
- package/dist/services/agent/inputHandler.js +54 -29
- package/dist/services/agent/slashCommands.js +29 -6
- package/dist/services/agent/syntaxAgent.d.ts +3 -1
- package/dist/services/agent/syntaxAgent.js +15 -5
- package/dist/services/agent/toolLoop.js +1 -1
- package/dist/services/agent.d.ts +1 -1
- package/dist/services/agent.js +96 -24
- package/dist/services/ai.d.ts +3 -3
- package/dist/services/ai.js +50 -13
- package/dist/services/auth.d.ts +7 -0
- package/dist/services/auth.js +41 -0
- package/dist/services/contextAgent.d.ts +2 -2
- package/dist/services/contextAgent.js +61 -10
- package/dist/services/investigationComplexity.d.ts +1 -1
- package/dist/services/investigationComplexity.js +12 -2
- package/dist/services/orchestration/orchestrator.d.ts +1 -1
- package/dist/services/orchestration/orchestrator.js +1 -1
- package/dist/services/orchestration/subAgent.js +1 -1
- package/dist/services/proxyClient.js +44 -2
- package/dist/utils/config.d.ts +3 -1
- package/dist/utils/config.js +3 -1
- package/oclif.manifest.json +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,7 +88,8 @@ Hot-swap during a session using `/models`:
|
|
|
88
88
|
|
|
89
89
|
| Model | Best for |
|
|
90
90
|
| ------------------------- | --------------------------------------------------- |
|
|
91
|
-
| **Auto** (default) | Automatically selects (3.
|
|
91
|
+
| **Auto** (default) | Automatically selects (3.7 Flash or 3.5 Flash Lite) |
|
|
92
|
+
| **Gemini 3.7 Flash** | Next-gen performance, reasoning & fast execution |
|
|
92
93
|
| **Gemini 3.6 Flash** | Everyday coding — fast and accurate |
|
|
93
94
|
| **Gemini 3.1 Pro** | Complex architectural changes |
|
|
94
95
|
| **Gemini 3.5 Flash Lite** | Best for speed and cost efficiency |
|
|
@@ -31,6 +31,8 @@ export declare class AsyncInputHandler {
|
|
|
31
31
|
private stopped;
|
|
32
32
|
/** Reference to the AbortController controlling the active AI request to trigger cancellations */
|
|
33
33
|
private ac;
|
|
34
|
+
/** Timeout reference for reattaching listener after prompting to avoid race conditions */
|
|
35
|
+
private reattachTimeout;
|
|
34
36
|
/**
|
|
35
37
|
* Registers the active AbortController for the current AI request.
|
|
36
38
|
* This is triggered when the user commands a process cancel (e.g., typing "stop").
|
|
@@ -45,6 +47,14 @@ export declare class AsyncInputHandler {
|
|
|
45
47
|
* @returns True if a text prompt is currently displayed, false otherwise.
|
|
46
48
|
*/
|
|
47
49
|
isCurrentlyPrompting(): boolean;
|
|
50
|
+
/**
|
|
51
|
+
* Checks if there are any queued user messages pending.
|
|
52
|
+
*/
|
|
53
|
+
hasQueuedMessages(): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Returns a copy of currently queued messages without clearing them.
|
|
56
|
+
*/
|
|
57
|
+
peek(): string[];
|
|
48
58
|
/**
|
|
49
59
|
* Blocks and waits until any active prompting action is completed.
|
|
50
60
|
* Guarantees terminal stdout is clean before resuming logs.
|
|
@@ -63,16 +73,21 @@ export declare class AsyncInputHandler {
|
|
|
63
73
|
private onData;
|
|
64
74
|
/**
|
|
65
75
|
* Starts intercepting keystrokes and enables raw terminal processing.
|
|
66
|
-
*
|
|
76
|
+
* Clears any stale queued messages and saves the original raw mode configuration.
|
|
67
77
|
*
|
|
68
78
|
* @param spinner - The current active Clack spinner UI reference, if any.
|
|
69
79
|
*/
|
|
70
80
|
start(spinner?: ReturnType<typeof p.spinner>): void;
|
|
71
81
|
/**
|
|
72
|
-
* Disables raw mode, stops intercepting keystrokes,
|
|
73
|
-
* the terminal stdin stream to its original raw/cooked state
|
|
82
|
+
* Disables raw mode, stops intercepting keystrokes, restores
|
|
83
|
+
* the terminal stdin stream to its original raw/cooked state, and
|
|
84
|
+
* completely clears the queued messages.
|
|
74
85
|
*/
|
|
75
86
|
stop(): void;
|
|
87
|
+
/**
|
|
88
|
+
* Clears all pending queued messages without modifying stream state.
|
|
89
|
+
*/
|
|
90
|
+
clear(): void;
|
|
76
91
|
/**
|
|
77
92
|
* Clears the spinner reference without stopping the input handler.
|
|
78
93
|
*/
|
|
@@ -1,6 +1,12 @@
|
|
|
1
1
|
import * as p from '@clack/prompts';
|
|
2
2
|
import pc from 'picocolors';
|
|
3
3
|
import { truncateForTerminal } from '../../utils/terminal.js';
|
|
4
|
+
if (process.stdin.setMaxListeners) {
|
|
5
|
+
process.stdin.setMaxListeners(50);
|
|
6
|
+
}
|
|
7
|
+
if (process.stdout.setMaxListeners) {
|
|
8
|
+
process.stdout.setMaxListeners(50);
|
|
9
|
+
}
|
|
4
10
|
/**
|
|
5
11
|
* Asynchronous Input Handler (AsyncInputHandler)
|
|
6
12
|
*
|
|
@@ -33,6 +39,8 @@ export class AsyncInputHandler {
|
|
|
33
39
|
stopped = true;
|
|
34
40
|
/** Reference to the AbortController controlling the active AI request to trigger cancellations */
|
|
35
41
|
ac = null;
|
|
42
|
+
/** Timeout reference for reattaching listener after prompting to avoid race conditions */
|
|
43
|
+
reattachTimeout = null;
|
|
36
44
|
/**
|
|
37
45
|
* Registers the active AbortController for the current AI request.
|
|
38
46
|
* This is triggered when the user commands a process cancel (e.g., typing "stop").
|
|
@@ -51,6 +59,18 @@ export class AsyncInputHandler {
|
|
|
51
59
|
isCurrentlyPrompting() {
|
|
52
60
|
return this.isPrompting;
|
|
53
61
|
}
|
|
62
|
+
/**
|
|
63
|
+
* Checks if there are any queued user messages pending.
|
|
64
|
+
*/
|
|
65
|
+
hasQueuedMessages() {
|
|
66
|
+
return this.queue.length > 0;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Returns a copy of currently queued messages without clearing them.
|
|
70
|
+
*/
|
|
71
|
+
peek() {
|
|
72
|
+
return [...this.queue];
|
|
73
|
+
}
|
|
54
74
|
/**
|
|
55
75
|
* Blocks and waits until any active prompting action is completed.
|
|
56
76
|
* Guarantees terminal stdout is clean before resuming logs.
|
|
@@ -72,7 +92,7 @@ export class AsyncInputHandler {
|
|
|
72
92
|
*/
|
|
73
93
|
onData = async (chunk) => {
|
|
74
94
|
try {
|
|
75
|
-
if (this.isPrompting)
|
|
95
|
+
if (this.stopped || this.isPrompting)
|
|
76
96
|
return;
|
|
77
97
|
const char = chunk.toString();
|
|
78
98
|
// Handle Ctrl+C (End of Text ASCII 0x03) immediately
|
|
@@ -99,6 +119,9 @@ export class AsyncInputHandler {
|
|
|
99
119
|
placeholder: '(Leave blank and press Enter to cancel)',
|
|
100
120
|
initialValue: char,
|
|
101
121
|
});
|
|
122
|
+
if (this.stopped) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
102
125
|
let wasAborted = false;
|
|
103
126
|
if (!p.isCancel(userInput) && userInput.trim()) {
|
|
104
127
|
const text = userInput.trim();
|
|
@@ -114,7 +137,7 @@ export class AsyncInputHandler {
|
|
|
114
137
|
p.log.info(pc.cyan(`📥 Queued message: "${text}"`));
|
|
115
138
|
}
|
|
116
139
|
}
|
|
117
|
-
if (this.spinner && !wasAborted) {
|
|
140
|
+
if (this.spinner && !wasAborted && !this.stopped) {
|
|
118
141
|
const resumeMsg = this.spinner._lastMessage || 'Resuming execution...';
|
|
119
142
|
this.spinner.start(resumeMsg);
|
|
120
143
|
}
|
|
@@ -128,9 +151,14 @@ export class AsyncInputHandler {
|
|
|
128
151
|
process.stdin.setRawMode(true);
|
|
129
152
|
}
|
|
130
153
|
process.stdin.resume();
|
|
154
|
+
if (this.reattachTimeout) {
|
|
155
|
+
clearTimeout(this.reattachTimeout);
|
|
156
|
+
}
|
|
131
157
|
// Small delay before reattaching listener to avoid capturing duplicate keypress frames
|
|
132
|
-
setTimeout(() => {
|
|
158
|
+
this.reattachTimeout = setTimeout(() => {
|
|
159
|
+
this.reattachTimeout = null;
|
|
133
160
|
if (!this.stopped) {
|
|
161
|
+
process.stdin.removeListener('data', this.onData);
|
|
134
162
|
process.stdin.on('data', this.onData);
|
|
135
163
|
}
|
|
136
164
|
this.isPrompting = false;
|
|
@@ -143,56 +171,53 @@ export class AsyncInputHandler {
|
|
|
143
171
|
};
|
|
144
172
|
/**
|
|
145
173
|
* Starts intercepting keystrokes and enables raw terminal processing.
|
|
146
|
-
*
|
|
174
|
+
* Clears any stale queued messages and saves the original raw mode configuration.
|
|
147
175
|
*
|
|
148
176
|
* @param spinner - The current active Clack spinner UI reference, if any.
|
|
149
177
|
*/
|
|
150
178
|
start(spinner) {
|
|
179
|
+
if (this.reattachTimeout) {
|
|
180
|
+
clearTimeout(this.reattachTimeout);
|
|
181
|
+
this.reattachTimeout = null;
|
|
182
|
+
}
|
|
151
183
|
this.stopped = false;
|
|
184
|
+
this.queue = [];
|
|
152
185
|
if (spinner) {
|
|
153
|
-
this.spinner
|
|
154
|
-
// Monkey-patch to track the latest message for un-pausing
|
|
155
|
-
if (!spinner._isPatched) {
|
|
156
|
-
;
|
|
157
|
-
spinner._isPatched = true;
|
|
158
|
-
spinner._lastMessage = 'Executing...';
|
|
159
|
-
const originalMessage = spinner.message.bind(spinner);
|
|
160
|
-
spinner.message = (msg) => {
|
|
161
|
-
if (msg) {
|
|
162
|
-
;
|
|
163
|
-
spinner._lastMessage = msg;
|
|
164
|
-
}
|
|
165
|
-
originalMessage(msg ? truncateForTerminal(msg) : msg);
|
|
166
|
-
};
|
|
167
|
-
const originalStart = spinner.start.bind(spinner);
|
|
168
|
-
spinner.start = (msg) => {
|
|
169
|
-
if (msg) {
|
|
170
|
-
;
|
|
171
|
-
spinner._lastMessage = msg;
|
|
172
|
-
}
|
|
173
|
-
originalStart(msg ? truncateForTerminal(msg) : msg);
|
|
174
|
-
};
|
|
175
|
-
}
|
|
186
|
+
this.setSpinner(spinner);
|
|
176
187
|
}
|
|
177
188
|
if (process.stdin.isTTY) {
|
|
178
189
|
this.originalRawMode = process.stdin.isRaw;
|
|
179
190
|
process.stdin.setRawMode(true);
|
|
180
191
|
}
|
|
181
192
|
process.stdin.resume();
|
|
193
|
+
process.stdin.removeListener('data', this.onData);
|
|
182
194
|
process.stdin.on('data', this.onData);
|
|
183
195
|
}
|
|
184
196
|
/**
|
|
185
|
-
* Disables raw mode, stops intercepting keystrokes,
|
|
186
|
-
* the terminal stdin stream to its original raw/cooked state
|
|
197
|
+
* Disables raw mode, stops intercepting keystrokes, restores
|
|
198
|
+
* the terminal stdin stream to its original raw/cooked state, and
|
|
199
|
+
* completely clears the queued messages.
|
|
187
200
|
*/
|
|
188
201
|
stop() {
|
|
189
202
|
this.stopped = true;
|
|
203
|
+
this.isPrompting = false;
|
|
204
|
+
if (this.reattachTimeout) {
|
|
205
|
+
clearTimeout(this.reattachTimeout);
|
|
206
|
+
this.reattachTimeout = null;
|
|
207
|
+
}
|
|
190
208
|
process.stdin.removeListener('data', this.onData);
|
|
191
209
|
if (process.stdin.isTTY) {
|
|
192
210
|
process.stdin.setRawMode(this.originalRawMode);
|
|
193
211
|
}
|
|
194
212
|
process.stdin.resume();
|
|
195
213
|
this.spinner = null;
|
|
214
|
+
this.queue = [];
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Clears all pending queued messages without modifying stream state.
|
|
218
|
+
*/
|
|
219
|
+
clear() {
|
|
220
|
+
this.queue = [];
|
|
196
221
|
}
|
|
197
222
|
/**
|
|
198
223
|
* Clears the spinner reference without stopping the input handler.
|
|
@@ -13,6 +13,7 @@ import { renderTerminalMarkdown } from '../../utils/terminal.js';
|
|
|
13
13
|
import { readPaste } from '../../utils/paste.js';
|
|
14
14
|
import { setApprovalMode, getApprovalMode, isSubAgentsEnabled, setSubAgentsEnabled } from '../agent-tools.js';
|
|
15
15
|
import { ProxyClient, getAndResetTurnUsage } from '../proxyClient.js';
|
|
16
|
+
import { checkByokSubscription } from '../auth.js';
|
|
16
17
|
import { GEMINI_MODELS, isByokEnabled } from '../../utils/config.js';
|
|
17
18
|
import { loadCredentials, updateCredentialField } from '../../utils/credentialStore.js';
|
|
18
19
|
import { getGlobalActiveModel, setGlobalActiveModel, ProxyChatSession } from '../ai.js';
|
|
@@ -25,7 +26,7 @@ import { getGlobalActiveModel, setGlobalActiveModel, ProxyChatSession } from '..
|
|
|
25
26
|
* - `/paste` : Enter multi-line paste mode using EOF tracking (`Ctrl+D` submission).
|
|
26
27
|
* - `/plan` : Toggle AI step-by-step implementation planning mode.
|
|
27
28
|
* - `/clear` : Clear conversation history, wipe terminal screen, and reset CLI header.
|
|
28
|
-
* - `/models` : Hot-swap the active generative AI model (Gemini 3.1 Pro, Gemini 3.6 Flash, Gemini 3.5 Flash-Lite, Auto routing).
|
|
29
|
+
* - `/models` : Hot-swap the active generative AI model (Gemini 3.1 Pro, Gemini 3.7 Flash, Gemini 3.6 Flash, Gemini 3.5 Flash-Lite, Auto routing).
|
|
29
30
|
* - `/debug` : Toggle internal agent telemetry and diagnostic logging.
|
|
30
31
|
* - `/auto-approve`: Toggle automatic confirmation skipping for terminal shell execution commands.
|
|
31
32
|
* - `/sub-agents` : Toggle MMAAK Engine for parallel investigation sub-agent orchestration.
|
|
@@ -120,10 +121,15 @@ export async function handleSlashCommand(command, context) {
|
|
|
120
121
|
// label: 'Claude 5 Sonnet',
|
|
121
122
|
// hint: 'Best for raw speed and cost efficiency',
|
|
122
123
|
// },
|
|
124
|
+
{
|
|
125
|
+
value: 'gemini-3.7-flash',
|
|
126
|
+
label: 'Gemini 3.7 Flash',
|
|
127
|
+
hint: 'Next-gen reasoning, speed & balanced performance',
|
|
128
|
+
},
|
|
123
129
|
{
|
|
124
130
|
value: 'gemini-3.6-flash',
|
|
125
131
|
label: 'Gemini 3.6 Flash',
|
|
126
|
-
hint: '
|
|
132
|
+
hint: 'Everyday coding — fast and accurate',
|
|
127
133
|
},
|
|
128
134
|
{
|
|
129
135
|
value: 'gemini-3.5-flash-lite',
|
|
@@ -133,9 +139,9 @@ export async function handleSlashCommand(command, context) {
|
|
|
133
139
|
{
|
|
134
140
|
value: 'auto',
|
|
135
141
|
label: 'Auto (Flash-Lite / Flash)',
|
|
136
|
-
hint: 'Dynamically routes between Gemini 3.5 Flash-Lite and Gemini 3.
|
|
142
|
+
hint: 'Dynamically routes between Gemini 3.5 Flash-Lite and Gemini 3.7 Flash based on prompt complexity',
|
|
137
143
|
},
|
|
138
|
-
].filter(o => !(byokEnabled && o.value.includes('claude')));
|
|
144
|
+
].filter((o) => !(byokEnabled && o.value.includes('claude')));
|
|
139
145
|
const selectedModel = await p['select']({
|
|
140
146
|
message: `Select AI Model (Current: ${pc.cyan(currentModel)})`,
|
|
141
147
|
initialValue: currentModel,
|
|
@@ -1046,12 +1052,29 @@ ${diffOut}
|
|
|
1046
1052
|
if (!byokEnabled && !creds.geminiApiKey) {
|
|
1047
1053
|
p.log.error('You must set an API key before enabling BYOK mode.');
|
|
1048
1054
|
}
|
|
1055
|
+
else if (!byokEnabled) {
|
|
1056
|
+
const subCheck = await checkByokSubscription();
|
|
1057
|
+
if (!subCheck.active) {
|
|
1058
|
+
p.log.error(subCheck.message ||
|
|
1059
|
+
'A $3.99/month BYOK Subscription is required. Visit https://www.minovativemind.dev/pricing');
|
|
1060
|
+
}
|
|
1061
|
+
else {
|
|
1062
|
+
await updateCredentialField('useByok', true);
|
|
1063
|
+
p.log.success(`BYOK mode is now ${pc.green('Enabled')}`);
|
|
1064
|
+
}
|
|
1065
|
+
}
|
|
1049
1066
|
else {
|
|
1050
|
-
await updateCredentialField('useByok',
|
|
1051
|
-
p.log.success(`BYOK mode is now ${
|
|
1067
|
+
await updateCredentialField('useByok', false);
|
|
1068
|
+
p.log.success(`BYOK mode is now ${pc.yellow('Disabled')}`);
|
|
1052
1069
|
}
|
|
1053
1070
|
}
|
|
1054
1071
|
else if (action === 'set') {
|
|
1072
|
+
const subCheck = await checkByokSubscription();
|
|
1073
|
+
if (!subCheck.active) {
|
|
1074
|
+
p.log.error(subCheck.message ||
|
|
1075
|
+
'A $3.99/month BYOK Subscription is required to use your own API key. Please visit https://www.minovativemind.dev/pricing to subscribe. The $3.99 is to cover account maintance for you.');
|
|
1076
|
+
return { shouldContinue: true };
|
|
1077
|
+
}
|
|
1055
1078
|
const key = await p['password']({
|
|
1056
1079
|
message: 'Enter your Google AI Studio API Key:',
|
|
1057
1080
|
validate: (v) => (!v ? 'API key is required' : undefined),
|
|
@@ -8,12 +8,14 @@
|
|
|
8
8
|
* @param error Optional error message from local validation to guide the AI.
|
|
9
9
|
* @returns The fixed content, or undefined if it was completely valid or couldn't be fixed.
|
|
10
10
|
*/
|
|
11
|
-
export declare function validateAndFixSyntax(content: string, filePath: string, error?: string): Promise<string | undefined>;
|
|
11
|
+
export declare function validateAndFixSyntax(content: string, filePath: string, error?: string, abortSignal?: AbortSignal): Promise<string | undefined>;
|
|
12
12
|
export interface AIFuzzyMatchOptions {
|
|
13
13
|
/** Optional custom Gemini model override. Defaults to GEMINI_MODELS.FLASH. */
|
|
14
14
|
model?: string;
|
|
15
15
|
/** Whether to validate and fix syntax on the updated content. Defaults to true. */
|
|
16
16
|
validateSyntax?: boolean;
|
|
17
|
+
/** Optional AbortSignal to cancel execution immediately. */
|
|
18
|
+
abortSignal?: AbortSignal;
|
|
17
19
|
}
|
|
18
20
|
export interface AIFuzzyMatchResult {
|
|
19
21
|
/** Indicates whether the fuzzy search matching and edit application succeeded. */
|
|
@@ -68,7 +68,9 @@ function cleanOutput(raw) {
|
|
|
68
68
|
* @param error Optional error message from local validation to guide the AI.
|
|
69
69
|
* @returns The fixed content, or undefined if it was completely valid or couldn't be fixed.
|
|
70
70
|
*/
|
|
71
|
-
export async function validateAndFixSyntax(content, filePath, error) {
|
|
71
|
+
export async function validateAndFixSyntax(content, filePath, error, abortSignal) {
|
|
72
|
+
if (abortSignal?.aborted)
|
|
73
|
+
return undefined;
|
|
72
74
|
// 1. First run fast local validation to check if content is already valid or gather error details
|
|
73
75
|
const localResult = localValidate(filePath, content);
|
|
74
76
|
if (localResult.isValid && !error) {
|
|
@@ -108,7 +110,7 @@ ${win.snippet}
|
|
|
108
110
|
|
|
109
111
|
Please fix the syntax error in the snippet above and return ONLY the raw repaired code snippet:`;
|
|
110
112
|
try {
|
|
111
|
-
const result = await snippetChat.sendMessage(snippetPrompt);
|
|
113
|
+
const result = await snippetChat.sendMessage(snippetPrompt, undefined, abortSignal);
|
|
112
114
|
const repairedSnippet = cleanOutput(result.response.text());
|
|
113
115
|
if (repairedSnippet && repairedSnippet !== win.snippet) {
|
|
114
116
|
const candidateContent = content.slice(0, win.startPos) + repairedSnippet + content.slice(win.endPos);
|
|
@@ -123,6 +125,8 @@ Please fix the syntax error in the snippet above and return ONLY the raw repaire
|
|
|
123
125
|
}
|
|
124
126
|
}
|
|
125
127
|
}
|
|
128
|
+
if (abortSignal?.aborted)
|
|
129
|
+
return undefined;
|
|
126
130
|
// 3. Full file repair strategy (for smaller files or when snippet repair was insufficient)
|
|
127
131
|
const fullSystemInstruction = `
|
|
128
132
|
<identity>
|
|
@@ -150,7 +154,7 @@ ${effectiveError}
|
|
|
150
154
|
Content:
|
|
151
155
|
${content}`;
|
|
152
156
|
try {
|
|
153
|
-
const result = await fullChat.sendMessage(fullPrompt);
|
|
157
|
+
const result = await fullChat.sendMessage(fullPrompt, undefined, abortSignal);
|
|
154
158
|
const output = cleanOutput(result.response.text());
|
|
155
159
|
if (output === 'VALID' || output === '' || output === content) {
|
|
156
160
|
return undefined;
|
|
@@ -185,6 +189,12 @@ export async function aiFuzzyMatch(fileContent, searchContent, replaceContent, f
|
|
|
185
189
|
error: 'File content and search content must not be empty.',
|
|
186
190
|
};
|
|
187
191
|
}
|
|
192
|
+
if (options.abortSignal?.aborted) {
|
|
193
|
+
return {
|
|
194
|
+
success: false,
|
|
195
|
+
error: 'Operation aborted',
|
|
196
|
+
};
|
|
197
|
+
}
|
|
188
198
|
const model = options.model || GEMINI_MODELS.FLASH;
|
|
189
199
|
const shouldValidateSyntax = options.validateSyntax !== false;
|
|
190
200
|
const systemInstruction = `
|
|
@@ -217,7 +227,7 @@ ${replaceContent}
|
|
|
217
227
|
File Content:
|
|
218
228
|
${fileContent}`;
|
|
219
229
|
try {
|
|
220
|
-
const response = await chat.sendMessage(prompt);
|
|
230
|
+
const response = await chat.sendMessage(prompt, undefined, options.abortSignal);
|
|
221
231
|
const rawOutput = response.response.text();
|
|
222
232
|
const output = cleanOutput(rawOutput);
|
|
223
233
|
if (output === 'UNMATCHED' || !output || output === fileContent) {
|
|
@@ -231,7 +241,7 @@ ${fileContent}`;
|
|
|
231
241
|
const valResult = localValidate(filePath, finalContent);
|
|
232
242
|
if (!valResult.isValid) {
|
|
233
243
|
// Attempt automatic syntax repair on AI output if local validation detected syntax error
|
|
234
|
-
const repaired = await validateAndFixSyntax(finalContent, filePath, valResult.error);
|
|
244
|
+
const repaired = await validateAndFixSyntax(finalContent, filePath, valResult.error, options.abortSignal);
|
|
235
245
|
if (repaired) {
|
|
236
246
|
finalContent = repaired;
|
|
237
247
|
}
|
|
@@ -264,7 +264,7 @@ export async function processResponse(chat, result, workspaceRoot, inputHandler,
|
|
|
264
264
|
additionalText = `[USER INTERRUPTION] The user sent the following message during your execution:\n"${queuedMsg}"\n\nPlease incorporate this feedback into your ongoing work. Address the user's message, but DO NOT lose track of your original overall plan or focus. After addressing this interruption, continue with your broader objective.`;
|
|
265
265
|
p.log.info(pc.cyan(`Sending queued message to AI...`));
|
|
266
266
|
// Dynamically upgrade agent permissions/intent to EXECUTE mode if the interrupted instruction requires system modifications
|
|
267
|
-
const newIntent = await routeIntent(queuedMsg);
|
|
267
|
+
const newIntent = await routeIntent(queuedMsg, '', abortSignal);
|
|
268
268
|
if (agentState.targetAgent === 'CHAT') {
|
|
269
269
|
if (newIntent.targetAgent === 'EXECUTE' || newIntent.needsContext) {
|
|
270
270
|
agentState.targetAgent = 'EXECUTE';
|
package/dist/services/agent.d.ts
CHANGED
|
@@ -125,4 +125,4 @@ export declare const HISTORY_SUMMARIZATION_THRESHOLD = 50;
|
|
|
125
125
|
* @param chat - The active ProxyChatSession instance.
|
|
126
126
|
* @returns A promise resolving to true if history was summarized and updated; false otherwise.
|
|
127
127
|
*/
|
|
128
|
-
export declare function summarizeHistoryIfNeeded(chat: any): Promise<boolean>;
|
|
128
|
+
export declare function summarizeHistoryIfNeeded(chat: any, abortSignal?: AbortSignal): Promise<boolean>;
|