vigthoria-cli 1.0.2 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/src/index.ts CHANGED
@@ -11,6 +11,7 @@
11
11
  * vigthoria review <file> - Review code quality
12
12
  * vigthoria login - Authenticate with Vigthoria
13
13
  * vigthoria config - Configure settings
14
+ * vigthoria hub - Discover & activate API modules
14
15
  */
15
16
 
16
17
  import { Command } from 'commander';
@@ -21,6 +22,9 @@ import { ExplainCommand } from './commands/explain.js';
21
22
  import { AuthCommand } from './commands/auth.js';
22
23
  import { ConfigCommand } from './commands/config.js';
23
24
  import { ReviewCommand } from './commands/review.js';
25
+ import { HubCommand } from './commands/hub.js';
26
+ import { RepoCommand } from './commands/repo.js';
27
+ import { DeployCommand } from './commands/deploy.js';
24
28
  import { Config } from './utils/config.js';
25
29
  import { Logger } from './utils/logger.js';
26
30
  import chalk from 'chalk';
@@ -47,10 +51,46 @@ function getVersion(): string {
47
51
  } catch (e) {
48
52
  // Fallback to hardcoded version
49
53
  }
50
- return '1.0.1';
54
+ return '1.1.0';
51
55
  }
52
56
  const VERSION = getVersion();
53
57
 
