vigthoria-cli 1.6.60 → 1.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commands/auth.d.ts +0 -1
- package/dist/commands/auth.js +29 -27
- package/dist/commands/chat.js +72 -7
- package/dist/commands/history.js +2 -0
- package/package.json +1 -1
package/dist/commands/auth.d.ts
CHANGED
package/dist/commands/auth.js
CHANGED
|
@@ -50,41 +50,48 @@ const api_js_1 = require("../utils/api.js");
|
|
|
50
50
|
* which triggers ERR_USE_AFTER_CLOSE on Node 20 Windows TTY when a second
|
|
51
51
|
* prompt is attempted on the same process.stdin. Using raw readline avoids
|
|
52
52
|
* this entirely.
|
|
53
|
+
*
|
|
54
|
+
* IMPORTANT: We reuse a single readline.Interface for all prompts in the
|
|
55
|
+
* login flow to avoid the triple-rl stdin contention that causes stalls
|
|
56
|
+
* on Windows TTY and piped terminals.
|
|
53
57
|
*/
|
|
54
58
|
function ask(rl, question) {
|
|
55
59
|
return new Promise((resolve) => rl.question(question, resolve));
|
|
56
60
|
}
|
|
57
|
-
function askHidden(question) {
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
+
function askHidden(rl, question) {
|
|
62
|
+
// In non-interactive (piped) terminals, fall back to plain rl.question
|
|
63
|
+
// because raw data events won't fire after stdin reaches EOF.
|
|
64
|
+
if (!process.stdin.isTTY) {
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
rl.question(question, (answer) => {
|
|
67
|
+
resolve(answer.trim());
|
|
68
|
+
});
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
return new Promise((resolve) => {
|
|
61
72
|
const stdout = process.stdout;
|
|
62
73
|
let answer = '';
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
74
|
+
// Pause rl so it doesn't compete for stdin data events
|
|
75
|
+
rl.pause();
|
|
76
|
+
stdout.write(question);
|
|
77
|
+
process.stdin.setRawMode(true);
|
|
67
78
|
process.stdin.resume();
|
|
68
79
|
const onData = (ch) => {
|
|
69
80
|
const c = ch.toString('utf8');
|
|
70
81
|
if (c === '\n' || c === '\r' || c === '\u0004') {
|
|
71
|
-
|
|
72
|
-
process.stdin.setRawMode(false);
|
|
73
|
-
}
|
|
82
|
+
process.stdin.setRawMode(false);
|
|
74
83
|
process.stdin.removeListener('data', onData);
|
|
75
84
|
stdout.write('\n');
|
|
76
|
-
rl.
|
|
85
|
+
rl.resume();
|
|
77
86
|
resolve(answer);
|
|
78
87
|
}
|
|
79
88
|
else if (c === '\u007f' || c === '\b') {
|
|
80
|
-
// backspace
|
|
81
89
|
if (answer.length > 0) {
|
|
82
90
|
answer = answer.slice(0, -1);
|
|
83
91
|
stdout.write('\b \b');
|
|
84
92
|
}
|
|
85
93
|
}
|
|
86
94
|
else if (c === '\u0003') {
|
|
87
|
-
// Ctrl-C
|
|
88
95
|
rl.close();
|
|
89
96
|
process.exit(1);
|
|
90
97
|
}
|
|
@@ -124,17 +131,18 @@ class AuthCommand {
|
|
|
124
131
|
console.log(chalk_1.default.white(' 3) Browser Login'));
|
|
125
132
|
console.log();
|
|
126
133
|
const choice = (await ask(rl, chalk_1.default.cyan('? ') + 'Choose login method (1/2/3): ')).trim();
|
|
127
|
-
rl.close();
|
|
128
134
|
switch (choice) {
|
|
129
135
|
case '1':
|
|
130
136
|
case 'credentials': {
|
|
131
|
-
const email = await
|
|
137
|
+
const email = (await ask(rl, chalk_1.default.cyan('? ') + 'Email: ')).trim();
|
|
132
138
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
133
139
|
if (!emailRegex.test(email)) {
|
|
134
140
|
this.logger.error('Please enter a valid email');
|
|
141
|
+
rl.close();
|
|
135
142
|
return;
|
|
136
143
|
}
|
|
137
|
-
const password = await askHidden(chalk_1.default.cyan('? ') + 'Password: ');
|
|
144
|
+
const password = await askHidden(rl, chalk_1.default.cyan('? ') + 'Password: ');
|
|
145
|
+
rl.close();
|
|
138
146
|
if (password.length < 6) {
|
|
139
147
|
this.logger.error('Password must be at least 6 characters');
|
|
140
148
|
return;
|
|
@@ -144,7 +152,8 @@ class AuthCommand {
|
|
|
144
152
|
}
|
|
145
153
|
case '2':
|
|
146
154
|
case 'token': {
|
|
147
|
-
const token = await askHidden(chalk_1.default.cyan('? ') + 'API Token: ');
|
|
155
|
+
const token = await askHidden(rl, chalk_1.default.cyan('? ') + 'API Token: ');
|
|
156
|
+
rl.close();
|
|
148
157
|
if (!token) {
|
|
149
158
|
this.logger.error('Please enter your API token');
|
|
150
159
|
return;
|
|
@@ -154,9 +163,11 @@ class AuthCommand {
|
|
|
154
163
|
}
|
|
155
164
|
case '3':
|
|
156
165
|
case 'browser':
|
|
166
|
+
rl.close();
|
|
157
167
|
await this.loginWithBrowser();
|
|
158
168
|
break;
|
|
159
169
|
default:
|
|
170
|
+
rl.close();
|
|
160
171
|
this.logger.error('Invalid choice. Please enter 1, 2, or 3.');
|
|
161
172
|
break;
|
|
162
173
|
}
|
|
@@ -166,15 +177,6 @@ class AuthCommand {
|
|
|
166
177
|
throw err;
|
|
167
178
|
}
|
|
168
179
|
}
|
|
169
|
-
askInput(label) {
|
|
170
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
171
|
-
return new Promise((resolve) => {
|
|
172
|
-
rl.question(chalk_1.default.cyan('? ') + label, (answer) => {
|
|
173
|
-
rl.close();
|
|
174
|
-
resolve(answer.trim());
|
|
175
|
-
});
|
|
176
|
-
});
|
|
177
|
-
}
|
|
178
180
|
async doCredentialLogin(email, password) {
|
|
179
181
|
const spinner = (0, logger_js_1.createSpinner)('Logging in...').start();
|
|
180
182
|
const success = await this.api.login(email, password);
|
package/dist/commands/chat.js
CHANGED
|
@@ -326,10 +326,19 @@ class ChatCommand {
|
|
|
326
326
|
const toolTarget = event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '';
|
|
327
327
|
const shortTarget = toolTarget ? ` → ${String(toolTarget).split('/').slice(-2).join('/')}` : '';
|
|
328
328
|
const stepLabel = chalk_1.default.cyan(` [${this.v3IterationCount}/${this.v3ToolCallCount}]`) + ` ${toolDesc}${shortTarget}`;
|
|
329
|
-
// Print each tool call as a persistent log line so the user sees progress
|
|
330
329
|
if (spinner.isSpinning)
|
|
331
330
|
spinner.stop();
|
|
332
331
|
process.stderr.write(stepLabel + '\n');
|
|
332
|
+
// Show extra detail for key tools
|
|
333
|
+
const args = event.arguments || {};
|
|
334
|
+
const toolName = event.name || event.tool || '';
|
|
335
|
+
if ((toolName === 'write_file' || toolName === 'edit_file') && typeof args.content === 'string') {
|
|
336
|
+
const len = args.content.length;
|
|
337
|
+
process.stderr.write(chalk_1.default.gray(` ${len > 1000 ? Math.round(len / 1024) + ' KB' : len + ' bytes'} content\n`));
|
|
338
|
+
}
|
|
339
|
+
else if (toolName === 'bash' && typeof args.command === 'string') {
|
|
340
|
+
process.stderr.write(chalk_1.default.gray(` $ ${args.command.slice(0, 120)}${args.command.length > 120 ? '…' : ''}\n`));
|
|
341
|
+
}
|
|
333
342
|
spinner.start();
|
|
334
343
|
spinner.text = `Running ${toolDesc}...`;
|
|
335
344
|
return;
|
|
@@ -341,6 +350,16 @@ class ChatCommand {
|
|
|
341
350
|
if (spinner.isSpinning)
|
|
342
351
|
spinner.stop();
|
|
343
352
|
process.stderr.write(`${indicator} ${toolName}\n`);
|
|
353
|
+
// Show output for failures, or brief summary for successes
|
|
354
|
+
const output = typeof event.output === 'string' ? event.output.trim() : '';
|
|
355
|
+
if (!success && output) {
|
|
356
|
+
const lines = output.split('\n').slice(0, 4);
|
|
357
|
+
process.stderr.write(chalk_1.default.red(` ${lines.join('\n ')}\n`));
|
|
358
|
+
}
|
|
359
|
+
else if (success && output && output.length > 0) {
|
|
360
|
+
const brief = output.split('\n')[0].slice(0, 120);
|
|
361
|
+
process.stderr.write(chalk_1.default.gray(` ${brief}${output.length > 120 ? '…' : ''}\n`));
|
|
362
|
+
}
|
|
344
363
|
spinner.start();
|
|
345
364
|
spinner.text = 'Next step...';
|
|
346
365
|
return;
|
|
@@ -348,11 +367,9 @@ class ChatCommand {
|
|
|
348
367
|
if (event.type === 'thinking') {
|
|
349
368
|
this.v3IterationCount += 1;
|
|
350
369
|
const iterText = event.content || '';
|
|
351
|
-
const iterMatch = iterText.match(/Iteration (\d+)/i);
|
|
352
|
-
const iterNum = iterMatch ? iterMatch[1] : String(this.v3IterationCount);
|
|
353
370
|
if (spinner.isSpinning)
|
|
354
371
|
spinner.stop();
|
|
355
|
-
process.stderr.write(chalk_1.default.cyan(`\n── Iteration ${
|
|
372
|
+
process.stderr.write(chalk_1.default.cyan(`\n── ${iterText || `Iteration ${this.v3IterationCount}`} ──\n`));
|
|
356
373
|
spinner.start();
|
|
357
374
|
spinner.text = 'Analyzing...';
|
|
358
375
|
return;
|
|
@@ -385,18 +402,66 @@ class ChatCommand {
|
|
|
385
402
|
const tools = event.tool_calls || this.v3ToolCallCount;
|
|
386
403
|
if (spinner.isSpinning)
|
|
387
404
|
spinner.stop();
|
|
388
|
-
|
|
405
|
+
let statLine = `${iters} iterations, ${tools} tool calls`;
|
|
406
|
+
if (elapsed)
|
|
407
|
+
statLine += `, ${elapsed}`;
|
|
408
|
+
if (event.mode === 'planner-executor') {
|
|
409
|
+
const ok = event.tasks_completed ?? '?';
|
|
410
|
+
const fail = event.tasks_failed ?? 0;
|
|
411
|
+
statLine += ` — ${ok} tasks done`;
|
|
412
|
+
if (fail > 0)
|
|
413
|
+
statLine += chalk_1.default.yellow(`, ${fail} failed`);
|
|
414
|
+
}
|
|
415
|
+
process.stderr.write(chalk_1.default.green(`\n✓ Complete`) + ` — ${statLine}\n`);
|
|
416
|
+
// Show seal quality score if available
|
|
417
|
+
if (event.seal_score && typeof event.seal_score.overall === 'number') {
|
|
418
|
+
const score = event.seal_score.overall;
|
|
419
|
+
const tier = event.seal_score.tier || '';
|
|
420
|
+
const scoreColor = score >= 7 ? chalk_1.default.green : score >= 5 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
421
|
+
process.stderr.write(chalk_1.default.cyan(' [Quality] ') + scoreColor(`${score}/10`) + (tier ? chalk_1.default.gray(` (${tier})`) : '') + '\n');
|
|
422
|
+
}
|
|
389
423
|
return;
|
|
390
424
|
}
|
|
391
425
|
if (event.type === 'plan') {
|
|
392
|
-
const
|
|
426
|
+
const plan = event.plan || {};
|
|
427
|
+
const planKind = plan.task_kind || event.task_kind || '';
|
|
428
|
+
const quality = plan.quality_profile || '';
|
|
393
429
|
if (spinner.isSpinning)
|
|
394
430
|
spinner.stop();
|
|
395
|
-
process.stderr.write(chalk_1.default.cyan(` [Plan] `) + `Task: ${planKind || 'analyzing'}
|
|
431
|
+
process.stderr.write(chalk_1.default.cyan(` [Plan] `) + `Task: ${planKind || 'analyzing'}`);
|
|
432
|
+
if (quality)
|
|
433
|
+
process.stderr.write(chalk_1.default.gray(` (${quality})`));
|
|
434
|
+
process.stderr.write('\n');
|
|
435
|
+
// Planner-executor: show task list
|
|
436
|
+
if (Array.isArray(plan.tasks) && plan.tasks.length > 0) {
|
|
437
|
+
process.stderr.write(chalk_1.default.gray(` ${plan.total_tasks || plan.tasks.length} tasks:\n`));
|
|
438
|
+
for (const t of plan.tasks.slice(0, 10)) {
|
|
439
|
+
const targets = Array.isArray(t.targets) && t.targets.length ? ` → ${t.targets.join(', ')}` : '';
|
|
440
|
+
process.stderr.write(chalk_1.default.gray(` • ${t.title || t.id}${targets}\n`));
|
|
441
|
+
}
|
|
442
|
+
if (plan.tasks.length > 10) {
|
|
443
|
+
process.stderr.write(chalk_1.default.gray(` ... and ${plan.tasks.length - 10} more\n`));
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
// Monolithic: show target files
|
|
447
|
+
if (Array.isArray(plan.target_files) && plan.target_files.length > 0) {
|
|
448
|
+
process.stderr.write(chalk_1.default.gray(` Files: ${plan.target_files.join(', ')}\n`));
|
|
449
|
+
}
|
|
396
450
|
spinner.start();
|
|
397
451
|
spinner.text = 'Planning...';
|
|
398
452
|
return;
|
|
399
453
|
}
|
|
454
|
+
if (event.type === 'file_mutation') {
|
|
455
|
+
const filePath = typeof event.path === 'string' ? event.path.split('/').slice(-2).join('/') : '';
|
|
456
|
+
const action = event.action === 'delete' ? chalk_1.default.red('deleted') : chalk_1.default.green('wrote');
|
|
457
|
+
if (filePath) {
|
|
458
|
+
if (spinner.isSpinning)
|
|
459
|
+
spinner.stop();
|
|
460
|
+
process.stderr.write(chalk_1.default.cyan(' [File] ') + `${action} ${filePath}\n`);
|
|
461
|
+
spinner.start();
|
|
462
|
+
}
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
400
465
|
if (event.type === 'error') {
|
|
401
466
|
if (event.checkpointed) {
|
|
402
467
|
if (spinner.isSpinning)
|
package/dist/commands/history.js
CHANGED
|
@@ -62,6 +62,8 @@ class HistoryCommand {
|
|
|
62
62
|
const params = new URLSearchParams({
|
|
63
63
|
limit: String(limit),
|
|
64
64
|
workspace_root: workspace,
|
|
65
|
+
local_workspace_path: project,
|
|
66
|
+
project_path: project,
|
|
65
67
|
});
|
|
66
68
|
const resp = await fetch(`${baseUrl}/api/runs?${params}`, {
|
|
67
69
|
headers: this.getHeaders(),
|