lua-cli 1.3.1 → 1.3.2-alpha.2
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/compile.js +227 -165
- package/dist/commands/dev.js +117 -114
- package/dist/commands/test.js +134 -113
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/services/api.d.ts +6 -0
- package/dist/services/api.js +27 -0
- package/dist/skill.d.ts +16 -1
- package/dist/skill.js +49 -0
- package/dist/types/index.d.ts +3 -3
- package/dist/user-data-api.d.ts +2 -15
- package/dist/user-data-api.js +9 -110
- package/dist/utils/files.js +33 -5
- package/dist/utils/sandbox.d.ts +96 -0
- package/dist/utils/sandbox.js +161 -0
- package/dist/web/app.css +274 -43
- package/dist/web/app.js +13 -13
- package/dist/web/tools-page.css +70 -53
- package/package.json +1 -1
- package/template/lua.skill.yaml +16 -0
- package/template/package-lock.json +9 -1
- package/template/package.json +3 -3
- package/template/src/index.ts +3 -14
- package/template/src/tools/CreatePostTool.ts +15 -23
- package/template/src/tools/GetWeatherTool.ts +22 -23
- package/template/src/tools/UserDataTool.ts +56 -0
- package/template/src/services/MathService.ts +0 -61
- package/template/src/tools/AdvancedMathTool.ts +0 -82
- package/template/src/tools/CalculatorTool.ts +0 -65
- package/template/src/tools/GetUserDataTool.ts +0 -38
- package/template/src/tools/UserPreferencesTool.ts +0 -73
- package/template/tools/UserPreferencesTool.ts +0 -73
package/dist/commands/compile.js
CHANGED
|
@@ -17,6 +17,11 @@ function decompressCode(compressedCode) {
|
|
|
17
17
|
export async function compileCommand() {
|
|
18
18
|
return withErrorHandling(async () => {
|
|
19
19
|
writeProgress("🔨 Compiling Lua skill...");
|
|
20
|
+
// Clean up old .lua directory
|
|
21
|
+
const oldLuaDir = path.join(process.cwd(), ".lua");
|
|
22
|
+
if (fs.existsSync(oldLuaDir)) {
|
|
23
|
+
fs.rmSync(oldLuaDir, { recursive: true, force: true });
|
|
24
|
+
}
|
|
20
25
|
// Read package.json to get version and name
|
|
21
26
|
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
22
27
|
if (!fs.existsSync(packageJsonPath)) {
|
|
@@ -79,21 +84,31 @@ async function extractSkillInfo(indexContent, indexFilePath) {
|
|
|
79
84
|
const sourceFile = ts.createSourceFile(indexFilePath, indexContent, ts.ScriptTarget.Latest, true);
|
|
80
85
|
// Traverse the AST to find skill.addTool() calls
|
|
81
86
|
function visit(node) {
|
|
82
|
-
// Check for skill.addTool() calls
|
|
87
|
+
// Check for skill.addTool() and skill.addTools() calls
|
|
83
88
|
if (ts.isCallExpression(node) &&
|
|
84
89
|
ts.isPropertyAccessExpression(node.expression) &&
|
|
85
90
|
ts.isIdentifier(node.expression.expression) &&
|
|
86
91
|
node.expression.expression.text === 'skill' &&
|
|
87
92
|
ts.isIdentifier(node.expression.name) &&
|
|
88
|
-
node.expression.name.text === 'addTool') {
|
|
93
|
+
(node.expression.name.text === 'addTool' || node.expression.name.text === 'addTools')) {
|
|
89
94
|
// Check if this call is commented out
|
|
90
95
|
if (isNodeCommentedOut(node, sourceFile)) {
|
|
91
96
|
return;
|
|
92
97
|
}
|
|
93
|
-
//
|
|
94
|
-
if (node.
|
|
95
|
-
|
|
96
|
-
|
|
98
|
+
// Handle both addTool and addTools calls
|
|
99
|
+
if (node.expression.name.text === 'addTool') {
|
|
100
|
+
// Single tool call
|
|
101
|
+
if (node.arguments.length > 0) {
|
|
102
|
+
toolArguments.push(node.arguments[0]);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
else if (node.expression.name.text === 'addTools') {
|
|
106
|
+
// Multiple tools call - add each tool from the array
|
|
107
|
+
if (node.arguments.length > 0 && ts.isArrayLiteralExpression(node.arguments[0])) {
|
|
108
|
+
for (const element of node.arguments[0].elements) {
|
|
109
|
+
toolArguments.push(element);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
97
112
|
}
|
|
98
113
|
}
|
|
99
114
|
// Continue traversing
|
|
@@ -106,9 +121,8 @@ async function extractSkillInfo(indexContent, indexFilePath) {
|
|
|
106
121
|
}
|
|
107
122
|
}
|
|
108
123
|
catch (error) {
|
|
109
|
-
console.warn('Warning: Could not parse TypeScript AST
|
|
110
|
-
|
|
111
|
-
return await extractSkillInfoRegex(indexContent, indexFilePath);
|
|
124
|
+
console.warn('Warning: Could not parse TypeScript AST:', error);
|
|
125
|
+
return [];
|
|
112
126
|
}
|
|
113
127
|
return tools;
|
|
114
128
|
}
|
|
@@ -152,9 +166,6 @@ async function processInlineTool(objectNode, sourceFile, indexContent, tools) {
|
|
|
152
166
|
else if (key === 'inputSchema' && ts.isIdentifier(value)) {
|
|
153
167
|
toolProperties.inputSchemaVar = value.text;
|
|
154
168
|
}
|
|
155
|
-
else if (key === 'outputSchema' && ts.isIdentifier(value)) {
|
|
156
|
-
toolProperties.outputSchemaVar = value.text;
|
|
157
|
-
}
|
|
158
169
|
else if (key === 'execute' && ts.isArrowFunction(value)) {
|
|
159
170
|
// Extract the function body
|
|
160
171
|
if (ts.isBlock(value.body)) {
|
|
@@ -168,16 +179,14 @@ async function processInlineTool(objectNode, sourceFile, indexContent, tools) {
|
|
|
168
179
|
if (toolProperties.name &&
|
|
169
180
|
toolProperties.description &&
|
|
170
181
|
toolProperties.inputSchemaVar &&
|
|
171
|
-
toolProperties.outputSchemaVar &&
|
|
172
182
|
toolProperties.executeBody) {
|
|
173
|
-
|
|
174
|
-
const
|
|
183
|
+
// For inline tools, we need to find the schema definitions in the index file
|
|
184
|
+
const inputSchema = extractSchemaFromIndex(toolProperties.inputSchemaVar, indexContent);
|
|
175
185
|
const selfContainedExecute = await createSelfContainedExecute(toolProperties.executeBody, indexContent);
|
|
176
186
|
tools.push({
|
|
177
187
|
name: toolProperties.name,
|
|
178
188
|
description: toolProperties.description,
|
|
179
|
-
inputSchema,
|
|
180
|
-
outputSchema,
|
|
189
|
+
inputSchema: inputSchema || { type: "object" },
|
|
181
190
|
execute: selfContainedExecute
|
|
182
191
|
});
|
|
183
192
|
}
|
|
@@ -203,142 +212,149 @@ function extractFunctionBody(blockStatement, sourceFile) {
|
|
|
203
212
|
}
|
|
204
213
|
return fullText;
|
|
205
214
|
}
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
const
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
braceCount++;
|
|
242
|
-
else if (char === '}')
|
|
243
|
-
braceCount--;
|
|
244
|
-
}
|
|
245
|
-
if (!found) {
|
|
246
|
-
searchIndex = addToolIndex + 1;
|
|
247
|
-
continue;
|
|
248
|
-
}
|
|
249
|
-
const toolArgument = indexContent.substring(callStart, callEnd).trim();
|
|
250
|
-
// Check if it's an inline tool definition: skill.addTool({...})
|
|
251
|
-
if (toolArgument.startsWith('{')) {
|
|
252
|
-
// Extract tool properties
|
|
253
|
-
const nameMatch = toolArgument.match(/name:\s*["']([^"']+)["']/);
|
|
254
|
-
const descriptionMatch = toolArgument.match(/description:\s*["']([^"']+)["']/);
|
|
255
|
-
const inputSchemaMatch = toolArgument.match(/inputSchema:\s*(\w+)/);
|
|
256
|
-
const outputSchemaMatch = toolArgument.match(/outputSchema:\s*(\w+)/);
|
|
257
|
-
const executeMatch = toolArgument.match(/execute:\s*async\s*\([^)]*\)\s*=>\s*\{([\s\S]*?)\}/);
|
|
258
|
-
if (nameMatch && descriptionMatch && inputSchemaMatch && outputSchemaMatch && executeMatch) {
|
|
259
|
-
const toolName = nameMatch[1];
|
|
260
|
-
const toolDescription = descriptionMatch[1];
|
|
261
|
-
const inputSchemaVar = inputSchemaMatch[1];
|
|
262
|
-
const outputSchemaVar = outputSchemaMatch[1];
|
|
263
|
-
const executeBody = executeMatch[1];
|
|
264
|
-
// Convert schemas to JSON Schema format
|
|
265
|
-
const inputSchema = convertSchemaToJSON(inputSchemaVar, indexContent);
|
|
266
|
-
const outputSchema = convertSchemaToJSON(outputSchemaVar, indexContent);
|
|
267
|
-
// Create self-contained execute function
|
|
268
|
-
const selfContainedExecute = await createSelfContainedExecute(executeBody, indexContent);
|
|
269
|
-
tools.push({
|
|
270
|
-
name: toolName,
|
|
271
|
-
description: toolDescription,
|
|
272
|
-
inputSchema,
|
|
273
|
-
outputSchema,
|
|
274
|
-
execute: selfContainedExecute
|
|
275
|
-
});
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
// Check if it's a class-based tool: skill.addTool(new SomeTool())
|
|
279
|
-
else if (toolArgument.startsWith('new ')) {
|
|
280
|
-
const classMatch = toolArgument.match(/new\s+(\w+)\(\)/);
|
|
281
|
-
if (classMatch) {
|
|
282
|
-
const className = classMatch[1];
|
|
283
|
-
// Find the tool class definition
|
|
284
|
-
const toolInfo = await extractToolFromClass(className, indexContent, indexFilePath);
|
|
285
|
-
if (toolInfo) {
|
|
286
|
-
tools.push(toolInfo);
|
|
215
|
+
function convertZodTypeToJSONSchema(zodType) {
|
|
216
|
+
switch (zodType) {
|
|
217
|
+
case 'string':
|
|
218
|
+
return { type: 'string' };
|
|
219
|
+
case 'number':
|
|
220
|
+
return { type: 'number' };
|
|
221
|
+
case 'boolean':
|
|
222
|
+
return { type: 'boolean' };
|
|
223
|
+
default:
|
|
224
|
+
return { type: 'string' };
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
function extractZodSchemaFromAST(node) {
|
|
228
|
+
// Handle z.object({...}) calls
|
|
229
|
+
if (ts.isCallExpression(node) &&
|
|
230
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
231
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
232
|
+
node.expression.expression.text === 'z' &&
|
|
233
|
+
ts.isIdentifier(node.expression.name) &&
|
|
234
|
+
node.expression.name.text === 'object') {
|
|
235
|
+
const objectLiteral = node.arguments[0];
|
|
236
|
+
if (ts.isObjectLiteralExpression(objectLiteral)) {
|
|
237
|
+
const properties = {};
|
|
238
|
+
const required = [];
|
|
239
|
+
for (const property of objectLiteral.properties) {
|
|
240
|
+
if (ts.isPropertyAssignment(property) &&
|
|
241
|
+
ts.isIdentifier(property.name) &&
|
|
242
|
+
property.initializer) {
|
|
243
|
+
const propertyName = property.name.text;
|
|
244
|
+
const zodType = extractZodTypeFromAST(property.initializer);
|
|
245
|
+
properties[propertyName] = zodType;
|
|
246
|
+
// Only add to required if it's not optional
|
|
247
|
+
if (!isOptionalZodType(property.initializer)) {
|
|
248
|
+
required.push(propertyName);
|
|
249
|
+
}
|
|
287
250
|
}
|
|
288
251
|
}
|
|
252
|
+
return {
|
|
253
|
+
type: "object",
|
|
254
|
+
properties,
|
|
255
|
+
required
|
|
256
|
+
};
|
|
289
257
|
}
|
|
290
|
-
searchIndex = callEnd + 1;
|
|
291
|
-
}
|
|
292
|
-
return tools;
|
|
293
|
-
}
|
|
294
|
-
function convertSchemaToJSON(schemaVar, indexContent) {
|
|
295
|
-
// Find the schema definition
|
|
296
|
-
const schemaRegex = new RegExp(`const\\s+${schemaVar}\\s*=\\s*z\\.object\\(\\{([\\s\\S]*?)\\}\\\);`, 'g');
|
|
297
|
-
const match = schemaRegex.exec(indexContent);
|
|
298
|
-
if (match) {
|
|
299
|
-
const schemaContent = match[1];
|
|
300
|
-
// Convert Zod schema to JSON Schema format
|
|
301
|
-
return {
|
|
302
|
-
type: "object",
|
|
303
|
-
properties: parseZodProperties(schemaContent),
|
|
304
|
-
required: extractRequiredFields(schemaContent)
|
|
305
|
-
};
|
|
306
258
|
}
|
|
307
|
-
|
|
308
|
-
return { type: "object", properties: {} };
|
|
259
|
+
return { type: "object" };
|
|
309
260
|
}
|
|
310
|
-
function
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
const
|
|
317
|
-
|
|
318
|
-
switch (fieldType) {
|
|
261
|
+
function extractZodTypeFromAST(node) {
|
|
262
|
+
// Handle z.string(), z.number(), z.boolean(), etc.
|
|
263
|
+
if (ts.isCallExpression(node) &&
|
|
264
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
265
|
+
ts.isIdentifier(node.expression.expression) &&
|
|
266
|
+
node.expression.expression.text === 'z') {
|
|
267
|
+
const zodType = node.expression.name.text;
|
|
268
|
+
switch (zodType) {
|
|
319
269
|
case 'string':
|
|
320
|
-
|
|
321
|
-
break;
|
|
270
|
+
return { type: 'string' };
|
|
322
271
|
case 'number':
|
|
323
|
-
|
|
324
|
-
break;
|
|
272
|
+
return { type: 'number' };
|
|
325
273
|
case 'boolean':
|
|
326
|
-
|
|
327
|
-
|
|
274
|
+
return { type: 'boolean' };
|
|
275
|
+
case 'array':
|
|
276
|
+
// Handle z.array(z.string()) etc.
|
|
277
|
+
if (node.arguments.length > 0) {
|
|
278
|
+
const elementType = extractZodTypeFromAST(node.arguments[0]);
|
|
279
|
+
return { type: 'array', items: elementType };
|
|
280
|
+
}
|
|
281
|
+
return { type: 'array' };
|
|
282
|
+
case 'object':
|
|
283
|
+
// Handle nested z.object({...}) calls
|
|
284
|
+
if (node.arguments.length > 0) {
|
|
285
|
+
return extractZodSchemaFromAST(node);
|
|
286
|
+
}
|
|
287
|
+
return { type: 'object' };
|
|
288
|
+
case 'enum':
|
|
289
|
+
// Handle z.enum(['a', 'b', 'c'])
|
|
290
|
+
if (node.arguments.length > 0 && ts.isArrayLiteralExpression(node.arguments[0])) {
|
|
291
|
+
const enumValues = [];
|
|
292
|
+
for (const element of node.arguments[0].elements) {
|
|
293
|
+
if (ts.isStringLiteral(element)) {
|
|
294
|
+
enumValues.push(element.text);
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
return { type: 'string', enum: enumValues };
|
|
298
|
+
}
|
|
299
|
+
return { type: 'string' };
|
|
328
300
|
default:
|
|
329
|
-
|
|
301
|
+
return { type: 'string' };
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
// Handle method chaining like z.string().optional()
|
|
305
|
+
if (ts.isCallExpression(node) &&
|
|
306
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
307
|
+
ts.isCallExpression(node.expression.expression)) {
|
|
308
|
+
const baseType = extractZodTypeFromAST(node.expression.expression);
|
|
309
|
+
const method = node.expression.name.text;
|
|
310
|
+
if (method === 'optional') {
|
|
311
|
+
// Optional fields are handled by not including them in required array
|
|
312
|
+
return baseType;
|
|
330
313
|
}
|
|
314
|
+
return baseType;
|
|
331
315
|
}
|
|
332
|
-
return
|
|
316
|
+
return { type: 'string' };
|
|
333
317
|
}
|
|
334
|
-
function
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
318
|
+
function isOptionalZodType(node) {
|
|
319
|
+
// Check if this is a chained call ending with .optional()
|
|
320
|
+
if (ts.isCallExpression(node) &&
|
|
321
|
+
ts.isPropertyAccessExpression(node.expression) &&
|
|
322
|
+
ts.isIdentifier(node.expression.name) &&
|
|
323
|
+
node.expression.name.text === 'optional') {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
return false;
|
|
327
|
+
}
|
|
328
|
+
function extractSchemaFromIndex(schemaVar, indexContent) {
|
|
329
|
+
// Create a source file from the index content to parse schemas using AST
|
|
330
|
+
const sourceFile = ts.createSourceFile('index.ts', indexContent, ts.ScriptTarget.Latest, true);
|
|
331
|
+
let schema = null;
|
|
332
|
+
function findSchema(node) {
|
|
333
|
+
// Look for const schemaVar = z.object({...}) declarations
|
|
334
|
+
if (ts.isVariableDeclaration(node) &&
|
|
335
|
+
ts.isIdentifier(node.name) &&
|
|
336
|
+
node.name.text === schemaVar &&
|
|
337
|
+
node.initializer) {
|
|
338
|
+
schema = extractZodSchemaFromAST(node.initializer);
|
|
339
|
+
return;
|
|
340
|
+
}
|
|
341
|
+
ts.forEachChild(node, findSchema);
|
|
342
|
+
}
|
|
343
|
+
findSchema(sourceFile);
|
|
344
|
+
return schema;
|
|
345
|
+
}
|
|
346
|
+
function extractEnvironmentVariables() {
|
|
347
|
+
const config = readSkillConfig();
|
|
348
|
+
const envVars = [];
|
|
349
|
+
if (config?.skill?.env) {
|
|
350
|
+
for (const [key, value] of Object.entries(config.skill.env)) {
|
|
351
|
+
envVars.push({
|
|
352
|
+
name: key,
|
|
353
|
+
value: value
|
|
354
|
+
});
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
return envVars;
|
|
342
358
|
}
|
|
343
359
|
async function createSelfContainedExecute(executeBody, indexContent) {
|
|
344
360
|
const dependencies = [];
|
|
@@ -741,14 +757,34 @@ const axios = {
|
|
|
741
757
|
`;
|
|
742
758
|
}
|
|
743
759
|
async function extractToolFromClass(className, indexContent, indexFilePath) {
|
|
744
|
-
// Find the import statement for this class
|
|
745
|
-
const
|
|
746
|
-
|
|
747
|
-
|
|
760
|
+
// Find the import statement for this class using AST
|
|
761
|
+
const sourceFile = ts.createSourceFile(indexFilePath, indexContent, ts.ScriptTarget.Latest, true);
|
|
762
|
+
let importPath = null;
|
|
763
|
+
function findImport(node) {
|
|
764
|
+
if (ts.isImportDeclaration(node) && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
|
765
|
+
const moduleSpecifier = node.moduleSpecifier;
|
|
766
|
+
// Check if this import has the class we're looking for
|
|
767
|
+
if (node.importClause && node.importClause.name && node.importClause.name.text === className) {
|
|
768
|
+
importPath = moduleSpecifier.text;
|
|
769
|
+
return;
|
|
770
|
+
}
|
|
771
|
+
// Check named imports
|
|
772
|
+
if (node.importClause && node.importClause.namedBindings && ts.isNamedImports(node.importClause.namedBindings)) {
|
|
773
|
+
for (const element of node.importClause.namedBindings.elements) {
|
|
774
|
+
if (element.name.text === className) {
|
|
775
|
+
importPath = moduleSpecifier.text;
|
|
776
|
+
return;
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
}
|
|
780
|
+
}
|
|
781
|
+
ts.forEachChild(node, findImport);
|
|
782
|
+
}
|
|
783
|
+
findImport(sourceFile);
|
|
784
|
+
if (!importPath) {
|
|
748
785
|
console.warn(`Warning: Could not find import for class ${className}`);
|
|
749
786
|
return null;
|
|
750
787
|
}
|
|
751
|
-
const importPath = importMatch[1];
|
|
752
788
|
// Read the tool file - handle both relative and absolute paths
|
|
753
789
|
let toolFilePath;
|
|
754
790
|
if (importPath.startsWith('./') || importPath.startsWith('../')) {
|
|
@@ -765,32 +801,59 @@ async function extractToolFromClass(className, indexContent, indexFilePath) {
|
|
|
765
801
|
return null;
|
|
766
802
|
}
|
|
767
803
|
const toolContent = fs.readFileSync(toolFilePath, 'utf8');
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
804
|
+
const toolSourceFile = ts.createSourceFile(toolFilePath, toolContent, ts.ScriptTarget.Latest, true);
|
|
805
|
+
// Extract tool properties using AST
|
|
806
|
+
let toolName = null;
|
|
807
|
+
let toolDescription = null;
|
|
808
|
+
let inputSchema = null;
|
|
809
|
+
let executeMethod = null;
|
|
810
|
+
function extractToolInfo(node) {
|
|
811
|
+
// Look for class declaration
|
|
812
|
+
if (ts.isClassDeclaration(node) && node.name && node.name.text === className) {
|
|
813
|
+
// Extract class members
|
|
814
|
+
for (const member of node.members) {
|
|
815
|
+
if (ts.isPropertyDeclaration(member) && member.name && ts.isIdentifier(member.name)) {
|
|
816
|
+
const propertyName = member.name.text;
|
|
817
|
+
// Extract name property
|
|
818
|
+
if (propertyName === 'name' && member.initializer && ts.isStringLiteral(member.initializer)) {
|
|
819
|
+
toolName = member.initializer.text;
|
|
820
|
+
}
|
|
821
|
+
// Extract description property
|
|
822
|
+
if (propertyName === 'description' && member.initializer && ts.isStringLiteral(member.initializer)) {
|
|
823
|
+
toolDescription = member.initializer.text;
|
|
824
|
+
}
|
|
825
|
+
// Extract inputSchema property
|
|
826
|
+
if (propertyName === 'inputSchema' && member.initializer) {
|
|
827
|
+
inputSchema = extractZodSchemaFromAST(member.initializer);
|
|
828
|
+
}
|
|
829
|
+
}
|
|
830
|
+
// Extract execute method
|
|
831
|
+
if (ts.isMethodDeclaration(member) && member.name && ts.isIdentifier(member.name) && member.name.text === 'execute') {
|
|
832
|
+
executeMethod = member;
|
|
833
|
+
}
|
|
834
|
+
}
|
|
835
|
+
}
|
|
836
|
+
ts.forEachChild(node, extractToolInfo);
|
|
837
|
+
}
|
|
838
|
+
extractToolInfo(toolSourceFile);
|
|
839
|
+
if (!toolName || !toolDescription) {
|
|
772
840
|
console.warn(`Warning: Could not extract name or description from ${className}`);
|
|
773
841
|
return null;
|
|
774
842
|
}
|
|
775
|
-
|
|
776
|
-
const toolDescription = descriptionMatch[1];
|
|
777
|
-
// Extract schemas - look for multiple schema definitions
|
|
778
|
-
const inputSchemaMatch = toolContent.match(/const\s+(\w+)\s*=\s*z\.object\(/);
|
|
779
|
-
const outputSchemaMatch = toolContent.match(/const\s+(\w+)\s*=\s*z\.object\(/);
|
|
780
|
-
if (!inputSchemaMatch) {
|
|
843
|
+
if (!inputSchema) {
|
|
781
844
|
console.warn(`Warning: Could not find input schema in ${className}`);
|
|
782
845
|
return null;
|
|
783
846
|
}
|
|
784
|
-
|
|
785
|
-
const inputSchema = convertSchemaToJSON(inputSchemaMatch[1], toolContent);
|
|
786
|
-
const outputSchema = outputSchemaMatch ? convertSchemaToJSON(outputSchemaMatch[1], toolContent) : { type: "object" };
|
|
787
|
-
// Extract execute method
|
|
788
|
-
const executeMatch = toolContent.match(/async\s+execute\s*\([^)]*\)\s*\{([\s\S]*?)\}/);
|
|
789
|
-
if (!executeMatch) {
|
|
847
|
+
if (!executeMethod) {
|
|
790
848
|
console.warn(`Warning: Could not find execute method in ${className}`);
|
|
791
849
|
return null;
|
|
792
850
|
}
|
|
793
|
-
|
|
851
|
+
// Extract execute method body
|
|
852
|
+
if (!executeMethod.body) {
|
|
853
|
+
console.warn(`Warning: Execute method has no body in ${className}`);
|
|
854
|
+
return null;
|
|
855
|
+
}
|
|
856
|
+
const executeBody = extractFunctionBody(executeMethod.body, toolSourceFile);
|
|
794
857
|
// For class-based tools, we need to create a self-contained function that includes:
|
|
795
858
|
// 1. The service classes
|
|
796
859
|
// 2. Class instantiation
|
|
@@ -799,8 +862,7 @@ async function extractToolFromClass(className, indexContent, indexFilePath) {
|
|
|
799
862
|
return {
|
|
800
863
|
name: toolName,
|
|
801
864
|
description: toolDescription,
|
|
802
|
-
inputSchema,
|
|
803
|
-
outputSchema,
|
|
865
|
+
inputSchema: inputSchema || { type: "object" },
|
|
804
866
|
execute: selfContainedExecute
|
|
805
867
|
};
|
|
806
868
|
}
|