58
+ /**
59
+ * Compare semantic versions properly
60
+ * Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
61
+ */
62
+ function compareVersions(v1: string, v2: string): number {
63
+ const parts1 = v1.split('.').map(Number);
64
+ const parts2 = v2.split('.').map(Number);
65
+
66
+ for (let i = 0; i < Math.max(parts1.length, parts2.length); i++) {
67
+ const p1 = parts1[i] || 0;
68
+ const p2 = parts2[i] || 0;
69
+ if (p1 < p2) return -1;
70
+ if (p1 > p2) return 1;
71
+ }
72
+ return 0;
73
+ }
74
+
75
+ // Check for updates silently on startup (non-blocking)
76
+ async function checkForUpdatesQuietly(): Promise<void> {
77
+ try {
78
+ const { execSync } = await import('child_process');
79
+ const npmVersion = execSync('npm view vigthoria-cli version 2>/dev/null', {
80
+ encoding: 'utf8',
81
+ timeout: 5000
82
+ }).trim();
83
+
84
+ // Only show update message if npm version is NEWER than current (not older)
85
+ if (npmVersion && compareVersions(npmVersion, VERSION) > 0) {
86
+ console.log(chalk.yellow(`\nšŸ“¦ Update available: ${VERSION} → ${npmVersion}`));
87
+ console.log(chalk.gray(' Run `vigthoria update` to install\n'));
88
+ }
89
+ } catch {
90
+ // Silently ignore - network issues shouldn't block CLI
91
+ }
92
+ }
93
+
54
94
  async function main() {
55
95
  const program = new Command();
56
96
  const config = new Config();
@@ -73,19 +113,23 @@ async function main() {
73
113
  console.log(chalk.cyan('ā•š' + '═'.repeat(boxWidth) + 'ā•'));
74
114
  console.log();
75
115
 
116
+ // Check for updates in background (don't wait)
117
+ checkForUpdatesQuietly();
118
+
76
119
  program
77
120
  .name('vigthoria')
78
121
  .description('AI-powered terminal coding assistant for Vigthoria Coder subscribers')
79
122
  .version(VERSION);
80
123
 
81
- // Chat command - Interactive mode
124
+ // Chat command - Interactive mode (Agent mode is default for best results)
82
125
  program
83
126
  .command('chat')
84
127
  .alias('c')
85
128
  .description('Start interactive chat with Vigthoria AI')
86
- .option('-m, --model <model>', 'Select AI model (fast, balanced, code, creative)', 'balanced')
129
+ .option('-m, --model <model>', 'Select AI model (fast, balanced, code, creative)', 'code')
87
130
  .option('-p, --project <path>', 'Set project context path', process.cwd())
88
- .option('-a, --agent', 'Enable agentic mode (Claude Code-like autonomous actions)', false)
131
+ .option('-a, --agent', 'Enable agentic mode (default: true for best quality)', true)
132
+ .option('--no-agent', 'Disable agentic mode (simple chat only)')
89
133
  .option('-r, --resume', 'Resume last session for this project', false)
90
134
  .option('--auto-approve', 'Auto-approve agent actions (dangerous!)', false)
91
135
  .action(async (options) => {
@@ -177,6 +221,261 @@ async function main() {
177
221
  await review.run(file, options);
178
222
  });
179
223
 
224
+ // ==================== HUB / MARKETPLACE COMMANDS ====================
225
+
226
+ // Hub command - Discover and activate API modules
227
+ const hubCommand = program
228
+ .command('hub')
229
+ .alias('marketplace')
230
+ .description('Discover, search, and activate Vigthoria API modules');
231
+
232
+ hubCommand
233
+ .command('discover')
234
+ .alias('d')
235
+ .description('Interactive module discovery - find the right APIs for your project')
236
+ .action(async () => {
237
+ const hub = new HubCommand(config, logger);
238
+ await hub.discover();
239
+ });
240
+
241
+ hubCommand
242
+ .command('list')
243
+ .alias('ls')
244
+ .description('List all available API modules')
245
+ .option('-c, --category <category>', 'Filter by category (payments, communication, ai, creative, media)')
246
+ .action(async (options) => {
247
+ const hub = new HubCommand(config, logger);
248
+ await hub.list(options);
249
+ });
250
+
251
+ hubCommand
252
+ .command('search <query>')
253
+ .alias('find')
254
+ .description('Semantic search for modules (e.g., "generate background music for my app")')
255
+ .action(async (query) => {
256
+ const hub = new HubCommand(config, logger);
257
+ await hub.search(query);
258
+ });
259
+
260
+ hubCommand
261
+ .command('activate <module>')
262
+ .alias('enable')
263
+ .description('Activate a module for your API key (enables pay-as-you-go)')
264
+ .action(async (module) => {
265
+ const hub = new HubCommand(config, logger);
266
+ await hub.activate(module);
267
+ });
268
+
269
+ hubCommand
270
+ .command('active')
271
+ .description('Show your currently active modules')
272
+ .action(async () => {
273
+ const hub = new HubCommand(config, logger);
274
+ await hub.active();
275
+ });
276
+
277
+ hubCommand
278
+ .command('info <module>')
279
+ .alias('details')
280
+ .description('Get detailed information about a module')
281
+ .action(async (module) => {
282
+ const hub = new HubCommand(config, logger);
283
+ await hub.info(module);
284
+ });
285
+
286
+ // Default hub action shows discover
287
+ hubCommand.action(async () => {
288
+ const hub = new HubCommand(config, logger);
289
+ await hub.discover();
290
+ });
291
+
292
+ // ==================== REPO COMMANDS ====================
293
+
294
+ // Repo command - Push/Pull projects to/from Vigthoria Repository
295
+ const repoCommand = program
296
+ .command('repo')
297
+ .alias('repository')
298
+ .description('Push and pull projects to/from your Vigthoria Repository');
299
+
300
+ repoCommand
301
+ .command('push [path]')
302
+ .alias('upload')
303
+ .description('Push current or specified project to Vigthoria Repo')
304
+ .option('-v, --visibility <type>', 'Set visibility (private, restricted, public)', 'private')
305
+ .option('-d, --description <text>', 'Project description')
306
+ .option('-f, --force', 'Overwrite existing project', false)
307
+ .action(async (pathArg, options) => {
308
+ const repo = new RepoCommand(config, logger);
309
+ await repo.push({
310
+ path: pathArg,
311
+ visibility: options.visibility,
312
+ description: options.description,
313
+ force: options.force
314
+ });
315
+ });
316
+
317
+ repoCommand
318
+ .command('pull <name>')
319
+ .alias('download')
320
+ .description('Pull a project from your Vigthoria Repo')
321
+ .option('-o, --output <path>', 'Output directory path')
322
+ .option('-f, --force', 'Overwrite existing directory', false)
323
+ .action(async (name, options) => {
324
+ const repo = new RepoCommand(config, logger);
325
+ await repo.pull(name, {
326
+ output: options.output,
327
+ force: options.force
328
+ });
329
+ });
330
+
331
+ repoCommand
332
+ .command('list')
333
+ .alias('ls')
334
+ .description('List all your projects in Vigthoria Repo')
335
+ .option('-v, --visibility <type>', 'Filter by visibility (private, restricted, public)')
336
+ .action(async (options) => {
337
+ const repo = new RepoCommand(config, logger);
338
+ await repo.list({ visibility: options.visibility });
339
+ });
340
+
341
+ repoCommand
342
+ .command('status')
343
+ .description('Show sync status of current project')
344
+ .action(async () => {
345
+ const repo = new RepoCommand(config, logger);
346
+ await repo.status();
347
+ });
348
+
349
+ repoCommand
350
+ .command('share <name>')
351
+ .description('Generate a shareable link for a project')
352
+ .option('-e, --expires <duration>', 'Link expiration (e.g., 7d, 24h, 30m)', '7d')
353
+ .action(async (name, options) => {
354
+ const repo = new RepoCommand(config, logger);
355
+ await repo.share(name, { expires: options.expires });
356
+ });
357
+
358
+ repoCommand
359
+ .command('delete <name>')
360
+ .alias('rm')
361
+ .description('Remove a project from your Vigthoria Repo')
362
+ .action(async (name) => {
363
+ const repo = new RepoCommand(config, logger);
364
+ await repo.delete(name);
365
+ });
366
+
367
+ repoCommand
368
+ .command('clone <url>')
369
+ .description('Clone a public project from Vigthoria Repo')
370
+ .option('-o, --output <path>', 'Output directory path')
371
+ .option('-f, --force', 'Overwrite existing directory', false)
372
+ .action(async (url, options) => {
373
+ const repo = new RepoCommand(config, logger);
374
+ await repo.clone(url, {
375
+ output: options.output,
376
+ force: options.force
377
+ });
378
+ });
379
+
380
+ // Default repo action shows list
381
+ repoCommand.action(async () => {
382
+ const repo = new RepoCommand(config, logger);
383
+ await repo.list({});
384
+ });
385
+
386
+ // ==================== DEPLOY COMMANDS ====================
387
+
388
+ // Deploy command - Host projects on Vigthoria
389
+ const deployCommand = program
390
+ .command('deploy')
391
+ .alias('host')
392
+ .description('Deploy and host your project on Vigthoria infrastructure');
393
+
394
+ deployCommand
395
+ .command('preview')
396
+ .description('Deploy to free preview URL')
397
+ .option('-p, --project <path>', 'Project directory path', process.cwd())
398
+ .action(async (options) => {
399
+ const deploy = new DeployCommand(config, logger);
400
+ await deploy.deployToPreview(options.project);
401
+ });
402
+
403
+ deployCommand
404
+ .command('subdomain <name>')
405
+ .description('Deploy to yourname.vigthoria.io')
406
+ .option('-p, --project <path>', 'Project directory path', process.cwd())
407
+ .action(async (name, options) => {
408
+ const deploy = new DeployCommand(config, logger);
409
+ await deploy.deployToSubdomain(name, options.project);
410
+ });
411
+
412
+ deployCommand
413
+ .command('custom <domain>')
414
+ .description('Deploy to your custom domain')
415
+ .option('-p, --project <path>', 'Project directory path', process.cwd())
416
+ .action(async (domain, options) => {
417
+ const deploy = new DeployCommand(config, logger);
418
+ await deploy.deployToCustomDomain(domain, options.project);
419
+ });
420
+
421
+ deployCommand
422
+ .command('list')
423
+ .alias('ls')
424
+ .description('List all your deployments')
425
+ .action(async () => {
426
+ const deploy = new DeployCommand(config, logger);
427
+ await deploy.list();
428
+ });
429
+
430
+ deployCommand
431
+ .command('plans')
432
+ .description('Show hosting plans and pricing')
433
+ .action(async () => {
434
+ const deploy = new DeployCommand(config, logger);
435
+ await deploy.showPlans();
436
+ });
437
+
438
+ deployCommand
439
+ .command('status [domain]')
440
+ .description('Check deployment status')
441
+ .action(async (domain) => {
442
+ const deploy = new DeployCommand(config, logger);
443
+ await deploy.status(domain);
444
+ });
445
+
446
+ deployCommand
447
+ .command('verify <domain>')
448
+ .description('Verify DNS configuration for custom domain')
449
+ .action(async (domain) => {
450
+ const deploy = new DeployCommand(config, logger);
451
+ await deploy.verify(domain);
452
+ });
453
+
454
+ deployCommand
455
+ .command('remove <domain>')
456
+ .alias('rm')
457
+ .description('Remove a deployment')
458
+ .action(async (domain) => {
459
+ const deploy = new DeployCommand(config, logger);
460
+ await deploy.remove(domain);
461
+ });
462
+
463
+ // Default deploy action shows interactive wizard
464
+ deployCommand
465
+ .option('-s, --subdomain <name>', 'Deploy to subdomain')
466
+ .option('-d, --domain <domain>', 'Deploy to custom domain')
467
+ .option('-p, --project <path>', 'Project directory path', process.cwd())
468
+ .action(async (options) => {
469
+ const deploy = new DeployCommand(config, logger);
470
+ await deploy.deploy({
471
+ subdomain: options.subdomain,
472
+ domain: options.domain,
473
+ project: options.project
474
+ });
475
+ });
476
+
477
+ // ==================== AUTH COMMANDS ====================
478
+
180
479
  // Auth commands
181
480
  program
182
481
  .command('login')
@@ -216,6 +515,46 @@ async function main() {
216
515
  await configCmd.run(options);
217
516
  });
218
517
 
518
+ // Update command - Check for and install updates
519
+ program
520
+ .command('update')
521
+ .alias('upgrade')
522
+ .description('Check for updates and upgrade Vigthoria CLI')
523
+ .option('-c, --check', 'Only check for updates, don\'t install')
524
+ .action(async (options) => {
525
+ const { execSync } = await import('child_process');
526
+
527
+ console.log(chalk.cyan('šŸ” Checking for updates...'));
528
+
529
+ try {
530
+ // Get latest version from npm
531
+ const latestVersion = execSync('npm view vigthoria-cli version', { encoding: 'utf8' }).trim();
532
+ const currentVersion = VERSION;
533
+
534
+ if (latestVersion === currentVersion) {
535
+ console.log(chalk.green(`āœ… You are running the latest version (${currentVersion})`));
536
+ return;
537
+ }
538
+
539
+ console.log(chalk.yellow(`šŸ“¦ Update available: ${currentVersion} → ${latestVersion}`));
540
+
541
+ if (options.check) {
542
+ console.log(chalk.gray('Run `vigthoria update` to install the update'));
543
+ return;
544
+ }
545
+
546
+ console.log(chalk.cyan('šŸ“„ Installing update...'));
547
+ execSync('npm install -g vigthoria-cli@latest', { stdio: 'inherit' });
548
+
549
+ console.log(chalk.green(`āœ… Updated to version ${latestVersion}`));
550
+ console.log(chalk.gray('Please restart the CLI to use the new version'));
551
+
552
+ } catch (error: any) {
553
+ console.error(chalk.red('āŒ Failed to check for updates:'), error.message);
554
+ console.log(chalk.gray('Try manually: npm install -g vigthoria-cli@latest'));
555
+ }
556
+ });
557
+
219
558
  // Init command - Initialize project
220
559
  program
221
560
  .command('init')
package/src/utils/api.ts CHANGED
@@ -299,26 +299,7 @@ export class APIClient {
299
299
  this.logger.debug('Ollama failed...');
300
300
  }
301
301
 
302
- // Strategy 3: Try ViAgen6 AI endpoint (authenticated fallback)
303
- if (this.config.isAuthenticated()) {
304
- try {
305
- const response = await this.client.post('/viagen6/api/ai/generate', {
306
- prompt: messages.map(m => `${m.role}: ${m.content}`).join('\n'),
307
- model: resolvedModel,
308
- max_tokens: this.config.get('preferences').maxTokens,
309
- });
310
-
311
- return {
312
- id: `viagen6-${Date.now()}`,
313
- message: response.data.code || response.data.response || response.data.content,
314
- model: model,
315
- };
316
- } catch (fallbackError) {
317
- // Continue to error
318
- }
319
- }
320
-
321
- throw new Error('All AI backends unavailable. Please check your connection or authentication.');
302
+ throw new Error('AI service unavailable. Please check your authentication with `vigthoria login` or try again later.');
322
303
  }
323
304
 
324
305
  // Map CLI model names to Ollama model names (for local fallback)
@@ -444,9 +425,9 @@ export class APIClient {
444
425
  });
