vigthoria-cli 1.1.0 → 1.3.0
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 +83 -0
- package/dist/commands/deploy.d.ts +80 -0
- package/dist/commands/deploy.d.ts.map +1 -0
- package/dist/commands/deploy.js +514 -0
- package/dist/commands/deploy.js.map +1 -0
- package/dist/commands/hub.d.ts +40 -0
- package/dist/commands/hub.d.ts.map +1 -0
- package/dist/commands/hub.js +289 -0
- package/dist/commands/hub.js.map +1 -0
- package/dist/commands/repo.d.ts +80 -0
- package/dist/commands/repo.d.ts.map +1 -0
- package/dist/commands/repo.js +585 -0
- package/dist/commands/repo.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +254 -7
- package/dist/index.js.map +1 -1
- package/dist/utils/api.d.ts.map +1 -1
- package/dist/utils/api.js +6 -24
- package/dist/utils/api.js.map +1 -1
- package/dist/utils/tools.d.ts +6 -0
- package/dist/utils/tools.d.ts.map +1 -1
- package/dist/utils/tools.js +269 -15
- package/dist/utils/tools.js.map +1 -1
- package/package.json +5 -2
- package/src/commands/deploy.ts +609 -0
- package/src/commands/hub.ts +382 -0
- package/src/commands/repo.ts +701 -0
- package/src/index.ts +285 -7
- package/src/utils/api.ts +6 -25
- package/src/utils/tools.ts +283 -16
package/src/utils/tools.ts
CHANGED
|
@@ -262,6 +262,22 @@ export class AgenticTools {
|
|
|
262
262
|
riskLevel: 'medium',
|
|
263
263
|
category: 'execute',
|
|
264
264
|
},
|
|
265
|
+
{
|
|
266
|
+
name: 'repo',
|
|
267
|
+
description: 'Manage projects in Vigthoria Repository - push, pull, list, share, delete, or clone projects',
|
|
268
|
+
parameters: [
|
|
269
|
+
{ name: 'action', description: 'Action: push, pull, list, status, share, delete, clone', required: true },
|
|
270
|
+
{ name: 'project', description: 'Project name (for push/pull/status/share/delete)', required: false },
|
|
271
|
+
{ name: 'visibility', description: 'Visibility: public or private (for push)', required: false },
|
|
272
|
+
{ name: 'path', description: 'Directory path (for push) or target path (for clone)', required: false },
|
|
273
|
+
{ name: 'username', description: 'Username to share with (for share action)', required: false },
|
|
274
|
+
{ name: 'permission', description: 'Permission level: read, write, admin (for share action)', required: false },
|
|
275
|
+
],
|
|
276
|
+
requiresPermission: true,
|
|
277
|
+
dangerous: false,
|
|
278
|
+
riskLevel: 'medium',
|
|
279
|
+
category: 'execute',
|
|
280
|
+
},
|
|
265
281
|
];
|
|
266
282
|
}
|
|
267
283
|
|
|
@@ -376,6 +392,8 @@ export class AgenticTools {
|
|
|
376
392
|
return this.glob(call.args);
|
|
377
393
|
case 'git':
|
|
378
394
|
return this.git(call.args);
|
|
395
|
+
case 'repo':
|
|
396
|
+
return this.repo(call.args);
|
|
379
397
|
default:
|
|
380
398
|
return this.createErrorResult(
|
|
381
399
|
ToolErrorType.INVALID_ARGS,
|
|
@@ -850,6 +868,121 @@ export class AgenticTools {
|
|
|
850
868
|
}
|
|
851
869
|
}
|
|
852
870
|
|
|
871
|
+
/**
|
|
872
|
+
* Vigthoria Repository management tool
|
|
873
|
+
* Allows AI to push, pull, list, share, and manage projects in the Vigthoria Repository
|
|
874
|
+
*/
|
|
875
|
+
private async repo(args: Record<string, string>): Promise<ToolResult> {
|
|
876
|
+
const action = args.action?.toLowerCase();
|
|
877
|
+
const project = args.project;
|
|
878
|
+
const visibility = args.visibility || 'private';
|
|
879
|
+
const targetPath = args.path || this.cwd;
|
|
880
|
+
|
|
881
|
+
try {
|
|
882
|
+
// Use vigthoria CLI for repo operations
|
|
883
|
+
let command: string;
|
|
884
|
+
|
|
885
|
+
switch (action) {
|
|
886
|
+
case 'push':
|
|
887
|
+
if (!project) {
|
|
888
|
+
return {
|
|
889
|
+
success: false,
|
|
890
|
+
error: 'Project name is required for push',
|
|
891
|
+
suggestion: 'Provide a project name, e.g., repo action=push project=my-project'
|
|
892
|
+
};
|
|
893
|
+
}
|
|
894
|
+
command = `vigthoria repo push "${project}" "${targetPath}" --visibility ${visibility}`;
|
|
895
|
+
break;
|
|
896
|
+
|
|
897
|
+
case 'pull':
|
|
898
|
+
if (!project) {
|
|
899
|
+
return {
|
|
900
|
+
success: false,
|
|
901
|
+
error: 'Project name is required for pull',
|
|
902
|
+
suggestion: 'Provide a project name, e.g., repo action=pull project=my-project'
|
|
903
|
+
};
|
|
904
|
+
}
|
|
905
|
+
command = `vigthoria repo pull "${project}"`;
|
|
906
|
+
break;
|
|
907
|
+
|
|
908
|
+
case 'list':
|
|
909
|
+
command = 'vigthoria repo list';
|
|
910
|
+
break;
|
|
911
|
+
|
|
912
|
+
case 'status':
|
|
913
|
+
if (!project) {
|
|
914
|
+
return {
|
|
915
|
+
success: false,
|
|
916
|
+
error: 'Project name is required for status',
|
|
917
|
+
suggestion: 'Provide a project name, e.g., repo action=status project=my-project'
|
|
918
|
+
};
|
|
919
|
+
}
|
|
920
|
+
command = `vigthoria repo status "${project}"`;
|
|
921
|
+
break;
|
|
922
|
+
|
|
923
|
+
case 'share':
|
|
924
|
+
if (!project || !args.username) {
|
|
925
|
+
return {
|
|
926
|
+
success: false,
|
|
927
|
+
error: 'Project name and username are required for share',
|
|
928
|
+
suggestion: 'Provide both, e.g., repo action=share project=my-project username=collaborator permission=read'
|
|
929
|
+
};
|
|
930
|
+
}
|
|
931
|
+
const permission = args.permission || 'read';
|
|
932
|
+
command = `vigthoria repo share "${project}" "${args.username}" --permission ${permission}`;
|
|
933
|
+
break;
|
|
934
|
+
|
|
935
|
+
case 'delete':
|
|
936
|
+
if (!project) {
|
|
937
|
+
return {
|
|
938
|
+
success: false,
|
|
939
|
+
error: 'Project name is required for delete',
|
|
940
|
+
suggestion: 'Provide a project name, e.g., repo action=delete project=my-project'
|
|
941
|
+
};
|
|
942
|
+
}
|
|
943
|
+
command = `vigthoria repo delete "${project}" --force`;
|
|
944
|
+
break;
|
|
945
|
+
|
|
946
|
+
case 'clone':
|
|
947
|
+
if (!project) {
|
|
948
|
+
return {
|
|
949
|
+
success: false,
|
|
950
|
+
error: 'Project name is required for clone',
|
|
951
|
+
suggestion: 'Provide a project name, e.g., repo action=clone project=my-project path=/path/to/target'
|
|
952
|
+
};
|
|
953
|
+
}
|
|
954
|
+
command = `vigthoria repo clone "${project}" "${targetPath}"`;
|
|
955
|
+
break;
|
|
956
|
+
|
|
957
|
+
default:
|
|
958
|
+
return {
|
|
959
|
+
success: false,
|
|
960
|
+
error: `Unknown repo action: ${action}`,
|
|
961
|
+
suggestion: 'Available actions: push, pull, list, status, share, delete, clone'
|
|
962
|
+
};
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
const output = execSync(command, {
|
|
966
|
+
cwd: this.cwd,
|
|
967
|
+
encoding: 'utf-8',
|
|
968
|
+
timeout: 120000, // 2 minute timeout for repo operations
|
|
969
|
+
env: { ...process.env, FORCE_COLOR: '0' } // Disable colors for clean output
|
|
970
|
+
});
|
|
971
|
+
|
|
972
|
+
return {
|
|
973
|
+
success: true,
|
|
974
|
+
output: output.trim(),
|
|
975
|
+
metadata: { action, project }
|
|
976
|
+
};
|
|
977
|
+
} catch (error: any) {
|
|
978
|
+
return {
|
|
979
|
+
success: false,
|
|
980
|
+
error: error.stderr || error.message,
|
|
981
|
+
suggestion: 'Make sure you are logged in with vigthoria login and have the required permissions.'
|
|
982
|
+
};
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
|
|
853
986
|
private resolvePath(p: string): string {
|
|
854
987
|
if (path.isAbsolute(p)) {
|
|
855
988
|
return p;
|
|
@@ -859,18 +992,66 @@ export class AgenticTools {
|
|
|
859
992
|
|
|
860
993
|
/**
|
|
861
994
|
* Parse tool calls from AI response (Claude Code format)
|
|
995
|
+
* Enhanced to handle various AI output formats including malformed JSON
|
|
862
996
|
*/
|
|
863
997
|
static parseToolCalls(text: string): ToolCall[] {
|
|
864
998
|
const calls: ToolCall[] = [];
|
|
865
|
-
|
|
866
|
-
// Match <tool_call>...</tool_call> blocks
|
|
867
|
-
const toolCallRegex = /<tool_call>\s*(\{[\s\S]*?\})\s*<\/tool_call>/g;
|
|
868
999
|
let match;
|
|
869
1000
|
|
|
1001
|
+
// Helper to fix common JSON issues from AI outputs
|
|
1002
|
+
const fixJson = (jsonStr: string): string => {
|
|
1003
|
+
return jsonStr
|
|
1004
|
+
.replace(/'/g, '"') // Replace single quotes with double
|
|
1005
|
+
.replace(/([{,]\s*)(\w+):/g, '$1"$2":') // Quote unquoted keys
|
|
1006
|
+
.replace(/:\s*'([^']*)'\s*([,}])/g, ': "$1"$2') // Quote values with single quotes
|
|
1007
|
+
.replace(/\n/g, '\\n') // Escape newlines
|
|
1008
|
+
.replace(/\r/g, '') // Remove carriage returns
|
|
1009
|
+
.replace(/\t/g, '\\t') // Escape tabs
|
|
1010
|
+
.replace(/,\s*}/g, '}') // Remove trailing commas in objects
|
|
1011
|
+
.replace(/,\s*]/g, ']'); // Remove trailing commas in arrays
|
|
1012
|
+
};
|
|
1013
|
+
|
|
1014
|
+
// Normalize tool name from various formats
|
|
1015
|
+
const normalizeToolName = (name: string): string => {
|
|
1016
|
+
const normalized = name
|
|
1017
|
+
.replace(/^__/, '') // Remove leading underscores
|
|
1018
|
+
.replace(/__$/, '') // Remove trailing underscores
|
|
1019
|
+
.replace(/^execute_/i, '') // Remove execute_ prefix
|
|
1020
|
+
.replace(/_execute$/i, '') // Remove _execute suffix
|
|
1021
|
+
.toLowerCase();
|
|
1022
|
+
|
|
1023
|
+
// Map common variations
|
|
1024
|
+
const toolMap: Record<string, string> = {
|
|
1025
|
+
'bash': 'bash',
|
|
1026
|
+
'shell': 'bash',
|
|
1027
|
+
'run': 'bash',
|
|
1028
|
+
'command': 'bash',
|
|
1029
|
+
'list_dir': 'list_dir',
|
|
1030
|
+
'list_directory': 'list_dir',
|
|
1031
|
+
'ls': 'list_dir',
|
|
1032
|
+
'dir': 'list_dir',
|
|
1033
|
+
'read_file': 'read_file',
|
|
1034
|
+
'readfile': 'read_file',
|
|
1035
|
+
'read': 'read_file',
|
|
1036
|
+
'write_file': 'write_file',
|
|
1037
|
+
'writefile': 'write_file',
|
|
1038
|
+
'write': 'write_file',
|
|
1039
|
+
'edit_file': 'edit_file',
|
|
1040
|
+
'editfile': 'edit_file',
|
|
1041
|
+
'edit': 'edit_file',
|
|
1042
|
+
};
|
|
1043
|
+
|
|
1044
|
+
return toolMap[normalized] || normalized;
|
|
1045
|
+
};
|
|
1046
|
+
|
|
1047
|
+
// Match <tool_call>...</tool_call> blocks
|
|
1048
|
+
const toolCallRegex = /<tool_call>\s*([\s\S]*?)\s*<\/tool_call>/g;
|
|
870
1049
|
while ((match = toolCallRegex.exec(text)) !== null) {
|
|
871
1050
|
try {
|
|
872
|
-
const
|
|
1051
|
+
const fixed = fixJson(match[1]);
|
|
1052
|
+
const parsed = JSON.parse(fixed);
|
|
873
1053
|
if (parsed.tool && parsed.args) {
|
|
1054
|
+
parsed.tool = normalizeToolName(parsed.tool);
|
|
874
1055
|
calls.push(parsed);
|
|
875
1056
|
}
|
|
876
1057
|
} catch (e) {
|
|
@@ -878,12 +1059,14 @@ export class AgenticTools {
|
|
|
878
1059
|
}
|
|
879
1060
|
}
|
|
880
1061
|
|
|
881
|
-
//
|
|
882
|
-
const codeBlockRegex = /```tool\s*\n(
|
|
1062
|
+
// Match ```tool format
|
|
1063
|
+
const codeBlockRegex = /```tool\s*\n([\s\S]*?)\n```/g;
|
|
883
1064
|
while ((match = codeBlockRegex.exec(text)) !== null) {
|
|
884
1065
|
try {
|
|
885
|
-
const
|
|
1066
|
+
const fixed = fixJson(match[1]);
|
|
1067
|
+
const parsed = JSON.parse(fixed);
|
|
886
1068
|
if (parsed.tool && parsed.args) {
|
|
1069
|
+
parsed.tool = normalizeToolName(parsed.tool);
|
|
887
1070
|
calls.push(parsed);
|
|
888
1071
|
}
|
|
889
1072
|
} catch (e) {
|
|
@@ -891,6 +1074,67 @@ export class AgenticTools {
|
|
|
891
1074
|
}
|
|
892
1075
|
}
|
|
893
1076
|
|
|
1077
|
+
// Match ```json blocks with tool definitions
|
|
1078
|
+
const jsonBlockRegex = /```(?:json)?\s*\n?([\s\S]*?"tool"[\s\S]*?)\n?```/g;
|
|
1079
|
+
while ((match = jsonBlockRegex.exec(text)) !== null) {
|
|
1080
|
+
try {
|
|
1081
|
+
const fixed = fixJson(match[1]);
|
|
1082
|
+
const parsed = JSON.parse(fixed);
|
|
1083
|
+
if (parsed.tool && parsed.args) {
|
|
1084
|
+
parsed.tool = normalizeToolName(parsed.tool);
|
|
1085
|
+
// Prevent duplicates
|
|
1086
|
+
if (!calls.some(c => c.tool === parsed.tool && JSON.stringify(c.args) === JSON.stringify(parsed.args))) {
|
|
1087
|
+
calls.push(parsed);
|
|
1088
|
+
}
|
|
1089
|
+
}
|
|
1090
|
+
} catch (e) {
|
|
1091
|
+
// Invalid JSON, skip
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
|
|
1095
|
+
// Match inline JSON with "tool" key (various formats)
|
|
1096
|
+
const inlineToolRegex = /\{[^{}]*"?tool"?\s*:\s*["']?([^"',}]+)["']?[^{}]*"?args"?\s*:\s*\{([^{}]*)\}[^{}]*\}/gi;
|
|
1097
|
+
while ((match = inlineToolRegex.exec(text)) !== null) {
|
|
1098
|
+
try {
|
|
1099
|
+
const fixed = fixJson(match[0]);
|
|
1100
|
+
const parsed = JSON.parse(fixed);
|
|
1101
|
+
if (parsed.tool && parsed.args) {
|
|
1102
|
+
parsed.tool = normalizeToolName(parsed.tool);
|
|
1103
|
+
if (!calls.some(c => c.tool === parsed.tool && JSON.stringify(c.args) === JSON.stringify(parsed.args))) {
|
|
1104
|
+
calls.push(parsed);
|
|
1105
|
+
}
|
|
1106
|
+
}
|
|
1107
|
+
} catch (e) {
|
|
1108
|
+
// Invalid JSON, skip
|
|
1109
|
+
}
|
|
1110
|
+
}
|
|
1111
|
+
|
|
1112
|
+
// Parse Vigthoria V2 format: {"tool": "__BASH__", ...}
|
|
1113
|
+
const vigV2Regex = /"?tool"?\s*:\s*["']__?([A-Za-z_]+)__?["']/gi;
|
|
1114
|
+
while ((match = vigV2Regex.exec(text)) !== null) {
|
|
1115
|
+
try {
|
|
1116
|
+
const toolName = normalizeToolName(match[1]);
|
|
1117
|
+
// Extract args from nearby context
|
|
1118
|
+
const pathMatch = text.match(/"?(?:arg_)?path"?\s*:\s*["']([^"']+)["']/i);
|
|
1119
|
+
const cmdMatch = text.match(/"?command"?\s*:\s*(?:["']([^"']+)["']|\[\s*["']([^"']+)["']\s*\])/i);
|
|
1120
|
+
const contentMatch = text.match(/"?content"?\s*:\s*["']([^"']+)["']/i);
|
|
1121
|
+
|
|
1122
|
+
const args: Record<string, string> = {};
|
|
1123
|
+
if (pathMatch) args.path = pathMatch[1];
|
|
1124
|
+
if (cmdMatch) args.command = cmdMatch[1] || cmdMatch[2];
|
|
1125
|
+
if (contentMatch) args.content = contentMatch[1];
|
|
1126
|
+
|
|
1127
|
+
if (Object.keys(args).length > 0) {
|
|
1128
|
+
// Prevent duplicates
|
|
1129
|
+
if (!calls.some(c => c.tool === toolName && JSON.stringify(c.args) === JSON.stringify(args))) {
|
|
1130
|
+
calls.push({ tool: toolName, args });
|
|
1131
|
+
}
|
|
1132
|
+
}
|
|
1133
|
+
} catch (e) {
|
|
1134
|
+
// Skip
|
|
1135
|
+
}
|
|
1136
|
+
}
|
|
1137
|
+
|
|
894
1138
|
return calls;
|
|
895
1139
|
}
|
|
896
1140
|
|
|
@@ -914,18 +1158,41 @@ ${tool.parameters.map(p => ` - ${p.name}${p.required ? ' (required)' : ''}: ${p
|
|
|
914
1158
|
}
|
|
915
1159
|
|
|
916
1160
|
prompt += `
|
|
917
|
-
|
|
1161
|
+
## How to Use Tools
|
|
1162
|
+
|
|
1163
|
+
To use a tool, output a JSON block in a code fence with "tool" language:
|
|
1164
|
+
|
|
918
1165
|
\`\`\`tool
|
|
919
|
-
{
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
1166
|
+
{"tool": "tool_name", "args": {"param1": "value1"}}
|
|
1167
|
+
\`\`\`
|
|
1168
|
+
|
|
1169
|
+
### Examples:
|
|
1170
|
+
|
|
1171
|
+
1. List directory contents:
|
|
1172
|
+
\`\`\`tool
|
|
1173
|
+
{"tool": "list_dir", "args": {"path": "/var/www/project"}}
|
|
1174
|
+
\`\`\`
|
|
1175
|
+
|
|
1176
|
+
2. Read a file:
|
|
1177
|
+
\`\`\`tool
|
|
1178
|
+
{"tool": "read_file", "args": {"path": "/var/www/project/index.html"}}
|
|
1179
|
+
\`\`\`
|
|
1180
|
+
|
|
1181
|
+
3. Run a shell command:
|
|
1182
|
+
\`\`\`tool
|
|
1183
|
+
{"tool": "bash", "args": {"command": "ls -la /var/www"}}
|
|
1184
|
+
\`\`\`
|
|
1185
|
+
|
|
1186
|
+
4. Write a file:
|
|
1187
|
+
\`\`\`tool
|
|
1188
|
+
{"tool": "write_file", "args": {"path": "/var/www/project/new.txt", "content": "Hello World"}}
|
|
925
1189
|
\`\`\`
|
|
926
1190
|
|
|
927
|
-
|
|
928
|
-
|
|
1191
|
+
IMPORTANT:
|
|
1192
|
+
- Use ONLY the exact tool names: list_dir, read_file, write_file, edit_file, bash, grep, glob, git
|
|
1193
|
+
- The JSON must be valid with double quotes for all keys and string values
|
|
1194
|
+
- After tool execution, you will receive results and can continue with the next step
|
|
1195
|
+
- Explain what you're doing before using tools
|
|
929
1196
|
`;
|
|
930
1197
|
|
|
931
1198
|
return prompt;
|