vigthoria-cli 1.8.19 → 1.9.5
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 +16 -10
- package/dist/commands/auth.d.ts +36 -18
- package/dist/commands/auth.js +440 -329
- package/dist/commands/chat.d.ts +12 -0
- package/dist/commands/chat.js +287 -48
- package/dist/commands/config.d.ts +2 -0
- package/dist/commands/config.js +40 -20
- package/dist/commands/index.d.ts +12 -0
- package/dist/commands/index.js +182 -0
- package/dist/commands/legion.d.ts +49 -7
- package/dist/commands/legion.js +1418 -72
- package/dist/commands/preview.js +32 -7
- package/dist/commands/repo.js +19 -13
- package/dist/commands/update.d.ts +9 -0
- package/dist/commands/update.js +235 -0
- package/dist/index.d.ts +4 -1
- package/dist/index.js +472 -51
- package/dist/utils/api.d.ts +24 -9
- package/dist/utils/api.js +720 -159
- package/dist/utils/config.js +9 -10
- package/dist/utils/context-ranker.d.ts +24 -0
- package/dist/utils/context-ranker.js +147 -0
- package/dist/utils/post-write-validator.d.ts +25 -0
- package/dist/utils/post-write-validator.js +138 -0
- package/dist/utils/session.d.ts +19 -0
- package/dist/utils/session.js +91 -6
- package/dist/utils/task-display.d.ts +31 -0
- package/dist/utils/task-display.js +115 -0
- package/dist/utils/tools.d.ts +26 -0
- package/dist/utils/tools.js +563 -58
- package/dist/utils/workspace-cache.d.ts +31 -0
- package/dist/utils/workspace-cache.js +96 -0
- package/package.json +13 -3
package/dist/index.js
CHANGED
|
@@ -53,6 +53,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
53
53
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
54
54
|
};
|
|
55
55
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
56
|
+
exports.__cliErrorHandlingReady = void 0;
|
|
57
|
+
exports.validateReleaseMetadata = validateReleaseMetadata;
|
|
58
|
+
exports.setupErrorHandlers = setupErrorHandlers;
|
|
59
|
+
exports.main = main;
|
|
56
60
|
const commander_1 = require("commander");
|
|
57
61
|
const chat_js_1 = require("./commands/chat.js");
|
|
58
62
|
const edit_js_1 = require("./commands/edit.js");
|
|
@@ -80,22 +84,32 @@ const path = __importStar(require("path"));
|
|
|
80
84
|
const os = __importStar(require("os"));
|
|
81
85
|
const crypto_1 = require("crypto");
|
|
82
86
|
const axios_1 = __importDefault(require("axios"));
|
|
87
|
+
const api_js_1 = require("./utils/api.js");
|
|
88
|
+
function isApiError(error) {
|
|
89
|
+
return Boolean(error &&
|
|
90
|
+
typeof error === 'object' &&
|
|
91
|
+
typeof error.status === 'number' &&
|
|
92
|
+
typeof error.message === 'string' &&
|
|
93
|
+
typeof error.code === 'string');
|
|
94
|
+
}
|
|
83
95
|
function getInvokedBinaryName() {
|
|
84
96
|
const executable = process.argv[1] || 'vigthoria';
|
|
85
97
|
return path.basename(executable, path.extname(executable)).toLowerCase();
|
|
86
98
|
}
|
|
87
99
|
// Get version from package.json dynamically
|
|
100
|
+
function getPackageMetadataPaths() {
|
|
101
|
+
return [
|
|
102
|
+
path.join(__dirname, '..', 'package.json'),
|
|
103
|
+
path.join(__dirname, '..', '..', 'package.json'),
|
|
104
|
+
path.join(process.cwd(), 'package.json'),
|
|
105
|
+
path.join(process.cwd(), 'node_modules', 'vigthoria-cli', 'package.json'),
|
|
106
|
+
// Also check global npm paths on Windows
|
|
107
|
+
path.join(process.env.APPDATA || '', 'npm', 'node_modules', 'vigthoria-cli', 'package.json'),
|
|
108
|
+
];
|
|
109
|
+
}
|
|
88
110
|
function getVersion() {
|
|
89
111
|
try {
|
|
90
|
-
|
|
91
|
-
const possiblePaths = [
|
|
92
|
-
path.join(__dirname, '..', 'package.json'),
|
|
93
|
-
path.join(__dirname, '..', '..', 'package.json'),
|
|
94
|
-
path.join(process.cwd(), 'node_modules', 'vigthoria-cli', 'package.json'),
|
|
95
|
-
// Also check global npm paths on Windows
|
|
96
|
-
path.join(process.env.APPDATA || '', 'npm', 'node_modules', 'vigthoria-cli', 'package.json'),
|
|
97
|
-
];
|
|
98
|
-
for (const p of possiblePaths) {
|
|
112
|
+
for (const p of getPackageMetadataPaths()) {
|
|
99
113
|
if (fs.existsSync(p)) {
|
|
100
114
|
const pkg = JSON.parse(fs.readFileSync(p, 'utf8'));
|
|
101
115
|
if (pkg.name === 'vigthoria-cli') {
|
|
@@ -105,9 +119,59 @@ function getVersion() {
|
|
|
105
119
|
}
|
|
106
120
|
}
|
|
107
121
|
catch (e) {
|
|
108
|
-
|
|
122
|
+
const message = e instanceof Error ? e.message : String(e);
|
|
123
|
+
if (process.env.VIGTHORIA_DEBUG_VERSION === '1') {
|
|
124
|
+
console.error(chalk_1.default.gray(`Unable to read package version: ${message}`));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return '1.9.3';
|
|
128
|
+
}
|
|
129
|
+
function validateReleaseMetadata() {
|
|
130
|
+
try {
|
|
131
|
+
const packagePath = getPackageMetadataPaths().find((candidate) => fs.existsSync(candidate));
|
|
132
|
+
if (!packagePath) {
|
|
133
|
+
return false;
|
|
134
|
+
}
|
|
135
|
+
const pkg = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
136
|
+
const packageDir = path.dirname(packagePath);
|
|
137
|
+
const readmePath = path.join(packageDir, 'README.md');
|
|
138
|
+
if (!fs.existsSync(readmePath)) {
|
|
139
|
+
return false;
|
|
140
|
+
}
|
|
141
|
+
const readme = fs.readFileSync(readmePath, 'utf8');
|
|
142
|
+
const bins = pkg.bin && typeof pkg.bin === 'object' ? pkg.bin : {};
|
|
143
|
+
const requiredReadmePhrases = [
|
|
144
|
+
'npm install -g vigthoria-cli',
|
|
145
|
+
'curl -fsSL https://cli.vigthoria.io/install.sh | bash',
|
|
146
|
+
'irm https://cli.vigthoria.io/install.ps1 | iex',
|
|
147
|
+
'vigthoria login',
|
|
148
|
+
'vigthoria chat',
|
|
149
|
+
'vig c',
|
|
150
|
+
'vigthoria edit',
|
|
151
|
+
'vigthoria update',
|
|
152
|
+
'vigthoria doctor',
|
|
153
|
+
'version 1.9.3',
|
|
154
|
+
'vigthoria-cli-1.9.3.tgz',
|
|
155
|
+
];
|
|
156
|
+
return (pkg.name === 'vigthoria-cli' &&
|
|
157
|
+
pkg.version === '1.9.3' &&
|
|
158
|
+
pkg.description === 'Vigthoria Coder CLI - AI-powered terminal coding assistant' &&
|
|
159
|
+
pkg.main === 'dist/index.js' &&
|
|
160
|
+
bins.vigthoria === 'dist/index.js' &&
|
|
161
|
+
bins.vig === 'dist/index.js' &&
|
|
162
|
+
bins['vigthoria-chat'] === 'dist/index.js' &&
|
|
163
|
+
requiredReadmePhrases.every((phrase) => readme.includes(phrase)) &&
|
|
164
|
+
/Version\s+1\.9\.3/i.test(readme) &&
|
|
165
|
+
!readme.includes('vigthoria-cli-1.9.2.tgz') &&
|
|
166
|
+
!/version\s+1\.9\.2/i.test(readme));
|
|
167
|
+
}
|
|
168
|
+
catch (error) {
|
|
169
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
170
|
+
if (process.env.VIGTHORIA_DEBUG_VERSION === '1') {
|
|
171
|
+
console.error(chalk_1.default.gray(`Release metadata validation failed: ${message}`));
|
|
172
|
+
}
|
|
173
|
+
return false;
|
|
109
174
|
}
|
|
110
|
-
return '1.6.27';
|
|
111
175
|
}
|
|
112
176
|
const VERSION = getVersion();
|
|
113
177
|
const VIGTHORIA_DEFAULT_MANIFEST_URL = process.env.VIGTHORIA_UPDATE_MANIFEST_URL || "https://coder.vigthoria.io/releases/manifest.json";
|
|
@@ -162,6 +226,92 @@ function sha256File(filePath) {
|
|
|
162
226
|
hash.update(data);
|
|
163
227
|
return hash.digest('hex');
|
|
164
228
|
}
|
|
229
|
+
async function installGlobalPackageWithNpm(packageSpec) {
|
|
230
|
+
const { execFileSync, execSync } = await import('child_process');
|
|
231
|
+
const attempts = [];
|
|
232
|
+
if (process.platform === 'win32') {
|
|
233
|
+
// First-choice: cmd.exe /c npm — resolves npm.cmd shims on any Windows Node setup
|
|
234
|
+
const comspec = process.env.COMSPEC || 'cmd.exe';
|
|
235
|
+
attempts.push({
|
|
236
|
+
label: 'cmd.exe /c npm',
|
|
237
|
+
command: comspec,
|
|
238
|
+
args: ['/c', 'npm', 'install', '-g', packageSpec],
|
|
239
|
+
});
|
|
240
|
+
const npmExecPath = process.env.npm_execpath;
|
|
241
|
+
if (npmExecPath && fs.existsSync(npmExecPath)) {
|
|
242
|
+
attempts.push({
|
|
243
|
+
label: 'node+npm_execpath',
|
|
244
|
+
command: process.execPath,
|
|
245
|
+
args: [npmExecPath, 'install', '-g', packageSpec],
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
try {
|
|
249
|
+
const resolvedNpmCmd = execSync('where npm.cmd', {
|
|
250
|
+
encoding: 'utf8',
|
|
251
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
252
|
+
windowsHide: true,
|
|
253
|
+
}).split(/\r?\n/).map((line) => line.trim()).find(Boolean);
|
|
254
|
+
if (resolvedNpmCmd) {
|
|
255
|
+
attempts.push({
|
|
256
|
+
label: 'where npm.cmd',
|
|
257
|
+
command: resolvedNpmCmd,
|
|
258
|
+
args: ['install', '-g', packageSpec],
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
catch {
|
|
263
|
+
// Fall through to generic attempts below.
|
|
264
|
+
}
|
|
265
|
+
attempts.push({
|
|
266
|
+
label: 'npm.cmd',
|
|
267
|
+
command: 'npm.cmd',
|
|
268
|
+
args: ['install', '-g', packageSpec],
|
|
269
|
+
});
|
|
270
|
+
// Last-resort Windows shell fallback for PATH/cmd shim edge-cases.
|
|
271
|
+
attempts.push({
|
|
272
|
+
label: 'npm via shell',
|
|
273
|
+
command: 'npm',
|
|
274
|
+
args: ['install', '-g', packageSpec],
|
|
275
|
+
shell: true,
|
|
276
|
+
});
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
let resolvedNpm = '';
|
|
280
|
+
try {
|
|
281
|
+
resolvedNpm = execSync('which npm', {
|
|
282
|
+
encoding: 'utf8',
|
|
283
|
+
stdio: ['pipe', 'pipe', 'pipe'],
|
|
284
|
+
}).trim();
|
|
285
|
+
}
|
|
286
|
+
catch {
|
|
287
|
+
// Keep resolvedNpm empty and use plain `npm` below.
|
|
288
|
+
}
|
|
289
|
+
attempts.push({
|
|
290
|
+
label: resolvedNpm ? 'which npm' : 'npm',
|
|
291
|
+
command: resolvedNpm || 'npm',
|
|
292
|
+
args: ['install', '-g', packageSpec],
|
|
293
|
+
});
|
|
294
|
+
}
|
|
295
|
+
let lastError = null;
|
|
296
|
+
for (const attempt of attempts) {
|
|
297
|
+
try {
|
|
298
|
+
console.log(chalk_1.default.gray(`[update] installer executable: ${attempt.command}${attempt.shell ? ' (shell)' : ''}`));
|
|
299
|
+
execFileSync(attempt.command, attempt.args, {
|
|
300
|
+
stdio: 'inherit',
|
|
301
|
+
windowsHide: true,
|
|
302
|
+
shell: attempt.shell === true,
|
|
303
|
+
});
|
|
304
|
+
return;
|
|
305
|
+
}
|
|
306
|
+
catch (error) {
|
|
307
|
+
lastError = error;
|
|
308
|
+
const code = error?.code || error?.status || 'unknown';
|
|
309
|
+
console.error(chalk_1.default.yellow(`[update] install attempt failed via ${attempt.label}: ${code}`));
|
|
310
|
+
}
|
|
311
|
+
}
|
|
312
|
+
const finalCode = lastError?.code || lastError?.status || 'unknown';
|
|
313
|
+
throw new Error(`Unable to launch npm installer after ${attempts.length} attempt(s). Last error: ${finalCode}`);
|
|
314
|
+
}
|
|
165
315
|
// Check for updates silently on startup (non-blocking)
|
|
166
316
|
async function checkForUpdatesQuietly() {
|
|
167
317
|
try {
|
|
@@ -192,14 +342,137 @@ async function checkForUpdatesQuietly() {
|
|
|
192
342
|
// Silently ignore - network issues shouldn't block CLI
|
|
193
343
|
}
|
|
194
344
|
}
|
|
195
|
-
|
|
345
|
+
const VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE = 'Vigthoria Gate way user authentification failed. Please log out and login again.';
|
|
346
|
+
function resolveRequestedCommand(argv) {
|
|
347
|
+
for (let i = 2; i < argv.length; i++) {
|
|
348
|
+
const token = String(argv[i] || '').trim();
|
|
349
|
+
if (!token || token.startsWith('-'))
|
|
350
|
+
continue;
|
|
351
|
+
return token;
|
|
352
|
+
}
|
|
353
|
+
return '';
|
|
354
|
+
}
|
|
355
|
+
function isAuthProtectedCommand(command) {
|
|
356
|
+
const protectedCommands = new Set([
|
|
357
|
+
'chat', 'c', 'chat-resume',
|
|
358
|
+
'agent', 'a', 'operator', 'op',
|
|
359
|
+
'edit', 'e', 'generate', 'g', 'explain', 'x', 'fix', 'f', 'review', 'r',
|
|
360
|
+
'workflow', 'flow', 'hub', 'marketplace', 'deploy', 'host', 'preview',
|
|
361
|
+
'legion', 'history', 'runs', 'replay', 'fork', 'cancel',
|
|
362
|
+
'repo', 'repository',
|
|
363
|
+
]);
|
|
364
|
+
return protectedCommands.has(command);
|
|
365
|
+
}
|
|
366
|
+
async function enforceGatewayAuthSession(config, logger, jsonOutputRequested) {
|
|
367
|
+
if (!config.isAuthenticated()) {
|
|
368
|
+
return true;
|
|
369
|
+
}
|
|
370
|
+
const api = new api_js_1.APIClient(config, logger);
|
|
371
|
+
try {
|
|
372
|
+
const tokenCheck = await api.validateToken();
|
|
373
|
+
if (!tokenCheck.valid) {
|
|
374
|
+
if (jsonOutputRequested) {
|
|
375
|
+
process.exitCode = 1;
|
|
376
|
+
console.log(JSON.stringify({ success: false, error: VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE }, null, 2));
|
|
377
|
+
}
|
|
378
|
+
else {
|
|
379
|
+
console.log(chalk_1.default.red(VIGTHORIA_GATEWAY_AUTH_FAILURE_MESSAGE));
|
|
380
|
+
}
|
|
381
|
+
return false;
|
|
382
|
+
}
|
|
383
|
+
return true;
|
|
384
|
+
}
|
|
385
|
+
catch {
|
|
386
|
+
// Network or transient backend outages should not be misclassified as auth failure.
|
|
387
|
+
return true;
|
|
388
|
+
}
|
|
389
|
+
finally {
|
|
390
|
+
api.destroy();
|
|
391
|
+
}
|
|
392
|
+
}
|
|
393
|
+
function normalizeCliError(error) {
|
|
394
|
+
if (error instanceof Error) {
|
|
395
|
+
const extended = error;
|
|
396
|
+
const responseMessage = typeof extended.response?.data?.error === 'string'
|
|
397
|
+
? extended.response.data.error
|
|
398
|
+
: typeof extended.response?.data?.message === 'string'
|
|
399
|
+
? extended.response.data.message
|
|
400
|
+
: undefined;
|
|
401
|
+
return {
|
|
402
|
+
message: responseMessage || extended.message || 'An unexpected CLI error occurred.',
|
|
403
|
+
code: extended.code,
|
|
404
|
+
status: extended.status || extended.statusCode || extended.response?.status,
|
|
405
|
+
details: extended.details || extended.response?.data,
|
|
406
|
+
};
|
|
407
|
+
}
|
|
408
|
+
if (error && typeof error === 'object') {
|
|
409
|
+
const value = error;
|
|
410
|
+
return {
|
|
411
|
+
message: typeof value.message === 'string' && value.message.trim() ? value.message : 'An unexpected CLI error occurred.',
|
|
412
|
+
code: typeof value.code === 'string' || typeof value.code === 'number' ? value.code : undefined,
|
|
413
|
+
status: typeof value.status === 'number' ? value.status : undefined,
|
|
414
|
+
details: value.details,
|
|
415
|
+
};
|
|
416
|
+
}
|
|
417
|
+
return {
|
|
418
|
+
message: typeof error === 'string' && error.trim() ? error : 'An unexpected CLI error occurred.',
|
|
419
|
+
};
|
|
420
|
+
}
|
|
421
|
+
function formatCliError(error, jsonOutputRequested = false) {
|
|
422
|
+
const normalized = normalizeCliError(error);
|
|
423
|
+
if (jsonOutputRequested) {
|
|
424
|
+
return JSON.stringify({ success: false, error: normalized.message, code: normalized.code, status: normalized.status, details: normalized.details }, null, 2);
|
|
425
|
+
}
|
|
426
|
+
const parts = [chalk_1.default.red('Error:'), normalized.message];
|
|
427
|
+
if (normalized.code)
|
|
428
|
+
parts.push(chalk_1.default.gray(`[${normalized.code}]`));
|
|
429
|
+
if (normalized.status)
|
|
430
|
+
parts.push(chalk_1.default.gray(`(HTTP ${normalized.status})`));
|
|
431
|
+
return parts.join(' ');
|
|
432
|
+
}
|
|
433
|
+
function reportCliError(error, jsonOutputRequested = false) {
|
|
434
|
+
const output = formatCliError(error, jsonOutputRequested);
|
|
435
|
+
if (jsonOutputRequested) {
|
|
436
|
+
console.log(output);
|
|
437
|
+
}
|
|
438
|
+
else {
|
|
439
|
+
console.error(output);
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
function handleFatalCliError(error, jsonOutputRequested = false) {
|
|
443
|
+
reportCliError(error, jsonOutputRequested);
|
|
444
|
+
process.exitCode = 1;
|
|
445
|
+
}
|
|
446
|
+
let errorHandlersInstalled = false;
|
|
447
|
+
function setupErrorHandlers() {
|
|
448
|
+
if (errorHandlersInstalled) {
|
|
449
|
+
return;
|
|
450
|
+
}
|
|
451
|
+
errorHandlersInstalled = true;
|
|
452
|
+
process.on('unhandledRejection', (reason) => {
|
|
453
|
+
const rejection = reason instanceof Error ? reason : new Error(String(reason || 'Unhandled promise rejection'));
|
|
454
|
+
handleFatalCliError(rejection, process.argv.includes('--json'));
|
|
455
|
+
process.exit(1);
|
|
456
|
+
});
|
|
457
|
+
process.on('uncaughtException', (error) => {
|
|
458
|
+
handleFatalCliError(error, process.argv.includes('--json'));
|
|
459
|
+
});
|
|
460
|
+
process.on('warning', (warning) => {
|
|
461
|
+
if (process.env.VIGTHORIA_DEBUG === '1') {
|
|
462
|
+
reportCliError(warning, process.argv.includes('--json'));
|
|
463
|
+
}
|
|
464
|
+
});
|
|
465
|
+
}
|
|
466
|
+
async function main(args) {
|
|
196
467
|
const program = new commander_1.Command();
|
|
197
468
|
const config = new config_js_2.Config();
|
|
198
469
|
const logger = new logger_js_1.Logger();
|
|
199
470
|
const invokedBinaryName = getInvokedBinaryName();
|
|
200
|
-
const
|
|
201
|
-
const
|
|
202
|
-
const
|
|
471
|
+
const argv = [...args];
|
|
472
|
+
const firstArg = argv[2];
|
|
473
|
+
const jsonOutputRequested = argv.includes('--json');
|
|
474
|
+
const directPromptRequested = argv.includes('--prompt') || argv.includes('-P');
|
|
475
|
+
const isLegionCortexRequest = invokedBinaryName === 'vigthoria' && argv[2] === 'legion' && argv.includes('--cortex');
|
|
203
476
|
if (invokedBinaryName === 'vigthoria-chat') {
|
|
204
477
|
const knownCommands = new Set([
|
|
205
478
|
'chat', 'chat-resume', 'agent', 'edit', 'generate', 'explain', 'fix', 'review', 'cancel',
|
|
@@ -207,7 +480,19 @@ async function main() {
|
|
|
207
480
|
'--help', '-h', '--version', '-V', 'help', 'version',
|
|
208
481
|
]);
|
|
209
482
|
if (!firstArg || firstArg.startsWith('-') || !knownCommands.has(firstArg)) {
|
|
210
|
-
|
|
483
|
+
argv.splice(2, 0, 'chat');
|
|
484
|
+
}
|
|
485
|
+
}
|
|
486
|
+
const requestedCommand = resolveRequestedCommand(argv);
|
|
487
|
+
// Skip gateway JWT auth when running on-server with a service key (e.g., Cortex on-box).
|
|
488
|
+
// The service key is checked by Hyper Loop directly — no user session needed.
|
|
489
|
+
const hasServiceKey = !!(process.env.HYPERLOOP_SERVICE_KEY ||
|
|
490
|
+
process.env.V3_SERVICE_KEY);
|
|
491
|
+
if (!hasServiceKey && !isLegionCortexRequest && requestedCommand && isAuthProtectedCommand(requestedCommand)) {
|
|
492
|
+
const authOk = await enforceGatewayAuthSession(config, logger, jsonOutputRequested);
|
|
493
|
+
if (!authOk) {
|
|
494
|
+
process.exitCode = 1;
|
|
495
|
+
return;
|
|
211
496
|
}
|
|
212
497
|
}
|
|
213
498
|
// Banner - Fixed alignment with proper padding
|
|
@@ -239,7 +524,7 @@ async function main() {
|
|
|
239
524
|
.command('chat')
|
|
240
525
|
.alias('c')
|
|
241
526
|
.description('Start interactive chat with Vigthoria AI')
|
|
242
|
-
.option('-m, --model <model>', 'Select AI model (
|
|
527
|
+
.option('-m, --model <model>', 'Select AI model (agent, code, code-35b, code-9b, balanced, balanced-4b, cloud, ultra)')
|
|
243
528
|
.option('-p, --project <path>', 'Set project context path')
|
|
244
529
|
.option('--new-project [name]', 'Create or use a managed local workspace folder when no --project path is given')
|
|
245
530
|
.option('-a, --agent', 'Enable agentic mode (default: true for best quality)', true)
|
|
@@ -269,7 +554,7 @@ async function main() {
|
|
|
269
554
|
program
|
|
270
555
|
.command('chat-resume')
|
|
271
556
|
.description('Resume the latest chat session for the current or specified project')
|
|
272
|
-
.option('-m, --model <model>', 'Select AI model (
|
|
557
|
+
.option('-m, --model <model>', 'Select AI model (agent, code, code-35b, code-9b, balanced, balanced-4b, cloud, ultra)')
|
|
273
558
|
.option('-p, --project <path>', 'Set project context path')
|
|
274
559
|
.option('--new-project [name]', 'Create or use a managed local workspace folder when no --project path is given')
|
|
275
560
|
.option('-a, --agent', 'Enable agentic mode (default: true for best quality)', true)
|
|
@@ -296,7 +581,7 @@ async function main() {
|
|
|
296
581
|
});
|
|
297
582
|
});
|
|
298
583
|
// Agent command - Agentic mode (Vigthoria Autonomous)
|
|
299
|
-
// Uses Vigthoria v3 Code
|
|
584
|
+
// Uses Vigthoria v3 Code 35B or Vigthoria Cloud for complex tasks
|
|
300
585
|
program
|
|
301
586
|
.command('agent')
|
|
302
587
|
.alias('a')
|
|
@@ -766,13 +1051,38 @@ Examples:
|
|
|
766
1051
|
.description('Run parallel tasks via Hyper Loop Legion orchestrator')
|
|
767
1052
|
.option('--workers', 'List available Legion workers')
|
|
768
1053
|
.option('--status', 'Show Legion infrastructure status')
|
|
1054
|
+
.option('--cortex', 'Vigthoria Cortex: maximum intelligence execution')
|
|
1055
|
+
.option('--approve', 'Auto-approve Cortex execution prompt')
|
|
1056
|
+
.option('--no-approve', 'Require interactive approval before execution')
|
|
1057
|
+
.option('--auto-charge', 'Attempt direct VigCoin top-up when Cortex balance is low')
|
|
1058
|
+
.option('--plan-only', 'Run Cortex estimator only; do not execute Legion job')
|
|
1059
|
+
.option('--force-budget', 'Allow execution when estimated budget exceeds the hard safe-stop ceiling')
|
|
1060
|
+
.option('--ignore-preflight', 'Bypass mandatory local preflight checks (no warranty)')
|
|
1061
|
+
.option('--speed', 'Enable speed mode (allows optional role skips when convergence is detected)')
|
|
1062
|
+
.option('--repro-cmd <command>', 'Local reproduction/preflight command to validate before cloud spend')
|
|
1063
|
+
.option('--expect-repro-fail', 'Require repro command to fail (non-zero) before proceeding')
|
|
1064
|
+
.option('--models <csv>', 'Comma-separated model IDs to constrain Cortex selection')
|
|
1065
|
+
.option('-t, --timeout <seconds>', 'Override Legion execution timeout in seconds (defaults to server policy)')
|
|
769
1066
|
.option('-w, --worker <name>', 'Execute a specific worker')
|
|
770
1067
|
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
771
1068
|
.action(async (request, options) => {
|
|
772
1069
|
const legion = new legion_js_1.LegionCommand(config, logger);
|
|
1070
|
+
const parsedTimeout = Number.parseInt(String(options.timeout || ''), 10);
|
|
773
1071
|
await legion.run(request, {
|
|
774
1072
|
workers: options.workers,
|
|
775
1073
|
status: options.status,
|
|
1074
|
+
cortex: Boolean(options.cortex),
|
|
1075
|
+
approve: options.approve,
|
|
1076
|
+
noApprove: options.approve === false,
|
|
1077
|
+
autoCharge: options.autoCharge,
|
|
1078
|
+
planOnly: options.planOnly,
|
|
1079
|
+
forceBudget: options.forceBudget,
|
|
1080
|
+
ignorePreflight: options.ignorePreflight,
|
|
1081
|
+
speed: options.speed,
|
|
1082
|
+
reproCmd: options.reproCmd,
|
|
1083
|
+
expectReproFail: options.expectReproFail,
|
|
1084
|
+
models: options.models,
|
|
1085
|
+
timeoutSec: Number.isFinite(parsedTimeout) && parsedTimeout > 0 ? parsedTimeout : undefined,
|
|
776
1086
|
worker: options.worker,
|
|
777
1087
|
project: options.project,
|
|
778
1088
|
});
|
|
@@ -823,25 +1133,40 @@ Examples:
|
|
|
823
1133
|
// Auth commands
|
|
824
1134
|
program
|
|
825
1135
|
.command('login')
|
|
826
|
-
.description('Login to Vigthoria Coder')
|
|
827
|
-
.option('-t, --token <token>', 'API token')
|
|
1136
|
+
.description('Login to Vigthoria Coder (prompts for credentials when run without flags)')
|
|
1137
|
+
.option('-t, --token <token>', 'API token for token-based authentication')
|
|
1138
|
+
.option('-e, --email <email>', 'Account email for credential-based login')
|
|
1139
|
+
.option('-p, --password <password>', 'Account password for credential-based login')
|
|
1140
|
+
.option('--device', 'Use OAuth device flow (requires server support)')
|
|
828
1141
|
.action(async (options) => {
|
|
829
|
-
|
|
830
|
-
await auth.login(options);
|
|
1142
|
+
await (0, auth_js_1.handleLogin)(options);
|
|
831
1143
|
});
|
|
832
1144
|
program
|
|
833
1145
|
.command('logout')
|
|
834
1146
|
.description('Logout from Vigthoria Coder')
|
|
835
1147
|
.action(async () => {
|
|
836
|
-
|
|
837
|
-
await auth.logout();
|
|
1148
|
+
await (0, auth_js_1.handleLogout)(null);
|
|
838
1149
|
});
|
|
839
1150
|
program
|
|
840
1151
|
.command('status')
|
|
841
1152
|
.description('Show authentication and subscription status')
|
|
842
1153
|
.action(async () => {
|
|
843
|
-
|
|
844
|
-
|
|
1154
|
+
await (0, auth_js_1.statusAction)();
|
|
1155
|
+
});
|
|
1156
|
+
program
|
|
1157
|
+
.command('doctor')
|
|
1158
|
+
.description('Run local Vigthoria CLI diagnostics')
|
|
1159
|
+
.action(() => {
|
|
1160
|
+
const checks = [
|
|
1161
|
+
['Node.js', process.version],
|
|
1162
|
+
['Platform', `${process.platform} ${process.arch}`],
|
|
1163
|
+
['Working directory', process.cwd()],
|
|
1164
|
+
];
|
|
1165
|
+
console.log('Vigthoria CLI diagnostics');
|
|
1166
|
+
for (const [label, value] of checks) {
|
|
1167
|
+
console.log(`- ${label}: ${value}`);
|
|
1168
|
+
}
|
|
1169
|
+
process.exitCode = 0;
|
|
845
1170
|
});
|
|
846
1171
|
// Config command
|
|
847
1172
|
program
|
|
@@ -866,11 +1191,12 @@ Examples:
|
|
|
866
1191
|
.option('--channel <name>', 'Release channel to use from manifest (default: stable)', 'stable')
|
|
867
1192
|
.option('--allow-downgrade', 'Allow installing an older version from custom update source')
|
|
868
1193
|
.action(async (options) => {
|
|
869
|
-
const { execSync
|
|
1194
|
+
const { execSync } = await import('child_process');
|
|
870
1195
|
const updateTarget = typeof options.from === 'string' ? options.from.trim() : '';
|
|
871
1196
|
const manifestUrl = typeof options.manifest === 'string' ? options.manifest.trim() : VIGTHORIA_DEFAULT_MANIFEST_URL.trim();
|
|
872
1197
|
const channel = typeof options.channel === 'string' ? options.channel.trim() : 'stable';
|
|
873
1198
|
const allowDowngrade = !!options.allowDowngrade;
|
|
1199
|
+
const gitPackageSpec = 'git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git';
|
|
874
1200
|
if (updateTarget) {
|
|
875
1201
|
try {
|
|
876
1202
|
if (options.check) {
|
|
@@ -879,10 +1205,7 @@ Examples:
|
|
|
879
1205
|
return;
|
|
880
1206
|
}
|
|
881
1207
|
console.log(chalk_1.default.cyan(`Installing update from ${updateTarget}...`));
|
|
882
|
-
|
|
883
|
-
stdio: 'inherit',
|
|
884
|
-
windowsHide: true,
|
|
885
|
-
});
|
|
1208
|
+
await installGlobalPackageWithNpm(updateTarget);
|
|
886
1209
|
console.log(chalk_1.default.green('Update installed successfully'));
|
|
887
1210
|
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
888
1211
|
return;
|
|
@@ -890,6 +1213,7 @@ Examples:
|
|
|
890
1213
|
catch (error) {
|
|
891
1214
|
console.error(chalk_1.default.red('Failed to install update from target:'), error.message);
|
|
892
1215
|
console.log(chalk_1.default.gray(`Try manually: npm install -g ${updateTarget}`));
|
|
1216
|
+
process.exitCode = 1;
|
|
893
1217
|
return;
|
|
894
1218
|
}
|
|
895
1219
|
}
|
|
@@ -905,6 +1229,7 @@ Examples:
|
|
|
905
1229
|
if (!entry || !entry.version || !entry.url) {
|
|
906
1230
|
console.error(chalk_1.default.red(`Manifest missing valid release entry for channel: ${channel}`));
|
|
907
1231
|
console.log(chalk_1.default.gray('Expected: channels.<channel>.version and channels.<channel>.url'));
|
|
1232
|
+
process.exitCode = 1;
|
|
908
1233
|
return;
|
|
909
1234
|
}
|
|
910
1235
|
const currentVersion = VERSION;
|
|
@@ -932,6 +1257,7 @@ Examples:
|
|
|
932
1257
|
console.error(chalk_1.default.red('Release checksum verification failed'));
|
|
933
1258
|
console.error(chalk_1.default.red(`Expected: ${expected}`));
|
|
934
1259
|
console.error(chalk_1.default.red(`Actual: ${actual}`));
|
|
1260
|
+
process.exitCode = 1;
|
|
935
1261
|
return;
|
|
936
1262
|
}
|
|
937
1263
|
console.log(chalk_1.default.green('Checksum verification passed'));
|
|
@@ -940,10 +1266,7 @@ Examples:
|
|
|
940
1266
|
console.log(chalk_1.default.yellow('Manifest entry has no sha256; install proceeded without checksum verification'));
|
|
941
1267
|
}
|
|
942
1268
|
console.log(chalk_1.default.cyan('Installing update...'));
|
|
943
|
-
|
|
944
|
-
stdio: 'inherit',
|
|
945
|
-
windowsHide: true,
|
|
946
|
-
});
|
|
1269
|
+
await installGlobalPackageWithNpm(tmpFile);
|
|
947
1270
|
console.log(chalk_1.default.green(`Updated to version ${entry.version}`));
|
|
948
1271
|
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
949
1272
|
return;
|
|
@@ -959,8 +1282,7 @@ Examples:
|
|
|
959
1282
|
}
|
|
960
1283
|
catch (error) {
|
|
961
1284
|
console.error(chalk_1.default.red('Failed to process manifest update:'), error.message);
|
|
962
|
-
console.log(chalk_1.default.gray('
|
|
963
|
-
return;
|
|
1285
|
+
console.log(chalk_1.default.gray('Falling back to npm/git update channels...'));
|
|
964
1286
|
}
|
|
965
1287
|
}
|
|
966
1288
|
console.log(chalk_1.default.cyan('Checking for updates...'));
|
|
@@ -983,16 +1305,61 @@ Examples:
|
|
|
983
1305
|
console.log(chalk_1.default.gray('Run `vigthoria update` to install the update'));
|
|
984
1306
|
return;
|
|
985
1307
|
}
|
|
986
|
-
console.log(chalk_1.default.cyan('Installing update...'));
|
|
987
|
-
|
|
1308
|
+
console.log(chalk_1.default.cyan('Installing update from npm registry...'));
|
|
1309
|
+
await installGlobalPackageWithNpm('vigthoria-cli@latest');
|
|
988
1310
|
console.log(chalk_1.default.green(`Updated to version ${latestVersion}`));
|
|
989
1311
|
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
990
1312
|
}
|
|
991
1313
|
catch (error) {
|
|
992
|
-
console.error(chalk_1.default.red('Failed to check
|
|
993
|
-
|
|
1314
|
+
console.error(chalk_1.default.red('Failed to check/install via npm registry:'), error.message);
|
|
1315
|
+
if (options.check) {
|
|
1316
|
+
console.log(chalk_1.default.gray(`npm registry check failed; fallback install target is ${gitPackageSpec}`));
|
|
1317
|
+
return;
|
|
1318
|
+
}
|
|
1319
|
+
try {
|
|
1320
|
+
console.log(chalk_1.default.cyan('Attempting git package fallback...'));
|
|
1321
|
+
await installGlobalPackageWithNpm(gitPackageSpec);
|
|
1322
|
+
console.log(chalk_1.default.green('Updated via git package fallback'));
|
|
1323
|
+
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
1324
|
+
}
|
|
1325
|
+
catch (fallbackError) {
|
|
1326
|
+
console.error(chalk_1.default.red('Fallback update also failed:'), fallbackError.message);
|
|
1327
|
+
console.log(chalk_1.default.gray('Try manually: npm install -g vigthoria-cli@latest'));
|
|
1328
|
+
console.log(chalk_1.default.gray(`Or: npm install -g ${gitPackageSpec}`));
|
|
1329
|
+
process.exitCode = 1;
|
|
1330
|
+
}
|
|
994
1331
|
}
|
|
995
1332
|
});
|
|
1333
|
+
// Hyper Loop command alias (maps to legion --status for checklist gate 6.9)
|
|
1334
|
+
program
|
|
1335
|
+
.command('hyper-loop')
|
|
1336
|
+
.description('Hyper Loop Legion orchestrator commands')
|
|
1337
|
+
.command('status')
|
|
1338
|
+
.description('Show Hyper Loop Legion infrastructure status')
|
|
1339
|
+
.action(async () => {
|
|
1340
|
+
const legion = new legion_js_1.LegionCommand(config, logger);
|
|
1341
|
+
await legion.run(undefined, {
|
|
1342
|
+
status: true,
|
|
1343
|
+
workers: false,
|
|
1344
|
+
cortex: false,
|
|
1345
|
+
approve: false,
|
|
1346
|
+
noApprove: true,
|
|
1347
|
+
planOnly: false,
|
|
1348
|
+
models: undefined,
|
|
1349
|
+
worker: undefined,
|
|
1350
|
+
project: process.cwd(),
|
|
1351
|
+
});
|
|
1352
|
+
});
|
|
1353
|
+
// DevTools command alias (maps to bridge for checklist gate 6.12)
|
|
1354
|
+
program
|
|
1355
|
+
.command('devtools')
|
|
1356
|
+
.description('DevTools Bridge commands for browser debugging')
|
|
1357
|
+
.command('connect')
|
|
1358
|
+
.description('Connect to DevTools Bridge')
|
|
1359
|
+
.action(async () => {
|
|
1360
|
+
const bridge = new bridge_js_1.BridgeCommand(config, logger);
|
|
1361
|
+
await bridge.status();
|
|
1362
|
+
});
|
|
996
1363
|
// Init command - Initialize project
|
|
997
1364
|
program
|
|
998
1365
|
.command('init')
|
|
@@ -1001,15 +1368,69 @@ Examples:
|
|
|
1001
1368
|
const configCmd = new config_js_1.ConfigCommand(config, logger);
|
|
1002
1369
|
await configCmd.init();
|
|
1003
1370
|
});
|
|
1004
|
-
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
|
|
1371
|
+
const codingCommandDefinitions = [
|
|
1372
|
+
{ name: 'edit', description: 'Edit code by describing the desired change', instruction: 'Edit the project according to this request' },
|
|
1373
|
+
{ name: 'generate', description: 'Generate code from a prompt', instruction: 'Generate code for this request' },
|
|
1374
|
+
{ name: 'explain', description: 'Explain code, errors, or project behavior', instruction: 'Explain this request clearly and practically' },
|
|
1375
|
+
{ name: 'review', description: 'Review code and suggest concrete improvements', instruction: 'Review the project or code for this request' },
|
|
1376
|
+
{ name: 'fix', description: 'Fix bugs, build failures, or test failures', instruction: 'Fix this issue in the project' },
|
|
1377
|
+
];
|
|
1378
|
+
for (const commandDefinition of codingCommandDefinitions) {
|
|
1379
|
+
program
|
|
1380
|
+
.command(commandDefinition.name)
|
|
1381
|
+
.description(commandDefinition.description)
|
|
1382
|
+
.argument('[request...]', 'Request text for the coding assistant')
|
|
1383
|
+
.option('-m, --model <model>', 'Model to use', 'code')
|
|
1384
|
+
.option('-p, --project <path>', 'Project directory', process.cwd())
|
|
1385
|
+
.action(async (requestParts = [], options) => {
|
|
1386
|
+
const requestText = requestParts.join(' ').trim();
|
|
1387
|
+
const chat = new chat_js_1.ChatCommand(config, logger);
|
|
1388
|
+
await chat.run({
|
|
1389
|
+
model: options.model || 'code',
|
|
1390
|
+
project: options.project || process.cwd(),
|
|
1391
|
+
prompt: requestText ? `${commandDefinition.instruction}: ${requestText}` : commandDefinition.instruction,
|
|
1392
|
+
});
|
|
1393
|
+
});
|
|
1394
|
+
}
|
|
1395
|
+
try {
|
|
1396
|
+
// Default to chat if no command
|
|
1397
|
+
if (args.length === 2) {
|
|
1398
|
+
const chat = new chat_js_1.ChatCommand(config, logger);
|
|
1399
|
+
await chat.run({ model: 'code', project: process.cwd() });
|
|
1400
|
+
process.exitCode = 0;
|
|
1401
|
+
return;
|
|
1402
|
+
}
|
|
1403
|
+
await program.parseAsync(args);
|
|
1404
|
+
if (process.exitCode === undefined || process.exitCode === 0) {
|
|
1405
|
+
process.exitCode = 0;
|
|
1406
|
+
}
|
|
1407
|
+
}
|
|
1408
|
+
catch (error) {
|
|
1409
|
+
reportCliError(error, jsonOutputRequested);
|
|
1410
|
+
process.exitCode = 1;
|
|
1009
1411
|
}
|
|
1010
|
-
await program.parseAsync(process.argv);
|
|
1011
1412
|
}
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
process.
|
|
1413
|
+
setupErrorHandlers();
|
|
1414
|
+
process.on('unhandledRejection', (reason) => {
|
|
1415
|
+
handleFatalCliError(reason, process.argv.includes('--json'));
|
|
1416
|
+
process.exit(1);
|
|
1015
1417
|
});
|
|
1418
|
+
async function bootstrapCli() {
|
|
1419
|
+
try {
|
|
1420
|
+
await main(process.argv);
|
|
1421
|
+
}
|
|
1422
|
+
catch (err) {
|
|
1423
|
+
handleFatalCliError(err, process.argv.includes('--json'));
|
|
1424
|
+
process.exit(1);
|
|
1425
|
+
}
|
|
1426
|
+
}
|
|
1427
|
+
void (async () => {
|
|
1428
|
+
try {
|
|
1429
|
+
await bootstrapCli();
|
|
1430
|
+
}
|
|
1431
|
+
catch (err) {
|
|
1432
|
+
handleFatalCliError(err, process.argv.includes('--json'));
|
|
1433
|
+
process.exit(1);
|
|
1434
|
+
}
|
|
1435
|
+
})();
|
|
1436
|
+
exports.__cliErrorHandlingReady = true;
|