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.
@@ -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 toolName = event.name || event.tool || '';
889
- if ((toolName === 'write_file' || toolName === 'edit_file') && typeof args.content === 'string') {
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 (toolName === 'bash' && typeof args.command === 'string') {
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 (toolName === 'read_file') {
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
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.11.11",
3
+ "version": "1.11.12",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",