vigthoria-cli 1.11.7 → 1.11.8
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
CHANGED
|
@@ -64,6 +64,7 @@ export declare class ChatCommand {
|
|
|
64
64
|
private resolveInitialModel;
|
|
65
65
|
private isLegacyAgentFallbackAllowed;
|
|
66
66
|
private shouldRescueFailedAnalysis;
|
|
67
|
+
private isDeepAnalysisPrompt;
|
|
67
68
|
private tryAnalysisLocalRescue;
|
|
68
69
|
private resolveAgentExecutionPolicy;
|
|
69
70
|
private getMessagesForModel;
|
package/dist/commands/chat.js
CHANGED
|
@@ -262,6 +262,10 @@ export class ChatCommand {
|
|
|
262
262
|
shouldRescueFailedAnalysis() {
|
|
263
263
|
return process.env.VIGTHORIA_DISABLE_ANALYSIS_RESCUE !== '1';
|
|
264
264
|
}
|
|
265
|
+
isDeepAnalysisPrompt(prompt) {
|
|
266
|
+
return /\b(deep|deeper|full|complete|thorough|systematic|architecture|architectural)\s+(analyse|analyze|analysis|review|dive|scan)\b/i.test(prompt)
|
|
267
|
+
|| /\b(analyse|analyze|analysis|review)\b[\s\S]{0,40}\b(deep|deeper|full|complete|thorough|systematic|architecture|architectural)\b/i.test(prompt);
|
|
268
|
+
}
|
|
265
269
|
async tryAnalysisLocalRescue(prompt, workspacePath) {
|
|
266
270
|
if (!this.shouldRescueFailedAnalysis() || !this.tools) {
|
|
267
271
|
return false;
|
|
@@ -784,6 +788,9 @@ export class ChatCommand {
|
|
|
784
788
|
.replace(/^\s*(?:list_dir|read_file|write_file|edit_file|glob|grep|bash)\s*$/gim, '')
|
|
785
789
|
.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, '')
|
|
786
790
|
.replace(/<tool_code>[\s\S]*?<\/tool_code>/gi, '')
|
|
791
|
+
.replace(/<read_file>\s*<path>[\s\S]*?<\/path>\s*<\/read_file>/gi, '')
|
|
792
|
+
.replace(/<(?:grep|list_directory|search_files|glob|tool_result)\b[\s\S]*?<\/(?:grep|list_directory|search_files|glob|tool_result)>/gi, '')
|
|
793
|
+
.replace(/bootstrap discovery completed\s*[—-]\s*inspect the most relevant files next\.?/gi, '')
|
|
787
794
|
.replace(/\n{3,}/g, '\n\n');
|
|
788
795
|
return output;
|
|
789
796
|
}
|
|
@@ -1988,6 +1995,7 @@ export class ChatCommand {
|
|
|
1988
1995
|
buildLocalLoopLiveOutcome(prompt) {
|
|
1989
1996
|
const liveOutcome = createLiveOutcome();
|
|
1990
1997
|
liveOutcome.requiresWorkspaceChanges = this.taskRequiresWorkspaceChanges(prompt);
|
|
1998
|
+
liveOutcome.deepAnalysisRequired = this.isDeepAnalysisPrompt(prompt);
|
|
1991
1999
|
liveOutcome.analysisToolsUsed = this.agentToolEvidence.discovery;
|
|
1992
2000
|
liveOutcome.changedFileCount = this.agentToolEvidence.mutation;
|
|
1993
2001
|
liveOutcome.workspaceHasOutput = this.agentToolEvidence.mutation > 0;
|
|
@@ -2514,6 +2522,7 @@ export class ChatCommand {
|
|
|
2514
2522
|
qualityMissing: [],
|
|
2515
2523
|
qualityBlockers: [],
|
|
2516
2524
|
};
|
|
2525
|
+
liveOutcome.deepAnalysisRequired = this.isDeepAnalysisPrompt(prompt);
|
|
2517
2526
|
const parsePlannerSummary = (raw) => {
|
|
2518
2527
|
if (!raw || typeof raw !== 'string')
|
|
2519
2528
|
return;
|
|
@@ -2648,6 +2657,12 @@ export class ChatCommand {
|
|
|
2648
2657
|
if (Number(event.discovery_tools_used) > 0) {
|
|
2649
2658
|
liveOutcome.analysisToolsUsed = Math.max(liveOutcome.analysisToolsUsed, Number(event.discovery_tools_used));
|
|
2650
2659
|
}
|
|
2660
|
+
if (Number(event.discovery_read_files) > 0) {
|
|
2661
|
+
liveOutcome.analysisReadToolsUsed = Math.max(liveOutcome.analysisReadToolsUsed, Number(event.discovery_read_files));
|
|
2662
|
+
}
|
|
2663
|
+
if (event.analysis_deep_required === true) {
|
|
2664
|
+
liveOutcome.deepAnalysisRequired = true;
|
|
2665
|
+
}
|
|
2651
2666
|
taskDisplay.complete(1);
|
|
2652
2667
|
}
|
|
2653
2668
|
else if (event.type === 'executor_error') {
|
|
@@ -2759,6 +2774,9 @@ export class ChatCommand {
|
|
|
2759
2774
|
const runEvaluation = evaluateExecutorSuccess(liveOutcome);
|
|
2760
2775
|
let executorSucceeded = runEvaluation.executorSucceeded;
|
|
2761
2776
|
let finalAnswer = answerContent;
|
|
2777
|
+
if (isToolEvidenceStubAnswer(finalAnswer)) {
|
|
2778
|
+
finalAnswer = '';
|
|
2779
|
+
}
|
|
2762
2780
|
const needsAnalysisRescue = !requiresWorkspaceChanges && !this.jsonOutput
|
|
2763
2781
|
&& (!executorSucceeded || !isSubstantiveAgentAnswer(finalAnswer));
|
|
2764
2782
|
if (needsAnalysisRescue) {
|
|
@@ -2876,7 +2894,7 @@ export class ChatCommand {
|
|
|
2876
2894
|
qualityMissing: liveOutcome.qualityMissing,
|
|
2877
2895
|
qualityBlockers: liveOutcome.qualityBlockers,
|
|
2878
2896
|
hasOutput: workspaceHasOutput,
|
|
2879
|
-
answerContent:
|
|
2897
|
+
answerContent: finalAnswer || null,
|
|
2880
2898
|
selfHealStatus,
|
|
2881
2899
|
selfHealTool,
|
|
2882
2900
|
plannerError: liveOutcome.plannerError ? sanitizeUserFacingErrorText(liveOutcome.plannerError) : null,
|
|
@@ -2904,7 +2922,7 @@ export class ChatCommand {
|
|
|
2904
2922
|
taskId: response.taskId || null,
|
|
2905
2923
|
contextId: response.contextId || null,
|
|
2906
2924
|
partial: response.partial === true || (!executorSucceeded && liveOutcome.tasksSucceeded > 0),
|
|
2907
|
-
content:
|
|
2925
|
+
content: finalAnswer || runEvaluation.statusHeadline,
|
|
2908
2926
|
statusHeadline: runEvaluation.statusHeadline,
|
|
2909
2927
|
tasksSucceeded: liveOutcome.tasksSucceeded,
|
|
2910
2928
|
tasksTotal: liveOutcome.tasksTotal,
|
|
@@ -2920,7 +2938,7 @@ export class ChatCommand {
|
|
|
2920
2938
|
},
|
|
2921
2939
|
}, null, 2));
|
|
2922
2940
|
}
|
|
2923
|
-
this.messages.push({ role: 'assistant', content:
|
|
2941
|
+
this.messages.push({ role: 'assistant', content: finalAnswer || runEvaluation.statusHeadline });
|
|
2924
2942
|
watcher?.stop();
|
|
2925
2943
|
return true;
|
|
2926
2944
|
}
|
|
@@ -18,6 +18,8 @@ export interface LiveOutcome {
|
|
|
18
18
|
analysisReadToolsUsed: number;
|
|
19
19
|
/** Final user-facing answer text (stream + response body) */
|
|
20
20
|
answerContent?: string;
|
|
21
|
+
/** User asked for deep/project-scale analysis, so shallow evidence must not pass. */
|
|
22
|
+
deepAnalysisRequired?: boolean;
|
|
21
23
|
streamAborted?: boolean;
|
|
22
24
|
}
|
|
23
25
|
export interface TaskSummaryEvent {
|
|
@@ -31,7 +33,7 @@ export interface RunEvaluation {
|
|
|
31
33
|
uiTheme: 'success' | 'warning' | 'error';
|
|
32
34
|
}
|
|
33
35
|
export declare function createLiveOutcome(): LiveOutcome;
|
|
34
|
-
/** Tool-trace stubs like `[read_file] "index.html"` — not a user-facing answer. */
|
|
36
|
+
/** Tool-trace stubs like `[read_file] "index.html"` or `<read_file>…</read_file>` — not a user-facing answer. */
|
|
35
37
|
export declare function isToolEvidenceStubAnswer(text: string): boolean;
|
|
36
38
|
/** True when text looks like a real answer, not an executor/system placeholder. */
|
|
37
39
|
export declare function isSubstantiveAgentAnswer(text: string): boolean;
|
|
@@ -17,10 +17,12 @@ export function createLiveOutcome() {
|
|
|
17
17
|
analysisToolsUsed: 0,
|
|
18
18
|
analysisReadToolsUsed: 0,
|
|
19
19
|
answerContent: '',
|
|
20
|
+
deepAnalysisRequired: false,
|
|
20
21
|
streamAborted: false,
|
|
21
22
|
};
|
|
22
23
|
}
|
|
23
24
|
const EXECUTOR_PLACEHOLDER_RE = /read-only analysis turn|run at least one discovery tool|reviewing attached files and workspace findings/i;
|
|
25
|
+
const BOOTSTRAP_PLACEHOLDER_RE = /bootstrap discovery completed|inspect the most relevant files next|reviewing attached files and workspace findings/i;
|
|
24
26
|
const LIST_ONLY_DISCOVERY_TOOLS = new Set([
|
|
25
27
|
'list_directory',
|
|
26
28
|
'list_dir',
|
|
@@ -28,19 +30,29 @@ const LIST_ONLY_DISCOVERY_TOOLS = new Set([
|
|
|
28
30
|
'dir',
|
|
29
31
|
]);
|
|
30
32
|
const GENERIC_SUMMARY_RE = /^(completed the requested analysis|reviewed the workspace without writing changes|task completed|done|finished|analysis completed)([.\s]|$)/i;
|
|
31
|
-
/** Tool-trace stubs like `[read_file] "index.html"` — not a user-facing answer. */
|
|
33
|
+
/** Tool-trace stubs like `[read_file] "index.html"` or `<read_file>…</read_file>` — not a user-facing answer. */
|
|
32
34
|
export function isToolEvidenceStubAnswer(text) {
|
|
33
35
|
const trimmed = String(text || '').trim();
|
|
34
36
|
if (!trimmed)
|
|
35
37
|
return true;
|
|
38
|
+
if (BOOTSTRAP_PLACEHOLDER_RE.test(trimmed))
|
|
39
|
+
return true;
|
|
36
40
|
if (GENERIC_SUMMARY_RE.test(trimmed.replace(/\.\s*\d+\s+tool steps.*$/i, '').trim()))
|
|
37
41
|
return true;
|
|
38
42
|
const lines = trimmed.split('\n').map((line) => line.trim()).filter(Boolean);
|
|
39
43
|
if (lines.length === 0)
|
|
40
44
|
return true;
|
|
41
45
|
const stubLine = /^\[(?:read_file|grep|list_directory|search_files|glob|tool_call)\]/i;
|
|
46
|
+
const xmlToolLine = /^<\/?(?:read_file|grep|list_directory|search_files|glob|tool_call|tool_result|path)\b[^>]*>/i;
|
|
47
|
+
const xmlToolBlockOnly = trimmed
|
|
48
|
+
.replace(/<read_file>\s*<path>[\s\S]*?<\/path>\s*<\/read_file>/gi, '')
|
|
49
|
+
.replace(/<(?:grep|list_directory|search_files|glob|tool_call|tool_result)\b[\s\S]*?<\/(?:grep|list_directory|search_files|glob|tool_call|tool_result)>/gi, '')
|
|
50
|
+
.replace(/\s+/g, '')
|
|
51
|
+
.trim();
|
|
52
|
+
if (!xmlToolBlockOnly)
|
|
53
|
+
return true;
|
|
42
54
|
const filesOnly = /^Files inspected:/i;
|
|
43
|
-
const stubLines = lines.filter((line) => stubLine.test(line) || filesOnly.test(line)).length;
|
|
55
|
+
const stubLines = lines.filter((line) => stubLine.test(line) || xmlToolLine.test(line) || filesOnly.test(line)).length;
|
|
44
56
|
if (stubLines === lines.length)
|
|
45
57
|
return true;
|
|
46
58
|
if (stubLines > 0 && stubLines / lines.length >= 0.6 && trimmed.length < 400)
|
|
@@ -101,6 +113,7 @@ const READ_DISCOVERY_TOOLS = new Set([
|
|
|
101
113
|
'grep',
|
|
102
114
|
'list_directory',
|
|
103
115
|
'glob',
|
|
116
|
+
'search_files',
|
|
104
117
|
'search_project',
|
|
105
118
|
'list_dir',
|
|
106
119
|
'dir',
|
|
@@ -171,6 +184,10 @@ export function evaluateExecutorSuccess(liveOutcome) {
|
|
|
171
184
|
const answerText = normalizeAgentAnswerContent(liveOutcome.answerContent);
|
|
172
185
|
const hasSubstantiveAnswer = isSubstantiveAgentAnswer(answerText);
|
|
173
186
|
const hasDeepRead = liveOutcome.analysisReadToolsUsed > 0;
|
|
187
|
+
const meetsDeepAnalysisDepth = !liveOutcome.deepAnalysisRequired
|
|
188
|
+
|| (liveOutcome.analysisToolsUsed >= 4
|
|
189
|
+
&& liveOutcome.analysisReadToolsUsed >= 3
|
|
190
|
+
&& answerText.length >= 700);
|
|
174
191
|
if (hasFatalError && !hasSubstantiveAnswer) {
|
|
175
192
|
return {
|
|
176
193
|
executorSucceeded: false,
|
|
@@ -199,6 +216,13 @@ export function evaluateExecutorSuccess(liveOutcome) {
|
|
|
199
216
|
uiTheme: 'warning',
|
|
200
217
|
};
|
|
201
218
|
}
|
|
219
|
+
if (!meetsDeepAnalysisDepth) {
|
|
220
|
+
return {
|
|
221
|
+
executorSucceeded: false,
|
|
222
|
+
statusHeadline: '⚠ Deep analysis was too shallow — retrying needs a project map, multiple file reads, and a structured report',
|
|
223
|
+
uiTheme: 'warning',
|
|
224
|
+
};
|
|
225
|
+
}
|
|
202
226
|
return {
|
|
203
227
|
executorSucceeded: true,
|
|
204
228
|
statusHeadline: '✓ Analysis completed',
|
package/dist/utils/api.js
CHANGED
|
@@ -3358,11 +3358,15 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3358
3358
|
if (Array.isArray(data?.events)) {
|
|
3359
3359
|
const completionEvent = [...data.events].reverse().find((event) => event && event.type === 'complete' && typeof event.summary === 'string' && event.summary.trim());
|
|
3360
3360
|
if (completionEvent) {
|
|
3361
|
-
|
|
3361
|
+
const text = this.sanitizeV3AgentResponseText(completionEvent.summary);
|
|
3362
|
+
if (isSubstantiveAgentAnswer(text))
|
|
3363
|
+
return text;
|
|
3362
3364
|
}
|
|
3363
3365
|
const messageEvent = [...data.events].reverse().find((event) => event && event.type === 'message' && typeof event.content === 'string' && event.content.trim());
|
|
3364
3366
|
if (messageEvent) {
|
|
3365
|
-
|
|
3367
|
+
const text = this.sanitizeV3AgentResponseText(messageEvent.content);
|
|
3368
|
+
if (isSubstantiveAgentAnswer(text))
|
|
3369
|
+
return text;
|
|
3366
3370
|
}
|
|
3367
3371
|
// Synthesize a grounded answer from the tool-call evidence the
|
|
3368
3372
|
// agent produced, rather than dumping the raw event trace.
|
|
@@ -3387,6 +3391,9 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3387
3391
|
.replace(/<thinking>[\s\S]*?<\/thinking>/gi, '')
|
|
3388
3392
|
.replace(/<tool_call>[\s\S]*?<\/tool_call>/gi, '')
|
|
3389
3393
|
.replace(/<tool_code>[\s\S]*?<\/tool_code>/gi, '')
|
|
3394
|
+
.replace(/<read_file>\s*<path>[\s\S]*?<\/path>\s*<\/read_file>/gi, '')
|
|
3395
|
+
.replace(/<(?:grep|list_directory|search_files|glob|tool_result)\b[\s\S]*?<\/(?:grep|list_directory|search_files|glob|tool_result)>/gi, '')
|
|
3396
|
+
.replace(/bootstrap discovery completed\s*[—-]\s*inspect the most relevant files next\.?/gi, '')
|
|
3390
3397
|
.replace(/```json\s*\[\s*\{[\s\S]*?"tool"[\s\S]*?\}\s*\]\s*```/gi, '')
|
|
3391
3398
|
.replace(/```json\s*\{[\s\S]*?"tool"[\s\S]*?\}\s*```/gi, '')
|
|
3392
3399
|
.replace(/^\s*(?:json\s*)?\[\s*\{[\s\S]*?"tool"[\s\S]*$/gim, '')
|