centaurus-cli 2.7.0 → 2.7.2
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/cli-adapter.d.ts +9 -0
- package/dist/cli-adapter.d.ts.map +1 -1
- package/dist/cli-adapter.js +352 -119
- package/dist/cli-adapter.js.map +1 -1
- package/dist/services/ai-service-client.d.ts.map +1 -1
- package/dist/services/ai-service-client.js +3 -0
- package/dist/services/ai-service-client.js.map +1 -1
- package/dist/services/environment-context-injector.d.ts +2 -2
- package/dist/services/environment-context-injector.d.ts.map +1 -1
- package/dist/services/environment-context-injector.js +4 -4
- package/dist/services/environment-context-injector.js.map +1 -1
- package/dist/tools/command.d.ts +1 -2
- package/dist/tools/command.d.ts.map +1 -1
- package/dist/tools/command.js +39 -131
- package/dist/tools/command.js.map +1 -1
- package/dist/tools/file-ops.d.ts +3 -3
- package/dist/tools/file-ops.d.ts.map +1 -1
- package/dist/tools/file-ops.js +120 -92
- package/dist/tools/file-ops.js.map +1 -1
- package/dist/tools/get-diff.d.ts +5 -0
- package/dist/tools/get-diff.d.ts.map +1 -1
- package/dist/tools/get-diff.js +67 -5
- package/dist/tools/get-diff.js.map +1 -1
- package/dist/tools/grep-search.d.ts +13 -21
- package/dist/tools/grep-search.d.ts.map +1 -1
- package/dist/tools/grep-search.js +309 -280
- package/dist/tools/grep-search.js.map +1 -1
- package/dist/tools/inspect-symbol.d.ts +5 -0
- package/dist/tools/inspect-symbol.d.ts.map +1 -1
- package/dist/tools/inspect-symbol.js +102 -20
- package/dist/tools/inspect-symbol.js.map +1 -1
- package/dist/tools/types.d.ts +2 -1
- package/dist/tools/types.d.ts.map +1 -1
- package/dist/tools/validation.d.ts +8 -10
- package/dist/tools/validation.d.ts.map +1 -1
- package/dist/tools/validation.js +35 -37
- package/dist/tools/validation.js.map +1 -1
- package/dist/ui/components/App.d.ts +1 -0
- package/dist/ui/components/App.d.ts.map +1 -1
- package/dist/ui/components/App.js +24 -17
- package/dist/ui/components/App.js.map +1 -1
- package/dist/ui/components/AuthWelcomeScreen.d.ts.map +1 -1
- package/dist/ui/components/AuthWelcomeScreen.js +1 -9
- package/dist/ui/components/AuthWelcomeScreen.js.map +1 -1
- package/dist/ui/components/CodeBlock.d.ts.map +1 -1
- package/dist/ui/components/CodeBlock.js +24 -13
- package/dist/ui/components/CodeBlock.js.map +1 -1
- package/dist/ui/components/DiffViewer.d.ts +1 -0
- package/dist/ui/components/DiffViewer.d.ts.map +1 -1
- package/dist/ui/components/DiffViewer.js +107 -70
- package/dist/ui/components/DiffViewer.js.map +1 -1
- package/dist/ui/components/InputBox.d.ts.map +1 -1
- package/dist/ui/components/InputBox.js +4 -15
- package/dist/ui/components/InputBox.js.map +1 -1
- package/dist/ui/components/ToolExecutionMessage.d.ts.map +1 -1
- package/dist/ui/components/ToolExecutionMessage.js +118 -23
- package/dist/ui/components/ToolExecutionMessage.js.map +1 -1
- package/dist/utils/input-classifier.d.ts.map +1 -1
- package/dist/utils/input-classifier.js +2 -1
- package/dist/utils/input-classifier.js.map +1 -1
- package/package.json +1 -1
- package/prompts/system-prompt-autonomous.md +22 -73
package/dist/cli-adapter.d.ts
CHANGED
|
@@ -56,6 +56,7 @@ export declare class CentaurusCLI {
|
|
|
56
56
|
type: 'code' | 'diff';
|
|
57
57
|
content: string;
|
|
58
58
|
language?: string;
|
|
59
|
+
fullDiff?: string;
|
|
59
60
|
};
|
|
60
61
|
operationType?: 'write_file' | 'edit_file' | 'execute_command';
|
|
61
62
|
operationDetails?: Record<string, any>;
|
|
@@ -82,6 +83,14 @@ export declare class CentaurusCLI {
|
|
|
82
83
|
getCurrentSubshellContext(): SubshellContext;
|
|
83
84
|
handlePickerSelection(selection: string, pickerType: 'model'): Promise<void>;
|
|
84
85
|
private sshHandler?;
|
|
86
|
+
/**
|
|
87
|
+
* Notify UI about tool execution status
|
|
88
|
+
*/
|
|
89
|
+
private notifyToolStatus;
|
|
90
|
+
/**
|
|
91
|
+
* Truncate large results for AI consumption
|
|
92
|
+
*/
|
|
93
|
+
private truncateResult;
|
|
85
94
|
initialize(): Promise<void>;
|
|
86
95
|
/**
|
|
87
96
|
* Get migration message if configuration was migrated
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-adapter.d.ts","sourceRoot":"","sources":["../src/cli-adapter.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"cli-adapter.d.ts","sourceRoot":"","sources":["../src/cli-adapter.ts"],"names":[],"mappings":"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"}
|
package/dist/cli-adapter.js
CHANGED
|
@@ -7,8 +7,13 @@ const __filename = fileURLToPath(import.meta.url);
|
|
|
7
7
|
const __dirname = dirname(__filename);
|
|
8
8
|
import { ConfigManager } from './config/manager.js';
|
|
9
9
|
import { ToolRegistry } from './tools/registry.js';
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { viewFileTool, writeToFileTool, editFileTool, listDirTool } from './tools/file-ops.js';
|
|
11
|
+
import { runCommandTool } from './tools/command.js';
|
|
12
|
+
import { grepSearchTool } from './tools/grep-search.js';
|
|
13
|
+
import { findFilesTool } from './tools/find-files.js';
|
|
14
|
+
import { getDiffTool } from './tools/get-diff.js';
|
|
15
|
+
import { inspectSymbolTool } from './tools/inspect-symbol.js';
|
|
16
|
+
import { exitPlanModeTool, getPlanStatusTool, updatePlanStepTool } from './tools/plan-mode.js';
|
|
12
17
|
import { webSearchTool, fetchUrlTool } from './tools/web-search.js';
|
|
13
18
|
import { taskCompleteTool } from './tools/task-complete.js';
|
|
14
19
|
import { apiClient } from './services/api-client.js';
|
|
@@ -173,14 +178,50 @@ export class CentaurusCLI {
|
|
|
173
178
|
}
|
|
174
179
|
}
|
|
175
180
|
sshHandler;
|
|
181
|
+
/**
|
|
182
|
+
* Notify UI about tool execution status
|
|
183
|
+
*/
|
|
184
|
+
notifyToolStatus(toolName, status, args, result, error) {
|
|
185
|
+
if (this.onToolExecutionUpdate) {
|
|
186
|
+
// Add cwd to arguments for execute_command tool
|
|
187
|
+
const toolArgs = toolName === 'execute_command' && args
|
|
188
|
+
? { ...args, cwd: this.cwd }
|
|
189
|
+
: args;
|
|
190
|
+
this.onToolExecutionUpdate({
|
|
191
|
+
toolName,
|
|
192
|
+
status,
|
|
193
|
+
result,
|
|
194
|
+
error,
|
|
195
|
+
arguments: toolArgs
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Truncate large results for AI consumption
|
|
201
|
+
*/
|
|
202
|
+
truncateResult(result, maxLength = 500000) {
|
|
203
|
+
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
204
|
+
if (resultStr.length > maxLength) {
|
|
205
|
+
const truncated = resultStr.substring(0, maxLength);
|
|
206
|
+
const linesRemoved = (resultStr.match(/\n/g) || []).length - (truncated.match(/\n/g) || []).length;
|
|
207
|
+
return truncated + `\n\n[... truncated ${resultStr.length - maxLength} characters, ~${linesRemoved} lines removed for brevity ...]`;
|
|
208
|
+
}
|
|
209
|
+
return result;
|
|
210
|
+
}
|
|
176
211
|
async initialize() {
|
|
177
212
|
// Register tools
|
|
178
|
-
this.toolRegistry.register(
|
|
179
|
-
this.toolRegistry.register(
|
|
213
|
+
this.toolRegistry.register(viewFileTool);
|
|
214
|
+
this.toolRegistry.register(writeToFileTool);
|
|
180
215
|
this.toolRegistry.register(editFileTool);
|
|
181
|
-
this.toolRegistry.register(
|
|
182
|
-
this.toolRegistry.register(
|
|
216
|
+
this.toolRegistry.register(listDirTool);
|
|
217
|
+
this.toolRegistry.register(runCommandTool);
|
|
183
218
|
this.toolRegistry.register(grepSearchTool);
|
|
219
|
+
this.toolRegistry.register(findFilesTool);
|
|
220
|
+
this.toolRegistry.register(getDiffTool);
|
|
221
|
+
this.toolRegistry.register(inspectSymbolTool);
|
|
222
|
+
this.toolRegistry.register(exitPlanModeTool);
|
|
223
|
+
this.toolRegistry.register(getPlanStatusTool);
|
|
224
|
+
this.toolRegistry.register(updatePlanStepTool);
|
|
184
225
|
this.toolRegistry.register(webSearchTool);
|
|
185
226
|
this.toolRegistry.register(fetchUrlTool);
|
|
186
227
|
this.toolRegistry.register(taskCompleteTool);
|
|
@@ -370,7 +411,8 @@ Press Enter to continue...
|
|
|
370
411
|
const currentContext = this.contextManager.getCurrentContext();
|
|
371
412
|
messages = this.aiContextInjector.injectSubshellContext(messages, currentContext);
|
|
372
413
|
// Build environment context to send to backend
|
|
373
|
-
|
|
414
|
+
// Initial context - will be updated in loop
|
|
415
|
+
let environmentContext = this.getEnvironmentContext();
|
|
374
416
|
const mode = this.getMode();
|
|
375
417
|
let finalAssistantMessage = '';
|
|
376
418
|
const MAX_TURNS = 500; // Allow up to 500 turns for complex tasks
|
|
@@ -378,6 +420,7 @@ Press Enter to continue...
|
|
|
378
420
|
const MAX_NARRATION_ATTEMPTS = 3; // Maximum times we'll prompt AI to stop narrating
|
|
379
421
|
let turnCount = 0;
|
|
380
422
|
let narrationAttempts = 0; // Track how many times AI narrated without executing
|
|
423
|
+
let completionAttempts = 0; // Track how many times AI provided text summary without task_complete
|
|
381
424
|
let thoughtStartTime = null; // Track when thinking started
|
|
382
425
|
let thoughtContent = ''; // Accumulate thought content
|
|
383
426
|
// Create AbortController for this request
|
|
@@ -385,6 +428,14 @@ Press Enter to continue...
|
|
|
385
428
|
// Multi-turn tool execution loop
|
|
386
429
|
while (turnCount < MAX_TURNS) {
|
|
387
430
|
turnCount++;
|
|
431
|
+
// Refresh environment context to capture any CWD changes from previous turns
|
|
432
|
+
environmentContext = this.getEnvironmentContext();
|
|
433
|
+
// Refresh system prompt with new CWD
|
|
434
|
+
const refreshedSystemPrompt = environmentContextInjector.getEnhancedSystemPrompt(systemPrompt, this.cwd);
|
|
435
|
+
// Update the system message in the messages array
|
|
436
|
+
if (messages.length > 0 && messages[0].role === 'system') {
|
|
437
|
+
messages[0].content = refreshedSystemPrompt;
|
|
438
|
+
}
|
|
388
439
|
let assistantMessage = '';
|
|
389
440
|
let toolCalls = [];
|
|
390
441
|
// Stream AI response from backend
|
|
@@ -469,8 +520,8 @@ Press Enter to continue...
|
|
|
469
520
|
}
|
|
470
521
|
break;
|
|
471
522
|
}
|
|
472
|
-
}
|
|
473
|
-
// If there are tool calls, execute them
|
|
523
|
+
} // End of stream loop
|
|
524
|
+
// If there are tool calls, execute them
|
|
474
525
|
if (toolCalls.length > 0) {
|
|
475
526
|
// CRITICAL: AI should ONLY communicate via reason_text and task_complete summary
|
|
476
527
|
// Any text output alongside tool calls should be suppressed
|
|
@@ -483,16 +534,6 @@ Press Enter to continue...
|
|
|
483
534
|
// Silently limit tool calls
|
|
484
535
|
toolCalls = toolCalls.slice(0, MAX_TOOL_CALLS_PER_TURN);
|
|
485
536
|
}
|
|
486
|
-
// Helper function to truncate large results
|
|
487
|
-
const truncateResult = (result, maxLength = 500000) => {
|
|
488
|
-
const resultStr = typeof result === 'string' ? result : JSON.stringify(result);
|
|
489
|
-
if (resultStr.length > maxLength) {
|
|
490
|
-
const truncated = resultStr.substring(0, maxLength);
|
|
491
|
-
const linesRemoved = (resultStr.match(/\n/g) || []).length - (truncated.match(/\n/g) || []).length;
|
|
492
|
-
return truncated + `\n\n[... truncated ${resultStr.length - maxLength} characters, ~${linesRemoved} lines removed for brevity ...]`;
|
|
493
|
-
}
|
|
494
|
-
return result;
|
|
495
|
-
};
|
|
496
537
|
const toolResults = [];
|
|
497
538
|
let userCancelledOperation = false;
|
|
498
539
|
let taskCompleted = false;
|
|
@@ -561,7 +602,7 @@ Press Enter to continue...
|
|
|
561
602
|
}
|
|
562
603
|
}
|
|
563
604
|
// Truncate result before sending to AI (to avoid exceeding message size limits)
|
|
564
|
-
const truncatedResult = truncateResult(parsedResult);
|
|
605
|
+
const truncatedResult = this.truncateResult(parsedResult);
|
|
565
606
|
toolResults.push({
|
|
566
607
|
tool_call_id: toolCall.id,
|
|
567
608
|
name: toolCall.name,
|
|
@@ -691,107 +732,115 @@ Press Enter to continue...
|
|
|
691
732
|
},
|
|
692
733
|
...this.conversationHistory
|
|
693
734
|
];
|
|
694
|
-
// Re-inject subshell context
|
|
735
|
+
// Re-inject subshell context
|
|
695
736
|
messages = this.aiContextInjector.injectSubshellContext(messages, currentContext);
|
|
696
|
-
//
|
|
697
|
-
await new Promise(resolve => setTimeout(resolve, 500));
|
|
698
|
-
// Continue to next turn to let AI process results
|
|
699
|
-
continue;
|
|
737
|
+
continue; // Loop back to AI service
|
|
700
738
|
}
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
//
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
|
|
715
|
-
|
|
716
|
-
|
|
717
|
-
|
|
718
|
-
// If AI keeps narrating without executing, force completion immediately
|
|
719
|
-
if (narrationAttempts >= MAX_NARRATION_ATTEMPTS) {
|
|
720
|
-
// Force task completion with error message
|
|
721
|
-
finalAssistantMessage = '⚠️ **Task Incomplete**: The AI repeatedly described actions without executing them.\n\n' +
|
|
722
|
-
'**What happened**: The AI entered a narration loop, describing what it wanted to do instead of using tool calls.\n\n' +
|
|
723
|
-
'**Suggestions**:\n' +
|
|
724
|
-
'1. Try rephrasing your request more specifically\n' +
|
|
725
|
-
'2. Break the task into smaller, concrete steps\n' +
|
|
726
|
-
'3. Provide explicit file paths if known\n' +
|
|
727
|
-
'4. Check if the model supports tool calling properly\n\n' +
|
|
728
|
-
'**Last message**: ' + assistantMessage;
|
|
729
|
-
break;
|
|
730
|
-
}
|
|
731
|
-
// First narration attempt - give a strong warning with specific guidance
|
|
732
|
-
if (narrationAttempts === 1) {
|
|
733
|
-
const completionPrompt = '🛑 **CRITICAL ERROR**: You output text without using tools.\n\n' +
|
|
734
|
-
'**COMMUNICATION RULE VIOLATION**: You can ONLY communicate through:\n' +
|
|
735
|
-
'1. `reason_text` parameter in tool calls\n' +
|
|
736
|
-
'2. `summary` parameter in task_complete tool\n\n' +
|
|
737
|
-
'**Your text output was HIDDEN from the user.**\n\n' +
|
|
738
|
-
'**MANDATORY CORRECTION**:\n' +
|
|
739
|
-
'- If you need to DO something: Call the tool with `reason_text`\n' +
|
|
740
|
-
'- If you are DONE: Call `task_complete(summary="your message")`\n' +
|
|
741
|
-
'- NEVER output plain text - it will be hidden\n\n' +
|
|
742
|
-
'**Example for greeting**:\n' +
|
|
743
|
-
'```\n' +
|
|
744
|
-
'<thought>User said hello, I should greet back</thought>\n' +
|
|
745
|
-
'(Call task_complete with summary="Hello! How can I help you today?")\n' +
|
|
746
|
-
'```\n\n' +
|
|
747
|
-
'**Your NEXT response MUST use tools.**';
|
|
748
|
-
this.conversationHistory.push({
|
|
749
|
-
role: 'user',
|
|
750
|
-
content: completionPrompt,
|
|
751
|
-
});
|
|
752
|
-
}
|
|
753
|
-
else {
|
|
754
|
-
// Second narration attempt - final warning before forced completion
|
|
755
|
-
const completionPrompt = '🚨 **FINAL WARNING** (Attempt ' + narrationAttempts + '/' + MAX_NARRATION_ATTEMPTS + '): You are STILL narrating instead of executing.\n\n' +
|
|
756
|
-
'**This is your LAST chance**:\n' +
|
|
757
|
-
'1. Execute a tool call NOW, or\n' +
|
|
758
|
-
'2. Call task_complete() to end\n\n' +
|
|
759
|
-
'If you output narration text again, the task will be forcibly terminated.';
|
|
760
|
-
this.conversationHistory.push({
|
|
761
|
-
role: 'user',
|
|
762
|
-
content: completionPrompt,
|
|
763
|
-
});
|
|
764
|
-
}
|
|
739
|
+
else {
|
|
740
|
+
// No tool calls - check for silent stop or text-only response
|
|
741
|
+
// Case 1: Silent Stop (No tool calls AND no text)
|
|
742
|
+
if (!assistantMessage || !assistantMessage.trim()) {
|
|
743
|
+
// No tool calls and no message - AI stopped silently
|
|
744
|
+
// This usually means the AI thinks it's done but didn't call task_complete
|
|
745
|
+
// Prompt it to either continue or complete
|
|
746
|
+
const silentStopPrompt = '⚠️ **SILENT STOP DETECTED**: You ended your turn without any output or tool calls.\n\n' +
|
|
747
|
+
'**This is not allowed.** You must either:\n' +
|
|
748
|
+
'1. Execute a tool call if more work is needed, OR\n' +
|
|
749
|
+
'2. Call task_complete() with a summary of what you accomplished\n\n' +
|
|
750
|
+
'**If you have completed the task**, call task_complete() NOW with a comprehensive summary.\n' +
|
|
751
|
+
'**If more work is needed**, execute the next tool call immediately.';
|
|
752
|
+
this.conversationHistory.push({
|
|
753
|
+
role: 'user',
|
|
754
|
+
content: silentStopPrompt,
|
|
755
|
+
});
|
|
765
756
|
}
|
|
757
|
+
// Case 2: Text-only response (Narration or Summary)
|
|
766
758
|
else {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
759
|
+
const isNarration = /\b(I will|I'll|Let me|Let's|I need to|I'm going to|I should|I can)\b/i.test(assistantMessage);
|
|
760
|
+
if (isNarration) {
|
|
761
|
+
narrationAttempts++;
|
|
762
|
+
// If AI keeps narrating without executing, force completion immediately
|
|
763
|
+
if (narrationAttempts >= MAX_NARRATION_ATTEMPTS) {
|
|
764
|
+
// Force task completion with error message
|
|
765
|
+
finalAssistantMessage = '⚠️ **Task Incomplete**: The AI repeatedly described actions without executing them.\n\n' +
|
|
766
|
+
'**What happened**: The AI entered a narration loop, describing what it wanted to do instead of using tool calls.\n\n' +
|
|
767
|
+
'**Suggestions**:\n' +
|
|
768
|
+
'1. Try rephrasing your request more specifically\n' +
|
|
769
|
+
'2. Break the task into smaller, concrete steps\n' +
|
|
770
|
+
'3. Provide explicit file paths if known\n' +
|
|
771
|
+
'4. Check if the model supports tool calling properly\n\n' +
|
|
772
|
+
'**Last message**: ' + assistantMessage;
|
|
773
|
+
break;
|
|
774
|
+
}
|
|
775
|
+
// First narration attempt - give a strong warning with specific guidance
|
|
776
|
+
if (narrationAttempts === 1) {
|
|
777
|
+
const completionPrompt = '🛑 **CRITICAL ERROR**: You output text without using tools.\n\n' +
|
|
778
|
+
'**COMMUNICATION RULE VIOLATION**: You can ONLY communicate through:\n' +
|
|
779
|
+
'1. `reason_text` parameter in tool calls\n' +
|
|
780
|
+
'2. `summary` parameter in task_complete tool\n\n' +
|
|
781
|
+
'**Your text output was HIDDEN from the user.**\n\n' +
|
|
782
|
+
'**MANDATORY CORRECTION**:\n' +
|
|
783
|
+
'- If you need to DO something: Call the tool with `reason_text`\n' +
|
|
784
|
+
'- If you are DONE: Call `task_complete(summary="your message")`\n' +
|
|
785
|
+
'- NEVER output plain text - it will be hidden\n\n' +
|
|
786
|
+
'**Example for greeting**:\n' +
|
|
787
|
+
'```\n' +
|
|
788
|
+
'<thought>User said hello, I should greet back</thought>\n' +
|
|
789
|
+
'(Call task_complete with summary="Hello! How can I help you today?")\n' +
|
|
790
|
+
'```\n\n' +
|
|
791
|
+
'**Your NEXT response MUST use tools.**';
|
|
792
|
+
this.conversationHistory.push({
|
|
793
|
+
role: 'user',
|
|
794
|
+
content: completionPrompt,
|
|
795
|
+
});
|
|
796
|
+
}
|
|
797
|
+
else {
|
|
798
|
+
// Second narration attempt - final warning before forced completion
|
|
799
|
+
const completionPrompt = '🚨 **FINAL WARNING** (Attempt ' + narrationAttempts + '/' + MAX_NARRATION_ATTEMPTS + '): You are STILL narrating instead of executing.\n\n' +
|
|
800
|
+
'**This is your LAST chance**:\n' +
|
|
801
|
+
'1. Execute a tool call NOW, or\n' +
|
|
802
|
+
'2. Call task_complete() to end\n\n' +
|
|
803
|
+
'If you output narration text again, the task will be forcibly terminated.';
|
|
804
|
+
this.conversationHistory.push({
|
|
805
|
+
role: 'user',
|
|
806
|
+
content: completionPrompt,
|
|
807
|
+
});
|
|
808
|
+
}
|
|
785
809
|
}
|
|
786
810
|
else {
|
|
787
|
-
//
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
811
|
+
// AI output a response without narration - it should finish
|
|
812
|
+
// Reset narration counter since this is a valid response
|
|
813
|
+
narrationAttempts = 0;
|
|
814
|
+
// Check if the message looks like a final answer/summary
|
|
815
|
+
// If it has substantial length, assume it's a summary attempt
|
|
816
|
+
const isFinalAnswer = assistantMessage.length > 20;
|
|
817
|
+
if (isFinalAnswer) {
|
|
818
|
+
completionAttempts++;
|
|
819
|
+
// If AI keeps providing text summaries without calling task_complete, accept the text and finish
|
|
820
|
+
// This prevents the infinite loop where the AI keeps summarizing in response to our prompt
|
|
821
|
+
if (completionAttempts > 1) {
|
|
822
|
+
finalAssistantMessage = assistantMessage;
|
|
823
|
+
break;
|
|
824
|
+
}
|
|
825
|
+
// This looks like a final answer - prompt to call task_complete
|
|
826
|
+
const completionPrompt = '✅ **Possible Completion Detected**: You provided a text response but did not call `task_complete`.\n\n' +
|
|
827
|
+
'**To finish the conversation, you MUST call the `task_complete` tool.**\n\n' +
|
|
828
|
+
'Please call `task_complete` now with your summary as the argument.';
|
|
829
|
+
this.conversationHistory.push({
|
|
830
|
+
role: 'user',
|
|
831
|
+
content: completionPrompt,
|
|
832
|
+
});
|
|
833
|
+
}
|
|
834
|
+
else {
|
|
835
|
+
// Short message without clear intent - ask for clarification or completion
|
|
836
|
+
const completionPrompt = 'Your response is unclear. Either:\n' +
|
|
837
|
+
'1. Execute the next tool call if more work is needed, or\n' +
|
|
838
|
+
'2. Call task_complete() if the task is done';
|
|
839
|
+
this.conversationHistory.push({
|
|
840
|
+
role: 'user',
|
|
841
|
+
content: completionPrompt,
|
|
842
|
+
});
|
|
843
|
+
}
|
|
795
844
|
}
|
|
796
845
|
}
|
|
797
846
|
// Rebuild messages array
|
|
@@ -850,10 +899,10 @@ Press Enter to continue...
|
|
|
850
899
|
});
|
|
851
900
|
// Save assistant message to backend
|
|
852
901
|
await this.saveMessageToBackend('assistant', finalMessage);
|
|
853
|
-
}
|
|
902
|
+
} // End of while loop
|
|
854
903
|
// Parse response for plan mode
|
|
855
904
|
if (this.planMode) {
|
|
856
|
-
const planData = this.parsePlanResponse(
|
|
905
|
+
const planData = this.parsePlanResponse(finalAssistantMessage);
|
|
857
906
|
if (planData && this.onPlanApprovalRequest) {
|
|
858
907
|
// Ask user for approval
|
|
859
908
|
const approved = await this.onPlanApprovalRequest(planData);
|
|
@@ -870,8 +919,8 @@ Press Enter to continue...
|
|
|
870
919
|
}
|
|
871
920
|
}
|
|
872
921
|
// Send response back to UI (only if there's a message)
|
|
873
|
-
if (this.onResponseCallback &&
|
|
874
|
-
this.onResponseCallback(
|
|
922
|
+
if (this.onResponseCallback && finalAssistantMessage) {
|
|
923
|
+
this.onResponseCallback(finalAssistantMessage);
|
|
875
924
|
}
|
|
876
925
|
}
|
|
877
926
|
catch (error) {
|
|
@@ -898,6 +947,7 @@ Press Enter to continue...
|
|
|
898
947
|
case 'help':
|
|
899
948
|
responseMessage = `Available Commands:\n\n` +
|
|
900
949
|
`/help - Show this help message\n` +
|
|
950
|
+
`/init - Analyze project and create/load centaurus.md context file\n` +
|
|
901
951
|
`/clear - Clear conversation history\n` +
|
|
902
952
|
`/config - View current configuration\n` +
|
|
903
953
|
`/model - Select from available Google models\n` +
|
|
@@ -913,6 +963,189 @@ Press Enter to continue...
|
|
|
913
963
|
`Ctrl+T - Toggle auto-accept mode\n` +
|
|
914
964
|
`? - Show keyboard shortcuts help`;
|
|
915
965
|
break;
|
|
966
|
+
case 'init':
|
|
967
|
+
try {
|
|
968
|
+
// Define the context file names in priority order
|
|
969
|
+
const contextFiles = ['centaurus.md', 'gemini.md', 'claude.md'];
|
|
970
|
+
let foundFile = null;
|
|
971
|
+
let foundFilePath = null;
|
|
972
|
+
// Check for existing context files in priority order
|
|
973
|
+
for (const fileName of contextFiles) {
|
|
974
|
+
const filePath = path.join(this.cwd, fileName);
|
|
975
|
+
if (fs.existsSync(filePath)) {
|
|
976
|
+
foundFile = fileName;
|
|
977
|
+
foundFilePath = filePath;
|
|
978
|
+
break;
|
|
979
|
+
}
|
|
980
|
+
}
|
|
981
|
+
if (foundFile) {
|
|
982
|
+
// Context file exists - read and load it
|
|
983
|
+
try {
|
|
984
|
+
const content = fs.readFileSync(foundFilePath, 'utf-8');
|
|
985
|
+
// Check if content is empty
|
|
986
|
+
if (!content.trim()) {
|
|
987
|
+
responseMessage = `⚠️ Found ${foundFile} but it's empty.\n\n` +
|
|
988
|
+
`Please either:\n` +
|
|
989
|
+
`1. Delete the file and run /init again to generate new documentation\n` +
|
|
990
|
+
`2. Add content to the file manually`;
|
|
991
|
+
break;
|
|
992
|
+
}
|
|
993
|
+
// If the found file is not centaurus.md, create a copy
|
|
994
|
+
if (foundFile !== 'centaurus.md') {
|
|
995
|
+
const centaurusPath = path.join(this.cwd, 'centaurus.md');
|
|
996
|
+
// Check if centaurus.md already exists
|
|
997
|
+
if (fs.existsSync(centaurusPath)) {
|
|
998
|
+
responseMessage = `✅ Found both ${foundFile} and centaurus.md\n\n` +
|
|
999
|
+
`Loading context from centaurus.md...\n\n` +
|
|
1000
|
+
`📄 I have loaded the project context from centaurus.md and now understand:\n` +
|
|
1001
|
+
`• Project structure and architecture\n` +
|
|
1002
|
+
`• Technology stack and dependencies\n` +
|
|
1003
|
+
`• Key components and their interactions\n` +
|
|
1004
|
+
`• Development conventions and patterns\n\n` +
|
|
1005
|
+
`I'm ready to assist with this project!`;
|
|
1006
|
+
}
|
|
1007
|
+
else {
|
|
1008
|
+
// Create a copy as centaurus.md
|
|
1009
|
+
fs.copyFileSync(foundFilePath, centaurusPath);
|
|
1010
|
+
responseMessage = `✅ Found ${foundFile} and created a copy as centaurus.md\n\n` +
|
|
1011
|
+
`📄 I have loaded the project context and now understand:\n` +
|
|
1012
|
+
`• Project structure and architecture\n` +
|
|
1013
|
+
`• Technology stack and dependencies\n` +
|
|
1014
|
+
`• Key components and their interactions\n` +
|
|
1015
|
+
`• Development conventions and patterns\n\n` +
|
|
1016
|
+
`I'm ready to assist with this project!`;
|
|
1017
|
+
}
|
|
1018
|
+
}
|
|
1019
|
+
else {
|
|
1020
|
+
// Already centaurus.md
|
|
1021
|
+
responseMessage = `✅ Loaded context from centaurus.md\n\n` +
|
|
1022
|
+
`📄 I have loaded the project context and now understand:\n` +
|
|
1023
|
+
`• Project structure and architecture\n` +
|
|
1024
|
+
`• Technology stack and dependencies\n` +
|
|
1025
|
+
`• Key components and their interactions\n` +
|
|
1026
|
+
`• Development conventions and patterns\n\n` +
|
|
1027
|
+
`I'm ready to assist with this project!`;
|
|
1028
|
+
}
|
|
1029
|
+
// Add the context to conversation history so the AI actually has it
|
|
1030
|
+
this.conversationHistory.push({
|
|
1031
|
+
role: 'user',
|
|
1032
|
+
content: `Here is the project context from ${foundFile}:\n\n${content}`
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
1035
|
+
catch (readError) {
|
|
1036
|
+
responseMessage = `❌ Error reading ${foundFile}: ${readError.message}\n\n` +
|
|
1037
|
+
`Please check file permissions and try again.`;
|
|
1038
|
+
}
|
|
1039
|
+
}
|
|
1040
|
+
else {
|
|
1041
|
+
// No context file exists - trigger AI analysis
|
|
1042
|
+
responseMessage = `🔍 No context file found (centaurus.md, gemini.md, or claude.md).\n\n` +
|
|
1043
|
+
`I will now analyze your project and create a comprehensive centaurus.md file...\n\n` +
|
|
1044
|
+
`This may take a few moments as I:\n` +
|
|
1045
|
+
`• Explore the directory structure\n` +
|
|
1046
|
+
`• Examine key files and configurations\n` +
|
|
1047
|
+
`• Understand the technology stack\n` +
|
|
1048
|
+
`• Document the architecture and components\n\n` +
|
|
1049
|
+
`Please wait...`;
|
|
1050
|
+
// Send initial response
|
|
1051
|
+
if (this.onResponseCallback) {
|
|
1052
|
+
this.onResponseCallback(responseMessage);
|
|
1053
|
+
}
|
|
1054
|
+
// Create a specialized prompt for project analysis
|
|
1055
|
+
const initPrompt = `You are tasked with analyzing the current project directory and creating a comprehensive documentation file called "centaurus.md".
|
|
1056
|
+
|
|
1057
|
+
**Your Task:**
|
|
1058
|
+
1. Use the list_directory tool to explore the project structure starting from the current directory
|
|
1059
|
+
2. Use read_file to examine key files such as:
|
|
1060
|
+
- package.json, requirements.txt, or similar dependency files
|
|
1061
|
+
- README files
|
|
1062
|
+
- Configuration files (tsconfig.json, .eslintrc, etc.)
|
|
1063
|
+
- Main entry points (index.js, main.py, App.tsx, etc.)
|
|
1064
|
+
3. Use grep_search to find important patterns and understand the codebase
|
|
1065
|
+
4. Create a comprehensive centaurus.md file using the write_file tool
|
|
1066
|
+
|
|
1067
|
+
**The centaurus.md file should include:**
|
|
1068
|
+
|
|
1069
|
+
# [Project Name]
|
|
1070
|
+
|
|
1071
|
+
## Overview
|
|
1072
|
+
Brief description of what this project does and its purpose
|
|
1073
|
+
|
|
1074
|
+
## Technology Stack
|
|
1075
|
+
- **Languages**: List programming languages used
|
|
1076
|
+
- **Frameworks**: Main frameworks (React, Express, Django, etc.)
|
|
1077
|
+
- **Key Dependencies**: Important libraries and tools
|
|
1078
|
+
- **Build Tools**: Webpack, Vite, Maven, etc.
|
|
1079
|
+
|
|
1080
|
+
## Directory Structure
|
|
1081
|
+
\`\`\`
|
|
1082
|
+
/
|
|
1083
|
+
/src - Main source code
|
|
1084
|
+
/tests - Test files
|
|
1085
|
+
/config - Configuration files
|
|
1086
|
+
...
|
|
1087
|
+
\`\`\`
|
|
1088
|
+
|
|
1089
|
+
Brief explanation of each major directory's purpose
|
|
1090
|
+
|
|
1091
|
+
## Key Components
|
|
1092
|
+
Describe the main modules, classes, or components:
|
|
1093
|
+
- **Component Name**: What it does, where it's located
|
|
1094
|
+
- **Component Name**: What it does, where it's located
|
|
1095
|
+
|
|
1096
|
+
## Architecture
|
|
1097
|
+
Explain how the components interact:
|
|
1098
|
+
- Data flow
|
|
1099
|
+
- Communication patterns (REST APIs, GraphQL, event-driven, etc.)
|
|
1100
|
+
- State management
|
|
1101
|
+
- Database architecture (if applicable)
|
|
1102
|
+
|
|
1103
|
+
## Development Workflow
|
|
1104
|
+
- How to install dependencies
|
|
1105
|
+
- How to run the development server
|
|
1106
|
+
- How to run tests
|
|
1107
|
+
- How to build for production
|
|
1108
|
+
|
|
1109
|
+
## Important Conventions
|
|
1110
|
+
- Code organization patterns
|
|
1111
|
+
- Naming conventions
|
|
1112
|
+
- File structure patterns
|
|
1113
|
+
- Any special patterns or best practices used
|
|
1114
|
+
|
|
1115
|
+
## Entry Points
|
|
1116
|
+
- Main files where execution starts
|
|
1117
|
+
- API endpoints (if applicable)
|
|
1118
|
+
- CLI commands (if applicable)
|
|
1119
|
+
|
|
1120
|
+
## Quick Reference
|
|
1121
|
+
Useful commands, key files to know about, common tasks
|
|
1122
|
+
|
|
1123
|
+
**IMPORTANT INSTRUCTIONS:**
|
|
1124
|
+
- Be thorough but concise
|
|
1125
|
+
- Use clear, professional language
|
|
1126
|
+
- Include code examples where helpful
|
|
1127
|
+
- Create the file in the current working directory: ${this.cwd}
|
|
1128
|
+
- After creating the file, call task_complete with a summary
|
|
1129
|
+
|
|
1130
|
+
**Current working directory**: ${this.cwd}
|
|
1131
|
+
|
|
1132
|
+
Start by listing the directory structure to understand what you're working with.`;
|
|
1133
|
+
// Add to conversation history
|
|
1134
|
+
this.conversationHistory.push({
|
|
1135
|
+
role: 'user',
|
|
1136
|
+
content: initPrompt
|
|
1137
|
+
});
|
|
1138
|
+
// Trigger the AI to process this
|
|
1139
|
+
await this.handleMessage('');
|
|
1140
|
+
// Don't send another response - the AI will respond
|
|
1141
|
+
return;
|
|
1142
|
+
}
|
|
1143
|
+
}
|
|
1144
|
+
catch (error) {
|
|
1145
|
+
responseMessage = `❌ Error executing /init command: ${error.message}\n\n` +
|
|
1146
|
+
`Please try again or check file permissions.`;
|
|
1147
|
+
}
|
|
1148
|
+
break;
|
|
916
1149
|
case 'sign-in':
|
|
917
1150
|
// Check if already authenticated
|
|
918
1151
|
if (apiClient.isAuthenticated()) {
|