vigthoria-cli 1.11.11 → 1.11.12
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 +40 -4
- package/dist/utils/deckEvents.d.ts +17 -0
- package/dist/utils/deckEvents.js +35 -0
- package/package.json +1 -1
package/dist/commands/chat.js
CHANGED
|
@@ -15,6 +15,7 @@ import { buildPersonaOverlay, normalizePersonaMode } from '../utils/persona.js';
|
|
|
15
15
|
import { runAgentSessionMenu, shouldShowAgentSessionMenu } from './agent-session-menu.js';
|
|
16
16
|
import { createLiveOutcome, evaluateExecutorSuccess, handleTaskEvent, isSubstantiveAgentAnswer, isToolEvidenceStubAnswer, normalizeAgentAnswerContent, noteAnalysisToolUse, } from '../utils/agentRunOutcome.js';
|
|
17
17
|
import { looksLikeMarkdownReport, renderMarkdownToTerminal, summarizeMarkdownReport, } from '../utils/terminalMarkdown.js';
|
|
18
|
+
import { emitDeckEvent, isDeckModeEnabled } from '../utils/deckEvents.js';
|
|
18
19
|
const DEFAULT_V3_AGENT_TIMEOUT_MS = (() => {
|
|
19
20
|
const rawValue = process.env.VIGTHORIA_AGENT_TIMEOUT_MS || process.env.V3_AGENT_TIMEOUT_MS;
|
|
20
21
|
if (!rawValue) {
|
|
@@ -803,6 +804,11 @@ export class ChatCommand {
|
|
|
803
804
|
if (!isSubstantiveAgentAnswer(content)) {
|
|
804
805
|
return;
|
|
805
806
|
}
|
|
807
|
+
emitDeckEvent({ type: 'report_ready', markdown: content });
|
|
808
|
+
if (isDeckModeEnabled()) {
|
|
809
|
+
this.v3StreamedAnswerDisplayed = true;
|
|
810
|
+
return;
|
|
811
|
+
}
|
|
806
812
|
console.log('');
|
|
807
813
|
console.log(renderMarkdownToTerminal(content, this.getTerminalContentWidth()));
|
|
808
814
|
this.v3StreamedAnswerDisplayed = true;
|
|
@@ -875,6 +881,13 @@ export class ChatCommand {
|
|
|
875
881
|
}
|
|
876
882
|
this.v3SeenToolCalls.add(eventKey);
|
|
877
883
|
this.v3ToolCallCount += 1;
|
|
884
|
+
const toolName = event.name || event.tool || event.tool_name || '';
|
|
885
|
+
emitDeckEvent({
|
|
886
|
+
type: 'tool_start',
|
|
887
|
+
tool: toolName,
|
|
888
|
+
index: this.v3ToolCallCount,
|
|
889
|
+
target: event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '',
|
|
890
|
+
});
|
|
878
891
|
const toolDesc = this.describeV3AgentTool(event.tool || event.name || event.tool_name);
|
|
879
892
|
const toolTarget = event.arguments?.path || event.arguments?.file_path || event.arguments?.pattern || '';
|
|
880
893
|
const sanitizedTarget = this.sanitizeServerPath(String(toolTarget));
|
|
@@ -885,16 +898,16 @@ export class ChatCommand {
|
|
|
885
898
|
this.writeAgentActivityLine(this.fitTerminalText(stepLabel) + '\n');
|
|
886
899
|
// Show extra detail for key tools
|
|
887
900
|
const args = event.arguments || {};
|
|
888
|
-
const
|
|
889
|
-
if ((
|
|
901
|
+
const toolNameForDetail = event.name || event.tool || '';
|
|
902
|
+
if ((toolNameForDetail === 'write_file' || toolNameForDetail === 'edit_file') && typeof args.content === 'string') {
|
|
890
903
|
const len = args.content.length;
|
|
891
904
|
this.writeAgentActivityLine(chalk.gray(` ${len > 1000 ? Math.round(len / 1024) + ' KB' : len + ' bytes'} content\n`));
|
|
892
905
|
}
|
|
893
|
-
else if (
|
|
906
|
+
else if (toolNameForDetail === 'bash' && typeof args.command === 'string') {
|
|
894
907
|
const command = this.sanitizeServerPath(args.command);
|
|
895
908
|
this.writeAgentActivityLine(chalk.gray(` ${this.fitTerminalText(`$ ${command}`, 6)}\n`));
|
|
896
909
|
}
|
|
897
|
-
else if (
|
|
910
|
+
else if (toolNameForDetail === 'read_file') {
|
|
898
911
|
this.writeAgentActivityLine(chalk.gray(` ${this.fitTerminalText(`reading ${sanitizedTarget || 'file'}`, 6)}\n`));
|
|
899
912
|
}
|
|
900
913
|
spinner.text = `Running ${toolDesc}...`;
|
|
@@ -909,6 +922,12 @@ export class ChatCommand {
|
|
|
909
922
|
this.v3SeenToolResults.add(eventKey);
|
|
910
923
|
const success = event.success !== false;
|
|
911
924
|
const toolName = event.name || event.tool || '';
|
|
925
|
+
emitDeckEvent({
|
|
926
|
+
type: 'tool_end',
|
|
927
|
+
tool: toolName,
|
|
928
|
+
success,
|
|
929
|
+
index: this.v3ToolCallCount,
|
|
930
|
+
});
|
|
912
931
|
const indicator = success ? chalk.green(' ✓') : chalk.red(' ✗');
|
|
913
932
|
if (spinner.isSpinning)
|
|
914
933
|
spinner.stop();
|
|
@@ -981,6 +1000,13 @@ export class ChatCommand {
|
|
|
981
1000
|
if (spinner.isSpinning)
|
|
982
1001
|
spinner.stop();
|
|
983
1002
|
this.displayV3StreamedAnswer();
|
|
1003
|
+
emitDeckEvent({
|
|
1004
|
+
type: 'run_complete',
|
|
1005
|
+
success: true,
|
|
1006
|
+
tools: event.tool_calls || this.v3ToolCallCount,
|
|
1007
|
+
iterations: event.iterations || this.v3IterationCount,
|
|
1008
|
+
elapsed: event.elapsed || '',
|
|
1009
|
+
});
|
|
984
1010
|
let statLine = `${iters} iterations, ${tools} tool calls`;
|
|
985
1011
|
if (elapsed)
|
|
986
1012
|
statLine += `, ${elapsed}`;
|
|
@@ -2578,6 +2604,7 @@ export class ChatCommand {
|
|
|
2578
2604
|
this.v3StreamedAnswerDisplayed = false;
|
|
2579
2605
|
this.v3SeenToolCalls.clear();
|
|
2580
2606
|
this.v3SeenToolResults.clear();
|
|
2607
|
+
emitDeckEvent({ type: 'agent_start' });
|
|
2581
2608
|
const taskDisplay = new TaskDisplay(['Analyse workspace', 'Execute tasks', 'Validate output', 'Self-heal'], false);
|
|
2582
2609
|
taskDisplay.start(0);
|
|
2583
2610
|
const spinner = this.jsonOutput ? null : createSpinner({
|
|
@@ -3397,6 +3424,15 @@ export class ChatCommand {
|
|
|
3397
3424
|
*/
|
|
3398
3425
|
printAgentRunSummary(outcome, evaluation, changedFileCount) {
|
|
3399
3426
|
const executorSucceeded = evaluation.executorSucceeded;
|
|
3427
|
+
if (outcome.answerContent && isSubstantiveAgentAnswer(outcome.answerContent)) {
|
|
3428
|
+
const reportSummary = summarizeMarkdownReport(outcome.answerContent);
|
|
3429
|
+
emitDeckEvent({
|
|
3430
|
+
type: 'run_summary',
|
|
3431
|
+
success: executorSucceeded,
|
|
3432
|
+
title: reportSummary?.title || 'Agent run complete',
|
|
3433
|
+
sections: reportSummary?.sections || [],
|
|
3434
|
+
});
|
|
3435
|
+
}
|
|
3400
3436
|
const bar = chalk.gray('─'.repeat(63));
|
|
3401
3437
|
const ok = chalk.green('✓');
|
|
3402
3438
|
const warn = chalk.yellow('⚠');
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured events for Vigthoria Workbench (VIGTHORIA_DECK_MODE=1).
|
|
3
|
+
* Emitted as single lines: @vigthoria-deck:{json}
|
|
4
|
+
* Workbench strips these from terminal display and updates UI panels.
|
|
5
|
+
*/
|
|
6
|
+
export type DeckEventType = 'agent_start' | 'tool_start' | 'tool_end' | 'report_ready' | 'run_complete' | 'run_summary';
|
|
7
|
+
export interface DeckEvent {
|
|
8
|
+
type: DeckEventType;
|
|
9
|
+
ts: number;
|
|
10
|
+
[key: string]: unknown;
|
|
11
|
+
}
|
|
12
|
+
export declare function isDeckModeEnabled(): boolean;
|
|
13
|
+
export declare function emitDeckEvent(event: Omit<DeckEvent, 'ts'> & {
|
|
14
|
+
ts?: number;
|
|
15
|
+
}): void;
|
|
16
|
+
export declare function parseDeckLine(line: string): DeckEvent | null;
|
|
17
|
+
export declare function stripDeckLines(text: string): string;
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Structured events for Vigthoria Workbench (VIGTHORIA_DECK_MODE=1).
|
|
3
|
+
* Emitted as single lines: @vigthoria-deck:{json}
|
|
4
|
+
* Workbench strips these from terminal display and updates UI panels.
|
|
5
|
+
*/
|
|
6
|
+
const DECK_PREFIX = '@vigthoria-deck:';
|
|
7
|
+
export function isDeckModeEnabled() {
|
|
8
|
+
return /^(1|true|yes)$/i.test(String(process.env.VIGTHORIA_DECK_MODE || ''));
|
|
9
|
+
}
|
|
10
|
+
export function emitDeckEvent(event) {
|
|
11
|
+
if (!isDeckModeEnabled())
|
|
12
|
+
return;
|
|
13
|
+
const payload = {
|
|
14
|
+
...event,
|
|
15
|
+
ts: event.ts ?? Date.now(),
|
|
16
|
+
};
|
|
17
|
+
process.stdout.write(`${DECK_PREFIX}${JSON.stringify(payload)}\n`);
|
|
18
|
+
}
|
|
19
|
+
export function parseDeckLine(line) {
|
|
20
|
+
const trimmed = line.trim();
|
|
21
|
+
if (!trimmed.startsWith(DECK_PREFIX))
|
|
22
|
+
return null;
|
|
23
|
+
try {
|
|
24
|
+
return JSON.parse(trimmed.slice(DECK_PREFIX.length));
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export function stripDeckLines(text) {
|
|
31
|
+
return text
|
|
32
|
+
.split('\n')
|
|
33
|
+
.filter((line) => !line.trim().startsWith(DECK_PREFIX))
|
|
34
|
+
.join('\n');
|
|
35
|
+
}
|