vigthoria-cli 1.6.45 → 1.6.48

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.
@@ -150,8 +150,9 @@ export declare class ChatCommand {
150
150
  private resolveDirectModeCompletion;
151
151
  /**
152
152
  * Strip system-prompt echoes, tool execution headers, grounding-rule
153
- * parroting, and recovery banners from the model's final answer so that
154
- * --json output contains only the substantive answer.
153
+ * parroting, recovery banners, and multi-line tool output blocks from
154
+ * the model's final answer so that --json output contains only the
155
+ * substantive answer.
155
156
  */
156
157
  private sanitizeDirectModeOutput;
157
158
  private isDirectModeFollowUpQuestion;
@@ -678,7 +678,9 @@ class ChatCommand {
678
678
  return false;
679
679
  }
680
680
  async handleDirectPrompt(prompt) {
681
- if (!this.jsonOutput) {
681
+ // Suppress all setup banners in direct-prompt mode so only the final
682
+ // answer reaches stdout. Interactive (REPL) mode still shows them.
683
+ if (!this.jsonOutput && !this.directPromptMode) {
682
684
  console.log(chalk_1.default.cyan('Running single prompt in direct mode.'));
683
685
  console.log(chalk_1.default.gray(`Model: ${this.currentModel}`));
684
686
  console.log(chalk_1.default.gray(`Project: ${this.currentProjectPath}`));
@@ -1303,12 +1305,12 @@ class ChatCommand {
1303
1305
  tool: 'read_file',
1304
1306
  args: { path: targetFile },
1305
1307
  };
1306
- if (!this.jsonOutput) {
1308
+ if (!this.jsonOutput && !this.directPromptMode) {
1307
1309
  console.log(chalk_1.default.cyan(`⚙ Executing: ${readCall.tool}`));
1308
1310
  }
1309
1311
  const readResult = await this.tools.execute(readCall);
1310
1312
  const readSummary = this.formatToolResult(readCall, readResult);
1311
- if (!this.jsonOutput) {
1313
+ if (!this.jsonOutput && !this.directPromptMode) {
1312
1314
  console.log(readResult.success ? chalk_1.default.gray(readSummary) : chalk_1.default.red(readSummary));
1313
1315
  }
1314
1316
  this.messages.push({ role: 'system', content: readSummary });
@@ -1351,12 +1353,12 @@ class ChatCommand {
1351
1353
  content: rewrittenContent,
1352
1354
  },
1353
1355
  };
1354
- if (!this.jsonOutput) {
1356
+ if (!this.jsonOutput && !this.directPromptMode) {
1355
1357
  console.log(chalk_1.default.cyan(`⚙ Executing: ${writeCall.tool}`));
1356
1358
  }
1357
1359
  const writeResult = await this.tools.execute(writeCall);
1358
1360
  const writeSummary = this.formatToolResult(writeCall, writeResult);
1359
- if (!this.jsonOutput) {
1361
+ if (!this.jsonOutput && !this.directPromptMode) {
1360
1362
  console.log(writeResult.success ? chalk_1.default.gray(writeSummary) : chalk_1.default.red(writeSummary));
1361
1363
  }
1362
1364
  this.messages.push({ role: 'system', content: writeSummary });
@@ -1503,14 +1505,18 @@ class ChatCommand {
1503
1505
  }, null, 2));
1504
1506
  }
1505
1507
  else if (response.content) {
1506
- console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
1508
+ if (!this.directPromptMode) {
1509
+ console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
1510
+ }
1507
1511
  console.log(response.content);
1508
1512
  }
1509
1513
  else {
1510
- console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
1514
+ if (!this.directPromptMode) {
1515
+ console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'} via model ${routingPolicy.selectedModel}`));
1516
+ }
1511
1517
  console.log('V3 agent workflow completed.');
1512
1518
  }
1513
- if (!this.jsonOutput && previewGate?.required) {
1519
+ if (!this.jsonOutput && !this.directPromptMode && previewGate?.required) {
1514
1520
  if (previewGate.passed) {
1515
1521
  console.log(chalk_1.default.gray(`Template Service preview gate: passed via ${previewGate.backendUrl || 'unknown backend'}`));
1516
1522
  }
@@ -2165,48 +2171,78 @@ class ChatCommand {
2165
2171
  }
2166
2172
  /**
2167
2173
  * Strip system-prompt echoes, tool execution headers, grounding-rule
2168
- * parroting, and recovery banners from the model's final answer so that
2169
- * --json output contains only the substantive answer.
2174
+ * parroting, recovery banners, and multi-line tool output blocks from
2175
+ * the model's final answer so that --json output contains only the
2176
+ * substantive answer.
2170
2177
  */
2171
2178
  sanitizeDirectModeOutput(text) {
2172
- // Lines the model might echo verbatim from our system/continuation prompts
2179
+ let cleaned = text;
2180
+ // ── Phase 1: Strip entire multi-line tool-output blocks ──
2181
+ // Pattern: "Tool <name> succeeded/FAILED." followed by optional
2182
+ // metadata lines (File:, Search status:, Output:) and then a
2183
+ // content block until the next double-newline or end-of-string.
2184
+ cleaned = cleaned.replace(/Tool (?:read_file|grep|list_dir|glob|bash|write_file) (?:succeeded|FAILED)\.[\s\S]*?(?=\n\n[A-Z_]+:|$)/g, '');
2185
+ // Fallback: simpler block pattern for any remaining tool headers
2186
+ cleaned = cleaned.replace(/Tool (?:read_file|grep|list_dir|glob|bash|write_file) (?:succeeded|FAILED)\.[\s\S]*?(?:\n\n|\s*$)/g, '');
2187
+ // ── Phase 2: Strip echoed system-prompt / grounding lines ──
2173
2188
  const contaminationPatterns = [
2174
2189
  /^\[Agent recovered from backend failure[^\]]*\]\s*/m,
2175
2190
  /^Evidence gathered before backend failure:?\s*/m,
2176
- /^MANDATORY CROSS-FILE EVIDENCE \(computed from actual tool output[^)]*\):?\s*/m,
2177
- /^CONFIRMED CONFLICTING keys \(found in MULTIPLE files\):.*$/m,
2178
- /^Keys found ONLY in .+\(NOT in other files\):.*$/m,
2179
- /^CONSTRAINT: Your answer MUST list ONLY the keys from.*$/m,
2180
- /^GROUNDING CHECK:.*$/m,
2181
- /^VERIFICATION PROTOCOL for cross-file comparisons:.*$/m,
2182
- /^Quality gate: only \d+ discovery tool\(s\).*$/m,
2183
- /^Evidence collected: \d+ discovery.*$/m,
2184
- /^Warning: \d+ search tool call\(s\) failed\..*$/m,
2185
- /^Tool (?:read_file|grep|list_dir|glob|bash|write_file) (?:succeeded|FAILED)\.\s*/m,
2191
+ /^MANDATORY CROSS-FILE EVIDENCE[^\n]*\n?/m,
2192
+ /^CONFIRMED CONFLICTING keys[^\n]*/m,
2193
+ /^Keys found ONLY in [^\n]*/m,
2194
+ /^CONSTRAINT: Your answer MUST[^\n]*/m,
2195
+ /^GROUNDING CHECK:[^\n]*/m,
2196
+ /^VERIFICATION PROTOCOL[^\n]*/m,
2197
+ /^Quality gate:[^\n]*/m,
2198
+ /^Evidence collected:[^\n]*/m,
2199
+ /^Warning: \d+ search tool[^\n]*/m,
2200
+ /^Tool results received for direct mode[^\n]*/m,
2201
+ /^Original user request:[^\n]*/m,
2202
+ /^Project root boundary:[^\n]*/m,
2203
+ /^Do not declare success[^\n]*/m,
2204
+ /^Keep working from concrete[^\n]*/m,
2205
+ /^Because this is a debugging[^\n]*/m,
2206
+ /^If the request is already[^\n]*/m,
2207
+ /^If more work is required[^\n]*/m,
2208
+ /^Do not ask follow-up[^\n]*/m,
2209
+ /^CRITICAL GROUNDING RULE:[^\n]*/m,
2210
+ /^CROSS-FILE ATTRIBUTION:[^\n]*/m,
2211
+ /^EVIDENCE-GROUNDING RULE:[^\n]*/m,
2212
+ /^CROSS-FILE RULE:[^\n]*/m,
2213
+ /^OUTPUT DISCIPLINE:[^\n]*/m,
2186
2214
  /^File: \S+\s*$/m,
2187
2215
  /^Search status: \S+\s*$/m,
2188
2216
  /^Output:\s*$/m,
2189
- /^Tool results received for direct mode step \d+\.\s*$/m,
2190
- /^Original user request:.*$/m,
2191
- /^Project root boundary:.*$/m,
2192
- /^Do not declare success until.*$/m,
2193
- /^Keep working from concrete tool results\.\s*$/m,
2194
- /^Because this is a debugging task.*$/m,
2195
- /^If the request is already satisfied.*$/m,
2196
- /^If more work is required.*$/m,
2197
- /^Do not ask follow-up questions.*$/m,
2198
- /^CRITICAL GROUNDING RULE:.*$/m,
2199
- /^CROSS-FILE ATTRIBUTION:.*$/m,
2200
- /^EVIDENCE-GROUNDING RULE:.*$/m,
2201
- /^CROSS-FILE RULE:.*$/m,
2202
2217
  /^\[\.\.\. ?truncated\]\s*$/m,
2203
2218
  /^---\s*$/m,
2204
2219
  ];
2205
- let cleaned = text;
2206
2220
  for (const pat of contaminationPatterns) {
2207
2221
  cleaned = cleaned.replace(pat, '');
2208
2222
  }
2209
- // Collapse multiple blank lines left after stripping
2223
+ // ── Phase 3: Paragraph-level filter ──
2224
+ // Split into paragraph blocks and discard any that are pure tool
2225
+ // output, file content dumps, or system-instruction echoes.
2226
+ const paragraphs = cleaned.split(/\n\n+/);
2227
+ const kept = paragraphs.filter(p => {
2228
+ const t = p.trim();
2229
+ if (!t)
2230
+ return false;
2231
+ // Discard lingering tool headers
2232
+ if (/^Tool (?:read_file|grep|list_dir|glob|bash|write_file) /i.test(t))
2233
+ return false;
2234
+ // Discard paragraphs that are mostly file-content dumps (many
2235
+ // lines of code with typical code tokens like { } ; = function class)
2236
+ const lines = t.split('\n');
2237
+ if (lines.length > 6) {
2238
+ const codeLines = lines.filter(l => /[{};=]|function |class |const |let |var |import |export |switch |case /.test(l));
2239
+ if (codeLines.length / lines.length > 0.4)
2240
+ return false;
2241
+ }
2242
+ return true;
2243
+ });
2244
+ cleaned = kept.join('\n\n');
2245
+ // Collapse multiple blank lines
2210
2246
  cleaned = cleaned.replace(/\n{3,}/g, '\n\n').trim();
2211
2247
  return cleaned || text;
2212
2248
  }
@@ -2294,8 +2330,11 @@ class ChatCommand {
2294
2330
  if (!this.tools) {
2295
2331
  throw new Error('Agent tools are not initialized.');
2296
2332
  }
2333
+ // In direct-prompt mode (--prompt), suppress verbose tool output so
2334
+ // only the final answer prints. In interactive mode, show full detail.
2335
+ const verbose = !this.jsonOutput && !this.directPromptMode;
2297
2336
  for (const call of toolCalls) {
2298
- if (!this.jsonOutput) {
2337
+ if (verbose) {
2299
2338
  console.log(chalk_1.default.cyan(`⚙ Executing: ${call.tool}`));
2300
2339
  }
2301
2340
  (0, bridge_client_js_1.getBridgeClient)()?.emitToolCall({ tool: call.tool, args: call.args });
@@ -2303,7 +2342,7 @@ class ChatCommand {
2303
2342
  // Phase 2: If a search tool failed (search_failed), retry with alternate approach
2304
2343
  const searchStatus = result.metadata?.searchStatus;
2305
2344
  if (call.tool === 'grep' && searchStatus === 'search_failed') {
2306
- if (!this.jsonOutput) {
2345
+ if (verbose) {
2307
2346
  console.log(chalk_1.default.yellow(`⚠ Search backend failed, retrying with alternate method...`));
2308
2347
  }
2309
2348
  // Force Node-native fallback by re-executing with a note
@@ -2316,7 +2355,7 @@ class ChatCommand {
2316
2355
  }
2317
2356
  }
2318
2357
  const summary = this.formatToolResult(call, result);
2319
- if (!this.jsonOutput) {
2358
+ if (verbose) {
2320
2359
  console.log(result.success ? chalk_1.default.gray(summary) : chalk_1.default.red(summary));
2321
2360
  }
2322
2361
  this.messages.push({ role: 'system', content: summary });
package/dist/index.js CHANGED
@@ -155,6 +155,7 @@ async function main() {
155
155
  const invokedBinaryName = getInvokedBinaryName();
156
156
  const firstArg = process.argv[2];
157
157
  const jsonOutputRequested = process.argv.includes('--json');
158
+ const directPromptRequested = process.argv.includes('--prompt') || process.argv.includes('-P');
158
159
  if (invokedBinaryName === 'vigthoria-chat') {
159
160
  const knownCommands = new Set([
160
161
  'chat', 'chat-resume', 'agent', 'edit', 'generate', 'explain', 'fix', 'review',
@@ -172,7 +173,7 @@ async function main() {
172
173
  // Calculate padding for centering
173
174
  const titlePad = Math.floor((boxWidth - 4 - titleText.length) / 2);
174
175
  const versionPad = Math.floor((boxWidth - 4 - versionText.length) / 2);
175
- if (process.env.VIGTHORIA_NO_BANNER !== '1' && !jsonOutputRequested) {
176
+ if (process.env.VIGTHORIA_NO_BANNER !== '1' && !jsonOutputRequested && !directPromptRequested) {
176
177
  console.log(chalk_1.default.cyan(logger_js_1.CH.dTl + logger_js_1.CH.dH.repeat(boxWidth) + logger_js_1.CH.dTr));
177
178
  console.log(chalk_1.default.cyan(logger_js_1.CH.dV + ' '.repeat(boxWidth) + logger_js_1.CH.dV));
178
179
  console.log(chalk_1.default.cyan(logger_js_1.CH.dV) + ' '.repeat(titlePad) + chalk_1.default.bold.white('VIGTHORIA CLI') + chalk_1.default.cyan(' - AI-Powered Coding Assistant') + ' '.repeat(boxWidth - titlePad - titleText.length) + chalk_1.default.cyan(logger_js_1.CH.dV));
@@ -182,7 +183,7 @@ async function main() {
182
183
  console.log();
183
184
  }
184
185
  // Check for updates in background (don't wait)
185
- if (process.env.VIGTHORIA_NO_UPDATE_CHECK !== '1' && !jsonOutputRequested) {
186
+ if (process.env.VIGTHORIA_NO_UPDATE_CHECK !== '1' && !jsonOutputRequested && !directPromptRequested) {
186
187
  checkForUpdatesQuietly();
187
188
  }
188
189
  program
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vigthoria-cli",
3
- "version": "1.6.45",
3
+ "version": "1.6.48",
4
4
  "description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
5
5
  "main": "dist/index.js",
6
6
  "files": [