vigthoria-cli 1.9.9 → 1.9.19

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.
Files changed (52) hide show
  1. package/README.md +5 -5
  2. package/dist/commands/auth.js +48 -65
  3. package/dist/commands/bridge.js +12 -19
  4. package/dist/commands/cancel.js +15 -22
  5. package/dist/commands/chat.d.ts +11 -0
  6. package/dist/commands/chat.js +404 -248
  7. package/dist/commands/config.js +31 -71
  8. package/dist/commands/deploy.js +83 -123
  9. package/dist/commands/device.d.ts +35 -0
  10. package/dist/commands/device.js +239 -0
  11. package/dist/commands/edit.js +32 -39
  12. package/dist/commands/explain.js +18 -25
  13. package/dist/commands/fork.js +22 -27
  14. package/dist/commands/generate.js +37 -44
  15. package/dist/commands/history.js +20 -25
  16. package/dist/commands/hub.js +95 -102
  17. package/dist/commands/index.js +41 -46
  18. package/dist/commands/legion.d.ts +1 -0
  19. package/dist/commands/legion.js +162 -209
  20. package/dist/commands/preview.js +60 -98
  21. package/dist/commands/replay.js +27 -32
  22. package/dist/commands/repo.js +103 -141
  23. package/dist/commands/review.js +29 -36
  24. package/dist/commands/security.js +5 -12
  25. package/dist/commands/update.js +15 -49
  26. package/dist/commands/workflow.d.ts +8 -1
  27. package/dist/commands/workflow.js +53 -19
  28. package/dist/index.js +409 -234
  29. package/dist/utils/api.d.ts +5 -0
  30. package/dist/utils/api.js +398 -176
  31. package/dist/utils/bridge-client.js +11 -52
  32. package/dist/utils/cli-state.d.ts +54 -0
  33. package/dist/utils/cli-state.js +185 -0
  34. package/dist/utils/config.d.ts +5 -0
  35. package/dist/utils/config.js +35 -14
  36. package/dist/utils/context-ranker.js +15 -21
  37. package/dist/utils/files.js +5 -42
  38. package/dist/utils/logger.js +42 -50
  39. package/dist/utils/post-write-validator.js +22 -29
  40. package/dist/utils/project-memory.d.ts +56 -0
  41. package/dist/utils/project-memory.js +289 -0
  42. package/dist/utils/session.d.ts +29 -3
  43. package/dist/utils/session.js +137 -85
  44. package/dist/utils/task-display.js +13 -20
  45. package/dist/utils/tools.d.ts +19 -0
  46. package/dist/utils/tools.js +84 -87
  47. package/dist/utils/workspace-cache.js +18 -26
  48. package/dist/utils/workspace-stream.js +26 -64
  49. package/install.ps1 +14 -0
  50. package/package.json +5 -3
  51. package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
  52. package/scripts/release/validate-no-go-gates.sh +2 -2
