vigthoria-cli 1.12.3 → 1.13.7
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 +1 -1
- package/dist/commands/chat.d.ts +3 -1
- package/dist/commands/chat.js +36 -42
- package/dist/commands/game.d.ts +26 -0
- package/dist/commands/game.js +113 -0
- package/dist/commands/repo.d.ts +9 -1
- package/dist/commands/repo.js +182 -31
- package/dist/commands/v4.d.ts +3 -0
- package/dist/commands/v4.js +12 -0
- package/dist/index.js +117 -58
- package/dist/utils/api.d.ts +1 -0
- package/dist/utils/api.js +99 -62
- package/dist/utils/brain-hub-client.js +42 -14
- package/dist/utils/codebase-indexer.js +29 -6
- package/dist/utils/command-menu.d.ts +11 -0
- package/dist/utils/command-menu.js +97 -0
- package/dist/utils/deckEvents.js +7 -1
- package/dist/utils/requestIntent.d.ts +4 -0
- package/dist/utils/requestIntent.js +16 -1
- package/dist/utils/tools.js +18 -0
- package/install.ps1 +5 -4
- package/install.sh +7 -5
- package/package.json +11 -6
- package/scripts/release/LOCAL_MACHINE_USER_VERIFICATION.md +1 -1
- package/scripts/release/validate-no-go-gates.sh +1 -1
|
@@ -2,6 +2,22 @@
|
|
|
2
2
|
* Brain Hub client — sync workspace index + fetch account brain context
|
|
3
3
|
* via coder.vigthoria.io (JWT-authenticated).
|
|
4
4
|
*/
|
|
5
|
+
// Brain Hub calls are an optional personalization enhancement to an agent
|
|
6
|
+
// turn, not on the critical path. Native `fetch()` has NO default timeout,
|
|
7
|
+
// so a slow/unresponsive coder.vigthoria.io backend previously caused the
|
|
8
|
+
// ENTIRE agent turn to hang indefinitely with zero console output, well
|
|
9
|
+
// before any "ROUTING DECISION" text is printed (2026-07-10 root-cause).
|
|
10
|
+
const BRAIN_HUB_TIMEOUT_MS = 3500;
|
|
11
|
+
async function fetchWithTimeout(url, init = {}, timeoutMs = BRAIN_HUB_TIMEOUT_MS) {
|
|
12
|
+
const controller = new AbortController();
|
|
13
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
14
|
+
try {
|
|
15
|
+
return await fetch(url, { ...init, signal: controller.signal });
|
|
16
|
+
}
|
|
17
|
+
finally {
|
|
18
|
+
clearTimeout(timer);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
5
21
|
export class BrainHubClient {
|
|
6
22
|
apiBase;
|
|
7
23
|
getAuthToken;
|
|
@@ -22,27 +38,39 @@ export class BrainHubClient {
|
|
|
22
38
|
if (!headers.Authorization) {
|
|
23
39
|
return { ok: false, skipped: true, reason: 'not_authenticated' };
|
|
24
40
|
}
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
41
|
+
try {
|
|
42
|
+
const resp = await fetchWithTimeout(`${this.apiBase}/api/brain/sync-index`, {
|
|
43
|
+
method: 'POST',
|
|
44
|
+
headers,
|
|
45
|
+
body: JSON.stringify(payload),
|
|
46
|
+
});
|
|
47
|
+
const data = await resp.json().catch(() => ({}));
|
|
48
|
+
if (!resp.ok) {
|
|
49
|
+
return { ok: false, error: data.error || `HTTP ${resp.status}` };
|
|
50
|
+
}
|
|
51
|
+
return data;
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
const timedOut = error instanceof Error && error.name === 'AbortError';
|
|
55
|
+
return { ok: false, error: timedOut ? `timeout after ${BRAIN_HUB_TIMEOUT_MS}ms` : String(error) };
|
|
33
56
|
}
|
|
34
|
-
return data;
|
|
35
57
|
}
|
|
36
58
|
async fetchAccountContext(limit = 25) {
|
|
37
59
|
const headers = await this.headers();
|
|
38
60
|
if (!headers.Authorization) {
|
|
39
61
|
return { ok: false, formattedText: '', memories: [] };
|
|
40
62
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
63
|
+
try {
|
|
64
|
+
const resp = await fetchWithTimeout(`${this.apiBase}/api/brain/context?limit=${limit}`, { headers });
|
|
65
|
+
const data = await resp.json().catch(() => ({}));
|
|
66
|
+
if (!resp.ok) {
|
|
67
|
+
return { ok: false, formattedText: '', error: data.error || `HTTP ${resp.status}` };
|
|
68
|
+
}
|
|
69
|
+
return data;
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
const timedOut = error instanceof Error && error.name === 'AbortError';
|
|
73
|
+
return { ok: false, formattedText: '', error: timedOut ? `timeout after ${BRAIN_HUB_TIMEOUT_MS}ms` : String(error) };
|
|
45
74
|
}
|
|
46
|
-
return data;
|
|
47
75
|
}
|
|
48
76
|
}
|
|
@@ -23,6 +23,7 @@ export class CodebaseIndexer {
|
|
|
23
23
|
'.DS_Store', 'package-lock.json', 'yarn.lock', 'pnpm-lock.yaml',
|
|
24
24
|
'.vsix', '.map', '.min.js', '.min.css', 'coverage',
|
|
25
25
|
'.cache', '.tmp', 'tmp', 'temp', '.idea', '.vscode',
|
|
26
|
+
'.vigthoria',
|
|
26
27
|
];
|
|
27
28
|
supportedExtensions = new Set([
|
|
28
29
|
'.js', '.ts', '.jsx', '.tsx', '.py', '.java', '.go', '.rs',
|
|
@@ -96,10 +97,23 @@ export class CodebaseIndexer {
|
|
|
96
97
|
for (const filePath of files) {
|
|
97
98
|
this.indexFile(filePath);
|
|
98
99
|
}
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
100
|
+
// The synchronization contract is content-addressed. Stable file and
|
|
101
|
+
// chunk counts must never hide a source modification from the Brain.
|
|
102
|
+
const contentHasher = crypto.createHash('sha256');
|
|
103
|
+
const contentEntries = Array.from(this.fileHashes.entries())
|
|
104
|
+
.map(([filePath, fileHash]) => [
|
|
105
|
+
path.relative(this.workspaceRoot, filePath).split(path.sep).join('/'),
|
|
106
|
+
fileHash,
|
|
107
|
+
])
|
|
108
|
+
.sort(([left], [right]) => left.localeCompare(right));
|
|
109
|
+
for (const [relativePath, fileHash] of contentEntries) {
|
|
110
|
+
contentHasher.update(relativePath, 'utf8');
|
|
111
|
+
contentHasher.update('\0', 'utf8');
|
|
112
|
+
contentHasher.update(fileHash, 'ascii');
|
|
113
|
+
contentHasher.update('\n', 'utf8');
|
|
114
|
+
}
|
|
115
|
+
// Empty workspaces still receive a deterministic, valid SHA-256 value.
|
|
116
|
+
const indexHash = contentHasher.digest('hex');
|
|
103
117
|
const topFiles = files.slice(0, 12).map((filePath) => path.relative(this.workspaceRoot, filePath));
|
|
104
118
|
const meta = {
|
|
105
119
|
indexedFileCount: this.indexedFileCount,
|
|
@@ -308,7 +322,16 @@ export class CodebaseIndexer {
|
|
|
308
322
|
shouldIgnore(name, fullPath) {
|
|
309
323
|
if (name.startsWith('.') && name !== '.env')
|
|
310
324
|
return true;
|
|
311
|
-
const
|
|
312
|
-
|
|
325
|
+
const relativePath = path.relative(this.workspaceRoot, fullPath);
|
|
326
|
+
const segments = relativePath.split(path.sep).map((segment) => segment.toLowerCase());
|
|
327
|
+
const fileName = segments.at(-1) || '';
|
|
328
|
+
const suffixPatterns = new Set(['.vsix', '.map', '.min.js', '.min.css']);
|
|
329
|
+
return this.ignorePatterns.some((rawPattern) => {
|
|
330
|
+
const pattern = rawPattern.toLowerCase();
|
|
331
|
+
if (suffixPatterns.has(pattern)) {
|
|
332
|
+
return fileName.endsWith(pattern);
|
|
333
|
+
}
|
|
334
|
+
return segments.includes(pattern);
|
|
335
|
+
});
|
|
313
336
|
}
|
|
314
337
|
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Command } from 'commander';
|
|
2
|
+
export type CommandFamily = 'Vigthoria Repo Management' | 'Agent Mode' | 'System & Configuration';
|
|
3
|
+
export interface CommandCatalogEntry {
|
|
4
|
+
path: string;
|
|
5
|
+
description: string;
|
|
6
|
+
family: CommandFamily;
|
|
7
|
+
command: Command;
|
|
8
|
+
}
|
|
9
|
+
export declare function buildCommandCatalog(program: Command): CommandCatalogEntry[];
|
|
10
|
+
export declare function renderDynamicHelp(program: Command): string;
|
|
11
|
+
export declare function selectInteractiveCommand(program: Command): Promise<string[] | null>;
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import inquirer from 'inquirer';
|
|
2
|
+
const AGENT_COMMANDS = new Set([
|
|
3
|
+
'agent', 'chat', 'chat-resume', 'operator', 'legion', 'workflow',
|
|
4
|
+
'history', 'replay', 'fork', 'cancel',
|
|
5
|
+
]);
|
|
6
|
+
function familyFor(commandPath) {
|
|
7
|
+
const root = commandPath.split(' ')[0];
|
|
8
|
+
if (root === 'repo')
|
|
9
|
+
return 'Vigthoria Repo Management';
|
|
10
|
+
if (AGENT_COMMANDS.has(root))
|
|
11
|
+
return 'Agent Mode';
|
|
12
|
+
return 'System & Configuration';
|
|
13
|
+
}
|
|
14
|
+
export function buildCommandCatalog(program) {
|
|
15
|
+
const entries = [];
|
|
16
|
+
const visit = (command, parents) => {
|
|
17
|
+
const commandPath = [...parents, command.name()].join(' ');
|
|
18
|
+
entries.push({
|
|
19
|
+
path: commandPath,
|
|
20
|
+
description: command.description() || '',
|
|
21
|
+
family: familyFor(commandPath),
|
|
22
|
+
command,
|
|
23
|
+
});
|
|
24
|
+
for (const child of command.commands)
|
|
25
|
+
visit(child, [...parents, command.name()]);
|
|
26
|
+
};
|
|
27
|
+
for (const command of program.commands)
|
|
28
|
+
visit(command, []);
|
|
29
|
+
return entries.sort((left, right) => left.family.localeCompare(right.family) || left.path.localeCompare(right.path));
|
|
30
|
+
}
|
|
31
|
+
export function renderDynamicHelp(program) {
|
|
32
|
+
const catalog = buildCommandCatalog(program);
|
|
33
|
+
const lines = ['Commands:'];
|
|
34
|
+
const families = [
|
|
35
|
+
'Vigthoria Repo Management',
|
|
36
|
+
'Agent Mode',
|
|
37
|
+
'System & Configuration',
|
|
38
|
+
];
|
|
39
|
+
for (const family of families) {
|
|
40
|
+
lines.push('', `${family}:`);
|
|
41
|
+
for (const entry of catalog.filter((candidate) => candidate.family === family)) {
|
|
42
|
+
const aliases = entry.command.aliases();
|
|
43
|
+
const displayPath = aliases.length
|
|
44
|
+
? `${entry.path} (${aliases.join(', ')})`
|
|
45
|
+
: entry.path;
|
|
46
|
+
lines.push(` ${displayPath.padEnd(30)} ${entry.description}`);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return lines.join('\n');
|
|
50
|
+
}
|
|
51
|
+
async function collectRequiredArguments(entry) {
|
|
52
|
+
const values = [];
|
|
53
|
+
for (const argument of entry.command.registeredArguments) {
|
|
54
|
+
if (!argument.required)
|
|
55
|
+
continue;
|
|
56
|
+
const answer = await inquirer.prompt([{
|
|
57
|
+
type: 'input',
|
|
58
|
+
name: 'value',
|
|
59
|
+
message: `${argument.name()}:`,
|
|
60
|
+
validate: (value) => value.trim().length > 0 || `${argument.name()} is required`,
|
|
61
|
+
}]);
|
|
62
|
+
values.push(String(answer.value).trim());
|
|
63
|
+
}
|
|
64
|
+
return values;
|
|
65
|
+
}
|
|
66
|
+
export async function selectInteractiveCommand(program) {
|
|
67
|
+
const catalog = buildCommandCatalog(program);
|
|
68
|
+
const familyAnswer = await inquirer.prompt([{
|
|
69
|
+
type: 'list',
|
|
70
|
+
name: 'family',
|
|
71
|
+
message: 'Select a command family:',
|
|
72
|
+
choices: [
|
|
73
|
+
'Vigthoria Repo Management',
|
|
74
|
+
'Agent Mode',
|
|
75
|
+
'System & Configuration',
|
|
76
|
+
new inquirer.Separator(),
|
|
77
|
+
{ name: 'Exit', value: null },
|
|
78
|
+
],
|
|
79
|
+
}]);
|
|
80
|
+
if (!familyAnswer.family)
|
|
81
|
+
return null;
|
|
82
|
+
const entries = catalog.filter((entry) => entry.family === familyAnswer.family && entry.command.commands.length === 0);
|
|
83
|
+
const commandAnswer = await inquirer.prompt([{
|
|
84
|
+
type: 'list',
|
|
85
|
+
name: 'path',
|
|
86
|
+
message: `${familyAnswer.family}:`,
|
|
87
|
+
pageSize: 20,
|
|
88
|
+
choices: entries.map((entry) => ({
|
|
89
|
+
name: `${entry.path.padEnd(24)} ${entry.description}`,
|
|
90
|
+
value: entry.path,
|
|
91
|
+
})),
|
|
92
|
+
}]);
|
|
93
|
+
const selected = entries.find((entry) => entry.path === commandAnswer.path);
|
|
94
|
+
if (!selected)
|
|
95
|
+
return null;
|
|
96
|
+
return [...selected.path.split(' '), ...await collectRequiredArguments(selected)];
|
|
97
|
+
}
|
package/dist/utils/deckEvents.js
CHANGED
|
@@ -14,7 +14,13 @@ export function emitDeckEvent(event) {
|
|
|
14
14
|
...event,
|
|
15
15
|
ts: event.ts ?? Date.now(),
|
|
16
16
|
};
|
|
17
|
-
|
|
17
|
+
// Force the marker onto its own fresh line. Callers may have just updated an
|
|
18
|
+
// in-place spinner (e.g. ora) which redraws via "\r" and never emits a
|
|
19
|
+
// trailing "\n", so without this leading newline the marker can land stuck
|
|
20
|
+
// mid-line after visible text (e.g. "Executing plan...@vigthoria-deck:{...}")
|
|
21
|
+
// and the Workbench's line-start prefix check won't strip it, leaking raw
|
|
22
|
+
// JSON into the terminal.
|
|
23
|
+
process.stdout.write(`\n${DECK_PREFIX}${JSON.stringify(payload)}\n`);
|
|
18
24
|
}
|
|
19
25
|
export function parseDeckLine(line) {
|
|
20
26
|
const trimmed = line.trim();
|
|
@@ -9,6 +9,8 @@ export type IntentContext = {
|
|
|
9
9
|
export declare function stripExecutionShaping(prompt: string): string;
|
|
10
10
|
export declare function hasBuildVerb(prompt: string): boolean;
|
|
11
11
|
export declare function hasArtifactNoun(prompt: string): boolean;
|
|
12
|
+
export type GameEngineHint = 'babylon' | 'three' | 'canvas-2d';
|
|
13
|
+
export declare function inferGameEngine(prompt: string): GameEngineHint;
|
|
12
14
|
export declare function hasGameIntent(prompt: string): boolean;
|
|
13
15
|
/** True when the CLI already expanded a /continue-style follow-up prompt. */
|
|
14
16
|
export declare function isBuiltContinuePrompt(prompt: string): boolean;
|
|
@@ -52,4 +54,6 @@ export declare function buildExecutionHints(agentTaskType: string, prompt: strin
|
|
|
52
54
|
classify_from: string;
|
|
53
55
|
workflow_type: 'analysis_only' | 'full';
|
|
54
56
|
fast_path?: string;
|
|
57
|
+
game_engine?: GameEngineHint;
|
|
58
|
+
render_transport?: 'client-state';
|
|
55
59
|
};
|
|
@@ -7,7 +7,7 @@ const READONLY_SHAPING_BLOCK = /(?:^|\n\n)(?:Read-only analysis mode is active\.
|
|
|
7
7
|
const BUILD_VERBS = /\b(build|create|make|implement|complete|fix|repair|edit|modify|write|generate|add|finish|scaffold|develop|update|change|refactor|want|need|require|looking for|let's|let us|we need|we should|erstelle|erstellen|schreib|schreibe|bearbeite)\b/i;
|
|
8
8
|
const ARTIFACT_NOUNS = /\b(file|files|project|game|spiel|app|website|html5|frontend|component|feature|code|workspace|repo|clone|replica|remake|page|site|screen|button|popup|modal|alert|canvas|sprite|level|levels|enemy|enemies|character|npc|world|scene|script|module|api|database|config|landing|dashboard|platformer|arcade|playable|collectible|scoreboard|leaderboard|pitfall|pacman|rogue|html|css|javascript|typescript)\b/i;
|
|
9
9
|
/** Canvas/playable games only — bare "html5" or "website" must NOT match. */
|
|
10
|
-
const GAME_INTENT = /\b(game|spiel|playable|html5\s+(?:game|canvas)|html5\s+game|canvas\s+game|game\s+canvas|arcade|platformer|side[- ]?scroller|pitfall|pac[- ]?man|tetris|snake|breakout|pong|roguelike|metroidvania|tower\s+defense|clone\s+of\s+(?:a\s+)?(?:game|pitfall|pac|mario|zelda|arcade)|gameplay|collectible|boss\s+fight|level\s+design|sprite\s+sheet|wild\s+(?:boar|pig|forest)|forest\s+pig)\b/i;
|
|
10
|
+
const GAME_INTENT = /\b(game|spiel|playable|babylon(?:\.js|js)?|vge|webgl|3d\s+(?:game|runner|prototype|world|experience)|html5\s+(?:game|canvas)|html5\s+game|canvas\s+game|game\s+canvas|arcade|platformer|side[- ]?scroller|pitfall|pac[- ]?man|tetris|snake|breakout|pong|roguelike|metroidvania|tower\s+defense|clone\s+of\s+(?:a\s+)?(?:game|pitfall|pac|mario|zelda|arcade)|gameplay|collectible|boss\s+fight|level\s+design|sprite\s+sheet|wild\s+(?:boar|pig|forest)|forest\s+pig)\b/i;
|
|
11
11
|
const WEB_PAGE_INTENT = /\b(website|web\s*site|webpage|web\s*page|landing\s+page|home\s*page|index\.html|html\s+page|static\s+page|single\s+page|popup|alert|modal|hello\s+world)\b/i;
|
|
12
12
|
const CLONE_BUILD = /\bclone\s+of\b|\b(build|create|make)\s+(?:a|an|the|us|me)?\s*(?:clone|replica|remake|port)\b/i;
|
|
13
13
|
const READ_ONLY_INTENT = /\b(analy[sz]e|analyse|analysis|audit|review|inspect|proof|understand|summari[sz]e|scan|read[\s-]?only|where we left|what is|how does|show me|tell me|identify\s+gaps?|gap\s+analysis|production\s+blockers?)\b/i;
|
|
@@ -34,6 +34,16 @@ export function hasArtifactNoun(prompt) {
|
|
|
34
34
|
}
|
|
35
35
|
/** Game clones require a game target — generic "clone of X" must not imply game-build. */
|
|
36
36
|
const GAME_CLONE_TARGET = /\bclone\s+of\s+(?:a\s+)?(?:the\s+)?(?:game|pitfall|pac[- ]?man|mario|zelda|tetris|snake|arcade|spiel)\b/i;
|
|
37
|
+
export function inferGameEngine(prompt) {
|
|
38
|
+
const text = stripExecutionShaping(prompt);
|
|
39
|
+
if (/\bthree(?:\.js|js)?\b/i.test(text))
|
|
40
|
+
return 'three';
|
|
41
|
+
if (/\bbabylon(?:\.js|js)?\b|\bvge\b|vigthoria gaming engine/i.test(text))
|
|
42
|
+
return 'babylon';
|
|
43
|
+
if (/\b3d\s+(?:game|runner|prototype|world|experience)\b|\bwebgl\b/i.test(text))
|
|
44
|
+
return 'babylon';
|
|
45
|
+
return 'canvas-2d';
|
|
46
|
+
}
|
|
37
47
|
export function hasGameIntent(prompt) {
|
|
38
48
|
const text = stripExecutionShaping(prompt);
|
|
39
49
|
if (GAME_INTENT.test(text)) {
|
|
@@ -370,6 +380,11 @@ export function buildExecutionHints(agentTaskType, prompt, options = {}) {
|
|
|
370
380
|
classify_from: String(prompt || ''),
|
|
371
381
|
workflow_type: workflowType,
|
|
372
382
|
};
|
|
383
|
+
if (kind === 'game-build' || hasGameIntent(prompt)) {
|
|
384
|
+
hints.game_engine = inferGameEngine(prompt);
|
|
385
|
+
if (hints.game_engine === 'babylon')
|
|
386
|
+
hints.render_transport = 'client-state';
|
|
387
|
+
}
|
|
373
388
|
if (options.fastPath) {
|
|
374
389
|
hints.fast_path = options.fastPath;
|
|
375
390
|
}
|
package/dist/utils/tools.js
CHANGED
|
@@ -2104,6 +2104,24 @@ export class AgenticTools {
|
|
|
2104
2104
|
result = await response.json();
|
|
2105
2105
|
if (response.ok && result.success)
|
|
2106
2106
|
break;
|
|
2107
|
+
if (result.code === 'REPOSITORY_SECURITY_REVIEW') {
|
|
2108
|
+
return {
|
|
2109
|
+
success: false,
|
|
2110
|
+
error: result.error || 'Repository security review required',
|
|
2111
|
+
metadata: {
|
|
2112
|
+
code: result.code,
|
|
2113
|
+
review: {
|
|
2114
|
+
reviewId: result.reviewId,
|
|
2115
|
+
status: result.status,
|
|
2116
|
+
riskScore: result.riskScore,
|
|
2117
|
+
findings: result.findings || [],
|
|
2118
|
+
actionItems: result.actionItems || [],
|
|
2119
|
+
retryCommand: result.retryCommand,
|
|
2120
|
+
},
|
|
2121
|
+
},
|
|
2122
|
+
suggestion: `Inspect with "vigthoria repo review ${result.reviewId}" and retry corrected content with "${result.retryCommand || `vigthoria repo push --retry ${result.reviewId}`}".`,
|
|
2123
|
+
};
|
|
2124
|
+
}
|
|
2107
2125
|
lastError = result.error || result.message || `Status ${response.status}`;
|
|
2108
2126
|
result = null;
|
|
2109
2127
|
}
|
package/install.ps1
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
$ErrorActionPreference = "Stop"
|
|
6
6
|
|
|
7
7
|
# Configuration
|
|
8
|
-
$CLI_VERSION = "1.
|
|
8
|
+
$CLI_VERSION = "1.13.7"
|
|
9
9
|
$INSTALL_DIR = "$env:USERPROFILE\.vigthoria"
|
|
10
10
|
$NPM_PACKAGE = "vigthoria-cli"
|
|
11
11
|
$GIT_PACKAGE_URL = "git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
|
|
@@ -74,11 +74,12 @@ function Test-Prerequisites {
|
|
|
74
74
|
try {
|
|
75
75
|
$nodeVersion = node -v 2>$null
|
|
76
76
|
if ($nodeVersion) {
|
|
77
|
-
$
|
|
78
|
-
|
|
77
|
+
$versionText = $nodeVersion.TrimStart('v')
|
|
78
|
+
$parsedVersion = [version]$versionText
|
|
79
|
+
if ($parsedVersion -ge [version]"20.19.0") {
|
|
79
80
|
Write-Host "✓ Node.js $nodeVersion" -ForegroundColor Green
|
|
80
81
|
} else {
|
|
81
|
-
Write-Host "✗ Node.js
|
|
82
|
+
Write-Host "✗ Node.js 20.19+ required (found $nodeVersion)" -ForegroundColor Red
|
|
82
83
|
Write-Host " Download from: https://nodejs.org/" -ForegroundColor Yellow
|
|
83
84
|
return $false
|
|
84
85
|
}
|
package/install.sh
CHANGED
|
@@ -26,7 +26,7 @@ else
|
|
|
26
26
|
fi
|
|
27
27
|
|
|
28
28
|
# Configuration
|
|
29
|
-
CLI_VERSION="1.
|
|
29
|
+
CLI_VERSION="1.13.7"
|
|
30
30
|
INSTALL_DIR="$HOME/.vigthoria"
|
|
31
31
|
REPO_URL="https://market.vigthoria.io/vigthoria/vigthoria-cli"
|
|
32
32
|
GIT_PACKAGE_URL="git+https://market.vigthoria.io/vigthoria/vigthoria-cli.git"
|
|
@@ -130,7 +130,7 @@ check_requirements() {
|
|
|
130
130
|
if ! command -v node &> /dev/null; then
|
|
131
131
|
echo -e "${RED}✗ Node.js is not installed${NC}"
|
|
132
132
|
echo ""
|
|
133
|
-
echo " Please install Node.js
|
|
133
|
+
echo " Please install Node.js 20.19 or later:"
|
|
134
134
|
if [ "$PLATFORM" = "macos" ]; then
|
|
135
135
|
echo " brew install node"
|
|
136
136
|
echo " or download from: https://nodejs.org/"
|
|
@@ -144,9 +144,11 @@ check_requirements() {
|
|
|
144
144
|
exit 1
|
|
145
145
|
fi
|
|
146
146
|
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
147
|
+
NODE_VERSION_FULL=$(node -v | sed 's/^v//')
|
|
148
|
+
NODE_VERSION_MAJOR=$(printf '%s' "$NODE_VERSION_FULL" | cut -d'.' -f1)
|
|
149
|
+
NODE_VERSION_MINOR=$(printf '%s' "$NODE_VERSION_FULL" | cut -d'.' -f2)
|
|
150
|
+
if [ "$NODE_VERSION_MAJOR" -lt 20 ] || { [ "$NODE_VERSION_MAJOR" -eq 20 ] && [ "$NODE_VERSION_MINOR" -lt 19 ]; }; then
|
|
151
|
+
echo -e "${RED}✗ Node.js version must be 20.19 or higher (found: v$NODE_VERSION_FULL)${NC}"
|
|
150
152
|
exit 1
|
|
151
153
|
fi
|
|
152
154
|
echo -e "${GREEN}✓ Node.js v$(node -v | cut -d'v' -f2)${NC}"
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "vigthoria-cli",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.13.7",
|
|
4
4
|
"description": "Vigthoria Coder CLI - AI-powered terminal coding assistant",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -60,10 +60,12 @@
|
|
|
60
60
|
"test:package:hygiene": "npm run build && node scripts/verify-package-hygiene.js",
|
|
61
61
|
"test:v3:platforms": "npm run build && node scripts/test-v3-platforms-e2e.js",
|
|
62
62
|
"test:repo:live": "npm run build && node scripts/test-live-repo-e2e.js",
|
|
63
|
+
"test:repo:auth-fallback": "node scripts/test-community-repo-auth-fallback.mjs",
|
|
64
|
+
"test:repo:payload-fallback": "node scripts/test-repo-payload-fallback.mjs",
|
|
63
65
|
"test:game:live": "npm run build && node scripts/test-live-game-push.js",
|
|
64
66
|
"proof:agent": "npm run build && node scripts/proof-agent-mode.js",
|
|
65
67
|
"test:fresh-install": "node scripts/test-fresh-install.js",
|
|
66
|
-
"prepublishOnly": "npm run build && npm run validate:no-go && node scripts/verify-package-hygiene.js && node scripts/test-fresh-install.js",
|
|
68
|
+
"prepublishOnly": "npm run build && npm run validate:no-go && npm run test:repo:auth-fallback && npm run test:repo:payload-fallback && node scripts/verify-package-hygiene.js && node scripts/test-fresh-install.js",
|
|
67
69
|
"precheck:services": "node scripts/precheck-local-services.js",
|
|
68
70
|
"test:model:governance": "npm run build && node scripts/test-model-governance-no-agent.js",
|
|
69
71
|
"validate:no-go": "bash scripts/release/validate-no-go-gates.sh",
|
|
@@ -73,7 +75,9 @@
|
|
|
73
75
|
"test:session:project-match": "npm run build && node scripts/test-session-project-match.mjs",
|
|
74
76
|
"test:v3-stream-mutation": "npm run build && node scripts/test-v3-stream-mutation.js",
|
|
75
77
|
"test:context:budget": "npm run build && node scripts/test-context-budget.js",
|
|
76
|
-
"test:
|
|
78
|
+
"test:v3-client-tool-quality": "npm run build && node scripts/test-v3-client-tool-quality.mjs",
|
|
79
|
+
"test:pitfall:context": "npm run build && node scripts/test-pitfall-context-smoke.js",
|
|
80
|
+
"test:game:command": "node scripts/test-game-command.mjs"
|
|
77
81
|
},
|
|
78
82
|
"keywords": [
|
|
79
83
|
"ai",
|
|
@@ -87,7 +91,7 @@
|
|
|
87
91
|
"author": "Vigthoria Technologies",
|
|
88
92
|
"license": "MIT",
|
|
89
93
|
"dependencies": {
|
|
90
|
-
"archiver": "^
|
|
94
|
+
"archiver": "^8.0.0",
|
|
91
95
|
"axios": "^1.6.0",
|
|
92
96
|
"chalk": "^5.3.0",
|
|
93
97
|
"chokidar": "^5.0.0",
|
|
@@ -114,9 +118,10 @@
|
|
|
114
118
|
"typescript": "^5.3.2"
|
|
115
119
|
},
|
|
116
120
|
"engines": {
|
|
117
|
-
"node": ">=
|
|
121
|
+
"node": ">=20.19.0"
|
|
118
122
|
},
|
|
119
123
|
"overrides": {
|
|
120
|
-
"glob": "^13.0.6"
|
|
124
|
+
"glob": "^13.0.6",
|
|
125
|
+
"brace-expansion": "^5.0.8"
|
|
121
126
|
}
|
|
122
127
|
}
|
|
@@ -4,7 +4,7 @@ Use this checklist on real user machines before and after rollout. The goal is t
|
|
|
4
4
|
|
|
5
5
|
## 1. Preflight
|
|
6
6
|
|
|
7
|
-
- [ ] Node.js `>=
|
|
7
|
+
- [ ] Node.js `>=20.19` available
|
|
8
8
|
- [ ] `npm` available
|
|
9
9
|
- [ ] No stale shell aliases shadowing `vigthoria`
|
|
10
10
|
- [ ] Network access to:
|