lua-cli 2.2.8-alpha.2 → 2.3.0-alpha.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/API_REFERENCE.md +1408 -0
- package/CLI_REFERENCE.md +818 -0
- package/GETTING_STARTED.md +1040 -0
- package/README.md +738 -424
- package/TEMPLATE_GUIDE.md +1398 -0
- package/dist/api/agent.api.service.d.ts +33 -6
- package/dist/api/agent.api.service.js +27 -0
- package/dist/api/auth.api.service.d.ts +31 -2
- package/dist/api/auth.api.service.js +29 -0
- package/dist/api/basket.api.service.d.ts +53 -11
- package/dist/api/basket.api.service.js +63 -14
- package/dist/api/chat.api.service.d.ts +15 -3
- package/dist/api/chat.api.service.js +12 -0
- package/dist/api/credentials.d.ts +24 -0
- package/dist/api/credentials.js +46 -0
- package/dist/api/custom.data.api.service.d.ts +45 -9
- package/dist/api/custom.data.api.service.js +43 -9
- package/dist/api/lazy-instances.d.ts +49 -0
- package/dist/api/lazy-instances.js +95 -0
- package/dist/api/order.api.service.d.ts +34 -4
- package/dist/api/order.api.service.js +41 -3
- package/dist/api/products.api.service.d.ts +39 -9
- package/dist/api/products.api.service.js +43 -5
- package/dist/api/skills.api.service.d.ts +49 -2
- package/dist/api/skills.api.service.js +47 -1
- package/dist/api/tool.api.service.d.ts +39 -1
- package/dist/api/tool.api.service.js +38 -0
- package/dist/api/user.data.api.service.d.ts +23 -1
- package/dist/api/user.data.api.service.js +22 -0
- package/dist/api-exports.d.ts +236 -5
- package/dist/api-exports.js +264 -81
- package/dist/cli/command-definitions.d.ts +30 -0
- package/dist/cli/command-definitions.js +71 -0
- package/dist/commands/agents.d.ts +20 -0
- package/dist/commands/agents.js +24 -2
- package/dist/commands/apiKey.d.ts +23 -0
- package/dist/commands/apiKey.js +23 -0
- package/dist/commands/compile.d.ts +24 -0
- package/dist/commands/compile.js +67 -759
- package/dist/commands/configure.d.ts +24 -0
- package/dist/commands/configure.js +31 -96
- package/dist/commands/deploy.d.ts +31 -19
- package/dist/commands/deploy.js +45 -74
- package/dist/commands/destroy.d.ts +27 -0
- package/dist/commands/destroy.js +27 -1
- package/dist/commands/dev.d.ts +25 -62
- package/dist/commands/dev.js +58 -878
- package/dist/commands/init.d.ts +27 -0
- package/dist/commands/init.js +98 -260
- package/dist/commands/push.d.ts +24 -21
- package/dist/commands/push.js +39 -92
- package/dist/commands/test.d.ts +26 -0
- package/dist/commands/test.js +41 -188
- package/dist/common/basket.instance.d.ts +54 -3
- package/dist/common/basket.instance.js +56 -3
- package/dist/common/data.entry.instance.d.ts +25 -2
- package/dist/common/data.entry.instance.js +24 -0
- package/dist/common/http.client.d.ts +51 -1
- package/dist/common/http.client.js +50 -0
- package/dist/common/order.instance.d.ts +22 -0
- package/dist/common/order.instance.js +31 -4
- package/dist/common/product.instance.d.ts +22 -1
- package/dist/common/product.instance.js +24 -6
- package/dist/common/product.pagination.instance.d.ts +22 -2
- package/dist/common/product.pagination.instance.js +22 -1
- package/dist/common/product.search.instance.d.ts +13 -3
- package/dist/common/product.search.instance.js +12 -1
- package/dist/common/user.instance.d.ts +27 -3
- package/dist/common/user.instance.js +28 -7
- package/dist/config/auth.constants.d.ts +11 -0
- package/dist/config/auth.constants.js +11 -0
- package/dist/config/compile.constants.d.ts +67 -0
- package/dist/config/compile.constants.js +99 -0
- package/dist/config/constants.d.ts +5 -0
- package/dist/config/constants.js +5 -0
- package/dist/config/dev.constants.d.ts +65 -0
- package/dist/config/dev.constants.js +79 -0
- package/dist/config/init.constants.d.ts +23 -0
- package/dist/config/init.constants.js +41 -0
- package/dist/index.d.ts +19 -3
- package/dist/index.js +28 -44
- package/dist/interfaces/admin.d.ts +56 -50
- package/dist/interfaces/admin.js +4 -0
- package/dist/interfaces/agent.d.ts +21 -0
- package/dist/interfaces/agent.js +4 -0
- package/dist/interfaces/baskets.d.ts +60 -0
- package/dist/interfaces/baskets.js +12 -0
- package/dist/interfaces/chat.d.ts +48 -4
- package/dist/interfaces/chat.js +4 -0
- package/dist/interfaces/common.d.ts +62 -0
- package/dist/interfaces/common.js +8 -0
- package/dist/interfaces/compile.d.ts +11 -0
- package/dist/interfaces/compile.js +4 -0
- package/dist/interfaces/custom.data.d.ts +49 -19
- package/dist/interfaces/custom.data.js +4 -0
- package/dist/interfaces/deploy.d.ts +29 -0
- package/dist/interfaces/deploy.js +4 -0
- package/dist/interfaces/dev.d.ts +53 -0
- package/dist/interfaces/dev.js +5 -0
- package/dist/interfaces/init.d.ts +60 -0
- package/dist/interfaces/init.js +4 -0
- package/dist/interfaces/orders.d.ts +37 -0
- package/dist/interfaces/orders.js +12 -0
- package/dist/interfaces/product.d.ts +38 -10
- package/dist/interfaces/product.js +4 -0
- package/dist/interfaces/push.d.ts +26 -0
- package/dist/interfaces/push.js +4 -0
- package/dist/interfaces/test.d.ts +36 -0
- package/dist/interfaces/test.js +4 -0
- package/dist/services/auth.d.ts +54 -99
- package/dist/services/auth.js +76 -12
- package/dist/types/api-contracts.d.ts +211 -0
- package/dist/types/api-contracts.js +8 -0
- package/dist/types/compile.types.d.ts +76 -0
- package/dist/types/compile.types.js +4 -0
- package/dist/types/index.d.ts +23 -121
- package/dist/types/index.js +25 -14
- package/dist/types/skill.d.ts +142 -0
- package/dist/{skill.js → types/skill.js} +66 -17
- package/dist/types/tool-validation.d.ts +34 -0
- package/dist/types/tool-validation.js +42 -0
- package/dist/utils/auth-flows.d.ts +26 -0
- package/dist/utils/auth-flows.js +141 -0
- package/dist/utils/bundling.d.ts +36 -0
- package/dist/utils/bundling.js +137 -0
- package/dist/utils/compile.d.ts +37 -0
- package/dist/utils/compile.js +242 -0
- package/dist/utils/deploy-api.d.ts +26 -0
- package/dist/utils/deploy-api.js +53 -0
- package/dist/utils/deploy-helpers.d.ts +46 -0
- package/dist/utils/deploy-helpers.js +86 -0
- package/dist/utils/deployment.d.ts +25 -0
- package/dist/utils/deployment.js +161 -0
- package/dist/utils/dev-api.d.ts +61 -0
- package/dist/utils/dev-api.js +262 -0
- package/dist/utils/dev-helpers.d.ts +46 -0
- package/dist/utils/dev-helpers.js +83 -0
- package/dist/utils/dev-server.d.ts +24 -0
- package/dist/utils/dev-server.js +555 -0
- package/dist/utils/dev-watcher.d.ts +31 -0
- package/dist/utils/dev-watcher.js +110 -0
- package/dist/utils/files.js +0 -5
- package/dist/utils/init-agent.d.ts +34 -0
- package/dist/utils/init-agent.js +129 -0
- package/dist/utils/init-helpers.d.ts +41 -0
- package/dist/utils/init-helpers.js +73 -0
- package/dist/utils/init-prompts.d.ts +47 -0
- package/dist/utils/init-prompts.js +168 -0
- package/dist/utils/push-api.d.ts +15 -0
- package/dist/utils/push-api.js +48 -0
- package/dist/utils/push-helpers.d.ts +38 -0
- package/dist/utils/push-helpers.js +84 -0
- package/dist/utils/sandbox-storage.d.ts +27 -0
- package/dist/utils/sandbox-storage.js +71 -0
- package/dist/utils/sandbox.js +78 -114
- package/dist/utils/skill-management.d.ts +14 -0
- package/dist/utils/skill-management.js +148 -0
- package/dist/utils/test-helpers.d.ts +40 -0
- package/dist/utils/test-helpers.js +92 -0
- package/dist/utils/test-prompts.d.ts +23 -0
- package/dist/utils/test-prompts.js +186 -0
- package/dist/utils/tool-detection.d.ts +18 -0
- package/dist/utils/tool-detection.js +110 -0
- package/dist/web/app.css +14 -9
- package/package.json +7 -4
- package/template/QUICKSTART.md +299 -144
- package/template/README.md +928 -349
- package/template/TOOL_EXAMPLES.md +655 -0
- package/template/package-lock.json +5 -5
- package/template/package.json +1 -1
- package/template/src/index.ts +147 -207
- package/template/src/tools/BasketTool.ts +128 -0
- package/template/src/tools/CustomDataTool.ts +7 -13
- package/template/src/tools/OrderTool.ts +54 -0
- package/template/src/tools/PaymentTool.ts +1 -1
- package/template/src/tools/ProductsTool.ts +56 -118
- package/template/src/tools/UserDataTool.ts +4 -26
- package/dist/common/config.d.ts +0 -5
- package/dist/common/config.js +0 -5
- package/dist/custom-data-api.d.ts +0 -72
- package/dist/custom-data-api.js +0 -174
- package/dist/product-api.d.ts +0 -189
- package/dist/product-api.js +0 -141
- package/dist/services/api.d.ts +0 -549
- package/dist/services/api.js +0 -596
- package/dist/skill.d.ts +0 -50
- package/dist/types.d.ts +0 -1
- package/dist/types.js +0 -2
- package/dist/user-data-api.d.ts +0 -39
- package/dist/user-data-api.js +0 -50
- package/template/API.md +0 -604
- package/template/DEVELOPER.md +0 -771
- package/template/lua.skill.yaml +0 -7
package/dist/commands/compile.js
CHANGED
|
@@ -1,781 +1,89 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile Command
|
|
3
|
+
* Orchestrates the skill compilation process by coordinating various compilation steps
|
|
4
|
+
*/
|
|
1
5
|
import fs from "fs";
|
|
2
6
|
import path from "path";
|
|
3
|
-
import {
|
|
7
|
+
import { Project } from "ts-morph";
|
|
4
8
|
import { withErrorHandling, writeProgress, writeSuccess } from "../utils/cli.js";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
9
|
+
import { findIndexFile } from '../utils/compile.js';
|
|
10
|
+
import { detectTools } from '../utils/tool-detection.js';
|
|
11
|
+
import { bundleTool, bundleMainIndex, extractExecuteCode } from '../utils/bundling.js';
|
|
12
|
+
import { createDeploymentData, createLegacyDeploymentData } from '../utils/deployment.js';
|
|
13
|
+
import { COMPILE_DIRS, COMPILE_FILES } from '../config/compile.constants.js';
|
|
14
|
+
/**
|
|
15
|
+
* Main compile command - orchestrates the entire skill compilation process.
|
|
16
|
+
*
|
|
17
|
+
* This command performs the following steps:
|
|
18
|
+
* 1. Cleans and prepares output directories (dist/ and .lua/)
|
|
19
|
+
* 2. Analyzes the TypeScript project to detect all tools
|
|
20
|
+
* 3. Bundles each tool individually using esbuild
|
|
21
|
+
* 4. Extracts execute code and schemas from bundled tools
|
|
22
|
+
* 5. Bundles the main index file
|
|
23
|
+
* 6. Creates deployment data in both new and legacy formats
|
|
24
|
+
*
|
|
25
|
+
* Output:
|
|
26
|
+
* - dist/deployment.json - New deployment format with tool references
|
|
27
|
+
* - dist/tools/*.js - Individual bundled tool files
|
|
28
|
+
* - dist/index.js - Main skill entry point
|
|
29
|
+
* - .lua/deploy.json - Legacy deployment format with compressed tools
|
|
30
|
+
* - .lua/*.js - Individual uncompressed tool files for debugging
|
|
31
|
+
*
|
|
32
|
+
* @returns Promise that resolves when compilation is complete
|
|
33
|
+
*/
|
|
16
34
|
export async function compileCommand() {
|
|
17
35
|
return withErrorHandling(async () => {
|
|
18
36
|
writeProgress("🔨 Compiling Lua skill...");
|
|
19
|
-
//
|
|
20
|
-
const distDir =
|
|
21
|
-
|
|
22
|
-
if (fs.existsSync(distDir)) {
|
|
23
|
-
fs.rmSync(distDir, { recursive: true, force: true });
|
|
24
|
-
}
|
|
25
|
-
if (fs.existsSync(luaDir)) {
|
|
26
|
-
fs.rmSync(luaDir, { recursive: true, force: true });
|
|
27
|
-
}
|
|
28
|
-
// Create directory structures
|
|
29
|
-
fs.mkdirSync(distDir, { recursive: true });
|
|
30
|
-
fs.mkdirSync(path.join(distDir, "tools"), { recursive: true });
|
|
31
|
-
fs.mkdirSync(luaDir, { recursive: true });
|
|
32
|
-
// Find index.ts file
|
|
37
|
+
// Step 1: Prepare output directories
|
|
38
|
+
const { distDir, luaDir } = prepareOutputDirectories();
|
|
39
|
+
// Step 2: Analyze TypeScript project and detect tools
|
|
33
40
|
const indexPath = findIndexFile();
|
|
34
|
-
|
|
35
|
-
const project = new Project({
|
|
36
|
-
tsConfigFilePath: path.join(process.cwd(), "tsconfig.json"),
|
|
37
|
-
});
|
|
38
|
-
// Add the index file to the project
|
|
41
|
+
const project = createTypeScriptProject();
|
|
39
42
|
const indexFile = project.addSourceFileAtPath(indexPath);
|
|
40
|
-
// Detect tools from skill.addTools calls
|
|
41
43
|
const tools = await detectTools(indexFile, project);
|
|
42
44
|
writeProgress(`📦 Found ${tools.length} tools to bundle...`);
|
|
43
|
-
// Bundle each tool
|
|
45
|
+
// Step 3: Bundle each tool and extract metadata
|
|
44
46
|
for (const tool of tools) {
|
|
45
47
|
await bundleTool(tool, distDir);
|
|
46
48
|
await extractExecuteCode(tool, project);
|
|
47
49
|
}
|
|
48
|
-
// Bundle the main index file
|
|
50
|
+
// Step 4: Bundle the main index file
|
|
49
51
|
await bundleMainIndex(indexPath, distDir);
|
|
50
|
-
// Create both
|
|
52
|
+
// Step 5: Create deployment data in both formats
|
|
51
53
|
await createDeploymentData(tools, distDir);
|
|
52
54
|
await createLegacyDeploymentData(tools, luaDir, indexFile);
|
|
53
55
|
writeSuccess(`✅ Skill compiled successfully - ${tools.length} tools bundled`);
|
|
54
56
|
}, "compilation");
|
|
55
57
|
}
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
if (Node.isNewExpression(element)) {
|
|
87
|
-
const toolInfo = extractToolFromNewExpressionSync(element, project);
|
|
88
|
-
if (toolInfo) {
|
|
89
|
-
tools.push(toolInfo);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
});
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
});
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
});
|
|
100
|
-
// Find all call expressions in the file (addTools method calls)
|
|
101
|
-
indexFile.forEachDescendant((node) => {
|
|
102
|
-
if (Node.isCallExpression(node)) {
|
|
103
|
-
const expression = node.getExpression();
|
|
104
|
-
// Check if this is skill.addTools or skill.addTool
|
|
105
|
-
if (Node.isPropertyAccessExpression(expression)) {
|
|
106
|
-
const object = expression.getExpression();
|
|
107
|
-
const property = expression.getName();
|
|
108
|
-
if (property === 'addTools' || property === 'addTool') {
|
|
109
|
-
const args = node.getArguments();
|
|
110
|
-
if (property === 'addTools' && args.length > 0) {
|
|
111
|
-
// Handle skill.addTools([...]) - array of tools
|
|
112
|
-
const arrayArg = args[0];
|
|
113
|
-
if (Node.isArrayLiteralExpression(arrayArg)) {
|
|
114
|
-
const elements = arrayArg.getElements();
|
|
115
|
-
for (const element of elements) {
|
|
116
|
-
if (Node.isNewExpression(element)) {
|
|
117
|
-
const toolInfo = extractToolFromNewExpressionSync(element, project);
|
|
118
|
-
if (toolInfo) {
|
|
119
|
-
tools.push(toolInfo);
|
|
120
|
-
}
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
else if (property === 'addTool' && args.length > 0) {
|
|
126
|
-
// Handle skill.addTool(new ToolClass()) - single tool
|
|
127
|
-
const arg = args[0];
|
|
128
|
-
if (Node.isNewExpression(arg)) {
|
|
129
|
-
const toolInfo = extractToolFromNewExpressionSync(arg, project);
|
|
130
|
-
if (toolInfo) {
|
|
131
|
-
tools.push(toolInfo);
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
});
|
|
139
|
-
return tools;
|
|
140
|
-
}
|
|
141
|
-
function extractToolFromNewExpressionSync(newExpr, project) {
|
|
142
|
-
try {
|
|
143
|
-
const expression = newExpr.getExpression();
|
|
144
|
-
const className = expression.getText();
|
|
145
|
-
// Find the import declaration for this class
|
|
146
|
-
const sourceFile = newExpr.getSourceFile();
|
|
147
|
-
const imports = sourceFile.getImportDeclarations();
|
|
148
|
-
for (const importDecl of imports) {
|
|
149
|
-
const namedImports = importDecl.getNamedImports();
|
|
150
|
-
const defaultImport = importDecl.getDefaultImport();
|
|
151
|
-
let toolFilePath = null;
|
|
152
|
-
// Check named imports
|
|
153
|
-
for (const namedImport of namedImports) {
|
|
154
|
-
if (namedImport.getName() === className) {
|
|
155
|
-
toolFilePath = resolveImportPath(importDecl.getModuleSpecifierValue(), sourceFile.getFilePath());
|
|
156
|
-
break;
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
// Check default import
|
|
160
|
-
if (!toolFilePath && defaultImport && defaultImport.getText() === className) {
|
|
161
|
-
toolFilePath = resolveImportPath(importDecl.getModuleSpecifierValue(), sourceFile.getFilePath());
|
|
162
|
-
}
|
|
163
|
-
if (toolFilePath && fs.existsSync(toolFilePath)) {
|
|
164
|
-
// Extract tool metadata from the class file
|
|
165
|
-
try {
|
|
166
|
-
const toolSourceFile = project.addSourceFileAtPath(toolFilePath);
|
|
167
|
-
const classDecl = toolSourceFile.getClass(className);
|
|
168
|
-
if (classDecl) {
|
|
169
|
-
const nameProperty = classDecl.getProperty('name');
|
|
170
|
-
const descProperty = classDecl.getProperty('description');
|
|
171
|
-
let toolName = className.replace(/Tool$/, '').toLowerCase();
|
|
172
|
-
let description = '';
|
|
173
|
-
// Extract name from property if available
|
|
174
|
-
if (nameProperty && nameProperty.getInitializer()) {
|
|
175
|
-
const nameValue = nameProperty.getInitializer()?.getText();
|
|
176
|
-
if (nameValue) {
|
|
177
|
-
toolName = nameValue.replace(/['"]/g, '');
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
// Extract description from property if available
|
|
181
|
-
if (descProperty && descProperty.getInitializer()) {
|
|
182
|
-
const descValue = descProperty.getInitializer()?.getText();
|
|
183
|
-
if (descValue) {
|
|
184
|
-
description = descValue.replace(/['"]/g, '');
|
|
185
|
-
}
|
|
186
|
-
}
|
|
187
|
-
const toolInfo = {
|
|
188
|
-
name: toolName,
|
|
189
|
-
className,
|
|
190
|
-
filePath: toolFilePath,
|
|
191
|
-
description
|
|
192
|
-
};
|
|
193
|
-
return toolInfo;
|
|
194
|
-
}
|
|
195
|
-
}
|
|
196
|
-
catch (fileError) {
|
|
197
|
-
console.warn(`Warning: Could not load tool file ${toolFilePath}:`, fileError);
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return null;
|
|
202
|
-
}
|
|
203
|
-
catch (error) {
|
|
204
|
-
console.warn(`Warning: Could not extract tool info for ${newExpr.getText()}:`, error);
|
|
205
|
-
return null;
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
function resolveImportPath(moduleSpecifier, currentFilePath) {
|
|
209
|
-
if (moduleSpecifier.startsWith('./') || moduleSpecifier.startsWith('../')) {
|
|
210
|
-
// Relative import - resolve relative to current file
|
|
211
|
-
const currentDir = path.dirname(currentFilePath);
|
|
212
|
-
return path.resolve(currentDir, moduleSpecifier + '.ts');
|
|
213
|
-
}
|
|
214
|
-
else {
|
|
215
|
-
// Absolute import - assume it's in the project
|
|
216
|
-
return path.resolve(process.cwd(), 'src', moduleSpecifier + '.ts');
|
|
217
|
-
}
|
|
218
|
-
}
|
|
219
|
-
async function bundleTool(tool, distDir) {
|
|
220
|
-
writeProgress(`📦 Bundling ${tool.className}...`);
|
|
221
|
-
try {
|
|
222
|
-
const outputPath = path.join(distDir, 'tools', `${tool.className}.js`);
|
|
223
|
-
await build({
|
|
224
|
-
entryPoints: [tool.filePath],
|
|
225
|
-
bundle: true,
|
|
226
|
-
format: 'cjs',
|
|
227
|
-
platform: 'node',
|
|
228
|
-
target: 'node16',
|
|
229
|
-
outfile: outputPath,
|
|
230
|
-
external: ['lua-cli/skill', 'lua-cli/user-data-api', 'lua-cli/product-api', 'lua-cli/custom-data-api', 'zod', 'keytar', 'esbuild', 'commander', 'inquirer', 'node-fetch', 'ws', 'socket.io-client', 'ts-morph'], // Exclude lua-cli modules, zod, and native modules
|
|
231
|
-
minify: true, // Minify for smaller file sizes
|
|
232
|
-
sourcemap: false,
|
|
233
|
-
resolveExtensions: ['.ts', '.js', '.json'],
|
|
234
|
-
define: {
|
|
235
|
-
'process.env.NODE_ENV': '"production"'
|
|
236
|
-
},
|
|
237
|
-
// Ensure all other dependencies are bundled
|
|
238
|
-
packages: 'bundle',
|
|
239
|
-
// Handle different module formats
|
|
240
|
-
mainFields: ['main', 'module'],
|
|
241
|
-
conditions: ['node']
|
|
242
|
-
});
|
|
243
|
-
// Add VM-compatible wrapper
|
|
244
|
-
await wrapToolForVM(outputPath, tool);
|
|
245
|
-
}
|
|
246
|
-
catch (error) {
|
|
247
|
-
console.warn(`Warning: Failed to bundle ${tool.className}:`, error);
|
|
248
|
-
}
|
|
249
|
-
}
|
|
250
|
-
async function wrapToolForVM(outputPath, tool) {
|
|
251
|
-
const bundledCode = fs.readFileSync(outputPath, 'utf8');
|
|
252
|
-
// Create a wrapper that's compatible with the existing sandbox.ts VM system
|
|
253
|
-
// The sandbox expects: const executeFunction = ${toolCode}; module.exports = async (input) => { return await executeFunction(input); };
|
|
254
|
-
const wrappedCode = `async (input) => {
|
|
255
|
-
// Mock lua-cli/skill module for external dependencies
|
|
256
|
-
const luaCliSkill = {
|
|
257
|
-
env: function(key) {
|
|
258
|
-
if (typeof env !== 'undefined') {
|
|
259
|
-
return env(key);
|
|
260
|
-
}
|
|
261
|
-
return process.env[key] || '';
|
|
262
|
-
}
|
|
263
|
-
};
|
|
264
|
-
|
|
265
|
-
// Mock lua-cli/user-data-api module
|
|
266
|
-
const luaCliUserDataApi = {
|
|
267
|
-
user: typeof user !== 'undefined' ? user : {
|
|
268
|
-
data: {
|
|
269
|
-
get: async () => ({}),
|
|
270
|
-
update: async (data) => data,
|
|
271
|
-
create: async (data) => data
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
};
|
|
275
|
-
|
|
276
|
-
// Mock lua-cli/product-api module
|
|
277
|
-
const luaCliProductApi = {
|
|
278
|
-
product: typeof product !== 'undefined' ? product : {
|
|
279
|
-
data: {
|
|
280
|
-
get: async (page = 1, limit = 10) => ({ success: true, data: [], pagination: { currentPage: page, totalPages: 1, totalCount: 0, limit, hasNextPage: false, hasPrevPage: false, nextPage: null, prevPage: null } }),
|
|
281
|
-
update: async (data, productId) => ({ updated: true, isNew: false, product: data }),
|
|
282
|
-
create: async (data) => ({ updated: false, isNew: true, product: data }),
|
|
283
|
-
delete: async (productId) => ({ deleted: true }),
|
|
284
|
-
search: async (searchQuery) => ({ success: true, message: \`Found 0 products for "\${searchQuery}"\`, data: [] })
|
|
285
|
-
}
|
|
286
|
-
}
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
// Mock lua-cli/custom-data-api module
|
|
290
|
-
const luaCliCustomDataApi = {
|
|
291
|
-
customData: typeof customData !== 'undefined' ? customData : {
|
|
292
|
-
create: async (collectionName, data) => ({
|
|
293
|
-
id: 'mock-id-' + Date.now(),
|
|
294
|
-
data: data.data,
|
|
295
|
-
createdAt: Date.now(),
|
|
296
|
-
updatedAt: Date.now(),
|
|
297
|
-
searchText: data.searchText
|
|
298
|
-
}),
|
|
299
|
-
get: async (collectionName, filter, page = 1, limit = 10) => ({
|
|
300
|
-
data: [],
|
|
301
|
-
pagination: {
|
|
302
|
-
currentPage: page,
|
|
303
|
-
totalPages: 1,
|
|
304
|
-
totalCount: 0,
|
|
305
|
-
limit,
|
|
306
|
-
hasNextPage: false,
|
|
307
|
-
hasPrevPage: false
|
|
308
|
-
}
|
|
309
|
-
}),
|
|
310
|
-
getEntry: async (collectionName, entryId) => null,
|
|
311
|
-
update: async (collectionName, entryId, data) => ({
|
|
312
|
-
status: 'success',
|
|
313
|
-
message: 'Custom data entry updated'
|
|
314
|
-
}),
|
|
315
|
-
search: async (collectionName, searchText, limit = 10, scoreThreshold = 0.6) => ({
|
|
316
|
-
data: [],
|
|
317
|
-
count: 0
|
|
318
|
-
}),
|
|
319
|
-
delete: async (collectionName, entryId) => ({
|
|
320
|
-
status: 'success',
|
|
321
|
-
message: 'Custom data entry deleted'
|
|
322
|
-
})
|
|
323
|
-
}
|
|
324
|
-
};
|
|
325
|
-
|
|
326
|
-
// Mock zod module
|
|
327
|
-
const zodModule = (() => {
|
|
328
|
-
try {
|
|
329
|
-
if (typeof require !== 'undefined') {
|
|
330
|
-
return require('zod');
|
|
331
|
-
}
|
|
332
|
-
} catch (e) {
|
|
333
|
-
// Fallback zod implementation
|
|
334
|
-
}
|
|
335
|
-
return {
|
|
336
|
-
z: {
|
|
337
|
-
object: (schema) => ({
|
|
338
|
-
parse: (data) => data,
|
|
339
|
-
safeParse: (data) => ({ success: true, data })
|
|
340
|
-
}),
|
|
341
|
-
string: () => ({
|
|
342
|
-
parse: (data) => String(data),
|
|
343
|
-
safeParse: (data) => ({ success: true, data: String(data) })
|
|
344
|
-
}),
|
|
345
|
-
number: () => ({
|
|
346
|
-
parse: (data) => Number(data),
|
|
347
|
-
safeParse: (data) => ({ success: true, data: Number(data) })
|
|
348
|
-
}),
|
|
349
|
-
boolean: () => ({
|
|
350
|
-
parse: (data) => Boolean(data),
|
|
351
|
-
safeParse: (data) => ({ success: true, data: Boolean(data) })
|
|
352
|
-
})
|
|
353
|
-
}
|
|
354
|
-
};
|
|
355
|
-
})();
|
|
356
|
-
|
|
357
|
-
// Override require for external modules during execution
|
|
358
|
-
const originalRequire = require;
|
|
359
|
-
require = function(id) {
|
|
360
|
-
if (id === 'lua-cli/skill') {
|
|
361
|
-
return luaCliSkill;
|
|
362
|
-
}
|
|
363
|
-
if (id === 'lua-cli/user-data-api') {
|
|
364
|
-
return luaCliUserDataApi;
|
|
365
|
-
}
|
|
366
|
-
if (id === 'lua-cli/product-api') {
|
|
367
|
-
return luaCliProductApi;
|
|
368
|
-
}
|
|
369
|
-
if (id === 'lua-cli/custom-data-api') {
|
|
370
|
-
return luaCliCustomDataApi;
|
|
371
|
-
}
|
|
372
|
-
if (id === 'zod') {
|
|
373
|
-
return zodModule;
|
|
374
|
-
}
|
|
375
|
-
return originalRequire(id);
|
|
376
|
-
};
|
|
377
|
-
|
|
378
|
-
// Execute the bundled tool code
|
|
379
|
-
${bundledCode}
|
|
380
|
-
|
|
381
|
-
// Restore original require
|
|
382
|
-
require = originalRequire;
|
|
383
|
-
|
|
384
|
-
// Get the tool class from exports
|
|
385
|
-
const ToolClass = module.exports.default || module.exports.${tool.className} || module.exports;
|
|
386
|
-
|
|
387
|
-
// Create and execute the tool
|
|
388
|
-
const toolInstance = new ToolClass();
|
|
389
|
-
return await toolInstance.execute(input);
|
|
390
|
-
}`;
|
|
391
|
-
fs.writeFileSync(outputPath, wrappedCode);
|
|
392
|
-
}
|
|
393
|
-
async function bundleMainIndex(indexPath, distDir) {
|
|
394
|
-
writeProgress("📦 Bundling main index...");
|
|
395
|
-
try {
|
|
396
|
-
await build({
|
|
397
|
-
entryPoints: [indexPath],
|
|
398
|
-
bundle: true,
|
|
399
|
-
format: 'cjs',
|
|
400
|
-
platform: 'node',
|
|
401
|
-
target: 'node16',
|
|
402
|
-
outfile: path.join(distDir, 'index.js'),
|
|
403
|
-
external: ['lua-cli/skill', 'lua-cli/user-data-api', 'lua-cli/product-api', 'lua-cli/custom-data-api', 'zod', 'keytar', 'esbuild', 'commander', 'inquirer', 'node-fetch', 'ws', 'socket.io-client', 'ts-morph'], // Exclude lua-cli modules, zod, and native modules
|
|
404
|
-
minify: true, // Minify for smaller file sizes
|
|
405
|
-
sourcemap: false,
|
|
406
|
-
resolveExtensions: ['.ts', '.js', '.json'],
|
|
407
|
-
define: {
|
|
408
|
-
'process.env.NODE_ENV': '"production"'
|
|
409
|
-
},
|
|
410
|
-
packages: 'bundle',
|
|
411
|
-
mainFields: ['main', 'module'],
|
|
412
|
-
conditions: ['node']
|
|
413
|
-
});
|
|
414
|
-
}
|
|
415
|
-
catch (error) {
|
|
416
|
-
console.warn("Warning: Failed to bundle main index:", error);
|
|
417
|
-
}
|
|
418
|
-
}
|
|
419
|
-
async function extractExecuteCode(tool, project) {
|
|
420
|
-
try {
|
|
421
|
-
const toolSourceFile = project.getSourceFile(tool.filePath);
|
|
422
|
-
if (!toolSourceFile) {
|
|
423
|
-
console.warn(`Warning: Could not find source file for ${tool.className}`);
|
|
424
|
-
return;
|
|
425
|
-
}
|
|
426
|
-
const classDecl = toolSourceFile.getClass(tool.className);
|
|
427
|
-
if (!classDecl) {
|
|
428
|
-
console.warn(`Warning: Could not find class ${tool.className} in ${tool.filePath}`);
|
|
429
|
-
return;
|
|
430
|
-
}
|
|
431
|
-
// Extract the execute method
|
|
432
|
-
const executeMethod = classDecl.getMethod('execute');
|
|
433
|
-
if (!executeMethod) {
|
|
434
|
-
console.warn(`Warning: Could not find execute method in ${tool.className}`);
|
|
435
|
-
return;
|
|
436
|
-
}
|
|
437
|
-
// Get the execute method body
|
|
438
|
-
const executeBody = executeMethod.getBodyText();
|
|
439
|
-
if (!executeBody) {
|
|
440
|
-
console.warn(`Warning: Execute method has no body in ${tool.className}`);
|
|
441
|
-
return;
|
|
442
|
-
}
|
|
443
|
-
// Read the bundled tool file to get the self-contained code
|
|
444
|
-
const bundledPath = path.join(process.cwd(), 'dist', 'tools', `${tool.className}.js`);
|
|
445
|
-
if (fs.existsSync(bundledPath)) {
|
|
446
|
-
const bundledCode = fs.readFileSync(bundledPath, 'utf8');
|
|
447
|
-
// Extract just the tool execution function from the bundled code
|
|
448
|
-
// The bundled code contains the VM wrapper, we need to extract the core functionality
|
|
449
|
-
const executeFunction = createExecuteFunction(bundledCode, tool);
|
|
450
|
-
tool.executeCode = executeFunction;
|
|
451
|
-
}
|
|
452
|
-
// Extract input schema from zod definition using proper library
|
|
453
|
-
const inputSchemaProperty = classDecl.getProperty('inputSchema');
|
|
454
|
-
if (inputSchemaProperty && inputSchemaProperty.getInitializer()) {
|
|
455
|
-
const initializer = inputSchemaProperty.getInitializer();
|
|
456
|
-
if (initializer) {
|
|
457
|
-
try {
|
|
458
|
-
// Evaluate the Zod schema to get the actual schema object
|
|
459
|
-
const zodSchemaCode = initializer.getText();
|
|
460
|
-
tool.inputSchema = await evaluateZodSchemaToJsonSchema(zodSchemaCode);
|
|
461
|
-
}
|
|
462
|
-
catch (error) {
|
|
463
|
-
console.warn(`Warning: Could not parse Zod schema for ${tool.className}:`, error);
|
|
464
|
-
tool.inputSchema = { type: "object" };
|
|
465
|
-
}
|
|
466
|
-
}
|
|
467
|
-
}
|
|
468
|
-
if (!tool.inputSchema) {
|
|
469
|
-
tool.inputSchema = { type: "object" };
|
|
470
|
-
}
|
|
471
|
-
}
|
|
472
|
-
catch (error) {
|
|
473
|
-
console.warn(`Warning: Could not extract execute code for ${tool.className}:`, error);
|
|
474
|
-
}
|
|
475
|
-
}
|
|
476
|
-
function createExecuteFunction(bundledCode, tool) {
|
|
477
|
-
// The bundled code is already wrapped for VM execution by wrapToolForVM
|
|
478
|
-
// Just return it directly since it's already an async function
|
|
479
|
-
return bundledCode;
|
|
480
|
-
}
|
|
481
|
-
async function evaluateZodSchemaToJsonSchema(zodSchemaCode) {
|
|
482
|
-
try {
|
|
483
|
-
// Import zod and zod-to-json-schema dynamically
|
|
484
|
-
const { z } = await import('zod');
|
|
485
|
-
const { zodToJsonSchema } = await import('zod-to-json-schema');
|
|
486
|
-
// Create a safe evaluation context using Function constructor
|
|
487
|
-
const evalFunction = new Function('z', `return ${zodSchemaCode}`);
|
|
488
|
-
const zodSchema = evalFunction(z);
|
|
489
|
-
// Convert to JSON Schema using the library
|
|
490
|
-
const jsonSchema = zodToJsonSchema(zodSchema, 'schema');
|
|
491
|
-
// Extract just the core schema, removing JSON Schema references and definitions
|
|
492
|
-
if (jsonSchema.$ref && jsonSchema.definitions && jsonSchema.definitions.schema) {
|
|
493
|
-
// Return just the schema definition without the wrapper
|
|
494
|
-
return jsonSchema.definitions.schema;
|
|
495
|
-
}
|
|
496
|
-
// Remove the top-level $schema and title properties that we don't need
|
|
497
|
-
const { $schema, title, definitions, $ref, ...cleanSchema } = jsonSchema;
|
|
498
|
-
return cleanSchema;
|
|
499
|
-
}
|
|
500
|
-
catch (error) {
|
|
501
|
-
console.warn('Warning: Could not evaluate Zod schema, falling back to basic parsing:', error);
|
|
502
|
-
// Fallback to basic parsing for simple cases
|
|
503
|
-
if (zodSchemaCode.includes('z.object({')) {
|
|
504
|
-
return { type: 'object' };
|
|
505
|
-
}
|
|
506
|
-
if (zodSchemaCode.includes('z.string()'))
|
|
507
|
-
return { type: 'string' };
|
|
508
|
-
if (zodSchemaCode.includes('z.number()'))
|
|
509
|
-
return { type: 'number' };
|
|
510
|
-
if (zodSchemaCode.includes('z.boolean()'))
|
|
511
|
-
return { type: 'boolean' };
|
|
512
|
-
return { type: 'object' };
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
async function createDeploymentData(tools, distDir) {
|
|
516
|
-
const config = readSkillConfig();
|
|
517
|
-
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
518
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
519
|
-
const deploymentData = {
|
|
520
|
-
name: config?.skill?.name || packageJson.name || "lua-skill",
|
|
521
|
-
version: config?.skill?.version || packageJson.version || "1.0.0",
|
|
522
|
-
skillId: config?.skill?.skillId || "",
|
|
523
|
-
description: config?.skill?.description || packageJson.description || "",
|
|
524
|
-
context: config?.skill?.context || "",
|
|
525
|
-
tools: tools.map(tool => ({
|
|
526
|
-
name: tool.name,
|
|
527
|
-
className: tool.className,
|
|
528
|
-
description: tool.description || "",
|
|
529
|
-
filePath: `tools/${tool.className}.js`
|
|
530
|
-
}))
|
|
531
|
-
};
|
|
532
|
-
fs.writeFileSync(path.join(distDir, 'deployment.json'), JSON.stringify(deploymentData, null, 2));
|
|
533
|
-
}
|
|
534
|
-
async function createLegacyDeploymentData(tools, luaDir, indexFile) {
|
|
535
|
-
const config = readSkillConfig();
|
|
536
|
-
const packageJsonPath = path.join(process.cwd(), "package.json");
|
|
537
|
-
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, "utf8"));
|
|
538
|
-
// Extract skills metadata from index.ts
|
|
539
|
-
const skillsMetadata = extractSkillsMetadata(indexFile);
|
|
540
|
-
// Group tools by skill based on addTools calls
|
|
541
|
-
const skillToTools = new Map();
|
|
542
|
-
// Find addTools calls to associate tools with skills
|
|
543
|
-
indexFile.forEachDescendant((node) => {
|
|
544
|
-
if (Node.isCallExpression(node)) {
|
|
545
|
-
const expression = node.getExpression();
|
|
546
|
-
if (Node.isPropertyAccessExpression(expression) && expression.getName() === 'addTools') {
|
|
547
|
-
const object = expression.getExpression();
|
|
548
|
-
const objectName = object.getText();
|
|
549
|
-
// Get the tools array
|
|
550
|
-
const args = node.getArguments();
|
|
551
|
-
if (args.length > 0 && Node.isArrayLiteralExpression(args[0])) {
|
|
552
|
-
const toolsArray = args[0];
|
|
553
|
-
const toolNames = toolsArray.getElements().map((element) => {
|
|
554
|
-
if (Node.isNewExpression(element)) {
|
|
555
|
-
return element.getExpression().getText();
|
|
556
|
-
}
|
|
557
|
-
return '';
|
|
558
|
-
}).filter(name => name);
|
|
559
|
-
skillToTools.set(objectName, toolNames);
|
|
560
|
-
}
|
|
561
|
-
}
|
|
562
|
-
}
|
|
563
|
-
});
|
|
564
|
-
// Create skills array with their associated tools
|
|
565
|
-
const skillsArray = skillsMetadata.map(skillMeta => {
|
|
566
|
-
let skillTools = [];
|
|
567
|
-
// First, check for tools from constructor
|
|
568
|
-
if (skillMeta.constructorTools && skillMeta.constructorTools.length > 0) {
|
|
569
|
-
skillTools = tools.filter(tool => {
|
|
570
|
-
return skillMeta.constructorTools.includes(tool.className) ||
|
|
571
|
-
skillMeta.constructorTools.includes(tool.name);
|
|
572
|
-
});
|
|
573
|
-
}
|
|
574
|
-
else {
|
|
575
|
-
// Find tools for this skill by matching variable names from addTools calls
|
|
576
|
-
for (const [varName, toolNames] of skillToTools.entries()) {
|
|
577
|
-
// Simple heuristic: if variable name contains skill name, associate tools
|
|
578
|
-
if (varName.toLowerCase().includes(skillMeta.name.toLowerCase().replace('-skill', '')) ||
|
|
579
|
-
varName.toLowerCase().includes(skillMeta.name.toLowerCase())) {
|
|
580
|
-
skillTools = tools.filter(tool => {
|
|
581
|
-
return toolNames.includes(tool.className) || toolNames.includes(tool.name);
|
|
582
|
-
});
|
|
583
|
-
break;
|
|
584
|
-
}
|
|
585
|
-
}
|
|
586
|
-
}
|
|
587
|
-
return {
|
|
588
|
-
name: skillMeta.name,
|
|
589
|
-
version: skillMeta.version,
|
|
590
|
-
description: skillMeta.description,
|
|
591
|
-
context: skillMeta.context,
|
|
592
|
-
tools: skillTools.map(tool => ({
|
|
593
|
-
name: tool.name,
|
|
594
|
-
description: tool.description || "",
|
|
595
|
-
inputSchema: tool.inputSchema || { type: "object" },
|
|
596
|
-
execute: compressCode(tool.executeCode || "")
|
|
597
|
-
}))
|
|
598
|
-
};
|
|
599
|
-
});
|
|
600
|
-
// Match skills from code with skills in YAML and create missing ones
|
|
601
|
-
const updatedSkillsArray = await ensureSkillsExistInYaml(skillsArray, config);
|
|
602
|
-
const deployData = {
|
|
603
|
-
skills: updatedSkillsArray
|
|
604
|
-
};
|
|
605
|
-
// Write legacy deploy.json to .lua directory
|
|
606
|
-
fs.writeFileSync(path.join(luaDir, "deploy.json"), JSON.stringify(deployData, null, 2));
|
|
607
|
-
// Write individual tool files to .lua directory (uncompressed)
|
|
608
|
-
for (const tool of tools) {
|
|
609
|
-
if (tool.executeCode) {
|
|
610
|
-
const toolFilePath = path.join(luaDir, `${tool.name}.js`);
|
|
611
|
-
fs.writeFileSync(toolFilePath, tool.executeCode);
|
|
612
|
-
}
|
|
613
|
-
}
|
|
614
|
-
}
|
|
615
|
-
function extractSkillsMetadata(indexFile) {
|
|
616
|
-
const skills = [];
|
|
617
|
-
// Find all LuaSkill constructor calls
|
|
618
|
-
indexFile.forEachDescendant((node) => {
|
|
619
|
-
if (Node.isNewExpression(node)) {
|
|
620
|
-
const expression = node.getExpression();
|
|
621
|
-
if (expression.getText() === 'LuaSkill') {
|
|
622
|
-
const args = node.getArguments();
|
|
623
|
-
if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {
|
|
624
|
-
const configObj = args[0];
|
|
625
|
-
let skillName = '';
|
|
626
|
-
let skillVersion = '';
|
|
627
|
-
let description = '';
|
|
628
|
-
let context = '';
|
|
629
|
-
let constructorTools = [];
|
|
630
|
-
// Extract properties
|
|
631
|
-
configObj.getProperties().forEach((prop) => {
|
|
632
|
-
if (Node.isPropertyAssignment(prop)) {
|
|
633
|
-
const name = prop.getName();
|
|
634
|
-
const value = prop.getInitializer();
|
|
635
|
-
if (name === 'name' && value) {
|
|
636
|
-
skillName = value.getText().replace(/['"]/g, '');
|
|
637
|
-
}
|
|
638
|
-
else if (name === 'version' && value) {
|
|
639
|
-
skillVersion = value.getText().replace(/['"]/g, '');
|
|
640
|
-
}
|
|
641
|
-
else if (name === 'description' && value) {
|
|
642
|
-
description = value.getText().replace(/['"]/g, '');
|
|
643
|
-
}
|
|
644
|
-
else if (name === 'context' && value) {
|
|
645
|
-
context = value.getText().replace(/['"]/g, '');
|
|
646
|
-
}
|
|
647
|
-
else if (name === 'tools' && value && Node.isArrayLiteralExpression(value)) {
|
|
648
|
-
// Extract tools from constructor array
|
|
649
|
-
const toolsArray = value;
|
|
650
|
-
constructorTools = toolsArray.getElements().map((element) => {
|
|
651
|
-
if (Node.isNewExpression(element)) {
|
|
652
|
-
return element.getExpression().getText();
|
|
653
|
-
}
|
|
654
|
-
return '';
|
|
655
|
-
}).filter(name => name);
|
|
656
|
-
}
|
|
657
|
-
}
|
|
658
|
-
});
|
|
659
|
-
if (skillName) {
|
|
660
|
-
skills.push({
|
|
661
|
-
name: skillName,
|
|
662
|
-
version: skillVersion || '1.0.0',
|
|
663
|
-
description,
|
|
664
|
-
context,
|
|
665
|
-
constructorTools
|
|
666
|
-
});
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
}
|
|
670
|
-
}
|
|
671
|
-
});
|
|
672
|
-
return skills;
|
|
673
|
-
}
|
|
674
|
-
async function ensureSkillsExistInYaml(skillsArray, config) {
|
|
675
|
-
const updatedSkillsArray = [];
|
|
676
|
-
let yamlUpdated = false;
|
|
677
|
-
// Get existing skills from YAML
|
|
678
|
-
const existingSkills = config?.skills || [];
|
|
679
|
-
const existingSkillsMap = new Map();
|
|
680
|
-
// Create map of existing skills
|
|
681
|
-
existingSkills.forEach((skill) => {
|
|
682
|
-
existingSkillsMap.set(skill.name, skill);
|
|
683
|
-
});
|
|
684
|
-
// Process each detected skill
|
|
685
|
-
for (const skill of skillsArray) {
|
|
686
|
-
const existingSkill = existingSkillsMap.get(skill.name);
|
|
687
|
-
if (existingSkill && existingSkill.skillId && existingSkill.skillId !== '') {
|
|
688
|
-
// Skill exists with valid skillId - use it
|
|
689
|
-
// console.log(`Using existing skillId for ${skill.name}: ${existingSkill.skillId}`);
|
|
690
|
-
updatedSkillsArray.push({
|
|
691
|
-
...skill,
|
|
692
|
-
skillId: existingSkill.skillId
|
|
693
|
-
});
|
|
694
|
-
}
|
|
695
|
-
else {
|
|
696
|
-
// Skill doesn't exist or missing skillId - create it via API
|
|
697
|
-
// console.log(`Creating new skill: ${skill.name}`);
|
|
698
|
-
try {
|
|
699
|
-
// Get API key and agent ID for skill creation
|
|
700
|
-
const apiKey = await loadApiKey();
|
|
701
|
-
if (!apiKey) {
|
|
702
|
-
throw new Error("No API key found. Run 'lua auth configure' first.");
|
|
703
|
-
}
|
|
704
|
-
const agentId = config?.agent?.agentId;
|
|
705
|
-
if (!agentId) {
|
|
706
|
-
throw new Error("No agent ID found in lua.skill.yaml. Run 'lua init' first.");
|
|
707
|
-
}
|
|
708
|
-
// Call create skill API
|
|
709
|
-
console.log(`Calling create skill API for: ${skill.name}`);
|
|
710
|
-
const skillPayload = {
|
|
711
|
-
name: skill.name,
|
|
712
|
-
description: skill.description || `A Lua skill for ${skill.name}`,
|
|
713
|
-
context: skill.context || ''
|
|
714
|
-
};
|
|
715
|
-
const result = await ApiService.Skill.createSkill(apiKey, agentId, skillPayload);
|
|
716
|
-
// console.log(`Create skill API response:`, result);
|
|
717
|
-
if (result.success && result.data && result.data.id) {
|
|
718
|
-
const newSkillId = result.data.id; // API returns 'id', not 'skillId'
|
|
719
|
-
// console.log(`✅ Created skill ${skill.name} with ID: ${newSkillId}`);
|
|
720
|
-
updatedSkillsArray.push({
|
|
721
|
-
...skill,
|
|
722
|
-
skillId: newSkillId
|
|
723
|
-
});
|
|
724
|
-
// Update YAML with new skill
|
|
725
|
-
if (!existingSkill) {
|
|
726
|
-
existingSkills.push({
|
|
727
|
-
name: skill.name || '',
|
|
728
|
-
version: skill.version || '1.0.0',
|
|
729
|
-
skillId: newSkillId
|
|
730
|
-
});
|
|
731
|
-
yamlUpdated = true;
|
|
732
|
-
}
|
|
733
|
-
else {
|
|
734
|
-
// Update existing skill with new skillId
|
|
735
|
-
existingSkill.skillId = newSkillId;
|
|
736
|
-
yamlUpdated = true;
|
|
737
|
-
}
|
|
738
|
-
}
|
|
739
|
-
else {
|
|
740
|
-
console.error(`❌ Failed to create skill ${skill.name}:`, result.error);
|
|
741
|
-
throw new Error(result.error?.message || 'Failed to create skill - no ID returned from API');
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
catch (error) {
|
|
745
|
-
console.error(`❌ Failed to create skill ${skill.name}:`, error);
|
|
746
|
-
throw error; // Don't use temp IDs, let the process fail properly
|
|
747
|
-
}
|
|
748
|
-
}
|
|
749
|
-
}
|
|
750
|
-
// Update YAML file if needed
|
|
751
|
-
if (yamlUpdated) {
|
|
752
|
-
await updateYamlWithSkills(existingSkills, config);
|
|
753
|
-
}
|
|
754
|
-
return updatedSkillsArray;
|
|
755
|
-
}
|
|
756
|
-
async function updateYamlWithSkills(skills, config) {
|
|
757
|
-
// Clean skills array to ensure no undefined values
|
|
758
|
-
const cleanedSkills = skills.map(skill => ({
|
|
759
|
-
name: skill.name || '',
|
|
760
|
-
version: skill.version || '1.0.0',
|
|
761
|
-
skillId: skill.skillId || '' // Ensure skillId is never undefined
|
|
762
|
-
}));
|
|
763
|
-
// Update config with cleaned skills array
|
|
764
|
-
const updatedConfig = {
|
|
765
|
-
...config,
|
|
766
|
-
skills: cleanedSkills
|
|
767
|
-
};
|
|
768
|
-
// Write updated YAML
|
|
769
|
-
const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
770
|
-
const yamlContent = yaml.dump(updatedConfig, {
|
|
771
|
-
indent: 2,
|
|
772
|
-
lineWidth: -1,
|
|
773
|
-
noRefs: true,
|
|
774
|
-
replacer: (key, value) => {
|
|
775
|
-
// Replace undefined values with empty strings
|
|
776
|
-
return value === undefined ? '' : value;
|
|
777
|
-
}
|
|
58
|
+
/**
|
|
59
|
+
* Prepares output directories for compilation.
|
|
60
|
+
* Removes old directories and creates fresh ones for dist and .lua outputs.
|
|
61
|
+
*
|
|
62
|
+
* @returns Object containing the dist and lua directory paths
|
|
63
|
+
*/
|
|
64
|
+
function prepareOutputDirectories() {
|
|
65
|
+
const distDir = path.join(process.cwd(), COMPILE_DIRS.DIST);
|
|
66
|
+
const luaDir = path.join(process.cwd(), COMPILE_DIRS.LUA);
|
|
67
|
+
// Clean up old directories
|
|
68
|
+
if (fs.existsSync(distDir)) {
|
|
69
|
+
fs.rmSync(distDir, { recursive: true, force: true });
|
|
70
|
+
}
|
|
71
|
+
if (fs.existsSync(luaDir)) {
|
|
72
|
+
fs.rmSync(luaDir, { recursive: true, force: true });
|
|
73
|
+
}
|
|
74
|
+
// Create fresh directory structures
|
|
75
|
+
fs.mkdirSync(distDir, { recursive: true });
|
|
76
|
+
fs.mkdirSync(path.join(distDir, COMPILE_DIRS.TOOLS), { recursive: true });
|
|
77
|
+
fs.mkdirSync(luaDir, { recursive: true });
|
|
78
|
+
return { distDir, luaDir };
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Creates and configures a TypeScript project for AST analysis.
|
|
82
|
+
*
|
|
83
|
+
* @returns Configured ts-morph Project instance
|
|
84
|
+
*/
|
|
85
|
+
function createTypeScriptProject() {
|
|
86
|
+
return new Project({
|
|
87
|
+
tsConfigFilePath: path.join(process.cwd(), COMPILE_FILES.TSCONFIG_JSON),
|
|
778
88
|
});
|
|
779
|
-
fs.writeFileSync(yamlPath, yamlContent);
|
|
780
|
-
console.log('Updated lua.skill.yaml with new skills');
|
|
781
89
|
}
|