@@ -0,0 +1,35 @@
1
+ import { Config } from '../utils/config.js';
2
+ import { Logger } from '../utils/logger.js';
3
+ type DeviceOptions = {
4
+ device?: string;
5
+ json?: boolean;
6
+ output?: string;
7
+ lines?: string;
8
+ follow?: boolean;
9
+ port?: string;
10
+ };
11
+ export declare class DeviceCommand {
12
+ private logger;
13
+ constructor(_config: Config, logger: Logger);
14
+ status(options?: DeviceOptions): Promise<void>;
15
+ list(options?: DeviceOptions): Promise<void>;
16
+ screenshot(options?: DeviceOptions): Promise<void>;
17
+ install(apkPath: string, options?: DeviceOptions): Promise<void>;
18
+ launch(packageName: string, options?: DeviceOptions & {
19
+ activity?: string;
20
+ }): Promise<void>;
21
+ logs(options?: DeviceOptions): Promise<void>;
22
+ tcpip(options?: DeviceOptions): Promise<void>;
23
+ connect(address: string, options?: DeviceOptions): Promise<void>;
24
+ disconnect(address?: string, options?: DeviceOptions): Promise<void>;
25
+ private getDevices;
26
+ private parseDeviceLine;
27
+ private resolveDeviceId;
28
+ private withDevice;
29
+ private runAdb;
30
+ private printResult;
31
+ private requireAdbPath;
32
+ private findAdbPath;
33
+ private timestamp;
34
+ }
35
+ export {};
@@ -0,0 +1,239 @@
1
+ import chalk from 'chalk';
2
+ import * as fs from 'fs';
3
+ import * as os from 'os';
4
+ import * as path from 'path';
5
+ import { execFile, spawn } from 'child_process';
6
+ import { promisify } from 'util';
7
+ import { CH } from '../utils/logger.js';
8
+ const execFileAsync = promisify(execFile);
9
+ export class DeviceCommand {
10
+ logger;
11
+ constructor(_config, logger) {
12
+ this.logger = logger;
13
+ }
14
+ async status(options = {}) {
15
+ const adbPath = this.findAdbPath();
16
+ const devices = adbPath ? await this.getDevices(adbPath) : [];
17
+ const payload = {
18
+ adbAvailable: Boolean(adbPath),
19
+ adbPath,
20
+ deviceCount: devices.filter((device) => device.state === 'device').length,
21
+ devices,
22
+ };
23
+ if (options.json) {
24
+ console.log(JSON.stringify(payload, null, 2));
25
+ return;
26
+ }
27
+ console.log();
28
+ console.log(chalk.bold.white(` ${CH.hLine.repeat(3)} Vigthoria Android Developer Bridge ${CH.hLine.repeat(20)}`));
29
+ console.log(chalk.gray(' ADB: ') + (adbPath ? chalk.green(adbPath) : chalk.yellow('not found')));
30
+ if (!adbPath) {
31
+ console.log(chalk.gray(' Install Android SDK Platform Tools, then make adb available on PATH.'));
32
+ console.log();
33
+ return;
34
+ }
35
+ if (devices.length === 0) {
36
+ console.log(chalk.yellow(' No Android devices visible.'));
37
+ console.log(chalk.gray(' Enable Developer Options + USB debugging, then run `vigthoria device list`.'));
38
+ console.log();
39
+ return;
40
+ }
41
+ for (const device of devices) {
42
+ const label = device.model || device.product || 'Android device';
43
+ const state = device.state === 'device' ? chalk.green(device.state) : chalk.yellow(device.state);
44
+ console.log(` ${chalk.white(device.id)} ${state} ${chalk.gray(label)}`);
45
+ }
46
+ console.log();
47
+ }
48
+ async list(options = {}) {
49
+ const adbPath = this.requireAdbPath();
50
+ const devices = await this.getDevices(adbPath);
51
+ if (options.json) {
52
+ console.log(JSON.stringify({ devices }, null, 2));
53
+ return;
54
+ }
55
+ if (devices.length === 0) {
56
+ console.log(chalk.yellow('No Android devices found.'));
57
+ return;
58
+ }
59
+ for (const device of devices) {
60
+ console.log(`${chalk.white(device.id)}\t${device.state}\t${device.model || device.product || ''}`.trim());
61
+ }
62
+ }
63
+ async screenshot(options = {}) {
64
+ const adbPath = this.requireAdbPath();
65
+ const deviceId = await this.resolveDeviceId(adbPath, options.device);
66
+ const output = path.resolve(options.output || `vigthoria-android-screenshot-${this.timestamp()}.png`);
67
+ const args = this.withDevice(deviceId, ['exec-out', 'screencap', '-p']);
68
+ const result = await execFileAsync(adbPath, args, { encoding: 'buffer', maxBuffer: 20 * 1024 * 1024 });
69
+ fs.writeFileSync(output, result.stdout);
70
+ console.log(chalk.green(`Saved screenshot: ${output}`));
71
+ }
72
+ async install(apkPath, options = {}) {
73
+ if (!apkPath)
74
+ throw new Error('APK path is required.');
75
+ const resolvedApk = path.resolve(apkPath);
76
+ if (!fs.existsSync(resolvedApk))
77
+ throw new Error(`APK not found: ${resolvedApk}`);
78
+ const adbPath = this.requireAdbPath();
79
+ const deviceId = await this.resolveDeviceId(adbPath, options.device);
80
+ const result = await this.runAdb(adbPath, this.withDevice(deviceId, ['install', '-r', resolvedApk]), 120000);
81
+ this.printResult(result, options.json);
82
+ }
83
+ async launch(packageName, options = {}) {
84
+ if (!packageName)
85
+ throw new Error('Android package name is required.');
86
+ const adbPath = this.requireAdbPath();
87
+ const deviceId = await this.resolveDeviceId(adbPath, options.device);
88
+ const args = options.activity
89
+ ? ['shell', 'am', 'start', '-n', `${packageName}/${options.activity}`]
90
+ : ['shell', 'monkey', '-p', packageName, '-c', 'android.intent.category.LAUNCHER', '1'];
91
+ const result = await this.runAdb(adbPath, this.withDevice(deviceId, args));
92
+ this.printResult(result, options.json);
93
+ }
94
+ async logs(options = {}) {
95
+ const adbPath = this.requireAdbPath();
96
+ const deviceId = await this.resolveDeviceId(adbPath, options.device);
97
+ const lines = String(options.lines || '250');
98
+ const args = this.withDevice(deviceId, options.follow ? ['logcat'] : ['logcat', '-d', '-t', lines]);
99
+ if (options.follow) {
100
+ await new Promise((resolve, reject) => {
101
+ const child = spawn(adbPath, args, { stdio: 'inherit' });
102
+ child.on('error', reject);
103
+ child.on('exit', (code) => {
104
+ if (code && code !== 0)
105
+ reject(new Error(`adb logcat exited with code ${code}`));
106
+ else
107
+ resolve();
108
+ });
109
+ });
110
+ return;
111
+ }
112
+ const result = await this.runAdb(adbPath, args, 30000, 8 * 1024 * 1024);
113
+ this.printResult(result, options.json);
114
+ }
115
+ async tcpip(options = {}) {
116
+ const adbPath = this.requireAdbPath();
117
+ const deviceId = await this.resolveDeviceId(adbPath, options.device);
118
+ const port = String(options.port || '5555');
119
+ const result = await this.runAdb(adbPath, this.withDevice(deviceId, ['tcpip', port]));
120
+ this.printResult(result, options.json);
121
+ }
122
+ async connect(address, options = {}) {
123
+ if (!address)
124
+ throw new Error('Device address is required, for example 192.168.1.30:5555.');
125
+ const adbPath = this.requireAdbPath();
126
+ const result = await this.runAdb(adbPath, ['connect', address]);
127
+ this.printResult(result, options.json);
128
+ }
129
+ async disconnect(address, options = {}) {
130
+ const adbPath = this.requireAdbPath();
131
+ const result = await this.runAdb(adbPath, address ? ['disconnect', address] : ['disconnect']);
132
+ this.printResult(result, options.json);
133
+ }
134
+ async getDevices(adbPath) {
135
+ const result = await this.runAdb(adbPath, ['devices', '-l']);
136
+ if (!result.success)
137
+ return [];
138
+ return result.stdout
139
+ .split(/\r?\n/)
140
+ .slice(1)
141
+ .map((line) => line.trim())
142
+ .filter(Boolean)
143
+ .map((line) => this.parseDeviceLine(line));
144
+ }
145
+ parseDeviceLine(line) {
146
+ const parts = line.split(/\s+/);
147
+ const id = parts[0] || '';
148
+ const state = parts[1] || 'unknown';
149
+ const metadata = new Map();
150
+ for (const token of parts.slice(2)) {
151
+ const separator = token.indexOf(':');
152
+ if (separator > 0)
153
+ metadata.set(token.slice(0, separator), token.slice(separator + 1));
154
+ }
155
+ return {
156
+ id,
157
+ state,
158
+ model: metadata.get('model'),
159
+ product: metadata.get('product'),
160
+ transport: metadata.get('transport_id'),
161
+ raw: line,
162
+ };
163
+ }
164
+ async resolveDeviceId(adbPath, requested) {
165
+ if (requested && requested.trim())
166
+ return requested.trim();
167
+ const devices = (await this.getDevices(adbPath)).filter((device) => device.state === 'device');
168
+ if (devices.length === 0)
169
+ throw new Error('No authorized Android device found. Run `vigthoria device status`.');
170
+ if (devices.length > 1)
171
+ throw new Error('Multiple Android devices found. Pass --device <id>.');
172
+ return devices[0].id;
173
+ }
174
+ withDevice(deviceId, args) {
175
+ return deviceId ? ['-s', deviceId, ...args] : args;
176
+ }
177
+ async runAdb(adbPath, args, timeout = 30000, maxBuffer = 1024 * 1024) {
178
+ try {
179
+ const result = await execFileAsync(adbPath, args, { timeout, maxBuffer });
180
+ return { success: true, stdout: String(result.stdout || '').trim(), stderr: String(result.stderr || '').trim() };
181
+ }
182
+ catch (error) {
183
+ const failure = error;
184
+ return {
185
+ success: false,
186
+ stdout: String(failure.stdout || '').trim(),
187
+ stderr: String(failure.stderr || failure.message || '').trim(),
188
+ };
189
+ }
190
+ }
191
+ printResult(result, json = false) {
192
+ if (json) {
193
+ console.log(JSON.stringify(result, null, 2));
194
+ return;
195
+ }
196
+ if (result.stdout)
197
+ console.log(result.stdout);
198
+ if (result.stderr)
199
+ console.error(result.success ? chalk.gray(result.stderr) : chalk.red(result.stderr));
200
+ if (!result.success)
201
+ process.exitCode = 1;
202
+ }
203
+ requireAdbPath() {
204
+ const adbPath = this.findAdbPath();
205
+ if (!adbPath) {
206
+ throw new Error('ADB not found. Install Android SDK Platform Tools and make adb available on PATH.');
207
+ }
208
+ return adbPath;
209
+ }
210
+ findAdbPath() {
211
+ const executable = process.platform === 'win32' ? 'adb.exe' : 'adb';
212
+ const candidates = [
213
+ process.env.VIGTHORIA_ADB_PATH,
214
+ process.env.ADB_PATH,
215
+ process.env.ANDROID_HOME ? path.join(process.env.ANDROID_HOME, 'platform-tools', executable) : undefined,
216
+ process.env.ANDROID_SDK_ROOT ? path.join(process.env.ANDROID_SDK_ROOT, 'platform-tools', executable) : undefined,
217
+ path.join(os.homedir(), 'Android', 'Sdk', 'platform-tools', executable),
218
+ process.platform === 'win32' ? path.join(process.env.LOCALAPPDATA || '', 'Android', 'Sdk', 'platform-tools', executable) : undefined,
219
+ process.platform === 'darwin' ? path.join(os.homedir(), 'Library', 'Android', 'sdk', 'platform-tools', executable) : undefined,
220
+ '/usr/bin/adb',
221
+ '/usr/local/bin/adb',
222
+ '/opt/android-sdk/platform-tools/adb',
223
+ ].filter((candidate) => Boolean(candidate));
224
+ for (const candidate of candidates) {
225
+ if (fs.existsSync(candidate))
226
+ return candidate;
227
+ }
228
+ const pathDirs = String(process.env.PATH || '').split(path.delimiter).filter(Boolean);
229
+ for (const pathDir of pathDirs) {
230
+ const candidate = path.join(pathDir, executable);
231
+ if (fs.existsSync(candidate))
232
+ return candidate;
233
+ }
234
+ return null;
235
+ }
236
+ timestamp() {
237
+ return new Date().toISOString().replace(/[:.]/g, '-');
238
+ }
239
+ }
@@ -1,18 +1,12 @@
1
- "use strict";
2
1
  /**
3
2
  * Edit Command - File editing with AI assistance
4
3
  */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.EditCommand = void 0;
