vigthoria-cli 1.9.9 → 1.9.19
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 +5 -5
- package/dist/commands/auth.js +48 -65
- package/dist/commands/bridge.js +12 -19
- package/dist/commands/cancel.js +15 -22
- package/dist/commands/chat.d.ts +11 -0
- package/dist/commands/chat.js +404 -248
- package/dist/commands/config.js +31 -71
- package/dist/commands/deploy.js +83 -123
- package/dist/commands/device.d.ts +35 -0
- package/dist/commands/device.js +239 -0
- package/dist/commands/edit.js +32 -39
- package/dist/commands/explain.js +18 -25
- package/dist/commands/fork.js +22 -27
- package/dist/commands/generate.js +37 -44
- package/dist/commands/history.js +20 -25
- package/dist/commands/hub.js +95 -102
- package/dist/commands/index.js +41 -46
- package/dist/commands/legion.d.ts +1 -0
- package/dist/commands/legion.js +162 -209
- package/dist/commands/preview.js +60 -98
- package/dist/commands/replay.js +27 -32
- package/dist/commands/repo.js +103 -141
- package/dist/commands/review.js +29 -36
- package/dist/commands/security.js +5 -12
- package/dist/commands/update.js +15 -49
- package/dist/commands/workflow.d.ts +8 -1
- package/dist/commands/workflow.js +53 -19
- package/dist/index.js +409 -234
- package/dist/utils/api.d.ts +5 -0
- package/dist/utils/api.js +398 -176
- package/dist/utils/bridge-client.js +11 -52
- package/dist/utils/cli-state.d.ts +54 -0
- package/dist/utils/cli-state.js +185 -0
- package/dist/utils/config.d.ts +5 -0
- package/dist/utils/config.js +35 -14
- package/dist/utils/context-ranker.js +15 -21
- package/dist/utils/files.js +5 -42
- package/dist/utils/logger.js +42 -50
- package/dist/utils/post-write-validator.js +22 -29
- package/dist/utils/project-memory.d.ts +56 -0
- package/dist/utils/project-memory.js +289 -0
- package/dist/utils/session.d.ts +29 -3
- package/dist/utils/session.js +137 -85
- package/dist/utils/task-display.js +13 -20
- package/dist/utils/tools.d.ts +19 -0
- package/dist/utils/tools.js +84 -87
- package/dist/utils/workspace-cache.js +18 -26
- package/dist/utils/workspace-stream.js +26 -64
- package/install.ps1 +14 -0
- package/package.json +5 -3
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
- package/scripts/release/validate-no-go-gates.sh +2 -2
package/dist/index.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
"use strict";
|
|
3
2
|
/**
|
|
4
3
|
* Vigthoria CLI - AI-Powered Terminal Coding Assistant
|
|
5
4
|
*
|
|
@@ -16,76 +15,43 @@
|
|
|
16
15
|
* vigthoria workflow - Manage repeatable VigFlow workflows
|
|
17
16
|
* vigthoria operator - Start BMAD operator mode
|
|
18
17
|
*/
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
exports.__cliErrorHandlingReady = void 0;
|
|
57
|
-
exports.validateReleaseMetadata = validateReleaseMetadata;
|
|
58
|
-
exports.setupErrorHandlers = setupErrorHandlers;
|
|
59
|
-
exports.main = main;
|
|
60
|
-
const commander_1 = require("commander");
|
|
61
|
-
const chat_js_1 = require("./commands/chat.js");
|
|
62
|
-
const edit_js_1 = require("./commands/edit.js");
|
|
63
|
-
const generate_js_1 = require("./commands/generate.js");
|
|
64
|
-
const explain_js_1 = require("./commands/explain.js");
|
|
65
|
-
const auth_js_1 = require("./commands/auth.js");
|
|
66
|
-
const config_js_1 = require("./commands/config.js");
|
|
67
|
-
const review_js_1 = require("./commands/review.js");
|
|
68
|
-
const hub_js_1 = require("./commands/hub.js");
|
|
69
|
-
const repo_js_1 = require("./commands/repo.js");
|
|
70
|
-
const deploy_js_1 = require("./commands/deploy.js");
|
|
71
|
-
const bridge_js_1 = require("./commands/bridge.js");
|
|
72
|
-
const workflow_js_1 = require("./commands/workflow.js");
|
|
73
|
-
const preview_js_1 = require("./commands/preview.js");
|
|
74
|
-
const legion_js_1 = require("./commands/legion.js");
|
|
75
|
-
const history_js_1 = require("./commands/history.js");
|
|
76
|
-
const replay_js_1 = require("./commands/replay.js");
|
|
77
|
-
const fork_js_1 = require("./commands/fork.js");
|
|
78
|
-
const cancel_js_1 = require("./commands/cancel.js");
|
|
79
|
-
const security_js_1 = require("./commands/security.js");
|
|
80
|
-
const config_js_2 = require("./utils/config.js");
|
|
81
|
-
const logger_js_1 = require("./utils/logger.js");
|
|
82
|
-
const chalk_1 = __importDefault(require("chalk"));
|
|
83
|
-
const fs = __importStar(require("fs"));
|
|
84
|
-
const path = __importStar(require("path"));
|
|
85
|
-
const os = __importStar(require("os"));
|
|
86
|
-
const crypto_1 = require("crypto");
|
|
87
|
-
const axios_1 = __importDefault(require("axios"));
|
|
88
|
-
const api_js_1 = require("./utils/api.js");
|
|
18
|
+
import { Command } from 'commander';
|
|
19
|
+
import { ChatCommand } from './commands/chat.js';
|
|
20
|
+
import { EditCommand } from './commands/edit.js';
|
|
21
|
+
import { GenerateCommand } from './commands/generate.js';
|
|
22
|
+
import { ExplainCommand } from './commands/explain.js';
|
|
23
|
+
import { handleLogin, handleLogout, statusAction } from './commands/auth.js';
|
|
24
|
+
import { ConfigCommand } from './commands/config.js';
|
|
25
|
+
import { ReviewCommand } from './commands/review.js';
|
|
26
|
+
import { HubCommand } from './commands/hub.js';
|
|
27
|
+
import { RepoCommand } from './commands/repo.js';
|
|
28
|
+
import { DeployCommand } from './commands/deploy.js';
|
|
29
|
+
import { BridgeCommand } from './commands/bridge.js';
|
|
30
|
+
import { DeviceCommand } from './commands/device.js';
|
|
31
|
+
import { WorkflowCommand } from './commands/workflow.js';
|
|
32
|
+
import { PreviewCommand } from './commands/preview.js';
|
|
33
|
+
import { LegionCommand } from './commands/legion.js';
|
|
34
|
+
import { HistoryCommand } from './commands/history.js';
|
|
35
|
+
import { ReplayCommand } from './commands/replay.js';
|
|
36
|
+
import { ForkCommand } from './commands/fork.js';
|
|
37
|
+
import { CancelCommand } from './commands/cancel.js';
|
|
38
|
+
import { SecurityCommand } from './commands/security.js';
|
|
39
|
+
import { Config } from './utils/config.js';
|
|
40
|
+
import { Logger, CH } from './utils/logger.js';
|
|
41
|
+
import chalk from 'chalk';
|
|
42
|
+
import * as fs from 'fs';
|
|
43
|
+
import * as path from 'path';
|
|
44
|
+
import * as os from 'os';
|
|
45
|
+
import { fileURLToPath } from 'url';
|
|
46
|
+
import { createHash } from 'crypto';
|
|
47
|
+
import axios from 'axios';
|
|
48
|
+
// ESM shim — TypeScript emits ESM under "type": "module", so __dirname
|
|
49
|
+
// is not available natively. Restore the CommonJS-style helper so the
|
|
50
|
+
// pre-existing package-discovery logic continues to work unchanged.
|
|
51
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
52
|
+
const __dirname = path.dirname(__filename);
|
|
53
|
+
import { APIClient, sanitizeUserFacingErrorText } from './utils/api.js';
|
|
54
|
+
import { getCliStateFile, isOfflineMode, isSafeNpmPackageSpec, isUpdateCheckSuppressed, readCachedLatestVersion, readGatewayPreflightCache, writeCachedLatestVersion, writeGatewayPreflightCache, } from './utils/cli-state.js';
|
|
89
55
|
function isApiError(error) {
|
|
90
56
|
return Boolean(error &&
|
|
91
57
|
typeof error === 'object' &&
|
|
@@ -122,12 +88,12 @@ function getVersion() {
|
|
|
122
88
|
catch (e) {
|
|
123
89
|
const message = e instanceof Error ? e.message : String(e);
|
|
124
90
|
if (process.env.VIGTHORIA_DEBUG_VERSION === '1') {
|
|
125
|
-
console.error(
|
|
91
|
+
console.error(chalk.gray(`Unable to read package version: ${message}`));
|
|
126
92
|
}
|
|
127
93
|
}
|
|
128
94
|
return '0.0.0';
|
|
129
95
|
}
|
|
130
|
-
function validateReleaseMetadata() {
|
|
96
|
+
export function validateReleaseMetadata() {
|
|
131
97
|
try {
|
|
132
98
|
const packagePath = getPackageMetadataPaths().find((candidate) => fs.existsSync(candidate));
|
|
133
99
|
if (!packagePath) {
|
|
@@ -164,7 +130,7 @@ function validateReleaseMetadata() {
|
|
|
164
130
|
catch (error) {
|
|
165
131
|
const message = error instanceof Error ? error.message : String(error);
|
|
166
132
|
if (process.env.VIGTHORIA_DEBUG_VERSION === '1') {
|
|
167
|
-
console.error(
|
|
133
|
+
console.error(chalk.gray(`Release metadata validation failed: ${message}`));
|
|
168
134
|
}
|
|
169
135
|
return false;
|
|
170
136
|
}
|
|
@@ -204,7 +170,7 @@ function resolveManifestEntry(manifest, channel) {
|
|
|
204
170
|
return null;
|
|
205
171
|
}
|
|
206
172
|
async function downloadFile(url, targetPath) {
|
|
207
|
-
const response = await
|
|
173
|
+
const response = await axios.get(url, {
|
|
208
174
|
responseType: 'arraybuffer',
|
|
209
175
|
timeout: 20000,
|
|
210
176
|
maxRedirects: 5,
|
|
@@ -213,7 +179,7 @@ async function downloadFile(url, targetPath) {
|
|
|
213
179
|
fs.writeFileSync(targetPath, Buffer.from(response.data));
|
|
214
180
|
}
|
|
215
181
|
function sha256File(filePath) {
|
|
216
|
-
const hash =
|
|
182
|
+
const hash = createHash('sha256');
|
|
217
183
|
const data = fs.readFileSync(filePath);
|
|
218
184
|
hash.update(data);
|
|
219
185
|
return hash.digest('hex');
|
|
@@ -287,7 +253,7 @@ async function installGlobalPackageWithNpm(packageSpec) {
|
|
|
287
253
|
let lastError = null;
|
|
288
254
|
for (const attempt of attempts) {
|
|
289
255
|
try {
|
|
290
|
-
console.log(
|
|
256
|
+
console.log(chalk.gray(`[update] installer executable: ${attempt.command}${attempt.shell ? ' (shell)' : ''}`));
|
|
291
257
|
execFileSync(attempt.command, attempt.args, {
|
|
292
258
|
stdio: 'inherit',
|
|
293
259
|
windowsHide: true,
|
|
@@ -298,40 +264,57 @@ async function installGlobalPackageWithNpm(packageSpec) {
|
|
|
298
264
|
catch (error) {
|
|
299
265
|
lastError = error;
|
|
300
266
|
const code = error?.code || error?.status || 'unknown';
|
|
301
|
-
console.error(
|
|
267
|
+
console.error(chalk.yellow(`[update] install attempt failed via ${attempt.label}: ${code}`));
|
|
302
268
|
}
|
|
303
269
|
}
|
|
304
270
|
const finalCode = lastError?.code || lastError?.status || 'unknown';
|
|
305
271
|
throw new Error(`Unable to launch npm installer after ${attempts.length} attempt(s). Last error: ${finalCode}`);
|
|
306
272
|
}
|
|
307
|
-
|
|
273
|
+
function renderUpdateBanner(latestVersion) {
|
|
274
|
+
if (compareVersions(latestVersion, '1.4.0') >= 0 && compareVersions(VERSION, '1.4.0') < 0) {
|
|
275
|
+
console.log(chalk.red.bold(`\n${CH.warnEmoji} SECURITY UPDATE AVAILABLE`));
|
|
276
|
+
console.log(chalk.red(` Version ${VERSION} has security vulnerabilities.`));
|
|
277
|
+
console.log(chalk.yellow(` Please update to ${latestVersion} immediately:`));
|
|
278
|
+
console.log(chalk.white.bold(' npm install -g vigthoria-cli@latest\n'));
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
console.log(chalk.yellow(`\n${CH.warnEmoji} Update available: ${VERSION} -> ${latestVersion}`));
|
|
282
|
+
console.log(chalk.gray(' Run `vigthoria update` to install\n'));
|
|
283
|
+
}
|
|
284
|
+
}
|
|
285
|
+
// Check for updates quietly on startup. Cached (24 h) so we never block
|
|
286
|
+
// startup on `npm view`. Honours VIGTHORIA_OFFLINE / VIGTHORIA_NO_UPDATE_CHECK.
|
|
308
287
|
async function checkForUpdatesQuietly() {
|
|
288
|
+
if (isUpdateCheckSuppressed()) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const cached = readCachedLatestVersion();
|
|
292
|
+
if (cached) {
|
|
293
|
+
if (compareVersions(cached, VERSION) > 0) {
|
|
294
|
+
renderUpdateBanner(cached);
|
|
295
|
+
}
|
|
296
|
+
return;
|
|
297
|
+
}
|
|
298
|
+
// Cache miss: probe npm registry in the background, with a hard 5 s
|
|
299
|
+
// timeout. Result is cached for 24 h so subsequent runs are instant.
|
|
309
300
|
try {
|
|
310
301
|
const { execSync } = await import('child_process');
|
|
311
|
-
// Cross-platform: use stdio: 'pipe' to suppress output on Windows
|
|
312
302
|
const npmVersion = execSync('npm view vigthoria-cli version', {
|
|
313
303
|
encoding: 'utf8',
|
|
314
304
|
timeout: 5000,
|
|
315
|
-
stdio: ['pipe', 'pipe', 'pipe'],
|
|
305
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
316
306
|
windowsHide: true,
|
|
317
307
|
}).trim();
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
console.log(chalk_1.default.yellow(` Please update to ${npmVersion} immediately:`));
|
|
325
|
-
console.log(chalk_1.default.white.bold(' npm install -g vigthoria-cli@latest\n'));
|
|
326
|
-
}
|
|
327
|
-
else {
|
|
328
|
-
console.log(chalk_1.default.yellow(`\n📦 Update available: ${VERSION} → ${npmVersion}`));
|
|
329
|
-
console.log(chalk_1.default.gray(' Run `vigthoria update` to install\n'));
|
|
330
|
-
}
|
|
308
|
+
if (!npmVersion) {
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
writeCachedLatestVersion(npmVersion);
|
|
312
|
+
if (compareVersions(npmVersion, VERSION) > 0) {
|
|
313
|
+
renderUpdateBanner(npmVersion);
|
|
331
314
|
}
|
|
332
315
|
}
|
|
333
316
|
catch {
|
|
334
|
-
//
|
|
317
|
+
// Network or npm failure should never block CLI; do not cache failure.
|
|
335
318
|
}
|
|
336
319
|
}
|
|
337
320
|
const VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE = 'Vigthoria Gate way user authentification failed. Please log out and login again.';
|
|
@@ -349,7 +332,7 @@ function isAuthProtectedCommand(command) {
|
|
|
349
332
|
'chat', 'c', 'chat-resume',
|
|
350
333
|
'agent', 'a', 'operator', 'op',
|
|
351
334
|
'edit', 'e', 'generate', 'g', 'explain', 'x', 'fix', 'f', 'review', 'r',
|
|
352
|
-
'workflow', 'flow', 'hub', 'marketplace', 'deploy', 'host', 'preview',
|
|
335
|
+
'workflow', 'flow', 'hub', 'marketplace', 'deploy', 'host', 'preview', 'device',
|
|
353
336
|
'legion', 'history', 'runs', 'replay', 'fork', 'cancel',
|
|
354
337
|
'repo', 'repository',
|
|
355
338
|
]);
|
|
@@ -359,19 +342,30 @@ async function enforceGatewayAuthSession(config, logger, jsonOutputRequested) {
|
|
|
359
342
|
if (!config.isAuthenticated()) {
|
|
360
343
|
return true;
|
|
361
344
|
}
|
|
362
|
-
|
|
345
|
+
// Offline mode disables every outbound preflight call.
|
|
346
|
+
if (isOfflineMode()) {
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
// Short-lived cache so back-to-back CLI invocations don't re-probe.
|
|
350
|
+
const cached = readGatewayPreflightCache();
|
|
351
|
+
if (cached === true) {
|
|
352
|
+
return true;
|
|
353
|
+
}
|
|
354
|
+
const api = new APIClient(config, logger);
|
|
363
355
|
try {
|
|
364
356
|
const tokenCheck = await api.validateToken();
|
|
365
357
|
if (!tokenCheck.valid) {
|
|
358
|
+
writeGatewayPreflightCache(false);
|
|
366
359
|
if (jsonOutputRequested) {
|
|
367
360
|
process.exitCode = 1;
|
|
368
361
|
console.log(JSON.stringify({ success: false, error: VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE }, null, 2));
|
|
369
362
|
}
|
|
370
363
|
else {
|
|
371
|
-
console.log(
|
|
364
|
+
console.log(chalk.red(VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE));
|
|
372
365
|
}
|
|
373
366
|
return false;
|
|
374
367
|
}
|
|
368
|
+
writeGatewayPreflightCache(true);
|
|
375
369
|
return true;
|
|
376
370
|
}
|
|
377
371
|
catch {
|
|
@@ -382,6 +376,14 @@ async function enforceGatewayAuthSession(config, logger, jsonOutputRequested) {
|
|
|
382
376
|
api.destroy();
|
|
383
377
|
}
|
|
384
378
|
}
|
|
379
|
+
function scrubMessageForUser(message) {
|
|
380
|
+
try {
|
|
381
|
+
return sanitizeUserFacingErrorText(message) || message;
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
return message;
|
|
385
|
+
}
|
|
386
|
+
}
|
|
385
387
|
function normalizeCliError(error) {
|
|
386
388
|
if (error instanceof Error) {
|
|
387
389
|
const extended = error;
|
|
@@ -390,8 +392,9 @@ function normalizeCliError(error) {
|
|
|
390
392
|
: typeof extended.response?.data?.message === 'string'
|
|
391
393
|
? extended.response.data.message
|
|
392
394
|
: undefined;
|
|
395
|
+
const rawMessage = responseMessage || extended.message || 'An unexpected CLI error occurred.';
|
|
393
396
|
return {
|
|
394
|
-
message:
|
|
397
|
+
message: scrubMessageForUser(rawMessage),
|
|
395
398
|
code: extended.code,
|
|
396
399
|
status: extended.status || extended.statusCode || extended.response?.status,
|
|
397
400
|
details: extended.details || extended.response?.data,
|
|
@@ -399,15 +402,17 @@ function normalizeCliError(error) {
|
|
|
399
402
|
}
|
|
400
403
|
if (error && typeof error === 'object') {
|
|
401
404
|
const value = error;
|
|
405
|
+
const rawMessage = typeof value.message === 'string' && value.message.trim() ? value.message : 'An unexpected CLI error occurred.';
|
|
402
406
|
return {
|
|
403
|
-
message:
|
|
407
|
+
message: scrubMessageForUser(rawMessage),
|
|
404
408
|
code: typeof value.code === 'string' || typeof value.code === 'number' ? value.code : undefined,
|
|
405
409
|
status: typeof value.status === 'number' ? value.status : undefined,
|
|
406
410
|
details: value.details,
|
|
407
411
|
};
|
|
408
412
|
}
|
|
413
|
+
const rawMessage = typeof error === 'string' && error.trim() ? error : 'An unexpected CLI error occurred.';
|
|
409
414
|
return {
|
|
410
|
-
message:
|
|
415
|
+
message: scrubMessageForUser(rawMessage),
|
|
411
416
|
};
|
|
412
417
|
}
|
|
413
418
|
function formatCliError(error, jsonOutputRequested = false) {
|
|
@@ -415,11 +420,11 @@ function formatCliError(error, jsonOutputRequested = false) {
|
|
|
415
420
|
if (jsonOutputRequested) {
|
|
416
421
|
return JSON.stringify({ success: false, error: normalized.message, code: normalized.code, status: normalized.status, details: normalized.details }, null, 2);
|
|
417
422
|
}
|
|
418
|
-
const parts = [
|
|
423
|
+
const parts = [chalk.red('Error:'), normalized.message];
|
|
419
424
|
if (normalized.code)
|
|
420
|
-
parts.push(
|
|
425
|
+
parts.push(chalk.gray(`[${normalized.code}]`));
|
|
421
426
|
if (normalized.status)
|
|
422
|
-
parts.push(
|
|
427
|
+
parts.push(chalk.gray(`(HTTP ${normalized.status})`));
|
|
423
428
|
return parts.join(' ');
|
|
424
429
|
}
|
|
425
430
|
function reportCliError(error, jsonOutputRequested = false) {
|
|
@@ -436,7 +441,7 @@ function handleFatalCliError(error, jsonOutputRequested = false) {
|
|
|
436
441
|
process.exitCode = 1;
|
|
437
442
|
}
|
|
438
443
|
let errorHandlersInstalled = false;
|
|
439
|
-
function setupErrorHandlers() {
|
|
444
|
+
export function setupErrorHandlers() {
|
|
440
445
|
if (errorHandlersInstalled) {
|
|
441
446
|
return;
|
|
442
447
|
}
|
|
@@ -455,20 +460,22 @@ function setupErrorHandlers() {
|
|
|
455
460
|
}
|
|
456
461
|
});
|
|
457
462
|
}
|
|
458
|
-
async function main(args) {
|
|
459
|
-
const program = new
|
|
460
|
-
const config = new
|
|
461
|
-
const logger = new
|
|
463
|
+
export async function main(args) {
|
|
464
|
+
const program = new Command();
|
|
465
|
+
const config = new Config();
|
|
466
|
+
const logger = new Logger();
|
|
462
467
|
const invokedBinaryName = getInvokedBinaryName();
|
|
463
468
|
const argv = [...args];
|
|
464
469
|
const firstArg = argv[2];
|
|
465
470
|
const jsonOutputRequested = argv.includes('--json');
|
|
466
471
|
const directPromptRequested = argv.includes('--prompt') || argv.includes('-P');
|
|
472
|
+
const helpOrVersionRequested = argv.some((token) => token === '--help' || token === '-h' || token === '--version' || token === '-V' ||
|
|
473
|
+
token === 'help' || token === 'version');
|
|
467
474
|
const isLegionCortexRequest = invokedBinaryName === 'vigthoria' && argv[2] === 'legion' && argv.includes('--cortex');
|
|
468
475
|
if (invokedBinaryName === 'vigthoria-chat') {
|
|
469
476
|
const knownCommands = new Set([
|
|
470
477
|
'chat', 'chat-resume', 'agent', 'edit', 'generate', 'explain', 'fix', 'review', 'cancel',
|
|
471
|
-
'hub', 'repo', 'deploy', 'operator', 'workflow', 'flow', 'security', 'vsec', 'login', 'logout', 'status', 'config', 'update',
|
|
478
|
+
'hub', 'repo', 'deploy', 'operator', 'workflow', 'flow', 'device', 'security', 'vsec', 'login', 'logout', 'status', 'config', 'update',
|
|
472
479
|
'--help', '-h', '--version', '-V', 'help', 'version',
|
|
473
480
|
]);
|
|
474
481
|
if (!firstArg || firstArg.startsWith('-') || !knownCommands.has(firstArg)) {
|
|
@@ -494,18 +501,25 @@ async function main(args) {
|
|
|
494
501
|
// Calculate padding for centering
|
|
495
502
|
const titlePad = Math.floor((boxWidth - 4 - titleText.length) / 2);
|
|
496
503
|
const versionPad = Math.floor((boxWidth - 4 - versionText.length) / 2);
|
|
497
|
-
if (process.env.VIGTHORIA_NO_BANNER !== '1' &&
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
console.log(
|
|
502
|
-
console.log(
|
|
503
|
-
console.log(
|
|
504
|
+
if (process.env.VIGTHORIA_NO_BANNER !== '1' &&
|
|
505
|
+
!jsonOutputRequested &&
|
|
506
|
+
!directPromptRequested &&
|
|
507
|
+
!helpOrVersionRequested) {
|
|
508
|
+
console.log(chalk.cyan(CH.dTl + CH.dH.repeat(boxWidth) + CH.dTr));
|
|
509
|
+
console.log(chalk.cyan(CH.dV + ' '.repeat(boxWidth) + CH.dV));
|
|
510
|
+
console.log(chalk.cyan(CH.dV) + ' '.repeat(titlePad) + chalk.bold.white('VIGTHORIA CLI') + chalk.cyan(' - AI-Powered Coding Assistant') + ' '.repeat(boxWidth - titlePad - titleText.length) + chalk.cyan(CH.dV));
|
|
511
|
+
console.log(chalk.cyan(CH.dV) + ' '.repeat(versionPad) + chalk.gray(versionText) + ' '.repeat(boxWidth - versionPad - versionText.length) + chalk.cyan(CH.dV));
|
|
512
|
+
console.log(chalk.cyan(CH.dV + ' '.repeat(boxWidth) + CH.dV));
|
|
513
|
+
console.log(chalk.cyan(CH.dBl + CH.dH.repeat(boxWidth) + CH.dBr));
|
|
504
514
|
console.log();
|
|
505
515
|
}
|
|
506
|
-
// Check for updates in background (don't wait)
|
|
507
|
-
|
|
508
|
-
|
|
516
|
+
// Check for updates in background (don't wait). Skip for JSON / direct
|
|
517
|
+
// prompt / help / version invocations to keep them deterministic.
|
|
518
|
+
if (!isUpdateCheckSuppressed() &&
|
|
519
|
+
!jsonOutputRequested &&
|
|
520
|
+
!directPromptRequested &&
|
|
521
|
+
!helpOrVersionRequested) {
|
|
522
|
+
void checkForUpdatesQuietly();
|
|
509
523
|
}
|
|
510
524
|
program
|
|
511
525
|
.name(invokedBinaryName === 'vigthoria-chat' ? 'vigthoria-chat' : 'vigthoria')
|
|
@@ -528,7 +542,7 @@ async function main(args) {
|
|
|
528
542
|
.option('--auto-approve', 'Auto-approve agent actions (dangerous!)', false)
|
|
529
543
|
.option('--bridge <url>', 'Connect to Vigthoria Commando Bridge for remote admin observability')
|
|
530
544
|
.action(async (options) => {
|
|
531
|
-
const chat = new
|
|
545
|
+
const chat = new ChatCommand(config, logger);
|
|
532
546
|
await chat.run({
|
|
533
547
|
model: options.model,
|
|
534
548
|
project: options.project,
|
|
@@ -557,7 +571,7 @@ async function main(args) {
|
|
|
557
571
|
.option('--auto-approve', 'Auto-approve agent actions (dangerous!)', false)
|
|
558
572
|
.option('--bridge <url>', 'Connect to Vigthoria Commando Bridge for remote admin observability')
|
|
559
573
|
.action(async (options) => {
|
|
560
|
-
const chat = new
|
|
574
|
+
const chat = new ChatCommand(config, logger);
|
|
561
575
|
await chat.run({
|
|
562
576
|
model: options.model,
|
|
563
577
|
project: options.project,
|
|
@@ -587,7 +601,7 @@ async function main(args) {
|
|
|
587
601
|
.option('--auto-approve', 'Auto-approve all actions (dangerous!)', false)
|
|
588
602
|
.option('--bridge <url>', 'Connect to Vigthoria Commando Bridge for remote admin observability')
|
|
589
603
|
.action(async (options) => {
|
|
590
|
-
const chat = new
|
|
604
|
+
const chat = new ChatCommand(config, logger);
|
|
591
605
|
await chat.run({
|
|
592
606
|
model: options.model,
|
|
593
607
|
project: options.project,
|
|
@@ -615,7 +629,7 @@ async function main(args) {
|
|
|
615
629
|
.option('--json', 'Emit machine-readable JSON output for direct prompt runs', false)
|
|
616
630
|
.option('--bridge <url>', 'Connect to Vigthoria Commando Bridge for remote admin observability')
|
|
617
631
|
.action(async (options) => {
|
|
618
|
-
const chat = new
|
|
632
|
+
const chat = new ChatCommand(config, logger);
|
|
619
633
|
await chat.run({
|
|
620
634
|
model: options.model,
|
|
621
635
|
project: options.project,
|
|
@@ -636,9 +650,98 @@ async function main(args) {
|
|
|
636
650
|
.command('status')
|
|
637
651
|
.description('Show live DevTools Bridge status')
|
|
638
652
|
.action(async () => {
|
|
639
|
-
const bridge = new
|
|
653
|
+
const bridge = new BridgeCommand(config, logger);
|
|
640
654
|
await bridge.status();
|
|
641
655
|
});
|
|
656
|
+
const deviceCommand = program
|
|
657
|
+
.command('device')
|
|
658
|
+
.alias('adb')
|
|
659
|
+
.description('Android Developer Bridge commands via local ADB');
|
|
660
|
+
deviceCommand
|
|
661
|
+
.command('status')
|
|
662
|
+
.description('Show ADB availability and connected Android devices')
|
|
663
|
+
.option('--json', 'Emit JSON output', false)
|
|
664
|
+
.action(async (options) => {
|
|
665
|
+
const device = new DeviceCommand(config, logger);
|
|
666
|
+
await device.status(options);
|
|
667
|
+
});
|
|
668
|
+
deviceCommand
|
|
669
|
+
.command('list')
|
|
670
|
+
.description('List connected Android devices')
|
|
671
|
+
.option('--json', 'Emit JSON output', false)
|
|
672
|
+
.action(async (options) => {
|
|
673
|
+
const device = new DeviceCommand(config, logger);
|
|
674
|
+
await device.list(options);
|
|
675
|
+
});
|
|
676
|
+
deviceCommand
|
|
677
|
+
.command('screenshot')
|
|
678
|
+
.description('Capture a screenshot from an Android device')
|
|
679
|
+
.option('-d, --device <id>', 'ADB device id')
|
|
680
|
+
.option('-o, --output <path>', 'Output PNG path')
|
|
681
|
+
.action(async (options) => {
|
|
682
|
+
const device = new DeviceCommand(config, logger);
|
|
683
|
+
await device.screenshot(options);
|
|
684
|
+
});
|
|
685
|
+
deviceCommand
|
|
686
|
+
.command('install <apk>')
|
|
687
|
+
.description('Install or update an APK on an Android device')
|
|
688
|
+
.option('-d, --device <id>', 'ADB device id')
|
|
689
|
+
.option('--json', 'Emit JSON output', false)
|
|
690
|
+
.action(async (apk, options) => {
|
|
691
|
+
const device = new DeviceCommand(config, logger);
|
|
692
|
+
await device.install(apk, options);
|
|
693
|
+
});
|
|
694
|
+
deviceCommand
|
|
695
|
+
.command('launch <package>')
|
|
696
|
+
.description('Launch an Android app by package name')
|
|
697
|
+
.option('-d, --device <id>', 'ADB device id')
|
|
698
|
+
.option('-a, --activity <activity>', 'Activity class, for example .MainActivity')
|
|
699
|
+
.option('--json', 'Emit JSON output', false)
|
|
700
|
+
.action(async (packageName, options) => {
|
|
701
|
+
const device = new DeviceCommand(config, logger);
|
|
702
|
+
await device.launch(packageName, options);
|
|
703
|
+
});
|
|
704
|
+
deviceCommand
|
|
705
|
+
.command('logs')
|
|
706
|
+
.description('Read Android logcat output')
|
|
707
|
+
.option('-d, --device <id>', 'ADB device id')
|
|
708
|
+
.option('-n, --lines <count>', 'Number of log lines for snapshot mode', '250')
|
|
709
|
+
.option('-f, --follow', 'Follow logcat until interrupted', false)
|
|
710
|
+
.option('--json', 'Emit JSON output for snapshot mode', false)
|
|
711
|
+
.action(async (options) => {
|
|
712
|
+
const device = new DeviceCommand(config, logger);
|
|
713
|
+
await device.logs(options);
|
|
714
|
+
});
|
|
715
|
+
deviceCommand
|
|
716
|
+
.command('tcpip')
|
|
717
|
+
.description('Enable wireless ADB tcpip mode on the selected USB-connected device')
|
|
718
|
+
.option('-d, --device <id>', 'ADB device id')
|
|
719
|
+
.option('-p, --port <port>', 'Wireless ADB port', '5555')
|
|
720
|
+
.option('--json', 'Emit JSON output', false)
|
|
721
|
+
.action(async (options) => {
|
|
722
|
+
const device = new DeviceCommand(config, logger);
|
|
723
|
+
await device.tcpip(options);
|
|
724
|
+
});
|
|
725
|
+
deviceCommand
|
|
726
|
+
.command('connect <address>')
|
|
727
|
+
.description('Connect to a wireless ADB device, for example 192.168.1.30:5555')
|
|
728
|
+
.option('--json', 'Emit JSON output', false)
|
|
729
|
+
.action(async (address, options) => {
|
|
730
|
+
const device = new DeviceCommand(config, logger);
|
|
731
|
+
await device.connect(address, options);
|
|
732
|
+
});
|
|
733
|
+
deviceCommand
|
|
734
|
+
.command('disconnect [address]')
|
|
735
|
+
.description('Disconnect a wireless ADB device')
|
|
736
|
+
.option('--json', 'Emit JSON output', false)
|
|
737
|
+
.action(async (address, options) => {
|
|
738
|
+
const device = new DeviceCommand(config, logger);
|
|
739
|
+
await device.disconnect(address, options);
|
|
740
|
+
});
|
|
741
|
+
deviceCommand.action(async () => {
|
|
742
|
+
const device = new DeviceCommand(config, logger);
|
|
743
|
+
await device.status({});
|
|
744
|
+
});
|
|
642
745
|
// Security command group - Security DevOps scans and fix plans
|
|
643
746
|
const securityCommand = program
|
|
644
747
|
.command('security')
|
|
@@ -650,7 +753,7 @@ async function main(args) {
|
|
|
650
753
|
.option('-d, --dir <path>', 'Directory to scan (default: current directory)')
|
|
651
754
|
.option('--json', 'Emit JSON output', false)
|
|
652
755
|
.action(async (options) => {
|
|
653
|
-
const security = new
|
|
756
|
+
const security = new SecurityCommand(config, logger);
|
|
654
757
|
await security.scan({ dir: options.dir, json: options.json });
|
|
655
758
|
});
|
|
656
759
|
securityCommand
|
|
@@ -659,7 +762,7 @@ async function main(args) {
|
|
|
659
762
|
.option('-d, --dir <path>', 'Directory to score (default: current directory)')
|
|
660
763
|
.option('--json', 'Emit JSON output', false)
|
|
661
764
|
.action(async (options) => {
|
|
662
|
-
const security = new
|
|
765
|
+
const security = new SecurityCommand(config, logger);
|
|
663
766
|
await security.score({ dir: options.dir, json: options.json });
|
|
664
767
|
});
|
|
665
768
|
securityCommand
|
|
@@ -670,7 +773,7 @@ async function main(args) {
|
|
|
670
773
|
.option('--apply', 'Request auto-apply mode (safe mode still requires explicit patching)', false)
|
|
671
774
|
.option('--json', 'Emit JSON output', false)
|
|
672
775
|
.action(async (options) => {
|
|
673
|
-
const security = new
|
|
776
|
+
const security = new SecurityCommand(config, logger);
|
|
674
777
|
await security.fix({ dir: options.dir, issueId: options.issueId, apply: options.apply, json: options.json });
|
|
675
778
|
});
|
|
676
779
|
// Edit command - Edit files with AI
|
|
@@ -682,7 +785,7 @@ async function main(args) {
|
|
|
682
785
|
.option('-m, --model <model>', 'Select AI model', 'code')
|
|
683
786
|
.option('--apply', 'Automatically apply changes without confirmation', false)
|
|
684
787
|
.action(async (file, options) => {
|
|
685
|
-
const edit = new
|
|
788
|
+
const edit = new EditCommand(config, logger);
|
|
686
789
|
await edit.run(file, options);
|
|
687
790
|
});
|
|
688
791
|
// Generate command - Generate code
|
|
@@ -695,7 +798,7 @@ async function main(args) {
|
|
|
695
798
|
.option('-m, --model <model>', 'Select AI model', 'code')
|
|
696
799
|
.option('-p, --pro', 'Senior Developer Mode: plan, generate, quality check (recommended)', false)
|
|
697
800
|
.action(async (description, options) => {
|
|
698
|
-
const generate = new
|
|
801
|
+
const generate = new GenerateCommand(config, logger);
|
|
699
802
|
await generate.run(description, options);
|
|
700
803
|
});
|
|
701
804
|
// Explain command - Explain code
|
|
@@ -706,7 +809,7 @@ async function main(args) {
|
|
|
706
809
|
.option('-l, --lines <range>', 'Line range (e.g., 1-50)')
|
|
707
810
|
.option('-d, --detail <level>', 'Detail level (brief, normal, detailed)', 'normal')
|
|
708
811
|
.action(async (file, options) => {
|
|
709
|
-
const explain = new
|
|
812
|
+
const explain = new ExplainCommand(config, logger);
|
|
710
813
|
await explain.run(file, options);
|
|
711
814
|
});
|
|
712
815
|
// Fix command - Fix code issues
|
|
@@ -722,7 +825,7 @@ async function main(args) {
|
|
|
722
825
|
process.exitCode = 1;
|
|
723
826
|
return;
|
|
724
827
|
}
|
|
725
|
-
const edit = new
|
|
828
|
+
const edit = new EditCommand(config, logger);
|
|
726
829
|
await edit.fix(file, options);
|
|
727
830
|
});
|
|
728
831
|
// Review command - Code review
|
|
@@ -732,7 +835,7 @@ async function main(args) {
|
|
|
732
835
|
.description('Review code quality')
|
|
733
836
|
.option('-f, --format <format>', 'Output format (text, json, markdown)', 'text')
|
|
734
837
|
.action(async (file, options) => {
|
|
735
|
-
const review = new
|
|
838
|
+
const review = new ReviewCommand(config, logger);
|
|
736
839
|
await review.run(file, options);
|
|
737
840
|
});
|
|
738
841
|
const workflowCommand = program
|
|
@@ -747,7 +850,7 @@ async function main(args) {
|
|
|
747
850
|
.option('-s, --search <query>', 'Search template names, descriptions, and tags')
|
|
748
851
|
.option('--json', 'Emit machine-readable JSON output', false)
|
|
749
852
|
.action(async (options) => {
|
|
750
|
-
const workflow = new
|
|
853
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
751
854
|
await workflow.templates(options);
|
|
752
855
|
});
|
|
753
856
|
workflowCommand
|
|
@@ -756,7 +859,7 @@ async function main(args) {
|
|
|
756
859
|
.description('List workflows created for the current account')
|
|
757
860
|
.option('--json', 'Emit machine-readable JSON output', false)
|
|
758
861
|
.action(async (options) => {
|
|
759
|
-
const workflow = new
|
|
862
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
760
863
|
await workflow.list(options);
|
|
761
864
|
});
|
|
762
865
|
workflowCommand
|
|
@@ -766,28 +869,30 @@ async function main(args) {
|
|
|
766
869
|
.option('-v, --variables <json>', 'Template variables as a JSON object')
|
|
767
870
|
.option('--json', 'Emit machine-readable JSON output', false)
|
|
768
871
|
.action(async (templateId, options) => {
|
|
769
|
-
const workflow = new
|
|
872
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
770
873
|
await workflow.useTemplate(templateId, options);
|
|
771
874
|
});
|
|
772
875
|
workflowCommand
|
|
773
876
|
.command('run <workflowId>')
|
|
774
877
|
.description('Run a workflow immediately')
|
|
775
878
|
.option('-d, --data <json>', 'Execution input data as a JSON object')
|
|
879
|
+
.option('--no-brain', 'Do not attach local Project Brain context to this workflow run')
|
|
776
880
|
.option('--json', 'Emit machine-readable JSON output', false)
|
|
777
881
|
.action(async (workflowId, options) => {
|
|
778
|
-
const workflow = new
|
|
882
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
779
883
|
await workflow.run(workflowId, options);
|
|
780
884
|
});
|
|
781
885
|
workflowCommand
|
|
782
886
|
.command('status <executionId>')
|
|
783
887
|
.description('Get the current or final status of a workflow execution')
|
|
888
|
+
.option('--no-brain', 'Do not remember this workflow status in local Project Brain')
|
|
784
889
|
.option('--json', 'Emit machine-readable JSON output', false)
|
|
785
890
|
.action(async (executionId, options) => {
|
|
786
|
-
const workflow = new
|
|
891
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
787
892
|
await workflow.status(executionId, options);
|
|
788
893
|
});
|
|
789
894
|
workflowCommand.action(async () => {
|
|
790
|
-
const workflow = new
|
|
895
|
+
const workflow = new WorkflowCommand(config, logger);
|
|
791
896
|
await workflow.templates({});
|
|
792
897
|
});
|
|
793
898
|
// ==================== HUB / MARKETPLACE COMMANDS ====================
|
|
@@ -801,7 +906,7 @@ async function main(args) {
|
|
|
801
906
|
.alias('d')
|
|
802
907
|
.description('Interactive module discovery - find the right APIs for your project')
|
|
803
908
|
.action(async () => {
|
|
804
|
-
const hub = new
|
|
909
|
+
const hub = new HubCommand(config, logger);
|
|
805
910
|
await hub.discover();
|
|
806
911
|
});
|
|
807
912
|
hubCommand
|
|
@@ -810,7 +915,7 @@ async function main(args) {
|
|
|
810
915
|
.description('List all available API modules')
|
|
811
916
|
.option('-c, --category <category>', 'Filter by category (payments, communication, ai, creative, media)')
|
|
812
917
|
.action(async (options) => {
|
|
813
|
-
const hub = new
|
|
918
|
+
const hub = new HubCommand(config, logger);
|
|
814
919
|
await hub.list(options);
|
|
815
920
|
});
|
|
816
921
|
hubCommand
|
|
@@ -818,7 +923,7 @@ async function main(args) {
|
|
|
818
923
|
.alias('find')
|
|
819
924
|
.description('Semantic search for modules (e.g., "generate background music for my app")')
|
|
820
925
|
.action(async (query) => {
|
|
821
|
-
const hub = new
|
|
926
|
+
const hub = new HubCommand(config, logger);
|
|
822
927
|
await hub.search(query);
|
|
823
928
|
});
|
|
824
929
|
hubCommand
|
|
@@ -826,14 +931,14 @@ async function main(args) {
|
|
|
826
931
|
.alias('enable')
|
|
827
932
|
.description('Activate a module for your API key (enables pay-as-you-go)')
|
|
828
933
|
.action(async (module) => {
|
|
829
|
-
const hub = new
|
|
934
|
+
const hub = new HubCommand(config, logger);
|
|
830
935
|
await hub.activate(module);
|
|
831
936
|
});
|
|
832
937
|
hubCommand
|
|
833
938
|
.command('active')
|
|
834
939
|
.description('Show your currently active modules')
|
|
835
940
|
.action(async () => {
|
|
836
|
-
const hub = new
|
|
941
|
+
const hub = new HubCommand(config, logger);
|
|
837
942
|
await hub.active();
|
|
838
943
|
});
|
|
839
944
|
hubCommand
|
|
@@ -841,12 +946,12 @@ async function main(args) {
|
|
|
841
946
|
.alias('details')
|
|
842
947
|
.description('Get detailed information about a module')
|
|
843
948
|
.action(async (module) => {
|
|
844
|
-
const hub = new
|
|
949
|
+
const hub = new HubCommand(config, logger);
|
|
845
950
|
await hub.info(module);
|
|
846
951
|
});
|
|
847
952
|
// Default hub action shows discover
|
|
848
953
|
hubCommand.action(async () => {
|
|
849
|
-
const hub = new
|
|
954
|
+
const hub = new HubCommand(config, logger);
|
|
850
955
|
await hub.discover();
|
|
851
956
|
});
|
|
852
957
|
// ==================== REPO COMMANDS ====================
|
|
@@ -867,7 +972,7 @@ async function main(args) {
|
|
|
867
972
|
.option('--open-in <engine>', 'After push, open project in engine: shop, visual, game')
|
|
868
973
|
.option('--browser', 'Open result URL in default browser', false)
|
|
869
974
|
.action(async (pathArg, options) => {
|
|
870
|
-
const repo = new
|
|
975
|
+
const repo = new RepoCommand(config, logger);
|
|
871
976
|
await repo.push({
|
|
872
977
|
path: pathArg,
|
|
873
978
|
name: options.name,
|
|
@@ -893,7 +998,7 @@ async function main(args) {
|
|
|
893
998
|
.option('-o, --output <path>', 'Output directory path')
|
|
894
999
|
.option('-f, --force', 'Overwrite existing directory', false)
|
|
895
1000
|
.action(async (name, options) => {
|
|
896
|
-
const repo = new
|
|
1001
|
+
const repo = new RepoCommand(config, logger);
|
|
897
1002
|
await repo.pull(name, {
|
|
898
1003
|
output: options.output,
|
|
899
1004
|
force: options.force
|
|
@@ -905,14 +1010,14 @@ async function main(args) {
|
|
|
905
1010
|
.description('List all your projects in Vigthoria Repo')
|
|
906
1011
|
.option('-v, --visibility <type>', 'Filter by visibility (private, restricted, public)')
|
|
907
1012
|
.action(async (options) => {
|
|
908
|
-
const repo = new
|
|
1013
|
+
const repo = new RepoCommand(config, logger);
|
|
909
1014
|
await repo.list({ visibility: options.visibility });
|
|
910
1015
|
});
|
|
911
1016
|
repoCommand
|
|
912
1017
|
.command('status')
|
|
913
1018
|
.description('Show sync status of current project')
|
|
914
1019
|
.action(async () => {
|
|
915
|
-
const repo = new
|
|
1020
|
+
const repo = new RepoCommand(config, logger);
|
|
916
1021
|
await repo.status();
|
|
917
1022
|
});
|
|
918
1023
|
repoCommand
|
|
@@ -920,7 +1025,7 @@ async function main(args) {
|
|
|
920
1025
|
.description('Generate a shareable link for a project')
|
|
921
1026
|
.option('-e, --expires <duration>', 'Link expiration (e.g., 7d, 24h, 30m)', '7d')
|
|
922
1027
|
.action(async (name, options) => {
|
|
923
|
-
const repo = new
|
|
1028
|
+
const repo = new RepoCommand(config, logger);
|
|
924
1029
|
await repo.share(name, { expires: options.expires });
|
|
925
1030
|
});
|
|
926
1031
|
repoCommand
|
|
@@ -928,7 +1033,7 @@ async function main(args) {
|
|
|
928
1033
|
.alias('rm')
|
|
929
1034
|
.description('Remove a project from your Vigthoria Repo')
|
|
930
1035
|
.action(async (name) => {
|
|
931
|
-
const repo = new
|
|
1036
|
+
const repo = new RepoCommand(config, logger);
|
|
932
1037
|
await repo.delete(name);
|
|
933
1038
|
});
|
|
934
1039
|
repoCommand
|
|
@@ -937,7 +1042,7 @@ async function main(args) {
|
|
|
937
1042
|
.option('-o, --output <path>', 'Output directory path')
|
|
938
1043
|
.option('-f, --force', 'Overwrite existing directory', false)
|
|
939
1044
|
.action(async (url, options) => {
|
|
940
|
-
const repo = new
|
|
1045
|
+
const repo = new RepoCommand(config, logger);
|
|
941
1046
|
await repo.clone(url, {
|
|
942
1047
|
output: options.output,
|
|
943
1048
|
force: options.force
|
|
@@ -958,7 +1063,7 @@ Examples:
|
|
|
958
1063
|
logger.error(`Unknown engine "${engine}". Valid options: shop, visual, game`);
|
|
959
1064
|
process.exit(1);
|
|
960
1065
|
}
|
|
961
|
-
const repo = new
|
|
1066
|
+
const repo = new RepoCommand(config, logger);
|
|
962
1067
|
await repo.openIn(engine, projectName, {
|
|
963
1068
|
browser: options.browser,
|
|
964
1069
|
shopId: options.shopId
|
|
@@ -979,7 +1084,7 @@ Examples:
|
|
|
979
1084
|
.description('Deploy to free preview URL')
|
|
980
1085
|
.option('-p, --project <path>', 'Project directory path', process.cwd())
|
|
981
1086
|
.action(async (options) => {
|
|
982
|
-
const deploy = new
|
|
1087
|
+
const deploy = new DeployCommand(config, logger);
|
|
983
1088
|
await deploy.deployToPreview(options.project);
|
|
984
1089
|
});
|
|
985
1090
|
deployCommand
|
|
@@ -987,7 +1092,7 @@ Examples:
|
|
|
987
1092
|
.description('Deploy to yourname.vigthoria.io')
|
|
988
1093
|
.option('-p, --project <path>', 'Project directory path', process.cwd())
|
|
989
1094
|
.action(async (name, options) => {
|
|
990
|
-
const deploy = new
|
|
1095
|
+
const deploy = new DeployCommand(config, logger);
|
|
991
1096
|
await deploy.deployToSubdomain(name, options.project);
|
|
992
1097
|
});
|
|
993
1098
|
deployCommand
|
|
@@ -995,7 +1100,7 @@ Examples:
|
|
|
995
1100
|
.description('Deploy to your custom domain')
|
|
996
1101
|
.option('-p, --project <path>', 'Project directory path', process.cwd())
|
|
997
1102
|
.action(async (domain, options) => {
|
|
998
|
-
const deploy = new
|
|
1103
|
+
const deploy = new DeployCommand(config, logger);
|
|
999
1104
|
await deploy.deployToCustomDomain(domain, options.project);
|
|
1000
1105
|
});
|
|
1001
1106
|
deployCommand
|
|
@@ -1003,28 +1108,28 @@ Examples:
|
|
|
1003
1108
|
.alias('ls')
|
|
1004
1109
|
.description('List all your deployments')
|
|
1005
1110
|
.action(async () => {
|
|
1006
|
-
const deploy = new
|
|
1111
|
+
const deploy = new DeployCommand(config, logger);
|
|
1007
1112
|
await deploy.list();
|
|
1008
1113
|
});
|
|
1009
1114
|
deployCommand
|
|
1010
1115
|
.command('plans')
|
|
1011
1116
|
.description('Show hosting plans and pricing')
|
|
1012
1117
|
.action(async () => {
|
|
1013
|
-
const deploy = new
|
|
1118
|
+
const deploy = new DeployCommand(config, logger);
|
|
1014
1119
|
await deploy.showPlans();
|
|
1015
1120
|
});
|
|
1016
1121
|
deployCommand
|
|
1017
1122
|
.command('status [domain]')
|
|
1018
1123
|
.description('Check deployment status')
|
|
1019
1124
|
.action(async (domain) => {
|
|
1020
|
-
const deploy = new
|
|
1125
|
+
const deploy = new DeployCommand(config, logger);
|
|
1021
1126
|
await deploy.status(domain);
|
|
1022
1127
|
});
|
|
1023
1128
|
deployCommand
|
|
1024
1129
|
.command('verify <domain>')
|
|
1025
1130
|
.description('Verify DNS configuration for custom domain')
|
|
1026
1131
|
.action(async (domain) => {
|
|
1027
|
-
const deploy = new
|
|
1132
|
+
const deploy = new DeployCommand(config, logger);
|
|
1028
1133
|
await deploy.verify(domain);
|
|
1029
1134
|
});
|
|
1030
1135
|
deployCommand
|
|
@@ -1032,7 +1137,7 @@ Examples:
|
|
|
1032
1137
|
.alias('rm')
|
|
1033
1138
|
.description('Remove a deployment')
|
|
1034
1139
|
.action(async (domain) => {
|
|
1035
|
-
const deploy = new
|
|
1140
|
+
const deploy = new DeployCommand(config, logger);
|
|
1036
1141
|
await deploy.remove(domain);
|
|
1037
1142
|
});
|
|
1038
1143
|
// Default deploy action shows interactive wizard
|
|
@@ -1041,7 +1146,7 @@ Examples:
|
|
|
1041
1146
|
.option('-d, --domain <domain>', 'Deploy to custom domain')
|
|
1042
1147
|
.option('-p, --project <path>', 'Project directory path', process.cwd())
|
|
1043
1148
|
.action(async (options) => {
|
|
1044
|
-
const deploy = new
|
|
1149
|
+
const deploy = new DeployCommand(config, logger);
|
|
1045
1150
|
await deploy.deploy({
|
|
1046
1151
|
subdomain: options.subdomain,
|
|
1047
1152
|
domain: options.domain,
|
|
@@ -1060,7 +1165,7 @@ Examples:
|
|
|
1060
1165
|
.option('--proof', 'Run Template Service preview gate and persist proof bundle')
|
|
1061
1166
|
.option('--screenshot', 'Capture screenshot via Puppeteer')
|
|
1062
1167
|
.action(async (options) => {
|
|
1063
|
-
const preview = new
|
|
1168
|
+
const preview = new PreviewCommand(config, logger);
|
|
1064
1169
|
await preview.run({
|
|
1065
1170
|
project: options.project,
|
|
1066
1171
|
entry: options.entry,
|
|
@@ -1092,7 +1197,7 @@ Examples:
|
|
|
1092
1197
|
.option('-w, --worker <name>', 'Execute a specific worker')
|
|
1093
1198
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1094
1199
|
.action(async (request, options) => {
|
|
1095
|
-
const legion = new
|
|
1200
|
+
const legion = new LegionCommand(config, logger);
|
|
1096
1201
|
const parsedTimeout = Number.parseInt(String(options.timeout || ''), 10);
|
|
1097
1202
|
await legion.run(request, {
|
|
1098
1203
|
workers: options.workers,
|
|
@@ -1122,7 +1227,7 @@ Examples:
|
|
|
1122
1227
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1123
1228
|
.option('--json', 'Machine-readable JSON output', false)
|
|
1124
1229
|
.action(async (options) => {
|
|
1125
|
-
const history = new
|
|
1230
|
+
const history = new HistoryCommand(config, logger);
|
|
1126
1231
|
await history.run({ limit: parseInt(options.limit, 10) || 20, json: options.json, project: options.project });
|
|
1127
1232
|
});
|
|
1128
1233
|
program
|
|
@@ -1132,7 +1237,7 @@ Examples:
|
|
|
1132
1237
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1133
1238
|
.option('--json', 'Machine-readable JSON output', false)
|
|
1134
1239
|
.action(async (runId, options) => {
|
|
1135
|
-
const replay = new
|
|
1240
|
+
const replay = new ReplayCommand(config, logger);
|
|
1136
1241
|
await replay.run(runId, { speed: parseInt(options.speed, 10) || 200, json: options.json, project: options.project });
|
|
1137
1242
|
});
|
|
1138
1243
|
program
|
|
@@ -1142,7 +1247,7 @@ Examples:
|
|
|
1142
1247
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1143
1248
|
.option('--json', 'Machine-readable JSON output', false)
|
|
1144
1249
|
.action(async (runId, message, options) => {
|
|
1145
|
-
const fork = new
|
|
1250
|
+
const fork = new ForkCommand(config, logger);
|
|
1146
1251
|
await fork.run(runId, message || '', { eventIndex: parseInt(options.eventIndex, 10) || 0, project: options.project, json: options.json });
|
|
1147
1252
|
});
|
|
1148
1253
|
program
|
|
@@ -1152,7 +1257,7 @@ Examples:
|
|
|
1152
1257
|
.option('-l, --list', 'List active runs without cancelling', false)
|
|
1153
1258
|
.option('--json', 'Machine-readable JSON output', false)
|
|
1154
1259
|
.action(async (contextId, options) => {
|
|
1155
|
-
const cancel = new
|
|
1260
|
+
const cancel = new CancelCommand(config, logger);
|
|
1156
1261
|
await cancel.run(contextId, { all: options.all, list: options.list, json: options.json });
|
|
1157
1262
|
});
|
|
1158
1263
|
// ==================== AUTH COMMANDS ====================
|
|
@@ -1165,32 +1270,90 @@ Examples:
|
|
|
1165
1270
|
.option('-p, --password <password>', 'Account password for credential-based login')
|
|
1166
1271
|
.option('--device', 'Use OAuth device flow (requires server support)')
|
|
1167
1272
|
.action(async (options) => {
|
|
1168
|
-
await
|
|
1273
|
+
await handleLogin(options);
|
|
1169
1274
|
});
|
|
1170
1275
|
program
|
|
1171
1276
|
.command('logout')
|
|
1172
1277
|
.description('Logout from Vigthoria Coder')
|
|
1173
1278
|
.action(async () => {
|
|
1174
|
-
await
|
|
1279
|
+
await handleLogout(null);
|
|
1175
1280
|
});
|
|
1176
1281
|
program
|
|
1177
1282
|
.command('status')
|
|
1178
1283
|
.description('Show authentication and subscription status')
|
|
1179
1284
|
.action(async () => {
|
|
1180
|
-
await
|
|
1285
|
+
await statusAction();
|
|
1181
1286
|
});
|
|
1182
1287
|
program
|
|
1183
1288
|
.command('doctor')
|
|
1184
|
-
.description('Run local Vigthoria CLI diagnostics')
|
|
1185
|
-
.
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1289
|
+
.description('Run local Vigthoria CLI diagnostics (no network calls unless --check-api)')
|
|
1290
|
+
.option('--check-api', 'Also probe Vigthoria API reachability', false)
|
|
1291
|
+
.option('--json', 'Emit machine-readable JSON output', false)
|
|
1292
|
+
.action(async (options) => {
|
|
1293
|
+
const apiUrl = String(config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
1294
|
+
const modelsApiUrl = String(config.get('modelsApiUrl') || 'https://api.vigthoria.io').replace(/\/$/, '');
|
|
1295
|
+
const offline = isOfflineMode();
|
|
1296
|
+
const updateSuppressed = isUpdateCheckSuppressed();
|
|
1297
|
+
const subscription = config.get('subscription') || { plan: null, status: null, expiresAt: null };
|
|
1298
|
+
const report = {
|
|
1299
|
+
cliVersion: VERSION,
|
|
1300
|
+
nodeVersion: process.version,
|
|
1301
|
+
platform: `${process.platform} ${process.arch}`,
|
|
1302
|
+
cwd: process.cwd(),
|
|
1303
|
+
homeDir: os.homedir(),
|
|
1304
|
+
configPath: config.getConfigPath(),
|
|
1305
|
+
stateFile: getCliStateFile(),
|
|
1306
|
+
apiUrl,
|
|
1307
|
+
modelsApiUrl,
|
|
1308
|
+
loggedIn: config.isAuthenticated(),
|
|
1309
|
+
subscriptionPlan: subscription.plan || null,
|
|
1310
|
+
subscriptionStatus: subscription.status || null,
|
|
1311
|
+
offlineMode: offline,
|
|
1312
|
+
updateCheckSuppressed: updateSuppressed,
|
|
1313
|
+
envOverrides: {
|
|
1314
|
+
VIGTHORIA_API_URL: process.env.VIGTHORIA_API_URL || null,
|
|
1315
|
+
VIGTHORIA_V3_AGENT_URL: process.env.VIGTHORIA_V3_AGENT_URL || null,
|
|
1316
|
+
VIGTHORIA_OFFLINE: process.env.VIGTHORIA_OFFLINE || null,
|
|
1317
|
+
VIGTHORIA_TOKEN: process.env.VIGTHORIA_TOKEN ? '<set>' : null,
|
|
1318
|
+
HYPERLOOP_SERVICE_KEY: process.env.HYPERLOOP_SERVICE_KEY ? '<set>' : null,
|
|
1319
|
+
V3_SERVICE_KEY: process.env.V3_SERVICE_KEY ? '<set>' : null,
|
|
1320
|
+
},
|
|
1321
|
+
};
|
|
1322
|
+
if (options.checkApi && !offline) {
|
|
1323
|
+
try {
|
|
1324
|
+
const probe = await axios.get(`${apiUrl}/api/health`, { timeout: 4000, validateStatus: () => true });
|
|
1325
|
+
report.apiHealth = probe.status >= 200 && probe.status < 400 ? 'online' : `status ${probe.status}`;
|
|
1326
|
+
}
|
|
1327
|
+
catch (error) {
|
|
1328
|
+
report.apiHealth = `unreachable (${error.message})`;
|
|
1329
|
+
}
|
|
1330
|
+
try {
|
|
1331
|
+
const probe = await axios.get(`${modelsApiUrl}/health`, { timeout: 4000, validateStatus: () => true });
|
|
1332
|
+
report.modelsApiHealth = probe.status >= 200 && probe.status < 400 ? 'online' : `status ${probe.status}`;
|
|
1333
|
+
}
|
|
1334
|
+
catch (error) {
|
|
1335
|
+
report.modelsApiHealth = `unreachable (${error.message})`;
|
|
1336
|
+
}
|
|
1337
|
+
}
|
|
1338
|
+
if (options.json) {
|
|
1339
|
+
console.log(JSON.stringify(report, null, 2));
|
|
1340
|
+
}
|
|
1341
|
+
else {
|
|
1342
|
+
console.log(chalk.bold('Vigthoria CLI diagnostics'));
|
|
1343
|
+
for (const [key, value] of Object.entries(report)) {
|
|
1344
|
+
if (value && typeof value === 'object') {
|
|
1345
|
+
console.log(chalk.gray(`- ${key}:`));
|
|
1346
|
+
for (const [subKey, subVal] of Object.entries(value)) {
|
|
1347
|
+
console.log(chalk.gray(` - ${subKey}: ${subVal ?? '(none)'}`));
|
|
1348
|
+
}
|
|
1349
|
+
}
|
|
1350
|
+
else {
|
|
1351
|
+
console.log(chalk.gray(`- ${key}: ${value ?? '(none)'}`));
|
|
1352
|
+
}
|
|
1353
|
+
}
|
|
1354
|
+
if (!options.checkApi) {
|
|
1355
|
+
console.log(chalk.gray('\nTip: pass --check-api to verify API reachability.'));
|
|
1356
|
+
}
|
|
1194
1357
|
}
|
|
1195
1358
|
process.exitCode = 0;
|
|
1196
1359
|
});
|
|
@@ -1203,7 +1366,7 @@ Examples:
|
|
|
1203
1366
|
.option('-l, --list', 'List all settings')
|
|
1204
1367
|
.option('-r, --reset', 'Reset to defaults')
|
|
1205
1368
|
.action(async (options) => {
|
|
1206
|
-
const configCmd = new
|
|
1369
|
+
const configCmd = new ConfigCommand(config, logger);
|
|
1207
1370
|
await configCmd.run(options);
|
|
1208
1371
|
});
|
|
1209
1372
|
// Update command - Check for and install updates
|
|
@@ -1224,77 +1387,89 @@ Examples:
|
|
|
1224
1387
|
const allowDowngrade = !!options.allowDowngrade;
|
|
1225
1388
|
const gitPackageSpec = 'git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git';
|
|
1226
1389
|
if (updateTarget) {
|
|
1390
|
+
if (!isSafeNpmPackageSpec(updateTarget)) {
|
|
1391
|
+
console.error(chalk.red('Refusing to run installer with unsafe package spec.'));
|
|
1392
|
+
console.error(chalk.gray('Allowed characters: A-Z a-z 0-9 . _ - / @ : + \\ ='));
|
|
1393
|
+
process.exitCode = 1;
|
|
1394
|
+
return;
|
|
1395
|
+
}
|
|
1227
1396
|
try {
|
|
1228
1397
|
if (options.check) {
|
|
1229
|
-
console.log(
|
|
1230
|
-
console.log(
|
|
1398
|
+
console.log(chalk.cyan(`Update source configured: ${updateTarget}`));
|
|
1399
|
+
console.log(chalk.gray('Run `vigthoria update --from <target>` to install from this source'));
|
|
1231
1400
|
return;
|
|
1232
1401
|
}
|
|
1233
|
-
console.log(
|
|
1402
|
+
console.log(chalk.cyan(`Installing update from ${updateTarget}...`));
|
|
1234
1403
|
await installGlobalPackageWithNpm(updateTarget);
|
|
1235
|
-
console.log(
|
|
1236
|
-
console.log(
|
|
1404
|
+
console.log(chalk.green('Update installed successfully'));
|
|
1405
|
+
console.log(chalk.gray('Please restart the CLI to use the new version'));
|
|
1237
1406
|
return;
|
|
1238
1407
|
}
|
|
1239
1408
|
catch (error) {
|
|
1240
|
-
console.error(
|
|
1241
|
-
console.log(
|
|
1409
|
+
console.error(chalk.red('Failed to install update from target:'), error.message);
|
|
1410
|
+
console.log(chalk.gray(`Try manually: npm install -g ${updateTarget}`));
|
|
1242
1411
|
process.exitCode = 1;
|
|
1243
1412
|
return;
|
|
1244
1413
|
}
|
|
1245
1414
|
}
|
|
1246
1415
|
if (manifestUrl) {
|
|
1416
|
+
if (isOfflineMode()) {
|
|
1417
|
+
console.log(chalk.yellow('Offline mode (VIGTHORIA_OFFLINE=1): skipping manifest update.'));
|
|
1418
|
+
return;
|
|
1419
|
+
}
|
|
1247
1420
|
try {
|
|
1248
|
-
console.log(
|
|
1249
|
-
const response = await
|
|
1421
|
+
console.log(chalk.cyan(`Checking manifest channel ${channel}...`));
|
|
1422
|
+
const response = await axios.get(manifestUrl, {
|
|
1250
1423
|
timeout: 10000,
|
|
1251
1424
|
maxRedirects: 5,
|
|
1252
1425
|
validateStatus: (status) => status >= 200 && status < 300,
|
|
1253
1426
|
});
|
|
1254
1427
|
const entry = resolveManifestEntry(response.data || {}, channel);
|
|
1255
1428
|
if (!entry || !entry.version || !entry.url) {
|
|
1256
|
-
console.error(
|
|
1257
|
-
console.log(
|
|
1429
|
+
console.error(chalk.red(`Manifest missing valid release entry for channel: ${channel}`));
|
|
1430
|
+
console.log(chalk.gray('Expected: channels.<channel>.version and channels.<channel>.url'));
|
|
1258
1431
|
process.exitCode = 1;
|
|
1259
1432
|
return;
|
|
1260
1433
|
}
|
|
1261
1434
|
const currentVersion = VERSION;
|
|
1262
1435
|
const comparison = compareVersions(entry.version, currentVersion);
|
|
1263
1436
|
if (!allowDowngrade && comparison <= 0) {
|
|
1264
|
-
console.log(
|
|
1437
|
+
console.log(chalk.green(`You are running the latest version for channel ${channel} (${currentVersion})`));
|
|
1265
1438
|
return;
|
|
1266
1439
|
}
|
|
1267
|
-
console.log(
|
|
1440
|
+
console.log(chalk.yellow(`Update available from manifest: ${currentVersion} -> ${entry.version} (${channel})`));
|
|
1268
1441
|
if (entry.notes) {
|
|
1269
|
-
console.log(
|
|
1442
|
+
console.log(chalk.gray(` ${entry.notes}`));
|
|
1270
1443
|
}
|
|
1271
1444
|
if (options.check) {
|
|
1272
|
-
console.log(
|
|
1445
|
+
console.log(chalk.gray(`Install with: vigthoria update --manifest ${manifestUrl} --channel ${channel}`));
|
|
1273
1446
|
return;
|
|
1274
1447
|
}
|
|
1275
1448
|
const tmpFile = path.join(os.tmpdir(), `vigthoria-update-${Date.now()}.tgz`);
|
|
1276
1449
|
try {
|
|
1277
|
-
console.log(
|
|
1450
|
+
console.log(chalk.cyan('Downloading release package...'));
|
|
1278
1451
|
await downloadFile(entry.url, tmpFile);
|
|
1279
1452
|
if (entry.sha256) {
|
|
1280
1453
|
const expected = entry.sha256.toLowerCase();
|
|
1281
1454
|
const actual = sha256File(tmpFile).toLowerCase();
|
|
1282
1455
|
if (actual !== expected) {
|
|
1283
|
-
console.error(
|
|
1284
|
-
console.error(
|
|
1285
|
-
console.error(
|
|
1456
|
+
console.error(chalk.red('Release checksum verification failed'));
|
|
1457
|
+
console.error(chalk.red(`Expected: ${expected}`));
|
|
1458
|
+
console.error(chalk.red(`Actual: ${actual}`));
|
|
1286
1459
|
process.exitCode = 1;
|
|
1287
1460
|
return;
|
|
1288
1461
|
}
|
|
1289
|
-
console.log(
|
|
1462
|
+
console.log(chalk.green('Checksum verification passed'));
|
|
1290
1463
|
}
|
|
1291
1464
|
else {
|
|
1292
|
-
console.log(
|
|
1465
|
+
console.log(chalk.yellow.bold('WARNING: manifest entry has no sha256.'));
|
|
1466
|
+
console.log(chalk.yellow(' The release artifact will be installed without integrity verification.'));
|
|
1467
|
+
console.log(chalk.gray(' Set --manifest to a trusted source, or supply sha256 in the manifest entry.'));
|
|
1293
1468
|
}
|
|
1294
|
-
console.log(
|
|
1469
|
+
console.log(chalk.cyan('Installing update...'));
|
|
1295
1470
|
await installGlobalPackageWithNpm(tmpFile);
|
|
1296
|
-
console.log(
|
|
1297
|
-
console.log(
|
|
1471
|
+
console.log(chalk.green(`Updated to version ${entry.version}`));
|
|
1472
|
+
console.log(chalk.gray('Please restart the CLI to use the new version'));
|
|
1298
1473
|
return;
|
|
1299
1474
|
}
|
|
1300
1475
|
finally {
|
|
@@ -1307,11 +1482,15 @@ Examples:
|
|
|
1307
1482
|
}
|
|
1308
1483
|
}
|
|
1309
1484
|
catch (error) {
|
|
1310
|
-
console.error(
|
|
1311
|
-
console.log(
|
|
1485
|
+
console.error(chalk.red('Failed to process manifest update:'), error.message);
|
|
1486
|
+
console.log(chalk.gray('Falling back to npm/git update channels...'));
|
|
1312
1487
|
}
|
|
1313
1488
|
}
|
|
1314
|
-
|
|
1489
|
+
if (isOfflineMode()) {
|
|
1490
|
+
console.log(chalk.yellow('Offline mode (VIGTHORIA_OFFLINE=1): skipping update check.'));
|
|
1491
|
+
return;
|
|
1492
|
+
}
|
|
1493
|
+
console.log(chalk.cyan('Checking for updates...'));
|
|
1315
1494
|
try {
|
|
1316
1495
|
// Get latest version from npm - cross-platform
|
|
1317
1496
|
const latestVersion = execSync('npm view vigthoria-cli version', {
|
|
@@ -1323,35 +1502,35 @@ Examples:
|
|
|
1323
1502
|
// Use semantic version comparison (1.6.0 > 1.5.9)
|
|
1324
1503
|
const comparison = compareVersions(latestVersion, currentVersion);
|
|
1325
1504
|
if (comparison <= 0) {
|
|
1326
|
-
console.log(
|
|
1505
|
+
console.log(chalk.green(`You are running the latest version (${currentVersion})`));
|
|
1327
1506
|
return;
|
|
1328
1507
|
}
|
|
1329
|
-
console.log(
|
|
1508
|
+
console.log(chalk.yellow(`Update available: ${currentVersion} -> ${latestVersion}`));
|
|
1330
1509
|
if (options.check) {
|
|
1331
|
-
console.log(
|
|
1510
|
+
console.log(chalk.gray('Run `vigthoria update` to install the update'));
|
|
1332
1511
|
return;
|
|
1333
1512
|
}
|
|
1334
|
-
console.log(
|
|
1513
|
+
console.log(chalk.cyan('Installing update from npm registry...'));
|
|
1335
1514
|
await installGlobalPackageWithNpm('vigthoria-cli@latest');
|
|
1336
|
-
console.log(
|
|
1337
|
-
console.log(
|
|
1515
|
+
console.log(chalk.green(`Updated to version ${latestVersion}`));
|
|
1516
|
+
console.log(chalk.gray('Please restart the CLI to use the new version'));
|
|
1338
1517
|
}
|
|
1339
1518
|
catch (error) {
|
|
1340
|
-
console.error(
|
|
1519
|
+
console.error(chalk.red('Failed to check/install via npm registry:'), error.message);
|
|
1341
1520
|
if (options.check) {
|
|
1342
|
-
console.log(
|
|
1521
|
+
console.log(chalk.gray(`npm registry check failed; fallback install target is ${gitPackageSpec}`));
|
|
1343
1522
|
return;
|
|
1344
1523
|
}
|
|
1345
1524
|
try {
|
|
1346
|
-
console.log(
|
|
1525
|
+
console.log(chalk.cyan('Attempting git package fallback...'));
|
|
1347
1526
|
await installGlobalPackageWithNpm(gitPackageSpec);
|
|
1348
|
-
console.log(
|
|
1349
|
-
console.log(
|
|
1527
|
+
console.log(chalk.green('Updated via git package fallback'));
|
|
1528
|
+
console.log(chalk.gray('Please restart the CLI to use the new version'));
|
|
1350
1529
|
}
|
|
1351
1530
|
catch (fallbackError) {
|
|
1352
|
-
console.error(
|
|
1353
|
-
console.log(
|
|
1354
|
-
console.log(
|
|
1531
|
+
console.error(chalk.red('Fallback update also failed:'), fallbackError.message);
|
|
1532
|
+
console.log(chalk.gray('Try manually: npm install -g vigthoria-cli@latest'));
|
|
1533
|
+
console.log(chalk.gray(`Or: npm install -g ${gitPackageSpec}`));
|
|
1355
1534
|
process.exitCode = 1;
|
|
1356
1535
|
}
|
|
1357
1536
|
}
|
|
@@ -1363,7 +1542,7 @@ Examples:
|
|
|
1363
1542
|
.command('status')
|
|
1364
1543
|
.description('Show Hyper Loop Legion infrastructure status')
|
|
1365
1544
|
.action(async () => {
|
|
1366
|
-
const legion = new
|
|
1545
|
+
const legion = new LegionCommand(config, logger);
|
|
1367
1546
|
await legion.run(undefined, {
|
|
1368
1547
|
status: true,
|
|
1369
1548
|
workers: false,
|
|
@@ -1383,7 +1562,7 @@ Examples:
|
|
|
1383
1562
|
.command('connect')
|
|
1384
1563
|
.description('Connect to DevTools Bridge')
|
|
1385
1564
|
.action(async () => {
|
|
1386
|
-
const bridge = new
|
|
1565
|
+
const bridge = new BridgeCommand(config, logger);
|
|
1387
1566
|
await bridge.status();
|
|
1388
1567
|
});
|
|
1389
1568
|
// Init command - Initialize project
|
|
@@ -1391,7 +1570,7 @@ Examples:
|
|
|
1391
1570
|
.command('init')
|
|
1392
1571
|
.description('Initialize Vigthoria in current project')
|
|
1393
1572
|
.action(async () => {
|
|
1394
|
-
const configCmd = new
|
|
1573
|
+
const configCmd = new ConfigCommand(config, logger);
|
|
1395
1574
|
await configCmd.init();
|
|
1396
1575
|
});
|
|
1397
1576
|
const codingCommandDefinitions = [
|
|
@@ -1410,7 +1589,7 @@ Examples:
|
|
|
1410
1589
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1411
1590
|
.action(async (requestParts = [], options) => {
|
|
1412
1591
|
const requestText = requestParts.join(' ').trim();
|
|
1413
|
-
const chat = new
|
|
1592
|
+
const chat = new ChatCommand(config, logger);
|
|
1414
1593
|
await chat.run({
|
|
1415
1594
|
model: options.model || 'code',
|
|
1416
1595
|
project: options.project || process.cwd(),
|
|
@@ -1421,7 +1600,7 @@ Examples:
|
|
|
1421
1600
|
try {
|
|
1422
1601
|
// Default to chat if no command
|
|
1423
1602
|
if (args.length === 2) {
|
|
1424
|
-
const chat = new
|
|
1603
|
+
const chat = new ChatCommand(config, logger);
|
|
1425
1604
|
await chat.run({ model: 'code', project: process.cwd() });
|
|
1426
1605
|
process.exitCode = 0;
|
|
1427
1606
|
return;
|
|
@@ -1437,10 +1616,6 @@ Examples:
|
|
|
1437
1616
|
}
|
|
1438
1617
|
}
|
|
1439
1618
|
setupErrorHandlers();
|
|
1440
|
-
process.on('unhandledRejection', (reason) => {
|
|
1441
|
-
handleFatalCliError(reason, process.argv.includes('--json'));
|
|
1442
|
-
process.exit(1);
|
|
1443
|
-
});
|
|
1444
1619
|
async function bootstrapCli() {
|
|
1445
1620
|
try {
|
|
1446
1621
|
await main(process.argv);
|
|
@@ -1459,4 +1634,4 @@ void (async () => {
|
|
|
1459
1634
|
process.exit(1);
|
|
1460
1635
|
}
|
|
1461
1636
|
})();
|
|
1462
|
-
|
|
1637
|
+
export const __cliErrorHandlingReady = true;
|