vigthoria-cli 1.8.14 → 1.8.19
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 +1 -2
- package/dist/commands/chat.js +124 -66
- package/dist/index.js +146 -8
- package/dist/utils/api.d.ts +13 -17
- package/dist/utils/api.js +170 -746
- package/package.json +1 -1
package/dist/commands/chat.d.ts
CHANGED
|
@@ -118,8 +118,7 @@ export declare class ChatCommand {
|
|
|
118
118
|
private runLocalAgentLoop;
|
|
119
119
|
private tryDirectSingleFileFlow;
|
|
120
120
|
private tryV3AgentWorkflow;
|
|
121
|
-
private
|
|
122
|
-
private tryCommandLevelSaaSRescue;
|
|
121
|
+
private tryRecoverV3ServiceAndRetry;
|
|
123
122
|
private startInteractiveChat;
|
|
124
123
|
private showHelp;
|
|
125
124
|
private showContext;
|
package/dist/commands/chat.js
CHANGED
|
@@ -458,13 +458,20 @@ class ChatCommand {
|
|
|
458
458
|
const plan = event.plan || {};
|
|
459
459
|
const planKind = plan.task_kind || event.task_kind || '';
|
|
460
460
|
const quality = plan.quality_profile || '';
|
|
461
|
+
const status = typeof plan.status === 'string' ? plan.status : '';
|
|
462
|
+
const summary = typeof plan.summary === 'string' ? plan.summary : '';
|
|
461
463
|
if (spinner.isSpinning)
|
|
462
464
|
spinner.stop();
|
|
463
465
|
process.stderr.write(chalk_1.default.cyan(` [Plan] `) + `Task: ${planKind || 'analyzing'}`);
|
|
464
466
|
if (quality)
|
|
465
467
|
process.stderr.write(chalk_1.default.gray(` (${quality})`));
|
|
466
468
|
process.stderr.write('\n');
|
|
467
|
-
|
|
469
|
+
if (summary) {
|
|
470
|
+
process.stderr.write(chalk_1.default.gray(` ${summary}\n`));
|
|
471
|
+
}
|
|
472
|
+
if (status === 'planning' && Number.isFinite(Number(plan.elapsed_seconds))) {
|
|
473
|
+
process.stderr.write(chalk_1.default.gray(` elapsed: ${plan.elapsed_seconds}s\n`));
|
|
474
|
+
}
|
|
468
475
|
if (Array.isArray(plan.tasks) && plan.tasks.length > 0) {
|
|
469
476
|
process.stderr.write(chalk_1.default.gray(` ${plan.total_tasks || plan.tasks.length} tasks:\n`));
|
|
470
477
|
for (const t of plan.tasks.slice(0, 10)) {
|
|
@@ -475,12 +482,53 @@ class ChatCommand {
|
|
|
475
482
|
process.stderr.write(chalk_1.default.gray(` ... and ${plan.tasks.length - 10} more\n`));
|
|
476
483
|
}
|
|
477
484
|
}
|
|
478
|
-
|
|
485
|
+
if (Array.isArray(plan.notes) && plan.notes.length > 0) {
|
|
486
|
+
for (const note of plan.notes.slice(0, 3)) {
|
|
487
|
+
process.stderr.write(chalk_1.default.gray(` note: ${note}\n`));
|
|
488
|
+
}
|
|
489
|
+
}
|
|
479
490
|
if (Array.isArray(plan.target_files) && plan.target_files.length > 0) {
|
|
480
491
|
process.stderr.write(chalk_1.default.gray(` Files: ${plan.target_files.join(', ')}\n`));
|
|
481
492
|
}
|
|
482
493
|
spinner.start();
|
|
483
|
-
spinner.text = 'Planning...';
|
|
494
|
+
spinner.text = status === 'planning' ? 'Planning...' : 'Executing plan...';
|
|
495
|
+
return;
|
|
496
|
+
}
|
|
497
|
+
if (event.type === 'executor_start') {
|
|
498
|
+
if (spinner.isSpinning)
|
|
499
|
+
spinner.stop();
|
|
500
|
+
process.stderr.write(chalk_1.default.cyan(' [Executor] ') + `Starting ${event.task_id || 'task'}${event.title ? ` - ${event.title}` : ''}
|
|
501
|
+
`);
|
|
502
|
+
spinner.start();
|
|
503
|
+
spinner.text = 'Vigthoria Executor running...';
|
|
504
|
+
return;
|
|
505
|
+
}
|
|
506
|
+
if (event.type === 'executor_error') {
|
|
507
|
+
if (spinner.isSpinning)
|
|
508
|
+
spinner.stop();
|
|
509
|
+
const msg = (0, api_js_1.sanitizeUserFacingErrorText)(String(event.error || 'Executor error')) || 'Executor error';
|
|
510
|
+
process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor encountered an issue: ${msg}
|
|
511
|
+
`);
|
|
512
|
+
spinner.start();
|
|
513
|
+
spinner.text = 'Recovering executor...';
|
|
514
|
+
return;
|
|
515
|
+
}
|
|
516
|
+
if (event.type === 'executor_complete') {
|
|
517
|
+
if (spinner.isSpinning)
|
|
518
|
+
spinner.stop();
|
|
519
|
+
const summary = event.summary || {};
|
|
520
|
+
const status = String(summary.status || 'completed');
|
|
521
|
+
const changed = Array.isArray(summary.changed_files) ? summary.changed_files.length : 0;
|
|
522
|
+
if (status === 'failed') {
|
|
523
|
+
process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor task failed${summary.task_id ? ` (${summary.task_id})` : ''}.
|
|
524
|
+
`);
|
|
525
|
+
}
|
|
526
|
+
else {
|
|
527
|
+
process.stderr.write(chalk_1.default.green(' [Executor] ') + `Task completed${summary.task_id ? ` (${summary.task_id})` : ''}${changed ? `, ${changed} files changed` : ''}.
|
|
528
|
+
`);
|
|
529
|
+
}
|
|
530
|
+
spinner.start();
|
|
531
|
+
spinner.text = 'Continuing plan...';
|
|
484
532
|
return;
|
|
485
533
|
}
|
|
486
534
|
if (event.type === 'file_mutation') {
|
|
@@ -505,7 +553,18 @@ class ChatCommand {
|
|
|
505
553
|
else {
|
|
506
554
|
if (spinner.isSpinning)
|
|
507
555
|
spinner.stop();
|
|
508
|
-
|
|
556
|
+
const message = (0, api_js_1.sanitizeUserFacingErrorText)(String(event.message || 'Agent error')) || 'Agent error';
|
|
557
|
+
const plannerLike = /plan|planner|dependency graph/i.test(message);
|
|
558
|
+
const executorLike = /executor|task failed|iteration/i.test(message);
|
|
559
|
+
if (plannerLike) {
|
|
560
|
+
process.stderr.write(chalk_1.default.red(' [Planner] ') + `Vigthoria Planner encountered an issue: ${message}\n`);
|
|
561
|
+
}
|
|
562
|
+
else if (executorLike) {
|
|
563
|
+
process.stderr.write(chalk_1.default.red(' [Executor] ') + `Vigthoria Executor encountered an issue: ${message}\n`);
|
|
564
|
+
}
|
|
565
|
+
else {
|
|
566
|
+
process.stderr.write(chalk_1.default.red(' [Error] ') + message + '\n');
|
|
567
|
+
}
|
|
509
568
|
}
|
|
510
569
|
return;
|
|
511
570
|
}
|
|
@@ -1601,7 +1660,6 @@ class ChatCommand {
|
|
|
1601
1660
|
async tryV3AgentWorkflow(prompt) {
|
|
1602
1661
|
const runtimeContext = await this.getPromptRuntimeContext(prompt);
|
|
1603
1662
|
const routingPolicy = this.resolveAgentExecutionPolicy(prompt);
|
|
1604
|
-
const rescueEligible = this.isSaaSRescuePrompt(prompt);
|
|
1605
1663
|
// Reset streaming counters for new workflow
|
|
1606
1664
|
this.v3IterationCount = 0;
|
|
1607
1665
|
this.v3ToolCallCount = 0;
|
|
@@ -1649,14 +1707,7 @@ class ChatCommand {
|
|
|
1649
1707
|
...runtimeContext,
|
|
1650
1708
|
onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
|
|
1651
1709
|
});
|
|
1652
|
-
const response = await
|
|
1653
|
-
? Promise.race([
|
|
1654
|
-
workflowPromise,
|
|
1655
|
-
new Promise((_, reject) => {
|
|
1656
|
-
setTimeout(() => reject(new Error('V3_SAAS_SOFT_TIMEOUT')), DEFAULT_V3_AGENT_SOFT_TIMEOUT_MS);
|
|
1657
|
-
}),
|
|
1658
|
-
])
|
|
1659
|
-
: workflowPromise);
|
|
1710
|
+
const response = await workflowPromise;
|
|
1660
1711
|
if (spinner) {
|
|
1661
1712
|
spinner.stop();
|
|
1662
1713
|
}
|
|
@@ -1719,18 +1770,18 @@ class ChatCommand {
|
|
|
1719
1770
|
else if (this.v3StreamingStarted) {
|
|
1720
1771
|
// Content was already streamed to stdout in real-time; skip duplicate print.
|
|
1721
1772
|
if (!this.directPromptMode) {
|
|
1722
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1773
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1723
1774
|
}
|
|
1724
1775
|
}
|
|
1725
1776
|
else if (response.content) {
|
|
1726
1777
|
if (!this.directPromptMode) {
|
|
1727
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1778
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1728
1779
|
}
|
|
1729
1780
|
console.log(response.content);
|
|
1730
1781
|
}
|
|
1731
1782
|
else {
|
|
1732
1783
|
if (!this.directPromptMode) {
|
|
1733
|
-
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}
|
|
1784
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1734
1785
|
}
|
|
1735
1786
|
console.log('V3 agent workflow completed.');
|
|
1736
1787
|
}
|
|
@@ -1762,9 +1813,9 @@ class ChatCommand {
|
|
|
1762
1813
|
}
|
|
1763
1814
|
catch (error) {
|
|
1764
1815
|
watcher?.stop();
|
|
1765
|
-
if (
|
|
1766
|
-
const
|
|
1767
|
-
if (
|
|
1816
|
+
if (!this.api.hasAgentWorkspaceOutput(workspaceContext)) {
|
|
1817
|
+
const recovered = await this.tryRecoverV3ServiceAndRetry(executionPrompt, prompt, workspaceContext, routingPolicy, spinner, error);
|
|
1818
|
+
if (recovered) {
|
|
1768
1819
|
return true;
|
|
1769
1820
|
}
|
|
1770
1821
|
}
|
|
@@ -1800,60 +1851,67 @@ class ChatCommand {
|
|
|
1800
1851
|
return true;
|
|
1801
1852
|
}
|
|
1802
1853
|
}
|
|
1803
|
-
|
|
1804
|
-
|
|
1805
|
-
|
|
1806
|
-
async tryCommandLevelSaaSRescue(executionPrompt, rawPrompt, workspaceContext, routingPolicy, spinner, error) {
|
|
1807
|
-
const apiAny = this.api;
|
|
1808
|
-
if (typeof apiAny.materializeEmergencySaaSWorkspace !== 'function') {
|
|
1854
|
+
async tryRecoverV3ServiceAndRetry(executionPrompt, rawPrompt, workspaceContext, routingPolicy, spinner, error) {
|
|
1855
|
+
const recovery = await this.api.attemptV3ServiceRecovery((error && error.message) || '');
|
|
1856
|
+
if (!recovery.recovered) {
|
|
1809
1857
|
return false;
|
|
1810
1858
|
}
|
|
1811
|
-
|
|
1812
|
-
if (!appName) {
|
|
1813
|
-
return false;
|
|
1814
|
-
}
|
|
1815
|
-
if (typeof apiAny.ensureAgentFrontendPolish === 'function') {
|
|
1816
|
-
await apiAny.ensureAgentFrontendPolish(executionPrompt, workspaceContext);
|
|
1817
|
-
}
|
|
1818
|
-
const previewGate = await this.api.runTemplateServicePreviewGate(executionPrompt, {
|
|
1819
|
-
...workspaceContext,
|
|
1820
|
-
rawPrompt,
|
|
1821
|
-
});
|
|
1822
|
-
if (spinner) {
|
|
1859
|
+
if (spinner && spinner.isSpinning) {
|
|
1823
1860
|
spinner.stop();
|
|
1824
1861
|
}
|
|
1825
|
-
|
|
1826
|
-
|
|
1827
|
-
console.log(JSON.stringify({
|
|
1828
|
-
success: true,
|
|
1829
|
-
mode: 'agent',
|
|
1830
|
-
model: routingPolicy.selectedModel,
|
|
1831
|
-
routingPolicy,
|
|
1832
|
-
taskId: null,
|
|
1833
|
-
contextId: null,
|
|
1834
|
-
partial: true,
|
|
1835
|
-
content: rescueMessage,
|
|
1836
|
-
metadata: {
|
|
1837
|
-
source: 'cli-saas-rescue',
|
|
1838
|
-
previewGate,
|
|
1839
|
-
rescueReason: error.message,
|
|
1840
|
-
},
|
|
1841
|
-
}, null, 2));
|
|
1862
|
+
if (!this.jsonOutput) {
|
|
1863
|
+
console.log(chalk_1.default.yellow(`V3 recovery: ${recovery.message} Retrying once...`));
|
|
1842
1864
|
}
|
|
1843
|
-
|
|
1844
|
-
|
|
1845
|
-
|
|
1846
|
-
|
|
1847
|
-
|
|
1848
|
-
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
|
|
1852
|
-
|
|
1865
|
+
this.v3IterationCount = 0;
|
|
1866
|
+
this.v3ToolCallCount = 0;
|
|
1867
|
+
this.v3LastActivity = Date.now();
|
|
1868
|
+
this.v3StreamingStarted = false;
|
|
1869
|
+
try {
|
|
1870
|
+
const retryResponse = await this.api.runV3AgentWorkflow(executionPrompt, {
|
|
1871
|
+
workspace: { path: this.currentProjectPath },
|
|
1872
|
+
...workspaceContext,
|
|
1873
|
+
executionSurface: 'cli',
|
|
1874
|
+
clientSurface: 'cli',
|
|
1875
|
+
localMachineCapable: true,
|
|
1876
|
+
agentTimeoutMs: DEFAULT_V3_AGENT_TIMEOUT_MS,
|
|
1877
|
+
agentIdleTimeoutMs: DEFAULT_V3_AGENT_IDLE_TIMEOUT_MS,
|
|
1878
|
+
model: routingPolicy.selectedModel,
|
|
1879
|
+
requestedModel: this.currentModel,
|
|
1880
|
+
agentExecutionPolicy: routingPolicy,
|
|
1881
|
+
legacyFallbackAllowed: this.isLegacyAgentFallbackAllowed(),
|
|
1882
|
+
rawPrompt,
|
|
1883
|
+
history: this.getMessagesForModel(),
|
|
1884
|
+
onStreamEvent: spinner ? (event) => this.updateV3AgentSpinner(spinner, event) : undefined,
|
|
1885
|
+
});
|
|
1886
|
+
if (spinner && spinner.isSpinning) {
|
|
1887
|
+
spinner.stop();
|
|
1853
1888
|
}
|
|
1889
|
+
if (this.v3StreamingStarted) {
|
|
1890
|
+
process.stdout.write('\n');
|
|
1891
|
+
}
|
|
1892
|
+
if (this.jsonOutput) {
|
|
1893
|
+
console.log(JSON.stringify({
|
|
1894
|
+
success: true,
|
|
1895
|
+
mode: 'agent',
|
|
1896
|
+
model: routingPolicy.selectedModel,
|
|
1897
|
+
routingPolicy,
|
|
1898
|
+
taskId: retryResponse.taskId || null,
|
|
1899
|
+
contextId: retryResponse.contextId || null,
|
|
1900
|
+
partial: retryResponse.partial === true,
|
|
1901
|
+
content: retryResponse.content || 'V3 agent workflow completed after recovery.',
|
|
1902
|
+
metadata: { ...(retryResponse.metadata || {}), recoveryAttempted: true },
|
|
1903
|
+
}, null, 2));
|
|
1904
|
+
}
|
|
1905
|
+
else if (!this.v3StreamingStarted && retryResponse.content) {
|
|
1906
|
+
console.log(chalk_1.default.gray(`Agent routing: ${routingPolicy.cloudSelected ? 'Vigthoria Cloud' : 'V3 Agent'}`));
|
|
1907
|
+
console.log(retryResponse.content);
|
|
1908
|
+
}
|
|
1909
|
+
this.messages.push({ role: 'assistant', content: retryResponse.content || 'V3 agent workflow completed after recovery.' });
|
|
1910
|
+
return true;
|
|
1911
|
+
}
|
|
1912
|
+
catch {
|
|
1913
|
+
return false;
|
|
1854
1914
|
}
|
|
1855
|
-
this.messages.push({ role: 'assistant', content: rescueMessage });
|
|
1856
|
-
return true;
|
|
1857
1915
|
}
|
|
1858
1916
|
async startInteractiveChat() {
|
|
1859
1917
|
const chatTitle = this.operatorMode
|
package/dist/index.js
CHANGED
|
@@ -77,6 +77,9 @@ const logger_js_1 = require("./utils/logger.js");
|
|
|
77
77
|
const chalk_1 = __importDefault(require("chalk"));
|
|
78
78
|
const fs = __importStar(require("fs"));
|
|
79
79
|
const path = __importStar(require("path"));
|
|
80
|
+
const os = __importStar(require("os"));
|
|
81
|
+
const crypto_1 = require("crypto");
|
|
82
|
+
const axios_1 = __importDefault(require("axios"));
|
|
80
83
|
function getInvokedBinaryName() {
|
|
81
84
|
const executable = process.argv[1] || 'vigthoria';
|
|
82
85
|
return path.basename(executable, path.extname(executable)).toLowerCase();
|
|
@@ -107,6 +110,7 @@ function getVersion() {
|
|
|
107
110
|
return '1.6.27';
|
|
108
111
|
}
|
|
109
112
|
const VERSION = getVersion();
|
|
113
|
+
const VIGTHORIA_DEFAULT_MANIFEST_URL = process.env.VIGTHORIA_UPDATE_MANIFEST_URL || "https://coder.vigthoria.io/releases/manifest.json";
|
|
110
114
|
/**
|
|
111
115
|
* Compare semantic versions properly
|
|
112
116
|
* Returns: -1 if v1 < v2, 0 if equal, 1 if v1 > v2
|
|
@@ -124,6 +128,40 @@ function compareVersions(v1, v2) {
|
|
|
124
128
|
}
|
|
125
129
|
return 0;
|
|
126
130
|
}
|
|
131
|
+
function resolveManifestEntry(manifest, channel) {
|
|
132
|
+
const normalized = String(channel || 'stable').trim() || 'stable';
|
|
133
|
+
if (manifest.channels && manifest.channels[normalized]) {
|
|
134
|
+
return manifest.channels[normalized];
|
|
135
|
+
}
|
|
136
|
+
const direct = manifest[normalized];
|
|
137
|
+
if (direct && typeof direct === 'object') {
|
|
138
|
+
return direct;
|
|
139
|
+
}
|
|
140
|
+
if (normalized === 'stable') {
|
|
141
|
+
const rootVersion = typeof manifest.version === 'string' ? manifest.version : '';
|
|
142
|
+
const rootUrl = typeof manifest.url === 'string' ? manifest.url : '';
|
|
143
|
+
const rootSha = typeof manifest.sha256 === 'string' ? manifest.sha256 : undefined;
|
|
144
|
+
if (rootVersion && rootUrl) {
|
|
145
|
+
return { version: rootVersion, url: rootUrl, sha256: rootSha };
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
return null;
|
|
149
|
+
}
|
|
150
|
+
async function downloadFile(url, targetPath) {
|
|
151
|
+
const response = await axios_1.default.get(url, {
|
|
152
|
+
responseType: 'arraybuffer',
|
|
153
|
+
timeout: 20000,
|
|
154
|
+
maxRedirects: 5,
|
|
155
|
+
validateStatus: (status) => status >= 200 && status < 300,
|
|
156
|
+
});
|
|
157
|
+
fs.writeFileSync(targetPath, Buffer.from(response.data));
|
|
158
|
+
}
|
|
159
|
+
function sha256File(filePath) {
|
|
160
|
+
const hash = (0, crypto_1.createHash)('sha256');
|
|
161
|
+
const data = fs.readFileSync(filePath);
|
|
162
|
+
hash.update(data);
|
|
163
|
+
return hash.digest('hex');
|
|
164
|
+
}
|
|
127
165
|
// Check for updates silently on startup (non-blocking)
|
|
128
166
|
async function checkForUpdatesQuietly() {
|
|
129
167
|
try {
|
|
@@ -821,11 +859,111 @@ Examples:
|
|
|
821
859
|
program
|
|
822
860
|
.command('update')
|
|
823
861
|
.alias('upgrade')
|
|
824
|
-
.description('Check for updates and upgrade Vigthoria CLI')
|
|
862
|
+
.description('Check for updates and upgrade Vigthoria CLI. Default manifest: https://coder.vigthoria.io/releases/manifest.json')
|
|
825
863
|
.option('-c, --check', 'Only check for updates, don\'t install')
|
|
864
|
+
.option('-f, --from <target>', 'Install update from npm spec, local .tgz path, or URL')
|
|
865
|
+
.option('-m, --manifest <url>', 'Update manifest URL for server-driven releases')
|
|
866
|
+
.option('--channel <name>', 'Release channel to use from manifest (default: stable)', 'stable')
|
|
867
|
+
.option('--allow-downgrade', 'Allow installing an older version from custom update source')
|
|
826
868
|
.action(async (options) => {
|
|
827
|
-
const { execSync } = await import('child_process');
|
|
828
|
-
|
|
869
|
+
const { execSync, execFileSync } = await import('child_process');
|
|
870
|
+
const updateTarget = typeof options.from === 'string' ? options.from.trim() : '';
|
|
871
|
+
const manifestUrl = typeof options.manifest === 'string' ? options.manifest.trim() : VIGTHORIA_DEFAULT_MANIFEST_URL.trim();
|
|
872
|
+
const channel = typeof options.channel === 'string' ? options.channel.trim() : 'stable';
|
|
873
|
+
const allowDowngrade = !!options.allowDowngrade;
|
|
874
|
+
if (updateTarget) {
|
|
875
|
+
try {
|
|
876
|
+
if (options.check) {
|
|
877
|
+
console.log(chalk_1.default.cyan(`Update source configured: ${updateTarget}`));
|
|
878
|
+
console.log(chalk_1.default.gray('Run `vigthoria update --from <target>` to install from this source'));
|
|
879
|
+
return;
|
|
880
|
+
}
|
|
881
|
+
console.log(chalk_1.default.cyan(`Installing update from ${updateTarget}...`));
|
|
882
|
+
execFileSync('npm', ['install', '-g', updateTarget], {
|
|
883
|
+
stdio: 'inherit',
|
|
884
|
+
windowsHide: true,
|
|
885
|
+
});
|
|
886
|
+
console.log(chalk_1.default.green('Update installed successfully'));
|
|
887
|
+
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
888
|
+
return;
|
|
889
|
+
}
|
|
890
|
+
catch (error) {
|
|
891
|
+
console.error(chalk_1.default.red('Failed to install update from target:'), error.message);
|
|
892
|
+
console.log(chalk_1.default.gray(`Try manually: npm install -g ${updateTarget}`));
|
|
893
|
+
return;
|
|
894
|
+
}
|
|
895
|
+
}
|
|
896
|
+
if (manifestUrl) {
|
|
897
|
+
try {
|
|
898
|
+
console.log(chalk_1.default.cyan(`Checking manifest channel ${channel}...`));
|
|
899
|
+
const response = await axios_1.default.get(manifestUrl, {
|
|
900
|
+
timeout: 10000,
|
|
901
|
+
maxRedirects: 5,
|
|
902
|
+
validateStatus: (status) => status >= 200 && status < 300,
|
|
903
|
+
});
|
|
904
|
+
const entry = resolveManifestEntry(response.data || {}, channel);
|
|
905
|
+
if (!entry || !entry.version || !entry.url) {
|
|
906
|
+
console.error(chalk_1.default.red(`Manifest missing valid release entry for channel: ${channel}`));
|
|
907
|
+
console.log(chalk_1.default.gray('Expected: channels.<channel>.version and channels.<channel>.url'));
|
|
908
|
+
return;
|
|
909
|
+
}
|
|
910
|
+
const currentVersion = VERSION;
|
|
911
|
+
const comparison = compareVersions(entry.version, currentVersion);
|
|
912
|
+
if (!allowDowngrade && comparison <= 0) {
|
|
913
|
+
console.log(chalk_1.default.green(`You are running the latest version for channel ${channel} (${currentVersion})`));
|
|
914
|
+
return;
|
|
915
|
+
}
|
|
916
|
+
console.log(chalk_1.default.yellow(`Update available from manifest: ${currentVersion} -> ${entry.version} (${channel})`));
|
|
917
|
+
if (entry.notes) {
|
|
918
|
+
console.log(chalk_1.default.gray(` ${entry.notes}`));
|
|
919
|
+
}
|
|
920
|
+
if (options.check) {
|
|
921
|
+
console.log(chalk_1.default.gray(`Install with: vigthoria update --manifest ${manifestUrl} --channel ${channel}`));
|
|
922
|
+
return;
|
|
923
|
+
}
|
|
924
|
+
const tmpFile = path.join(os.tmpdir(), `vigthoria-update-${Date.now()}.tgz`);
|
|
925
|
+
try {
|
|
926
|
+
console.log(chalk_1.default.cyan('Downloading release package...'));
|
|
927
|
+
await downloadFile(entry.url, tmpFile);
|
|
928
|
+
if (entry.sha256) {
|
|
929
|
+
const expected = entry.sha256.toLowerCase();
|
|
930
|
+
const actual = sha256File(tmpFile).toLowerCase();
|
|
931
|
+
if (actual !== expected) {
|
|
932
|
+
console.error(chalk_1.default.red('Release checksum verification failed'));
|
|
933
|
+
console.error(chalk_1.default.red(`Expected: ${expected}`));
|
|
934
|
+
console.error(chalk_1.default.red(`Actual: ${actual}`));
|
|
935
|
+
return;
|
|
936
|
+
}
|
|
937
|
+
console.log(chalk_1.default.green('Checksum verification passed'));
|
|
938
|
+
}
|
|
939
|
+
else {
|
|
940
|
+
console.log(chalk_1.default.yellow('Manifest entry has no sha256; install proceeded without checksum verification'));
|
|
941
|
+
}
|
|
942
|
+
console.log(chalk_1.default.cyan('Installing update...'));
|
|
943
|
+
execFileSync('npm', ['install', '-g', tmpFile], {
|
|
944
|
+
stdio: 'inherit',
|
|
945
|
+
windowsHide: true,
|
|
946
|
+
});
|
|
947
|
+
console.log(chalk_1.default.green(`Updated to version ${entry.version}`));
|
|
948
|
+
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
949
|
+
return;
|
|
950
|
+
}
|
|
951
|
+
finally {
|
|
952
|
+
if (fs.existsSync(tmpFile)) {
|
|
953
|
+
try {
|
|
954
|
+
fs.unlinkSync(tmpFile);
|
|
955
|
+
}
|
|
956
|
+
catch { }
|
|
957
|
+
}
|
|
958
|
+
}
|
|
959
|
+
}
|
|
960
|
+
catch (error) {
|
|
961
|
+
console.error(chalk_1.default.red('Failed to process manifest update:'), error.message);
|
|
962
|
+
console.log(chalk_1.default.gray('You can still update via npm: npm install -g vigthoria-cli@latest'));
|
|
963
|
+
return;
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
console.log(chalk_1.default.cyan('Checking for updates...'));
|
|
829
967
|
try {
|
|
830
968
|
// Get latest version from npm - cross-platform
|
|
831
969
|
const latestVersion = execSync('npm view vigthoria-cli version', {
|
|
@@ -837,21 +975,21 @@ Examples:
|
|
|
837
975
|
// Use semantic version comparison (1.6.0 > 1.5.9)
|
|
838
976
|
const comparison = compareVersions(latestVersion, currentVersion);
|
|
839
977
|
if (comparison <= 0) {
|
|
840
|
-
console.log(chalk_1.default.green(
|
|
978
|
+
console.log(chalk_1.default.green(`You are running the latest version (${currentVersion})`));
|
|
841
979
|
return;
|
|
842
980
|
}
|
|
843
|
-
console.log(chalk_1.default.yellow(
|
|
981
|
+
console.log(chalk_1.default.yellow(`Update available: ${currentVersion} -> ${latestVersion}`));
|
|
844
982
|
if (options.check) {
|
|
845
983
|
console.log(chalk_1.default.gray('Run `vigthoria update` to install the update'));
|
|
846
984
|
return;
|
|
847
985
|
}
|
|
848
|
-
console.log(chalk_1.default.cyan('
|
|
986
|
+
console.log(chalk_1.default.cyan('Installing update...'));
|
|
849
987
|
execSync('npm install -g vigthoria-cli@latest', { stdio: 'inherit' });
|
|
850
|
-
console.log(chalk_1.default.green(
|
|
988
|
+
console.log(chalk_1.default.green(`Updated to version ${latestVersion}`));
|
|
851
989
|
console.log(chalk_1.default.gray('Please restart the CLI to use the new version'));
|
|
852
990
|
}
|
|
853
991
|
catch (error) {
|
|
854
|
-
console.error(chalk_1.default.red('
|
|
992
|
+
console.error(chalk_1.default.red('Failed to check for updates:'), error.message);
|
|
855
993
|
console.log(chalk_1.default.gray('Try manually: npm install -g vigthoria-cli@latest'));
|
|
856
994
|
}
|
|
857
995
|
});
|
package/dist/utils/api.d.ts
CHANGED
|
@@ -19,6 +19,9 @@ export declare class CLIError extends Error {
|
|
|
19
19
|
export declare function classifyError(error: unknown, fallbackCategory?: CLIErrorCategory): CLIError;
|
|
20
20
|
/** Format a CLIError for user-facing display. */
|
|
21
21
|
export declare function formatCLIError(err: CLIError): string;
|
|
22
|
+
export declare function sanitizeUserFacingErrorText(input: string): string;
|
|
23
|
+
export declare function isServerRuntime(): boolean;
|
|
24
|
+
export declare function describeUpstreamStatus(status: number): string;
|
|
22
25
|
export interface ChatMessage {
|
|
23
26
|
role: 'user' | 'assistant' | 'system';
|
|
24
27
|
content: string;
|
|
@@ -39,8 +42,8 @@ export interface V3AgentWorkflowResponse {
|
|
|
39
42
|
contextId?: string | null;
|
|
40
43
|
backendUrl: string;
|
|
41
44
|
partial?: boolean;
|
|
42
|
-
changedFiles?: Record<string, string>;
|
|
43
45
|
metadata?: Record<string, unknown>;
|
|
46
|
+
changedFiles?: Record<string, string>;
|
|
44
47
|
}
|
|
45
48
|
export interface FrontendPreviewGateResult {
|
|
46
49
|
required: boolean;
|
|
@@ -186,9 +189,6 @@ export interface VigthoriUser {
|
|
|
186
189
|
adminAccess: boolean;
|
|
187
190
|
};
|
|
188
191
|
}
|
|
189
|
-
export declare function sanitizeUserFacingErrorText(input: string): string;
|
|
190
|
-
export declare function isServerRuntime(): boolean;
|
|
191
|
-
export declare function describeUpstreamStatus(status: number): string;
|
|
192
192
|
export declare class APIClient {
|
|
193
193
|
private client;
|
|
194
194
|
private modelRouterClient;
|
|
@@ -197,18 +197,12 @@ export declare class APIClient {
|
|
|
197
197
|
private logger;
|
|
198
198
|
private ws;
|
|
199
199
|
private vigFlowTokens;
|
|
200
|
-
private _httpsAgent;
|
|
201
200
|
constructor(config: Config, logger: Logger);
|
|
202
|
-
/**
|
|
203
|
-
* Destroy keep-alive sockets so the Node.js event loop can drain
|
|
204
|
-
* naturally. Call this before exiting commands that run HTTP probes
|
|
205
|
-
* (e.g. `status`) to avoid the libuv UV_HANDLE_CLOSING assertion
|
|
206
|
-
* on Windows / Node 25+.
|
|
207
|
-
*/
|
|
208
201
|
destroy(): void;
|
|
209
202
|
private getSelfHostedModelsApiUrl;
|
|
210
203
|
login(email: string, password: string): Promise<boolean>;
|
|
211
204
|
loginWithToken(token: string): Promise<boolean>;
|
|
205
|
+
private decodeJwtPayload;
|
|
212
206
|
private extractUserProfile;
|
|
213
207
|
private refreshToken;
|
|
214
208
|
getSubscriptionStatus(): Promise<void>;
|
|
@@ -292,7 +286,6 @@ export declare class APIClient {
|
|
|
292
286
|
private compactV3Context;
|
|
293
287
|
buildMinimalV3AgentContext(context?: Record<string, any>): string;
|
|
294
288
|
private extractEmergencyAppName;
|
|
295
|
-
private materializeEmergencySaaSWorkspace;
|
|
296
289
|
private ensureExecutionContext;
|
|
297
290
|
bindExecutionContext(context?: Record<string, any>): Promise<Record<string, any>>;
|
|
298
291
|
private resolveAgentTargetPath;
|
|
@@ -363,11 +356,6 @@ export declare class APIClient {
|
|
|
363
356
|
* Ensure code has balanced curly braces by appending missing closing braces.
|
|
364
357
|
*/
|
|
365
358
|
private ensureBalancedBraces;
|
|
366
|
-
/**
|
|
367
|
-
* Quick JS/TS syntax validation using Node's built-in parser.
|
|
368
|
-
* Returns true if the code parses without errors.
|
|
369
|
-
*/
|
|
370
|
-
private validateJsSyntax;
|
|
371
359
|
/**
|
|
372
360
|
* Extract the first complete function/class from code.
|
|
373
361
|
* Used as last-resort when the model keeps over-producing.
|
|
@@ -455,6 +443,14 @@ export declare class APIClient {
|
|
|
455
443
|
private getCoderHealth;
|
|
456
444
|
private getModelsHealth;
|
|
457
445
|
private getSelfHostedHealth;
|
|
446
|
+
attemptV3ServiceRecovery(reason?: string, options?: {
|
|
447
|
+
attempts?: number;
|
|
448
|
+
delayMs?: number;
|
|
449
|
+
}): Promise<{
|
|
450
|
+
recovered: boolean;
|
|
451
|
+
message: string;
|
|
452
|
+
endpoint?: string;
|
|
453
|
+
}>;
|
|
458
454
|
private getV3AgentHealth;
|
|
459
455
|
private getHyperLoopHealth;
|
|
460
456
|
private getRepoMemoryHealth;
|