vigthoria-cli 1.9.2 → 1.9.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/README.md +15 -5
- package/dist/commands/auth.d.ts +28 -38
- package/dist/commands/auth.js +461 -313
- package/dist/commands/bridge.js +3 -8
- package/dist/commands/chat.d.ts +3 -0
- package/dist/commands/chat.js +97 -34
- package/dist/commands/index.js +1 -1
- package/dist/commands/legion.d.ts +22 -19
- package/dist/commands/legion.js +561 -134
- package/dist/commands/preview.js +32 -7
- package/dist/commands/repo.js +19 -13
- package/dist/commands/security.d.ts +20 -0
- package/dist/commands/security.js +98 -0
- package/dist/commands/update.d.ts +9 -0
- package/dist/commands/update.js +235 -0
- package/dist/index.d.ts +2 -1
- package/dist/index.js +147 -40
- package/dist/utils/api.d.ts +25 -70
- package/dist/utils/api.js +875 -693
- package/dist/utils/config.js +1 -1
- package/dist/utils/tools.d.ts +11 -0
- package/dist/utils/tools.js +251 -5
- package/install.ps1 +322 -0
- package/install.sh +314 -0
- package/package.json +18 -3
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +159 -0
- package/scripts/release/publish-cli-release.sh +73 -0
- package/scripts/release/validate-no-go-gates.sh +129 -0
- package/scripts/release/verify-runtime-consistency.mjs +64 -0
package/dist/commands/bridge.js
CHANGED
|
@@ -19,14 +19,9 @@ 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
|
-
|
|
24
|
-
|
|
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
|
-
}
|
|
22
|
+
if (!bridge.ok) {
|
|
23
|
+
const detail = String(bridge.error || 'Connection refused').trim() || 'Connection refused';
|
|
24
|
+
console.log(chalk_1.default.gray(' Error: ') + chalk_1.default.yellow(detail));
|
|
30
25
|
}
|
|
31
26
|
console.log(chalk_1.default.gray(' Browser tasks: ') + (bridge.ok
|
|
32
27
|
? chalk_1.default.green('Local browser observability is available for debugging flows.')
|
package/dist/commands/chat.d.ts
CHANGED
|
@@ -90,6 +90,9 @@ export declare class ChatCommand {
|
|
|
90
90
|
*/
|
|
91
91
|
private sanitizeServerPath;
|
|
92
92
|
private describeV3AgentTool;
|
|
93
|
+
private isRawV3StreamPayload;
|
|
94
|
+
private consumeV3StreamPayload;
|
|
95
|
+
private writeV3StreamText;
|
|
93
96
|
private updateV3AgentSpinner;
|
|
94
97
|
private updateOperatorSpinner;
|
|
95
98
|
constructor(config: Config, logger: Logger);
|
package/dist/commands/chat.js
CHANGED
|
@@ -66,9 +66,12 @@ const DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS = (() => {
|
|
|
66
66
|
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
67
67
|
})();
|
|
68
68
|
const DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS = (() => {
|
|
69
|
-
const rawValue = process.env.VIGTHORIA_AGENT_SOFT_TIMEOUT_MS || process.env.V3_AGENT_SOFT_TIMEOUT_MS
|
|
69
|
+
const rawValue = process.env.VIGTHORIA_AGENT_SOFT_TIMEOUT_MS || process.env.V3_AGENT_SOFT_TIMEOUT_MS;
|
|
70
|
+
if (!rawValue) {
|
|
71
|
+
return 0;
|
|
72
|
+
}
|
|
70
73
|
const parsed = Number.parseInt(rawValue, 10);
|
|
71
|
-
return Number.isFinite(parsed) && parsed
|
|
74
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
72
75
|
})();
|
|
73
76
|
class ChatCommand {
|
|
74
77
|
config;
|
|
@@ -192,7 +195,9 @@ class ChatCommand {
|
|
|
192
195
|
if (attempt >= retries || (!this.isNetworkError(error) && !this.isTimeoutError(error))) {
|
|
193
196
|
this.handleApiError(error, context);
|
|
194
197
|
}
|
|
195
|
-
|
|
198
|
+
if (!this.jsonOutput) {
|
|
199
|
+
this.logger.warn(`${context} failed due to ${this.isTimeoutError(error) ? 'timeout' : 'network error'}; retrying (${attempt + 1}/${retries})...`);
|
|
200
|
+
}
|
|
196
201
|
await new Promise((resolve) => setTimeout(resolve, 500 * (attempt + 1)));
|
|
197
202
|
}
|
|
198
203
|
}
|
|
@@ -221,7 +226,9 @@ class ChatCommand {
|
|
|
221
226
|
reason: 'governance-blocked-model',
|
|
222
227
|
};
|
|
223
228
|
this.currentModel = effectiveModel;
|
|
224
|
-
this.
|
|
229
|
+
if (!this.jsonOutput) {
|
|
230
|
+
this.logger.warn(`Model ${requestedModel} is not permitted for no-agent chat; using ${effectiveModel}`);
|
|
231
|
+
}
|
|
225
232
|
return;
|
|
226
233
|
}
|
|
227
234
|
this.modelGovernanceFallback = null;
|
|
@@ -248,7 +255,7 @@ class ChatCommand {
|
|
|
248
255
|
}
|
|
249
256
|
operatorAccessMessage() {
|
|
250
257
|
const currentPlan = this.config.get('subscription').plan || 'free';
|
|
251
|
-
return `Operator mode requires Enterprise or admin access. Current plan: ${currentPlan}.`;
|
|
258
|
+
return `Operator mode requires Pro, Ultra, Enterprise, or admin access. Current plan: ${currentPlan}.`;
|
|
252
259
|
}
|
|
253
260
|
getDefaultChatModel() {
|
|
254
261
|
const preferredModel = String(this.config.get('preferences').defaultModel || '').trim().toLowerCase();
|
|
@@ -476,7 +483,67 @@ class ChatCommand {
|
|
|
476
483
|
}
|
|
477
484
|
return 'Working';
|
|
478
485
|
}
|
|
486
|
+
isRawV3StreamPayload(event) {
|
|
487
|
+
if (!event) {
|
|
488
|
+
return false;
|
|
489
|
+
}
|
|
490
|
+
if (typeof event === 'string' || Buffer.isBuffer(event) || event instanceof Uint8Array) {
|
|
491
|
+
return true;
|
|
492
|
+
}
|
|
493
|
+
const body = event?.body ?? event?.stream ?? event?.response;
|
|
494
|
+
return Boolean(body && (typeof body[Symbol.asyncIterator] === 'function' || typeof body.getReader === 'function'));
|
|
495
|
+
}
|
|
496
|
+
async consumeV3StreamPayload(spinner, event) {
|
|
497
|
+
try {
|
|
498
|
+
const source = (event && typeof event === 'object' && !Buffer.isBuffer(event) && !(event instanceof Uint8Array))
|
|
499
|
+
? (event.body ?? event.stream ?? event.response ?? event)
|
|
500
|
+
: event;
|
|
501
|
+
for await (const chunk of (0, tools_js_1.robustifyStreamResponse)(source)) {
|
|
502
|
+
this.v3LastActivity = Date.now();
|
|
503
|
+
if (chunk.type === 'error') {
|
|
504
|
+
if (spinner.isSpinning)
|
|
505
|
+
spinner.stop();
|
|
506
|
+
process.stderr.write(chalk_1.default.red(`\nStream error: ${chunk.content}\n`));
|
|
507
|
+
continue;
|
|
508
|
+
}
|
|
509
|
+
if (chunk.content) {
|
|
510
|
+
this.writeV3StreamText(spinner, chunk.content);
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
catch (error) {
|
|
515
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
516
|
+
if (spinner.isSpinning)
|
|
517
|
+
spinner.stop();
|
|
518
|
+
process.stderr.write(chalk_1.default.red(`\nStream error: ${message}\n`));
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
writeV3StreamText(spinner, text) {
|
|
522
|
+
if (!text) {
|
|
523
|
+
return;
|
|
524
|
+
}
|
|
525
|
+
if (!this.v3StreamingStarted) {
|
|
526
|
+
this.v3StreamingStarted = true;
|
|
527
|
+
spinner.stop();
|
|
528
|
+
if (!this.directPromptMode) {
|
|
529
|
+
console.log();
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
else {
|
|
533
|
+
spinner.stop();
|
|
534
|
+
}
|
|
535
|
+
process.stdout.write(text);
|
|
536
|
+
}
|
|
479
537
|
updateV3AgentSpinner(spinner, event) {
|
|
538
|
+
if (this.isRawV3StreamPayload(event)) {
|
|
539
|
+
this.consumeV3StreamPayload(spinner, event).catch((error) => {
|
|
540
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
541
|
+
if (spinner.isSpinning)
|
|
542
|
+
spinner.stop();
|
|
543
|
+
process.stderr.write(chalk_1.default.red(`\nStream error: ${message}\n`));
|
|
544
|
+
});
|
|
545
|
+
return;
|
|
546
|
+
}
|
|
480
547
|
if (!event || typeof event !== 'object') {
|
|
481
548
|
return;
|
|
482
549
|
}
|
|
@@ -543,17 +610,8 @@ class ChatCommand {
|
|
|
543
610
|
? (event.delta?.text || '')
|
|
544
611
|
: (event.content || '');
|
|
545
612
|
if (text) {
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
spinner.stop();
|
|
549
|
-
if (!this.directPromptMode) {
|
|
550
|
-
console.log();
|
|
551
|
-
}
|
|
552
|
-
}
|
|
553
|
-
else {
|
|
554
|
-
spinner.stop();
|
|
555
|
-
}
|
|
556
|
-
process.stdout.write(text);
|
|
613
|
+
this.v3LastActivity = Date.now();
|
|
614
|
+
this.writeV3StreamText(spinner, text);
|
|
557
615
|
}
|
|
558
616
|
else {
|
|
559
617
|
spinner.text = chalk_1.default.cyan('[Response] ') + 'Writing response...';
|
|
@@ -826,11 +884,16 @@ class ChatCommand {
|
|
|
826
884
|
return;
|
|
827
885
|
}
|
|
828
886
|
if (options.prompt) {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
887
|
+
const bridgePromptTimeoutMs = (() => {
|
|
888
|
+
const rawValue = process.env.VIGTHORIA_BRIDGE_PROMPT_TIMEOUT_MS || process.env.V3_BRIDGE_PROMPT_TIMEOUT_MS;
|
|
889
|
+
if (!rawValue) {
|
|
890
|
+
return 0;
|
|
891
|
+
}
|
|
892
|
+
const parsed = Number.parseInt(rawValue, 10);
|
|
893
|
+
return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
|
|
894
|
+
})();
|
|
832
895
|
let timedOut = false;
|
|
833
|
-
const timeoutId = options.bridge
|
|
896
|
+
const timeoutId = options.bridge && bridgePromptTimeoutMs > 0
|
|
834
897
|
? setTimeout(() => {
|
|
835
898
|
timedOut = true;
|
|
836
899
|
const b = (0, bridge_client_js_1.getBridgeClient)();
|
|
@@ -839,10 +902,10 @@ class ChatCommand {
|
|
|
839
902
|
b.destroy();
|
|
840
903
|
}
|
|
841
904
|
if (!this.jsonOutput) {
|
|
842
|
-
this.logger.error('Bridge prompt timed out after
|
|
905
|
+
this.logger.error('Bridge prompt timed out after ' + Math.round(bridgePromptTimeoutMs / 1000) + ' seconds.');
|
|
843
906
|
}
|
|
844
907
|
process.exitCode = 1;
|
|
845
|
-
},
|
|
908
|
+
}, bridgePromptTimeoutMs)
|
|
846
909
|
: null;
|
|
847
910
|
await this.handleDirectPrompt(options.prompt);
|
|
848
911
|
if (timeoutId)
|
|
@@ -1042,7 +1105,7 @@ class ChatCommand {
|
|
|
1042
1105
|
async handleDirectPrompt(prompt) {
|
|
1043
1106
|
// Suppress all setup banners in direct-prompt mode so only the final
|
|
1044
1107
|
// answer reaches stdout. Interactive (REPL) mode still shows them.
|
|
1045
|
-
if (!this.jsonOutput
|
|
1108
|
+
if (!this.jsonOutput) {
|
|
1046
1109
|
console.log(chalk_1.default.cyan('Running single prompt in direct mode.'));
|
|
1047
1110
|
console.log(chalk_1.default.gray(`Model: ${this.currentModel}`));
|
|
1048
1111
|
console.log(chalk_1.default.gray(`Project: ${this.currentProjectPath}`));
|
|
@@ -1694,12 +1757,12 @@ class ChatCommand {
|
|
|
1694
1757
|
tool: 'read_file',
|
|
1695
1758
|
args: { path: targetFile },
|
|
1696
1759
|
};
|
|
1697
|
-
if (!this.jsonOutput
|
|
1760
|
+
if (!this.jsonOutput) {
|
|
1698
1761
|
console.log(chalk_1.default.cyan(`⚙ Executing: ${readCall.tool}`));
|
|
1699
1762
|
}
|
|
1700
1763
|
const readResult = await this.tools.execute(readCall);
|
|
1701
1764
|
const readSummary = this.formatToolResult(readCall, readResult);
|
|
1702
|
-
if (!this.jsonOutput
|
|
1765
|
+
if (!this.jsonOutput) {
|
|
1703
1766
|
console.log(readResult.success ? chalk_1.default.gray(readSummary) : chalk_1.default.red(readSummary));
|
|
1704
1767
|
}
|
|
1705
1768
|
this.messages.push({ role: 'system', content: readSummary });
|
|
@@ -1742,12 +1805,12 @@ class ChatCommand {
|
|
|
1742
1805
|
content: rewrittenContent,
|
|
1743
1806
|
},
|
|
1744
1807
|
};
|
|
1745
|
-
if (!this.jsonOutput
|
|
1808
|
+
if (!this.jsonOutput) {
|
|
1746
1809
|
console.log(chalk_1.default.cyan(`⚙ Executing: ${writeCall.tool}`));
|
|
1747
1810
|
}
|
|
1748
1811
|
const writeResult = await this.tools.execute(writeCall);
|
|
1749
1812
|
const writeSummary = this.formatToolResult(writeCall, writeResult);
|
|
1750
|
-
if (!this.jsonOutput
|
|
1813
|
+
if (!this.jsonOutput) {
|
|
1751
1814
|
console.log(writeResult.success ? chalk_1.default.gray(writeSummary) : chalk_1.default.red(writeSummary));
|
|
1752
1815
|
}
|
|
1753
1816
|
this.messages.push({ role: 'system', content: writeSummary });
|
|
@@ -1921,7 +1984,7 @@ class ChatCommand {
|
|
|
1921
1984
|
}
|
|
1922
1985
|
else if (this.v3StreamingStarted) {
|
|
1923
1986
|
// Content was already streamed to stdout in real-time; skip duplicate print.
|
|
1924
|
-
if (!this.
|
|
1987
|
+
if (!this.jsonOutput) {
|
|
1925
1988
|
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1926
1989
|
}
|
|
1927
1990
|
}
|
|
@@ -1937,7 +2000,7 @@ class ChatCommand {
|
|
|
1937
2000
|
}
|
|
1938
2001
|
console.log('V3 agent workflow completed.');
|
|
1939
2002
|
}
|
|
1940
|
-
if (!this.jsonOutput &&
|
|
2003
|
+
if (!this.jsonOutput && previewGate?.required) {
|
|
1941
2004
|
if (previewGate.passed) {
|
|
1942
2005
|
console.log(chalk_1.default.gray(`Template Service preview gate: passed via ${previewGate.backendUrl || 'unknown backend'}`));
|
|
1943
2006
|
}
|
|
@@ -2481,10 +2544,10 @@ class ChatCommand {
|
|
|
2481
2544
|
isProtectedFileReference(prompt, filePath) {
|
|
2482
2545
|
const escapedPath = filePath.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
2483
2546
|
const protectedPatterns = [
|
|
2484
|
-
new RegExp(`do not modify\\s+[
|
|
2485
|
-
new RegExp(`don't modify\\s+[
|
|
2486
|
-
new RegExp(`leave\\s+[
|
|
2487
|
-
new RegExp(`without modifying\\s+[
|
|
2547
|
+
new RegExp(`do not modify\\s+[-\u001f\s\-\"][` + "'" + `]?${escapedPath}[` + "'" + `]?`, 'i'),
|
|
2548
|
+
new RegExp(`don't modify\\s+[-\u001f\s\-\"][` + "'" + `]?${escapedPath}[` + "'" + `]?`, 'i'),
|
|
2549
|
+
new RegExp(`leave\\s+[-\u001f\s\-\"][` + "'" + `]?${escapedPath}[` + "'" + `]?\\s+unchanged`, 'i'),
|
|
2550
|
+
new RegExp(`without modifying\\s+[-\u001f\s\-\"][` + "'" + `]?${escapedPath}[` + "'" + `]?`, 'i'),
|
|
2488
2551
|
];
|
|
2489
2552
|
return protectedPatterns.some((pattern) => pattern.test(prompt));
|
|
2490
2553
|
}
|
|
@@ -2846,7 +2909,7 @@ class ChatCommand {
|
|
|
2846
2909
|
}
|
|
2847
2910
|
// In direct-prompt mode (--prompt), suppress verbose tool output so
|
|
2848
2911
|
// only the final answer prints. In interactive mode, show full detail.
|
|
2849
|
-
const verbose = !this.jsonOutput
|
|
2912
|
+
const verbose = !this.jsonOutput;
|
|
2850
2913
|
for (const call of toolCalls) {
|
|
2851
2914
|
if (verbose) {
|
|
2852
2915
|
console.log(chalk_1.default.cyan(`⚙ Executing: ${call.tool}`));
|
package/dist/commands/index.js
CHANGED
|
@@ -10,19 +10,15 @@
|
|
|
10
10
|
*/
|
|
11
11
|
import { Config } from '../utils/config.js';
|
|
12
12
|
import { Logger } from '../utils/logger.js';
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
planOnly?: boolean;
|
|
23
|
-
models?: string;
|
|
24
|
-
timeoutSec?: number;
|
|
25
|
-
}
|
|
13
|
+
export type LegionOptions = {
|
|
14
|
+
/** Enables Vigthoria Cortex maximum-intelligence execution when --cortex is supplied. */
|
|
15
|
+
cortex?: boolean;
|
|
16
|
+
/** Model tier: 'heavy' (default — strongest LLMs) or 'lite' (cost-efficient, high quality). */
|
|
17
|
+
tier?: 'heavy' | 'lite';
|
|
18
|
+
email?: string;
|
|
19
|
+
password?: string;
|
|
20
|
+
[key: string]: any;
|
|
21
|
+
};
|
|
26
22
|
export declare class LegionCommand {
|
|
27
23
|
private config;
|
|
28
24
|
private logger;
|
|
@@ -32,15 +28,20 @@ export declare class LegionCommand {
|
|
|
32
28
|
private readJsonResponse;
|
|
33
29
|
private propagateLegionApiError;
|
|
34
30
|
run(request: string | undefined, options: LegionOptions): Promise<void>;
|
|
35
|
-
private
|
|
31
|
+
private runCortex;
|
|
32
|
+
private isCriticalRoleFailure;
|
|
33
|
+
private isOptionalRepairRoleFailure;
|
|
34
|
+
private estimateAdditionalLoopQuote;
|
|
35
|
+
private confirmAdditionalLoopCharge;
|
|
36
|
+
private runMandatoryPreflight;
|
|
36
37
|
private scanProject;
|
|
37
38
|
private resolveModelProfiles;
|
|
38
39
|
private buildRoleQuote;
|
|
39
|
-
private
|
|
40
|
+
private buildCortexExplicitSteps;
|
|
40
41
|
private buildBillingQuote;
|
|
41
42
|
private evaluateBillingGate;
|
|
42
43
|
private parseBooleanCandidate;
|
|
43
|
-
private
|
|
44
|
+
private fetchCortexEntitlement;
|
|
44
45
|
private isMasterAdminFree;
|
|
45
46
|
private getBillingBaseUrl;
|
|
46
47
|
private parseNumericCandidate;
|
|
@@ -51,18 +52,20 @@ export declare class LegionCommand {
|
|
|
51
52
|
private collectExecutionCharge;
|
|
52
53
|
private resolveBillingInsufficientFunds;
|
|
53
54
|
private printBillingGateSummary;
|
|
54
|
-
private
|
|
55
|
+
private printCortexQuote;
|
|
55
56
|
private confirmExecution;
|
|
56
57
|
/**
|
|
57
58
|
* SSE streaming URL for the Legion execution endpoint.
|
|
58
59
|
* Always hits Hyper Loop directly (port 8020) with the service key to avoid
|
|
59
|
-
* gateway JWT expiry killing long-running
|
|
60
|
+
* gateway JWT expiry killing long-running Cortex jobs.
|
|
60
61
|
*/
|
|
61
62
|
private getLegionStreamUrl;
|
|
62
63
|
private getLegionServiceKey;
|
|
63
64
|
private planAndExecute;
|
|
65
|
+
private buildCortexRunReport;
|
|
66
|
+
private extractModifiedFiles;
|
|
67
|
+
private writeCortexSummaryReport;
|
|
64
68
|
private formatLegionError;
|
|
65
69
|
private showWorkers;
|
|
66
70
|
private showStatus;
|
|
67
71
|
}
|
|
68
|
-
export {};
|