vigthoria-cli 1.6.2 → 1.6.4
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 +52 -1
- package/dist/commands/chat.d.ts +31 -45
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +374 -855
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/repo.d.ts +10 -0
- package/dist/commands/repo.d.ts.map +1 -1
- package/dist/commands/repo.js +215 -97
- package/dist/commands/repo.js.map +1 -1
- package/dist/index.js +32 -4
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +8 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +183 -42
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/config.d.ts.map +1 -1
- package/dist/utils/config.js +2 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/tools.d.ts +3 -0
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +116 -0
- package/dist/utils/tools.js.map +1 -1
- package/package.json +13 -2
- package/install.ps1 +0 -290
- package/install.sh +0 -307
- package/src/commands/auth.ts +0 -226
- package/src/commands/chat.ts +0 -1101
- package/src/commands/config.ts +0 -306
- package/src/commands/deploy.ts +0 -609
- package/src/commands/edit.ts +0 -310
- package/src/commands/explain.ts +0 -115
- package/src/commands/generate.ts +0 -222
- package/src/commands/hub.ts +0 -382
- package/src/commands/repo.ts +0 -742
- package/src/commands/review.ts +0 -186
- package/src/index.ts +0 -601
- package/src/types/marked-terminal.d.ts +0 -31
- package/src/utils/api.ts +0 -526
- package/src/utils/config.ts +0 -241
- package/src/utils/files.ts +0 -273
- package/src/utils/logger.ts +0 -130
- package/src/utils/session.ts +0 -179
- package/src/utils/tools.ts +0 -2086
- package/test-parse.js +0 -105
- package/test-parse2.js +0 -35
- package/tsconfig.json +0 -20
package/dist/commands/chat.js
CHANGED
|
@@ -1,9 +1,4 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Interactive Chat Command for Vigthoria CLI
|
|
4
|
-
*
|
|
5
|
-
* Now with Vigthoria Autonomous agentic capabilities!
|
|
6
|
-
*/
|
|
7
2
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
8
3
|
if (k2 === undefined) k2 = k;
|
|
9
4
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
@@ -44,11 +39,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
44
39
|
exports.ChatCommand = void 0;
|
|
45
40
|
const chalk_1 = __importDefault(require("chalk"));
|
|
46
41
|
const ora_1 = __importDefault(require("ora"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
47
43
|
const readline = __importStar(require("readline"));
|
|
48
|
-
const marked_1 = require("marked");
|
|
49
|
-
const marked_terminal_1 = require("marked-terminal");
|
|
50
44
|
const api_js_1 = require("../utils/api.js");
|
|
51
|
-
const files_js_1 = require("../utils/files.js");
|
|
52
45
|
const tools_js_1 = require("../utils/tools.js");
|
|
53
46
|
const session_js_1 = require("../utils/session.js");
|
|
54
47
|
class ChatCommand {
|
|
@@ -56,933 +49,459 @@ class ChatCommand {
|
|
|
56
49
|
logger;
|
|
57
50
|
api;
|
|
58
51
|
messages = [];
|
|
59
|
-
fileUtils;
|
|
60
|
-
marked;
|
|
61
52
|
tools = null;
|
|
62
|
-
agentMode = false;
|
|
63
|
-
rl = null;
|
|
64
53
|
sessionManager;
|
|
65
54
|
currentSession = null;
|
|
66
|
-
|
|
67
|
-
|
|
55
|
+
agentMode = false;
|
|
56
|
+
currentProjectPath = process.cwd();
|
|
57
|
+
lastActionableUserInput = '';
|
|
58
|
+
directPromptMode = false;
|
|
59
|
+
directToolContinuationCount = 0;
|
|
60
|
+
currentModel = 'code';
|
|
61
|
+
autoApprove = false;
|
|
68
62
|
constructor(config, logger) {
|
|
69
63
|
this.config = config;
|
|
70
64
|
this.logger = logger;
|
|
71
65
|
this.api = new api_js_1.APIClient(config, logger);
|
|
72
|
-
// Initialize with a safe default - will be updated in run()
|
|
73
|
-
this.fileUtils = new files_js_1.FileUtils('.', config.get('project').ignorePatterns);
|
|
74
66
|
this.sessionManager = new session_js_1.SessionManager();
|
|
75
|
-
// Setup marked for terminal rendering
|
|
76
|
-
this.marked = new marked_1.Marked();
|
|
77
|
-
this.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
78
67
|
}
|
|
79
68
|
async run(options) {
|
|
80
|
-
// Resolve and validate project path
|
|
81
|
-
const projectPath = this.resolveProjectPath(options.project);
|
|
82
|
-
if (!projectPath) {
|
|
83
|
-
this.logger.error(`Project path not found: ${options.project}`);
|
|
84
|
-
this.logger.info('Please specify a valid project directory with -p <path>');
|
|
85
|
-
return;
|
|
86
|
-
}
|
|
87
|
-
// SECURITY: Warn if using home directory as workspace
|
|
88
|
-
const homeDir = process.env.HOME || process.env.USERPROFILE || '';
|
|
89
|
-
const isHomeDir = projectPath === homeDir || projectPath === homeDir.replace(/\\/g, '/');
|
|
90
|
-
if (isHomeDir && options.agent) {
|
|
91
|
-
console.log('');
|
|
92
|
-
console.log(chalk_1.default.yellow('╔════════════════════════════════════════════════════════════╗'));
|
|
93
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.yellow.bold(' ⚠ WARNING: Agent mode in home directory ') + chalk_1.default.yellow('║'));
|
|
94
|
-
console.log(chalk_1.default.yellow('╠════════════════════════════════════════════════════════════╣'));
|
|
95
|
-
console.log(chalk_1.default.yellow('║') + ' You are running agent mode in your home directory. ' + chalk_1.default.yellow('║'));
|
|
96
|
-
console.log(chalk_1.default.yellow('║') + ' The AI can access ALL files in this location. ' + chalk_1.default.yellow('║'));
|
|
97
|
-
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
|
|
98
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.white(' For safety, navigate to your project folder first: ') + chalk_1.default.yellow('║'));
|
|
99
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.cyan(' cd C:\\path\\to\\your\\project ') + chalk_1.default.yellow('║'));
|
|
100
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.cyan(' vigthoria agent ') + chalk_1.default.yellow('║'));
|
|
101
|
-
console.log(chalk_1.default.yellow('║') + ' ' + chalk_1.default.yellow('║'));
|
|
102
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.white(' Or specify a project path: ') + chalk_1.default.yellow('║'));
|
|
103
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.cyan(' vigthoria agent -p C:\\path\\to\\your\\project ') + chalk_1.default.yellow('║'));
|
|
104
|
-
console.log(chalk_1.default.yellow('╚════════════════════════════════════════════════════════════╝'));
|
|
105
|
-
console.log('');
|
|
106
|
-
// Ask for confirmation
|
|
107
|
-
const readline = require('readline');
|
|
108
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
109
|
-
const answer = await new Promise((resolve) => {
|
|
110
|
-
rl.question(chalk_1.default.yellow('Continue anyway? [y/N] '), resolve);
|
|
111
|
-
});
|
|
112
|
-
rl.close();
|
|
113
|
-
if (answer.toLowerCase() !== 'y' && answer.toLowerCase() !== 'yes') {
|
|
114
|
-
this.logger.info('Agent mode cancelled. Navigate to a project folder first.');
|
|
115
|
-
return;
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
// Update fileUtils with correct project path
|
|
119
|
-
this.fileUtils = new files_js_1.FileUtils(projectPath, this.config.get('project').ignorePatterns);
|
|
120
|
-
// STRICT AUTHENTICATION - No local bypass
|
|
121
69
|
if (!this.config.isAuthenticated()) {
|
|
122
|
-
this.logger.error('');
|
|
123
|
-
this.logger.error('╔════════════════════════════════════════════════════════════╗');
|
|
124
|
-
this.logger.error('║ Authentication Required ║');
|
|
125
|
-
this.logger.error('╠════════════════════════════════════════════════════════════╣');
|
|
126
|
-
this.logger.error('║ Vigthoria CLI requires a valid account and subscription. ║');
|
|
127
|
-
this.logger.error('║ ║');
|
|
128
|
-
this.logger.error('║ To get started: ║');
|
|
129
|
-
this.logger.error('║ 1. Create account: https://coder.vigthoria.io/signup ║');
|
|
130
|
-
this.logger.error('║ 2. Choose a plan: https://coder.vigthoria.io/pricing ║');
|
|
131
|
-
this.logger.error('║ 3. Login: vigthoria login ║');
|
|
132
|
-
this.logger.error('╚════════════════════════════════════════════════════════════╝');
|
|
133
|
-
this.logger.error('');
|
|
70
|
+
this.logger.error('Not authenticated. Run: vigthoria login');
|
|
134
71
|
return;
|
|
135
72
|
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
this.logger.error('║ Renew at: https://coder.vigthoria.io/pricing ║');
|
|
148
|
-
this.logger.error('║ ║');
|
|
149
|
-
this.logger.error('║ Plans start at $9/month for unlimited AI coding. ║');
|
|
150
|
-
this.logger.error('╚════════════════════════════════════════════════════════════╝');
|
|
151
|
-
this.logger.error('');
|
|
152
|
-
return;
|
|
153
|
-
}
|
|
154
|
-
}
|
|
155
|
-
// Setup agentic tools if enabled - use resolved project path
|
|
156
|
-
this.agentMode = options.agent || false;
|
|
157
|
-
this.streamMode = options.stream !== false; // Default to true
|
|
158
|
-
this.localMode = false; // Never use local mode - always use Vigthoria API
|
|
159
|
-
// CRITICAL: Agent mode REQUIRES stronger models to prevent hallucinations
|
|
160
|
-
// Use Vigthoria Cloud for complex agent tasks
|
|
161
|
-
if (this.agentMode) {
|
|
162
|
-
// Upgrade model for agent mode if using a weak model
|
|
163
|
-
const weakModels = ['fast', 'mini', 'vigthoria-fast-1.7b'];
|
|
164
|
-
if (weakModels.includes(options.model)) {
|
|
165
|
-
this.logger.warn(`Agent mode works better with stronger models. Upgrading from '${options.model}' to 'code'`);
|
|
166
|
-
options.model = 'code';
|
|
167
|
-
}
|
|
168
|
-
this.tools = new tools_js_1.AgenticTools(this.logger, projectPath, // Use resolved path
|
|
169
|
-
this.askPermission.bind(this), options.autoApprove || false);
|
|
73
|
+
this.agentMode = options.agent === true;
|
|
74
|
+
this.autoApprove = options.autoApprove === true;
|
|
75
|
+
this.currentModel = options.model || 'code';
|
|
76
|
+
this.currentProjectPath = path.resolve(options.project || process.cwd());
|
|
77
|
+
this.directPromptMode = Boolean(options.prompt);
|
|
78
|
+
this.directToolContinuationCount = 0;
|
|
79
|
+
this.tools = new tools_js_1.AgenticTools(this.logger, this.currentProjectPath, async (action) => this.requestPermission(action), this.autoApprove);
|
|
80
|
+
this.initializeSession(options.resume === true);
|
|
81
|
+
if (options.prompt) {
|
|
82
|
+
await this.handleDirectPrompt(options.prompt);
|
|
83
|
+
return;
|
|
170
84
|
}
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
85
|
+
await this.startInteractiveChat();
|
|
86
|
+
}
|
|
87
|
+
initializeSession(resume) {
|
|
88
|
+
if (resume) {
|
|
89
|
+
this.currentSession = this.sessionManager.getLatest(this.currentProjectPath);
|
|
174
90
|
if (this.currentSession) {
|
|
175
91
|
this.messages = [...this.currentSession.messages];
|
|
176
|
-
this.
|
|
92
|
+
this.agentMode = this.currentSession.agentMode || this.agentMode;
|
|
93
|
+
this.currentModel = this.currentSession.model || this.currentModel;
|
|
94
|
+
return;
|
|
177
95
|
}
|
|
178
96
|
}
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
97
|
+
this.currentSession = this.sessionManager.create(this.currentProjectPath, this.currentModel, this.agentMode);
|
|
98
|
+
this.messages = [...this.currentSession.messages];
|
|
99
|
+
}
|
|
100
|
+
async handleDirectPrompt(prompt) {
|
|
101
|
+
console.log(chalk_1.default.cyan('Running single prompt in direct mode.'));
|
|
102
|
+
console.log(chalk_1.default.gray(`Model: ${this.currentModel}`));
|
|
103
|
+
console.log(chalk_1.default.gray(`Project: ${this.currentProjectPath}`));
|
|
104
|
+
console.log();
|
|
105
|
+
if (this.agentMode) {
|
|
106
|
+
await this.runAgentTurn(prompt);
|
|
107
|
+
return;
|
|
182
108
|
}
|
|
183
|
-
|
|
184
|
-
|
|
109
|
+
await this.runSimplePrompt(prompt);
|
|
110
|
+
}
|
|
111
|
+
async runSimplePrompt(prompt) {
|
|
112
|
+
this.lastActionableUserInput = prompt;
|
|
113
|
+
this.messages.push({ role: 'user', content: prompt });
|
|
114
|
+
const spinner = (0, ora_1.default)({ text: 'Thinking...', spinner: 'clock' }).start();
|
|
185
115
|
try {
|
|
186
|
-
|
|
116
|
+
const response = await this.api.chat(this.messages, this.currentModel);
|
|
117
|
+
spinner.stop();
|
|
118
|
+
const finalText = response.message.trim();
|
|
119
|
+
if (finalText) {
|
|
120
|
+
console.log(finalText);
|
|
121
|
+
}
|
|
122
|
+
this.messages.push({ role: 'assistant', content: response.message });
|
|
123
|
+
this.saveSession();
|
|
187
124
|
}
|
|
188
125
|
catch (error) {
|
|
189
|
-
|
|
190
|
-
this.logger.
|
|
126
|
+
spinner.fail('Failed to get response');
|
|
127
|
+
this.logger.error(error.message);
|
|
191
128
|
}
|
|
192
|
-
// Setup system message
|
|
193
|
-
const systemMessage = {
|
|
194
|
-
role: 'system',
|
|
195
|
-
content: this.buildSystemPrompt(projectContext, { ...options, project: projectPath }),
|
|
196
|
-
};
|
|
197
|
-
this.messages.push(systemMessage);
|
|
198
|
-
this.printWelcome({ ...options, project: projectPath });
|
|
199
|
-
// Start REPL
|
|
200
|
-
await this.startRepl({ ...options, project: projectPath });
|
|
201
|
-
}
|
|
202
|
-
buildSystemPrompt(projectContext, options) {
|
|
203
|
-
let prompt = `You are Vigthoria, the premier AI coding assistant of Vigthoria Technologies.
|
|
204
|
-
|
|
205
|
-
## IDENTITY & BRAND
|
|
206
|
-
- Created by Vigthoria Technologies (NOT OpenAI, NOT Anthropic, NOT Microsoft)
|
|
207
|
-
- Mascot: Viggy the Blue Queen
|
|
208
|
-
- Philosophy: "Innovation through Intelligence"
|
|
209
|
-
- Always respond as "Vigthoria" - never claim to be another AI
|
|
210
|
-
|
|
211
|
-
## VIGTHORIA ECOSYSTEM (Important - Know This!)
|
|
212
|
-
Vigthoria is a comprehensive tech platform with these key services:
|
|
213
|
-
- **Vigthoria Coder** (coder.vigthoria.io): AI-powered coding IDE and CLI (this tool!)
|
|
214
|
-
- **Vigthoria Community** (community.vigthoria.io): Code sharing platform, NOT GitHub. When user mentions "repo", assume Vigthoria Community unless they say "GitHub"
|
|
215
|
-
- **Vigthoria GoA** (agent.vigthoria.io): Graph of Agents - autonomous AI orchestration
|
|
216
|
-
- **Vigthoria Meet** (meet.vigthoria.io): Video conferencing platform
|
|
217
|
-
- **Vigthoria Pay**: Payment processing service
|
|
218
|
-
- **Vigthoria B2C Hub**: Business-to-consumer services
|
|
219
|
-
- **Model Router** (port 4009): Routes AI requests to optimal models
|
|
220
|
-
|
|
221
|
-
## CRITICAL RULES - NEVER VIOLATE:
|
|
222
|
-
1. **NEVER HALLUCINATE** - If you don't know something, say so. Don't make up file contents, directories, or project structures.
|
|
223
|
-
2. **NEVER ASSUME FILE CONTENTS** - If asked about a file, you MUST use read_file tool first. Do NOT guess what's in a file.
|
|
224
|
-
3. **NEVER CONFUSE PLATFORMS** - Vigthoria Community is NOT GitHub. Windows paths are NOT Unix paths.
|
|
225
|
-
4. **ALWAYS USE TOOLS** - In agent mode, USE the tools to read files, not your imagination.
|
|
226
|
-
|
|
227
|
-
## Project Context
|
|
228
|
-
- Type: ${projectContext.type}
|
|
229
|
-
- Root: ${options.project}
|
|
230
|
-
- Key files: ${projectContext.files.slice(0, 10).join(', ')}
|
|
231
|
-
${projectContext.type === 'node' ? `- Dependencies: ${Object.keys(projectContext.dependencies).slice(0, 15).join(', ')}` : ''}
|
|
232
|
-
|
|
233
|
-
## CODE QUALITY STANDARDS (CRITICAL):
|
|
234
|
-
1. ALWAYS produce complete, production-ready code - no placeholders
|
|
235
|
-
2. When creating UI/HTML/CSS:
|
|
236
|
-
- Ensure proper color contrast (text readable against backgrounds)
|
|
237
|
-
- Use CSS variables for theming
|
|
238
|
-
- Include responsive design
|
|
239
|
-
3. Include proper error handling
|
|
240
|
-
4. Add meaningful comments for complex logic
|
|
241
|
-
5. Follow modern best practices (2024-2026 standards)
|
|
242
|
-
6. Use semantic HTML, accessible patterns
|
|
243
|
-
7. Show COMPLETE implementations
|
|
244
|
-
|
|
245
|
-
## Guidelines:
|
|
246
|
-
- Provide working code first, explanations second
|
|
247
|
-
- Be concise but thorough
|
|
248
|
-
- Excellence is the standard - mediocrity is not acceptable
|
|
249
|
-
- If you need to see file contents, USE read_file FIRST before responding
|
|
250
|
-
|
|
251
|
-
## VIGTHORIA CLI COMMANDS (Know these to help users):
|
|
252
|
-
|
|
253
|
-
### Core Commands:
|
|
254
|
-
- \`vigthoria chat\` (or \`vig c\`) - Start interactive chat (this session!)
|
|
255
|
-
- \`vigthoria agent\` (or \`vig a\`) - Autonomous agent mode (can read/write files, run commands)
|
|
256
|
-
- \`vigthoria edit <file>\` (or \`vig e\`) - Edit a file with AI assistance
|
|
257
|
-
- \`vigthoria generate "desc"\` (or \`vig g\`) - Generate code from description
|
|
258
|
-
- \`vigthoria explain <file>\` (or \`vig x\`) - Explain code in detail
|
|
259
|
-
- \`vigthoria fix <file>\` (or \`vig f\`) - Fix bugs and issues
|
|
260
|
-
- \`vigthoria review <file>\` (or \`vig r\`) - Code quality review
|
|
261
|
-
|
|
262
|
-
### Repository Commands (Vigthoria Community - NOT GitHub):
|
|
263
|
-
- \`vigthoria repo push\` - Push project to Vigthoria Community repo
|
|
264
|
-
- \`vigthoria repo pull <name>\` - Pull project from Vigthoria repo
|
|
265
|
-
- \`vigthoria repo list\` - List your projects in Vigthoria repo
|
|
266
|
-
- \`vigthoria repo status\` - Show sync status
|
|
267
|
-
- \`vigthoria repo share <name>\` - Generate shareable link
|
|
268
|
-
- \`vigthoria repo clone <url>\` - Clone a public project
|
|
269
|
-
- \`vigthoria repo delete <name>\` - Remove from repo
|
|
270
|
-
|
|
271
|
-
### Hub/Marketplace Commands (Vigthoria API Modules):
|
|
272
|
-
- \`vigthoria hub discover\` - Interactive module discovery
|
|
273
|
-
- \`vigthoria hub list\` - List all API modules
|
|
274
|
-
- \`vigthoria hub search <query>\` - Semantic search for modules
|
|
275
|
-
- \`vigthoria hub activate <module>\` - Enable pay-as-you-go for module
|
|
276
|
-
- \`vigthoria hub active\` - Show your active modules
|
|
277
|
-
- \`vigthoria hub info <module>\` - Get module details
|
|
278
|
-
|
|
279
|
-
### Deployment Commands (Vigthoria Hosting):
|
|
280
|
-
- \`vigthoria deploy preview\` - Deploy to free preview URL
|
|
281
|
-
- \`vigthoria deploy subdomain <name>\` - Deploy to yourname.vigthoria.io
|
|
282
|
-
- \`vigthoria deploy custom <domain>\` - Deploy to custom domain
|
|
283
|
-
- \`vigthoria deploy list\` - List your deployments
|
|
284
|
-
- \`vigthoria deploy plans\` - Show hosting plans/pricing
|
|
285
|
-
- \`vigthoria deploy status\` - Check deployment status
|
|
286
|
-
- \`vigthoria deploy verify <domain>\` - Verify DNS config
|
|
287
|
-
- \`vigthoria deploy remove <domain>\` - Remove deployment
|
|
288
|
-
|
|
289
|
-
### Account & Config Commands:
|
|
290
|
-
- \`vigthoria login\` - Authenticate with Vigthoria
|
|
291
|
-
- \`vigthoria logout\` - Logout from account
|
|
292
|
-
- \`vigthoria status\` - Show auth & subscription status
|
|
293
|
-
- \`vigthoria config\` - Configure CLI settings
|
|
294
|
-
- \`vigthoria update\` - Check for updates & upgrade CLI
|
|
295
|
-
- \`vigthoria init\` - Initialize Vigthoria in project
|
|
296
|
-
|
|
297
|
-
## NATURAL LANGUAGE UNDERSTANDING (Interpret User Intent):
|
|
298
|
-
When users say these phrases, understand their intent:
|
|
299
|
-
- "push it", "upload this", "save to repo" → Run \`vigthoria repo push\`
|
|
300
|
-
- "pull my project", "download from repo" → Run \`vigthoria repo pull\`
|
|
301
|
-
- "deploy this", "host it", "put it online" → Run \`vigthoria deploy\`
|
|
302
|
-
- "show my repos", "list projects" → Run \`vigthoria repo list\`
|
|
303
|
-
- "share this project" → Run \`vigthoria repo share\`
|
|
304
|
-
- "check for updates", "upgrade cli" → Run \`vigthoria update\`
|
|
305
|
-
- "what APIs are available", "show modules" → Run \`vigthoria hub list\`
|
|
306
|
-
- "enable music api", "activate <module>" → Run \`vigthoria hub activate\`
|
|
307
|
-
- "my deployments", "where is it hosted" → Run \`vigthoria deploy list\`
|
|
308
|
-
- "make it live", "publish" → Run \`vigthoria deploy\`
|
|
309
|
-
- "fix bugs", "debug this" → Run \`vigthoria fix <file>\`
|
|
310
|
-
- "explain this code" → Run \`vigthoria explain <file>\`
|
|
311
|
-
- "review my code" → Run \`vigthoria review <file>\`
|
|
312
|
-
- "create a component", "generate code for" → Run \`vigthoria generate\`
|
|
313
|
-
|
|
314
|
-
## Special Chat Commands (user may use these in chat):
|
|
315
|
-
- /file <path> - Read and include a file in context
|
|
316
|
-
- /edit <path> - Switch to file editing mode
|
|
317
|
-
- /diff - Show pending changes
|
|
318
|
-
- /apply - Apply pending changes
|
|
319
|
-
- /clear - Clear conversation history
|
|
320
|
-
- /model <name> - Switch AI model
|
|
321
|
-
- /agent - Toggle agentic mode (Vigthoria autonomous actions)
|
|
322
|
-
- /help - Show available commands`;
|
|
323
|
-
// Add tool instructions if in agent mode
|
|
324
|
-
if (this.agentMode && this.tools) {
|
|
325
|
-
prompt += `\n\n${tools_js_1.AgenticTools.getToolsForPrompt()}`;
|
|
326
|
-
}
|
|
327
|
-
return prompt;
|
|
328
129
|
}
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
resolveProjectPath(inputPath) {
|
|
333
|
-
const path = require('path');
|
|
334
|
-
const fs = require('fs');
|
|
335
|
-
try {
|
|
336
|
-
// Resolve to absolute path
|
|
337
|
-
let resolvedPath = inputPath;
|
|
338
|
-
if (!path.isAbsolute(inputPath)) {
|
|
339
|
-
resolvedPath = path.resolve(process.cwd(), inputPath);
|
|
340
|
-
}
|
|
341
|
-
// Normalize the path for the current OS
|
|
342
|
-
resolvedPath = path.normalize(resolvedPath);
|
|
343
|
-
// Check if path exists
|
|
344
|
-
if (fs.existsSync(resolvedPath)) {
|
|
345
|
-
const stats = fs.statSync(resolvedPath);
|
|
346
|
-
if (stats.isDirectory()) {
|
|
347
|
-
return resolvedPath;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
// Try current working directory as fallback
|
|
351
|
-
const cwd = process.cwd();
|
|
352
|
-
if (fs.existsSync(cwd)) {
|
|
353
|
-
return cwd;
|
|
354
|
-
}
|
|
355
|
-
return null;
|
|
130
|
+
async runAgentTurn(prompt) {
|
|
131
|
+
if (!this.tools) {
|
|
132
|
+
throw new Error('Agent tools are not initialized.');
|
|
356
133
|
}
|
|
357
|
-
|
|
358
|
-
|
|
134
|
+
const handledByDirectFileFlow = await this.tryDirectSingleFileFlow(prompt);
|
|
135
|
+
if (handledByDirectFileFlow) {
|
|
136
|
+
this.saveSession();
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
this.lastActionableUserInput = prompt;
|
|
140
|
+
this.directToolContinuationCount = 0;
|
|
141
|
+
this.tools.clearSessionApprovals();
|
|
142
|
+
this.ensureAgentSystemPrompt();
|
|
143
|
+
this.messages.push({ role: 'user', content: this.buildScopedUserPrompt(prompt) });
|
|
144
|
+
this.saveSession();
|
|
145
|
+
const maxTurns = 10;
|
|
146
|
+
for (let turn = 0; turn < maxTurns; turn += 1) {
|
|
147
|
+
const spinner = (0, ora_1.default)({ text: turn === 0 ? 'Planning...' : 'Continuing...', spinner: 'clock' }).start();
|
|
359
148
|
try {
|
|
360
|
-
|
|
149
|
+
const response = await this.api.chat(this.messages, this.currentModel);
|
|
150
|
+
spinner.stop();
|
|
151
|
+
const assistantMessage = response.message || '';
|
|
152
|
+
this.messages.push({ role: 'assistant', content: assistantMessage });
|
|
153
|
+
const toolCalls = this.extractToolCalls(assistantMessage);
|
|
154
|
+
const visibleText = this.stripToolPayloads(assistantMessage).trim();
|
|
155
|
+
if (toolCalls.length === 0) {
|
|
156
|
+
console.log(visibleText || 'Task complete.');
|
|
157
|
+
this.saveSession();
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
await this.executeToolCalls(toolCalls);
|
|
161
|
+
this.directToolContinuationCount += 1;
|
|
162
|
+
this.messages.push({
|
|
163
|
+
role: 'system',
|
|
164
|
+
content: this.buildContinuationPrompt(),
|
|
165
|
+
});
|
|
166
|
+
this.saveSession();
|
|
361
167
|
}
|
|
362
|
-
catch {
|
|
363
|
-
|
|
168
|
+
catch (error) {
|
|
169
|
+
spinner.fail('Agent request failed');
|
|
170
|
+
this.logger.error(error.message);
|
|
171
|
+
return;
|
|
364
172
|
}
|
|
365
173
|
}
|
|
174
|
+
console.log('Task complete.');
|
|
175
|
+
this.saveSession();
|
|
366
176
|
}
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
this.logger.box(`Model: ${chalk_1.default.cyan(options.model)}\n` +
|
|
371
|
-
`Plan: ${chalk_1.default.green(sub.plan || 'free')}\n` +
|
|
372
|
-
`Project: ${chalk_1.default.gray(options.project)}\n` +
|
|
373
|
-
`Agent Mode: ${this.agentMode ? chalk_1.default.green('ON ✓') : chalk_1.default.gray('OFF')}`, 'Vigthoria Chat');
|
|
374
|
-
console.log();
|
|
375
|
-
if (this.agentMode) {
|
|
376
|
-
console.log(chalk_1.default.yellow('🤖 Agent Mode: AI can read files, edit code, and run commands autonomously.'));
|
|
177
|
+
async tryDirectSingleFileFlow(prompt) {
|
|
178
|
+
if (!this.directPromptMode || !this.tools) {
|
|
179
|
+
return false;
|
|
377
180
|
}
|
|
378
|
-
|
|
379
|
-
|
|
181
|
+
const targetFile = this.inferTargetFileFromPrompt(prompt);
|
|
182
|
+
if (!targetFile) {
|
|
183
|
+
return false;
|
|
184
|
+
}
|
|
185
|
+
const readCall = {
|
|
186
|
+
tool: 'read_file',
|
|
187
|
+
args: { path: targetFile },
|
|
188
|
+
};
|
|
189
|
+
console.log(chalk_1.default.cyan(`⚙ Executing: ${readCall.tool}`));
|
|
190
|
+
const readResult = await this.tools.execute(readCall);
|
|
191
|
+
const readSummary = this.formatToolResult(readCall, readResult);
|
|
192
|
+
console.log(readResult.success ? chalk_1.default.gray(readSummary) : chalk_1.default.red(readSummary));
|
|
193
|
+
this.messages.push({ role: 'system', content: readSummary });
|
|
194
|
+
if (!readResult.success || !readResult.output) {
|
|
195
|
+
return false;
|
|
196
|
+
}
|
|
197
|
+
const rewriteMessages = [
|
|
198
|
+
{
|
|
199
|
+
role: 'system',
|
|
200
|
+
content: [
|
|
201
|
+
'You are repairing a single file for a CLI agent task.',
|
|
202
|
+
`Return only the final contents for ${targetFile}.`,
|
|
203
|
+
'Do not use Markdown fences.',
|
|
204
|
+
'Do not add explanations before or after the file contents.',
|
|
205
|
+
'Produce complete, runnable code or markup.',
|
|
206
|
+
].join('\n'),
|
|
207
|
+
},
|
|
208
|
+
{
|
|
209
|
+
role: 'user',
|
|
210
|
+
content: [
|
|
211
|
+
`Task: ${prompt}`,
|
|
212
|
+
`Target file: ${targetFile}`,
|
|
213
|
+
'Current file contents:',
|
|
214
|
+
readResult.output,
|
|
215
|
+
].join('\n\n'),
|
|
216
|
+
},
|
|
217
|
+
];
|
|
218
|
+
const rewriteResponse = await this.api.chat(rewriteMessages, this.currentModel);
|
|
219
|
+
const rewrittenContent = this.extractFinalFileContent(rewriteResponse.message, targetFile);
|
|
220
|
+
if (!rewrittenContent) {
|
|
221
|
+
return false;
|
|
222
|
+
}
|
|
223
|
+
const writeCall = {
|
|
224
|
+
tool: 'write_file',
|
|
225
|
+
args: {
|
|
226
|
+
path: targetFile,
|
|
227
|
+
content: rewrittenContent,
|
|
228
|
+
},
|
|
229
|
+
};
|
|
230
|
+
console.log(chalk_1.default.cyan(`⚙ Executing: ${writeCall.tool}`));
|
|
231
|
+
const writeResult = await this.tools.execute(writeCall);
|
|
232
|
+
const writeSummary = this.formatToolResult(writeCall, writeResult);
|
|
233
|
+
console.log(writeResult.success ? chalk_1.default.gray(writeSummary) : chalk_1.default.red(writeSummary));
|
|
234
|
+
this.messages.push({ role: 'system', content: writeSummary });
|
|
235
|
+
if (!writeResult.success) {
|
|
236
|
+
return false;
|
|
237
|
+
}
|
|
238
|
+
console.log(`Updated ${targetFile}.`);
|
|
239
|
+
return true;
|
|
380
240
|
}
|
|
381
|
-
async
|
|
382
|
-
this.
|
|
241
|
+
async startInteractiveChat() {
|
|
242
|
+
this.logger.section(this.agentMode ? 'Interactive Agent Chat' : 'Interactive Chat');
|
|
243
|
+
console.log(chalk_1.default.gray('Type /help for commands. Type /exit to quit.'));
|
|
244
|
+
const rl = readline.createInterface({
|
|
383
245
|
input: process.stdin,
|
|
384
246
|
output: process.stdout,
|
|
385
|
-
prompt: chalk_1.default.cyan('you › '),
|
|
386
|
-
terminal: true,
|
|
387
247
|
});
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
if (
|
|
394
|
-
|
|
395
|
-
if (this.currentSession && this.messages.length > 1) {
|
|
396
|
-
this.sessionManager.save(this.currentSession);
|
|
397
|
-
console.log(chalk_1.default.gray(`Session saved: ${this.currentSession.id}`));
|
|
398
|
-
}
|
|
399
|
-
console.log(chalk_1.default.cyan('Run `vigthoria chat --resume` to continue.\n'));
|
|
400
|
-
isRunning = false;
|
|
248
|
+
while (true) {
|
|
249
|
+
const input = await new Promise((resolve) => {
|
|
250
|
+
rl.question(chalk_1.default.blue('> '), resolve);
|
|
251
|
+
});
|
|
252
|
+
const trimmed = input.trim();
|
|
253
|
+
if (!trimmed) {
|
|
254
|
+
continue;
|
|
401
255
|
}
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
if (isRunning) {
|
|
406
|
-
isRunning = false;
|
|
407
|
-
console.log(chalk_1.default.yellow('\n\nExiting...'));
|
|
408
|
-
if (this.currentSession && this.messages.length > 1) {
|
|
409
|
-
this.sessionManager.save(this.currentSession);
|
|
410
|
-
console.log(chalk_1.default.gray(`Session saved: ${this.currentSession.id}`));
|
|
411
|
-
}
|
|
412
|
-
console.log(chalk_1.default.cyan('Goodbye! 👋\n'));
|
|
413
|
-
process.exit(0);
|
|
256
|
+
if (trimmed === '/exit' || trimmed === '/quit') {
|
|
257
|
+
rl.close();
|
|
258
|
+
return;
|
|
414
259
|
}
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
for await (const line of this.rl) {
|
|
418
|
-
if (!isRunning)
|
|
419
|
-
break;
|
|
420
|
-
const input = line.trim();
|
|
421
|
-
if (!input) {
|
|
422
|
-
this.rl.prompt();
|
|
260
|
+
if (trimmed === '/help') {
|
|
261
|
+
this.showHelp();
|
|
423
262
|
continue;
|
|
424
263
|
}
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
break;
|
|
432
|
-
case 'clear':
|
|
433
|
-
this.messages = [this.messages[0]]; // Keep system message
|
|
434
|
-
this.logger.success('Conversation cleared');
|
|
435
|
-
break;
|
|
436
|
-
case 'model':
|
|
437
|
-
if (args[0]) {
|
|
438
|
-
const newModel = args[0];
|
|
439
|
-
currentModel = newModel;
|
|
440
|
-
// Show branded model name
|
|
441
|
-
const modelInfo = this.config.getAvailableModels().find(m => m.id === newModel);
|
|
442
|
-
const isCloud = this.config.isCloudModel(newModel);
|
|
443
|
-
if (isCloud) {
|
|
444
|
-
console.log();
|
|
445
|
-
console.log(chalk_1.default.magenta(' ☁️ Switched to: ') + chalk_1.default.magenta.bold(modelInfo?.name || 'Vigthoria Cloud'));
|
|
446
|
-
console.log(chalk_1.default.gray(' 671B cloud model - ideal for complex tasks'));
|
|
447
|
-
console.log();
|
|
448
|
-
}
|
|
449
|
-
else {
|
|
450
|
-
console.log();
|
|
451
|
-
console.log(chalk_1.default.green(' 🏠 Switched to: ') + chalk_1.default.green.bold(modelInfo?.name || newModel));
|
|
452
|
-
console.log(chalk_1.default.gray(' Local model - fast, no API costs'));
|
|
453
|
-
console.log();
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
else {
|
|
457
|
-
this.printModels();
|
|
458
|
-
}
|
|
459
|
-
break;
|
|
460
|
-
case 'agent':
|
|
461
|
-
this.agentMode = !this.agentMode;
|
|
462
|
-
if (this.agentMode && !this.tools) {
|
|
463
|
-
this.tools = new tools_js_1.AgenticTools(this.logger, options.project, this.askPermission.bind(this), options.autoApprove || false);
|
|
464
|
-
}
|
|
465
|
-
// Rebuild system prompt with/without tools
|
|
466
|
-
this.messages[0] = {
|
|
467
|
-
role: 'system',
|
|
468
|
-
content: this.buildSystemPrompt(await this.fileUtils.getProjectContext(), { ...options, agent: this.agentMode }),
|
|
469
|
-
};
|
|
470
|
-
this.logger.success(`Agent mode: ${this.agentMode ? chalk_1.default.green('ON') : chalk_1.default.red('OFF')}`);
|
|
471
|
-
if (this.agentMode) {
|
|
472
|
-
console.log(chalk_1.default.yellow(' AI can now read files, edit code, and run commands.'));
|
|
473
|
-
}
|
|
474
|
-
break;
|
|
475
|
-
case 'approve':
|
|
476
|
-
if (this.tools) {
|
|
477
|
-
options.autoApprove = !options.autoApprove;
|
|
478
|
-
this.tools = new tools_js_1.AgenticTools(this.logger, options.project, this.askPermission.bind(this), options.autoApprove);
|
|
479
|
-
this.logger.success(`Auto-approve: ${options.autoApprove ? chalk_1.default.green('ON') : chalk_1.default.red('OFF')}`);
|
|
480
|
-
if (options.autoApprove) {
|
|
481
|
-
console.log(chalk_1.default.red(' ⚠️ AI actions will be executed without confirmation!'));
|
|
482
|
-
}
|
|
483
|
-
}
|
|
484
|
-
break;
|
|
485
|
-
case 'file':
|
|
486
|
-
if (args[0]) {
|
|
487
|
-
await this.addFileToContext(args[0]);
|
|
488
|
-
}
|
|
489
|
-
else {
|
|
490
|
-
this.logger.error('Usage: /file <path>');
|
|
491
|
-
}
|
|
492
|
-
break;
|
|
493
|
-
case 'edit':
|
|
494
|
-
if (args[0]) {
|
|
495
|
-
pendingChanges = await this.startEditMode(args[0], currentModel);
|
|
496
|
-
}
|
|
497
|
-
else {
|
|
498
|
-
this.logger.error('Usage: /edit <path>');
|
|
499
|
-
}
|
|
500
|
-
break;
|
|
501
|
-
case 'diff':
|
|
502
|
-
if (pendingChanges) {
|
|
503
|
-
this.showPendingDiff(pendingChanges);
|
|
504
|
-
}
|
|
505
|
-
else {
|
|
506
|
-
this.logger.info('No pending changes');
|
|
507
|
-
}
|
|
508
|
-
break;
|
|
509
|
-
case 'apply':
|
|
510
|
-
if (pendingChanges) {
|
|
511
|
-
this.applyChanges(pendingChanges);
|
|
512
|
-
pendingChanges = null;
|
|
513
|
-
}
|
|
514
|
-
else {
|
|
515
|
-
this.logger.info('No pending changes to apply');
|
|
516
|
-
}
|
|
517
|
-
break;
|
|
518
|
-
case 'sessions':
|
|
519
|
-
this.listSessions();
|
|
520
|
-
break;
|
|
521
|
-
case 'history':
|
|
522
|
-
this.showHistory();
|
|
523
|
-
break;
|
|
524
|
-
case 'save':
|
|
525
|
-
if (this.currentSession) {
|
|
526
|
-
this.sessionManager.save(this.currentSession);
|
|
527
|
-
this.logger.success(`Session saved: ${this.currentSession.id}`);
|
|
528
|
-
}
|
|
529
|
-
break;
|
|
530
|
-
case 'new':
|
|
531
|
-
// Start new session
|
|
532
|
-
this.currentSession = this.sessionManager.create(options.project, currentModel, this.agentMode);
|
|
533
|
-
this.messages = [this.messages[0]]; // Keep only system message
|
|
534
|
-
this.logger.success(`New session: ${this.currentSession.id}`);
|
|
535
|
-
break;
|
|
536
|
-
case 'compact':
|
|
537
|
-
// Compact context by summarizing older messages
|
|
538
|
-
await this.compactContext(currentModel);
|
|
539
|
-
break;
|
|
540
|
-
case 'undo':
|
|
541
|
-
// Undo last file operation
|
|
542
|
-
if (this.tools) {
|
|
543
|
-
const undoResult = await this.tools.undo();
|
|
544
|
-
if (undoResult.success) {
|
|
545
|
-
this.logger.success(undoResult.output || 'Undo completed');
|
|
546
|
-
if (undoResult.metadata?.remainingUndos !== undefined) {
|
|
547
|
-
console.log(chalk_1.default.gray(` ${undoResult.metadata.remainingUndos} more undo(s) available`));
|
|
548
|
-
}
|
|
549
|
-
}
|
|
550
|
-
else {
|
|
551
|
-
this.logger.error(undoResult.error || 'Nothing to undo');
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
else {
|
|
555
|
-
this.logger.info('Undo is only available in agent mode. Use /agent to enable.');
|
|
556
|
-
}
|
|
557
|
-
break;
|
|
558
|
-
case 'logout':
|
|
559
|
-
// Logout from Vigthoria
|
|
560
|
-
this.config.clearAuth();
|
|
561
|
-
this.logger.success('Logged out successfully');
|
|
562
|
-
console.log(chalk_1.default.gray('Run `vigthoria login` to authenticate again.'));
|
|
563
|
-
// Auto-save session before exit
|
|
564
|
-
if (this.currentSession && this.messages.length > 1) {
|
|
565
|
-
this.sessionManager.save(this.currentSession);
|
|
566
|
-
}
|
|
567
|
-
console.log(chalk_1.default.cyan('\nGoodbye! 👋\n'));
|
|
568
|
-
this.rl.close();
|
|
569
|
-
return;
|
|
570
|
-
case 'status':
|
|
571
|
-
// Show current authentication status
|
|
572
|
-
if (this.config.isAuthenticated()) {
|
|
573
|
-
const email = this.config.get('email');
|
|
574
|
-
const sub = this.config.get('subscription');
|
|
575
|
-
console.log();
|
|
576
|
-
console.log(chalk_1.default.green('✓ Logged in'));
|
|
577
|
-
console.log(chalk_1.default.gray(' Email: ') + chalk_1.default.cyan(email));
|
|
578
|
-
console.log(chalk_1.default.gray(' Plan: ') + chalk_1.default.green(sub.plan || 'free'));
|
|
579
|
-
console.log(chalk_1.default.gray(' Model: ') + chalk_1.default.cyan(options.model));
|
|
580
|
-
console.log(chalk_1.default.gray(' Agent: ') + (this.agentMode ? chalk_1.default.green('ON') : chalk_1.default.gray('OFF')));
|
|
581
|
-
console.log();
|
|
582
|
-
}
|
|
583
|
-
else {
|
|
584
|
-
console.log();
|
|
585
|
-
this.logger.warn('Not logged in');
|
|
586
|
-
console.log(chalk_1.default.gray('Run `vigthoria login` to authenticate'));
|
|
587
|
-
console.log();
|
|
588
|
-
}
|
|
589
|
-
break;
|
|
590
|
-
case 'exit':
|
|
591
|
-
case 'quit':
|
|
592
|
-
// Auto-save session on exit
|
|
593
|
-
if (this.currentSession && this.messages.length > 1) {
|
|
594
|
-
this.sessionManager.save(this.currentSession);
|
|
595
|
-
console.log(chalk_1.default.gray(`Session saved: ${this.currentSession.id}`));
|
|
596
|
-
}
|
|
597
|
-
console.log(chalk_1.default.cyan('\nGoodbye! 👋\n'));
|
|
598
|
-
this.rl.close();
|
|
599
|
-
return;
|
|
600
|
-
default:
|
|
601
|
-
this.logger.warn(`Unknown command: /${cmd}`);
|
|
264
|
+
if (trimmed === '/agent') {
|
|
265
|
+
this.agentMode = !this.agentMode;
|
|
266
|
+
console.log(chalk_1.default.yellow(`Agent mode: ${this.agentMode ? 'ON' : 'OFF'}`));
|
|
267
|
+
if (this.currentSession) {
|
|
268
|
+
this.currentSession.agentMode = this.agentMode;
|
|
269
|
+
this.saveSession();
|
|
602
270
|
}
|
|
603
|
-
this.rl.prompt();
|
|
604
271
|
continue;
|
|
605
272
|
}
|
|
606
|
-
|
|
607
|
-
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
// Save message to session
|
|
611
|
-
if (this.currentSession) {
|
|
612
|
-
this.currentSession.messages = [...this.messages];
|
|
613
|
-
this.sessionManager.save(this.currentSession);
|
|
614
|
-
}
|
|
615
|
-
this.rl.prompt();
|
|
616
|
-
}
|
|
617
|
-
}
|
|
618
|
-
async chat(userInput, model) {
|
|
619
|
-
// Add user message (skip if empty - used for tool continuation)
|
|
620
|
-
if (userInput) {
|
|
621
|
-
this.messages.push({ role: 'user', content: userInput });
|
|
622
|
-
// Clear session-approved tools for new user turn
|
|
623
|
-
if (this.tools) {
|
|
624
|
-
this.tools.clearSessionApprovals();
|
|
273
|
+
if (trimmed === '/clear') {
|
|
274
|
+
this.messages = [];
|
|
275
|
+
console.log(chalk_1.default.yellow('Conversation cleared.'));
|
|
276
|
+
continue;
|
|
625
277
|
}
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
}).start();
|
|
631
|
-
try {
|
|
632
|
-
const response = await this.api.chat(this.messages, model, this.localMode);
|
|
633
|
-
spinner.stop();
|
|
634
|
-
// Add assistant message
|
|
635
|
-
this.messages.push({ role: 'assistant', content: response.message });
|
|
636
|
-
// Render markdown response
|
|
637
|
-
console.log();
|
|
638
|
-
console.log(chalk_1.default.cyan('vigthoria ›'));
|
|
639
|
-
console.log(this.marked.parse(response.message));
|
|
640
|
-
// Show token usage
|
|
641
|
-
if (response.usage) {
|
|
642
|
-
console.log(chalk_1.default.gray(`[${response.usage.total_tokens} tokens]`));
|
|
278
|
+
if (trimmed === '/save') {
|
|
279
|
+
this.saveSession();
|
|
280
|
+
console.log(chalk_1.default.green('Session saved.'));
|
|
281
|
+
continue;
|
|
643
282
|
}
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
283
|
+
if (trimmed.startsWith('/model ')) {
|
|
284
|
+
this.currentModel = trimmed.slice(7).trim() || this.currentModel;
|
|
285
|
+
console.log(chalk_1.default.yellow(`Model changed to: ${this.currentModel}`));
|
|
286
|
+
if (this.currentSession) {
|
|
287
|
+
this.currentSession.model = this.currentModel;
|
|
288
|
+
this.saveSession();
|
|
650
289
|
}
|
|
290
|
+
continue;
|
|
651
291
|
}
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
spinner.stop();
|
|
655
|
-
const errMsg = error.message || 'Unknown error';
|
|
656
|
-
// Check for specific error types
|
|
657
|
-
if (errMsg.includes('ECONNREFUSED') || errMsg.includes('ENOTFOUND')) {
|
|
658
|
-
this.logger.error('Connection failed: Unable to reach AI service');
|
|
659
|
-
console.log(chalk_1.default.gray(' Check your internet connection or try again later.'));
|
|
660
|
-
}
|
|
661
|
-
else if (errMsg.includes('timeout') || errMsg.includes('ETIMEDOUT')) {
|
|
662
|
-
this.logger.error('Request timed out: AI service took too long to respond');
|
|
663
|
-
console.log(chalk_1.default.gray(' Try a shorter query or check service status.'));
|
|
664
|
-
}
|
|
665
|
-
else if (errMsg.includes('401') || errMsg.includes('Unauthorized')) {
|
|
666
|
-
this.logger.error('Authentication failed: Your session may have expired');
|
|
667
|
-
console.log(chalk_1.default.gray(' Run `vigthoria login` to re-authenticate.'));
|
|
292
|
+
if (this.agentMode) {
|
|
293
|
+
await this.runAgentTurn(trimmed);
|
|
668
294
|
}
|
|
669
295
|
else {
|
|
670
|
-
this.
|
|
296
|
+
await this.runSimplePrompt(trimmed);
|
|
671
297
|
}
|
|
672
|
-
// Remove failed user message
|
|
673
|
-
this.messages.pop();
|
|
674
298
|
}
|
|
675
299
|
}
|
|
676
|
-
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
687
|
-
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
else {
|
|
692
|
-
this.logger.error(`${call.tool}: ${result.error}`);
|
|
693
|
-
}
|
|
300
|
+
showHelp() {
|
|
301
|
+
console.log('');
|
|
302
|
+
console.log('Commands:');
|
|
303
|
+
console.log(' /help Show this help');
|
|
304
|
+
console.log(' /exit Exit chat');
|
|
305
|
+
console.log(' /agent Toggle agent mode');
|
|
306
|
+
console.log(' /clear Clear conversation');
|
|
307
|
+
console.log(' /save Save session');
|
|
308
|
+
console.log(' /model <name> Change model');
|
|
309
|
+
console.log('');
|
|
310
|
+
}
|
|
311
|
+
ensureAgentSystemPrompt() {
|
|
312
|
+
const hasSystemPrompt = this.messages.some((message) => message.role === 'system' && message.content.includes('Vigthoria CLI agent operating contract'));
|
|
313
|
+
if (hasSystemPrompt) {
|
|
314
|
+
return;
|
|
694
315
|
}
|
|
695
|
-
|
|
696
|
-
|
|
697
|
-
|
|
698
|
-
|
|
699
|
-
|
|
700
|
-
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
316
|
+
this.messages.unshift({
|
|
317
|
+
role: 'system',
|
|
318
|
+
content: this.buildAgentSystemPrompt(),
|
|
319
|
+
});
|
|
320
|
+
}
|
|
321
|
+
buildAgentSystemPrompt() {
|
|
322
|
+
const toolCatalog = tools_js_1.AgenticTools.getToolDefinitions()
|
|
323
|
+
.map((tool) => {
|
|
324
|
+
const params = tool.parameters
|
|
325
|
+
.map((param) => `${param.name}${param.required ? ' (required)' : ''}`)
|
|
326
|
+
.join(', ');
|
|
327
|
+
return `- ${tool.name}: ${tool.description}${params ? ` Parameters: ${params}.` : ''}`;
|
|
328
|
+
})
|
|
329
|
+
.join('\n');
|
|
330
|
+
return [
|
|
331
|
+
'Vigthoria CLI agent operating contract.',
|
|
332
|
+
`You are operating inside the project root: ${this.currentProjectPath}`,
|
|
333
|
+
'Stay inside that project unless the user explicitly asks otherwise.',
|
|
334
|
+
'Read files before editing or rewriting them.',
|
|
335
|
+
'When you need a tool, emit only one or more tool wrappers in this exact format:',
|
|
336
|
+
'<tool_call>',
|
|
337
|
+
'{"tool":"read_file","args":{"path":"relative/path.ext"}}',
|
|
338
|
+
'</tool_call>',
|
|
339
|
+
'You may emit multiple <tool_call> blocks in one response.',
|
|
340
|
+
'Never emit raw tool JSON outside that wrapper.',
|
|
341
|
+
'In direct mode, do not ask follow-up questions. Finish the request completely and stop when satisfied.',
|
|
342
|
+
'After tool results arrive, either continue with the next minimal tool calls or return a concise completion summary with no more tool calls.',
|
|
343
|
+
'Available tools:',
|
|
344
|
+
toolCatalog,
|
|
345
|
+
].join('\n');
|
|
346
|
+
}
|
|
347
|
+
buildScopedUserPrompt(prompt) {
|
|
348
|
+
return [
|
|
349
|
+
prompt,
|
|
350
|
+
'',
|
|
351
|
+
`Project root: ${this.currentProjectPath}`,
|
|
352
|
+
'Stay within this project root unless the user explicitly expands scope.',
|
|
353
|
+
'Finish the request and stop once it is complete.',
|
|
354
|
+
].join('\n');
|
|
704
355
|
}
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
msg += `## ${tool}\n`;
|
|
712
|
-
msg += `Status: ${result.success ? 'Success' : 'Failed'}\n`;
|
|
713
|
-
if (result.output) {
|
|
714
|
-
msg += `Output:\n\`\`\`\n${this.truncateOutput(result.output)}\n\`\`\`\n`;
|
|
356
|
+
inferTargetFileFromPrompt(prompt) {
|
|
357
|
+
const matches = Array.from(prompt.matchAll(/([A-Za-z0-9_./-]+\.[A-Za-z0-9_-]+)/g));
|
|
358
|
+
for (const match of matches) {
|
|
359
|
+
const candidate = match[1];
|
|
360
|
+
if (!candidate) {
|
|
361
|
+
continue;
|
|
715
362
|
}
|
|
716
|
-
|
|
717
|
-
|
|
363
|
+
const resolved = path.resolve(this.currentProjectPath, candidate);
|
|
364
|
+
if (resolved.startsWith(this.currentProjectPath)) {
|
|
365
|
+
return candidate;
|
|
718
366
|
}
|
|
719
|
-
msg += '\n';
|
|
720
367
|
}
|
|
721
|
-
|
|
722
|
-
return msg;
|
|
368
|
+
return null;
|
|
723
369
|
}
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
370
|
+
buildContinuationPrompt() {
|
|
371
|
+
return [
|
|
372
|
+
`Tool results received for direct mode step ${this.directToolContinuationCount + 1}.`,
|
|
373
|
+
`Original user request: ${this.lastActionableUserInput}`,
|
|
374
|
+
`Project root boundary: ${this.currentProjectPath}`,
|
|
375
|
+
'If the request is already satisfied, return a concise completion summary and no tool calls.',
|
|
376
|
+
'If more work is required, continue with only the next minimal tool calls needed to finish it.',
|
|
377
|
+
'Do not ask follow-up questions or drift into unrelated tasks.',
|
|
378
|
+
].join('\n');
|
|
733
379
|
}
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
if (!this.rl) {
|
|
742
|
-
resolve(false);
|
|
743
|
-
return;
|
|
380
|
+
extractToolCalls(message) {
|
|
381
|
+
const calls = [];
|
|
382
|
+
const wrapperRegex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
|
383
|
+
for (const match of message.matchAll(wrapperRegex)) {
|
|
384
|
+
const call = this.parseToolPayload(match[1] || '');
|
|
385
|
+
if (call) {
|
|
386
|
+
calls.push(call);
|
|
744
387
|
}
|
|
745
|
-
const prompt = options?.batchApproval
|
|
746
|
-
? chalk_1.default.yellow('Allow? [y/N/a] ')
|
|
747
|
-
: chalk_1.default.yellow('Allow? [y/N] ');
|
|
748
|
-
this.rl.question(prompt, (answer) => {
|
|
749
|
-
const normalized = answer.toLowerCase().trim();
|
|
750
|
-
// Check for batch approval first
|
|
751
|
-
if (options?.batchApproval && (normalized === 'a' || normalized === 'all')) {
|
|
752
|
-
resolve('batch');
|
|
753
|
-
return;
|
|
754
|
-
}
|
|
755
|
-
const allowed = normalized === 'y' || normalized === 'yes';
|
|
756
|
-
resolve(allowed);
|
|
757
|
-
});
|
|
758
|
-
});
|
|
759
|
-
}
|
|
760
|
-
async addFileToContext(filePath) {
|
|
761
|
-
const file = this.fileUtils.readFile(filePath);
|
|
762
|
-
if (!file) {
|
|
763
|
-
this.logger.error(`File not found: ${filePath}`);
|
|
764
|
-
return;
|
|
765
388
|
}
|
|
766
|
-
|
|
767
|
-
const fileMessage = {
|
|
768
|
-
role: 'user',
|
|
769
|
-
content: `Here is the content of ${file.relativePath} (${file.language}, ${file.lines} lines):\n\n\`\`\`${file.language}\n${file.content}\n\`\`\``,
|
|
770
|
-
};
|
|
771
|
-
this.messages.push(fileMessage);
|
|
772
|
-
this.logger.success(`Added ${file.relativePath} to context (${file.lines} lines)`);
|
|
389
|
+
return calls;
|
|
773
390
|
}
|
|
774
|
-
|
|
775
|
-
const
|
|
776
|
-
if (!
|
|
777
|
-
this.logger.error(`File not found: ${filePath}`);
|
|
391
|
+
parseToolPayload(payload) {
|
|
392
|
+
const normalized = payload.trim();
|
|
393
|
+
if (!normalized) {
|
|
778
394
|
return null;
|
|
779
395
|
}
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
return;
|
|
792
|
-
const diff = this.fileUtils.createDiff(file.content, changes.content);
|
|
793
|
-
this.logger.section('Pending Changes');
|
|
794
|
-
this.logger.diff(diff.added, diff.removed);
|
|
795
|
-
}
|
|
796
|
-
applyChanges(changes) {
|
|
797
|
-
// Backup first
|
|
798
|
-
const backup = this.fileUtils.backupFile(changes.file);
|
|
799
|
-
if (backup) {
|
|
800
|
-
this.logger.info(`Backup created: ${backup}`);
|
|
801
|
-
}
|
|
802
|
-
// Apply
|
|
803
|
-
if (this.fileUtils.writeFile(changes.file, changes.content)) {
|
|
804
|
-
this.logger.success(`Changes applied to ${changes.file}`);
|
|
396
|
+
try {
|
|
397
|
+
const parsed = JSON.parse(normalized);
|
|
398
|
+
if (typeof parsed.tool !== 'string') {
|
|
399
|
+
return null;
|
|
400
|
+
}
|
|
401
|
+
const args = {};
|
|
402
|
+
if (parsed.args && typeof parsed.args === 'object') {
|
|
403
|
+
for (const [key, value] of Object.entries(parsed.args)) {
|
|
404
|
+
args[key] = typeof value === 'string' ? value : JSON.stringify(value);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
return { tool: parsed.tool, args };
|
|
805
408
|
}
|
|
806
|
-
|
|
807
|
-
|
|
409
|
+
catch {
|
|
410
|
+
return null;
|
|
808
411
|
}
|
|
809
412
|
}
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
this.logger.section('Available Commands');
|
|
813
|
-
console.log(chalk_1.default.yellow('── File & Context ──'));
|
|
814
|
-
console.log(chalk_1.default.cyan('/file <path>') + ' - Add file to conversation context');
|
|
815
|
-
console.log(chalk_1.default.cyan('/edit <path>') + ' - Start editing a file');
|
|
816
|
-
console.log(chalk_1.default.cyan('/diff') + ' - Show pending changes');
|
|
817
|
-
console.log(chalk_1.default.cyan('/apply') + ' - Apply pending changes');
|
|
818
|
-
console.log();
|
|
819
|
-
console.log(chalk_1.default.yellow('── AI & Models ──'));
|
|
820
|
-
console.log(chalk_1.default.cyan('/model <name>') + ' - Switch AI model (or list available)');
|
|
821
|
-
console.log(chalk_1.default.cyan('/agent') + ' - Toggle agentic mode (Vigthoria Autonomous)');
|
|
822
|
-
console.log(chalk_1.default.cyan('/approve') + ' - Toggle auto-approve for agent actions');
|
|
823
|
-
console.log(chalk_1.default.cyan('/undo') + ' - Undo last file operation (agent mode)');
|
|
824
|
-
console.log();
|
|
825
|
-
console.log(chalk_1.default.yellow('── Session & History ──'));
|
|
826
|
-
console.log(chalk_1.default.cyan('/clear') + ' - Clear conversation history');
|
|
827
|
-
console.log(chalk_1.default.cyan('/compact') + ' - Compact context (summarize older messages)');
|
|
828
|
-
console.log(chalk_1.default.cyan('/sessions') + ' - List saved sessions');
|
|
829
|
-
console.log(chalk_1.default.cyan('/history') + ' - Show conversation history');
|
|
830
|
-
console.log(chalk_1.default.cyan('/save') + ' - Save current session');
|
|
831
|
-
console.log(chalk_1.default.cyan('/new') + ' - Start new session');
|
|
832
|
-
console.log();
|
|
833
|
-
console.log(chalk_1.default.yellow('── Account ──'));
|
|
834
|
-
console.log(chalk_1.default.cyan('/status') + ' - Show login & subscription status');
|
|
835
|
-
console.log(chalk_1.default.cyan('/logout') + ' - Logout from Vigthoria');
|
|
836
|
-
console.log();
|
|
837
|
-
console.log(chalk_1.default.yellow('── General ──'));
|
|
838
|
-
console.log(chalk_1.default.cyan('/help') + ' - Show this help');
|
|
839
|
-
console.log(chalk_1.default.cyan('/exit') + ' - Exit Vigthoria (auto-saves)');
|
|
840
|
-
console.log(chalk_1.default.cyan('/quit') + ' - Same as /exit');
|
|
841
|
-
console.log();
|
|
842
|
-
console.log(chalk_1.default.yellow('── CLI Commands (run in terminal) ──'));
|
|
843
|
-
console.log(chalk_1.default.gray(' vigthoria repo push - Push to Vigthoria Community'));
|
|
844
|
-
console.log(chalk_1.default.gray(' vigthoria repo pull - Pull from your repos'));
|
|
845
|
-
console.log(chalk_1.default.gray(' vigthoria deploy - Deploy & host project'));
|
|
846
|
-
console.log(chalk_1.default.gray(' vigthoria hub - Browse API modules'));
|
|
847
|
-
console.log(chalk_1.default.gray(' vigthoria update - Update CLI to latest'));
|
|
848
|
-
console.log();
|
|
849
|
-
console.log(chalk_1.default.yellow('💡 Natural Language Tips:'));
|
|
850
|
-
console.log(chalk_1.default.gray(' Say "push it" → I\'ll help with vigthoria repo push'));
|
|
851
|
-
console.log(chalk_1.default.gray(' Say "deploy this" → I\'ll guide you through hosting'));
|
|
852
|
-
console.log(chalk_1.default.gray(' Say "what APIs are available" → I\'ll show hub modules'));
|
|
853
|
-
console.log();
|
|
854
|
-
if (this.agentMode) {
|
|
855
|
-
console.log(chalk_1.default.yellow('Agent Mode Tools:'));
|
|
856
|
-
console.log(chalk_1.default.gray(' read_file, write_file, edit_file, bash, grep, list_dir, glob, git'));
|
|
857
|
-
console.log();
|
|
858
|
-
}
|
|
413
|
+
stripToolPayloads(message) {
|
|
414
|
+
return message.replace(/<tool_call>[\s\S]*?<\/tool_call>/g, '').trim();
|
|
859
415
|
}
|
|
860
|
-
|
|
861
|
-
const
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
865
|
-
|
|
866
|
-
|
|
867
|
-
|
|
868
|
-
|
|
869
|
-
|
|
870
|
-
|
|
871
|
-
|
|
872
|
-
|
|
873
|
-
|
|
416
|
+
extractFinalFileContent(message, targetFile) {
|
|
417
|
+
const trimmed = message.trim();
|
|
418
|
+
if (!trimmed) {
|
|
419
|
+
return '';
|
|
420
|
+
}
|
|
421
|
+
const fencedMatch = trimmed.match(/```(?:[A-Za-z0-9_-]+)?\n([\s\S]*?)```/);
|
|
422
|
+
if (fencedMatch && fencedMatch[1]) {
|
|
423
|
+
return fencedMatch[1].trim();
|
|
424
|
+
}
|
|
425
|
+
const extension = path.extname(targetFile).toLowerCase();
|
|
426
|
+
if (extension === '.html') {
|
|
427
|
+
const htmlStart = trimmed.indexOf('<!DOCTYPE html>') >= 0
|
|
428
|
+
? trimmed.indexOf('<!DOCTYPE html>')
|
|
429
|
+
: trimmed.indexOf('<html');
|
|
430
|
+
if (htmlStart >= 0) {
|
|
431
|
+
return trimmed.slice(htmlStart).trim();
|
|
432
|
+
}
|
|
874
433
|
}
|
|
875
|
-
|
|
434
|
+
return trimmed;
|
|
876
435
|
}
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
console.log(chalk_1.default.
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
const preview = m.content.substring(0, 60).replace(/\n/g, ' ');
|
|
888
|
-
console.log(`${i + 1}. ${role}: ${chalk_1.default.gray(preview)}...`);
|
|
889
|
-
});
|
|
436
|
+
async executeToolCalls(toolCalls) {
|
|
437
|
+
if (!this.tools) {
|
|
438
|
+
throw new Error('Agent tools are not initialized.');
|
|
439
|
+
}
|
|
440
|
+
for (const call of toolCalls) {
|
|
441
|
+
console.log(chalk_1.default.cyan(`⚙ Executing: ${call.tool}`));
|
|
442
|
+
const result = await this.tools.execute(call);
|
|
443
|
+
const summary = this.formatToolResult(call, result);
|
|
444
|
+
console.log(result.success ? chalk_1.default.gray(summary) : chalk_1.default.red(summary));
|
|
445
|
+
this.messages.push({ role: 'system', content: summary });
|
|
890
446
|
}
|
|
891
|
-
console.log();
|
|
892
447
|
}
|
|
893
|
-
|
|
894
|
-
|
|
895
|
-
if (
|
|
896
|
-
this.
|
|
897
|
-
return;
|
|
448
|
+
formatToolResult(call, result) {
|
|
449
|
+
const parts = [`Tool ${call.tool} ${result.success ? 'succeeded' : 'failed'}.`];
|
|
450
|
+
if (result.output) {
|
|
451
|
+
parts.push(`Output:\n${this.truncateText(result.output)}`);
|
|
898
452
|
}
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
spinner: 'dots',
|
|
902
|
-
}).start();
|
|
903
|
-
try {
|
|
904
|
-
// Keep system message and last 4 messages
|
|
905
|
-
const systemMessage = this.messages[0];
|
|
906
|
-
const recentMessages = this.messages.slice(-4);
|
|
907
|
-
const olderMessages = this.messages.slice(1, -4);
|
|
908
|
-
if (olderMessages.length === 0) {
|
|
909
|
-
spinner.stop();
|
|
910
|
-
this.logger.info('Nothing to compact');
|
|
911
|
-
return;
|
|
912
|
-
}
|
|
913
|
-
// Ask AI to summarize older conversation
|
|
914
|
-
const summaryResponse = await this.api.chat([
|
|
915
|
-
{ role: 'system', content: 'Summarize this conversation in a concise way, preserving key context and decisions.' },
|
|
916
|
-
...olderMessages,
|
|
917
|
-
], model, this.localMode);
|
|
918
|
-
// Create compacted context
|
|
919
|
-
this.messages = [
|
|
920
|
-
systemMessage,
|
|
921
|
-
{ role: 'system', content: `[Previous conversation summary]: ${summaryResponse.message}` },
|
|
922
|
-
...recentMessages,
|
|
923
|
-
];
|
|
924
|
-
spinner.stop();
|
|
925
|
-
this.logger.success(`Compacted ${olderMessages.length} messages into summary`);
|
|
453
|
+
if (result.error) {
|
|
454
|
+
parts.push(`Error:\n${this.truncateText(result.error)}`);
|
|
926
455
|
}
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
this.logger.error('Failed to compact context:', error.message);
|
|
456
|
+
if (result.suggestion) {
|
|
457
|
+
parts.push(`Suggestion: ${result.suggestion}`);
|
|
930
458
|
}
|
|
459
|
+
return parts.join('\n');
|
|
931
460
|
}
|
|
932
|
-
|
|
933
|
-
const
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
console.log();
|
|
937
|
-
// Group by tier
|
|
938
|
-
const localModels = models.filter(m => m.tier === 'local');
|
|
939
|
-
const cloudModels = models.filter(m => m.tier === 'cloud');
|
|
940
|
-
console.log(chalk_1.default.green.bold(' 🏠 VIGTHORIA LOCAL (Self-hosted, fast, no API cost)'));
|
|
941
|
-
console.log(chalk_1.default.gray(' ─────────────────────────────────────────────────'));
|
|
942
|
-
localModels.forEach(m => {
|
|
943
|
-
const isDefault = m.id === 'code';
|
|
944
|
-
const marker = isDefault ? chalk_1.default.yellow(' ★ DEFAULT') : '';
|
|
945
|
-
console.log(chalk_1.default.cyan(' ' + m.id.padEnd(15)) + chalk_1.default.white(m.name.padEnd(25)) + chalk_1.default.gray(m.description) + marker);
|
|
946
|
-
});
|
|
947
|
-
if (cloudModels.length > 0) {
|
|
948
|
-
console.log();
|
|
949
|
-
console.log(chalk_1.default.magenta.bold(' ☁️ VIGTHORIA CLOUD (Premium, for complex tasks)'));
|
|
950
|
-
console.log(chalk_1.default.gray(' ─────────────────────────────────────────────────'));
|
|
951
|
-
cloudModels.forEach(m => {
|
|
952
|
-
console.log(chalk_1.default.cyan(' ' + m.id.padEnd(15)) + chalk_1.default.white(m.name.padEnd(25)) + chalk_1.default.gray(m.description));
|
|
953
|
-
});
|
|
954
|
-
console.log();
|
|
955
|
-
console.log(chalk_1.default.yellow(' 💡 Tip: Use /model cloud for complex multi-file tasks'));
|
|
461
|
+
truncateText(text) {
|
|
462
|
+
const maxLength = 4000;
|
|
463
|
+
if (text.length <= maxLength) {
|
|
464
|
+
return text;
|
|
956
465
|
}
|
|
957
|
-
|
|
958
|
-
console.log();
|
|
959
|
-
console.log(chalk_1.default.yellow(' 💡 Upgrade to Pro for Vigthoria Cloud (671B models)'));
|
|
960
|
-
}
|
|
961
|
-
console.log();
|
|
466
|
+
return `${text.slice(0, maxLength)}\n...[truncated]`;
|
|
962
467
|
}
|
|
963
|
-
|
|
964
|
-
|
|
965
|
-
|
|
966
|
-
if (this.config.isCloudModel(currentModel)) {
|
|
967
|
-
return false;
|
|
468
|
+
saveSession() {
|
|
469
|
+
if (!this.currentSession) {
|
|
470
|
+
this.currentSession = this.sessionManager.create(this.currentProjectPath, this.currentModel, this.agentMode);
|
|
968
471
|
}
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
972
|
-
|
|
973
|
-
|
|
974
|
-
|
|
975
|
-
|
|
976
|
-
|
|
977
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.white(' Type ') + chalk_1.default.cyan('/model cloud') + chalk_1.default.white(' for better results on: ') + chalk_1.default.yellow('║'));
|
|
978
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.gray(' • Multi-file refactoring ') + chalk_1.default.yellow('║'));
|
|
979
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.gray(' • Architecture decisions ') + chalk_1.default.yellow('║'));
|
|
980
|
-
console.log(chalk_1.default.yellow('║') + chalk_1.default.gray(' • Complex feature implementation ') + chalk_1.default.yellow('║'));
|
|
981
|
-
console.log(chalk_1.default.yellow('╚══════════════════════════════════════════════════════════╝'));
|
|
982
|
-
console.log();
|
|
472
|
+
this.currentSession.project = this.currentProjectPath;
|
|
473
|
+
this.currentSession.model = this.currentModel;
|
|
474
|
+
this.currentSession.agentMode = this.agentMode;
|
|
475
|
+
this.currentSession.messages = [...this.messages];
|
|
476
|
+
this.sessionManager.save(this.currentSession);
|
|
477
|
+
}
|
|
478
|
+
async requestPermission(action) {
|
|
479
|
+
if (this.autoApprove) {
|
|
983
480
|
return true;
|
|
984
481
|
}
|
|
985
|
-
|
|
482
|
+
const rl = readline.createInterface({
|
|
483
|
+
input: process.stdin,
|
|
484
|
+
output: process.stdout,
|
|
485
|
+
});
|
|
486
|
+
console.log(action);
|
|
487
|
+
const answer = await new Promise((resolve) => {
|
|
488
|
+
rl.question(chalk_1.default.yellow('Approve? [y]es / [n]o / [a]ll this turn: '), resolve);
|
|
489
|
+
});
|
|
490
|
+
rl.close();
|
|
491
|
+
const normalized = answer.trim().toLowerCase();
|
|
492
|
+
if (normalized === 'a' || normalized === 'all') {
|
|
493
|
+
return 'batch';
|
|
494
|
+
}
|
|
495
|
+
return normalized === 'y' || normalized === 'yes';
|
|
496
|
+
}
|
|
497
|
+
getCurrentSessionInfo() {
|
|
498
|
+
if (!this.currentSession) {
|
|
499
|
+
return 'No active session';
|
|
500
|
+
}
|
|
501
|
+
return `Session: ${this.currentSession.name} (${this.currentSession.messages.length} messages)`;
|
|
502
|
+
}
|
|
503
|
+
getChatHistory() {
|
|
504
|
+
return [...this.messages];
|
|
986
505
|
}
|
|
987
506
|
}
|
|
988
507
|
exports.ChatCommand = ChatCommand;
|