vigthoria-cli 1.6.38 → 1.6.40
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 +10 -43
- package/dist/commands/explain.d.ts +6 -0
- package/dist/commands/explain.js +29 -2
- package/dist/commands/review.d.ts +4 -0
- package/dist/commands/review.js +26 -3
- package/dist/index.js +1 -1
- package/dist/utils/api.js +2 -2
- package/package.json +1 -1
package/dist/commands/chat.js
CHANGED
|
@@ -82,8 +82,8 @@ class ChatCommand {
|
|
|
82
82
|
return;
|
|
83
83
|
}
|
|
84
84
|
if (enabledMode === 'operator') {
|
|
85
|
-
if (this.currentModel === 'agent' || !this.currentModel) {
|
|
86
|
-
this.currentModel = 'code
|
|
85
|
+
if (this.currentModel === 'agent' || this.currentModel === 'code-8b' || !this.currentModel) {
|
|
86
|
+
this.currentModel = 'code';
|
|
87
87
|
}
|
|
88
88
|
return;
|
|
89
89
|
}
|
|
@@ -108,10 +108,12 @@ class ChatCommand {
|
|
|
108
108
|
resolveInitialModel(options) {
|
|
109
109
|
const requestedModel = String(options.model || '').trim();
|
|
110
110
|
if (requestedModel) {
|
|
111
|
-
return requestedModel
|
|
111
|
+
return options.operator === true && requestedModel === 'code-8b'
|
|
112
|
+
? 'code'
|
|
113
|
+
: requestedModel;
|
|
112
114
|
}
|
|
113
115
|
if (options.operator === true) {
|
|
114
|
-
return 'code
|
|
116
|
+
return 'code';
|
|
115
117
|
}
|
|
116
118
|
if (options.agent === true) {
|
|
117
119
|
return 'agent';
|
|
@@ -673,13 +675,6 @@ class ChatCommand {
|
|
|
673
675
|
this.logger.error(this.operatorAccessMessage());
|
|
674
676
|
return;
|
|
675
677
|
}
|
|
676
|
-
// Smart routing: infrastructure action verbs always need the BMAD
|
|
677
|
-
// workflow. Everything else can be answered with a direct chat.
|
|
678
|
-
const isInfraAction = /(deploy|provision|scale|replicas|rollback|roll back|migrate|tear.?down|restart|stop\s+\w+|start\s+\w+|configure|set.?up|upgrade|pipeline)/i.test(prompt.trim());
|
|
679
|
-
if (!isInfraAction && (this.isSimpleDirectPrompt(prompt) || this.isOperatorDirectAnswerable(prompt))) {
|
|
680
|
-
await this.runSimplePrompt(prompt);
|
|
681
|
-
return;
|
|
682
|
-
}
|
|
683
678
|
await this.runOperatorTurn(prompt);
|
|
684
679
|
return;
|
|
685
680
|
}
|
|
@@ -791,34 +786,8 @@ class ChatCommand {
|
|
|
791
786
|
(0, bridge_client_js_1.getBridgeClient)()?.emitPrompt({ prompt, mode: 'operator', model: this.currentModel });
|
|
792
787
|
const runtimeContext = await this.getPromptRuntimeContext(prompt);
|
|
793
788
|
const spinner = this.jsonOutput ? null : (0, logger_js_1.createSpinner)({ text: 'Thinking like an operator...', spinner: 'clock' }).start();
|
|
794
|
-
const
|
|
795
|
-
const
|
|
796
|
-
? 'analysis_only'
|
|
797
|
-
: 'full_autonomy';
|
|
798
|
-
// For lightweight lookup tasks, prepend a grounding constraint so
|
|
799
|
-
// the operator returns a concise answer rather than a verbose report.
|
|
800
|
-
let executionPrompt = this.buildExecutionPrompt(prompt);
|
|
801
|
-
if (isLookup) {
|
|
802
|
-
// Inject workspace file listing into the prompt so the operator
|
|
803
|
-
// can answer "which file defines X" without a full agent loop.
|
|
804
|
-
let fileListing = '';
|
|
805
|
-
try {
|
|
806
|
-
const snapshot = this.api.getAgentWorkspaceSnapshot(this.currentProjectPath);
|
|
807
|
-
if (snapshot && snapshot.paths.length > 0) {
|
|
808
|
-
fileListing = '\n\nWorkspace file listing:\n' + snapshot.paths.slice(0, 80).join('\n');
|
|
809
|
-
}
|
|
810
|
-
}
|
|
811
|
-
catch { /* ignore */ }
|
|
812
|
-
executionPrompt = [
|
|
813
|
-
'INSTRUCTION: This is a lightweight lookup task. Return ONLY the concise answer the user asked for.',
|
|
814
|
-
'Do NOT produce a certification report, audit, or analysis blob.',
|
|
815
|
-
'Do NOT return files_analyzed counts or summary statistics.',
|
|
816
|
-
'Just answer the question directly.',
|
|
817
|
-
fileListing,
|
|
818
|
-
'',
|
|
819
|
-
executionPrompt,
|
|
820
|
-
].join('\n');
|
|
821
|
-
}
|
|
789
|
+
const workflowType = 'full';
|
|
790
|
+
const executionPrompt = this.buildExecutionPrompt(prompt);
|
|
822
791
|
try {
|
|
823
792
|
const response = await this.api.runOperatorWorkflow(executionPrompt, {
|
|
824
793
|
workspacePath: this.currentProjectPath,
|
|
@@ -838,14 +807,12 @@ class ChatCommand {
|
|
|
838
807
|
spinner.stop();
|
|
839
808
|
}
|
|
840
809
|
// Guard: if the operator workflow returned a useless policy
|
|
841
|
-
// acknowledgement instead of a real answer,
|
|
842
|
-
// simple prompt with operator grounding.
|
|
810
|
+
// acknowledgement instead of a real grounded answer, fail closed.
|
|
843
811
|
const responseText = (response.content || '').trim();
|
|
844
812
|
const isPolicyAck = /^(i will follow|i understand|i('ll| will) adhere|understood[.,!]|sure[.,!]|provide your|waiting for|i('ll| will) proceed)/i.test(responseText)
|
|
845
813
|
|| (responseText.length < 200 && /follow the instructions|next instruction|ready to assist/i.test(responseText));
|
|
846
814
|
if (isPolicyAck) {
|
|
847
|
-
|
|
848
|
-
return;
|
|
815
|
+
throw new api_js_1.CLIError('Operator workflow returned a non-actionable acknowledgement instead of a grounded result.', 'model_backend');
|
|
849
816
|
}
|
|
850
817
|
if (this.jsonOutput) {
|
|
851
818
|
console.log(JSON.stringify({
|
|
@@ -15,6 +15,12 @@ export declare class ExplainCommand {
|
|
|
15
15
|
private marked;
|
|
16
16
|
constructor(config: Config, logger: Logger);
|
|
17
17
|
run(filePath: string, options: ExplainOptions): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Clean marked-terminal output for release-grade CLI presentation.
|
|
20
|
+
* De-indents bullets, normalises bullet characters, and removes stray
|
|
21
|
+
* ANSI-only lines that marked-terminal inserts between sub-items.
|
|
22
|
+
*/
|
|
23
|
+
private cleanTerminalOutput;
|
|
18
24
|
private formatExplanation;
|
|
19
25
|
}
|
|
20
26
|
export {};
|
package/dist/commands/explain.js
CHANGED
|
@@ -25,7 +25,12 @@ class ExplainCommand {
|
|
|
25
25
|
this.api = new api_js_1.APIClient(config, logger);
|
|
26
26
|
this.fileUtils = new files_js_1.FileUtils(process.cwd(), config.get('project').ignorePatterns);
|
|
27
27
|
this.marked = new marked_1.Marked();
|
|
28
|
-
this.marked.use((0, marked_terminal_1.markedTerminal)(
|
|
28
|
+
this.marked.use((0, marked_terminal_1.markedTerminal)({
|
|
29
|
+
showSectionPrefix: false,
|
|
30
|
+
tab: 2,
|
|
31
|
+
width: 80,
|
|
32
|
+
reflowText: true,
|
|
33
|
+
}));
|
|
29
34
|
}
|
|
30
35
|
async run(filePath, options) {
|
|
31
36
|
// Check auth
|
|
@@ -77,7 +82,7 @@ class ExplainCommand {
|
|
|
77
82
|
// Format based on detail level
|
|
78
83
|
const formattedExplanation = this.formatExplanation(explanation, options.detail);
|
|
79
84
|
this.logger.section('Explanation');
|
|
80
|
-
console.log(this.marked.parse(formattedExplanation));
|
|
85
|
+
console.log(this.cleanTerminalOutput(this.marked.parse(formattedExplanation)));
|
|
81
86
|
}
|
|
82
87
|
catch (error) {
|
|
83
88
|
spinner.stop();
|
|
@@ -85,6 +90,28 @@ class ExplainCommand {
|
|
|
85
90
|
this.logger.error((0, api_js_1.formatCLIError)(cliErr));
|
|
86
91
|
}
|
|
87
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* Clean marked-terminal output for release-grade CLI presentation.
|
|
95
|
+
* De-indents bullets, normalises bullet characters, and removes stray
|
|
96
|
+
* ANSI-only lines that marked-terminal inserts between sub-items.
|
|
97
|
+
*/
|
|
98
|
+
cleanTerminalOutput(raw) {
|
|
99
|
+
let out = raw;
|
|
100
|
+
// De-indent top-level bullets: ' * text' → '- text'
|
|
101
|
+
out = out.replace(/^ \* /gm, '- ');
|
|
102
|
+
// De-indent sub-level bullets: ' * text' → ' - text'
|
|
103
|
+
out = out.replace(/^ \* /gm, ' - ');
|
|
104
|
+
// Remove lines that are only whitespace + ANSI (no visible text)
|
|
105
|
+
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
106
|
+
out = out.split('\n').filter(line => {
|
|
107
|
+
if (line === '')
|
|
108
|
+
return true;
|
|
109
|
+
return stripAnsi(line).trim().length > 0;
|
|
110
|
+
}).join('\n');
|
|
111
|
+
// Collapse 3+ consecutive newlines to 2
|
|
112
|
+
out = out.replace(/\n{3,}/g, '\n\n');
|
|
113
|
+
return out;
|
|
114
|
+
}
|
|
88
115
|
formatExplanation(explanation, detail) {
|
|
89
116
|
// Normalize formatting: convert any numbered lists to bullet lists
|
|
90
117
|
// to prevent broken nested numbering in terminal rendering.
|
|
@@ -17,6 +17,10 @@ export declare class ReviewCommand {
|
|
|
17
17
|
private printTextReview;
|
|
18
18
|
private printMarkdownReview;
|
|
19
19
|
private renderScoreBar;
|
|
20
|
+
/**
|
|
21
|
+
* Clean marked-terminal output for release-grade CLI presentation.
|
|
22
|
+
*/
|
|
23
|
+
private cleanTerminalOutput;
|
|
20
24
|
private getSeverityIcon;
|
|
21
25
|
private getSeverityColor;
|
|
22
26
|
}
|
package/dist/commands/review.js
CHANGED
|
@@ -25,7 +25,12 @@ class ReviewCommand {
|
|
|
25
25
|
this.api = new api_js_1.APIClient(config, logger);
|
|
26
26
|
this.fileUtils = new files_js_1.FileUtils(process.cwd(), config.get('project').ignorePatterns);
|
|
27
27
|
this.marked = new marked_1.Marked();
|
|
28
|
-
this.marked.use((0, marked_terminal_1.markedTerminal)(
|
|
28
|
+
this.marked.use((0, marked_terminal_1.markedTerminal)({
|
|
29
|
+
showSectionPrefix: false,
|
|
30
|
+
tab: 2,
|
|
31
|
+
width: 80,
|
|
32
|
+
reflowText: true,
|
|
33
|
+
}));
|
|
29
34
|
}
|
|
30
35
|
async run(filePath, options) {
|
|
31
36
|
// Check auth
|
|
@@ -122,14 +127,32 @@ class ReviewCommand {
|
|
|
122
127
|
markdown += `${i + 1}. ${s}\n`;
|
|
123
128
|
});
|
|
124
129
|
}
|
|
125
|
-
console.log(this.marked.parse(markdown));
|
|
130
|
+
console.log(this.cleanTerminalOutput(this.marked.parse(markdown)));
|
|
126
131
|
}
|
|
127
132
|
renderScoreBar(score) {
|
|
128
133
|
const width = 30;
|
|
129
134
|
const filled = Math.round((score / 100) * width);
|
|
130
135
|
const empty = width - filled;
|
|
131
136
|
const color = score >= 80 ? chalk_1.default.green : score >= 60 ? chalk_1.default.yellow : chalk_1.default.red;
|
|
132
|
-
|
|
137
|
+
const filledChar = process.platform === 'win32' ? '#' : '\u2588';
|
|
138
|
+
const emptyChar = process.platform === 'win32' ? '.' : '\u2591';
|
|
139
|
+
return color(filledChar.repeat(filled)) + chalk_1.default.gray(emptyChar.repeat(empty));
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* Clean marked-terminal output for release-grade CLI presentation.
|
|
143
|
+
*/
|
|
144
|
+
cleanTerminalOutput(raw) {
|
|
145
|
+
let out = raw;
|
|
146
|
+
out = out.replace(/^ \* /gm, '- ');
|
|
147
|
+
out = out.replace(/^ \* /gm, ' - ');
|
|
148
|
+
const stripAnsi = (s) => s.replace(/\x1b\[[0-9;]*m/g, '');
|
|
149
|
+
out = out.split('\n').filter(line => {
|
|
150
|
+
if (line === '')
|
|
151
|
+
return true;
|
|
152
|
+
return stripAnsi(line).trim().length > 0;
|
|
153
|
+
}).join('\n');
|
|
154
|
+
out = out.replace(/\n{3,}/g, '\n\n');
|
|
155
|
+
return out;
|
|
133
156
|
}
|
|
134
157
|
getSeverityIcon(severity) {
|
|
135
158
|
switch (severity.toLowerCase()) {
|
package/dist/index.js
CHANGED
|
@@ -284,7 +284,7 @@ async function main() {
|
|
|
284
284
|
.command('operator')
|
|
285
285
|
.alias('op')
|
|
286
286
|
.description('Start BMAD operator mode for infrastructure and system workflows')
|
|
287
|
-
.option('-m, --model <model>', 'Select operator model (code
|
|
287
|
+
.option('-m, --model <model>', 'Select operator model (code, agent, cloud)')
|
|
288
288
|
.option('-p, --project <path>', 'Set project context path')
|
|
289
289
|
.option('--new-project [name]', 'Create or use a managed local workspace folder when no --project path is given')
|
|
290
290
|
.option('--prompt <text>', 'Run a single operator prompt directly and exit')
|
package/dist/utils/api.js
CHANGED
|
@@ -2958,7 +2958,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2958
2958
|
workspace: { path: workspacePath },
|
|
2959
2959
|
workspace_path: workspacePath,
|
|
2960
2960
|
workspace_summary: workspaceSummary,
|
|
2961
|
-
model: this.resolveModelId(executionContext.model || 'code
|
|
2961
|
+
model: this.resolveModelId(executionContext.model || 'code'),
|
|
2962
2962
|
history: executionContext.history || [],
|
|
2963
2963
|
executionSurface: executionContext.executionSurface || 'cli',
|
|
2964
2964
|
clientSurface: executionContext.clientSurface || 'cli',
|
|
@@ -2969,7 +2969,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
2969
2969
|
rawPrompt: executionContext.rawPrompt || null,
|
|
2970
2970
|
requestStartedAt: executionContext.requestStartedAt,
|
|
2971
2971
|
},
|
|
2972
|
-
workflow_type: executionContext.workflowType || '
|
|
2972
|
+
workflow_type: executionContext.workflowType || 'full',
|
|
2973
2973
|
options: {
|
|
2974
2974
|
stream: true,
|
|
2975
2975
|
save_to_vigflow: executionContext.savePlanToVigFlow === true,
|