vigthoria-cli 1.6.34 → 1.6.36
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.js +44 -44
- package/dist/commands/chat.js +6 -1
- package/dist/commands/config.js +2 -1
- package/dist/commands/deploy.js +4 -4
- package/dist/commands/generate.js +1 -1
- package/dist/commands/repo.js +13 -10
- package/dist/commands/review.js +4 -4
- package/dist/commands/workflow.js +8 -2
- package/dist/index.js +7 -7
- package/dist/utils/api.js +48 -35
- package/dist/utils/bridge-client.js +2 -1
- package/dist/utils/logger.d.ts +30 -0
- package/dist/utils/logger.js +61 -24
- package/dist/utils/tools.js +18 -17
- package/package.json +1 -1
package/dist/commands/auth.js
CHANGED
|
@@ -27,7 +27,7 @@ class AuthCommand {
|
|
|
27
27
|
return;
|
|
28
28
|
}
|
|
29
29
|
console.log();
|
|
30
|
-
console.log(chalk_1.default.cyan(
|
|
30
|
+
console.log(chalk_1.default.cyan(`${logger_js_1.CH.hDouble.repeat(3)} Vigthoria Login ${logger_js_1.CH.hDouble.repeat(3)}`));
|
|
31
31
|
console.log();
|
|
32
32
|
// Prompt for credentials
|
|
33
33
|
const answers = await inquirer_1.default.prompt([
|
|
@@ -132,7 +132,7 @@ class AuthCommand {
|
|
|
132
132
|
}
|
|
133
133
|
async status() {
|
|
134
134
|
console.log();
|
|
135
|
-
console.log(chalk_1.default.cyan(
|
|
135
|
+
console.log(chalk_1.default.cyan(`${logger_js_1.CH.hDouble.repeat(3)} Account Status ${logger_js_1.CH.hDouble.repeat(3)}`));
|
|
136
136
|
console.log();
|
|
137
137
|
if (!this.config.isAuthenticated()) {
|
|
138
138
|
this.logger.warn('Not logged in');
|
|
@@ -166,16 +166,34 @@ class AuthCommand {
|
|
|
166
166
|
console.log(chalk_1.default.white('Available Models:'));
|
|
167
167
|
const models = this.config.getAvailableModels();
|
|
168
168
|
models.forEach(m => {
|
|
169
|
-
console.log(chalk_1.default.gray(
|
|
169
|
+
console.log(chalk_1.default.gray(` ${logger_js_1.CH.bullet} `) + chalk_1.default.cyan(m.id) + chalk_1.default.gray(' -> ') + chalk_1.default.white(m.name));
|
|
170
170
|
const runtimeLabel = m.tier === 'cloud' ? 'cloud' : 'blackwell';
|
|
171
|
-
console.log(chalk_1.default.gray(` ${m.tier === 'cloud' ?
|
|
171
|
+
console.log(chalk_1.default.gray(` ${m.tier === 'cloud' ? logger_js_1.CH.cloud : logger_js_1.CH.home} ${m.description}`));
|
|
172
172
|
console.log(chalk_1.default.gray(` Backend: ${m.backendModel} (${runtimeLabel})`));
|
|
173
173
|
});
|
|
174
174
|
console.log();
|
|
175
|
-
//
|
|
176
|
-
const spinner = (0, logger_js_1.createSpinner)('Checking API
|
|
177
|
-
const apiStatus = await
|
|
175
|
+
// Run ALL three probes in parallel — they are independent.
|
|
176
|
+
const spinner = (0, logger_js_1.createSpinner)('Checking API, capabilities and auth...').start();
|
|
177
|
+
const [apiStatus, capabilityStatus, tokenValidation] = await Promise.all([
|
|
178
|
+
this.api.getHealthStatus(),
|
|
179
|
+
Promise.race([
|
|
180
|
+
this.api.getCapabilityTruthStatus({
|
|
181
|
+
workspacePath: process.cwd(),
|
|
182
|
+
projectPath: process.cwd(),
|
|
183
|
+
targetPath: process.cwd(),
|
|
184
|
+
}),
|
|
185
|
+
new Promise(resolve => setTimeout(() => resolve({
|
|
186
|
+
overallOk: false,
|
|
187
|
+
v3Agent: { name: 'V3 Agent', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
188
|
+
hyperLoop: { name: 'Hyper Loop', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
189
|
+
repoMemory: { name: 'Repo Memory', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
190
|
+
devtoolsBridge: { name: 'DevTools Bridge', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
191
|
+
}), 8000)),
|
|
192
|
+
]),
|
|
193
|
+
this.api.validateToken(),
|
|
194
|
+
]);
|
|
178
195
|
spinner.stop();
|
|
196
|
+
// --- Display API Status ---
|
|
179
197
|
console.log(chalk_1.default.white('API Status:'));
|
|
180
198
|
console.log(chalk_1.default.gray(' Overall: ') + (apiStatus.overallOk ? chalk_1.default.green('Healthy') : chalk_1.default.yellow('Degraded')));
|
|
181
199
|
console.log(chalk_1.default.gray(' Coder API: ') + (apiStatus.coder.ok ? chalk_1.default.green('Online') : chalk_1.default.red('Offline')) + chalk_1.default.gray(` (${apiStatus.coder.endpoint})`));
|
|
@@ -198,59 +216,41 @@ class AuthCommand {
|
|
|
198
216
|
else {
|
|
199
217
|
console.log(chalk_1.default.gray(' Self-hosted Models: ') + chalk_1.default.gray('disabled'));
|
|
200
218
|
}
|
|
201
|
-
|
|
202
|
-
const capabilityStatus = await Promise.race([
|
|
203
|
-
this.api.getCapabilityTruthStatus({
|
|
204
|
-
workspacePath: process.cwd(),
|
|
205
|
-
projectPath: process.cwd(),
|
|
206
|
-
targetPath: process.cwd(),
|
|
207
|
-
}),
|
|
208
|
-
new Promise(resolve => setTimeout(() => resolve({
|
|
209
|
-
overallOk: false,
|
|
210
|
-
v3Agent: { name: 'V3 Agent', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
211
|
-
hyperLoop: { name: 'Hyper Loop', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
212
|
-
repoMemory: { name: 'Repo Memory', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
213
|
-
devtoolsBridge: { name: 'DevTools Bridge', endpoint: '', ok: false, error: 'Timed out (8s)' },
|
|
214
|
-
}), 8000)),
|
|
215
|
-
]);
|
|
216
|
-
capabilitySpinner.stop();
|
|
219
|
+
// --- Display Capability Truth ---
|
|
217
220
|
console.log();
|
|
218
221
|
console.log(chalk_1.default.white('Capability Truth:'));
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
222
|
+
const coreOk = apiStatus.overallOk;
|
|
223
|
+
console.log(chalk_1.default.gray(' Overall: ') + (coreOk ? chalk_1.default.green('Verified') : chalk_1.default.yellow('Partial')));
|
|
224
|
+
// V3 Agent — used by agent/chat commands (routed through model API)
|
|
225
|
+
console.log(chalk_1.default.gray(' V3 Agent: ') + (capabilityStatus.v3Agent.ok ? chalk_1.default.green('Reachable') : chalk_1.default.gray('Not deployed (routed through model API)')));
|
|
226
|
+
if (capabilityStatus.v3Agent.error && capabilityStatus.v3Agent.ok === false) {
|
|
227
|
+
const err = capabilityStatus.v3Agent.error;
|
|
228
|
+
if (!/timed? out|not reachable|No V3 agent/i.test(err)) {
|
|
229
|
+
console.log(chalk_1.default.gray(' Error: ') + chalk_1.default.red(err));
|
|
230
|
+
}
|
|
224
231
|
}
|
|
225
232
|
// Hyper Loop — optional orchestration layer
|
|
226
|
-
console.log(chalk_1.default.gray(' Hyper Loop: ') + (capabilityStatus.hyperLoop.ok ? chalk_1.default.green('Reachable') : chalk_1.default.
|
|
227
|
-
if (capabilityStatus.hyperLoop.error) {
|
|
228
|
-
console.log(chalk_1.default.gray(' Error: ') + chalk_1.default.yellow(capabilityStatus.hyperLoop.error));
|
|
229
|
-
}
|
|
233
|
+
console.log(chalk_1.default.gray(' Hyper Loop: ') + (capabilityStatus.hyperLoop.ok ? chalk_1.default.green('Reachable') : chalk_1.default.gray('Not deployed (optional)')));
|
|
230
234
|
// Repo Memory — separate auth scope, only affects repo commands
|
|
231
|
-
console.log(chalk_1.default.gray(' Repo Memory: ') + (capabilityStatus.repoMemory.ok ? chalk_1.default.green('Active') : chalk_1.default.
|
|
235
|
+
console.log(chalk_1.default.gray(' Repo Memory: ') + (capabilityStatus.repoMemory.ok ? chalk_1.default.green('Active') : chalk_1.default.gray('Not deployed (optional)')));
|
|
232
236
|
if (capabilityStatus.repoMemory.details?.compactContextLength !== undefined) {
|
|
233
237
|
console.log(chalk_1.default.gray(' Compact Context: ') + chalk_1.default.cyan(`${capabilityStatus.repoMemory.details.compactContextLength} chars`));
|
|
234
238
|
}
|
|
235
|
-
if (capabilityStatus.repoMemory.error) {
|
|
236
|
-
console.log(chalk_1.default.gray(' Error: ') + chalk_1.default.yellow(capabilityStatus.repoMemory.error));
|
|
237
|
-
}
|
|
238
239
|
// DevTools Bridge — local service, not required
|
|
239
|
-
console.log(chalk_1.default.gray(' DevTools Bridge: ') + (capabilityStatus.devtoolsBridge.ok ? chalk_1.default.green('
|
|
240
|
-
|
|
241
|
-
console.log(chalk_1.default.gray(' Error: ') + chalk_1.default.gray(capabilityStatus.devtoolsBridge.error));
|
|
242
|
-
}
|
|
243
|
-
// Auth scope summary — use a real server-side probe for Model Auth
|
|
244
|
-
const tokenValidation = await this.api.validateToken();
|
|
240
|
+
console.log(chalk_1.default.gray(' DevTools Bridge: ') + (capabilityStatus.devtoolsBridge.ok ? chalk_1.default.green('Connected') : chalk_1.default.gray('Not running (optional)')));
|
|
241
|
+
// --- Display Auth Scopes ---
|
|
245
242
|
console.log();
|
|
246
243
|
console.log(chalk_1.default.white('Auth Scopes:'));
|
|
247
244
|
console.log(chalk_1.default.gray(' Model Auth: ') + (tokenValidation.valid ? chalk_1.default.green('Valid') : chalk_1.default.red('Invalid')) + chalk_1.default.gray(' (used by chat, agent, review, explain, generate, fix)'));
|
|
248
245
|
if (!tokenValidation.valid && tokenValidation.error) {
|
|
249
246
|
console.log(chalk_1.default.gray(' ') + chalk_1.default.red(tokenValidation.error));
|
|
250
247
|
}
|
|
251
|
-
console.log(chalk_1.default.gray(' Repo Auth: ') + (capabilityStatus.repoMemory.ok ? chalk_1.default.green('Active') : chalk_1.default.
|
|
252
|
-
console.log(chalk_1.default.gray(' Bridge Auth: ') + (capabilityStatus.devtoolsBridge.ok ? chalk_1.default.green('Connected') : chalk_1.default.gray('N/A')) + chalk_1.default.gray(' (used by --bridge flag only)'));
|
|
248
|
+
console.log(chalk_1.default.gray(' Repo Auth: ') + (capabilityStatus.repoMemory.ok ? chalk_1.default.green('Active') : chalk_1.default.gray('N/A — repo memory not deployed')) + chalk_1.default.gray(' (used by repo push/pull/list only)'));
|
|
249
|
+
console.log(chalk_1.default.gray(' Bridge Auth: ') + (capabilityStatus.devtoolsBridge.ok ? chalk_1.default.green('Connected') : chalk_1.default.gray('N/A — bridge not running')) + chalk_1.default.gray(' (used by --bridge flag only)'));
|
|
253
250
|
console.log();
|
|
251
|
+
// Force clean exit — lingering connections (bridge WebSocket,
|
|
252
|
+
// axios keep-alive) would otherwise keep the process alive.
|
|
253
|
+
process.exit(0);
|
|
254
254
|
}
|
|
255
255
|
printLoginSuccess() {
|
|
256
256
|
const email = this.config.get('email');
|
package/dist/commands/chat.js
CHANGED
|
@@ -1804,11 +1804,16 @@ class ChatCommand {
|
|
|
1804
1804
|
}
|
|
1805
1805
|
extractToolCalls(message) {
|
|
1806
1806
|
const calls = [];
|
|
1807
|
+
const seen = new Set();
|
|
1807
1808
|
const wrapperRegex = /<tool_call>([\s\S]*?)<\/tool_call>/g;
|
|
1808
1809
|
for (const match of message.matchAll(wrapperRegex)) {
|
|
1809
1810
|
const call = this.parseToolPayload(match[1] || '');
|
|
1810
1811
|
if (call) {
|
|
1811
|
-
|
|
1812
|
+
const key = `${call.tool}::${JSON.stringify(call.args)}`;
|
|
1813
|
+
if (!seen.has(key)) {
|
|
1814
|
+
seen.add(key);
|
|
1815
|
+
calls.push(call);
|
|
1816
|
+
}
|
|
1812
1817
|
}
|
|
1813
1818
|
}
|
|
1814
1819
|
return calls;
|
package/dist/commands/config.js
CHANGED
|
@@ -44,6 +44,7 @@ const chalk_1 = __importDefault(require("chalk"));
|
|
|
44
44
|
const inquirer_1 = __importDefault(require("inquirer"));
|
|
45
45
|
const fs = __importStar(require("fs"));
|
|
46
46
|
const path = __importStar(require("path"));
|
|
47
|
+
const logger_js_1 = require("../utils/logger.js");
|
|
47
48
|
class ConfigCommand {
|
|
48
49
|
config;
|
|
49
50
|
logger;
|
|
@@ -73,7 +74,7 @@ class ConfigCommand {
|
|
|
73
74
|
}
|
|
74
75
|
async init() {
|
|
75
76
|
console.log();
|
|
76
|
-
console.log(chalk_1.default.cyan(
|
|
77
|
+
console.log(chalk_1.default.cyan(`${logger_js_1.CH.hDouble.repeat(3)} Initialize Vigthoria in Project ${logger_js_1.CH.hDouble.repeat(3)}`));
|
|
77
78
|
console.log();
|
|
78
79
|
const cwd = process.cwd();
|
|
79
80
|
const configFile = path.join(cwd, '.vigthoria.json');
|
package/dist/commands/deploy.js
CHANGED
|
@@ -182,7 +182,7 @@ class DeployCommand {
|
|
|
182
182
|
if (!response.ok || !data.success) {
|
|
183
183
|
if (data.requiresSubscription) {
|
|
184
184
|
spinner.stop();
|
|
185
|
-
console.log(chalk_1.default.yellow(
|
|
185
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Subdomain hosting requires a subscription (€4.99/mo)`));
|
|
186
186
|
const { proceed } = await inquirer_1.default.prompt([{
|
|
187
187
|
type: 'confirm',
|
|
188
188
|
name: 'proceed',
|
|
@@ -232,7 +232,7 @@ class DeployCommand {
|
|
|
232
232
|
if (!response.ok || !data.success) {
|
|
233
233
|
if (data.requiresSubscription) {
|
|
234
234
|
spinner.stop();
|
|
235
|
-
console.log(chalk_1.default.yellow(
|
|
235
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Custom domain hosting requires a subscription (€9.99/mo)`));
|
|
236
236
|
const { proceed } = await inquirer_1.default.prompt([{
|
|
237
237
|
type: 'confirm',
|
|
238
238
|
name: 'proceed',
|
|
@@ -366,7 +366,7 @@ class DeployCommand {
|
|
|
366
366
|
console.log(chalk_1.default.cyan(`\n🌐 Your Deployments (${data.domains.length})\n`));
|
|
367
367
|
for (const domain of data.domains) {
|
|
368
368
|
const statusIcon = domain.is_active ? '🟢' : '🔴';
|
|
369
|
-
const sslIcon = domain.ssl_status === 'active' ?
|
|
369
|
+
const sslIcon = domain.ssl_status === 'active' ? logger_js_1.CH.lock : logger_js_1.CH.warnEmoji;
|
|
370
370
|
const url = domain.domain_type === 'subdomain'
|
|
371
371
|
? `${domain.subdomain}.vigthoria.io`
|
|
372
372
|
: domain.domain_type === 'custom'
|
|
@@ -458,7 +458,7 @@ class DeployCommand {
|
|
|
458
458
|
default: false
|
|
459
459
|
}]);
|
|
460
460
|
if (!confirm) {
|
|
461
|
-
console.log(chalk_1.default.yellow(
|
|
461
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Removal cancelled.\n`));
|
|
462
462
|
return;
|
|
463
463
|
}
|
|
464
464
|
const spinner = (0, logger_js_1.createSpinner)(`Removing ${domain}...`).start();
|
|
@@ -43,7 +43,7 @@ class GenerateCommand {
|
|
|
43
43
|
if (!options.language) {
|
|
44
44
|
options.language = this.detectLanguageFromDescription(description);
|
|
45
45
|
}
|
|
46
|
-
this.logger.section(proMode ?
|
|
46
|
+
this.logger.section(proMode ? `${logger_js_1.CH.rocket} Senior Developer Mode` : 'Code Generation');
|
|
47
47
|
console.log(chalk_1.default.gray(`Language: ${options.language}`));
|
|
48
48
|
console.log(chalk_1.default.gray(`Description: ${description}`));
|
|
49
49
|
if (proMode) {
|
package/dist/commands/repo.js
CHANGED
|
@@ -191,7 +191,10 @@ class RepoCommand {
|
|
|
191
191
|
formatRepoError(error) {
|
|
192
192
|
const message = error instanceof Error ? error.message : 'Unknown error';
|
|
193
193
|
if (/invalid or expired session/i.test(message)) {
|
|
194
|
-
return
|
|
194
|
+
return 'Repo memory service is not deployed or not reachable. Check `vigthoria status` for details.';
|
|
195
|
+
}
|
|
196
|
+
if (/ECONNREFUSED|ENOTFOUND|ETIMEDOUT|socket hang up/i.test(message)) {
|
|
197
|
+
return 'Repo memory service is not reachable. Check `vigthoria status` for details.';
|
|
195
198
|
}
|
|
196
199
|
return message;
|
|
197
200
|
}
|
|
@@ -360,7 +363,7 @@ class RepoCommand {
|
|
|
360
363
|
}
|
|
361
364
|
]);
|
|
362
365
|
if (!answers.confirm) {
|
|
363
|
-
console.log(chalk_1.default.yellow(
|
|
366
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Push cancelled.\n`));
|
|
364
367
|
return;
|
|
365
368
|
}
|
|
366
369
|
const uploadSpinner = (0, logger_js_1.createSpinner)('Preparing project files...').start();
|
|
@@ -434,7 +437,7 @@ class RepoCommand {
|
|
|
434
437
|
default: false
|
|
435
438
|
}]);
|
|
436
439
|
if (!overwrite) {
|
|
437
|
-
console.log(chalk_1.default.yellow(
|
|
440
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Pull cancelled.\n`));
|
|
438
441
|
return;
|
|
439
442
|
}
|
|
440
443
|
}
|
|
@@ -523,7 +526,7 @@ class RepoCommand {
|
|
|
523
526
|
// Display owned projects grouped by visibility
|
|
524
527
|
if (ownedProjects.length > 0) {
|
|
525
528
|
console.log(chalk_1.default.bold.cyan(' 📁 YOUR PROJECTS'));
|
|
526
|
-
console.log(chalk_1.default.gray(' ' +
|
|
529
|
+
console.log(chalk_1.default.gray(' ' + logger_js_1.CH.hLine.repeat(50)));
|
|
527
530
|
// Group by visibility
|
|
528
531
|
const grouped = ownedProjects.reduce((acc, project) => {
|
|
529
532
|
const vis = project.visibility || 'private';
|
|
@@ -548,8 +551,8 @@ class RepoCommand {
|
|
|
548
551
|
const techStack = project.tech_stack || project.framework || 'Unknown';
|
|
549
552
|
const updatedAt = project.updated_at || project.updatedAt || project.created_at || project.createdAt;
|
|
550
553
|
const syncStatus = (project.last_synced_at || project.lastSyncedAt)
|
|
551
|
-
? chalk_1.default.green(
|
|
552
|
-
: chalk_1.default.yellow('
|
|
554
|
+
? chalk_1.default.green(`${logger_js_1.CH.success} synced`)
|
|
555
|
+
: chalk_1.default.yellow('- not synced');
|
|
553
556
|
console.log(chalk_1.default.white(` ${projectName.padEnd(30)} ${syncStatus}`));
|
|
554
557
|
if (project.description) {
|
|
555
558
|
console.log(chalk_1.default.gray(` ${project.description.substring(0, 50)}${project.description.length > 50 ? '...' : ''}`));
|
|
@@ -563,7 +566,7 @@ class RepoCommand {
|
|
|
563
566
|
// Display shared projects
|
|
564
567
|
if (sharedProjects.length > 0) {
|
|
565
568
|
console.log(chalk_1.default.bold.magenta('\n 🤝 SHARED WITH YOU'));
|
|
566
|
-
console.log(chalk_1.default.gray(' ' +
|
|
569
|
+
console.log(chalk_1.default.gray(' ' + logger_js_1.CH.hLine.repeat(50)));
|
|
567
570
|
sharedProjects.forEach((project) => {
|
|
568
571
|
const projectName = project.project_name || project.name || 'Unnamed';
|
|
569
572
|
const techStack = project.tech_stack || project.framework || 'Unknown';
|
|
@@ -578,7 +581,7 @@ class RepoCommand {
|
|
|
578
581
|
console.log();
|
|
579
582
|
});
|
|
580
583
|
}
|
|
581
|
-
console.log(chalk_1.default.gray(
|
|
584
|
+
console.log(chalk_1.default.gray(logger_js_1.CH.hLine.repeat(60)));
|
|
582
585
|
console.log(chalk_1.default.cyan('\nCommands:'));
|
|
583
586
|
console.log(chalk_1.default.gray(' vigthoria repo pull <name> - Download a project'));
|
|
584
587
|
console.log(chalk_1.default.gray(' vigthoria repo push - Upload current directory'));
|
|
@@ -617,7 +620,7 @@ class RepoCommand {
|
|
|
617
620
|
synced: '✅',
|
|
618
621
|
ahead: '⬆️',
|
|
619
622
|
behind: '⬇️',
|
|
620
|
-
diverged:
|
|
623
|
+
diverged: logger_js_1.CH.warnEmoji
|
|
621
624
|
};
|
|
622
625
|
console.log(chalk_1.default.cyan(`\n📦 Project: ${chalk_1.default.white(data.project.project_name)}\n`));
|
|
623
626
|
console.log(chalk_1.default.gray(` Path: ${projectPath}`));
|
|
@@ -688,7 +691,7 @@ class RepoCommand {
|
|
|
688
691
|
default: false
|
|
689
692
|
}]);
|
|
690
693
|
if (!confirm) {
|
|
691
|
-
console.log(chalk_1.default.yellow(
|
|
694
|
+
console.log(chalk_1.default.yellow(`\n${logger_js_1.CH.warnEmoji} Delete cancelled.\n`));
|
|
692
695
|
return;
|
|
693
696
|
}
|
|
694
697
|
const spinner = (0, logger_js_1.createSpinner)('Deleting project...').start();
|
package/dist/commands/review.js
CHANGED
|
@@ -134,13 +134,13 @@ class ReviewCommand {
|
|
|
134
134
|
getSeverityIcon(severity) {
|
|
135
135
|
switch (severity.toLowerCase()) {
|
|
136
136
|
case 'error':
|
|
137
|
-
return
|
|
137
|
+
return logger_js_1.CH.error;
|
|
138
138
|
case 'warning':
|
|
139
|
-
return
|
|
139
|
+
return logger_js_1.CH.warn;
|
|
140
140
|
case 'info':
|
|
141
|
-
return
|
|
141
|
+
return logger_js_1.CH.info;
|
|
142
142
|
default:
|
|
143
|
-
return
|
|
143
|
+
return logger_js_1.CH.bullet;
|
|
144
144
|
}
|
|
145
145
|
}
|
|
146
146
|
getSeverityColor(severity) {
|
|
@@ -56,7 +56,10 @@ class WorkflowCommand {
|
|
|
56
56
|
});
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
|
-
const
|
|
59
|
+
const raw = error.message || 'Unknown error';
|
|
60
|
+
const msg = /not available|not reachable|not deployed/i.test(raw)
|
|
61
|
+
? raw
|
|
62
|
+
: `Workflow service is not reachable: ${raw}`;
|
|
60
63
|
if (options.json) {
|
|
61
64
|
this.printJson({ success: false, error: msg, templates: [] });
|
|
62
65
|
}
|
|
@@ -88,7 +91,10 @@ class WorkflowCommand {
|
|
|
88
91
|
workflows = await this.api.listVigFlowWorkflows();
|
|
89
92
|
}
|
|
90
93
|
catch (error) {
|
|
91
|
-
const
|
|
94
|
+
const raw = error.message || 'Unknown error';
|
|
95
|
+
const msg = /not available|not reachable|not deployed/i.test(raw)
|
|
96
|
+
? raw
|
|
97
|
+
: `Workflow service is not reachable: ${raw}`;
|
|
92
98
|
if (options.json) {
|
|
93
99
|
this.printJson({ success: false, error: msg, workflows: [] });
|
|
94
100
|
}
|
package/dist/index.js
CHANGED
|
@@ -133,7 +133,7 @@ async function checkForUpdatesQuietly() {
|
|
|
133
133
|
if (npmVersion && compareVersions(npmVersion, VERSION) > 0) {
|
|
134
134
|
// Check if this is a security update (1.4.0+)
|
|
135
135
|
if (compareVersions(npmVersion, '1.4.0') >= 0 && compareVersions(VERSION, '1.4.0') < 0) {
|
|
136
|
-
console.log(chalk_1.default.red.bold(
|
|
136
|
+
console.log(chalk_1.default.red.bold(`\n${logger_js_1.CH.warnEmoji} SECURITY UPDATE AVAILABLE`));
|
|
137
137
|
console.log(chalk_1.default.red(` Version ${VERSION} has security vulnerabilities.`));
|
|
138
138
|
console.log(chalk_1.default.yellow(` Please update to ${npmVersion} immediately:`));
|
|
139
139
|
console.log(chalk_1.default.white.bold(' npm install -g vigthoria-cli@latest\n'));
|
|
@@ -173,12 +173,12 @@ async function main() {
|
|
|
173
173
|
const titlePad = Math.floor((boxWidth - 4 - titleText.length) / 2);
|
|
174
174
|
const versionPad = Math.floor((boxWidth - 4 - versionText.length) / 2);
|
|
175
175
|
if (process.env.VIGTHORIA_NO_BANNER !== '1' && !jsonOutputRequested) {
|
|
176
|
-
console.log(chalk_1.default.cyan(
|
|
177
|
-
console.log(chalk_1.default.cyan(
|
|
178
|
-
console.log(chalk_1.default.cyan(
|
|
179
|
-
console.log(chalk_1.default.cyan(
|
|
180
|
-
console.log(chalk_1.default.cyan(
|
|
181
|
-
console.log(chalk_1.default.cyan(
|
|
176
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dTl + logger_js_1.CH.dH.repeat(boxWidth) + logger_js_1.CH.dTr));
|
|
177
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dV + ' '.repeat(boxWidth) + logger_js_1.CH.dV));
|
|
178
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dV) + ' '.repeat(titlePad) + chalk_1.default.bold.white('VIGTHORIA CLI') + chalk_1.default.cyan(' - AI-Powered Coding Assistant') + ' '.repeat(boxWidth - titlePad - titleText.length) + chalk_1.default.cyan(logger_js_1.CH.dV));
|
|
179
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dV) + ' '.repeat(versionPad) + chalk_1.default.gray(versionText) + ' '.repeat(boxWidth - versionPad - versionText.length) + chalk_1.default.cyan(logger_js_1.CH.dV));
|
|
180
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dV + ' '.repeat(boxWidth) + logger_js_1.CH.dV));
|
|
181
|
+
console.log(chalk_1.default.cyan(logger_js_1.CH.dBl + logger_js_1.CH.dH.repeat(boxWidth) + logger_js_1.CH.dBr));
|
|
182
182
|
console.log();
|
|
183
183
|
}
|
|
184
184
|
// Check for updates in background (don't wait)
|
package/dist/utils/api.js
CHANGED
|
@@ -352,36 +352,31 @@ class APIClient {
|
|
|
352
352
|
if (!token) {
|
|
353
353
|
return { valid: false, error: 'No auth token configured. Run: vigthoria login' };
|
|
354
354
|
}
|
|
355
|
-
//
|
|
356
|
-
//
|
|
357
|
-
//
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
const mrAxErr = mrError;
|
|
365
|
-
if (mrAxErr.response?.status === 401 || mrAxErr.response?.status === 403) {
|
|
366
|
-
return { valid: false, error: 'Auth token expired or invalid. Run: vigthoria login' };
|
|
367
|
-
}
|
|
368
|
-
// Model Router unreachable — try Coder profile as fallback
|
|
369
|
-
try {
|
|
370
|
-
await this.client.get('/api/user/profile', { timeout: 10000 });
|
|
355
|
+
// Probe both endpoints in parallel. If EITHER succeeds the token is
|
|
356
|
+
// valid. Only if both return 401/403 is the token truly invalid.
|
|
357
|
+
// If both are unreachable assume the token is fine (offline scenario).
|
|
358
|
+
const results = await Promise.allSettled([
|
|
359
|
+
this.modelRouterClient.get('/v1/models', { timeout: 5000 }),
|
|
360
|
+
this.client.get('/api/user/profile', { timeout: 5000 }),
|
|
361
|
+
]);
|
|
362
|
+
for (const r of results) {
|
|
363
|
+
if (r.status === 'fulfilled')
|
|
371
364
|
return { valid: true };
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
365
|
+
}
|
|
366
|
+
// Both failed — check why
|
|
367
|
+
for (const r of results) {
|
|
368
|
+
if (r.status === 'rejected') {
|
|
369
|
+
const err = r.reason;
|
|
370
|
+
if (err.response?.status === 401 || err.response?.status === 403) {
|
|
375
371
|
return { valid: false, error: 'Auth token expired or invalid. Run: vigthoria login' };
|
|
376
372
|
}
|
|
377
|
-
|
|
378
|
-
if (axErr.response?.status === 401 || axErr.response?.status === 403) {
|
|
373
|
+
if (err instanceof CLIError && err.category === 'auth') {
|
|
379
374
|
return { valid: false, error: 'Auth token expired or invalid. Run: vigthoria login' };
|
|
380
375
|
}
|
|
381
|
-
// Both unreachable — don't assume token is bad
|
|
382
|
-
return { valid: true };
|
|
383
376
|
}
|
|
384
377
|
}
|
|
378
|
+
// Both unreachable — don't assume token is bad
|
|
379
|
+
return { valid: true };
|
|
385
380
|
}
|
|
386
381
|
getV3AgentBaseUrls(preferLocal = false) {
|
|
387
382
|
const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
|
|
@@ -922,7 +917,8 @@ class APIClient {
|
|
|
922
917
|
this.logger.debug(`VigFlow ${operation} via ${baseUrl} failed:`, lastError.message);
|
|
923
918
|
}
|
|
924
919
|
}
|
|
925
|
-
|
|
920
|
+
// Throw a clean message instead of the raw ECONNREFUSED from the last URL tried
|
|
921
|
+
throw new Error(`No VigFlow backend available for ${operation}. The workflow service is not deployed or not reachable.`);
|
|
926
922
|
}
|
|
927
923
|
/**
|
|
928
924
|
* Build the correct sub-path for VigFlow endpoints.
|
|
@@ -3631,7 +3627,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3631
3627
|
}
|
|
3632
3628
|
}
|
|
3633
3629
|
async explainCode(code, language) {
|
|
3634
|
-
const sysPrompt =
|
|
3630
|
+
const sysPrompt = [
|
|
3631
|
+
`You are a code explainer. Explain the following ${language} code clearly and concisely.`,
|
|
3632
|
+
'Focus on what it does, how it works, and any notable patterns or potential issues.',
|
|
3633
|
+
'Format your response as clean Markdown:',
|
|
3634
|
+
'- Use ## headers for major sections.',
|
|
3635
|
+
'- Use numbered lists for sequential steps.',
|
|
3636
|
+
'- Use bullet points for properties or details.',
|
|
3637
|
+
'- Wrap code references in backticks.',
|
|
3638
|
+
'- Keep paragraphs short (2-3 sentences max).',
|
|
3639
|
+
'- Do NOT use raw HTML or excessive blank lines.',
|
|
3640
|
+
].join('\n');
|
|
3635
3641
|
return this.chatComplete(sysPrompt, code);
|
|
3636
3642
|
}
|
|
3637
3643
|
async reviewCode(code, language) {
|
|
@@ -4244,7 +4250,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4244
4250
|
}
|
|
4245
4251
|
async getCoderHealth() {
|
|
4246
4252
|
try {
|
|
4247
|
-
const response = await this.client.get('/api/health', { timeout:
|
|
4253
|
+
const response = await this.client.get('/api/health', { timeout: 5000 });
|
|
4248
4254
|
const ok = response.data?.status === 'ok' || response.data?.healthy === true;
|
|
4249
4255
|
return {
|
|
4250
4256
|
name: 'Coder API',
|
|
@@ -4266,8 +4272,8 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4266
4272
|
const modelsApiUrl = this.config.get('modelsApiUrl');
|
|
4267
4273
|
try {
|
|
4268
4274
|
const [healthResponse, modelsResponse] = await Promise.all([
|
|
4269
|
-
this.modelRouterClient.get('/health', { timeout:
|
|
4270
|
-
this.modelRouterClient.get('/v1/models', { timeout:
|
|
4275
|
+
this.modelRouterClient.get('/health', { timeout: 5000 }),
|
|
4276
|
+
this.modelRouterClient.get('/v1/models', { timeout: 5000 }),
|
|
4271
4277
|
]);
|
|
4272
4278
|
const healthOk = healthResponse.data?.status === 'healthy'
|
|
4273
4279
|
|| healthResponse.data?.status === 'ok'
|
|
@@ -4298,7 +4304,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4298
4304
|
return null;
|
|
4299
4305
|
}
|
|
4300
4306
|
try {
|
|
4301
|
-
const response = await this.selfHostedModelRouterClient.get('/health', { timeout:
|
|
4307
|
+
const response = await this.selfHostedModelRouterClient.get('/health', { timeout: 5000 });
|
|
4302
4308
|
const ok = response.data?.status === 'healthy'
|
|
4303
4309
|
|| response.data?.status === 'ok'
|
|
4304
4310
|
|| response.data?.healthy === true;
|
|
@@ -4331,7 +4337,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4331
4337
|
for (const endpoint of candidates) {
|
|
4332
4338
|
try {
|
|
4333
4339
|
const controller = new AbortController();
|
|
4334
|
-
const timer = setTimeout(() => controller.abort(),
|
|
4340
|
+
const timer = setTimeout(() => controller.abort(), 3000);
|
|
4335
4341
|
const response = await fetch(endpoint, {
|
|
4336
4342
|
method: 'GET',
|
|
4337
4343
|
headers,
|
|
@@ -4379,7 +4385,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4379
4385
|
const runUrl = this.getV3AgentRunUrl(baseUrl);
|
|
4380
4386
|
try {
|
|
4381
4387
|
const controller = new AbortController();
|
|
4382
|
-
const timer = setTimeout(() => controller.abort(),
|
|
4388
|
+
const timer = setTimeout(() => controller.abort(), 2000);
|
|
4383
4389
|
const probe = await fetch(runUrl, { method: 'OPTIONS', headers, signal: controller.signal });
|
|
4384
4390
|
clearTimeout(timer);
|
|
4385
4391
|
if (probe.ok || probe.status === 204 || probe.status === 405) {
|
|
@@ -4536,11 +4542,18 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
4536
4542
|
});
|
|
4537
4543
|
}
|
|
4538
4544
|
async getCapabilityTruthStatus(context = {}) {
|
|
4545
|
+
// Wrap each probe with its own 6 s timeout so they always resolve
|
|
4546
|
+
// before the outer 8 s race in auth.ts, producing real error messages
|
|
4547
|
+
// (ECONNREFUSED, 404, etc.) instead of the generic "Timed out (8s)".
|
|
4548
|
+
const withTimeout = (p, name) => Promise.race([
|
|
4549
|
+
p,
|
|
4550
|
+
new Promise(resolve => setTimeout(() => resolve({ name, endpoint: '', ok: false, error: 'Service not reachable (6 s timeout)' }), 6000)),
|
|
4551
|
+
]);
|
|
4539
4552
|
const [v3Agent, hyperLoop, repoMemory, devtoolsBridge] = await Promise.all([
|
|
4540
|
-
this.getV3AgentHealth(),
|
|
4541
|
-
this.getHyperLoopHealth(),
|
|
4542
|
-
this.getRepoMemoryHealth(context),
|
|
4543
|
-
this.getDevtoolsBridgeStatus(),
|
|
4553
|
+
withTimeout(this.getV3AgentHealth(), 'V3 Agent'),
|
|
4554
|
+
withTimeout(this.getHyperLoopHealth(), 'Hyper Loop'),
|
|
4555
|
+
withTimeout(this.getRepoMemoryHealth(context), 'Repo Memory'),
|
|
4556
|
+
withTimeout(this.getDevtoolsBridgeStatus(), 'DevTools Bridge'),
|
|
4544
4557
|
]);
|
|
4545
4558
|
return {
|
|
4546
4559
|
overallOk: v3Agent.ok && hyperLoop.ok && repoMemory.ok,
|
|
@@ -54,6 +54,7 @@ exports.getBridgeClient = getBridgeClient;
|
|
|
54
54
|
const ws_1 = __importDefault(require("ws"));
|
|
55
55
|
const os = __importStar(require("os"));
|
|
56
56
|
const chalk_1 = __importDefault(require("chalk"));
|
|
57
|
+
const logger_js_1 = require("./logger.js");
|
|
57
58
|
// ── Singleton accessor ───────────────────────────────────────────────
|
|
58
59
|
let _instance = null;
|
|
59
60
|
/** Get the active bridge client (may be null if --bridge was not used). */
|
|
@@ -136,7 +137,7 @@ class BridgeClient {
|
|
|
136
137
|
this.stopHeartbeat();
|
|
137
138
|
this.scheduleReconnect();
|
|
138
139
|
if (process.env.DEBUG || process.env.VIGTHORIA_DEBUG) {
|
|
139
|
-
console.log(chalk_1.default.yellow(
|
|
140
|
+
console.log(chalk_1.default.yellow(`${logger_js_1.CH.warn} Bridge: connection failed, will retry in background.`));
|
|
140
141
|
}
|
|
141
142
|
resolve(); // resolve even on failure – must never block CLI
|
|
142
143
|
});
|
package/dist/utils/logger.d.ts
CHANGED
|
@@ -3,6 +3,36 @@
|
|
|
3
3
|
*/
|
|
4
4
|
import { type Options as OraOptions, type Ora } from 'ora';
|
|
5
5
|
export type { Ora };
|
|
6
|
+
export declare const CH: {
|
|
7
|
+
info: string;
|
|
8
|
+
warn: string;
|
|
9
|
+
error: string;
|
|
10
|
+
success: string;
|
|
11
|
+
ai: string;
|
|
12
|
+
user: string;
|
|
13
|
+
hLine: string;
|
|
14
|
+
hDouble: string;
|
|
15
|
+
vLine: string;
|
|
16
|
+
tl: string;
|
|
17
|
+
tr: string;
|
|
18
|
+
bl: string;
|
|
19
|
+
br: string;
|
|
20
|
+
teeR: string;
|
|
21
|
+
teeL: string;
|
|
22
|
+
cross: string;
|
|
23
|
+
bullet: string;
|
|
24
|
+
cloud: string;
|
|
25
|
+
home: string;
|
|
26
|
+
rocket: string;
|
|
27
|
+
lock: string;
|
|
28
|
+
warnEmoji: string;
|
|
29
|
+
dTl: string;
|
|
30
|
+
dTr: string;
|
|
31
|
+
dBl: string;
|
|
32
|
+
dBr: string;
|
|
33
|
+
dH: string;
|
|
34
|
+
dV: string;
|
|
35
|
+
};
|
|
6
36
|
/**
|
|
7
37
|
* Create an ora spinner that writes to stderr so it never
|
|
8
38
|
* pollutes stdout JSON output.
|
package/dist/utils/logger.js
CHANGED
|
@@ -6,10 +6,47 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
6
6
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
7
7
|
};
|
|
8
8
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
9
|
-
exports.Logger = void 0;
|
|
9
|
+
exports.Logger = exports.CH = void 0;
|
|
10
10
|
exports.createSpinner = createSpinner;
|
|
11
11
|
const chalk_1 = __importDefault(require("chalk"));
|
|
12
12
|
const ora_1 = __importDefault(require("ora"));
|
|
13
|
+
/**
|
|
14
|
+
* Platform-aware character map. Windows cmd.exe / PowerShell with legacy
|
|
15
|
+
* code pages (437/850) cannot render Unicode box-drawing or emoji, so we
|
|
16
|
+
* fall back to ASCII equivalents.
|
|
17
|
+
*/
|
|
18
|
+
const isWin = process.platform === 'win32';
|
|
19
|
+
exports.CH = {
|
|
20
|
+
info: isWin ? 'i' : 'ℹ',
|
|
21
|
+
warn: isWin ? '!' : '⚠',
|
|
22
|
+
error: isWin ? 'x' : '✗',
|
|
23
|
+
success: isWin ? '+' : '✓',
|
|
24
|
+
ai: isWin ? '>' : '🤖',
|
|
25
|
+
user: isWin ? '$' : '👤',
|
|
26
|
+
hLine: isWin ? '-' : '─',
|
|
27
|
+
hDouble: isWin ? '=' : '═',
|
|
28
|
+
vLine: isWin ? '|' : '│',
|
|
29
|
+
tl: isWin ? '+' : '┌',
|
|
30
|
+
tr: isWin ? '+' : '┐',
|
|
31
|
+
bl: isWin ? '+' : '└',
|
|
32
|
+
br: isWin ? '+' : '┘',
|
|
33
|
+
teeR: isWin ? '+' : '├',
|
|
34
|
+
teeL: isWin ? '+' : '┤',
|
|
35
|
+
cross: isWin ? '+' : '┼',
|
|
36
|
+
bullet: isWin ? '*' : '•',
|
|
37
|
+
cloud: isWin ? '[cloud]' : '☁️ ',
|
|
38
|
+
home: isWin ? '[local]' : '🏠 ',
|
|
39
|
+
rocket: isWin ? '>>' : '🚀',
|
|
40
|
+
lock: isWin ? '[lock]' : '🔒',
|
|
41
|
+
warnEmoji: isWin ? '[!]' : '⚠️',
|
|
42
|
+
// Double-line box drawing (used for main banner)
|
|
43
|
+
dTl: isWin ? '+' : '╔',
|
|
44
|
+
dTr: isWin ? '+' : '╗',
|
|
45
|
+
dBl: isWin ? '+' : '╚',
|
|
46
|
+
dBr: isWin ? '+' : '╝',
|
|
47
|
+
dH: isWin ? '=' : '═',
|
|
48
|
+
dV: isWin ? '|' : '║',
|
|
49
|
+
};
|
|
13
50
|
/**
|
|
14
51
|
* Create an ora spinner that writes to stderr so it never
|
|
15
52
|
* pollutes stdout JSON output.
|
|
@@ -42,33 +79,33 @@ class Logger {
|
|
|
42
79
|
}
|
|
43
80
|
}
|
|
44
81
|
info(...args) {
|
|
45
|
-
console.log(chalk_1.default.blue(
|
|
82
|
+
console.log(chalk_1.default.blue(exports.CH.info), ...args);
|
|
46
83
|
}
|
|
47
84
|
warn(...args) {
|
|
48
|
-
console.log(chalk_1.default.yellow(
|
|
85
|
+
console.log(chalk_1.default.yellow(exports.CH.warn), ...args);
|
|
49
86
|
}
|
|
50
87
|
error(...args) {
|
|
51
88
|
// Write error messages to stdout (not stderr) to avoid triggering
|
|
52
89
|
// PowerShell NativeCommandError styling. The red ✗ prefix already
|
|
53
90
|
// signals an error visually; stderr redirection is unnecessary.
|
|
54
|
-
console.log(chalk_1.default.red(
|
|
91
|
+
console.log(chalk_1.default.red(exports.CH.error), ...args);
|
|
55
92
|
}
|
|
56
93
|
success(...args) {
|
|
57
|
-
console.log(chalk_1.default.green(
|
|
94
|
+
console.log(chalk_1.default.green(exports.CH.success), ...args);
|
|
58
95
|
}
|
|
59
96
|
// AI response formatting
|
|
60
97
|
ai(message) {
|
|
61
|
-
console.log(chalk_1.default.cyan(
|
|
98
|
+
console.log(chalk_1.default.cyan(exports.CH.ai), message);
|
|
62
99
|
}
|
|
63
100
|
// User input formatting
|
|
64
101
|
user(message) {
|
|
65
|
-
console.log(chalk_1.default.white(
|
|
102
|
+
console.log(chalk_1.default.white(exports.CH.user), message);
|
|
66
103
|
}
|
|
67
104
|
// Code block
|
|
68
105
|
code(code, language) {
|
|
69
|
-
console.log(chalk_1.default.gray(
|
|
106
|
+
console.log(chalk_1.default.gray(exports.CH.hLine.repeat(60)));
|
|
70
107
|
console.log(chalk_1.default.yellow(code));
|
|
71
|
-
console.log(chalk_1.default.gray(
|
|
108
|
+
console.log(chalk_1.default.gray(exports.CH.hLine.repeat(60)));
|
|
72
109
|
}
|
|
73
110
|
// Diff output
|
|
74
111
|
diff(added, removed) {
|
|
@@ -78,7 +115,7 @@ class Logger {
|
|
|
78
115
|
// Section header
|
|
79
116
|
section(title) {
|
|
80
117
|
console.log();
|
|
81
|
-
console.log(chalk_1.default.bold.cyan(
|
|
118
|
+
console.log(chalk_1.default.bold.cyan(`${exports.CH.hDouble.repeat(3)} ${title} ${exports.CH.hDouble.repeat(3)}`));
|
|
82
119
|
console.log();
|
|
83
120
|
}
|
|
84
121
|
// Progress
|
|
@@ -96,18 +133,18 @@ class Logger {
|
|
|
96
133
|
const stripAnsi = (str) => str.replace(/\x1B\[[0-9;]*[a-zA-Z]/g, '');
|
|
97
134
|
const maxLen = Math.max(...lines.map(l => stripAnsi(l).length), title?.length || 0);
|
|
98
135
|
const width = maxLen + 4;
|
|
99
|
-
console.log(chalk_1.default.cyan(
|
|
136
|
+
console.log(chalk_1.default.cyan(exports.CH.tl + exports.CH.hLine.repeat(width - 2) + exports.CH.tr));
|
|
100
137
|
if (title) {
|
|
101
|
-
console.log(chalk_1.default.cyan('
|
|
102
|
-
console.log(chalk_1.default.cyan(
|
|
138
|
+
console.log(chalk_1.default.cyan(exports.CH.vLine + ' ') + chalk_1.default.bold.white(title.padEnd(width - 4)) + chalk_1.default.cyan(' ' + exports.CH.vLine));
|
|
139
|
+
console.log(chalk_1.default.cyan(exports.CH.teeR + exports.CH.hLine.repeat(width - 2) + exports.CH.teeL));
|
|
103
140
|
}
|
|
104
141
|
lines.forEach(line => {
|
|
105
142
|
// Calculate visible length and pad accordingly
|
|
106
143
|
const visibleLen = stripAnsi(line).length;
|
|
107
144
|
const padding = ' '.repeat(Math.max(0, width - 4 - visibleLen));
|
|
108
|
-
console.log(chalk_1.default.cyan('
|
|
145
|
+
console.log(chalk_1.default.cyan(exports.CH.vLine + ' ') + line + padding + chalk_1.default.cyan(' ' + exports.CH.vLine));
|
|
109
146
|
});
|
|
110
|
-
console.log(chalk_1.default.cyan(
|
|
147
|
+
console.log(chalk_1.default.cyan(exports.CH.bl + exports.CH.hLine.repeat(width - 2) + exports.CH.br));
|
|
111
148
|
}
|
|
112
149
|
// Table output
|
|
113
150
|
table(headers, rows) {
|
|
@@ -116,18 +153,18 @@ class Logger {
|
|
|
116
153
|
return Math.max(h.length, maxData);
|
|
117
154
|
});
|
|
118
155
|
// Header
|
|
119
|
-
console.log(chalk_1.default.gray('
|
|
120
|
-
headers.map((h, i) => chalk_1.default.bold(h.padEnd(colWidths[i]))).join(chalk_1.default.gray('
|
|
121
|
-
chalk_1.default.gray('
|
|
156
|
+
console.log(chalk_1.default.gray(exports.CH.vLine + ' ') +
|
|
157
|
+
headers.map((h, i) => chalk_1.default.bold(h.padEnd(colWidths[i]))).join(chalk_1.default.gray(' ' + exports.CH.vLine + ' ')) +
|
|
158
|
+
chalk_1.default.gray(' ' + exports.CH.vLine));
|
|
122
159
|
// Separator
|
|
123
|
-
console.log(chalk_1.default.gray(
|
|
124
|
-
colWidths.map(w =>
|
|
125
|
-
chalk_1.default.gray(
|
|
160
|
+
console.log(chalk_1.default.gray(exports.CH.teeR + exports.CH.hLine) +
|
|
161
|
+
colWidths.map(w => exports.CH.hLine.repeat(w)).join(chalk_1.default.gray(exports.CH.hLine + exports.CH.cross + exports.CH.hLine)) +
|
|
162
|
+
chalk_1.default.gray(exports.CH.hLine + exports.CH.teeL));
|
|
126
163
|
// Rows
|
|
127
164
|
rows.forEach(row => {
|
|
128
|
-
console.log(chalk_1.default.gray('
|
|
129
|
-
row.map((cell, i) => (cell || '').padEnd(colWidths[i])).join(chalk_1.default.gray('
|
|
130
|
-
chalk_1.default.gray('
|
|
165
|
+
console.log(chalk_1.default.gray(exports.CH.vLine + ' ') +
|
|
166
|
+
row.map((cell, i) => (cell || '').padEnd(colWidths[i])).join(chalk_1.default.gray(' ' + exports.CH.vLine + ' ')) +
|
|
167
|
+
chalk_1.default.gray(' ' + exports.CH.vLine));
|
|
131
168
|
});
|
|
132
169
|
}
|
|
133
170
|
}
|
package/dist/utils/tools.js
CHANGED
|
@@ -56,6 +56,7 @@ const fs = __importStar(require("fs"));
|
|
|
56
56
|
const path = __importStar(require("path"));
|
|
57
57
|
const child_process_1 = require("child_process");
|
|
58
58
|
const chalk_1 = __importDefault(require("chalk"));
|
|
59
|
+
const logger_js_1 = require("./logger.js");
|
|
59
60
|
const TOOL_ARG_ALIASES = {
|
|
60
61
|
read_file: {
|
|
61
62
|
path: ['file', 'filePath', 'filepath', 'target', 'targetPath'],
|
|
@@ -172,7 +173,7 @@ class AgenticTools {
|
|
|
172
173
|
fs.unlinkSync(lastOp.filePath);
|
|
173
174
|
return {
|
|
174
175
|
success: true,
|
|
175
|
-
output:
|
|
176
|
+
output: `${logger_js_1.CH.success} Undone: ${lastOp.description}\n File deleted: ${lastOp.filePath}`,
|
|
176
177
|
metadata: { remainingUndos: this.undoStack.length },
|
|
177
178
|
};
|
|
178
179
|
}
|
|
@@ -182,7 +183,7 @@ class AgenticTools {
|
|
|
182
183
|
fs.writeFileSync(lastOp.filePath, lastOp.originalContent, 'utf-8');
|
|
183
184
|
return {
|
|
184
185
|
success: true,
|
|
185
|
-
output:
|
|
186
|
+
output: `${logger_js_1.CH.success} Undone: ${lastOp.description}\n File restored: ${lastOp.filePath}`,
|
|
186
187
|
metadata: { remainingUndos: this.undoStack.length },
|
|
187
188
|
};
|
|
188
189
|
}
|
|
@@ -556,36 +557,36 @@ class AgenticTools {
|
|
|
556
557
|
const riskColor = riskColors[tool.riskLevel];
|
|
557
558
|
const riskIcon = riskIcons[tool.riskLevel];
|
|
558
559
|
let msg = `\n${riskIcon} ${riskColor(`${tool.riskLevel.toUpperCase()} RISK`)} - AI wants to use ${chalk_1.default.cyan.bold(call.tool)}\n`;
|
|
559
|
-
msg += chalk_1.default.gray(
|
|
560
|
+
msg += chalk_1.default.gray(logger_js_1.CH.hLine.repeat(50)) + '\n';
|
|
560
561
|
// Tool-specific details
|
|
561
562
|
if (call.tool === 'bash') {
|
|
562
|
-
msg += `${chalk_1.default.gray(
|
|
563
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Command:')} ${chalk_1.default.yellow(call.args.command)}\n`;
|
|
563
564
|
if (call.args.cwd) {
|
|
564
|
-
msg += `${chalk_1.default.gray(
|
|
565
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Directory:')} ${call.args.cwd}\n`;
|
|
565
566
|
}
|
|
566
|
-
msg += `${chalk_1.default.gray(
|
|
567
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Timeout:')} ${call.args.timeout || '30'}s\n`;
|
|
567
568
|
}
|
|
568
569
|
else if (call.tool === 'write_file') {
|
|
569
|
-
msg += `${chalk_1.default.gray(
|
|
570
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('File:')} ${chalk_1.default.cyan(call.args.path)}\n`;
|
|
570
571
|
const preview = call.args.content.substring(0, 100);
|
|
571
|
-
msg += `${chalk_1.default.gray(
|
|
572
|
-
msg += `${chalk_1.default.gray(
|
|
572
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Content preview:')} ${chalk_1.default.gray(preview)}${call.args.content.length > 100 ? '...' : ''}\n`;
|
|
573
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Size:')} ${call.args.content.length} bytes\n`;
|
|
573
574
|
}
|
|
574
575
|
else if (call.tool === 'edit_file') {
|
|
575
|
-
msg += `${chalk_1.default.gray(
|
|
576
|
-
msg += `${chalk_1.default.gray(
|
|
577
|
-
msg += `${chalk_1.default.gray(
|
|
576
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('File:')} ${chalk_1.default.cyan(call.args.path)}\n`;
|
|
577
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Replace:')} ${chalk_1.default.red(call.args.old_text.substring(0, 50))}${call.args.old_text.length > 50 ? '...' : ''}\n`;
|
|
578
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('With:')} ${chalk_1.default.green(call.args.new_text.substring(0, 50))}${call.args.new_text.length > 50 ? '...' : ''}\n`;
|
|
578
579
|
}
|
|
579
580
|
else if (call.tool === 'git') {
|
|
580
|
-
msg += `${chalk_1.default.gray(
|
|
581
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Command:')} git ${chalk_1.default.yellow(call.args.args)}\n`;
|
|
581
582
|
}
|
|
582
583
|
// Safety info
|
|
583
|
-
msg += chalk_1.default.gray(
|
|
584
|
+
msg += chalk_1.default.gray(logger_js_1.CH.hLine.repeat(50)) + '\n';
|
|
584
585
|
const canUndo = ['write_file', 'edit_file'].includes(call.tool);
|
|
585
|
-
msg += `${chalk_1.default.gray(
|
|
586
|
-
msg += `${chalk_1.default.gray(
|
|
586
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.teeR + logger_js_1.CH.hLine)} ${chalk_1.default.white('Undo:')} ${canUndo ? chalk_1.default.green(logger_js_1.CH.success + ' Available (use /undo)') : chalk_1.default.gray(logger_js_1.CH.error + ' Not available')}\n`;
|
|
587
|
+
msg += `${chalk_1.default.gray(logger_js_1.CH.bl + logger_js_1.CH.hLine)} ${chalk_1.default.white('Category:')} ${tool.category}\n`;
|
|
587
588
|
if (tool.dangerous) {
|
|
588
|
-
msg += `\n${chalk_1.default.red.bold('
|
|
589
|
+
msg += `\n${chalk_1.default.red.bold(logger_js_1.CH.warnEmoji + ' WARNING: This is a potentially dangerous action!')}\n`;
|
|
589
590
|
msg += chalk_1.default.red(' The AI is requesting to execute commands on your system.\n');
|
|
590
591
|
}
|
|
591
592
|
// Add batch approval hint
|