vigthoria-cli 1.10.48 → 1.10.49
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/agent-session-menu.js +2 -8
- package/dist/commands/bridge.js +36 -9
- package/dist/commands/chat.d.ts +3 -28
- package/dist/commands/chat.js +326 -295
- package/dist/commands/fork.js +1 -1
- package/dist/commands/history.js +1 -1
- package/dist/commands/replay.js +1 -1
- package/dist/index.js +40 -214
- package/dist/utils/api.d.ts +25 -53
- package/dist/utils/api.js +300 -1443
- package/dist/utils/config.d.ts +0 -3
- package/dist/utils/config.js +2 -0
- package/dist/utils/desktop-bridge-client.d.ts +12 -0
- package/dist/utils/desktop-bridge-client.js +30 -0
- package/dist/utils/post-write-validator.js +5 -5
- package/dist/utils/tools.d.ts +0 -7
- package/dist/utils/tools.js +15 -87
- package/package.json +2 -1
- package/scripts/release/validate-no-go-gates.sh +7 -4
package/dist/utils/config.d.ts
CHANGED
package/dist/utils/config.js
CHANGED
|
@@ -185,6 +185,7 @@ export class Config {
|
|
|
185
185
|
getAvailableModels() {
|
|
186
186
|
const sub = this.store.get('subscription');
|
|
187
187
|
const plan = (sub.plan || '').toLowerCase();
|
|
188
|
+
void plan;
|
|
188
189
|
// ═══════════════════════════════════════════════════════════════
|
|
189
190
|
// Vigthoria server infrastructure operational models
|
|
190
191
|
// ═══════════════════════════════════════════════════════════════
|
|
@@ -262,6 +263,7 @@ export class Config {
|
|
|
262
263
|
// DISABLED: Cloud routing is now EXPLICIT ONLY (--model cloud or /cloud command)
|
|
263
264
|
// Do NOT auto-route based on keywords. User must opt-in.
|
|
264
265
|
// If user wants cloud: they'll use --model cloud or request it explicitly.
|
|
266
|
+
void prompt;
|
|
265
267
|
return false;
|
|
266
268
|
}
|
|
267
269
|
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface DesktopBridgeStatus {
|
|
2
|
+
ok: boolean;
|
|
3
|
+
endpoint: string;
|
|
4
|
+
service?: string;
|
|
5
|
+
version?: string;
|
|
6
|
+
controlEnabled?: boolean;
|
|
7
|
+
error?: string;
|
|
8
|
+
}
|
|
9
|
+
export declare function getDesktopBridgeStatus(options?: {
|
|
10
|
+
url?: string;
|
|
11
|
+
timeoutMs?: number;
|
|
12
|
+
}): Promise<DesktopBridgeStatus>;
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
export async function getDesktopBridgeStatus(options = {}) {
|
|
2
|
+
const endpoint = options.url
|
|
3
|
+
|| process.env.VIGTHORIA_DESKTOP_BRIDGE_URL
|
|
4
|
+
|| `http://${process.env.VIGTHORIA_DESKTOP_HOST || '127.0.0.1'}:${process.env.VIGTHORIA_DESKTOP_PORT || '49160'}`;
|
|
5
|
+
const timeoutMs = options.timeoutMs ?? 5000;
|
|
6
|
+
try {
|
|
7
|
+
const controller = new AbortController();
|
|
8
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
9
|
+
const response = await fetch(`${endpoint.replace(/\/$/, '')}/health`, {
|
|
10
|
+
signal: controller.signal,
|
|
11
|
+
headers: { Accept: 'application/json' },
|
|
12
|
+
});
|
|
13
|
+
clearTimeout(timer);
|
|
14
|
+
if (!response.ok) {
|
|
15
|
+
return { ok: false, endpoint, error: `HTTP ${response.status}` };
|
|
16
|
+
}
|
|
17
|
+
const data = await response.json();
|
|
18
|
+
return {
|
|
19
|
+
ok: true,
|
|
20
|
+
endpoint,
|
|
21
|
+
service: typeof data.service === 'string' ? data.service : undefined,
|
|
22
|
+
version: typeof data.version === 'string' ? data.version : undefined,
|
|
23
|
+
controlEnabled: data.controlEnabled === true || data.control_enabled === true,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
catch (error) {
|
|
27
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
28
|
+
return { ok: false, endpoint, error: message };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -31,16 +31,16 @@ function resolveTscBin(workspacePath) {
|
|
|
31
31
|
const localTsc = path.join(workspacePath, 'node_modules', '.bin', 'tsc');
|
|
32
32
|
if (fs.existsSync(localTsc))
|
|
33
33
|
return { cmd: localTsc, args: ["--noEmit", "--skipLibCheck"] };
|
|
34
|
-
try {
|
|
35
|
-
execFileSync("npx", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
|
|
36
|
-
return { cmd: "npx", args: ["tsc", "--noEmit", "--skipLibCheck"] };
|
|
37
|
-
}
|
|
38
|
-
catch { /* npx not available */ }
|
|
39
34
|
try {
|
|
40
35
|
execFileSync("tsc", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
|
|
41
36
|
return { cmd: "tsc", args: ["--noEmit", "--skipLibCheck"] };
|
|
42
37
|
}
|
|
43
38
|
catch { /* tsc not available */ }
|
|
39
|
+
try {
|
|
40
|
+
execFileSync("npx", ["--version"], { stdio: "pipe", timeout: 4000, windowsHide: true });
|
|
41
|
+
return { cmd: "npx", args: ["--yes", "tsc", "--noEmit", "--skipLibCheck"] };
|
|
42
|
+
}
|
|
43
|
+
catch { /* npx not available */ }
|
|
44
44
|
return null;
|
|
45
45
|
}
|
|
46
46
|
function hasRealTestScript(dir) {
|
package/dist/utils/tools.d.ts
CHANGED
|
@@ -95,15 +95,10 @@ export declare class AgenticTools {
|
|
|
95
95
|
private requireNonEmptyString;
|
|
96
96
|
private requireArgsObject;
|
|
97
97
|
private sessionApprovedTools;
|
|
98
|
-
private indexedCodebaseSearch;
|
|
99
98
|
private static permissionsFile;
|
|
100
99
|
constructor(logger: Logger, cwd: string, permissionCallback: (action: string, options?: {
|
|
101
100
|
batchApproval?: boolean;
|
|
102
101
|
}) => Promise<boolean | 'batch' | 'persist'>, autoApprove?: boolean);
|
|
103
|
-
/** Rebind tool execution to a different local workspace root (e.g. prompt path override). */
|
|
104
|
-
setWorkspaceRoot(cwd: string): void;
|
|
105
|
-
setIndexedCodebaseSearch(handler: ((query: string, maxResults: number) => string) | null): void;
|
|
106
|
-
getWorkspaceRoot(): string;
|
|
107
102
|
private getErrorMessage;
|
|
108
103
|
private assertToolCall;
|
|
109
104
|
/**
|
|
@@ -188,8 +183,6 @@ export declare class AgenticTools {
|
|
|
188
183
|
*/
|
|
189
184
|
private formatPermissionRequest;
|
|
190
185
|
private sleep;
|
|
191
|
-
private bridgeToolsEnabled;
|
|
192
|
-
private tryBridgeReadFile;
|
|
193
186
|
/**
|
|
194
187
|
* Read file with enhanced error handling and suggestions
|
|
195
188
|
*/
|
package/dist/utils/tools.js
CHANGED
|
@@ -433,7 +433,6 @@ export class AgenticTools {
|
|
|
433
433
|
}
|
|
434
434
|
// Session-based tool approvals - remembers which tools user approved for this turn
|
|
435
435
|
sessionApprovedTools = new Set();
|
|
436
|
-
indexedCodebaseSearch = null;
|
|
437
436
|
// Persistent permissions - tool allowlists per project
|
|
438
437
|
static permissionsFile = path.join(process.env.HOME || process.env.USERPROFILE || '~', '.vigthoria', 'permissions.json');
|
|
439
438
|
constructor(logger, cwd, permissionCallback, autoApprove = false) {
|
|
@@ -450,23 +449,10 @@ export class AgenticTools {
|
|
|
450
449
|
throw new Error('AgenticTools initialization failed: autoApprove must be a boolean.');
|
|
451
450
|
}
|
|
452
451
|
this.logger = logger;
|
|
453
|
-
this.cwd =
|
|
452
|
+
this.cwd = cwd;
|
|
454
453
|
this.permissionCallback = permissionCallback;
|
|
455
454
|
this.autoApprove = autoApprove;
|
|
456
455
|
}
|
|
457
|
-
/** Rebind tool execution to a different local workspace root (e.g. prompt path override). */
|
|
458
|
-
setWorkspaceRoot(cwd) {
|
|
459
|
-
if (typeof cwd !== 'string' || cwd.trim().length === 0) {
|
|
460
|
-
throw new Error('AgenticTools.setWorkspaceRoot failed: cwd must be a non-empty string.');
|
|
461
|
-
}
|
|
462
|
-
this.cwd = path.resolve(cwd);
|
|
463
|
-
}
|
|
464
|
-
setIndexedCodebaseSearch(handler) {
|
|
465
|
-
this.indexedCodebaseSearch = handler;
|
|
466
|
-
}
|
|
467
|
-
getWorkspaceRoot() {
|
|
468
|
-
return this.cwd;
|
|
469
|
-
}
|
|
470
456
|
getErrorMessage(error) {
|
|
471
457
|
if (error instanceof Error) {
|
|
472
458
|
return error.message;
|
|
@@ -849,19 +835,8 @@ export class AgenticTools {
|
|
|
849
835
|
}
|
|
850
836
|
// Check permission for dangerous/modifying actions
|
|
851
837
|
if (tool.requiresPermission && !this.autoApprove) {
|
|
852
|
-
|
|
853
|
-
if (
|
|
854
|
-
const approved = await this.permissionCallback(this.formatPermissionRequest(normalizedCall, tool), { batchApproval: false });
|
|
855
|
-
if (approved === false) {
|
|
856
|
-
return {
|
|
857
|
-
success: false,
|
|
858
|
-
error: 'Permission denied by user',
|
|
859
|
-
canRetry: true,
|
|
860
|
-
};
|
|
861
|
-
}
|
|
862
|
-
}
|
|
863
|
-
else if (this.hasPersistentPermission(normalizedCall.tool)) {
|
|
864
|
-
// Check persistent permissions first (project-scoped), then session
|
|
838
|
+
// Check persistent permissions first (project-scoped), then session
|
|
839
|
+
if (this.hasPersistentPermission(normalizedCall.tool)) {
|
|
865
840
|
this.logger.info(`${call.tool}: Auto-approved (persistent)`);
|
|
866
841
|
}
|
|
867
842
|
else if (this.sessionApprovedTools.has(normalizedCall.tool)) {
|
|
@@ -1248,52 +1223,10 @@ export class AgenticTools {
|
|
|
1248
1223
|
return new Promise(resolve => setTimeout(resolve, ms));
|
|
1249
1224
|
}
|
|
1250
1225
|
// Tool implementations with enhanced error handling and undo support
|
|
1251
|
-
bridgeToolsEnabled() {
|
|
1252
|
-
const flag = String(process.env.VIGTHORIA_BRIDGE_TOOLS || '').trim().toLowerCase();
|
|
1253
|
-
return flag === '1' || flag === 'true' || flag === 'yes' || flag === 'on';
|
|
1254
|
-
}
|
|
1255
|
-
tryBridgeReadFile(args) {
|
|
1256
|
-
if (!this.bridgeToolsEnabled()) {
|
|
1257
|
-
return null;
|
|
1258
|
-
}
|
|
1259
|
-
const bridgeBase = String(process.env.VIGTHORIA_BRIDGE_HTTP
|
|
1260
|
-
|| process.env.VIGTHORIA_DESKTOP_BRIDGE_URL
|
|
1261
|
-
|| 'http://127.0.0.1:49160').replace(/\/$/, '');
|
|
1262
|
-
const targetPath = args.path || '';
|
|
1263
|
-
if (!targetPath) {
|
|
1264
|
-
return null;
|
|
1265
|
-
}
|
|
1266
|
-
try {
|
|
1267
|
-
const response = execSync(`curl -sS -m 15 -X POST "${bridgeBase}/tools/read_file" -H "Content-Type: application/json" -d ${JSON.stringify(JSON.stringify({
|
|
1268
|
-
path: targetPath,
|
|
1269
|
-
start_line: args.start_line ? Number(args.start_line) : undefined,
|
|
1270
|
-
end_line: args.end_line ? Number(args.end_line) : undefined,
|
|
1271
|
-
}))}`, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1272
|
-
const payload = JSON.parse(response);
|
|
1273
|
-
if (payload?.success === true) {
|
|
1274
|
-
return {
|
|
1275
|
-
success: true,
|
|
1276
|
-
output: String(payload.output || payload.content || ''),
|
|
1277
|
-
metadata: { source: 'desktop-bridge', path: targetPath },
|
|
1278
|
-
};
|
|
1279
|
-
}
|
|
1280
|
-
if (payload?.error) {
|
|
1281
|
-
this.logger.debug(`Desktop bridge read failed for ${targetPath}: ${payload.error}`);
|
|
1282
|
-
}
|
|
1283
|
-
}
|
|
1284
|
-
catch (error) {
|
|
1285
|
-
this.logger.debug(`Desktop bridge read unavailable for ${targetPath}: ${this.formatExternalToolError('read_file', 'bridge delegation', error)}`);
|
|
1286
|
-
}
|
|
1287
|
-
return null;
|
|
1288
|
-
}
|
|
1289
1226
|
/**
|
|
1290
1227
|
* Read file with enhanced error handling and suggestions
|
|
1291
1228
|
*/
|
|
1292
1229
|
readFile(args) {
|
|
1293
|
-
const bridgeRead = this.tryBridgeReadFile(args);
|
|
1294
|
-
if (bridgeRead) {
|
|
1295
|
-
return bridgeRead;
|
|
1296
|
-
}
|
|
1297
1230
|
const filePath = this.resolvePath(args.path);
|
|
1298
1231
|
if (!fs.existsSync(filePath)) {
|
|
1299
1232
|
// Try to find similar files
|
|
@@ -1609,7 +1542,18 @@ export class AgenticTools {
|
|
|
1609
1542
|
for (const part of cmdParts) {
|
|
1610
1543
|
const firstWord = part.trim().split(/\s+/)[0].toLowerCase();
|
|
1611
1544
|
if (unixOnlyCommands.includes(firstWord)) {
|
|
1612
|
-
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Command '${firstWord}' is not available on Windows`, `Use
|
|
1545
|
+
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Command '${firstWord}' is not available on Windows`, `Use the 'ssh_exec' tool to run Unix commands on the server, ` +
|
|
1546
|
+
`or use 'fetch_url' for web requests. ` +
|
|
1547
|
+
`PowerShell alternatives: dir (ls), type (cat), findstr (grep), select-string (grep)`);
|
|
1548
|
+
}
|
|
1549
|
+
}
|
|
1550
|
+
// Check for pipe to Unix command
|
|
1551
|
+
if (args.command.includes('|')) {
|
|
1552
|
+
const pipedCommands = args.command.split('|').map(c => c.trim().split(/\s+/)[0].toLowerCase());
|
|
1553
|
+
for (const cmd of pipedCommands) {
|
|
1554
|
+
if (unixOnlyCommands.includes(cmd)) {
|
|
1555
|
+
return this.createErrorResult(ToolErrorType.EXECUTION_FAILED, `Piped command '${cmd}' is not available on Windows`, `Windows doesn't have '${cmd}'. Use 'ssh_exec' tool to run this command on the Vigthoria server instead.`);
|
|
1556
|
+
}
|
|
1613
1557
|
}
|
|
1614
1558
|
}
|
|
1615
1559
|
}
|
|
@@ -2819,16 +2763,6 @@ export class AgenticTools {
|
|
|
2819
2763
|
const scope = args.scope || 'all';
|
|
2820
2764
|
const includePattern = args.include || '';
|
|
2821
2765
|
const maxResults = Math.min(parseInt(args.max_results || '30', 10), 100);
|
|
2822
|
-
if (this.indexedCodebaseSearch && (scope === 'all' || scope === 'content')) {
|
|
2823
|
-
const indexedOutput = this.indexedCodebaseSearch(query, maxResults);
|
|
2824
|
-
if (indexedOutput && !indexedOutput.includes('No indexed codebase matches found')) {
|
|
2825
|
-
return {
|
|
2826
|
-
success: true,
|
|
2827
|
-
output: indexedOutput,
|
|
2828
|
-
metadata: { searchStatus: 'search_matches_found', source: 'tfidf-index' },
|
|
2829
|
-
};
|
|
2830
|
-
}
|
|
2831
|
-
}
|
|
2832
2766
|
const results = [];
|
|
2833
2767
|
const seen = new Set();
|
|
2834
2768
|
// Helper: collect files recursively respecting gitignore-like patterns
|
|
@@ -3120,12 +3054,6 @@ export class AgenticTools {
|
|
|
3120
3054
|
'edit_file': 'edit_file',
|
|
3121
3055
|
'editfile': 'edit_file',
|
|
3122
3056
|
'edit': 'edit_file',
|
|
3123
|
-
'search_files': 'grep',
|
|
3124
|
-
'grep': 'grep',
|
|
3125
|
-
'glob': 'glob',
|
|
3126
|
-
'find_files': 'grep',
|
|
3127
|
-
'run_command': 'bash',
|
|
3128
|
-
'syntax_check': 'syntax_check',
|
|
3129
3057
|
};
|
|
3130
3058
|
return toolMap[normalized] || normalized;
|
|
3131
3059
|
};
|
package/package.json
CHANGED
|
@@ -67,7 +67,7 @@ python3 - << 'PY'
|
|
|
67
67
|
import json
|
|
68
68
|
j=json.load(open('/tmp/vig-balanced.json'))
|
|
69
69
|
assert j.get('success') is True
|
|
70
|
-
assert j.get('model')
|
|
70
|
+
assert j.get('model') in ('vigthoria-balanced-4b', 'vigthoria-v3-balanced-4b'), j
|
|
71
71
|
print('[pass] balanced-4b')
|
|
72
72
|
PY
|
|
73
73
|
|
|
@@ -96,9 +96,12 @@ curl -s http://localhost:4009/v1/models >/tmp/vig-models.json
|
|
|
96
96
|
python3 - << 'PY'
|
|
97
97
|
import json
|
|
98
98
|
ids={m.get('id','') for m in json.load(open('/tmp/vig-models.json')).get('data',[])}
|
|
99
|
-
|
|
100
|
-
assert 'vigthoria-
|
|
101
|
-
assert
|
|
99
|
+
if ids:
|
|
100
|
+
assert ('vigthoria-balanced-4b' in ids) or ('vigthoria-balanced-4b:latest' in ids) or ('vigthoria-v3-balanced-4b' in ids) or ('vigthoria-v3-balanced-4b:latest' in ids)
|
|
101
|
+
assert 'vigthoria-creative-9b-v4' in ids
|
|
102
|
+
assert any('vigthoria-v3-code-35b' in i for i in ids)
|
|
103
|
+
else:
|
|
104
|
+
print('[warn] model inventory empty on this host; route proof above is authoritative')
|
|
102
105
|
print('[pass] model inventory gates')
|
|
103
106
|
PY
|
|
104
107
|
|