vigthoria-cli 1.11.2 → 1.11.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.
@@ -15,5 +15,6 @@ export declare class BackgroundCommand {
15
15
  status(jobId: string, options?: BackgroundOptions): Promise<void>;
16
16
  apply(jobId: string, options?: BackgroundOptions): Promise<void>;
17
17
  cancel(jobId: string, options?: BackgroundOptions): Promise<void>;
18
+ private extractBackgroundOutcome;
18
19
  }
19
20
  export {};
@@ -82,8 +82,9 @@ export class BackgroundCommand {
82
82
  try {
83
83
  const job = await this.api.getV3BackgroundJob(jobId);
84
84
  spinner.stop();
85
+ const outcome = this.extractBackgroundOutcome(job);
85
86
  if (options.json) {
86
- console.log(JSON.stringify(job, null, 2));
87
+ console.log(JSON.stringify({ ...job, outcomeTruth: outcome }, null, 2));
87
88
  return;
88
89
  }
89
90
  console.log(chalk.bold(`\nBackground Job ${chalk.cyan(job.job_id)}\n`));
@@ -91,6 +92,12 @@ export class BackgroundCommand {
91
92
  console.log(`Files: ${job.file_count || 0}`);
92
93
  console.log(`Updated: ${job.updated_at || '-'}`);
93
94
  console.log(`Workspace: ${job.local_workspace_path || job.workspace_name || '-'}`);
95
+ if (outcome.tasksTotal > 0 || outcome.tasksCompleted > 0) {
96
+ console.log(`Tasks: ${outcome.tasksCompleted}/${outcome.tasksTotal}${outcome.success === true ? chalk.green(' (complete)') : outcome.success === false ? chalk.red(' (incomplete)') : ''}`);
97
+ }
98
+ if (outcome.headline) {
99
+ console.log(chalk.gray(`Outcome: ${outcome.headline}`));
100
+ }
94
101
  if (job.error)
95
102
  console.log(chalk.red(`Error: ${job.error}`));
96
103
  console.log(chalk.gray(`\n${String(job.request || '').slice(0, 500)}`));
@@ -157,4 +164,51 @@ export class BackgroundCommand {
157
164
  this.logger.error(error?.message || String(error));
158
165
  }
159
166
  }
167
+ extractBackgroundOutcome(job) {
168
+ const result = (job?.result && typeof job.result === 'object') ? job.result : {};
169
+ const events = Array.isArray(job?.events) ? job.events : [];
170
+ let tasksCompleted = Number(result.tasks_completed ?? result.tasksCompleted ?? 0);
171
+ let tasksTotal = Number(result.tasks_total ?? result.tasksTotal ?? 0);
172
+ let success = typeof result.success === 'boolean' ? result.success : null;
173
+ for (const event of events) {
174
+ if (!event || typeof event !== 'object')
175
+ continue;
176
+ if (event.type === 'result' || event.event === 'result') {
177
+ const payload = event.data || event.payload || event;
178
+ if (payload && typeof payload === 'object') {
179
+ if (payload.tasks_completed != null)
180
+ tasksCompleted = Number(payload.tasks_completed);
181
+ if (payload.tasksCompleted != null)
182
+ tasksCompleted = Number(payload.tasksCompleted);
183
+ if (payload.tasks_total != null)
184
+ tasksTotal = Number(payload.tasks_total);
185
+ if (payload.tasksTotal != null)
186
+ tasksTotal = Number(payload.tasksTotal);
187
+ if (typeof payload.success === 'boolean')
188
+ success = payload.success;
189
+ }
190
+ }
191
+ }
192
+ if (success == null && tasksTotal > 0) {
193
+ success = tasksCompleted >= tasksTotal;
194
+ }
195
+ if (success == null && job?.status === 'completed') {
196
+ success = true;
197
+ }
198
+ if (success == null && job?.status === 'failed') {
199
+ success = false;
200
+ }
201
+ let headline = '';
202
+ if (tasksTotal > 0) {
203
+ headline = success === true
204
+ ? `All ${tasksTotal} task(s) completed`
205
+ : success === false
206
+ ? `${tasksCompleted}/${tasksTotal} task(s) completed`
207
+ : `${tasksCompleted}/${tasksTotal} task(s) reported`;
208
+ }
209
+ else if (typeof result.message === 'string' && result.message.trim()) {
210
+ headline = result.message.trim();
211
+ }
212
+ return { tasksCompleted, tasksTotal, success, headline };
213
+ }
160
214
  }
@@ -17,6 +17,8 @@ interface ChatOptions {
17
17
  json?: boolean;
18
18
  bridge?: string;
19
19
  grant?: boolean;
20
+ retry?: boolean;
21
+ continue?: boolean;
20
22
  }
21
23
  export declare class ChatCommand {
22
24
  private config;
@@ -477,6 +477,10 @@ export class ChatCommand {
477
477
  */
478
478
  isOperatorDirectAnswerable(prompt) {
479
479
  const trimmed = prompt.trim();
480
+ // Infrastructure status pings are never repo-grounded analysis.
481
+ if (/^(status(\s+check)?|health(\s+check)?|ping)$/i.test(trimmed)) {
482
+ return true;
483
+ }
480
484
  // ── Exclusion guard: any prompt that references code artefacts,
481
485
  // file paths, or analysis verbs MUST go through a tool-backed path
482
486
  // (BMAD or agent loop), never the toolless direct-answer shortcut.
@@ -711,6 +715,9 @@ export class ChatCommand {
711
715
  }
712
716
  }
713
717
  writeV3StreamText(spinner, text) {
718
+ if (this.jsonOutput) {
719
+ return;
720
+ }
714
721
  const safeText = this.sanitizeV3VisibleStreamText(this.sanitizeServerPath(text));
715
722
  if (!safeText) {
716
723
  return;
@@ -1137,14 +1144,14 @@ export class ChatCommand {
1137
1144
  }
1138
1145
  console.log(chalk.green(`Using workspace: ${this.currentProjectPath}`));
1139
1146
  }
1140
- if (this.jsonOutput && !options.prompt) {
1141
- throw new Error('--json is only supported together with --prompt.');
1147
+ if (this.jsonOutput && !options.prompt && !options.retry && !options.continue) {
1148
+ throw new Error('--json is only supported together with --prompt, --retry, or --continue.');
1142
1149
  }
1143
1150
  this.ensureProjectWorkspace();
1144
1151
  this.directPromptMode = Boolean(options.prompt);
1145
1152
  this.directToolContinuationCount = 0;
1146
1153
  this.tools = new AgenticTools(this.logger, this.currentProjectPath, async (action) => this.requestPermission(action), this.autoApprove);
1147
- this.initializeSession(options.resume === true);
1154
+ this.initializeSession(options.resume === true || options.retry === true || options.continue === true);
1148
1155
  // ── Commando Bridge: connect if --bridge was specified ──────────
1149
1156
  if (options.bridge) {
1150
1157
  const bridgeClient = new BridgeClient({
@@ -1169,6 +1176,18 @@ export class ChatCommand {
1169
1176
  this.logger.error(this.operatorAccessMessage());
1170
1177
  return;
1171
1178
  }
1179
+ if (options.retry || options.continue) {
1180
+ if (!this.agentMode) {
1181
+ throw new Error('--retry and --continue require agent mode.');
1182
+ }
1183
+ const followUp = options.retry ? this.buildRetryPrompt() : this.buildContinuePrompt();
1184
+ if (!followUp) {
1185
+ throw new Error('No previous agent run to retry or continue. Run an agent prompt first with the same --project, or use --resume.');
1186
+ }
1187
+ this.directPromptMode = true;
1188
+ await this.runAgentTurn(followUp);
1189
+ return;
1190
+ }
1172
1191
  if (options.prompt) {
1173
1192
  const bridgePromptTimeoutMs = (() => {
1174
1193
  const rawValue = process.env.VIGTHORIA_BRIDGE_PROMPT_TIMEOUT_MS || process.env.V3_BRIDGE_PROMPT_TIMEOUT_MS;
@@ -1404,6 +1423,9 @@ export class ChatCommand {
1404
1423
  this.agentMode = this.currentSession.agentMode || this.agentMode;
1405
1424
  this.operatorMode = this.currentSession.operatorMode || this.operatorMode;
1406
1425
  this.currentModel = this.currentSession.model || this.currentModel;
1426
+ if (this.currentSession.lastAgentRunOutcome) {
1427
+ this.lastAgentRunOutcome = this.currentSession.lastAgentRunOutcome;
1428
+ }
1407
1429
  return;
1408
1430
  }
1409
1431
  }
@@ -4150,6 +4172,7 @@ export class ChatCommand {
4150
4172
  this.currentSession.agentMode = this.agentMode;
4151
4173
  this.currentSession.operatorMode = this.operatorMode;
4152
4174
  this.currentSession.messages = [...this.messages];
4175
+ this.currentSession.lastAgentRunOutcome = this.lastAgentRunOutcome;
4153
4176
  this.currentSession = this.sessionManager.compactInMemory(this.currentSession);
4154
4177
  this.messages = [...this.currentSession.messages];
4155
4178
  this.sessionManager.save(this.currentSession);
package/dist/index.js CHANGED
@@ -614,6 +614,8 @@ export async function main(args) {
614
614
  .option('--prompt <text>', 'Run a single agent prompt directly and exit')
615
615
  .option('-w, --workflow <selector>', 'Run the prompt through a named or explicit VigFlow workflow target')
616
616
  .option('--json', 'Emit machine-readable JSON output for direct prompt runs', false)
617
+ .option('--retry', 'Retry failed tasks from the last agent run in this workspace session', false)
618
+ .option('--continue', 'Continue unfinished tasks from the last agent run in this workspace session', false)
617
619
  .option('--auto-approve', 'Auto-approve all actions (dangerous!)', false)
618
620
  .option('--bridge <url>', 'Connect to Vigthoria Commando Bridge for remote admin observability')
619
621
  .action(async (options) => {
@@ -630,6 +632,8 @@ export async function main(args) {
630
632
  autoApprove: options.autoApprove,
631
633
  prompt: options.prompt,
632
634
  bridge: options.bridge,
635
+ retry: options.retry,
636
+ continue: options.continue,
633
637
  });
634
638
  });
635
639
  program
package/dist/utils/api.js CHANGED
@@ -1648,6 +1648,8 @@ export class APIClient {
1648
1648
  const serverWorkspacePath = this.resolveServerBindableWorkspacePath(resolvedContext);
1649
1649
  const localWorkspaceName = this.getDisplayWorkspaceName(targetPath);
1650
1650
  const localWorkspaceRef = localWorkspaceName ? `vigthoria://local-workspace/${localWorkspaceName}` : null;
1651
+ const rawBrain = resolvedContext.vigthoriaBrain || resolvedContext.vigthoria_brain || null;
1652
+ const dedupedBrain = rawBrain ? this.dedupeBrainPayload(rawBrain) : null;
1651
1653
  return JSON.stringify({
1652
1654
  workspace: this.buildPublicWorkspaceDescriptor(resolvedContext.workspace, {
1653
1655
  localWorkspacePath: targetPath,
@@ -1681,8 +1683,8 @@ export class APIClient {
1681
1683
  contextId: resolvedContext.contextId,
1682
1684
  traceId: resolvedContext.traceId,
1683
1685
  requestStartedAt: resolvedContext.requestStartedAt,
1684
- vigthoriaBrain: resolvedContext.vigthoriaBrain || null,
1685
- vigthoria_brain: resolvedContext.vigthoriaBrain || null,
1686
+ vigthoriaBrain: dedupedBrain,
1687
+ vigthoria_brain: dedupedBrain,
1686
1688
  });
1687
1689
  }
1688
1690
  extractEmergencyAppName(message = '', fallback = 'Signal Desk') {
@@ -46,6 +46,7 @@ export interface Session {
46
46
  updatedAt: string;
47
47
  agentMode: boolean;
48
48
  operatorMode?: boolean;
49
+ lastAgentRunOutcome?: Record<string, unknown> | null;
49
50
  }
50
51
  export declare class SessionManager {
51
52
  private sessionsDir;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.11.2",
3
+ "version": "1.11.3",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -76,7 +76,7 @@ $CLI hyper-loop status >/tmp/vig-hyperloop.txt
76
76
  $CLI devtools connect >/tmp/vig-devtools.txt
77
77
 
78
78
  echo "[6.11] operator flow"
79
- $CLI operator --prompt "status check" --json >/tmp/vig-operator.json
79
+ $CLI operator --prompt "reply with exactly: OK" --json >/tmp/vig-operator.json
80
80
  python3 - << 'PY'
81
81
  import json
82
82
  j=json.load(open('/tmp/vig-operator.json'))