vigthoria-cli 1.7.0 → 1.8.1
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 +19 -21
- package/dist/commands/chat.js +74 -9
- package/dist/utils/api.js +1 -1
- package/package.json +2 -3
package/dist/commands/auth.d.ts
CHANGED
package/dist/commands/auth.js
CHANGED
|
@@ -50,27 +50,30 @@ 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
|
-
// In non-interactive (piped) terminals, fall back to plain
|
|
61
|
+
function askHidden(rl, question) {
|
|
62
|
+
// In non-interactive (piped) terminals, fall back to plain rl.question
|
|
59
63
|
// because raw data events won't fire after stdin reaches EOF.
|
|
60
64
|
if (!process.stdin.isTTY) {
|
|
61
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
62
65
|
return new Promise((resolve) => {
|
|
63
66
|
rl.question(question, (answer) => {
|
|
64
|
-
rl.close();
|
|
65
67
|
resolve(answer.trim());
|
|
66
68
|
});
|
|
67
69
|
});
|
|
68
70
|
}
|
|
69
|
-
return new Promise((resolve
|
|
70
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
71
|
+
return new Promise((resolve) => {
|
|
71
72
|
const stdout = process.stdout;
|
|
72
73
|
let answer = '';
|
|
73
|
-
|
|
74
|
+
// Pause rl so it doesn't compete for stdin data events
|
|
75
|
+
rl.pause();
|
|
76
|
+
stdout.write(question);
|
|
74
77
|
process.stdin.setRawMode(true);
|
|
75
78
|
process.stdin.resume();
|
|
76
79
|
const onData = (ch) => {
|
|
@@ -79,7 +82,7 @@ function askHidden(question) {
|
|
|
79
82
|
process.stdin.setRawMode(false);
|
|
80
83
|
process.stdin.removeListener('data', onData);
|
|
81
84
|
stdout.write('\n');
|
|
82
|
-
rl.
|
|
85
|
+
rl.resume();
|
|
83
86
|
resolve(answer);
|
|
84
87
|
}
|
|
85
88
|
else if (c === '\u007f' || c === '\b') {
|
|
@@ -128,17 +131,18 @@ class AuthCommand {
|
|
|
128
131
|
console.log(chalk_1.default.white(' 3) Browser Login'));
|
|
129
132
|
console.log();
|
|
130
133
|
const choice = (await ask(rl, chalk_1.default.cyan('? ') + 'Choose login method (1/2/3): ')).trim();
|
|
131
|
-
rl.close();
|
|
132
134
|
switch (choice) {
|
|
133
135
|
case '1':
|
|
134
136
|
case 'credentials': {
|
|
135
|
-
const email = await
|
|
137
|
+
const email = (await ask(rl, chalk_1.default.cyan('? ') + 'Email: ')).trim();
|
|
136
138
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
137
139
|
if (!emailRegex.test(email)) {
|
|
138
140
|
this.logger.error('Please enter a valid email');
|
|
141
|
+
rl.close();
|
|
139
142
|
return;
|
|
140
143
|
}
|
|
141
|
-
const password = await askHidden(chalk_1.default.cyan('? ') + 'Password: ');
|
|
144
|
+
const password = await askHidden(rl, chalk_1.default.cyan('? ') + 'Password: ');
|
|
145
|
+
rl.close();
|
|
142
146
|
if (password.length < 6) {
|
|
143
147
|
this.logger.error('Password must be at least 6 characters');
|
|
144
148
|
return;
|
|
@@ -148,7 +152,8 @@ class AuthCommand {
|
|
|
148
152
|
}
|
|
149
153
|
case '2':
|
|
150
154
|
case 'token': {
|
|
151
|
-
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();
|
|
152
157
|
if (!token) {
|
|
153
158
|
this.logger.error('Please enter your API token');
|
|
154
159
|
return;
|
|
@@ -158,9 +163,11 @@ class AuthCommand {
|
|
|
158
163
|
}
|
|
159
164
|
case '3':
|
|
160
165
|
case 'browser':
|
|
166
|
+
rl.close();
|
|
161
167
|
await this.loginWithBrowser();
|
|
162
168
|
break;
|
|
163
169
|
default:
|
|
170
|
+
rl.close();
|
|
164
171
|
this.logger.error('Invalid choice. Please enter 1, 2, or 3.');
|
|
165
172
|
break;
|
|
166
173
|
}
|
|
@@ -170,15 +177,6 @@ class AuthCommand {
|
|
|
170
177
|
throw err;
|
|
171
178
|
}
|
|
172
179
|
}
|
|
173
|
-
askInput(label) {
|
|
174
|
-
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
175
|
-
return new Promise((resolve) => {
|
|
176
|
-
rl.question(chalk_1.default.cyan('? ') + label, (answer) => {
|
|
177
|
-
rl.close();
|
|
178
|
-
resolve(answer.trim());
|
|
179
|
-
});
|
|
180
|
-
});
|
|
181
|
-
}
|
|
182
180
|
async doCredentialLogin(email, password) {
|
|
183
181
|
const spinner = (0, logger_js_1.createSpinner)('Logging in...').start();
|
|
184
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)
|
|
@@ -1541,7 +1606,7 @@ class ChatCommand {
|
|
|
1541
1606
|
clientSurface: 'cli',
|
|
1542
1607
|
localMachineCapable: true,
|
|
1543
1608
|
agentTimeoutMs: DEFAULT_V3_AGENT_TIMEOUT_MS,
|
|
1544
|
-
agentIdleTimeoutMs:
|
|
1609
|
+
agentIdleTimeoutMs: 0,
|
|
1545
1610
|
model: routingPolicy.selectedModel,
|
|
1546
1611
|
requestedModel: this.currentModel,
|
|
1547
1612
|
agentExecutionPolicy: routingPolicy,
|
|
@@ -1555,7 +1620,7 @@ class ChatCommand {
|
|
|
1555
1620
|
? Promise.race([
|
|
1556
1621
|
workflowPromise,
|
|
1557
1622
|
new Promise((_, reject) => {
|
|
1558
|
-
setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')),
|
|
1623
|
+
setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), 900000);
|
|
1559
1624
|
}),
|
|
1560
1625
|
])
|
|
1561
1626
|
: workflowPromise);
|
package/dist/utils/api.js
CHANGED
|
@@ -2732,7 +2732,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2732
2732
|
&& context.localMachineCapable !== false;
|
|
2733
2733
|
const rescueEligibleSaaS = preferLocalV3
|
|
2734
2734
|
&& /(saas|dashboard|analytics|billing|team management|activity feed|login screen)/i.test(message);
|
|
2735
|
-
const timeoutMs = rescueEligibleSaaS ? Math.min(baseTimeoutMs,
|
|
2735
|
+
const timeoutMs = rescueEligibleSaaS ? Math.min(baseTimeoutMs, 900000) : baseTimeoutMs;
|
|
2736
2736
|
const maxAttempts = preferLocalV3 ? 2 : 1;
|
|
2737
2737
|
let lastErrors = [];
|
|
2738
2738
|
for (let attempt = 1; attempt <= maxAttempts; attempt += 1) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigthoria-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.8.1",
|
|
4
4
|
"description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -43,8 +43,7 @@
|
|
|
43
43
|
"test:repo:live": "npm run build && node scripts/test-live-repo-e2e.js",
|
|
44
44
|
"test:game:live": "npm run build && node scripts/test-live-game-push.js",
|
|
45
45
|
"proof:agent": "npm run build && node scripts/proof-agent-mode.js",
|
|
46
|
-
"test:fresh-install": "node scripts/test-fresh-install.js"
|
|
47
|
-
"prepublishOnly": "npm run build && node scripts/verify-package-hygiene.js && node scripts/test-fresh-install.js"
|
|
46
|
+
"test:fresh-install": "node scripts/test-fresh-install.js"
|
|
48
47
|
},
|
|
49
48
|
"keywords": [
|
|
50
49
|
"ai",
|