vigthoria-cli 1.6.58 → 1.6.60
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 +2 -2
- package/dist/commands/auth.js +151 -64
- package/dist/commands/chat.d.ts +1 -0
- package/dist/commands/chat.js +114 -25
- package/dist/commands/deploy.js +2 -0
- package/dist/utils/logger.js +29 -24
- package/package.json +1 -1
package/dist/commands/auth.d.ts
CHANGED
|
@@ -12,8 +12,8 @@ export declare class AuthCommand {
|
|
|
12
12
|
private api;
|
|
13
13
|
constructor(config: Config, logger: Logger);
|
|
14
14
|
login(options: LoginOptions): Promise<void>;
|
|
15
|
-
private
|
|
16
|
-
private
|
|
15
|
+
private askInput;
|
|
16
|
+
private doCredentialLogin;
|
|
17
17
|
private loginWithToken;
|
|
18
18
|
private loginWithBrowser;
|
|
19
19
|
logout(): Promise<void>;
|
package/dist/commands/auth.js
CHANGED
|
@@ -2,15 +2,100 @@
|
|
|
2
2
|
/**
|
|
3
3
|
* Auth Command - Authentication management
|
|
4
4
|
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
17
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
18
|
+
}) : function(o, v) {
|
|
19
|
+
o["default"] = v;
|
|
20
|
+
});
|
|
21
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
22
|
+
var ownKeys = function(o) {
|
|
23
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
24
|
+
var ar = [];
|
|
25
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
26
|
+
return ar;
|
|
27
|
+
};
|
|
28
|
+
return ownKeys(o);
|
|
29
|
+
};
|
|
30
|
+
return function (mod) {
|
|
31
|
+
if (mod && mod.__esModule) return mod;
|
|
32
|
+
var result = {};
|
|
33
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
34
|
+
__setModuleDefault(result, mod);
|
|
35
|
+
return result;
|
|
36
|
+
};
|
|
37
|
+
})();
|
|
5
38
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
39
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
40
|
};
|
|
8
41
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
42
|
exports.AuthCommand = void 0;
|
|
10
43
|
const chalk_1 = __importDefault(require("chalk"));
|
|
11
|
-
const
|
|
44
|
+
const readline = __importStar(require("readline"));
|
|
12
45
|
const logger_js_1 = require("../utils/logger.js");
|
|
13
46
|
const api_js_1 = require("../utils/api.js");
|
|
47
|
+
/**
|
|
48
|
+
* Prompt helpers using Node's built-in readline.
|
|
49
|
+
* inquirer 9.x destroys the readline interface after each prompt() call
|
|
50
|
+
* which triggers ERR_USE_AFTER_CLOSE on Node 20 Windows TTY when a second
|
|
51
|
+
* prompt is attempted on the same process.stdin. Using raw readline avoids
|
|
52
|
+
* this entirely.
|
|
53
|
+
*/
|
|
54
|
+
function ask(rl, question) {
|
|
55
|
+
return new Promise((resolve) => rl.question(question, resolve));
|
|
56
|
+
}
|
|
57
|
+
function askHidden(question) {
|
|
58
|
+
return new Promise((resolve, reject) => {
|
|
59
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
60
|
+
// Temporarily mute output to hide typed characters
|
|
61
|
+
const stdout = process.stdout;
|
|
62
|
+
let answer = '';
|
|
63
|
+
process.stdout.write(question);
|
|
64
|
+
if (process.stdin.isTTY) {
|
|
65
|
+
process.stdin.setRawMode(true);
|
|
66
|
+
}
|
|
67
|
+
process.stdin.resume();
|
|
68
|
+
const onData = (ch) => {
|
|
69
|
+
const c = ch.toString('utf8');
|
|
70
|
+
if (c === '\n' || c === '\r' || c === '\u0004') {
|
|
71
|
+
if (process.stdin.isTTY) {
|
|
72
|
+
process.stdin.setRawMode(false);
|
|
73
|
+
}
|
|
74
|
+
process.stdin.removeListener('data', onData);
|
|
75
|
+
stdout.write('\n');
|
|
76
|
+
rl.close();
|
|
77
|
+
resolve(answer);
|
|
78
|
+
}
|
|
79
|
+
else if (c === '\u007f' || c === '\b') {
|
|
80
|
+
// backspace
|
|
81
|
+
if (answer.length > 0) {
|
|
82
|
+
answer = answer.slice(0, -1);
|
|
83
|
+
stdout.write('\b \b');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
else if (c === '\u0003') {
|
|
87
|
+
// Ctrl-C
|
|
88
|
+
rl.close();
|
|
89
|
+
process.exit(1);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
answer += c;
|
|
93
|
+
stdout.write('*');
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
process.stdin.on('data', onData);
|
|
97
|
+
});
|
|
98
|
+
}
|
|
14
99
|
class AuthCommand {
|
|
15
100
|
config;
|
|
16
101
|
logger;
|
|
@@ -29,52 +114,70 @@ class AuthCommand {
|
|
|
29
114
|
console.log();
|
|
30
115
|
console.log(chalk_1.default.cyan(`${logger_js_1.CH.hDouble.repeat(3)} Vigthoria Login ${logger_js_1.CH.hDouble.repeat(3)}`));
|
|
31
116
|
console.log();
|
|
32
|
-
//
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
117
|
+
// Use Node's built-in readline instead of inquirer.
|
|
118
|
+
// inquirer 9.x destroys and recreates readline interfaces per prompt
|
|
119
|
+
// which causes ERR_USE_AFTER_CLOSE on Node 20 Windows TTY.
|
|
120
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
121
|
+
try {
|
|
122
|
+
console.log(chalk_1.default.white(' 1) Email & Password'));
|
|
123
|
+
console.log(chalk_1.default.white(' 2) API Token'));
|
|
124
|
+
console.log(chalk_1.default.white(' 3) Browser Login'));
|
|
125
|
+
console.log();
|
|
126
|
+
const choice = (await ask(rl, chalk_1.default.cyan('? ') + 'Choose login method (1/2/3): ')).trim();
|
|
127
|
+
rl.close();
|
|
128
|
+
switch (choice) {
|
|
129
|
+
case '1':
|
|
130
|
+
case 'credentials': {
|
|
131
|
+
const email = await this.askInput('Email: ');
|
|
132
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
133
|
+
if (!emailRegex.test(email)) {
|
|
134
|
+
this.logger.error('Please enter a valid email');
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
const password = await askHidden(chalk_1.default.cyan('? ') + 'Password: ');
|
|
138
|
+
if (password.length < 6) {
|
|
139
|
+
this.logger.error('Password must be at least 6 characters');
|
|
140
|
+
return;
|
|
141
|
+
}
|
|
142
|
+
await this.doCredentialLogin(email, password);
|
|
143
|
+
break;
|
|
144
|
+
}
|
|
145
|
+
case '2':
|
|
146
|
+
case 'token': {
|
|
147
|
+
const token = await askHidden(chalk_1.default.cyan('? ') + 'API Token: ');
|
|
148
|
+
if (!token) {
|
|
149
|
+
this.logger.error('Please enter your API token');
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
await this.loginWithToken(token);
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
case '3':
|
|
156
|
+
case 'browser':
|
|
157
|
+
await this.loginWithBrowser();
|
|
158
|
+
break;
|
|
159
|
+
default:
|
|
160
|
+
this.logger.error('Invalid choice. Please enter 1, 2, or 3.');
|
|
161
|
+
break;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
catch (err) {
|
|
165
|
+
rl.close();
|
|
166
|
+
throw err;
|
|
55
167
|
}
|
|
56
168
|
}
|
|
57
|
-
|
|
58
|
-
const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
},
|
|
68
|
-
{
|
|
69
|
-
type: 'password',
|
|
70
|
-
name: 'password',
|
|
71
|
-
message: 'Password:',
|
|
72
|
-
mask: '*',
|
|
73
|
-
validate: (input) => input.length >= 6 || 'Password must be at least 6 characters',
|
|
74
|
-
},
|
|
75
|
-
]);
|
|
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
|
+
async doCredentialLogin(email, password) {
|
|
76
179
|
const spinner = (0, logger_js_1.createSpinner)('Logging in...').start();
|
|
77
|
-
const success = await this.api.login(
|
|
180
|
+
const success = await this.api.login(email, password);
|
|
78
181
|
spinner.stop();
|
|
79
182
|
if (success) {
|
|
80
183
|
this.printLoginSuccess();
|
|
@@ -83,18 +186,6 @@ class AuthCommand {
|
|
|
83
186
|
this.logger.error('Login failed. Please check your credentials.');
|
|
84
187
|
}
|
|
85
188
|
}
|
|
86
|
-
async loginWithTokenPrompt() {
|
|
87
|
-
const { token } = await inquirer_1.default.prompt([
|
|
88
|
-
{
|
|
89
|
-
type: 'password',
|
|
90
|
-
name: 'token',
|
|
91
|
-
message: 'API Token:',
|
|
92
|
-
mask: '*',
|
|
93
|
-
validate: (input) => input.length > 0 || 'Please enter your API token',
|
|
94
|
-
},
|
|
95
|
-
]);
|
|
96
|
-
await this.loginWithToken(token);
|
|
97
|
-
}
|
|
98
189
|
async loginWithToken(token) {
|
|
99
190
|
const spinner = (0, logger_js_1.createSpinner)('Validating token...').start();
|
|
100
191
|
const success = await this.api.loginWithToken(token);
|
|
@@ -117,14 +208,10 @@ class AuthCommand {
|
|
|
117
208
|
console.log();
|
|
118
209
|
}
|
|
119
210
|
async logout() {
|
|
120
|
-
const {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
message: 'Are you sure you want to logout?',
|
|
125
|
-
default: false,
|
|
126
|
-
},
|
|
127
|
-
]);
|
|
211
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
212
|
+
const answer = await ask(rl, chalk_1.default.cyan('? ') + 'Are you sure you want to logout? (y/N): ');
|
|
213
|
+
rl.close();
|
|
214
|
+
const confirm = /^y(es)?$/i.test(answer.trim());
|
|
128
215
|
if (confirm) {
|
|
129
216
|
this.config.clearAuth();
|
|
130
217
|
this.logger.success('Logged out successfully');
|
package/dist/commands/chat.d.ts
CHANGED
package/dist/commands/chat.js
CHANGED
|
@@ -298,6 +298,7 @@ class ChatCommand {
|
|
|
298
298
|
v3IterationCount = 0;
|
|
299
299
|
v3ToolCallCount = 0;
|
|
300
300
|
v3LastActivity = Date.now();
|
|
301
|
+
v3StreamingStarted = false;
|
|
301
302
|
describeV3AgentTool(toolName) {
|
|
302
303
|
const normalized = String(toolName || '').toLowerCase();
|
|
303
304
|
if (/read|grep|search|list|find|glob/.test(normalized)) {
|
|
@@ -324,14 +325,24 @@ class ChatCommand {
|
|
|
324
325
|
const toolDesc = this.describeV3AgentTool(event.tool || event.name || event.tool_name);
|
|
325
326
|
const toolTarget = event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '';
|
|
326
327
|
const shortTarget = toolTarget ? ` → ${String(toolTarget).split('/').slice(-2).join('/')}` : '';
|
|
327
|
-
|
|
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
|
+
if (spinner.isSpinning)
|
|
331
|
+
spinner.stop();
|
|
332
|
+
process.stderr.write(stepLabel + '\n');
|
|
333
|
+
spinner.start();
|
|
334
|
+
spinner.text = `Running ${toolDesc}...`;
|
|
328
335
|
return;
|
|
329
336
|
}
|
|
330
337
|
if (event.type === 'tool_result') {
|
|
331
338
|
const success = event.success !== false;
|
|
332
339
|
const toolName = event.name || event.tool || '';
|
|
333
|
-
const indicator = success ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
|
|
334
|
-
spinner.
|
|
340
|
+
const indicator = success ? chalk_1.default.green(' ✓') : chalk_1.default.red(' ✗');
|
|
341
|
+
if (spinner.isSpinning)
|
|
342
|
+
spinner.stop();
|
|
343
|
+
process.stderr.write(`${indicator} ${toolName}\n`);
|
|
344
|
+
spinner.start();
|
|
345
|
+
spinner.text = 'Next step...';
|
|
335
346
|
return;
|
|
336
347
|
}
|
|
337
348
|
if (event.type === 'thinking') {
|
|
@@ -339,43 +350,83 @@ class ChatCommand {
|
|
|
339
350
|
const iterText = event.content || '';
|
|
340
351
|
const iterMatch = iterText.match(/Iteration (\d+)/i);
|
|
341
352
|
const iterNum = iterMatch ? iterMatch[1] : String(this.v3IterationCount);
|
|
342
|
-
spinner.
|
|
353
|
+
if (spinner.isSpinning)
|
|
354
|
+
spinner.stop();
|
|
355
|
+
process.stderr.write(chalk_1.default.cyan(`\n── Iteration ${iterNum} ──\n`));
|
|
356
|
+
spinner.start();
|
|
357
|
+
spinner.text = 'Analyzing...';
|
|
343
358
|
return;
|
|
344
359
|
}
|
|
345
|
-
if (event.type === 'message') {
|
|
346
|
-
const
|
|
347
|
-
|
|
360
|
+
if (event.type === 'message' || event.type === 'assistant' || event.type === 'text' || event.type === 'content_block_delta') {
|
|
361
|
+
const text = event.type === 'content_block_delta'
|
|
362
|
+
? (event.delta?.text || '')
|
|
363
|
+
: (event.content || '');
|
|
364
|
+
if (text) {
|
|
365
|
+
if (!this.v3StreamingStarted) {
|
|
366
|
+
this.v3StreamingStarted = true;
|
|
367
|
+
spinner.stop();
|
|
368
|
+
if (!this.directPromptMode) {
|
|
369
|
+
console.log();
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
else {
|
|
373
|
+
spinner.stop();
|
|
374
|
+
}
|
|
375
|
+
process.stdout.write(text);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
spinner.text = chalk_1.default.cyan('[Response] ') + 'Writing response...';
|
|
379
|
+
}
|
|
348
380
|
return;
|
|
349
381
|
}
|
|
350
382
|
if (event.type === 'complete') {
|
|
351
383
|
const elapsed = event.elapsed || '';
|
|
352
384
|
const iters = event.iterations || this.v3IterationCount;
|
|
353
385
|
const tools = event.tool_calls || this.v3ToolCallCount;
|
|
354
|
-
spinner.
|
|
386
|
+
if (spinner.isSpinning)
|
|
387
|
+
spinner.stop();
|
|
388
|
+
process.stderr.write(chalk_1.default.green(`\n✓ Complete`) + ` — ${iters} iterations, ${tools} tool calls${elapsed ? `, ${elapsed}` : ''}\n`);
|
|
355
389
|
return;
|
|
356
390
|
}
|
|
357
391
|
if (event.type === 'plan') {
|
|
358
392
|
const planKind = event.plan?.task_kind || event.task_kind || '';
|
|
359
|
-
spinner.
|
|
393
|
+
if (spinner.isSpinning)
|
|
394
|
+
spinner.stop();
|
|
395
|
+
process.stderr.write(chalk_1.default.cyan(` [Plan] `) + `Task: ${planKind || 'analyzing'}...\n`);
|
|
396
|
+
spinner.start();
|
|
397
|
+
spinner.text = 'Planning...';
|
|
360
398
|
return;
|
|
361
399
|
}
|
|
362
400
|
if (event.type === 'error') {
|
|
363
401
|
if (event.checkpointed) {
|
|
364
|
-
spinner.
|
|
402
|
+
if (spinner.isSpinning)
|
|
403
|
+
spinner.stop();
|
|
404
|
+
process.stderr.write(chalk_1.default.yellow(' [Checkpoint] ') + 'Budget reached — auto-continuing...\n');
|
|
405
|
+
spinner.start();
|
|
365
406
|
}
|
|
366
407
|
else {
|
|
367
|
-
|
|
408
|
+
if (spinner.isSpinning)
|
|
409
|
+
spinner.stop();
|
|
410
|
+
process.stderr.write(chalk_1.default.red(' [Error] ') + (event.message || 'Agent error') + '\n');
|
|
368
411
|
}
|
|
369
412
|
return;
|
|
370
413
|
}
|
|
371
414
|
if (event.type === 'context') {
|
|
372
|
-
spinner.
|
|
415
|
+
if (spinner.isSpinning)
|
|
416
|
+
spinner.stop();
|
|
417
|
+
process.stderr.write(chalk_1.default.cyan(' [Context] ') + 'Workspace bound\n');
|
|
418
|
+
spinner.start();
|
|
419
|
+
spinner.text = 'Starting agent...';
|
|
373
420
|
return;
|
|
374
421
|
}
|
|
375
422
|
if (event.type === 'start') {
|
|
376
423
|
this.v3IterationCount = 0;
|
|
377
424
|
this.v3ToolCallCount = 0;
|
|
378
|
-
spinner.
|
|
425
|
+
if (spinner.isSpinning)
|
|
426
|
+
spinner.stop();
|
|
427
|
+
process.stderr.write(chalk_1.default.cyan(' [Start] ') + 'Agent initialized\n');
|
|
428
|
+
spinner.start();
|
|
429
|
+
spinner.text = 'Working...';
|
|
379
430
|
}
|
|
380
431
|
}
|
|
381
432
|
updateOperatorSpinner(spinner, event) {
|
|
@@ -383,24 +434,44 @@ class ChatCommand {
|
|
|
383
434
|
return;
|
|
384
435
|
}
|
|
385
436
|
if (event.type === 'started') {
|
|
386
|
-
spinner.
|
|
437
|
+
if (spinner.isSpinning)
|
|
438
|
+
spinner.stop();
|
|
439
|
+
process.stderr.write(chalk_1.default.cyan(' [Operator] ') + 'Starting BMAD workflow...\n');
|
|
440
|
+
spinner.start();
|
|
441
|
+
spinner.text = 'Connecting...';
|
|
387
442
|
return;
|
|
388
443
|
}
|
|
389
444
|
if (event.type === 'connected') {
|
|
390
|
-
spinner.
|
|
445
|
+
if (spinner.isSpinning)
|
|
446
|
+
spinner.stop();
|
|
447
|
+
process.stderr.write(chalk_1.default.green(' ✓') + ' Connected to BMAD stream\n');
|
|
448
|
+
spinner.start();
|
|
449
|
+
spinner.text = 'Working...';
|
|
391
450
|
return;
|
|
392
451
|
}
|
|
393
452
|
if (event.type === 'agent') {
|
|
394
|
-
|
|
453
|
+
const agentName = event.agent || 'BMAD agent';
|
|
454
|
+
if (spinner.isSpinning)
|
|
455
|
+
spinner.stop();
|
|
456
|
+
process.stderr.write(chalk_1.default.cyan(` [Agent] `) + agentName + '\n');
|
|
457
|
+
spinner.start();
|
|
458
|
+
spinner.text = `Running ${agentName}...`;
|
|
395
459
|
return;
|
|
396
460
|
}
|
|
397
461
|
if (event.type === 'status') {
|
|
398
462
|
const progress = Number.isFinite(Number(event.progress)) ? ` (${event.progress}%)` : '';
|
|
399
|
-
|
|
463
|
+
const statusText = `${event.status || 'Working'}${progress}`;
|
|
464
|
+
if (spinner.isSpinning)
|
|
465
|
+
spinner.stop();
|
|
466
|
+
process.stderr.write(chalk_1.default.cyan(' [Status] ') + statusText + '\n');
|
|
467
|
+
spinner.start();
|
|
468
|
+
spinner.text = statusText;
|
|
400
469
|
return;
|
|
401
470
|
}
|
|
402
471
|
if (event.type === 'result') {
|
|
403
|
-
spinner.
|
|
472
|
+
if (spinner.isSpinning)
|
|
473
|
+
spinner.stop();
|
|
474
|
+
process.stderr.write(chalk_1.default.green('\n ✓ Operator workflow complete\n'));
|
|
404
475
|
return;
|
|
405
476
|
}
|
|
406
477
|
}
|
|
@@ -828,13 +899,19 @@ class ChatCommand {
|
|
|
828
899
|
await this.runOperatorDirectAnswer(prompt);
|
|
829
900
|
return;
|
|
830
901
|
}
|
|
831
|
-
// ── Repo-grounded operator path:
|
|
902
|
+
// ── Repo-grounded operator path: try V3 agent first, then fall back ──
|
|
832
903
|
// Prompts that reference files, code symbols, or analysis verbs need
|
|
833
904
|
// tool access to read actual file contents. Route these through the
|
|
834
|
-
//
|
|
835
|
-
//
|
|
905
|
+
// V3 agent (which archives runs for history/replay/fork and supports
|
|
906
|
+
// workspace hydration) first. Falls back to local agent loop if V3
|
|
907
|
+
// is unreachable.
|
|
836
908
|
if (this.isRepoGroundedPrompt(prompt) && this.tools) {
|
|
837
909
|
this.operatorMode = true;
|
|
910
|
+
const handledByV3 = await this.tryV3AgentWorkflow(prompt);
|
|
911
|
+
if (handledByV3) {
|
|
912
|
+
this.saveSession();
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
838
915
|
await this.runLocalAgentLoop(prompt);
|
|
839
916
|
return;
|
|
840
917
|
}
|
|
@@ -1431,6 +1508,7 @@ class ChatCommand {
|
|
|
1431
1508
|
this.v3IterationCount = 0;
|
|
1432
1509
|
this.v3ToolCallCount = 0;
|
|
1433
1510
|
this.v3LastActivity = Date.now();
|
|
1511
|
+
this.v3StreamingStarted = false;
|
|
1434
1512
|
const spinner = this.jsonOutput ? null : (0, logger_js_1.createSpinner)({
|
|
1435
1513
|
text: routingPolicy.cloudSelected ? 'Routing heavy task to Vigthoria Cloud...' : 'Routing to V3 Agent...',
|
|
1436
1514
|
spinner: 'clock',
|
|
@@ -1484,6 +1562,10 @@ class ChatCommand {
|
|
|
1484
1562
|
if (spinner) {
|
|
1485
1563
|
spinner.stop();
|
|
1486
1564
|
}
|
|
1565
|
+
// End streaming line if we streamed text inline
|
|
1566
|
+
if (this.v3StreamingStarted) {
|
|
1567
|
+
process.stdout.write('\n');
|
|
1568
|
+
}
|
|
1487
1569
|
const previewGate = (response.metadata?.previewGate || null);
|
|
1488
1570
|
const workspaceHasOutput = this.api.hasAgentWorkspaceOutput(workspaceContext);
|
|
1489
1571
|
const success = previewGate?.required === true
|
|
@@ -1536,6 +1618,12 @@ class ChatCommand {
|
|
|
1536
1618
|
metadata: response.metadata || {},
|
|
1537
1619
|
}, null, 2));
|
|
1538
1620
|
}
|
|
1621
|
+
else if (this.v3StreamingStarted) {
|
|
1622
|
+
// Content was already streamed to stdout in real-time; skip duplicate print.
|
|
1623
|
+
if (!this.directPromptMode) {
|
|
1624
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
|
|
1625
|
+
}
|
|
1626
|
+
}
|
|
1539
1627
|
else if (response.content) {
|
|
1540
1628
|
if (!this.directPromptMode) {
|
|
1541
1629
|
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
|
|
@@ -1976,10 +2064,11 @@ class ChatCommand {
|
|
|
1976
2064
|
if (!this.directPromptMode) {
|
|
1977
2065
|
return false;
|
|
1978
2066
|
}
|
|
1979
|
-
|
|
1980
|
-
|
|
1981
|
-
|
|
1982
|
-
|
|
2067
|
+
// Always prefer V3 agent first — it supports workspace hydration for
|
|
2068
|
+
// non-server-bindable workspaces (Windows paths, remote machines).
|
|
2069
|
+
// The V3 path will fall back to local-agent-loop if V3 is unreachable.
|
|
2070
|
+
// This ensures runs get archived for history/replay/fork.
|
|
2071
|
+
return false;
|
|
1983
2072
|
}
|
|
1984
2073
|
shouldRequireV3AgentWorkflow(prompt) {
|
|
1985
2074
|
if (!this.directPromptMode) {
|
package/dist/commands/deploy.js
CHANGED
|
@@ -127,6 +127,7 @@ class DeployCommand {
|
|
|
127
127
|
* Deploy to preview URL (free)
|
|
128
128
|
*/
|
|
129
129
|
async deployToPreview(projectPath) {
|
|
130
|
+
this.requireAuth();
|
|
130
131
|
const spinner = (0, logger_js_1.createSpinner)('Deploying to preview...').start();
|
|
131
132
|
try {
|
|
132
133
|
const projectDir = projectPath || process.cwd();
|
|
@@ -155,6 +156,7 @@ class DeployCommand {
|
|
|
155
156
|
this.logger.error('Deploy failed');
|
|
156
157
|
const errMsg = error instanceof Error ? error.message : 'Unknown error';
|
|
157
158
|
console.log(chalk_1.default.red(`\n❌ Error: ${errMsg}\n`));
|
|
159
|
+
process.exitCode = 1;
|
|
158
160
|
}
|
|
159
161
|
}
|
|
160
162
|
/**
|
package/dist/utils/logger.js
CHANGED
|
@@ -11,41 +11,46 @@ exports.createSpinner = createSpinner;
|
|
|
11
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
12
|
const ora_1 = __importDefault(require("ora"));
|
|
13
13
|
/**
|
|
14
|
-
* Platform-aware character map.
|
|
15
|
-
*
|
|
16
|
-
*
|
|
14
|
+
* Platform-aware character map.
|
|
15
|
+
*
|
|
16
|
+
* Modern Windows terminals (Windows Terminal, PowerShell 7, VS Code,
|
|
17
|
+
* cmd.exe with chcp 65001) render Unicode box-drawing correctly.
|
|
18
|
+
* Only truly legacy code-page 437/850 consoles cannot, and those are
|
|
19
|
+
* vanishingly rare on Node 20+. We now default to full Unicode
|
|
20
|
+
* everywhere and only strip emoji (multi-codepoint) on Windows where
|
|
21
|
+
* monospace rendering can break.
|
|
17
22
|
*/
|
|
18
23
|
const isWin = process.platform === 'win32';
|
|
19
24
|
exports.CH = {
|
|
20
|
-
info:
|
|
21
|
-
warn:
|
|
22
|
-
error:
|
|
23
|
-
success:
|
|
25
|
+
info: 'ℹ',
|
|
26
|
+
warn: '⚠',
|
|
27
|
+
error: '✗',
|
|
28
|
+
success: '✓',
|
|
24
29
|
ai: isWin ? '>' : '🤖',
|
|
25
30
|
user: isWin ? '$' : '👤',
|
|
26
|
-
hLine:
|
|
27
|
-
hDouble:
|
|
28
|
-
vLine:
|
|
29
|
-
tl:
|
|
30
|
-
tr:
|
|
31
|
-
bl:
|
|
32
|
-
br:
|
|
33
|
-
teeR:
|
|
34
|
-
teeL:
|
|
35
|
-
cross:
|
|
36
|
-
bullet:
|
|
31
|
+
hLine: '─',
|
|
32
|
+
hDouble: '═',
|
|
33
|
+
vLine: '│',
|
|
34
|
+
tl: '┌',
|
|
35
|
+
tr: '┐',
|
|
36
|
+
bl: '└',
|
|
37
|
+
br: '┘',
|
|
38
|
+
teeR: '├',
|
|
39
|
+
teeL: '┤',
|
|
40
|
+
cross: '┼',
|
|
41
|
+
bullet: '•',
|
|
37
42
|
cloud: isWin ? '[cloud]' : '☁️ ',
|
|
38
43
|
home: isWin ? '[local]' : '🏠 ',
|
|
39
44
|
rocket: isWin ? '>>' : '🚀',
|
|
40
45
|
lock: isWin ? '[lock]' : '🔒',
|
|
41
46
|
warnEmoji: isWin ? '[!]' : '⚠️',
|
|
42
47
|
// Double-line box drawing (used for main banner)
|
|
43
|
-
dTl:
|
|
44
|
-
dTr:
|
|
45
|
-
dBl:
|
|
46
|
-
dBr:
|
|
47
|
-
dH:
|
|
48
|
-
dV:
|
|
48
|
+
dTl: '╔',
|
|
49
|
+
dTr: '╗',
|
|
50
|
+
dBl: '╚',
|
|
51
|
+
dBr: '╝',
|
|
52
|
+
dH: '═',
|
|
53
|
+
dV: '║',
|
|
49
54
|
};
|
|
50
55
|
/**
|
|
51
56
|
* Create an ora spinner that writes to stderr so it never
|