vigthoria-cli 1.1.0 → 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,21 +51,39 @@ 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
+
54
75
  // Check for updates silently on startup (non-blocking)
55
76
  async function checkForUpdatesQuietly(): Promise<void> {
56
77
  try {
57
78
  const { execSync } = await import('child_process');
58
- const latestVersion = execSync('npm view vigthoria-cli version 2>/dev/null', {
79
+ const npmVersion = execSync('npm view vigthoria-cli version 2>/dev/null', {
59
80
  encoding: 'utf8',
60
81
  timeout: 5000
61
82
  }).trim();
62
83
 
63
- if (latestVersion && latestVersion !== VERSION) {
64
- console.log(chalk.yellow(`\nšŸ“¦ Update available: ${VERSION} → ${latestVersion}`));
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}`));
65
87
  console.log(chalk.gray(' Run `vigthoria update` to install\n'));
66
88
  }
67
89
  } catch {
@@ -99,14 +121,15 @@ async function main() {
99
121
  .description('AI-powered terminal coding assistant for Vigthoria Coder subscribers')
100
122
  .version(VERSION);
101
123
 
102
- // Chat command - Interactive mode
124
+ // Chat command - Interactive mode (Agent mode is default for best results)
103
125
  program
104
126
  .command('chat')
105
127
  .alias('c')
106
128
  .description('Start interactive chat with Vigthoria AI')
107
- .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')
108
130
  .option('-p, --project <path>', 'Set project context path', process.cwd())
109
- .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)')
110
133
  .option('-r, --resume', 'Resume last session for this project', false)
111
134
  .option('--auto-approve', 'Auto-approve agent actions (dangerous!)', false)
112
135
  .action(async (options) => {
@@ -198,6 +221,261 @@ async function main() {
198
221
  await review.run(file, options);
199
222
  });
200
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
+
201
479
  // Auth commands
202
480
  program
203
481
  .command('login')
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,