445
426
  }
446
427
 
447
- // Code operations
428
+ // Code operations - Using Vigthoria Centralized API
448
429
  async generateCode(prompt: string, language: string, model: string): Promise<string> {
449
- const response = await this.client.post('/ai/generate', {
430
+ const response = await this.client.post('/api/ai/generate', {
450
431
  prompt,
451
432
  language,
452
433
  model: this.resolveModelId(model),
@@ -456,7 +437,7 @@ export class APIClient {
456
437
  }
457
438
 
458
439
  async explainCode(code: string, language: string): Promise<string> {
459
- const response = await this.client.post('/ai/explain', {
440
+ const response = await this.client.post('/api/ai/explain', {
460
441
  code,
461
442
  language,
462
443
  });
@@ -469,7 +450,7 @@ export class APIClient {
469
450
  issues: { type: string; line: number; message: string; severity: string }[];
470
451
  suggestions: string[];
471
452
  }> {
472
- const response = await this.client.post('/ai/review', {
453
+ const response = await this.client.post('/api/ai/review', {
473
454
  code,
474
455
  language,
475
456
  });
@@ -481,7 +462,7 @@ export class APIClient {
481
462
  fixed: string;
482
463
  changes: { line: number; before: string; after: string; reason: string }[];
483
464
  }> {
484
- const response = await this.client.post('/ai/fix', {
465
+ const response = await this.client.post('/api/ai/fix', {
485
466
  code,
486
467
  language,
487
468
  fixType,
@@ -493,29 +474,64 @@ export class APIClient {
493
474
  // Model resolution - maps short names to actual Vigthoria model IDs
494
475
  private resolveModelId(shortName: string): string {
495
476
  const modelMap: Record<string, string> = {
496
- // Vigthoria Native Models
477
+ // ═══════════════════════════════════════════════════════════════
478
+ // Vigthoria Native Models - Core Suite
479
+ // ═══════════════════════════════════════════════════════════════
497
480
  'fast': 'vigthoria-fast-1.7b',
498
481
  'mini': 'vigthoria-mini-0.6b',
499
- 'code': 'vigthoria-v2-code-8b',
500
482
  'balanced': 'vigthoria-balanced-4b',
483
+
484
+ // Code Models - Current & Future Versions
485
+ 'code': 'vigthoria-v2-code-8b',
486
+ 'code-v2': 'vigthoria-v2-code-8b',
487
+ 'code-v2-8b': 'vigthoria-v2-code-8b',
488
+ 'code-v3': 'vigthoria-v3-code-8b', // Future
489
+ 'code-v3-8b': 'vigthoria-v3-code-8b', // Future
490
+ 'code-v3-32b': 'vigthoria-v3-code-32b', // Future large model
491
+ 'code-v4': 'vigthoria-v4-code-8b', // Future
492
+ 'code-32b': 'vigthoria-v3-code-32b', // Future large model alias
493
+
494
+ // Creative Models
501
495
  'creative': 'vigthoria-creative-9b-v4',
496
+ 'creative-v3': 'vigthoria-creative-9b-v3',
497
+ 'creative-v4': 'vigthoria-creative-9b-v4',
498
+
499
+ // Music Model
502
500
  'music': 'vigthoria-music-master-4b',
501
+ 'music-master': 'vigthoria-music-master-4b',
502
+
503
503
  // Aliases
504
504
  'pro': 'vigthoria-balanced-4b',
505
505
  'ultra': 'vigthoria-creative-9b-v4',
506
+
506
507
  // Legacy Vigthoria models
507
508
  'master': 'vigthoria_master:latest',
508
509
  'c1': 'vigthoria_c1_m:latest',
509
510
  'm1': 'vigthoria_m1_m:latest',
510
- // External models
511
+
512
+ // ═══════════════════════════════════════════════════════════════
513
+ // External Models (via Ollama fallback)
514
+ // ═══════════════════════════════════════════════════════════════
511
515
  'qwen-coder': 'qwen2.5-coder:7b',
516
+ 'qwen-coder-7b': 'qwen2.5-coder:7b',
512
517
  'qwen-coder-32b': 'qwen2.5-coder:32b',
513
518
  'deepseek': 'deepseek-coder-v2:latest',
514
519
  'deepseek-r1': 'deepseek-r1:8b',
520
+ 'deepseek-r1-32b': 'deepseek-r1:32b',
515
521
  'llama3': 'llama3:8b-instruct-q4_0',
516
522
  'mixtral': 'mixtral:8x7b-instruct-v0.1-q4_K_M',
517
523
  };
518
524
 
525
+ // If already a full model ID (contains 'vigthoria' or known prefix), return as-is
526
+ if (shortName.includes('vigthoria') || shortName.includes(':') || shortName.includes('-')) {
527
+ // Check if it's a known short name first
528
+ if (modelMap[shortName]) {
529
+ return modelMap[shortName];
530
+ }
531
+ // Otherwise assume it's a direct model ID
532
+ return shortName;
533
+ }
534
+
519
535
  return modelMap[shortName] || shortName;
520
536
  }
521
537