vigthoria-cli 1.12.1 → 1.12.3
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/chat.js +7 -1
- package/dist/commands/v4-menu.d.ts +9 -0
- package/dist/commands/v4-menu.js +136 -0
- package/dist/commands/v4.d.ts +2 -0
- package/dist/commands/v4.js +2 -2
- package/dist/index.js +29 -4
- package/dist/utils/logger.js +6 -1
- package/package.json +1 -1
package/dist/commands/chat.js
CHANGED
|
@@ -921,7 +921,13 @@ export class ChatCommand {
|
|
|
921
921
|
}
|
|
922
922
|
terminalColumns() {
|
|
923
923
|
const raw = Number(process.stdout.columns || process.stderr.columns || 80);
|
|
924
|
-
|
|
924
|
+
const safe = Number.isFinite(raw) && raw > 0 ? raw : 80;
|
|
925
|
+
// process.stdout.columns is not always a reliable indicator of how many
|
|
926
|
+
// columns actually render visually (seen mismatching badly in some
|
|
927
|
+
// embedded/split-pane terminal hosts on Windows) -- cap at a
|
|
928
|
+
// conservative width so wrapped/fitted text never overflows even when
|
|
929
|
+
// the reported column count is larger than the real usable width.
|
|
930
|
+
return Math.min(safe, 60);
|
|
925
931
|
}
|
|
926
932
|
fitTerminalText(text, reserve = 0) {
|
|
927
933
|
const width = Math.max(24, this.terminalColumns() - reserve);
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interactive V3/V4 agent + V4 provider picker, styled to match the rest of
|
|
3
|
+
* the Vigthoria CLI's menus (see agent-session-menu.ts). This is invoked as a
|
|
4
|
+
* subprocess (with inherited stdio, so it keeps full TTY/inquirer rendering)
|
|
5
|
+
* by the V4 Operating Agent's Python launcher (cli_menu.py) instead of that
|
|
6
|
+
* project rendering its own boxed prompt_toolkit dialog, which looked
|
|
7
|
+
* inconsistent with the CLI's visual design.
|
|
8
|
+
*
|
|
9
|
+
* The result is written as JSON to --out-file rather than printed to stdout,
|
|
10
|
+
* so stdout can stay fully interactive (a piped stdout would make inquirer
|
|
11
|
+
* fall back to non-interactive/plain rendering).
|
|
12
|
+
*/
|
|
13
|
+
import * as fs from 'fs';
|
|
14
|
+
import chalk from 'chalk';
|
|
15
|
+
import inquirer from 'inquirer';
|
|
16
|
+
function isCancelError(error) {
|
|
17
|
+
const name = error instanceof Error ? error.name : '';
|
|
18
|
+
return name === 'ExitPromptError' || name === 'ERR_CLOSED';
|
|
19
|
+
}
|
|
20
|
+
function writeResult(outFile, result) {
|
|
21
|
+
fs.writeFileSync(outFile, JSON.stringify(result), 'utf8');
|
|
22
|
+
}
|
|
23
|
+
export async function runV4Menu(options) {
|
|
24
|
+
const defaultAgent = options.defaultAgent === 'v4' ? 'v4' : 'v3';
|
|
25
|
+
const defaultProvider = options.defaultProvider === 'v3_local' || options.defaultProvider === 'byok'
|
|
26
|
+
? options.defaultProvider
|
|
27
|
+
: 'cloud';
|
|
28
|
+
console.log();
|
|
29
|
+
console.log(chalk.cyan('═══ Vigthoria Agent Launcher ═══'));
|
|
30
|
+
console.log(chalk.gray('Choose which agent runtime to start.'));
|
|
31
|
+
console.log();
|
|
32
|
+
try {
|
|
33
|
+
const { agent } = await inquirer.prompt([
|
|
34
|
+
{
|
|
35
|
+
type: 'list',
|
|
36
|
+
name: 'agent',
|
|
37
|
+
message: 'Select runtime',
|
|
38
|
+
default: defaultAgent,
|
|
39
|
+
choices: [
|
|
40
|
+
{ name: 'V3 Code Agent', value: 'v3' },
|
|
41
|
+
{ name: 'V4 Operating Agent', value: 'v4' },
|
|
42
|
+
],
|
|
43
|
+
},
|
|
44
|
+
]);
|
|
45
|
+
if (agent === 'v3') {
|
|
46
|
+
console.log();
|
|
47
|
+
console.log(chalk.cyan('── Session ready ──'));
|
|
48
|
+
console.log(chalk.gray('Runtime: V3 Code Agent'));
|
|
49
|
+
console.log();
|
|
50
|
+
writeResult(options.outFile, { agent: 'v3' });
|
|
51
|
+
return;
|
|
52
|
+
}
|
|
53
|
+
const { provider } = await inquirer.prompt([
|
|
54
|
+
{
|
|
55
|
+
type: 'list',
|
|
56
|
+
name: 'provider',
|
|
57
|
+
message: 'Select V4 backend',
|
|
58
|
+
default: defaultProvider,
|
|
59
|
+
choices: [
|
|
60
|
+
{ name: 'Vigthoria Cloud (Gateway + Session Wallet Token)', value: 'cloud' },
|
|
61
|
+
{ name: 'Vigthoria V3 Local (Blackwell 35B Direct)', value: 'v3_local' },
|
|
62
|
+
{ name: 'Bring Your Own Key (API Key + Base URL + Model)', value: 'byok' },
|
|
63
|
+
],
|
|
64
|
+
},
|
|
65
|
+
]);
|
|
66
|
+
if (provider !== 'byok') {
|
|
67
|
+
console.log();
|
|
68
|
+
console.log(chalk.cyan('── Session ready ──'));
|
|
69
|
+
console.log(chalk.gray(`Runtime: V4 Operating Agent (${provider === 'cloud' ? 'Vigthoria Cloud' : 'Vigthoria V3 Local'})`));
|
|
70
|
+
console.log();
|
|
71
|
+
writeResult(options.outFile, { agent: 'v4', provider });
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const existingApiKey = String(options.byokApiKey || '').trim();
|
|
75
|
+
const existingBaseUrl = String(options.byokBaseUrl || '').trim();
|
|
76
|
+
const existingModel = String(options.byokModel || '').trim();
|
|
77
|
+
const missing = !existingApiKey || !existingBaseUrl || !existingModel;
|
|
78
|
+
const questions = [];
|
|
79
|
+
if (!existingApiKey) {
|
|
80
|
+
questions.push({
|
|
81
|
+
type: 'password',
|
|
82
|
+
name: 'apiKey',
|
|
83
|
+
message: 'BYOK API key:',
|
|
84
|
+
mask: '*',
|
|
85
|
+
validate: (value) => (String(value || '').trim() ? true : 'API key is required.'),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
if (!existingBaseUrl) {
|
|
89
|
+
questions.push({
|
|
90
|
+
type: 'input',
|
|
91
|
+
name: 'baseUrl',
|
|
92
|
+
message: 'BYOK base URL:',
|
|
93
|
+
validate: (value) => (String(value || '').trim() ? true : 'Base URL is required.'),
|
|
94
|
+
});
|
|
95
|
+
}
|
|
96
|
+
if (!existingModel) {
|
|
97
|
+
questions.push({
|
|
98
|
+
type: 'input',
|
|
99
|
+
name: 'model',
|
|
100
|
+
message: 'BYOK default model:',
|
|
101
|
+
validate: (value) => (String(value || '').trim() ? true : 'Model is required.'),
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
const answers = questions.length > 0 ? await inquirer.prompt(questions) : {};
|
|
105
|
+
const apiKey = String(answers.apiKey || existingApiKey).trim();
|
|
106
|
+
const baseUrl = String(answers.baseUrl || existingBaseUrl).trim();
|
|
107
|
+
const model = String(answers.model || existingModel).trim();
|
|
108
|
+
let save = false;
|
|
109
|
+
if (missing) {
|
|
110
|
+
const { saveLocally } = await inquirer.prompt([
|
|
111
|
+
{
|
|
112
|
+
type: 'confirm',
|
|
113
|
+
name: 'saveLocally',
|
|
114
|
+
message: 'Store BYOK values locally in ~/.config/vigthoria/config.yaml?',
|
|
115
|
+
default: true,
|
|
116
|
+
},
|
|
117
|
+
]);
|
|
118
|
+
save = saveLocally;
|
|
119
|
+
}
|
|
120
|
+
console.log();
|
|
121
|
+
console.log(chalk.cyan('── Session ready ──'));
|
|
122
|
+
console.log(chalk.gray('Runtime: V4 Operating Agent (Bring Your Own Key)'));
|
|
123
|
+
console.log();
|
|
124
|
+
writeResult(options.outFile, { agent: 'v4', provider: 'byok', apiKey, baseUrl, model, save });
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
if (isCancelError(error)) {
|
|
128
|
+
console.log();
|
|
129
|
+
console.log(chalk.yellow('Cancelled.'));
|
|
130
|
+
writeResult(options.outFile, { cancelled: true });
|
|
131
|
+
process.exitCode = 130;
|
|
132
|
+
return;
|
|
133
|
+
}
|
|
134
|
+
throw error;
|
|
135
|
+
}
|
|
136
|
+
}
|
package/dist/commands/v4.d.ts
CHANGED
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
import { Command } from 'commander';
|
|
2
2
|
import { Config } from '../utils/config.js';
|
|
3
3
|
import { Logger } from '../utils/logger.js';
|
|
4
|
+
export declare function defaultV4PythonBin(): string;
|
|
5
|
+
export declare function defaultV4AgentDir(): string | undefined;
|
|
4
6
|
type V4Options = {
|
|
5
7
|
provider?: 'cloud' | 'v3_local' | 'byok';
|
|
6
8
|
apiKey?: string;
|
package/dist/commands/v4.js
CHANGED
|
@@ -3,10 +3,10 @@ import * as fs from 'fs';
|
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import chalk from 'chalk';
|
|
5
5
|
const DEFAULT_V4_AGENT_DIR_UNIX = '/var/www/V4-Operating-Agent';
|
|
6
|
-
function defaultV4PythonBin() {
|
|
6
|
+
export function defaultV4PythonBin() {
|
|
7
7
|
return process.env.VIGTHORIA_V4_PYTHON || (process.platform === 'win32' ? 'python' : 'python3');
|
|
8
8
|
}
|
|
9
|
-
function defaultV4AgentDir() {
|
|
9
|
+
export function defaultV4AgentDir() {
|
|
10
10
|
if (process.env.VIGTHORIA_V4_AGENT_DIR) {
|
|
11
11
|
return process.env.VIGTHORIA_V4_AGENT_DIR;
|
|
12
12
|
}
|
package/dist/index.js
CHANGED
|
@@ -38,7 +38,8 @@ import { ForkCommand } from './commands/fork.js';
|
|
|
38
38
|
import { CancelCommand } from './commands/cancel.js';
|
|
39
39
|
import { BackgroundCommand } from './commands/background.js';
|
|
40
40
|
import { SecurityCommand } from './commands/security.js';
|
|
41
|
-
import { V4Command } from './commands/v4.js';
|
|
41
|
+
import { V4Command, defaultV4PythonBin, defaultV4AgentDir } from './commands/v4.js';
|
|
42
|
+
import { runV4Menu } from './commands/v4-menu.js';
|
|
42
43
|
import { Config } from './utils/config.js';
|
|
43
44
|
import { Logger, CH } from './utils/logger.js';
|
|
44
45
|
import chalk from 'chalk';
|
|
@@ -584,8 +585,13 @@ export async function main(args) {
|
|
|
584
585
|
!jsonOutputRequested &&
|
|
585
586
|
!directPromptRequested &&
|
|
586
587
|
!helpOrVersionRequested) {
|
|
588
|
+
// process.stdout.columns is not always a reliable indicator of how
|
|
589
|
+
// many columns actually render visually (seen mismatching badly in some
|
|
590
|
+
// embedded/split-pane terminal hosts on Windows) -- cap the box at a
|
|
591
|
+
// conservative width so it never overflows even when the reported
|
|
592
|
+
// column count is larger than the real usable width.
|
|
587
593
|
const terminalWidth = Math.max(36, Number(process.stdout.columns || 80));
|
|
588
|
-
const boxWidth = Math.max(34, Math.min(
|
|
594
|
+
const boxWidth = Math.max(34, Math.min(44, terminalWidth - 8));
|
|
589
595
|
const innerWidth = boxWidth;
|
|
590
596
|
const fit = (text) => {
|
|
591
597
|
const clean = String(text || '').replace(/\s+/g, ' ').trim();
|
|
@@ -759,8 +765,8 @@ export async function main(args) {
|
|
|
759
765
|
.option('--harness-control-url <url>', 'Override harness control URL')
|
|
760
766
|
.option('--session-id <id>', 'Explicit V4 session id')
|
|
761
767
|
.option('--non-interactive', 'Disable interactive menu and use CLI options', false)
|
|
762
|
-
.option('--python <bin>', 'Python binary to use',
|
|
763
|
-
.option('--v4-path <path>', 'V4 agent root path
|
|
768
|
+
.option('--python <bin>', 'Python binary to use', defaultV4PythonBin())
|
|
769
|
+
.option('--v4-path <path>', 'V4 agent root path (or set VIGTHORIA_V4_AGENT_DIR)', defaultV4AgentDir())
|
|
764
770
|
.action(async (options) => {
|
|
765
771
|
const v4 = new V4Command(config, logger);
|
|
766
772
|
await v4.run({
|
|
@@ -777,6 +783,25 @@ export async function main(args) {
|
|
|
777
783
|
v4Path: options.v4Path,
|
|
778
784
|
});
|
|
779
785
|
});
|
|
786
|
+
program
|
|
787
|
+
.command('v4-menu')
|
|
788
|
+
.description('Internal: interactive V3/V4 agent + provider picker used by the V4 Operating Agent launcher')
|
|
789
|
+
.option('--default-agent <agent>', 'v3 | v4', 'v3')
|
|
790
|
+
.option('--default-provider <provider>', 'cloud | v3_local | byok', 'cloud')
|
|
791
|
+
.option('--byok-api-key <key>', 'Existing BYOK api key', '')
|
|
792
|
+
.option('--byok-base-url <url>', 'Existing BYOK base url', '')
|
|
793
|
+
.option('--byok-model <name>', 'Existing BYOK model', '')
|
|
794
|
+
.requiredOption('--out-file <path>', 'Write JSON selection result to this file')
|
|
795
|
+
.action(async (options) => {
|
|
796
|
+
await runV4Menu({
|
|
797
|
+
defaultAgent: options.defaultAgent,
|
|
798
|
+
defaultProvider: options.defaultProvider,
|
|
799
|
+
byokApiKey: options.byokApiKey,
|
|
800
|
+
byokBaseUrl: options.byokBaseUrl,
|
|
801
|
+
byokModel: options.byokModel,
|
|
802
|
+
outFile: options.outFile,
|
|
803
|
+
});
|
|
804
|
+
});
|
|
780
805
|
program
|
|
781
806
|
.command('bridge')
|
|
782
807
|
.description('Inspect local DevTools Bridge availability for browser debugging tasks')
|
package/dist/utils/logger.js
CHANGED
|
@@ -162,11 +162,16 @@ export class Logger {
|
|
|
162
162
|
}
|
|
163
163
|
// Section header
|
|
164
164
|
section(title) {
|
|
165
|
+
// process.stdout.columns is not always a reliable indicator of how many
|
|
166
|
+
// columns actually render visually (seen mismatching badly in some
|
|
167
|
+
// embedded/split-pane terminal hosts on Windows) -- cap at a
|
|
168
|
+
// conservative width so the separator line never overflows even when
|
|
169
|
+
// the reported column count is larger than the real usable width.
|
|
165
170
|
const width = Math.max(24, Number(process.stdout.columns || 80));
|
|
166
171
|
const cleanTitle = String(title || '').replace(/\s+/g, ' ').trim();
|
|
167
172
|
const maxTitle = Math.max(10, width - 10);
|
|
168
173
|
const fittedTitle = cleanTitle.length > maxTitle ? `${cleanTitle.slice(0, maxTitle - 1)}…` : cleanTitle;
|
|
169
|
-
const side = Math.max(3, Math.floor((Math.min(width,
|
|
174
|
+
const side = Math.max(3, Math.floor((Math.min(width, 44) - fittedTitle.length - 2) / 2));
|
|
170
175
|
console.log();
|
|
171
176
|
console.log(chalk.bold.cyan(`${CH.hDouble.repeat(side)} ${fittedTitle} ${CH.hDouble.repeat(side)}`));
|
|
172
177
|
console.log();
|