vigthoria-cli 1.3.0 ā 1.4.1
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 +2 -2
- package/SECURITY_HARDENING.md +253 -0
- package/dist/commands/chat.d.ts +2 -2
- package/dist/commands/chat.d.ts.map +1 -1
- package/dist/commands/chat.js +49 -5
- package/dist/commands/chat.js.map +1 -1
- package/dist/commands/generate.d.ts +3 -0
- package/dist/commands/generate.d.ts.map +1 -1
- package/dist/commands/generate.js +45 -4
- package/dist/commands/generate.js.map +1 -1
- package/dist/commands/repo.d.ts.map +1 -1
- package/dist/commands/repo.js +50 -28
- package/dist/commands/repo.js.map +1 -1
- package/dist/index.js +15 -5
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts +15 -0
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +56 -9
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/config.js +1 -1
- package/dist/utils/config.js.map +1 -1
- package/dist/utils/session.d.ts +1 -1
- package/dist/utils/session.js +1 -1
- package/dist/utils/tools.d.ts +12 -3
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +61 -9
- package/dist/utils/tools.js.map +1 -1
- package/install.sh +1 -1
- package/package.json +2 -2
- package/src/commands/chat.ts +50 -5
- package/src/commands/generate.ts +49 -4
- package/src/commands/repo.ts +56 -28
- package/src/index.ts +14 -5
- package/src/utils/api.ts +72 -9
- package/src/utils/config.ts +1 -1
- package/src/utils/session.ts +1 -1
- package/src/utils/tools.ts +69 -9
package/src/commands/repo.ts
CHANGED
|
@@ -445,6 +445,8 @@ export class RepoCommand {
|
|
|
445
445
|
const data = await response.json() as {
|
|
446
446
|
success: boolean;
|
|
447
447
|
projects: Project[];
|
|
448
|
+
owned?: Project[];
|
|
449
|
+
shared?: Project[];
|
|
448
450
|
total: number;
|
|
449
451
|
};
|
|
450
452
|
|
|
@@ -456,44 +458,70 @@ export class RepoCommand {
|
|
|
456
458
|
return;
|
|
457
459
|
}
|
|
458
460
|
|
|
461
|
+
// Separate owned and shared projects
|
|
462
|
+
const ownedProjects = data.owned || data.projects.filter((p: any) => p.access_level === 'owner');
|
|
463
|
+
const sharedProjects = data.shared || data.projects.filter((p: any) => p.access_level !== 'owner');
|
|
464
|
+
|
|
459
465
|
console.log(chalk.cyan(`\nš¦ Your Vigthoria Repository (${data.total} project${data.total !== 1 ? 's' : ''})\n`));
|
|
460
466
|
|
|
461
|
-
//
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
acc[vis].push(project);
|
|
466
|
-
return acc;
|
|
467
|
-
}, {});
|
|
468
|
-
|
|
469
|
-
const visibilityOrder = ['private', 'restricted', 'public'];
|
|
470
|
-
const visibilityIcons: Record<string, string> = {
|
|
471
|
-
private: 'š',
|
|
472
|
-
restricted: 'š„',
|
|
473
|
-
public: 'š'
|
|
474
|
-
};
|
|
467
|
+
// Display owned projects grouped by visibility
|
|
468
|
+
if (ownedProjects.length > 0) {
|
|
469
|
+
console.log(chalk.bold.cyan(' š YOUR PROJECTS'));
|
|
470
|
+
console.log(chalk.gray(' ' + 'ā'.repeat(50)));
|
|
475
471
|
|
|
476
|
-
|
|
477
|
-
const
|
|
478
|
-
|
|
472
|
+
// Group by visibility
|
|
473
|
+
const grouped = ownedProjects.reduce((acc: Record<string, Project[]>, project: Project) => {
|
|
474
|
+
const vis = project.visibility || 'private';
|
|
475
|
+
if (!acc[vis]) acc[vis] = [];
|
|
476
|
+
acc[vis].push(project);
|
|
477
|
+
return acc;
|
|
478
|
+
}, {});
|
|
479
|
+
|
|
480
|
+
const visibilityOrder = ['private', 'restricted', 'public'];
|
|
481
|
+
const visibilityIcons: Record<string, string> = {
|
|
482
|
+
private: 'š',
|
|
483
|
+
restricted: 'š„',
|
|
484
|
+
public: 'š'
|
|
485
|
+
};
|
|
486
|
+
|
|
487
|
+
visibilityOrder.forEach(vis => {
|
|
488
|
+
const projects = grouped[vis];
|
|
489
|
+
if (!projects || projects.length === 0) return;
|
|
490
|
+
|
|
491
|
+
console.log(chalk.bold.white(` ${visibilityIcons[vis]} ${vis.toUpperCase()}`));
|
|
492
|
+
|
|
493
|
+
projects.forEach((project) => {
|
|
494
|
+
const syncStatus = project.last_synced_at
|
|
495
|
+
? chalk.green('ā synced')
|
|
496
|
+
: chalk.yellow('ā not synced');
|
|
497
|
+
|
|
498
|
+
console.log(chalk.white(` ${project.project_name.padEnd(30)} ${syncStatus}`));
|
|
499
|
+
if (project.description) {
|
|
500
|
+
console.log(chalk.gray(` ${project.description.substring(0, 50)}${project.description.length > 50 ? '...' : ''}`));
|
|
501
|
+
}
|
|
502
|
+
console.log(chalk.gray(` Tech: ${project.tech_stack || 'Unknown'}`));
|
|
503
|
+
console.log(chalk.gray(` Updated: ${new Date(project.updated_at).toLocaleDateString()}`));
|
|
504
|
+
console.log();
|
|
505
|
+
});
|
|
506
|
+
});
|
|
507
|
+
}
|
|
479
508
|
|
|
480
|
-
|
|
509
|
+
// Display shared projects
|
|
510
|
+
if (sharedProjects.length > 0) {
|
|
511
|
+
console.log(chalk.bold.magenta('\n š¤ SHARED WITH YOU'));
|
|
481
512
|
console.log(chalk.gray(' ' + 'ā'.repeat(50)));
|
|
482
513
|
|
|
483
|
-
|
|
484
|
-
const
|
|
485
|
-
|
|
486
|
-
: chalk.yellow('ā not synced');
|
|
487
|
-
|
|
488
|
-
console.log(chalk.white(` ${project.project_name.padEnd(30)} ${syncStatus}`));
|
|
514
|
+
sharedProjects.forEach((project: any) => {
|
|
515
|
+
const accessIcon = project.access_level === 'admin' ? 'š' : project.access_level === 'write' ? 'āļø' : 'šļø';
|
|
516
|
+
console.log(chalk.white(` ${accessIcon} ${project.project_name.padEnd(28)} [${project.access_level}]`));
|
|
489
517
|
if (project.description) {
|
|
490
|
-
console.log(chalk.gray(`
|
|
518
|
+
console.log(chalk.gray(` ${project.description.substring(0, 50)}${project.description.length > 50 ? '...' : ''}`));
|
|
491
519
|
}
|
|
492
|
-
console.log(chalk.gray(`
|
|
493
|
-
console.log(chalk.gray(`
|
|
520
|
+
console.log(chalk.gray(` Tech: ${project.tech_stack || 'Unknown'}`));
|
|
521
|
+
console.log(chalk.gray(` Updated: ${new Date(project.updated_at).toLocaleDateString()}`));
|
|
494
522
|
console.log();
|
|
495
523
|
});
|
|
496
|
-
}
|
|
524
|
+
}
|
|
497
525
|
|
|
498
526
|
console.log(chalk.gray('ā'.repeat(60)));
|
|
499
527
|
console.log(chalk.cyan('\nCommands:'));
|
package/src/index.ts
CHANGED
|
@@ -51,7 +51,7 @@ function getVersion(): string {
|
|
|
51
51
|
} catch (e) {
|
|
52
52
|
// Fallback to hardcoded version
|
|
53
53
|
}
|
|
54
|
-
return '1.
|
|
54
|
+
return '1.4.0';
|
|
55
55
|
}
|
|
56
56
|
const VERSION = getVersion();
|
|
57
57
|
|
|
@@ -83,8 +83,16 @@ async function checkForUpdatesQuietly(): Promise<void> {
|
|
|
83
83
|
|
|
84
84
|
// Only show update message if npm version is NEWER than current (not older)
|
|
85
85
|
if (npmVersion && compareVersions(npmVersion, VERSION) > 0) {
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
// Check if this is a security update (1.4.0+)
|
|
87
|
+
if (compareVersions(npmVersion, '1.4.0') >= 0 && compareVersions(VERSION, '1.4.0') < 0) {
|
|
88
|
+
console.log(chalk.red.bold('\nā ļø SECURITY UPDATE AVAILABLE'));
|
|
89
|
+
console.log(chalk.red(` Version ${VERSION} has security vulnerabilities.`));
|
|
90
|
+
console.log(chalk.yellow(` Please update to ${npmVersion} immediately:`));
|
|
91
|
+
console.log(chalk.white.bold(' npm install -g vigthoria-cli@latest\n'));
|
|
92
|
+
} else {
|
|
93
|
+
console.log(chalk.yellow(`\nš¦ Update available: ${VERSION} ā ${npmVersion}`));
|
|
94
|
+
console.log(chalk.gray(' Run `vigthoria update` to install\n'));
|
|
95
|
+
}
|
|
88
96
|
}
|
|
89
97
|
} catch {
|
|
90
98
|
// Silently ignore - network issues shouldn't block CLI
|
|
@@ -143,7 +151,7 @@ async function main() {
|
|
|
143
151
|
});
|
|
144
152
|
});
|
|
145
153
|
|
|
146
|
-
// Agent command - Agentic mode (
|
|
154
|
+
// Agent command - Agentic mode (Vigthoria Autonomous)
|
|
147
155
|
program
|
|
148
156
|
.command('agent')
|
|
149
157
|
.alias('a')
|
|
@@ -178,9 +186,10 @@ async function main() {
|
|
|
178
186
|
.command('generate <description>')
|
|
179
187
|
.alias('g')
|
|
180
188
|
.description('Generate code from description')
|
|
181
|
-
.option('-l, --language <lang>', 'Target language', '
|
|
189
|
+
.option('-l, --language <lang>', 'Target language (html, typescript, python, etc.)', 'html')
|
|
182
190
|
.option('-o, --output <file>', 'Output file path')
|
|
183
191
|
.option('-m, --model <model>', 'Select AI model', 'code')
|
|
192
|
+
.option('-p, --pro', 'Senior Developer Mode: plan, generate, quality check (recommended)', false)
|
|
184
193
|
.action(async (description, options) => {
|
|
185
194
|
const generate = new GenerateCommand(config, logger);
|
|
186
195
|
await generate.run(description, options);
|
package/src/utils/api.ts
CHANGED
|
@@ -252,7 +252,29 @@ export class APIClient {
|
|
|
252
252
|
}
|
|
253
253
|
}
|
|
254
254
|
|
|
255
|
-
// Strategy 1: Try
|
|
255
|
+
// Strategy 1: Try Vigthoria Inference Server directly (NATIVE models on port 8010)
|
|
256
|
+
try {
|
|
257
|
+
const response = await axios.post('http://localhost:8010/v1/chat/completions', {
|
|
258
|
+
model: resolvedModel,
|
|
259
|
+
messages,
|
|
260
|
+
max_tokens: this.config.get('preferences').maxTokens,
|
|
261
|
+
temperature: 0.7,
|
|
262
|
+
stream: false,
|
|
263
|
+
}, { timeout: 120000 });
|
|
264
|
+
|
|
265
|
+
if (response.data.choices && response.data.choices.length > 0) {
|
|
266
|
+
return {
|
|
267
|
+
id: response.data.id || `vigthoria-native-${Date.now()}`,
|
|
268
|
+
message: response.data.choices[0].message?.content || response.data.choices[0].text,
|
|
269
|
+
model: response.data.model || model,
|
|
270
|
+
usage: response.data.usage,
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
} catch (error) {
|
|
274
|
+
this.logger.debug('Vigthoria Inference Server (8010) failed, trying Model Router...');
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Strategy 2: Try local Model Router's Vigthoria chat endpoint
|
|
256
278
|
try {
|
|
257
279
|
const response = await axios.post('http://localhost:4009/api/vigthoria/chat', {
|
|
258
280
|
messages,
|
|
@@ -271,10 +293,10 @@ export class APIClient {
|
|
|
271
293
|
};
|
|
272
294
|
}
|
|
273
295
|
} catch (error) {
|
|
274
|
-
this.logger.debug('Model
|
|
296
|
+
this.logger.debug('Model Router (4009) failed, trying Ollama directly...');
|
|
275
297
|
}
|
|
276
298
|
|
|
277
|
-
// Strategy
|
|
299
|
+
// Strategy 3: Try Ollama directly (for local development/testing)
|
|
278
300
|
try {
|
|
279
301
|
const ollamaModel = this.resolveToOllamaModel(model);
|
|
280
302
|
const prompt = this.formatMessagesForOllama(messages);
|
|
@@ -302,17 +324,20 @@ export class APIClient {
|
|
|
302
324
|
throw new Error('AI service unavailable. Please check your authentication with `vigthoria login` or try again later.');
|
|
303
325
|
}
|
|
304
326
|
|
|
305
|
-
// Map CLI model names to Ollama model names (for local fallback)
|
|
327
|
+
// Map CLI model names to Ollama model names (for local/offline fallback)
|
|
328
|
+
// Vigthoria_v3_Code_30B runs on qwen3-coder base via Vigthoria Cloud
|
|
329
|
+
// Local users with Ollama can use the base model for offline work
|
|
306
330
|
private resolveToOllamaModel(model: string): string {
|
|
307
331
|
const ollamaMap: Record<string, string> = {
|
|
308
332
|
'fast': 'qwen3:0.6b',
|
|
309
333
|
'mini': 'smollm2:135m',
|
|
310
|
-
'code': '
|
|
334
|
+
'code': 'qwen3-coder:latest', // Vigthoria_v3_Code_30B (cloud) / qwen3-coder (local fallback)
|
|
311
335
|
'balanced': 'phi3:mini',
|
|
312
336
|
'creative': 'gemma3:latest',
|
|
313
337
|
'vigthoria-fast-1.7b': 'qwen3:0.6b',
|
|
314
338
|
'vigthoria-mini-0.6b': 'smollm2:135m',
|
|
315
|
-
'vigthoria-
|
|
339
|
+
'vigthoria-v3-code-30b': 'qwen3-coder:latest', // Vigthoria_v3_Code_30B
|
|
340
|
+
'vigthoria-v2-code-8b': 'qwen3-coder:latest', // Legacy v2
|
|
316
341
|
'vigthoria-balanced-4b': 'phi3:mini',
|
|
317
342
|
'vigthoria-creative-9b-v4': 'gemma3:latest',
|
|
318
343
|
};
|
|
@@ -436,6 +461,37 @@ export class APIClient {
|
|
|
436
461
|
return response.data.code;
|
|
437
462
|
}
|
|
438
463
|
|
|
464
|
+
// Senior Developer Mode - Planning + Generation + Quality Check
|
|
465
|
+
async generateProject(prompt: string, projectType: string, model: string): Promise<{
|
|
466
|
+
code: string;
|
|
467
|
+
plan?: any;
|
|
468
|
+
quality?: {
|
|
469
|
+
lineCount: number;
|
|
470
|
+
score: number;
|
|
471
|
+
checks: {
|
|
472
|
+
hasAnimations: boolean;
|
|
473
|
+
hasNeonEffects: boolean;
|
|
474
|
+
hasResponsive: boolean;
|
|
475
|
+
hasFontAwesome: boolean;
|
|
476
|
+
hasGoogleFonts: boolean;
|
|
477
|
+
};
|
|
478
|
+
};
|
|
479
|
+
}> {
|
|
480
|
+
const response = await this.client.post('/api/ai/generate-project', {
|
|
481
|
+
prompt,
|
|
482
|
+
projectType,
|
|
483
|
+
model: this.resolveModelId(model),
|
|
484
|
+
}, {
|
|
485
|
+
timeout: 300000, // 5 minutes for complex generation
|
|
486
|
+
});
|
|
487
|
+
|
|
488
|
+
return {
|
|
489
|
+
code: response.data.code,
|
|
490
|
+
plan: response.data.plan,
|
|
491
|
+
quality: response.data.quality,
|
|
492
|
+
};
|
|
493
|
+
}
|
|
494
|
+
|
|
439
495
|
async explainCode(code: string, language: string): Promise<string> {
|
|
440
496
|
const response = await this.client.post('/api/ai/explain', {
|
|
441
497
|
code,
|
|
@@ -538,10 +594,17 @@ export class APIClient {
|
|
|
538
594
|
// Health check
|
|
539
595
|
async healthCheck(): Promise<boolean> {
|
|
540
596
|
try {
|
|
541
|
-
|
|
542
|
-
|
|
597
|
+
// Try the main API health endpoint first
|
|
598
|
+
const response = await this.client.get('/api/health');
|
|
599
|
+
return response.data?.status === 'ok' || response.data?.healthy === true;
|
|
543
600
|
} catch {
|
|
544
|
-
|
|
601
|
+
// Fallback: try root health endpoint
|
|
602
|
+
try {
|
|
603
|
+
await this.client.get('/health');
|
|
604
|
+
return true;
|
|
605
|
+
} catch {
|
|
606
|
+
return false;
|
|
607
|
+
}
|
|
545
608
|
}
|
|
546
609
|
}
|
|
547
610
|
}
|
package/src/utils/config.ts
CHANGED
|
@@ -206,7 +206,7 @@ export class Config {
|
|
|
206
206
|
// Pro plans get code and creative models
|
|
207
207
|
if (sub.plan === 'developer' || sub.plan === 'pro' || sub.plan === 'ultra' || sub.plan === 'enterprise') {
|
|
208
208
|
models.push(
|
|
209
|
-
{ id: 'code', name: '
|
|
209
|
+
{ id: 'code', name: 'Vigthoria_v3_Code_30B', description: 'Advanced code specialist with agent mode' },
|
|
210
210
|
{ id: 'creative', name: 'Vigthoria Creative 9B v4', description: 'Creative writing, lyrics' },
|
|
211
211
|
);
|
|
212
212
|
}
|
package/src/utils/session.ts
CHANGED
package/src/utils/tools.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Vigthoria CLI Tools - Agentic Tool System
|
|
3
3
|
*
|
|
4
|
-
* This module provides
|
|
4
|
+
* This module provides Vigthoria Autonomous autonomous tool execution.
|
|
5
5
|
* Tools can be called by the AI to perform actions.
|
|
6
6
|
*
|
|
7
7
|
* Enhanced with:
|
|
@@ -159,7 +159,7 @@ export class AgenticTools {
|
|
|
159
159
|
}
|
|
160
160
|
|
|
161
161
|
/**
|
|
162
|
-
* List of available tools -
|
|
162
|
+
* List of available tools - Vigthoria's advanced
|
|
163
163
|
* Enhanced with risk levels and categories
|
|
164
164
|
*/
|
|
165
165
|
static getToolDefinitions(): ToolDefinition[] {
|
|
@@ -726,11 +726,40 @@ export class AgenticTools {
|
|
|
726
726
|
|
|
727
727
|
/**
|
|
728
728
|
* Execute bash command with enhanced error handling
|
|
729
|
+
* SECURITY: Commands are sandboxed to workspace directory
|
|
729
730
|
*/
|
|
730
731
|
private bash(args: Record<string, string>): ToolResult {
|
|
731
732
|
const cwd = args.cwd ? this.resolvePath(args.cwd) : this.cwd;
|
|
732
733
|
const timeout = args.timeout ? parseInt(args.timeout) * 1000 : 30000;
|
|
733
734
|
|
|
735
|
+
// SECURITY: Block dangerous commands that could access outside workspace
|
|
736
|
+
const blockedPatterns = [
|
|
737
|
+
/\bcat\s+\/etc\//i, // Reading system files
|
|
738
|
+
/\bcat\s+\/var\/(?!log)/i, // Reading /var/ except logs
|
|
739
|
+
/\bcat\s+\/root\//i, // Reading root home
|
|
740
|
+
/\bcat\s+\/home\/[^\/]+\/\.[^\/]/i, // Reading hidden files in home dirs
|
|
741
|
+
/\bcat\s+~\/\./i, // Reading hidden files via ~
|
|
742
|
+
/\bcd\s+(\/etc|\/var\/www|\/root|\/home)/i, // CD to sensitive dirs
|
|
743
|
+
/\brm\s+-rf?\s+\//i, // Dangerous rm commands
|
|
744
|
+
/\b(curl|wget).*\|\s*(bash|sh)\b/i, // Downloading and executing scripts
|
|
745
|
+
/\bsudo\b/i, // Sudo commands
|
|
746
|
+
/\bsu\s+-/i, // Su to root
|
|
747
|
+
/\bchmod\s+[0-7]*777/i, // World-writable permissions
|
|
748
|
+
/\/(var\/www|opt)\/[a-z]+-?(database|models|coder|mcp|operator|voice|music)/i, // Vigthoria ecosystem
|
|
749
|
+
/vigthoria-(models|database|mcp|operator|voice|music)/i, // Vigthoria project names
|
|
750
|
+
];
|
|
751
|
+
|
|
752
|
+
for (const pattern of blockedPatterns) {
|
|
753
|
+
if (pattern.test(args.command)) {
|
|
754
|
+
this.logger.warn(`Security: Blocked potentially dangerous command: ${args.command.substring(0, 50)}...`);
|
|
755
|
+
return this.createErrorResult(
|
|
756
|
+
ToolErrorType.PERMISSION_DENIED,
|
|
757
|
+
'This command is blocked for security reasons',
|
|
758
|
+
'Commands must operate within your current project workspace.'
|
|
759
|
+
);
|
|
760
|
+
}
|
|
761
|
+
}
|
|
762
|
+
|
|
734
763
|
// Validate working directory
|
|
735
764
|
if (!fs.existsSync(cwd)) {
|
|
736
765
|
return this.createErrorResult(
|
|
@@ -983,15 +1012,43 @@ export class AgenticTools {
|
|
|
983
1012
|
}
|
|
984
1013
|
}
|
|
985
1014
|
|
|
1015
|
+
/**
|
|
1016
|
+
* Resolve and SANITIZE path - prevent path traversal outside workspace
|
|
1017
|
+
* SECURITY: All paths MUST stay within the workspace (cwd)
|
|
1018
|
+
*/
|
|
986
1019
|
private resolvePath(p: string): string {
|
|
1020
|
+
// Resolve the full path (handles both relative and absolute)
|
|
1021
|
+
let resolvedPath: string;
|
|
987
1022
|
if (path.isAbsolute(p)) {
|
|
988
|
-
|
|
1023
|
+
resolvedPath = path.normalize(p);
|
|
1024
|
+
} else {
|
|
1025
|
+
resolvedPath = path.normalize(path.join(this.cwd, p));
|
|
1026
|
+
}
|
|
1027
|
+
|
|
1028
|
+
// SECURITY CHECK: Ensure path is within workspace
|
|
1029
|
+
const workspaceRoot = path.normalize(this.cwd);
|
|
1030
|
+
if (!resolvedPath.startsWith(workspaceRoot + path.sep) && resolvedPath !== workspaceRoot) {
|
|
1031
|
+
// Path is outside workspace - force it back to workspace
|
|
1032
|
+
this.logger.warn(`Security: Blocked access to path outside workspace: ${p}`);
|
|
1033
|
+
// Return the sanitized relative path within workspace
|
|
1034
|
+
const basename = path.basename(p);
|
|
1035
|
+
return path.join(this.cwd, basename);
|
|
989
1036
|
}
|
|
990
|
-
|
|
1037
|
+
|
|
1038
|
+
return resolvedPath;
|
|
1039
|
+
}
|
|
1040
|
+
|
|
1041
|
+
/**
|
|
1042
|
+
* Check if a path is within the allowed workspace
|
|
1043
|
+
*/
|
|
1044
|
+
private isPathWithinWorkspace(p: string): boolean {
|
|
1045
|
+
const resolvedPath = path.normalize(path.isAbsolute(p) ? p : path.join(this.cwd, p));
|
|
1046
|
+
const workspaceRoot = path.normalize(this.cwd);
|
|
1047
|
+
return resolvedPath.startsWith(workspaceRoot + path.sep) || resolvedPath === workspaceRoot;
|
|
991
1048
|
}
|
|
992
1049
|
|
|
993
1050
|
/**
|
|
994
|
-
* Parse tool calls from AI response (
|
|
1051
|
+
* Parse tool calls from AI response (Vigthoria Agent format)
|
|
995
1052
|
* Enhanced to handle various AI output formats including malformed JSON
|
|
996
1053
|
*/
|
|
997
1054
|
static parseToolCalls(text: string): ToolCall[] {
|
|
@@ -1170,25 +1227,28 @@ To use a tool, output a JSON block in a code fence with "tool" language:
|
|
|
1170
1227
|
|
|
1171
1228
|
1. List directory contents:
|
|
1172
1229
|
\`\`\`tool
|
|
1173
|
-
{"tool": "list_dir", "args": {"path": "
|
|
1230
|
+
{"tool": "list_dir", "args": {"path": "."}}
|
|
1174
1231
|
\`\`\`
|
|
1175
1232
|
|
|
1176
1233
|
2. Read a file:
|
|
1177
1234
|
\`\`\`tool
|
|
1178
|
-
{"tool": "read_file", "args": {"path": "/
|
|
1235
|
+
{"tool": "read_file", "args": {"path": "src/index.js"}}
|
|
1179
1236
|
\`\`\`
|
|
1180
1237
|
|
|
1181
1238
|
3. Run a shell command:
|
|
1182
1239
|
\`\`\`tool
|
|
1183
|
-
{"tool": "bash", "args": {"command": "ls -la
|
|
1240
|
+
{"tool": "bash", "args": {"command": "ls -la"}}
|
|
1184
1241
|
\`\`\`
|
|
1185
1242
|
|
|
1186
1243
|
4. Write a file:
|
|
1187
1244
|
\`\`\`tool
|
|
1188
|
-
{"tool": "write_file", "args": {"path": "
|
|
1245
|
+
{"tool": "write_file", "args": {"path": "hello.py", "content": "print('Hello World')"}}
|
|
1189
1246
|
\`\`\`
|
|
1190
1247
|
|
|
1191
1248
|
IMPORTANT:
|
|
1249
|
+
- You can ONLY access files within the current project workspace
|
|
1250
|
+
- Use relative paths (e.g., "src/file.js", "app.py", "./config.json")
|
|
1251
|
+
- Never try to access system files or directories outside the workspace
|
|
1192
1252
|
- Use ONLY the exact tool names: list_dir, read_file, write_file, edit_file, bash, grep, glob, git
|
|
1193
1253
|
- The JSON must be valid with double quotes for all keys and string values
|
|
1194
1254
|
- After tool execution, you will receive results and can continue with the next step
|