@sschepis/robodev 1.0.0

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.
@@ -0,0 +1,126 @@
1
+ // Code Validator
2
+ // Performs real-time validation (linting, type-checking) on files
3
+ // to provide immediate feedback to AI agents.
4
+
5
+ import { exec } from 'child_process';
6
+ import util from 'util';
7
+ import path from 'path';
8
+ import fs from 'fs';
9
+ import { consoleStyler } from '../ui/console-styler.mjs';
10
+
11
+ const execPromise = util.promisify(exec);
12
+
13
+ export class CodeValidator {
14
+ constructor(workingDir) {
15
+ this.workingDir = workingDir;
16
+ }
17
+
18
+ /**
19
+ * Validates a file based on its extension.
20
+ * @param {string} filePath - Relative path to the file
21
+ * @returns {Promise<string|null>} - Formatted error string or null if valid
22
+ */
23
+ async validateFile(filePath) {
24
+ const ext = path.extname(filePath).toLowerCase();
25
+ const fullPath = path.resolve(this.workingDir, filePath);
26
+
27
+ // Only validate if file exists
28
+ if (!fs.existsSync(fullPath)) {
29
+ return null;
30
+ }
31
+
32
+ try {
33
+ if (['.ts', '.tsx'].includes(ext)) {
34
+ return await this.validateTypeScript(filePath);
35
+ } else if (['.js', '.mjs', '.jsx'].includes(ext)) {
36
+ return await this.validateJavaScript(filePath);
37
+ }
38
+ } catch (error) {
39
+ // If validation command fails (e.g. tsc not found), log it but don't break the tool
40
+ consoleStyler.log('error', `Validation tool error: ${error.message}`);
41
+ return `(Validation tool failed: ${error.message})`;
42
+ }
43
+
44
+ return null;
45
+ }
46
+
47
+ async validateTypeScript(filePath) {
48
+ // Run tsc on the specific file
49
+ // --noEmit: Don't generate JS
50
+ // --skipLibCheck: Speed up
51
+ // --allowJs: Allow JS files in check if needed
52
+ // --pretty false: output parseable text
53
+ // We use npx to use local or cached tsc
54
+ // Increased resilience with project root finding logic could go here,
55
+ // but cwd execution is usually sufficient for relative paths.
56
+
57
+ const cmd = `npx tsc --noEmit --skipLibCheck --allowJs --target es2020 --moduleResolution node --pretty false "${filePath}"`;
58
+
59
+ try {
60
+ await execPromise(cmd, { cwd: this.workingDir, timeout: 30000 }); // 30s timeout
61
+ return null; // Success = no output/errors
62
+ } catch (error) {
63
+ // timeout error
64
+ if (error.signal === 'SIGTERM') {
65
+ return `Validation timed out after 30s for ${filePath}`;
66
+ }
67
+
68
+ // tsc exits with non-zero if errors found
69
+ // stdout contains the errors
70
+ const output = error.stdout || error.stderr;
71
+ return this.formatOutput(output, filePath);
72
+ }
73
+ }
74
+
75
+ async validateJavaScript(filePath) {
76
+ // Try ESLint first
77
+ try {
78
+ const eslintCmd = `npx eslint --no-color --format unix "${filePath}"`;
79
+ await execPromise(eslintCmd, { cwd: this.workingDir, timeout: 20000 });
80
+ return null;
81
+ } catch (error) {
82
+ // If eslint fails due to config missing or errors found
83
+ if (error.stdout && (error.stdout.includes(filePath) || error.stdout.includes('error'))) {
84
+ return this.formatOutput(error.stdout, filePath);
85
+ }
86
+
87
+ // Fallback: Syntax check with node
88
+ try {
89
+ // node -c checks syntax
90
+ const nodeCmd = `node --check "${filePath}"`;
91
+ await execPromise(nodeCmd, { cwd: this.workingDir, timeout: 10000 });
92
+ return null;
93
+ } catch (syntaxError) {
94
+ return `Syntax Error: ${syntaxError.stderr.trim()}`;
95
+ }
96
+ }
97
+ }
98
+
99
+ formatOutput(output, filePath) {
100
+ if (!output) return null;
101
+
102
+ // Clean up ANSI codes if any remain (though we try to suppress them)
103
+ const cleanOutput = output.replace(/\u001b\[[0-9;]*m/g, '');
104
+
105
+ const lines = cleanOutput.split('\n');
106
+
107
+ // Filter lines relevant to the file or generic errors
108
+ // We want to capture the specific error lines, usually formatted like "file.ts(1,1): error ..."
109
+ const fileName = path.basename(filePath);
110
+ const relevantLines = lines.filter(line =>
111
+ line.includes(fileName) ||
112
+ line.includes('error TS') ||
113
+ (line.includes('Error:') && !line.includes('Validation tool error'))
114
+ );
115
+
116
+ if (relevantLines.length === 0) return null;
117
+
118
+ // Limit output size to prevent context flooding
119
+ const MAX_LINES = 15;
120
+ if (relevantLines.length > MAX_LINES) {
121
+ return relevantLines.slice(0, MAX_LINES).join('\n') + `\n... (${relevantLines.length - MAX_LINES} more errors truncated)`;
122
+ }
123
+
124
+ return relevantLines.join('\n');
125
+ }
126
+ }
@@ -0,0 +1,248 @@
1
+ // Quality evaluation system
2
+ // Handles response quality evaluation and retry logic
3
+
4
+ import { consoleStyler } from '../ui/console-styler.mjs';
5
+ import { ENHANCEMENT_TOOLS } from '../tools/tool-definitions.mjs';
6
+ import { callProvider } from '../core/ai-provider.mjs';
7
+
8
+ export class QualityEvaluator {
9
+ constructor(endpoint) {
10
+ this.endpoint = endpoint; // kept for backward compatibility
11
+ this.qualityIssue = null;
12
+ this.retryAttempts = 0;
13
+ this.maxRetryAttempts = 2;
14
+ }
15
+
16
+ // Evaluate response quality using AI
17
+ async evaluateResponse(userInput, finalResponse, toolCallsSummary, toolResults, createSystemPrompt, workingDir, workspace) {
18
+ // Don't evaluate if we've already exceeded retry attempts
19
+ if (this.retryAttempts >= this.maxRetryAttempts) {
20
+ consoleStyler.log('quality', `Skipping quality evaluation - max retry attempts (${this.maxRetryAttempts}) reached`);
21
+ return null;
22
+ }
23
+
24
+ consoleStyler.log('quality', 'Preparing comprehensive quality evaluation context...');
25
+
26
+ // Create comprehensive context for quality evaluation
27
+ let evaluationContext = `Please evaluate the quality of this AI response using the evaluate_response_quality tool:
28
+
29
+ ORIGINAL QUERY: "${userInput}"
30
+
31
+ AI RESPONSE: "${finalResponse}"`;
32
+
33
+ if (toolCallsSummary.length > 0) {
34
+ evaluationContext += `
35
+
36
+ TOOLS USED BY AI:`;
37
+ toolCallsSummary.forEach((call, i) => {
38
+ evaluationContext += `
39
+ ${i + 1}. ${call.tool}(${Object.entries(call.parameters).map(([k,v]) => `${k}: ${JSON.stringify(v)}`).join(', ')})`;
40
+ });
41
+
42
+ if (toolResults.length > 0) {
43
+ evaluationContext += `
44
+
45
+ TOOL RESULTS:`;
46
+ toolResults.forEach((result, i) => {
47
+ let resultStr = typeof result.result === 'string' ? result.result : JSON.stringify(result.result);
48
+ if (resultStr === undefined) resultStr = 'undefined';
49
+ evaluationContext += `
50
+ ${i + 1}. ${result.tool}: ${resultStr.substring(0, 200)}${resultStr.length > 200 ? '...' : ''}`;
51
+ });
52
+ }
53
+ }
54
+
55
+ evaluationContext += `
56
+
57
+ EVALUATION CRITERIA:
58
+ - 10 = Perfect response that fully addresses the query (consider both text response AND tool usage)
59
+ - 7-9 = Good response with minor issues
60
+ - 4-6 = Adequate but could be improved
61
+ - 1-3 = Poor response that doesn't address the query properly
62
+
63
+ IMPORTANT: When evaluating, consider BOTH the text response AND the tools that were called. If the user asked for something to be done and the AI called the appropriate tools successfully, that should be reflected in the quality score even if the text response is brief.
64
+
65
+ If rating < 4, provide specific remedy suggestions.`;
66
+
67
+ // Create a quality evaluation request
68
+ const qualityCheckHistory = [
69
+ { role: 'system', content: createSystemPrompt(workingDir, workspace) },
70
+ {
71
+ role: 'user',
72
+ content: evaluationContext
73
+ }
74
+ ];
75
+
76
+ consoleStyler.log('quality', `Evaluating response quality with ${toolCallsSummary.length} tool calls and ${toolResults.length} tool results`);
77
+
78
+ try {
79
+ // Import config dynamically to avoid circular dependencies
80
+ const { config } = await import('../config.mjs');
81
+
82
+ const qualityResult = await callProvider({
83
+ model: config.ai.model,
84
+ messages: qualityCheckHistory,
85
+ tools: ENHANCEMENT_TOOLS,
86
+ tool_choice: { type: "function", function: { name: "evaluate_response_quality" } },
87
+ temperature: 0.1,
88
+ reasoning_effort: "high" // Quality evaluation always uses high reasoning
89
+ });
90
+
91
+ if (qualityResult && qualityResult.choices) {
92
+ const qualityMessage = qualityResult.choices[0].message;
93
+
94
+ if (qualityMessage.tool_calls && qualityMessage.tool_calls.length > 0) {
95
+ for (const toolCall of qualityMessage.tool_calls) {
96
+ if (toolCall.function.name === 'evaluate_response_quality') {
97
+ const args = JSON.parse(toolCall.function.arguments);
98
+ const { quality_rating = 0, evaluation_reasoning = "No reasoning provided", remedy_suggestion = "" } = args;
99
+
100
+ consoleStyler.log('quality', `Quality evaluation results:`);
101
+ consoleStyler.log('quality', ` Rating: ${quality_rating}/10`, { indent: true });
102
+ if (evaluation_reasoning && typeof evaluation_reasoning === 'string') {
103
+ consoleStyler.log('quality', ` Reasoning: ${evaluation_reasoning.substring(0, 100)}...`, { indent: true });
104
+ }
105
+ if (remedy_suggestion && typeof remedy_suggestion === 'string') {
106
+ consoleStyler.log('quality', ` Remedy: ${remedy_suggestion.substring(0, 100)}...`, { indent: true });
107
+ }
108
+
109
+ return {
110
+ rating: quality_rating,
111
+ reasoning: evaluation_reasoning,
112
+ remedy: remedy_suggestion,
113
+ needsRetry: quality_rating < 4 && remedy_suggestion
114
+ };
115
+ }
116
+ }
117
+ }
118
+ }
119
+ } catch (qualityError) {
120
+ consoleStyler.log('error', `Quality evaluation failed: ${qualityError.message}`, { box: true });
121
+ }
122
+
123
+ consoleStyler.log('quality', 'Quality evaluation completed with no actionable results');
124
+ return null;
125
+ }
126
+
127
+ // Check if retry is needed based on quality evaluation
128
+ shouldRetry(qualityResult) {
129
+ if (!qualityResult || !qualityResult.needsRetry) {
130
+ return false;
131
+ }
132
+
133
+ if (this.retryAttempts >= this.maxRetryAttempts) {
134
+ consoleStyler.log('quality', `Maximum retry attempts (${this.maxRetryAttempts}) reached`);
135
+ return false;
136
+ }
137
+
138
+ return true;
139
+ }
140
+
141
+ // Create improved prompt for retry
142
+ createRetryPrompt(userInput, finalResponse, qualityResult) {
143
+ this.retryAttempts++;
144
+
145
+ consoleStyler.log('quality', `Poor quality detected (${qualityResult.rating}/10)`, { box: true });
146
+ consoleStyler.log('quality', `Remedy: ${qualityResult.remedy}`);
147
+
148
+ // Store quality issue for reference
149
+ this.qualityIssue = {
150
+ rating: qualityResult.rating,
151
+ reasoning: qualityResult.reasoning,
152
+ remedy: qualityResult.remedy,
153
+ original_query: userInput,
154
+ poor_response: finalResponse
155
+ };
156
+
157
+ // Create improved prompt with remedy
158
+ const improvedPrompt = `${userInput}
159
+
160
+ PREVIOUS RESPONSE WAS INADEQUATE (rated ${qualityResult.rating}/10):
161
+ "${finalResponse}"
162
+
163
+ REMEDY REQUIRED: ${qualityResult.remedy}
164
+
165
+ Please provide a better response that addresses these quality issues.`;
166
+
167
+ return improvedPrompt;
168
+ }
169
+
170
+ // Reset quality evaluation state
171
+ reset() {
172
+ this.qualityIssue = null;
173
+ this.retryAttempts = 0;
174
+ }
175
+
176
+ // Get current quality issue
177
+ getQualityIssue() {
178
+ return this.qualityIssue;
179
+ }
180
+
181
+ // Get retry attempt count
182
+ getRetryAttempts() {
183
+ return this.retryAttempts;
184
+ }
185
+
186
+ // Set quality issue manually (for tool execution)
187
+ setQualityIssue(issue) {
188
+ this.qualityIssue = issue;
189
+ }
190
+
191
+ // Check if we're currently in a retry situation
192
+ isRetrying() {
193
+ return this.retryAttempts > 0;
194
+ }
195
+
196
+ // Get quality evaluation summary for logging
197
+ getQualitySummary() {
198
+ if (!this.qualityIssue) {
199
+ return "No quality issues detected";
200
+ }
201
+
202
+ return `Quality issue: ${this.qualityIssue.rating}/10 - ${this.qualityIssue.remedy}`;
203
+ }
204
+
205
+ // Handle quality evaluation result from tool execution
206
+ handleQualityToolResult(args) {
207
+ const { quality_rating = 0, evaluation_reasoning = "No reasoning", remedy_suggestion = "" } = args;
208
+
209
+ if (quality_rating < 4) {
210
+ console.log(`\x1b[31m[QUALITY] Poor quality detected (${quality_rating}/10)\x1b[0m`);
211
+ if (remedy_suggestion) {
212
+ console.log(`\x1b[33m[QUALITY] Remedy: ${remedy_suggestion}\x1b[0m`);
213
+ }
214
+
215
+ // Store quality issue for retry
216
+ this.qualityIssue = {
217
+ rating: quality_rating,
218
+ reasoning: evaluation_reasoning,
219
+ remedy: remedy_suggestion
220
+ };
221
+
222
+ return `Quality rating ${quality_rating}/10 - retry needed with remedy: ${remedy_suggestion}`;
223
+ } else {
224
+ return `Quality rating ${quality_rating}/10 - response approved`;
225
+ }
226
+ }
227
+
228
+ // Extract tool call summary for quality evaluation
229
+ extractToolCallsSummary(history) {
230
+ return history
231
+ .filter(msg => msg.tool_calls && msg.tool_calls.length > 0)
232
+ .map(msg => msg.tool_calls.map(call => ({
233
+ tool: call.function.name,
234
+ parameters: JSON.parse(call.function.arguments)
235
+ })))
236
+ .flat();
237
+ }
238
+
239
+ // Extract tool results for quality evaluation
240
+ extractToolResults(history) {
241
+ return history
242
+ .filter(msg => msg.role === 'tool')
243
+ .map(msg => ({
244
+ tool: msg.name,
245
+ result: msg.content
246
+ }));
247
+ }
248
+ }
@@ -0,0 +1,258 @@
1
+ // Reasoning system for determining appropriate effort levels
2
+ // This module handles all logic related to determining how much reasoning effort to apply
3
+
4
+ import { consoleStyler } from '../ui/console-styler.mjs';
5
+
6
+ export class ReasoningSystem {
7
+ constructor() {
8
+ this.errorHistory = [];
9
+ this.predictedReasoning = null;
10
+ this.reasoningJustification = null;
11
+ }
12
+
13
+ // Determine reasoning effort based on task complexity
14
+ determineReasoningEffort(userInput, context = {}) {
15
+ // Check for user preference first
16
+ const userPreference = this.parseUserReasoningPreference(userInput);
17
+ if (userPreference) return userPreference;
18
+
19
+ // Check for complexity indicators
20
+ const complexityIndicators = {
21
+ high: [
22
+ /debug|troubleshoot|analyze error/i,
23
+ /architect|design|plan/i,
24
+ /optimize|refactor|improve performance/i,
25
+ /complex|complicated|multi-step/i,
26
+ /why|explain|understand/i,
27
+ /embellish|enhance|improve/i
28
+ ],
29
+ medium: [
30
+ /create|build|implement/i,
31
+ /fix|solve|resolve/i,
32
+ /convert|transform/i,
33
+ /test|validate/i,
34
+ /fetch|scrape|extract/i
35
+ ],
36
+ low: [
37
+ /simple|basic|quick/i,
38
+ /list|show|display/i,
39
+ /check|verify/i,
40
+ /format|clean/i,
41
+ /update status/i
42
+ ]
43
+ };
44
+
45
+ // Check if we're in a recovery/retry situation
46
+ if (context.isRetry || context.errorCount > 0) {
47
+ consoleStyler.log('reasoning', 'Using high effort due to retry/error context');
48
+ return "high";
49
+ }
50
+
51
+ // Check if we have a todo list with many steps
52
+ if (context.todoCount && context.todoCount > 5) {
53
+ consoleStyler.log('reasoning', 'Using high effort due to complex multi-step task');
54
+ return "high";
55
+ }
56
+
57
+ // Pattern matching
58
+ for (const [level, patterns] of Object.entries(complexityIndicators)) {
59
+ if (patterns.some(pattern => pattern.test(userInput))) {
60
+ consoleStyler.log('reasoning', `Detected ${level} complexity from input patterns`);
61
+ return level;
62
+ }
63
+ }
64
+
65
+ return "medium"; // Default
66
+ }
67
+
68
+ // Parse user preference for reasoning level
69
+ parseUserReasoningPreference(userInput) {
70
+ const reasoningHints = {
71
+ high: /\b(carefully|thoroughly|deeply|detailed|comprehensive)\b/i,
72
+ low: /\b(quickly|briefly|simple|fast|quick)\b/i
73
+ };
74
+
75
+ for (const [level, pattern] of Object.entries(reasoningHints)) {
76
+ if (pattern.test(userInput)) {
77
+ consoleStyler.log('reasoning', `User requested ${level} effort`);
78
+ return level;
79
+ }
80
+ }
81
+
82
+ return null; // No preference detected
83
+ }
84
+
85
+ // Get adaptive reasoning based on error history
86
+ getAdaptiveReasoningEffort() {
87
+ const recentErrors = this.errorHistory.filter(err => {
88
+ const errorTime = new Date(err.timestamp);
89
+ const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
90
+ return errorTime > fiveMinutesAgo;
91
+ });
92
+
93
+ if (recentErrors.length >= 3) {
94
+ consoleStyler.log('reasoning', `Using high effort due to ${recentErrors.length} recent errors`);
95
+ return "high";
96
+ }
97
+ if (recentErrors.length >= 1) {
98
+ consoleStyler.log('reasoning', 'Using medium effort due to recent errors');
99
+ return "medium";
100
+ }
101
+ return "low";
102
+ }
103
+
104
+ // Get tool-specific reasoning level
105
+ getToolSpecificReasoning(toolName) {
106
+ const toolReasoningMap = {
107
+ 'analyze_and_recover': 'high', // Error recovery needs deep thinking
108
+ 'embellish_request': 'high', // Planning needs thorough analysis
109
+ 'execute_javascript': 'medium', // Code execution is straightforward
110
+ 'create_todo_list': 'high', // Planning multi-step tasks
111
+ 'update_todo_status': 'low', // Simple status update
112
+ 'evaluate_response_quality': 'high' // Quality evaluation needs careful analysis
113
+ };
114
+
115
+ const level = toolReasoningMap[toolName] || 'medium';
116
+ consoleStyler.log('reasoning', `Using ${level} effort for tool: ${toolName}`);
117
+ return level;
118
+ }
119
+
120
+ // Get context-aware reasoning based on conversation state
121
+ getContextAwareReasoning(context = {}) {
122
+ const { historyLength = 0, toolCallCount = 0, pendingSteps = 0 } = context;
123
+
124
+ // Long conversations might need more reasoning
125
+ if (historyLength > 20) {
126
+ consoleStyler.log('reasoning', 'Using high effort due to long conversation history');
127
+ return "high";
128
+ }
129
+
130
+ // Multiple tool calls in history suggest complex task
131
+ if (toolCallCount > 5) {
132
+ consoleStyler.log('reasoning', 'Using high effort due to multiple tool calls');
133
+ return "high";
134
+ }
135
+
136
+ // Check if we're in the middle of a multi-step process
137
+ if (pendingSteps > 3) {
138
+ consoleStyler.log('reasoning', `Using high effort due to ${pendingSteps} pending steps`);
139
+ return "high";
140
+ }
141
+
142
+ return "medium";
143
+ }
144
+
145
+ // Combine all reasoning strategies to determine final effort level
146
+ determineOptimalReasoning(userInput = null, toolName = null, context = {}) {
147
+ // Priority order for reasoning determination
148
+ // 1. Tool-specific reasoning (if tool is being used)
149
+ if (toolName) {
150
+ return this.getToolSpecificReasoning(toolName);
151
+ }
152
+
153
+ // 2. Error-based adaptive reasoning
154
+ const errorBasedReasoning = this.getAdaptiveReasoningEffort();
155
+ if (errorBasedReasoning === "high") {
156
+ return errorBasedReasoning;
157
+ }
158
+
159
+ // 3. Context-aware reasoning
160
+ const contextReasoning = this.getContextAwareReasoning(context);
161
+ if (contextReasoning === "high") {
162
+ return contextReasoning;
163
+ }
164
+
165
+ // 4. Task complexity reasoning
166
+ const complexityReasoning = this.determineReasoningEffort(userInput || '', {
167
+ isRetry: context.retryAttempts > 0,
168
+ errorCount: this.errorHistory.length,
169
+ todoCount: context.todoCount
170
+ });
171
+
172
+ // Return the highest reasoning level among all strategies
173
+ const levels = [errorBasedReasoning, contextReasoning, complexityReasoning];
174
+ if (levels.includes("high")) return "high";
175
+ if (levels.includes("medium")) return "medium";
176
+ return "low";
177
+ }
178
+
179
+ // Add error to history for adaptive reasoning
180
+ addError(error) {
181
+ this.errorHistory.push({
182
+ error: error.message,
183
+ timestamp: new Date().toISOString()
184
+ });
185
+ }
186
+
187
+ // Set predicted reasoning from embellishment
188
+ setPredictedReasoning(reasoning, justification) {
189
+ this.predictedReasoning = reasoning;
190
+ this.reasoningJustification = justification;
191
+ consoleStyler.log('reasoning', `Predicted: ${reasoning} - ${justification}`);
192
+ }
193
+
194
+ // Get predicted reasoning
195
+ getPredictedReasoning() {
196
+ return this.predictedReasoning;
197
+ }
198
+
199
+ // Get simplified reasoning with minimal logic for performance
200
+ getSimplifiedReasoning(userInput = '', context = {}) {
201
+ // Critical overrides only
202
+ const recentErrors = this.errorHistory.filter(err => {
203
+ const errorTime = new Date(err.timestamp);
204
+ const fiveMinutesAgo = new Date(Date.now() - 5 * 60 * 1000);
205
+ return errorTime > fiveMinutesAgo;
206
+ }).length;
207
+
208
+ if (recentErrors >= 2) {
209
+ consoleStyler.log('reasoning', `Override: high due to ${recentErrors} recent errors`);
210
+ return "high";
211
+ }
212
+
213
+ if (context.toolName === 'analyze_and_recover' || context.toolName === 'evaluate_response_quality') {
214
+ consoleStyler.log('reasoning', `Override: high for ${context.toolName}`);
215
+ return "high";
216
+ }
217
+
218
+ if (this.predictedReasoning) {
219
+ consoleStyler.log('reasoning', `Using predicted: ${this.predictedReasoning}`);
220
+ return this.predictedReasoning;
221
+ }
222
+
223
+ // Default fallback
224
+ consoleStyler.log('reasoning', 'Using default: medium');
225
+ return "medium";
226
+ }
227
+
228
+ // Reset reasoning state
229
+ reset() {
230
+ this.predictedReasoning = null;
231
+ this.reasoningJustification = null;
232
+ }
233
+
234
+ // Simple heuristic-based reasoning prediction as fallback
235
+ predictReasoningFromInput(userInput) {
236
+ const lowerInput = userInput.toLowerCase();
237
+
238
+ if (lowerInput.includes('quickly') || lowerInput.includes('quick') ||
239
+ lowerInput.includes('fast') || lowerInput.includes('briefly')) {
240
+ this.predictedReasoning = 'low';
241
+ consoleStyler.log('reasoning', 'Detected user preference: low (quick/fast)');
242
+ } else if (lowerInput.includes('thoroughly') || lowerInput.includes('detailed') ||
243
+ lowerInput.includes('comprehensive') || lowerInput.includes('carefully')) {
244
+ this.predictedReasoning = 'high';
245
+ consoleStyler.log('reasoning', 'Detected user preference: high (thorough/detailed)');
246
+ } else if (lowerInput.includes('debug') || lowerInput.includes('analyze') ||
247
+ lowerInput.includes('troubleshoot') || lowerInput.includes('complex')) {
248
+ this.predictedReasoning = 'high';
249
+ consoleStyler.log('reasoning', 'Detected complexity: high (debug/analyze)');
250
+ } else if (lowerInput.includes('simple') || lowerInput.includes('basic') ||
251
+ lowerInput.includes('count') || lowerInput.includes('list')) {
252
+ this.predictedReasoning = 'low';
253
+ consoleStyler.log('reasoning', 'Detected simplicity: low (simple/basic)');
254
+ }
255
+
256
+ return this.predictedReasoning;
257
+ }
258
+ }