vigthoria-cli 1.5.6 → 1.5.8

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.
@@ -66,21 +66,21 @@ export class ChatCommand {
66
66
  const homeDir = process.env.HOME || process.env.USERPROFILE || '';
67
67
  const isHomeDir = projectPath === homeDir || projectPath === homeDir.replace(/\\/g, '/');
68
68
  if (isHomeDir && options.agent) {
69
- this.logger.warn('');
70
- this.logger.warn('╔════════════════════════════════════════════════════════════╗');
71
- this.logger.warn('║ ⚠️ WARNING: Agent mode in home directory ║');
72
- this.logger.warn('╠════════════════════════════════════════════════════════════╣');
73
- this.logger.warn('║ You are running agent mode in your home directory. ║');
74
- this.logger.warn('║ The AI can access ALL files in: ' + projectPath.slice(0, 20).padEnd(20) + ' ║');
75
- this.logger.warn('║ ║');
76
- this.logger.warn('║ For safety, navigate to your project folder first: ║');
77
- this.logger.warn('║ cd C:\\path\\to\\your\\project ║');
78
- this.logger.warn('║ vigthoria agent ║');
79
- this.logger.warn('║ ║');
80
- this.logger.warn('║ Or specify a project path: ║');
81
- this.logger.warn('║ vigthoria agent -p C:\\path\\to\\your\\project ║');
82
- this.logger.warn('╚════════════════════════════════════════════════════════════╝');
83
- this.logger.warn('');
69
+ console.log('');
70
+ console.log(chalk.yellow('╔════════════════════════════════════════════════════════════╗'));
71
+ console.log(chalk.yellow('║') + chalk.yellow.bold(' WARNING: Agent mode in home directory ') + chalk.yellow('║'));
72
+ console.log(chalk.yellow('╠════════════════════════════════════════════════════════════╣'));
73
+ console.log(chalk.yellow('║') + ' You are running agent mode in your home directory. ' + chalk.yellow('║'));
74
+ console.log(chalk.yellow('║') + ' The AI can access ALL files in this location. ' + chalk.yellow('║'));
75
+ console.log(chalk.yellow('║') + ' ' + chalk.yellow('║'));
76
+ console.log(chalk.yellow('║') + chalk.white(' For safety, navigate to your project folder first: ') + chalk.yellow('║'));
77
+ console.log(chalk.yellow('║') + chalk.cyan(' cd C:\\path\\to\\your\\project ') + chalk.yellow('║'));
78
+ console.log(chalk.yellow('║') + chalk.cyan(' vigthoria agent ') + chalk.yellow('║'));
79
+ console.log(chalk.yellow('║') + ' ' + chalk.yellow('║'));
80
+ console.log(chalk.yellow('║') + chalk.white(' Or specify a project path: ') + chalk.yellow('║'));
81
+ console.log(chalk.yellow('║') + chalk.cyan(' vigthoria agent -p C:\\path\\to\\your\\project ') + chalk.yellow('║'));
82
+ console.log(chalk.yellow('╚════════════════════════════════════════════════════════════╝'));
83
+ console.log('');
84
84
 
85
85
  // Ask for confirmation
86
86
  const readline = require('readline');
@@ -142,7 +142,16 @@ export class ChatCommand {
142
142
  this.streamMode = options.stream !== false; // Default to true
143
143
  this.localMode = false; // Never use local mode - always use Vigthoria API
144
144
 
145
+ // CRITICAL: Agent mode REQUIRES stronger models to prevent hallucinations
146
+ // Use Vigthoria Cloud for complex agent tasks
145
147
  if (this.agentMode) {
148
+ // Upgrade model for agent mode if using a weak model
149
+ const weakModels = ['fast', 'mini', 'vigthoria-fast-1.7b'];
150
+ if (weakModels.includes(options.model)) {
151
+ this.logger.warn(`Agent mode works better with stronger models. Upgrading from '${options.model}' to 'code'`);
152
+ options.model = 'code';
153
+ }
154
+
146
155
  this.tools = new AgenticTools(
147
156
  this.logger,
148
157
  projectPath, // Use resolved path
@@ -196,18 +205,35 @@ export class ChatCommand {
196
205
  ): string {
197
206
  let prompt = `You are Vigthoria, the premier AI coding assistant of Vigthoria Technologies.
198
207
 
199
- IDENTITY:
200
- - Created by Vigthoria Technologies
208
+ ## IDENTITY & BRAND
209
+ - Created by Vigthoria Technologies (NOT OpenAI, NOT Anthropic, NOT Microsoft)
201
210
  - Mascot: Viggy the Blue Queen
202
211
  - Philosophy: "Innovation through Intelligence"
203
-
204
- Project Context:
212
+ - Always respond as "Vigthoria" - never claim to be another AI
213
+
214
+ ## VIGTHORIA ECOSYSTEM (Important - Know This!)
215
+ Vigthoria is a comprehensive tech platform with these key services:
216
+ - **Vigthoria Coder** (coder.vigthoria.io): AI-powered coding IDE and CLI (this tool!)
217
+ - **Vigthoria Community** (community.vigthoria.io): Code sharing platform, NOT GitHub. When user mentions "repo", assume Vigthoria Community unless they say "GitHub"
218
+ - **Vigthoria GoA** (agent.vigthoria.io): Graph of Agents - autonomous AI orchestration
219
+ - **Vigthoria Meet** (meet.vigthoria.io): Video conferencing platform
220
+ - **Vigthoria Pay**: Payment processing service
221
+ - **Vigthoria B2C Hub**: Business-to-consumer services
222
+ - **Model Router** (port 4009): Routes AI requests to optimal models
223
+
224
+ ## CRITICAL RULES - NEVER VIOLATE:
225
+ 1. **NEVER HALLUCINATE** - If you don't know something, say so. Don't make up file contents, directories, or project structures.
226
+ 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.
227
+ 3. **NEVER CONFUSE PLATFORMS** - Vigthoria Community is NOT GitHub. Windows paths are NOT Unix paths.
228
+ 4. **ALWAYS USE TOOLS** - In agent mode, USE the tools to read files, not your imagination.
229
+
230
+ ## Project Context
205
231
  - Type: ${projectContext.type}
206
232
  - Root: ${options.project}
207
233
  - Key files: ${projectContext.files.slice(0, 10).join(', ')}
208
234
  ${projectContext.type === 'node' ? `- Dependencies: ${Object.keys(projectContext.dependencies).slice(0, 15).join(', ')}` : ''}
209
235
 
210
- CODE QUALITY STANDARDS (CRITICAL):
236
+ ## CODE QUALITY STANDARDS (CRITICAL):
211
237
  1. ALWAYS produce complete, production-ready code - no placeholders
212
238
  2. When creating UI/HTML/CSS:
213
239
  - Ensure proper color contrast (text readable against backgrounds)
@@ -219,12 +245,13 @@ CODE QUALITY STANDARDS (CRITICAL):
219
245
  6. Use semantic HTML, accessible patterns
220
246
  7. Show COMPLETE implementations
221
247
 
222
- Guidelines:
248
+ ## Guidelines:
223
249
  - Provide working code first, explanations second
224
250
  - Be concise but thorough
225
251
  - Excellence is the standard - mediocrity is not acceptable
252
+ - If you need to see file contents, USE read_file FIRST before responding
226
253
 
227
- Special Commands (user may use these):
254
+ ## Special Commands (user may use these):
228
255
  - /file <path> - Read and include a file in context
229
256
  - /edit <path> - Switch to file editing mode
230
257
  - /diff - Show pending changes
@@ -309,14 +336,44 @@ Special Commands (user may use these):
309
336
  input: process.stdin,
310
337
  output: process.stdout,
311
338
  prompt: chalk.cyan('you › '),
339
+ terminal: true,
312
340
  });
313
341
 
314
342
  let currentModel = options.model;
315
343
  let pendingChanges: { file: string; content: string } | null = null;
344
+ let isRunning = true;
345
+
346
+ // Handle unexpected close events
347
+ this.rl.on('close', () => {
348
+ if (isRunning) {
349
+ console.log(chalk.yellow('\n\n⚠ Session interrupted. Saving...'));
350
+ if (this.currentSession && this.messages.length > 1) {
351
+ this.sessionManager.save(this.currentSession);
352
+ console.log(chalk.gray(`Session saved: ${this.currentSession.id}`));
353
+ }
354
+ console.log(chalk.cyan('Run `vigthoria chat --resume` to continue.\n'));
355
+ isRunning = false;
356
+ }
357
+ });
358
+
359
+ // Handle SIGINT (Ctrl+C) gracefully
360
+ process.on('SIGINT', () => {
361
+ if (isRunning) {
362
+ isRunning = false;
363
+ console.log(chalk.yellow('\n\nExiting...'));
364
+ if (this.currentSession && this.messages.length > 1) {
365
+ this.sessionManager.save(this.currentSession);
366
+ console.log(chalk.gray(`Session saved: ${this.currentSession.id}`));
367
+ }
368
+ console.log(chalk.cyan('Goodbye! 👋\n'));
369
+ process.exit(0);
370
+ }
371
+ });
316
372
 
317
373
  this.rl.prompt();
318
374
 
319
375
  for await (const line of this.rl) {
376
+ if (!isRunning) break;
320
377
  const input = line.trim();
321
378
 
322
379
  if (!input) {
@@ -340,8 +397,24 @@ Special Commands (user may use these):
340
397
 
341
398
  case 'model':
342
399
  if (args[0]) {
343
- currentModel = args[0];
344
- this.logger.success(`Model switched to: ${currentModel}`);
400
+ const newModel = args[0];
401
+ currentModel = newModel;
402
+
403
+ // Show branded model name
404
+ const modelInfo = this.config.getAvailableModels().find(m => m.id === newModel);
405
+ const isCloud = this.config.isCloudModel(newModel);
406
+
407
+ if (isCloud) {
408
+ console.log();
409
+ console.log(chalk.magenta(' ☁️ Switched to: ') + chalk.magenta.bold(modelInfo?.name || 'Vigthoria Cloud'));
410
+ console.log(chalk.gray(' 671B cloud model - ideal for complex tasks'));
411
+ console.log();
412
+ } else {
413
+ console.log();
414
+ console.log(chalk.green(' 🏠 Switched to: ') + chalk.green.bold(modelInfo?.name || newModel));
415
+ console.log(chalk.gray(' Local model - fast, no API costs'));
416
+ console.log();
417
+ }
345
418
  } else {
346
419
  this.printModels();
347
420
  }
@@ -521,6 +594,9 @@ Special Commands (user may use these):
521
594
  }
522
595
 
523
596
  // Regular chat message
597
+ // Check if we should suggest Cloud upgrade for complex tasks
598
+ this.suggestCloudUpgrade(currentModel, input);
599
+
524
600
  await this.chat(input, currentModel);
525
601
 
526
602
  // Save message to session
@@ -579,7 +655,22 @@ Special Commands (user may use these):
579
655
 
580
656
  } catch (error) {
581
657
  spinner.stop();
582
- this.logger.error('Failed to get response:', (error as Error).message);
658
+ const errMsg = (error as Error).message || 'Unknown error';
659
+
660
+ // Check for specific error types
661
+ if (errMsg.includes('ECONNREFUSED') || errMsg.includes('ENOTFOUND')) {
662
+ this.logger.error('Connection failed: Unable to reach AI service');
663
+ console.log(chalk.gray(' Check your internet connection or try again later.'));
664
+ } else if (errMsg.includes('timeout') || errMsg.includes('ETIMEDOUT')) {
665
+ this.logger.error('Request timed out: AI service took too long to respond');
666
+ console.log(chalk.gray(' Try a shorter query or check service status.'));
667
+ } else if (errMsg.includes('401') || errMsg.includes('Unauthorized')) {
668
+ this.logger.error('Authentication failed: Your session may have expired');
669
+ console.log(chalk.gray(' Run `vigthoria login` to re-authenticate.'));
670
+ } else {
671
+ this.logger.error('Failed to get response:', errMsg);
672
+ }
673
+
583
674
  // Remove failed user message
584
675
  this.messages.pop();
585
676
  }
@@ -876,10 +967,60 @@ Special Commands (user may use these):
876
967
  const models = this.config.getAvailableModels();
877
968
 
878
969
  console.log();
879
- this.logger.section('Available Models');
880
- models.forEach(m => {
881
- console.log(chalk.cyan(m.id.padEnd(20)) + chalk.gray(m.description));
970
+ this.logger.section('═══ VIGTHORIA MODELS ═══');
971
+ console.log();
972
+
973
+ // Group by tier
974
+ const localModels = models.filter(m => m.tier === 'local');
975
+ const cloudModels = models.filter(m => m.tier === 'cloud');
976
+
977
+ console.log(chalk.green.bold(' 🏠 VIGTHORIA LOCAL (Self-hosted, fast, no API cost)'));
978
+ console.log(chalk.gray(' ─────────────────────────────────────────────────'));
979
+ localModels.forEach(m => {
980
+ const isDefault = m.id === 'code';
981
+ const marker = isDefault ? chalk.yellow(' ★ DEFAULT') : '';
982
+ console.log(chalk.cyan(' ' + m.id.padEnd(15)) + chalk.white(m.name.padEnd(25)) + chalk.gray(m.description) + marker);
882
983
  });
984
+
985
+ if (cloudModels.length > 0) {
986
+ console.log();
987
+ console.log(chalk.magenta.bold(' ☁️ VIGTHORIA CLOUD (Premium, for complex tasks)'));
988
+ console.log(chalk.gray(' ─────────────────────────────────────────────────'));
989
+ cloudModels.forEach(m => {
990
+ console.log(chalk.cyan(' ' + m.id.padEnd(15)) + chalk.white(m.name.padEnd(25)) + chalk.gray(m.description));
991
+ });
992
+ console.log();
993
+ console.log(chalk.yellow(' 💡 Tip: Use /model cloud for complex multi-file tasks'));
994
+ } else {
995
+ console.log();
996
+ console.log(chalk.yellow(' 💡 Upgrade to Pro for Vigthoria Cloud (671B models)'));
997
+ }
883
998
  console.log();
884
999
  }
1000
+
1001
+ // Suggest Cloud upgrade for complex tasks
1002
+ private suggestCloudUpgrade(currentModel: string, prompt: string): boolean {
1003
+ // Don't suggest if already on cloud
1004
+ if (this.config.isCloudModel(currentModel)) {
1005
+ return false;
1006
+ }
1007
+
1008
+ // Check if task seems complex
1009
+ if (this.config.isComplexTask(prompt)) {
1010
+ console.log();
1011
+ console.log(chalk.yellow('╔══════════════════════════════════════════════════════════╗'));
1012
+ console.log(chalk.yellow('║') + chalk.white.bold(' 💡 This looks like a complex task! ') + chalk.yellow('║'));
1013
+ console.log(chalk.yellow('║') + chalk.gray(' Current: ') + chalk.cyan(currentModel.padEnd(43)) + chalk.yellow('║'));
1014
+ console.log(chalk.yellow('║') + chalk.gray(' Suggested: ') + chalk.magenta('Vigthoria Cloud (671B)'.padEnd(41)) + chalk.yellow('║'));
1015
+ console.log(chalk.yellow('║ ║'));
1016
+ console.log(chalk.yellow('║') + chalk.white(' Type ') + chalk.cyan('/model cloud') + chalk.white(' for better results on: ') + chalk.yellow('║'));
1017
+ console.log(chalk.yellow('║') + chalk.gray(' • Multi-file refactoring ') + chalk.yellow('║'));
1018
+ console.log(chalk.yellow('║') + chalk.gray(' • Architecture decisions ') + chalk.yellow('║'));
1019
+ console.log(chalk.yellow('║') + chalk.gray(' • Complex feature implementation ') + chalk.yellow('║'));
1020
+ console.log(chalk.yellow('╚══════════════════════════════════════════════════════════╝'));
1021
+ console.log();
1022
+ return true;
1023
+ }
1024
+ return false;
1025
+ }
885
1026
  }
package/src/index.ts CHANGED
@@ -157,11 +157,12 @@ async function main() {
157
157
  });
158
158
 
159
159
  // Agent command - Agentic mode (Vigthoria Autonomous)
160
+ // Uses Vigthoria v3 Code 30B or Vigthoria Cloud for complex tasks
160
161
  program
161
162
  .command('agent')
162
163
  .alias('a')
163
164
  .description('Start agentic mode - AI can read/write files, run commands')
164
- .option('-m, --model <model>', 'Select AI model', 'code')
165
+ .option('-m, --model <model>', 'Select AI model (code, cloud, ultra)', 'code')
165
166
  .option('-p, --project <path>', 'Set project context path', process.cwd())
166
167
  .option('--auto-approve', 'Auto-approve all actions (dangerous!)', false)
167
168
  .action(async (options) => {
package/src/utils/api.ts CHANGED
@@ -73,7 +73,7 @@ export class APIClient {
73
73
  httpsAgent,
74
74
  headers: {
75
75
  'Content-Type': 'application/json',
76
- 'User-Agent': `Vigthoria-CLI/${process.env.npm_package_version || '1.4.5'}`,
76
+ 'User-Agent': `Vigthoria-CLI/${process.env.npm_package_version || '1.5.7'}`,
77
77
  },
78
78
  });
79
79
 
@@ -84,7 +84,7 @@ export class APIClient {
84
84
  httpsAgent,
85
85
  headers: {
86
86
  'Content-Type': 'application/json',
87
- 'User-Agent': `Vigthoria-CLI/${process.env.npm_package_version || '1.4.5'}`,
87
+ 'User-Agent': `Vigthoria-CLI/${process.env.npm_package_version || '1.5.7'}`,
88
88
  },
89
89
  });
90
90
 
@@ -231,18 +231,21 @@ export class APIClient {
231
231
  }
232
232
 
233
233
  /**
234
- * Chat API - Supports multiple inference strategies
234
+ * Chat API - SIMPLIFIED Architecture (NO Ollama!)
235
235
  *
236
- * For authenticated users: Uses Vigthoria Cloud API
237
- * For local users: Uses local Ollama or Model Router
236
+ * 1. Vigthoria Cloud API (coder.vigthoria.io) - Primary for authenticated users
237
+ * 2. Vigthoria Inference Service (port 8010) - Native 30B model
238
+ * 3. Model Router (port 4009) - Routes to OpenRouter (Kimi K2.5, DeepSeek)
239
+ *
240
+ * NO OLLAMA FALLBACK - That causes hallucinations with small models!
238
241
  */
239
242
  async chat(messages: ChatMessage[], model: string, useLocal: boolean = false): Promise<ChatResponse> {
240
243
  const resolvedModel = this.resolveModelId(model);
241
244
 
242
- // If authenticated and not forcing local, use Vigthoria Cloud API
243
- if (!useLocal && this.config.isAuthenticated()) {
245
+ // STRATEGY 1: Vigthoria Cloud API (authenticated users)
246
+ if (this.config.isAuthenticated()) {
244
247
  try {
245
- this.logger.debug(`Attempting Vigthoria Cloud API call to /api/ai/chat with model: ${resolvedModel}`);
248
+ this.logger.debug(`Vigthoria Cloud API: ${resolvedModel}`);
246
249
  const response = await this.client.post('/api/ai/chat', {
247
250
  messages,
248
251
  model: resolvedModel,
@@ -258,118 +261,62 @@ export class APIClient {
258
261
  usage: response.data.usage,
259
262
  };
260
263
  }
261
- this.logger.debug(`Cloud API returned success=false: ${JSON.stringify(response.data)}`);
264
+ this.logger.debug(`Cloud API returned success=false`);
262
265
  } catch (error: any) {
263
266
  const errMsg = error.response?.data?.error || error.message || 'Unknown error';
264
- const status = error.response?.status || 'no status';
265
- this.logger.debug(`Vigthoria Cloud API failed (${status}): ${errMsg}`);
267
+ this.logger.debug(`Vigthoria Cloud API failed: ${errMsg}`);
268
+ // Continue to fallback strategies
266
269
  }
267
- } else {
268
- this.logger.debug(`Skipping cloud API - useLocal: ${useLocal}, isAuthenticated: ${this.config.isAuthenticated()}`);
269
270
  }
270
271
 
271
- // Strategy 1: Try Vigthoria Inference Server directly (NATIVE models on port 8010)
272
+ // STRATEGY 2: Vigthoria Inference Service (port 8010) - Native 30B model
272
273
  try {
274
+ this.logger.debug(`Trying Vigthoria Inference Service (8010): ${resolvedModel}`);
273
275
  const response = await axios.post('http://localhost:8010/v1/chat/completions', {
274
276
  model: resolvedModel,
275
277
  messages,
276
278
  max_tokens: this.config.get('preferences').maxTokens,
277
279
  temperature: 0.7,
278
280
  stream: false,
279
- }, { timeout: 120000 });
281
+ }, { timeout: 180000 }); // 3 min timeout for 30B model
280
282
 
281
283
  if (response.data.choices && response.data.choices.length > 0) {
282
284
  return {
283
- id: response.data.id || `vigthoria-native-${Date.now()}`,
285
+ id: response.data.id || `vigthoria-inference-${Date.now()}`,
284
286
  message: response.data.choices[0].message?.content || response.data.choices[0].text,
285
287
  model: response.data.model || model,
286
288
  usage: response.data.usage,
287
289
  };
288
290
  }
289
291
  } catch (error) {
290
- this.logger.debug('Vigthoria Inference Server (8010) failed, trying Model Router...');
292
+ this.logger.debug('Vigthoria Inference Service (8010) unavailable');
291
293
  }
292
294
 
293
- // Strategy 2: Try local Model Router's Vigthoria chat endpoint
295
+ // STRATEGY 3: Model Router (port 4009) - Routes to OpenRouter (Kimi/DeepSeek)
294
296
  try {
295
- const response = await axios.post('http://localhost:4009/api/vigthoria/chat', {
296
- messages,
297
+ this.logger.debug(`Trying Model Router (4009): ${resolvedModel}`);
298
+ const response = await axios.post('http://localhost:4009/v1/chat/completions', {
297
299
  model: resolvedModel,
298
- maxTokens: this.config.get('preferences').maxTokens,
300
+ messages,
301
+ max_tokens: this.config.get('preferences').maxTokens,
299
302
  temperature: 0.7,
300
303
  stream: false,
301
- }, { timeout: 120000 });
304
+ }, { timeout: 180000 });
302
305
 
303
- if (response.data.success !== false) {
306
+ if (response.data.choices && response.data.choices.length > 0) {
304
307
  return {
305
308
  id: response.data.id || `router-${Date.now()}`,
306
- message: response.data.response || response.data.message || response.data.content,
309
+ message: response.data.choices[0].message?.content || response.data.choices[0].text,
307
310
  model: response.data.model || model,
308
311
  usage: response.data.usage,
309
312
  };
310
313
  }
311
314
  } catch (error) {
312
- this.logger.debug('Model Router (4009) failed, trying Ollama directly...');
315
+ this.logger.debug('Model Router (4009) unavailable');
313
316
  }
314
317
 
315
- // Strategy 3: Try Ollama directly (for local development/testing)
316
- try {
317
- const ollamaModel = this.resolveToOllamaModel(model);
318
- const prompt = this.formatMessagesForOllama(messages);
319
-
320
- const response = await axios.post('http://localhost:11434/api/generate', {
321
- model: ollamaModel,
322
- prompt,
323
- stream: false,
324
- }, { timeout: 120000 });
325
-
326
- return {
327
- id: `ollama-${Date.now()}`,
328
- message: response.data.response,
329
- model: ollamaModel,
330
- usage: {
331
- prompt_tokens: response.data.prompt_eval_count || 0,
332
- completion_tokens: response.data.eval_count || 0,
333
- total_tokens: (response.data.prompt_eval_count || 0) + (response.data.eval_count || 0),
334
- },
335
- };
336
- } catch (error) {
337
- this.logger.debug('Ollama failed...');
338
- }
339
-
340
- throw new Error('AI service unavailable. Please check your authentication with `vigthoria login` or try again later.');
341
- }
342
-
343
- // Map CLI model names to Ollama model names (for local/offline fallback)
344
- // Vigthoria_v3_Code_30B runs on qwen3-coder base via Vigthoria Cloud
345
- // Local users with Ollama can use the base model for offline work
346
- private resolveToOllamaModel(model: string): string {
347
- const ollamaMap: Record<string, string> = {
348
- 'fast': 'qwen3:0.6b',
349
- 'mini': 'smollm2:135m',
350
- 'code': 'qwen3-coder:latest', // Vigthoria_v3_Code_30B (cloud) / qwen3-coder (local fallback)
351
- 'balanced': 'phi3:mini',
352
- 'creative': 'gemma3:latest',
353
- 'vigthoria-fast-1.7b': 'qwen3:0.6b',
354
- 'vigthoria-mini-0.6b': 'smollm2:135m',
355
- 'vigthoria-v3-code-30b': 'qwen3-coder:latest', // Vigthoria_v3_Code_30B
356
- 'vigthoria-v2-code-8b': 'qwen3-coder:latest', // Legacy v2
357
- 'vigthoria-balanced-4b': 'phi3:mini',
358
- 'vigthoria-creative-9b-v4': 'gemma3:latest',
359
- };
360
- return ollamaMap[model] || model;
361
- }
362
-
363
- // Format messages for Ollama's generate API
364
- private formatMessagesForOllama(messages: ChatMessage[]): string {
365
- return messages
366
- .filter(m => m.role !== 'system' || messages.indexOf(m) === 0)
367
- .map(m => {
368
- if (m.role === 'system') return `System: ${m.content}\n\n`;
369
- if (m.role === 'user') return `User: ${m.content}\n`;
370
- return `Assistant: ${m.content}\n`;
371
- })
372
- .join('') + 'Assistant:';
318
+ // NO OLLAMA FALLBACK! That causes hallucinations!
319
+ throw new Error('AI service unavailable. Please ensure Vigthoria services are running or login with `vigthoria login`.');
373
320
  }
374
321
 
375
322
  // Streaming chat
@@ -543,108 +490,51 @@ export class APIClient {
543
490
  return response.data;
544
491
  }
545
492
 
546
- // Model resolution - maps short names to actual Vigthoria model IDs
493
+ // Model resolution - maps Vigthoria model names to internal IDs
494
+ // INTERNAL USE ONLY - users see only Vigthoria branding
547
495
  private resolveModelId(shortName: string): string {
548
496
  const modelMap: Record<string, string> = {
549
497
  // ═══════════════════════════════════════════════════════════════
550
- // Vigthoria Native Models - Core Suite
498
+ // VIGTHORIA LOCAL - Self-hosted models
551
499
  // ═══════════════════════════════════════════════════════════════
552
500
  'fast': 'vigthoria-fast-1.7b',
553
- 'mini': 'vigthoria-mini-0.6b',
501
+ 'mini': 'vigthoria-fast-1.7b',
554
502
  'balanced': 'vigthoria-balanced-4b',
555
-
556
- // Code Models - Current & Future Versions
557
- 'code': 'vigthoria-v2-code-8b',
558
- 'code-v2': 'vigthoria-v2-code-8b',
559
- 'code-v2-8b': 'vigthoria-v2-code-8b',
560
- 'code-v3': 'vigthoria-v3-code-8b', // Future
561
- 'code-v3-8b': 'vigthoria-v3-code-8b', // Future
562
- 'code-v3-32b': 'vigthoria-v3-code-32b', // Future large model
563
- 'code-v4': 'vigthoria-v4-code-8b', // Future
564
- 'code-32b': 'vigthoria-v3-code-32b', // Future large model alias
565
-
566
- // Creative Models
567
503
  'creative': 'vigthoria-creative-9b-v4',
568
- 'creative-v3': 'vigthoria-creative-9b-v3',
569
- 'creative-v4': 'vigthoria-creative-9b-v4',
570
-
571
- // Music Model
572
- 'music': 'vigthoria-music-master-4b',
573
- 'music-master': 'vigthoria-music-master-4b',
574
504
 
575
- // Aliases
576
- 'pro': 'vigthoria-balanced-4b',
577
- 'ultra': 'vigthoria-creative-9b-v4',
578
-
579
- // Legacy Vigthoria models
580
- 'master': 'vigthoria_master:latest',
581
- 'c1': 'vigthoria_c1_m:latest',
582
- 'm1': 'vigthoria_m1_m:latest',
505
+ // Code Models - 30B is the default powerhouse
506
+ 'code': 'qwen3-coder:latest', // Internal: qwen3-coder 30B
507
+ 'code-30b': 'qwen3-coder:latest',
508
+ 'code-8b': 'vigthoria-v2-code-8b',
509
+ 'pro': 'qwen3-coder:latest',
583
510
 
584
511
  // ═══════════════════════════════════════════════════════════════
585
- // External Models (via Ollama fallback)
512
+ // VIGTHORIA CLOUD - Premium cloud models (internal routing)
586
513
  // ═══════════════════════════════════════════════════════════════
587
- 'qwen-coder': 'qwen2.5-coder:7b',
588
- 'qwen-coder-7b': 'qwen2.5-coder:7b',
589
- 'qwen-coder-32b': 'qwen2.5-coder:32b',
590
- 'deepseek': 'deepseek-coder-v2:latest',
591
- 'deepseek-r1': 'deepseek-r1:8b',
592
- 'deepseek-r1-32b': 'deepseek-r1:32b',
593
- 'llama3': 'llama3:8b-instruct-q4_0',
594
- 'mixtral': 'mixtral:8x7b-instruct-v0.1-q4_K_M',
514
+ 'cloud': 'deepseek-v3.1:671b-cloud',
515
+ 'cloud-reason': 'moonshotai/kimi-k2.5',
516
+ 'agent': 'deepseek-v3.1:671b-cloud',
517
+ 'ultra': 'deepseek-v3.1:671b-cloud',
595
518
  };
596
519
 
597
- // If already a full model ID (contains 'vigthoria' or known prefix), return as-is
598
- if (shortName.includes('vigthoria') || shortName.includes(':') || shortName.includes('-')) {
599
- // Check if it's a known short name first
520
+ // If already a full model ID, return as-is
521
+ if (shortName.includes('vigthoria') || shortName.includes('/') || shortName.includes(':')) {
600
522
  if (modelMap[shortName]) {
601
523
  return modelMap[shortName];
602
524
  }
603
- // Otherwise assume it's a direct model ID
604
525
  return shortName;
605
526
  }
606
527
 
607
- return modelMap[shortName] || shortName;
528
+ return modelMap[shortName] || 'qwen3-coder:latest'; // Default to 30B
608
529
  }
609
530
 
610
- // Health check with short timeout and multiple fallbacks
531
+ // Health check
611
532
  async healthCheck(): Promise<boolean> {
612
- const apiUrl = this.config.get('apiUrl') || 'https://coder.vigthoria.io';
613
-
614
533
  try {
615
- // Try the main API health endpoint first with shorter timeout
616
- const response = await this.client.get('/api/health', {
617
- timeout: 10000, // 10 second timeout for health check
618
- });
534
+ const response = await this.client.get('/api/health', { timeout: 10000 });
619
535
  return response.data?.status === 'ok' || response.data?.healthy === true;
620
- } catch (error) {
621
- // Fallback 1: try root health endpoint with axios
622
- try {
623
- const fallback = await this.client.get('/health', {
624
- timeout: 5000,
625
- });
626
- return fallback.data?.status === 'ok' || fallback.data?.healthy === true || fallback.status === 200;
627
- } catch {
628
- // Fallback 2: try native fetch (Node 18+ built-in, works better on Windows)
629
- try {
630
- const controller = new AbortController();
631
- const timeoutId = setTimeout(() => controller.abort(), 5000);
632
-
633
- const fetchResponse = await fetch(`${apiUrl}/health`, {
634
- method: 'GET',
635
- signal: controller.signal,
636
- });
637
- clearTimeout(timeoutId);
638
-
639
- if (fetchResponse.ok) {
640
- const data = await fetchResponse.json() as { status?: string; healthy?: boolean };
641
- return data?.status === 'ok' || data?.healthy === true;
642
- }
643
- return fetchResponse.ok;
644
- } catch {
645
- return false;
646
- }
647
- }
536
+ } catch {
537
+ return false;
648
538
  }
649
539
  }
650
540
  }