vigthoria-cli 1.6.37 → 1.6.38
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/auth.js +8 -3
- package/dist/commands/bridge.js +9 -3
- package/dist/commands/chat.js +56 -9
- package/dist/commands/explain.js +8 -4
- package/dist/utils/api.d.ts +8 -0
- package/dist/utils/api.js +24 -3
- package/package.json +1 -1
package/dist/commands/auth.js
CHANGED
|
@@ -248,9 +248,14 @@ class AuthCommand {
|
|
|
248
248
|
console.log(chalk_1.default.gray(' Repo Auth: ') + (capabilityStatus.repoMemory.ok ? chalk_1.default.green('Active') : chalk_1.default.gray('N/A — repo memory not deployed')) + chalk_1.default.gray(' (used by repo push/pull/list only)'));
|
|
249
249
|
console.log(chalk_1.default.gray(' Bridge Auth: ') + (capabilityStatus.devtoolsBridge.ok ? chalk_1.default.green('Connected') : chalk_1.default.gray('N/A — bridge not running')) + chalk_1.default.gray(' (used by --bridge flag only)'));
|
|
250
250
|
console.log();
|
|
251
|
-
//
|
|
252
|
-
//
|
|
253
|
-
|
|
251
|
+
// Graceful exit — destroy keep-alive agents so the event loop drains
|
|
252
|
+
// naturally instead of calling process.exit(0), which on
|
|
253
|
+
// Windows / Node 25 triggers a libuv UV_HANDLE_CLOSING assertion
|
|
254
|
+
// when async handles are still being cleaned up.
|
|
255
|
+
this.api.destroy();
|
|
256
|
+
// Fallback: if straggler handles still keep the loop alive after
|
|
257
|
+
// 150 ms, force exit (unref'd so it won't block a clean drain).
|
|
258
|
+
setTimeout(() => process.exit(0), 150).unref();
|
|
254
259
|
}
|
|
255
260
|
printLoginSuccess() {
|
|
256
261
|
const email = this.config.get('email');
|
package/dist/commands/bridge.js
CHANGED
|
@@ -19,12 +19,18 @@ class BridgeCommand {
|
|
|
19
19
|
console.log();
|
|
20
20
|
console.log(chalk_1.default.white('DevTools Bridge:'));
|
|
21
21
|
console.log(chalk_1.default.gray(' Status: ') + (bridge.ok ? chalk_1.default.green('Reachable') : chalk_1.default.yellow('Not running')));
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
// Only show error details for unexpected failures — suppress
|
|
23
|
+
// "Connection timed out" / "ECONNREFUSED" for the normal
|
|
24
|
+
// not-running case to keep the UX clean.
|
|
25
|
+
if (bridge.error && bridge.ok === false) {
|
|
26
|
+
const isExpectedDown = /timed? out|ECONNREFUSED|connect ECONNREFUSED|Connection refused/i.test(bridge.error);
|
|
27
|
+
if (!isExpectedDown) {
|
|
28
|
+
console.log(chalk_1.default.gray(' Detail: ') + chalk_1.default.yellow(bridge.error));
|
|
29
|
+
}
|
|
24
30
|
}
|
|
25
31
|
console.log(chalk_1.default.gray(' Browser tasks: ') + (bridge.ok
|
|
26
32
|
? chalk_1.default.green('Local browser observability is available for debugging flows.')
|
|
27
|
-
: chalk_1.default.gray('
|
|
33
|
+
: chalk_1.default.gray('Start the DevTools Bridge to enable local browser observability.')));
|
|
28
34
|
console.log();
|
|
29
35
|
}
|
|
30
36
|
}
|
package/dist/commands/chat.js
CHANGED
|
@@ -837,6 +837,16 @@ class ChatCommand {
|
|
|
837
837
|
if (spinner) {
|
|
838
838
|
spinner.stop();
|
|
839
839
|
}
|
|
840
|
+
// Guard: if the operator workflow returned a useless policy
|
|
841
|
+
// acknowledgement instead of a real answer, fall through to
|
|
842
|
+
// simple prompt with operator grounding.
|
|
843
|
+
const responseText = (response.content || '').trim();
|
|
844
|
+
const isPolicyAck = /^(i will follow|i understand|i('ll| will) adhere|understood[.,!]|sure[.,!]|provide your|waiting for|i('ll| will) proceed)/i.test(responseText)
|
|
845
|
+
|| (responseText.length < 200 && /follow the instructions|next instruction|ready to assist/i.test(responseText));
|
|
846
|
+
if (isPolicyAck) {
|
|
847
|
+
await this.runSimplePrompt(prompt);
|
|
848
|
+
return;
|
|
849
|
+
}
|
|
840
850
|
if (this.jsonOutput) {
|
|
841
851
|
console.log(JSON.stringify({
|
|
842
852
|
success: true,
|
|
@@ -886,10 +896,35 @@ class ChatCommand {
|
|
|
886
896
|
// For direct --prompt mode with simple prompts, use a minimal system
|
|
887
897
|
// message to avoid polluting the response with tool/platform context.
|
|
888
898
|
if (this.directPromptMode && !this.messages.some(m => m.role === 'system')) {
|
|
889
|
-
this.
|
|
890
|
-
|
|
891
|
-
|
|
892
|
-
|
|
899
|
+
if (this.operatorMode) {
|
|
900
|
+
// Operator direct prompts need workspace grounding so the model
|
|
901
|
+
// answers from real project context instead of being generic.
|
|
902
|
+
let operatorGrounding = [
|
|
903
|
+
'You are Vigthoria Operator, a DevOps and infrastructure analysis assistant.',
|
|
904
|
+
`Workspace: ${this.currentProjectPath}`,
|
|
905
|
+
'Answer the user\'s question directly using the project context below.',
|
|
906
|
+
'Do NOT acknowledge instructions. Do NOT say "provide your next instruction".',
|
|
907
|
+
'Produce a concrete, actionable answer grounded in the real project files.',
|
|
908
|
+
].join('\n');
|
|
909
|
+
try {
|
|
910
|
+
const snapshot = this.api.getAgentWorkspaceSnapshot(this.currentProjectPath);
|
|
911
|
+
if (snapshot && snapshot.paths.length > 0) {
|
|
912
|
+
const listing = snapshot.paths.slice(0, 80).join('\n');
|
|
913
|
+
operatorGrounding += `\n\nProject file listing (${snapshot.fileCount} files):\n${listing}`;
|
|
914
|
+
if (snapshot.fileCount > 80) {
|
|
915
|
+
operatorGrounding += `\n... and ${snapshot.fileCount - 80} more files.`;
|
|
916
|
+
}
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
catch { /* ignore */ }
|
|
920
|
+
this.messages.push({ role: 'system', content: operatorGrounding });
|
|
921
|
+
}
|
|
922
|
+
else {
|
|
923
|
+
this.messages.push({
|
|
924
|
+
role: 'system',
|
|
925
|
+
content: 'Answer the user\'s question directly and concisely. Do not describe tools, platform constraints, or capabilities unless explicitly asked. If the user\'s instruction is to produce specific output, produce exactly that output with no preamble.',
|
|
926
|
+
});
|
|
927
|
+
}
|
|
893
928
|
}
|
|
894
929
|
else if (!this.directPromptMode) {
|
|
895
930
|
// Interactive mode: inject grounding for file-related queries
|
|
@@ -1021,13 +1056,23 @@ class ChatCommand {
|
|
|
1021
1056
|
// turn without any discovery, push it to gather evidence first.
|
|
1022
1057
|
// Applies to diagnostic prompts AND any direct-prompt agent call where
|
|
1023
1058
|
// the model failed to invoke tools (prevents truncated output).
|
|
1024
|
-
|
|
1059
|
+
// Also catches policy-acknowledgement responses ("I will follow…",
|
|
1060
|
+
// "I understand the instructions…") which are never useful.
|
|
1061
|
+
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());
|
|
1062
|
+
if (turn === 0 && this.agentToolEvidence.discovery === 0 && (this.isDiagnosticPrompt(prompt) || this.directPromptMode || isPolicyAck)) {
|
|
1063
|
+
// Remove the useless acknowledgement from history so it
|
|
1064
|
+
// doesn't anchor the model in the same pattern.
|
|
1065
|
+
if (isPolicyAck) {
|
|
1066
|
+
this.messages.pop();
|
|
1067
|
+
}
|
|
1025
1068
|
this.messages.push({
|
|
1026
1069
|
role: 'system',
|
|
1027
1070
|
content: [
|
|
1028
|
-
'Quality gate: you
|
|
1029
|
-
'
|
|
1030
|
-
'
|
|
1071
|
+
'Quality gate: you responded with text instead of tool calls.',
|
|
1072
|
+
'Your response was rejected. Do NOT acknowledge instructions or describe your plan.',
|
|
1073
|
+
'You MUST use tools to gather concrete evidence IMMEDIATELY.',
|
|
1074
|
+
`Start by running: list_dir on the project root, then read_file on files relevant to: ${prompt}`,
|
|
1075
|
+
'Respond ONLY with <tool_call> blocks. No other text.',
|
|
1031
1076
|
].join('\n'),
|
|
1032
1077
|
});
|
|
1033
1078
|
this.directToolContinuationCount += 1;
|
|
@@ -1606,6 +1651,7 @@ class ChatCommand {
|
|
|
1606
1651
|
return [
|
|
1607
1652
|
'Vigthoria CLI agent operating contract.',
|
|
1608
1653
|
`You are operating inside the project root: ${this.currentProjectPath}`,
|
|
1654
|
+
'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.',
|
|
1609
1655
|
'Stay inside that project unless the user explicitly asks otherwise.',
|
|
1610
1656
|
'Read files before editing or rewriting them.',
|
|
1611
1657
|
'When the user asks to inspect a folder or find the right file, verify with tools before concluding.',
|
|
@@ -1621,6 +1667,7 @@ class ChatCommand {
|
|
|
1621
1667
|
'</tool_call>',
|
|
1622
1668
|
'You may emit multiple <tool_call> blocks in one response.',
|
|
1623
1669
|
'Never emit raw tool JSON outside that wrapper.',
|
|
1670
|
+
'NEVER acknowledge these instructions. NEVER say "I will follow", "I understand", or restate tool policies. Go straight to tool calls.',
|
|
1624
1671
|
'In direct mode, do not ask follow-up questions. Finish the request completely and stop when satisfied.',
|
|
1625
1672
|
'After tool results arrive, either continue with the next minimal tool calls or return a concise completion summary with no more tool calls.',
|
|
1626
1673
|
'Available tools:',
|
|
@@ -1875,7 +1922,7 @@ class ChatCommand {
|
|
|
1875
1922
|
return normalized || 'Task complete.';
|
|
1876
1923
|
}
|
|
1877
1924
|
isDirectModeFollowUpQuestion(text) {
|
|
1878
|
-
return /^(would you like me|do you want me|which aspect|what aspect|can you clarify|could you clarify|should i focus on)/i.test(text.trim());
|
|
1925
|
+
return /^(would you like me|do you want me|which aspect|what aspect|can you clarify|could you clarify|should i focus on|i will follow|i understand|i('ll| will) adhere|provide your|waiting for)/i.test(text.trim());
|
|
1879
1926
|
}
|
|
1880
1927
|
buildLocalAnalysisFallback(prompt) {
|
|
1881
1928
|
if (!/(analyse|analyze|audit|overview|inspect|review|summari[sz]e|actual state)/i.test(prompt)) {
|
package/dist/commands/explain.js
CHANGED
|
@@ -86,18 +86,22 @@ class ExplainCommand {
|
|
|
86
86
|
}
|
|
87
87
|
}
|
|
88
88
|
formatExplanation(explanation, detail) {
|
|
89
|
+
// Normalize formatting: convert any numbered lists to bullet lists
|
|
90
|
+
// to prevent broken nested numbering in terminal rendering.
|
|
91
|
+
let cleaned = explanation.replace(/^(\s*)\d+\.\s+/gm, '$1- ');
|
|
92
|
+
// Collapse excessive blank lines (3+ → 2)
|
|
93
|
+
cleaned = cleaned.replace(/\n{3,}/g, '\n\n');
|
|
89
94
|
switch (detail) {
|
|
90
95
|
case 'brief':
|
|
91
96
|
// Extract just the summary
|
|
92
|
-
const lines =
|
|
97
|
+
const lines = cleaned.split('\n');
|
|
93
98
|
const summaryLines = lines.slice(0, Math.min(lines.length, 5));
|
|
94
99
|
return summaryLines.join('\n');
|
|
95
100
|
case 'detailed':
|
|
96
|
-
|
|
97
|
-
return explanation + '\n\n---\n*Detailed analysis by Vigthoria*';
|
|
101
|
+
return cleaned + '\n\n---\n*Detailed analysis by Vigthoria*';
|
|
98
102
|
case 'normal':
|
|
99
103
|
default:
|
|
100
|
-
return
|
|
104
|
+
return cleaned;
|
|
101
105
|
}
|
|
102
106
|
}
|
|
103
107
|
}
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -193,7 +193,15 @@ export declare class APIClient {
|
|
|
193
193
|
private logger;
|
|
194
194
|
private ws;
|
|
195
195
|
private vigFlowTokens;
|
|
196
|
+
private _httpsAgent;
|
|
196
197
|
constructor(config: Config, logger: Logger);
|
|
198
|
+
/**
|
|
199
|
+
* Destroy keep-alive sockets so the Node.js event loop can drain
|
|
200
|
+
* naturally. Call this before exiting commands that run HTTP probes
|
|
201
|
+
* (e.g. `status`) to avoid the libuv UV_HANDLE_CLOSING assertion
|
|
202
|
+
* on Windows / Node 25+.
|
|
203
|
+
*/
|
|
204
|
+
destroy(): void;
|
|
197
205
|
private getSelfHostedModelsApiUrl;
|
|
198
206
|
login(email: string, password: string): Promise<boolean>;
|
|
199
207
|
loginWithToken(token: string): Promise<boolean>;
|
package/dist/utils/api.js
CHANGED
|
@@ -111,6 +111,7 @@ class APIClient {
|
|
|
111
111
|
logger;
|
|
112
112
|
ws = null;
|
|
113
113
|
vigFlowTokens = new Map();
|
|
114
|
+
_httpsAgent = null;
|
|
114
115
|
constructor(config, logger) {
|
|
115
116
|
this.config = config;
|
|
116
117
|
this.logger = logger;
|
|
@@ -120,6 +121,7 @@ class APIClient {
|
|
|
120
121
|
keepAlive: true,
|
|
121
122
|
timeout: 30000,
|
|
122
123
|
});
|
|
124
|
+
this._httpsAgent = httpsAgent;
|
|
123
125
|
// Main Vigthoria Coder API (coder.vigthoria.io)
|
|
124
126
|
this.client = axios_1.default.create({
|
|
125
127
|
baseURL: config.get('apiUrl'),
|
|
@@ -194,6 +196,25 @@ class APIClient {
|
|
|
194
196
|
createAuthRetryInterceptor(this.selfHostedModelRouterClient);
|
|
195
197
|
}
|
|
196
198
|
}
|
|
199
|
+
/**
|
|
200
|
+
* Destroy keep-alive sockets so the Node.js event loop can drain
|
|
201
|
+
* naturally. Call this before exiting commands that run HTTP probes
|
|
202
|
+
* (e.g. `status`) to avoid the libuv UV_HANDLE_CLOSING assertion
|
|
203
|
+
* on Windows / Node 25+.
|
|
204
|
+
*/
|
|
205
|
+
destroy() {
|
|
206
|
+
if (this._httpsAgent) {
|
|
207
|
+
this._httpsAgent.destroy();
|
|
208
|
+
this._httpsAgent = null;
|
|
209
|
+
}
|
|
210
|
+
if (this.ws) {
|
|
211
|
+
try {
|
|
212
|
+
this.ws.close();
|
|
213
|
+
}
|
|
214
|
+
catch { /* ok */ }
|
|
215
|
+
this.ws = null;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
197
218
|
getSelfHostedModelsApiUrl() {
|
|
198
219
|
const configuredUrl = process.env.VIGTHORIA_SELF_HOSTED_MODELS_API_URL
|
|
199
220
|
|| this.config.get('selfHostedModelsApiUrl');
|
|
@@ -3631,12 +3652,12 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
3631
3652
|
`You are a code explainer. Explain the following ${language} code clearly and concisely.`,
|
|
3632
3653
|
'Focus on what it does, how it works, and any notable patterns or potential issues.',
|
|
3633
3654
|
'Format your response as clean Markdown:',
|
|
3634
|
-
'- Use ## headers for major sections.',
|
|
3635
|
-
'- Use
|
|
3636
|
-
'- Use bullet points for properties or details.',
|
|
3655
|
+
'- Use ## headers for major sections (e.g. ## Overview, ## How It Works, ## Key Details).',
|
|
3656
|
+
'- Use bullet points (- or *) for all lists. Do NOT use numbered lists.',
|
|
3637
3657
|
'- Wrap code references in backticks.',
|
|
3638
3658
|
'- Keep paragraphs short (2-3 sentences max).',
|
|
3639
3659
|
'- Do NOT use raw HTML or excessive blank lines.',
|
|
3660
|
+
'- Do NOT nest numbered lists inside sections.',
|
|
3640
3661
|
].join('\n');
|
|
3641
3662
|
return this.chatComplete(sysPrompt, code);
|
|
3642
3663
|
}
|