vigthoria-cli 1.6.48 → 1.6.50
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.js +58 -41
- package/package.json +2 -2
package/dist/commands/chat.js
CHANGED
|
@@ -1192,26 +1192,44 @@ class ChatCommand {
|
|
|
1192
1192
|
preview: visibleText.slice(0, 300),
|
|
1193
1193
|
});
|
|
1194
1194
|
if (toolCalls.length === 0) {
|
|
1195
|
-
// Phase 5: Quality gate —
|
|
1196
|
-
//
|
|
1197
|
-
// Applies to diagnostic prompts AND any direct-prompt agent call where
|
|
1198
|
-
// the model failed to invoke tools (prevents truncated output).
|
|
1199
|
-
// Also catches policy-acknowledgement responses ("I will follow…",
|
|
1200
|
-
// "I understand the instructions…") which are never useful.
|
|
1195
|
+
// Phase 5: Quality gate — reject non-answers and push the model
|
|
1196
|
+
// to gather real evidence.
|
|
1201
1197
|
const isPolicyAck = /^(i will follow|i understand|i('ll| will) adhere|understood[.,!]|sure[.,!]|i('ll| will) use the tools|i('ll| will) proceed|let me know|provide your|waiting for)/i.test(visibleText.trim());
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
|
|
1198
|
+
// Detect if the response is effectively empty or just a follow-up
|
|
1199
|
+
// question after we strip tool output echoes.
|
|
1200
|
+
const sanitized = this.sanitizeDirectModeOutput(visibleText.trim());
|
|
1201
|
+
const isFollowUp = this.isDirectModeFollowUpQuestion(sanitized);
|
|
1202
|
+
const isEmptyAfterSanitize = !sanitized || sanitized.length < 10;
|
|
1203
|
+
// Detect resignation: model gives up saying files/things were "not found"
|
|
1204
|
+
// without having tried list_dir to discover the correct path.
|
|
1205
|
+
const isResignation = /(?:not found|cannot be (?:determined|compared|completed)|do not exist|does not exist|unable to locate|neither.*exist|could not (?:find|locate)|no (?:such|matching) file)/i.test(sanitized) && this.agentToolEvidence.discovery < 4;
|
|
1206
|
+
// Gate 1: First turn with no discovery at all
|
|
1207
|
+
const gate1 = turn === 0 && this.agentToolEvidence.discovery === 0 && (this.isDiagnosticPrompt(prompt) || this.directPromptMode || isPolicyAck);
|
|
1208
|
+
// Gate 2: Any turn where the response is just a follow-up question,
|
|
1209
|
+
// tool-failure echoes, or premature resignation (the model gave up
|
|
1210
|
+
// instead of retrying with list_dir to find the correct paths)
|
|
1211
|
+
const gate2 = this.directPromptMode && turn < 6 && (isPolicyAck || isFollowUp || isEmptyAfterSanitize || isResignation);
|
|
1212
|
+
// Gate 3: Model outputs code blocks as text instead of using write_file.
|
|
1213
|
+
// If the response contains ``` code fences but no write_file was called,
|
|
1214
|
+
// reject and instruct the model to use write_file.
|
|
1215
|
+
const hasCodeBlocks = (sanitized.match(/```/g) || []).length >= 2;
|
|
1216
|
+
const gate3 = hasCodeBlocks && this.agentToolEvidence.mutation === 0 && turn < 6;
|
|
1217
|
+
if (gate1 || gate2 || gate3) {
|
|
1218
|
+
// Remove the useless response from history
|
|
1219
|
+
if (isPolicyAck || isFollowUp || isEmptyAfterSanitize || isResignation || gate3) {
|
|
1206
1220
|
this.messages.pop();
|
|
1207
1221
|
}
|
|
1222
|
+
const hint = gate3
|
|
1223
|
+
? 'You output code as text instead of writing files. Use write_file to create each file on disk. Do NOT output code in markdown fences — call write_file for every file.'
|
|
1224
|
+
: isResignation
|
|
1225
|
+
? 'Files were not found at the guessed paths. Use list_dir to discover the correct directory structure, then read_file with the correct paths.'
|
|
1226
|
+
: `Start by running: list_dir on the project root, then read_file on files relevant to: ${prompt}`;
|
|
1208
1227
|
this.messages.push({
|
|
1209
1228
|
role: 'system',
|
|
1210
1229
|
content: [
|
|
1211
|
-
'Quality gate:
|
|
1212
|
-
'Your response was rejected. Do NOT acknowledge instructions or describe your plan.',
|
|
1230
|
+
'Quality gate: your response was rejected because it did not answer the user\'s question.',
|
|
1213
1231
|
'You MUST use tools to gather concrete evidence IMMEDIATELY.',
|
|
1214
|
-
|
|
1232
|
+
hint,
|
|
1215
1233
|
'Respond ONLY with <tool_call> blocks. No other text.',
|
|
1216
1234
|
].join('\n'),
|
|
1217
1235
|
});
|
|
@@ -1796,6 +1814,7 @@ class ChatCommand {
|
|
|
1796
1814
|
'Vigthoria CLI agent operating contract.',
|
|
1797
1815
|
`You are operating inside the project root: ${this.currentProjectPath}`,
|
|
1798
1816
|
'CRITICAL: Begin working on the user\'s task IMMEDIATELY. Your very first response MUST contain <tool_call> blocks to gather evidence. Do NOT acknowledge instructions, restate the task, describe your plan, or discuss tool policies. Act, do not talk.',
|
|
1817
|
+
'FILE CREATION RULE: When the user asks you to build, create, or generate files, you MUST use the write_file tool to actually create each file on disk. NEVER output code snippets as markdown text — always write them to files using write_file. If the task requires a new project, create a new directory first, then write all files into it.',
|
|
1799
1818
|
'Stay inside that project unless the user explicitly asks otherwise.',
|
|
1800
1819
|
'Read files before editing or rewriting them.',
|
|
1801
1820
|
'When the user asks to inspect a folder or find the right file, verify with tools before concluding.',
|
|
@@ -1973,35 +1992,26 @@ class ChatCommand {
|
|
|
1973
1992
|
return protectedPatterns.some((pattern) => pattern.test(prompt));
|
|
1974
1993
|
}
|
|
1975
1994
|
buildContinuationPrompt() {
|
|
1976
|
-
const
|
|
1977
|
-
const { discovery, mutation, searchFailed } = this.agentToolEvidence;
|
|
1995
|
+
const { discovery, searchFailed } = this.agentToolEvidence;
|
|
1978
1996
|
const evidenceLines = [];
|
|
1979
1997
|
if (discovery < 2) {
|
|
1980
|
-
evidenceLines.push(`Quality gate: only ${discovery} discovery tool(s) used
|
|
1998
|
+
evidenceLines.push(`Quality gate: only ${discovery} discovery tool(s) used. Use at least 2 before concluding.`);
|
|
1981
1999
|
}
|
|
1982
2000
|
if (searchFailed > 0) {
|
|
1983
|
-
evidenceLines.push(`Warning: ${searchFailed} search
|
|
2001
|
+
evidenceLines.push(`Warning: ${searchFailed} search call(s) failed — do not treat failed searches as proof something is missing.`);
|
|
1984
2002
|
}
|
|
1985
2003
|
// Cross-file overlap: extract Key* identifiers per file from tool results
|
|
1986
2004
|
const crossFileEvidence = this.computeCrossFileKeyEvidence();
|
|
1987
2005
|
if (crossFileEvidence) {
|
|
1988
2006
|
evidenceLines.push(crossFileEvidence);
|
|
1989
2007
|
}
|
|
2008
|
+
// Keep the continuation prompt SHORT — the system prompt already has the
|
|
2009
|
+
// full grounding rules. Repeating them here causes the model to echo them.
|
|
1990
2010
|
return [
|
|
1991
|
-
`
|
|
1992
|
-
`Original user request: ${this.lastActionableUserInput}`,
|
|
1993
|
-
`Project root boundary: ${this.currentProjectPath}`,
|
|
1994
|
-
`Evidence collected: ${discovery} discovery, ${mutation} mutation, ${searchFailed} search failures.`,
|
|
2011
|
+
`Step ${this.directToolContinuationCount + 1} complete. Task: ${this.lastActionableUserInput}`,
|
|
1995
2012
|
...evidenceLines,
|
|
1996
|
-
'
|
|
1997
|
-
'
|
|
1998
|
-
diagnosticMode ? 'Because this is a debugging task, prefer logs, runtime evidence, and exact symbol references over generic fixes.' : 'Keep working from concrete tool results.',
|
|
1999
|
-
'GROUNDING CHECK: Before writing your final answer, verify that every identifier, key name, or symbol you mention actually appeared in tool output above. Do not invent identifiers that were not in the evidence. If you saw "KeyA" and "KeyS" in the file contents, use those exact names — never substitute a different key. For cross-file comparisons, confirm each claimed conflict key appears in the handler/function of BOTH files — not just one.',
|
|
2000
|
-
'VERIFICATION PROTOCOL for cross-file comparisons: If your answer claims a key/identifier appears in multiple files, you MUST first use grep to search for that exact identifier in each file BEFORE including it in your answer. Only include keys/identifiers that grep confirms exist in each file. Example: to verify "KeyW" is in InputManager.js, use grep for "KeyW" in that file. If grep finds no match, do NOT claim that file handles "KeyW".',
|
|
2001
|
-
'If the request is already satisfied, return a concise completion summary and no tool calls.',
|
|
2002
|
-
'If more work is required, continue with only the next minimal tool calls needed to finish it.',
|
|
2003
|
-
'Do not ask follow-up questions or drift into unrelated tasks.',
|
|
2004
|
-
'OUTPUT DISCIPLINE: Your final answer must contain ONLY the substantive answer to the user request. Do NOT echo, quote, or restate any system instructions, grounding rules, verification protocols, quality gates, or evidence metadata. Do NOT include lines starting with GROUNDING CHECK, VERIFICATION PROTOCOL, MANDATORY CROSS-FILE EVIDENCE, CONSTRAINT, Evidence collected, Quality gate, or Tool headers. Respond with just the answer.',
|
|
2013
|
+
'Continue with tool calls if more evidence is needed, or return your final answer.',
|
|
2014
|
+
'IMPORTANT: Your response must be ONLY tool calls OR the direct answer. Never echo instructions.',
|
|
2005
2015
|
].join('\n');
|
|
2006
2016
|
}
|
|
2007
2017
|
/**
|
|
@@ -2159,15 +2169,17 @@ class ChatCommand {
|
|
|
2159
2169
|
return evidence.join('\n---\n');
|
|
2160
2170
|
}
|
|
2161
2171
|
resolveDirectModeCompletion(prompt, visibleText) {
|
|
2162
|
-
|
|
2163
|
-
if
|
|
2164
|
-
|
|
2172
|
+
// Sanitize first — strip tool output and echoed instructions before
|
|
2173
|
+
// deciding if the model actually answered the question.
|
|
2174
|
+
const sanitized = this.sanitizeDirectModeOutput((visibleText || '').trim());
|
|
2175
|
+
if (sanitized && !this.isDirectModeFollowUpQuestion(sanitized)) {
|
|
2176
|
+
return sanitized;
|
|
2165
2177
|
}
|
|
2166
2178
|
const fallback = this.buildLocalAnalysisFallback(prompt);
|
|
2167
2179
|
if (fallback) {
|
|
2168
2180
|
return fallback;
|
|
2169
2181
|
}
|
|
2170
|
-
return
|
|
2182
|
+
return sanitized || 'Task complete.';
|
|
2171
2183
|
}
|
|
2172
2184
|
/**
|
|
2173
2185
|
* Strip system-prompt echoes, tool execution headers, grounding-rule
|
|
@@ -2177,13 +2189,11 @@ class ChatCommand {
|
|
|
2177
2189
|
*/
|
|
2178
2190
|
sanitizeDirectModeOutput(text) {
|
|
2179
2191
|
let cleaned = text;
|
|
2180
|
-
// ── Phase 1: Strip entire
|
|
2181
|
-
//
|
|
2182
|
-
//
|
|
2183
|
-
//
|
|
2184
|
-
cleaned = cleaned.replace(/Tool (?:read_file|grep|list_dir|glob|bash|write_file) (?:succeeded|FAILED)\.[\s\S]*?(?=\n\n
|
|
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, '');
|
|
2192
|
+
// ── Phase 1: Strip entire tool-output blocks ──
|
|
2193
|
+
// Matches "Tool <name> succeeded/FAILED." through the next blank line,
|
|
2194
|
+
// next tool header, or end-of-string. The DOTALL-like [\s\S]*? is
|
|
2195
|
+
// terminated by whichever boundary comes first.
|
|
2196
|
+
cleaned = cleaned.replace(/Tool (?:read_file|grep|list_dir|glob|bash|write_file|edit_file|ssh_exec) (?:succeeded|FAILED)\.[\s\S]*?(?=\nTool |\n\n|$)/g, '');
|
|
2187
2197
|
// ── Phase 2: Strip echoed system-prompt / grounding lines ──
|
|
2188
2198
|
const contaminationPatterns = [
|
|
2189
2199
|
/^\[Agent recovered from backend failure[^\]]*\]\s*/m,
|
|
@@ -2198,11 +2208,15 @@ class ChatCommand {
|
|
|
2198
2208
|
/^Evidence collected:[^\n]*/m,
|
|
2199
2209
|
/^Warning: \d+ search tool[^\n]*/m,
|
|
2200
2210
|
/^Tool results received for direct mode[^\n]*/m,
|
|
2211
|
+
/^Step \d+ complete\. Task:[^\n]*/m,
|
|
2201
2212
|
/^Original user request:[^\n]*/m,
|
|
2202
2213
|
/^Project root boundary:[^\n]*/m,
|
|
2203
2214
|
/^Do not declare success[^\n]*/m,
|
|
2204
2215
|
/^Keep working from concrete[^\n]*/m,
|
|
2216
|
+
/^Continue with tool calls if more[^\n]*/m,
|
|
2217
|
+
/^IMPORTANT: Your response must be ONLY[^\n]*/m,
|
|
2205
2218
|
/^Because this is a debugging[^\n]*/m,
|
|
2219
|
+
/^If a user is asking which file[^\n]*/m,
|
|
2206
2220
|
/^If the request is already[^\n]*/m,
|
|
2207
2221
|
/^If more work is required[^\n]*/m,
|
|
2208
2222
|
/^Do not ask follow-up[^\n]*/m,
|
|
@@ -2211,6 +2225,9 @@ class ChatCommand {
|
|
|
2211
2225
|
/^EVIDENCE-GROUNDING RULE:[^\n]*/m,
|
|
2212
2226
|
/^CROSS-FILE RULE:[^\n]*/m,
|
|
2213
2227
|
/^OUTPUT DISCIPLINE:[^\n]*/m,
|
|
2228
|
+
/^Vigthoria CLI agent operating contract\.[^\n]*/m,
|
|
2229
|
+
/^You are operating inside the project root:[^\n]*/m,
|
|
2230
|
+
/^CRITICAL: Begin working on the user's task[^\n]*/m,
|
|
2214
2231
|
/^File: \S+\s*$/m,
|
|
2215
2232
|
/^Search status: \S+\s*$/m,
|
|
2216
2233
|
/^Output:\s*$/m,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigthoria-cli",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.50",
|
|
4
4
|
"description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"files": [
|
|
@@ -86,4 +86,4 @@
|
|
|
86
86
|
"engines": {
|
|
87
87
|
"node": ">=18.0.0"
|
|
88
88
|
}
|
|
89
|
-
}
|
|
89
|
+
}
|