vigthoria-cli 1.11.5 → 1.11.6
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.d.ts +2 -0
- package/dist/commands/chat.js +31 -2
- package/dist/utils/api.js +42 -9
- package/package.json +1 -1
package/dist/commands/chat.d.ts
CHANGED
|
@@ -63,6 +63,8 @@ export declare class ChatCommand {
|
|
|
63
63
|
private getDefaultChatModel;
|
|
64
64
|
private resolveInitialModel;
|
|
65
65
|
private isLegacyAgentFallbackAllowed;
|
|
66
|
+
private shouldRescueFailedAnalysis;
|
|
67
|
+
private tryAnalysisLocalRescue;
|
|
66
68
|
private resolveAgentExecutionPolicy;
|
|
67
69
|
private getMessagesForModel;
|
|
68
70
|
private getActivePersonaMode;
|
package/dist/commands/chat.js
CHANGED
|
@@ -259,6 +259,28 @@ export class ChatCommand {
|
|
|
259
259
|
// Operators can still opt in during emergency local debugging.
|
|
260
260
|
return process.env.VIGTHORIA_ALLOW_LEGACY_AGENT_FALLBACK === '1';
|
|
261
261
|
}
|
|
262
|
+
shouldRescueFailedAnalysis() {
|
|
263
|
+
return process.env.VIGTHORIA_DISABLE_ANALYSIS_RESCUE !== '1';
|
|
264
|
+
}
|
|
265
|
+
async tryAnalysisLocalRescue(prompt, workspacePath) {
|
|
266
|
+
if (!this.shouldRescueFailedAnalysis() || !this.tools) {
|
|
267
|
+
return false;
|
|
268
|
+
}
|
|
269
|
+
const clientToolErrors = this.api.getClientToolErrors();
|
|
270
|
+
if (clientToolErrors.some((err) => /could not accept the result|client tool bridge failed/i.test(err))) {
|
|
271
|
+
return false;
|
|
272
|
+
}
|
|
273
|
+
console.log('');
|
|
274
|
+
console.log(chalk.yellow('V3 analysis did not produce a grounded answer — retrying with local workspace tools...'));
|
|
275
|
+
console.log(chalk.gray(`Workspace: ${workspacePath}`));
|
|
276
|
+
console.log('');
|
|
277
|
+
const last = this.messages[this.messages.length - 1];
|
|
278
|
+
if (last?.role === 'assistant') {
|
|
279
|
+
this.messages.pop();
|
|
280
|
+
}
|
|
281
|
+
await this.runLocalAgentLoop(prompt);
|
|
282
|
+
return true;
|
|
283
|
+
}
|
|
262
284
|
resolveAgentExecutionPolicy(prompt) {
|
|
263
285
|
const explicitModel = this.modelExplicitlySelected;
|
|
264
286
|
const heavyTask = this.config.isComplexTask(prompt);
|
|
@@ -2744,7 +2766,14 @@ export class ChatCommand {
|
|
|
2744
2766
|
let selfHealStatus = null;
|
|
2745
2767
|
let selfHealTool = null;
|
|
2746
2768
|
const runEvaluation = evaluateExecutorSuccess(liveOutcome);
|
|
2747
|
-
|
|
2769
|
+
let executorSucceeded = runEvaluation.executorSucceeded;
|
|
2770
|
+
if (!executorSucceeded && !requiresWorkspaceChanges && !this.jsonOutput) {
|
|
2771
|
+
const rescued = await this.tryAnalysisLocalRescue(prompt, workspacePath);
|
|
2772
|
+
if (rescued) {
|
|
2773
|
+
watcher?.stop();
|
|
2774
|
+
return true;
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2748
2777
|
if (!executorSucceeded && requiresWorkspaceChanges && changedFileCount === 0 && !liveOutcome.executorError) {
|
|
2749
2778
|
const clientToolErrors = this.api.getClientToolErrors();
|
|
2750
2779
|
const transportErrors = this.api.getLastChatTransportErrors();
|
|
@@ -2839,7 +2868,7 @@ export class ChatCommand {
|
|
|
2839
2868
|
clientToolErrors: this.api.getClientToolErrors(),
|
|
2840
2869
|
transportErrors: this.api.getLastChatTransportErrors(),
|
|
2841
2870
|
workspacePath: workspacePath || null,
|
|
2842
|
-
workspaceSyncIssue: (!executorSucceeded && workspaceHasOutput && changedFileCount === 0)
|
|
2871
|
+
workspaceSyncIssue: (!executorSucceeded && requiresWorkspaceChanges && workspaceHasOutput && changedFileCount === 0)
|
|
2843
2872
|
? 'Local workspace has files but the agent did not confirm tracked changes.'
|
|
2844
2873
|
: null,
|
|
2845
2874
|
finishedAt: Date.now(),
|
package/dist/utils/api.js
CHANGED
|
@@ -2745,9 +2745,10 @@ menu {
|
|
|
2745
2745
|
.map((entry) => `${entry.isDirectory() ? '[DIR] ' : ''}${entry.name}`);
|
|
2746
2746
|
return { success: true, output: entries.join('\n') || '(empty)' };
|
|
2747
2747
|
}
|
|
2748
|
-
if (name === 'glob' || name === 'search_files') {
|
|
2748
|
+
if (name === 'glob' || name === 'search_files' || name === 'grep') {
|
|
2749
2749
|
const pattern = String(args.pattern || args.query || '').toLowerCase();
|
|
2750
2750
|
const files = [];
|
|
2751
|
+
const matches = [];
|
|
2751
2752
|
const walk = (dir) => {
|
|
2752
2753
|
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
2753
2754
|
if (['node_modules', '.git'].includes(entry.name))
|
|
@@ -2758,18 +2759,30 @@ menu {
|
|
|
2758
2759
|
continue;
|
|
2759
2760
|
}
|
|
2760
2761
|
const relative = path.relative(rootPath, absolute).replace(/\\/g, '/');
|
|
2761
|
-
if (
|
|
2762
|
-
|
|
2763
|
-
}
|
|
2764
|
-
else if (name === 'search_files') {
|
|
2765
|
-
const content = fs.readFileSync(absolute, 'utf8');
|
|
2766
|
-
if (content.toLowerCase().includes(pattern))
|
|
2762
|
+
if (name === 'glob' && pattern) {
|
|
2763
|
+
if (!pattern || relative.toLowerCase().includes(pattern.replace(/\*/g, ''))) {
|
|
2767
2764
|
files.push(relative);
|
|
2765
|
+
}
|
|
2766
|
+
}
|
|
2767
|
+
else if (pattern) {
|
|
2768
|
+
try {
|
|
2769
|
+
const content = fs.readFileSync(absolute, 'utf8');
|
|
2770
|
+
if (relative.toLowerCase().includes(pattern.replace(/\*/g, '')) || content.toLowerCase().includes(pattern)) {
|
|
2771
|
+
matches.push(`${relative}: ${content.split('\n').find((line) => line.toLowerCase().includes(pattern))?.trim() || '(match)'}`);
|
|
2772
|
+
}
|
|
2773
|
+
}
|
|
2774
|
+
catch {
|
|
2775
|
+
// skip unreadable/binary files
|
|
2776
|
+
}
|
|
2768
2777
|
}
|
|
2769
2778
|
}
|
|
2770
2779
|
};
|
|
2771
|
-
|
|
2772
|
-
|
|
2780
|
+
const searchRoot = fs.statSync(target.absolutePath).isDirectory() ? target.absolutePath : rootPath;
|
|
2781
|
+
walk(searchRoot);
|
|
2782
|
+
if (name === 'glob') {
|
|
2783
|
+
return { success: true, output: files.slice(0, 200).join('\n') || '(no matches)' };
|
|
2784
|
+
}
|
|
2785
|
+
return { success: true, output: matches.slice(0, 100).join('\n') || '(no matches)' };
|
|
2773
2786
|
}
|
|
2774
2787
|
if (name === 'syntax_check') {
|
|
2775
2788
|
const content = fs.readFileSync(target.absolutePath, 'utf8');
|
|
@@ -2805,8 +2818,27 @@ menu {
|
|
|
2805
2818
|
if (!contextId || !callId)
|
|
2806
2819
|
return;
|
|
2807
2820
|
const backendUrl = responseUrl ? new URL(responseUrl).origin : (context.mcpContextBackendUrl || null);
|
|
2821
|
+
const emitStream = (streamEvent) => {
|
|
2822
|
+
if (typeof context.onStreamEvent === 'function') {
|
|
2823
|
+
try {
|
|
2824
|
+
context.onStreamEvent(streamEvent);
|
|
2825
|
+
}
|
|
2826
|
+
catch {
|
|
2827
|
+
// UI callbacks must never break the client tool bridge.
|
|
2828
|
+
}
|
|
2829
|
+
}
|
|
2830
|
+
};
|
|
2831
|
+
emitStream({ type: 'tool_call', name: toolName, tool: toolName, arguments: event.arguments || {} });
|
|
2808
2832
|
try {
|
|
2809
2833
|
const result = await this.executeV3ClientToolRequest(event, context);
|
|
2834
|
+
emitStream({
|
|
2835
|
+
type: 'tool_result',
|
|
2836
|
+
name: toolName,
|
|
2837
|
+
tool: toolName,
|
|
2838
|
+
success: result.success,
|
|
2839
|
+
output: result.output,
|
|
2840
|
+
error: result.error || '',
|
|
2841
|
+
});
|
|
2810
2842
|
try {
|
|
2811
2843
|
await this.submitClientToolResult(contextId, callId, result, backendUrl);
|
|
2812
2844
|
}
|
|
@@ -3646,6 +3678,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3646
3678
|
// Exit stream early on complete — agent is done; server-side teardown
|
|
3647
3679
|
// can hold the connection open for many seconds otherwise.
|
|
3648
3680
|
if (event.type === 'complete') {
|
|
3681
|
+
await Promise.allSettled([...this.pendingV3ClientToolTasks]);
|
|
3649
3682
|
reader.cancel().catch(() => { });
|
|
3650
3683
|
return {
|
|
3651
3684
|
task_id: events.find((entry) => entry && entry.task_id)?.task_id || null,
|