10
- const chalk_1 = __importDefault(require("chalk"));
11
- const inquirer_1 = __importDefault(require("inquirer"));
12
- const logger_js_1 = require("../utils/logger.js");
13
- const api_js_1 = require("../utils/api.js");
14
- const files_js_1 = require("../utils/files.js");
15
- class EditCommand {
4
+ import chalk from 'chalk';
5
+ import inquirer from 'inquirer';
6
+ import { createSpinner } from '../utils/logger.js';
7
+ import { APIClient, CLIError, classifyError, formatCLIError } from '../utils/api.js';
8
+ import { FileUtils } from '../utils/files.js';
9
+ export class EditCommand {
16
10
  config;
17
11
  logger;
18
12
  api;
@@ -20,8 +14,8 @@ class EditCommand {
20
14
  constructor(config, logger) {
21
15
  this.config = config;
22
16
  this.logger = logger;
23
- this.api = new api_js_1.APIClient(config, logger);
24
- this.fileUtils = new files_js_1.FileUtils(process.cwd(), config.get('project').ignorePatterns);
17
+ this.api = new APIClient(config, logger);
18
+ this.fileUtils = new FileUtils(process.cwd(), config.get('project').ignorePatterns);
25
19
  }
26
20
  async run(filePath, options) {
27
21
  // Check auth
@@ -42,7 +36,7 @@ class EditCommand {
42
36
  return;
43
37
  }
44
38
  this.logger.section(`Editing: ${file.relativePath}`);
45
- console.log(chalk_1.default.gray(`Language: ${file.language} | Lines: ${file.lines}`));
39
+ console.log(chalk.gray(`Language: ${file.language} | Lines: ${file.lines}`));
46
40
  console.log();
47
41
  // Get instruction
48
42
  let instruction = options.instruction;
@@ -57,7 +51,7 @@ class EditCommand {
57
51
  this.logger.error('No --instruction provided and stdin is not interactive. Use: vigthoria edit file.ts --instruction "..."');
58
52
  return;
59
53
  }
60
- const answer = await inquirer_1.default.prompt([
54
+ const answer = await inquirer.prompt([
61
55
  {
62
56
  type: 'input',
63
57
  name: 'instruction',
@@ -68,7 +62,7 @@ class EditCommand {
68
62
  instruction = answer.instruction;
69
63
  }
70
64
  // Generate edit
71
- const spinner = (0, logger_js_1.createSpinner)({
65
+ const spinner = createSpinner({
72
66
  text: 'Generating changes...',
73
67
  spinner: 'dots',
74
68
  }).start();
@@ -122,8 +116,8 @@ Return the complete modified file content:`,
122
116
  }
123
117
  catch (error) {
124
118
  spinner.stop();
125
- const cliErr = error instanceof api_js_1.CLIError ? error : (0, api_js_1.classifyError)(error);
126
- this.logger.error((0, api_js_1.formatCLIError)(cliErr));
119
+ const cliErr = error instanceof CLIError ? error : classifyError(error);
120
+ this.logger.error(formatCLIError(cliErr));
127
121
  }
128
122
  }
129
123
  async fix(filePath, options) {
@@ -145,9 +139,9 @@ Return the complete modified file content:`,
145
139
  return;
146
140
  }
147
141
  this.logger.section(`Fixing: ${file.relativePath}`);
148
- console.log(chalk_1.default.gray(`Fix type: ${options.type} | Language: ${file.language}`));
142
+ console.log(chalk.gray(`Fix type: ${options.type} | Language: ${file.language}`));
149
143
  console.log();
150
- const spinner = (0, logger_js_1.createSpinner)({
144
+ const spinner = createSpinner({
151
145
  text: `Analyzing for ${options.type} issues...`,
152
146
  spinner: 'dots',
153
147
  }).start();
@@ -162,7 +156,7 @@ Return the complete modified file content:`,
162
156
  // diff and let the user decide instead of silently discarding.
163
157
  if (result.fixed && result.fixed !== file.content) {
164
158
  this.logger.section('Found 1 issue(s)');
165
- console.log(chalk_1.default.yellow('1. Operator/character-level fix detected'));
159
+ console.log(chalk.yellow('1. Operator/character-level fix detected'));
166
160
  console.log();
167
161
  if (options.apply) {
168
162
  await this.applyFix(file.path, file.content, result.fixed);
@@ -178,10 +172,10 @@ Return the complete modified file content:`,
178
172
  // Show fixes
179
173
  this.logger.section(`Found ${result.changes.length} issue(s)`);
180
174
  result.changes.forEach((change, i) => {
181
- console.log(chalk_1.default.yellow(`${i + 1}. Line ${change.line}:`));
182
- console.log(chalk_1.default.red(` - ${change.before}`));
183
- console.log(chalk_1.default.green(` + ${change.after}`));
184
- console.log(chalk_1.default.gray(` Reason: ${change.reason}`));
175
+ console.log(chalk.yellow(`${i + 1}. Line ${change.line}:`));
176
+ console.log(chalk.red(` - ${change.before}`));
177
+ console.log(chalk.green(` + ${change.after}`));
178
+ console.log(chalk.gray(` Reason: ${change.reason}`));
185
179
  console.log();
186
180
  });
187
181
  // Apply or confirm
@@ -194,8 +188,8 @@ Return the complete modified file content:`,
194
188
  }
195
189
  catch (error) {
196
190
  spinner.stop();
197
- const cliErr = error instanceof api_js_1.CLIError ? error : (0, api_js_1.classifyError)(error);
198
- this.logger.error((0, api_js_1.formatCLIError)(cliErr));
191
+ const cliErr = error instanceof CLIError ? error : classifyError(error);
192
+ this.logger.error(formatCLIError(cliErr));
199
193
  }
200
194
  }
201
195
  extractCode(response, language) {
@@ -358,10 +352,10 @@ Return the complete modified file content:`,
358
352
  // Show diff
359
353
  this.logger.section('Changes');
360
354
  diff.removed.forEach(line => {
361
- console.log(chalk_1.default.red(line));
355
+ console.log(chalk.red(line));
362
356
  });
363
357
  diff.added.forEach(line => {
364
- console.log(chalk_1.default.green(line));
358
+ console.log(chalk.green(line));
365
359
  });
366
360
  console.log();
367
361
  // Confirm
@@ -376,7 +370,7 @@ Return the complete modified file content:`,
376
370
  this.logger.info('Non-interactive mode. Re-run with --apply to apply changes.');
377
371
  return;
378
372
  }
379
- const { action } = await inquirer_1.default.prompt([
373
+ const { action } = await inquirer.prompt([
380
374
  {
381
375
  type: 'list',
382
376
  name: 'action',
@@ -394,7 +388,7 @@ Return the complete modified file content:`,
394
388
  break;
395
389
  case 'view':
396
390
  this.showFullDiff(original, modified);
397
- const { confirm } = await inquirer_1.default.prompt([
391
+ const { confirm } = await inquirer.prompt([
398
392
  {
399
393
  type: 'confirm',
400
394
  name: 'confirm',
@@ -415,7 +409,7 @@ Return the complete modified file content:`,
415
409
  const originalLines = original.split('\n');
416
410
  const modifiedLines = modified.split('\n');
417
411
  console.log();
418
- console.log(chalk_1.default.gray('─'.repeat(60)));
412
+ console.log(chalk.gray('─'.repeat(60)));
419
413
  // Use LCS-based diff to avoid line-shift inflation
420
414
  const m = originalLines.length;
421
415
  const n = modifiedLines.length;
@@ -454,26 +448,26 @@ Return the complete modified file content:`,
454
448
  if (op.type === 'keep') {
455
449
  displayLine++;
456
450
  const lineNum = String(displayLine).padStart(4, ' ');
457
- console.log(chalk_1.default.gray(`${lineNum} │ ${op.text || ''}`));
451
+ console.log(chalk.gray(`${lineNum} │ ${op.text || ''}`));
458
452
  }
459
453
  else if (op.type === 'remove') {
460
454
  displayLine++;
461
455
  const lineNum = String(displayLine).padStart(4, ' ');
462
- console.log(chalk_1.default.red(`${lineNum} - ${op.text}`));
456
+ console.log(chalk.red(`${lineNum} - ${op.text}`));
463
457
  }
464
458
  else {
465
459
  const lineNum = ' +';
466
- console.log(chalk_1.default.green(`${lineNum} + ${op.text}`));
460
+ console.log(chalk.green(`${lineNum} + ${op.text}`));
467
461
  }
468
462
  }
469
- console.log(chalk_1.default.gray('─'.repeat(60)));
463
+ console.log(chalk.gray('─'.repeat(60)));
470
464
  console.log();
471
465
  }
472
466
  async applyFix(filePath, original, modified) {
473
467
  // Create backup
474
468
  const backup = this.fileUtils.backupFile(filePath);
475
469
  if (backup) {
476
- this.logger.info(`Backup: ${chalk_1.default.gray(backup)}`);
470
+ this.logger.info(`Backup: ${chalk.gray(backup)}`);
477
471
  }
478
472
  // Apply changes
479
473
  if (this.fileUtils.writeFile(filePath, modified)) {
@@ -484,4 +478,3 @@ Return the complete modified file content:`,
484
478
  }
485
479
  }
486
480
  }
487
- exports.EditCommand = EditCommand;
@@ -1,19 +1,13 @@
1
- "use strict";
2
1
  /**
3
2
  * Explain Command - Explain code in files
4
3
  */
5
- var __importDefault = (this && this.__importDefault) || function (mod) {
6
- return (mod && mod.__esModule) ? mod : { "default": mod };
7
- };
8
- Object.defineProperty(exports, "__esModule", { value: true });
9
- exports.ExplainCommand = void 0;
10
- const chalk_1 = __importDefault(require("chalk"));
11
- const marked_1 = require("marked");
12
- const marked_terminal_1 = require("marked-terminal");
13
- const logger_js_1 = require("../utils/logger.js");
14
- const api_js_1 = require("../utils/api.js");
15
- const files_js_1 = require("../utils/files.js");
16
- class ExplainCommand {
4
+ import chalk from 'chalk';
5
+ import { Marked } from 'marked';
6
+ import { markedTerminal } from 'marked-terminal';
7
+ import { createSpinner } from '../utils/logger.js';
8
+ import { APIClient, CLIError, classifyError, formatCLIError } from '../utils/api.js';
9
+ import { FileUtils } from '../utils/files.js';
10
+ export class ExplainCommand {
17
11
  config;
18
12
  logger;
19
13
  api;
@@ -22,10 +16,10 @@ class ExplainCommand {
22
16
  constructor(config, logger) {
23
17
  this.config = config;
24
18
  this.logger = logger;
25
- this.api = new api_js_1.APIClient(config, logger);
26
- this.fileUtils = new files_js_1.FileUtils(process.cwd(), config.get('project').ignorePatterns);
27
- this.marked = new marked_1.Marked();
28
- this.marked.use((0, marked_terminal_1.markedTerminal)({
19
+ this.api = new APIClient(config, logger);
20
+ this.fileUtils = new FileUtils(process.cwd(), config.get('project').ignorePatterns);
21
+ this.marked = new Marked();
22
+ this.marked.use(markedTerminal({
29
23
  showSectionPrefix: false,
30
24
  tab: 2,
31
25
  width: 80,
@@ -62,17 +56,17 @@ class ExplainCommand {
62
56
  }
63
57
  }
64
58
  this.logger.section(`Explaining: ${file.relativePath}${lineInfo}`);
65
- console.log(chalk_1.default.gray(`Language: ${file.language} | Detail: ${options.detail}`));
59
+ console.log(chalk.gray(`Language: ${file.language} | Detail: ${options.detail}`));
66
60
  console.log();
67
61
  // Show the code being explained
68
- console.log(chalk_1.default.gray('─'.repeat(60)));
62
+ console.log(chalk.gray('─'.repeat(60)));
69
63
  codeToExplain.split('\n').forEach((line, i) => {
70
- const lineNum = chalk_1.default.gray(String(i + 1).padStart(4, ' ') + ' │ ');
64
+ const lineNum = chalk.gray(String(i + 1).padStart(4, ' ') + ' │ ');
71
65
  console.log(lineNum + line);
72
66
  });
73
- console.log(chalk_1.default.gray('─'.repeat(60)));
67
+ console.log(chalk.gray('─'.repeat(60)));
74
68
  console.log();
75
- const spinner = (0, logger_js_1.createSpinner)({
69
+ const spinner = createSpinner({
76
70
  text: 'Analyzing code...',
77
71
  spinner: 'dots',
78
72
  }).start();
@@ -86,8 +80,8 @@ class ExplainCommand {
86
80
  }
87
81
  catch (error) {
88
82
  spinner.stop();
89
- const cliErr = error instanceof api_js_1.CLIError ? error : (0, api_js_1.classifyError)(error);
90
- this.logger.error((0, api_js_1.formatCLIError)(cliErr));
83
+ const cliErr = error instanceof CLIError ? error : classifyError(error);
84
+ this.logger.error(formatCLIError(cliErr));
91
85
  }
92
86
  }
93
87
  /**
@@ -132,4 +126,3 @@ class ExplainCommand {
132
126
  }
133
127
  }
134
128
  }
135
- exports.ExplainCommand = ExplainCommand;
@@ -1,16 +1,12 @@
1
- "use strict";
2
- var __importDefault = (this && this.__importDefault) || function (mod) {
3
- return (mod && mod.__esModule) ? mod : { "default": mod };
4
- };
5
- Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.ForkCommand = void 0;
7
- const api_js_1 = require("../utils/api.js");
1
+ import { isServerRuntime } from '../utils/api.js';
8
2
  /**
9
3
  * fork.ts — Fork from an existing V3 agent run and stream the result.
10
4
  */
11
- const chalk_1 = __importDefault(require("chalk"));
12
- const logger_js_1 = require("../utils/logger.js");
13
- class ForkCommand {
5
+ import chalk from 'chalk';
6
+ import { createRequire } from 'node:module';
7
+ import { createSpinner, CH } from '../utils/logger.js';
8
+ const require = createRequire(import.meta.url);
9
+ export class ForkCommand {
14
10
  config;
15
11
  logger;
16
12
  constructor(config, logger) {
@@ -33,7 +29,7 @@ class ForkCommand {
33
29
  }
34
30
  getBaseUrl() {
35
31
  const configuredApiUrl = String(this.config.get('apiUrl') || 'https://coder.vigthoria.io').replace(/\/$/, '');
36
- const allowLocal = (0, api_js_1.isServerRuntime)() && process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
32
+ const allowLocal = isServerRuntime() && process.env.VIGTHORIA_ALLOW_LOCAL_V3_AGENT === '1';
37
33
  return (process.env.VIGTHORIA_V3_AGENT_URL ||
38
34
  process.env.V3_AGENT_URL ||
39
35
  (allowLocal ? 'http://127.0.0.1:8030' : null) ||
@@ -56,7 +52,7 @@ class ForkCommand {
56
52
  const project = options.project || process.cwd();
57
53
  const workspace = this.resolveWorkspaceRoot(project);
58
54
  const eventIndex = options.eventIndex || 0;
59
- const spinner = (0, logger_js_1.createSpinner)(`Forking run ${runId}...`).start();
55
+ const spinner = createSpinner(`Forking run ${runId}...`).start();
60
56
  try {
61
57
  const baseUrl = this.getBaseUrl();
62
58
  const body = {
@@ -85,7 +81,7 @@ class ForkCommand {
85
81
  return;
86
82
  }
87
83
  spinner.stop();
88
- console.log(chalk_1.default.bold(`\n${logger_js_1.CH.success} Forked from ${chalk_1.default.cyan(runId)} at event ${eventIndex}\n`));
84
+ console.log(chalk.bold(`\n${CH.success} Forked from ${chalk.cyan(runId)} at event ${eventIndex}\n`));
89
85
  if (!resp.body) {
90
86
  this.logger.error('No response body');
91
87
  return;
@@ -107,7 +103,7 @@ class ForkCommand {
107
103
  continue;
108
104
  const payload = line.slice(6).trim();
109
105
  if (payload === '[DONE]') {
110
- console.log(chalk_1.default.bold(`\n${logger_js_1.CH.success} Fork run complete\n`));
106
+ console.log(chalk.bold(`\n${CH.success} Fork run complete\n`));
111
107
  return;
112
108
  }
113
109
  try {
@@ -119,39 +115,39 @@ class ForkCommand {
119
115
  }
120
116
  switch (type) {
121
117
  case 'context':
122
- console.log(chalk_1.default.blue(` context: ${evt.context_id || '?'}`) +
123
- (evt.forked_from ? chalk_1.default.dim(` (forked from ${evt.forked_from})`) : ''));
118
+ console.log(chalk.blue(` context: ${evt.context_id || '?'}`) +
119
+ (evt.forked_from ? chalk.dim(` (forked from ${evt.forked_from})`) : ''));
124
120
  break;
125
121
  case 'start':
126
- console.log(chalk_1.default.green(` ▶ START`) + ` task=${evt.task_id || '?'}` +
127
- (evt.forked_from ? chalk_1.default.dim(` forked_from=${evt.forked_from}`) : ''));
122
+ console.log(chalk.green(` ▶ START`) + ` task=${evt.task_id || '?'}` +
123
+ (evt.forked_from ? chalk.dim(` forked_from=${evt.forked_from}`) : ''));
128
124
  break;
129
125
  case 'plan':
130
- console.log(chalk_1.default.magenta(` 📋 PLAN`) + ` ${evt.tasks?.length || 0} tasks`);
126
+ console.log(chalk.magenta(` 📋 PLAN`) + ` ${evt.tasks?.length || 0} tasks`);
131
127
  break;
132
128
  case 'tool_call':
133
129
  toolCallNum++;
134
- console.log(chalk_1.default.yellow(` 🔧 #${toolCallNum}`) + ` ${evt.name || '?'}(${JSON.stringify(evt.arguments || {}).substring(0, 60)})`);
130
+ console.log(chalk.yellow(` 🔧 #${toolCallNum}`) + ` ${evt.name || '?'}(${JSON.stringify(evt.arguments || {}).substring(0, 60)})`);
135
131
  break;
136
132
  case 'tool_result': {
137
- const icon = evt.success !== false ? chalk_1.default.green('✓') : chalk_1.default.red('✗');
138
- console.log(` ${icon} ${evt.name || '?'}: ${chalk_1.default.dim((evt.output || '').substring(0, 100))}`);
133
+ const icon = evt.success !== false ? chalk.green('✓') : chalk.red('✗');
134
+ console.log(` ${icon} ${evt.name || '?'}: ${chalk.dim((evt.output || '').substring(0, 100))}`);
139
135
  break;
140
136
  }
141
137
  case 'message':
142
- console.log(chalk_1.default.cyan(` 💬 `) + (evt.content || '').substring(0, 150));
138
+ console.log(chalk.cyan(` 💬 `) + (evt.content || '').substring(0, 150));
143
139
  break;
144
140
  case 'complete': {
145
141
  const seal = evt.seal_score ? `[${evt.seal_score.tier} ${evt.seal_score.overall}]` : '';
146
- console.log(chalk_1.default.green(` ✅ COMPLETE `) + chalk_1.default.yellow(seal) +
142
+ console.log(chalk.green(` ✅ COMPLETE `) + chalk.yellow(seal) +
147
143
  ` ${evt.iterations || '?'} iterations, ${evt.tool_calls || '?'} tool calls`);
148
144
  break;
149
145
  }
150
146
  case 'error':
151
- console.log(chalk_1.default.red(` ❌ ERROR: `) + (evt.message || '').substring(0, 200));
147
+ console.log(chalk.red(` ❌ ERROR: `) + (evt.message || '').substring(0, 200));
152
148
  break;
153
149
  default:
154
- console.log(chalk_1.default.dim(` ${type}: ${JSON.stringify(evt).substring(0, 80)}`));
150
+ console.log(chalk.dim(` ${type}: ${JSON.stringify(evt).substring(0, 80)}`));
155
151
  }
156
152
  }
157
153
  catch {
@@ -166,4 +162,3 @@ class ForkCommand {
166
162
  }
167
163
  }
168
164
  }
169
- exports.ForkCommand = ForkCommand;