lua-cli 2.2.8-alpha.2 → 2.3.0-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/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 +941 -17
- package/dist/web/app.js +174 -22
- package/dist/web/index.html +7 -1
- package/package.json +13 -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
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Authentication Flow Utilities
|
|
3
|
+
* Handles different authentication methods (API key and email OTP)
|
|
4
|
+
*/
|
|
5
|
+
import inquirer from "inquirer";
|
|
6
|
+
import { saveApiKey, checkApiKey, requestEmailOTP, verifyOTPAndGetToken, generateApiKey } from "../services/auth.js";
|
|
7
|
+
import { clearPromptLines, writeProgress, writeSuccess } from "./cli.js";
|
|
8
|
+
/**
|
|
9
|
+
* Configuration for OTP verification
|
|
10
|
+
*/
|
|
11
|
+
const OTP_CONFIG = {
|
|
12
|
+
MAX_ATTEMPTS: 3,
|
|
13
|
+
OTP_LENGTH: 6,
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Handles API key authentication flow.
|
|
17
|
+
* Prompts for API key, validates it, and saves it securely.
|
|
18
|
+
*
|
|
19
|
+
* @returns Promise that resolves when authentication is complete
|
|
20
|
+
* @throws Error if API key is invalid
|
|
21
|
+
*/
|
|
22
|
+
export async function handleApiKeyAuth() {
|
|
23
|
+
const answers = await inquirer.prompt([
|
|
24
|
+
{
|
|
25
|
+
type: "password",
|
|
26
|
+
name: "apiKey",
|
|
27
|
+
message: "Enter your API key",
|
|
28
|
+
mask: "*",
|
|
29
|
+
},
|
|
30
|
+
]);
|
|
31
|
+
const data = await checkApiKey(answers.apiKey);
|
|
32
|
+
if (!data) {
|
|
33
|
+
throw new Error("Invalid API key");
|
|
34
|
+
}
|
|
35
|
+
await saveApiKey(answers.apiKey);
|
|
36
|
+
writeSuccess("✅ API key saved securely.");
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Handles email authentication flow with OTP verification.
|
|
40
|
+
* Sends OTP to email, verifies it, generates API key, and saves it.
|
|
41
|
+
*
|
|
42
|
+
* @returns Promise that resolves when authentication is complete
|
|
43
|
+
* @throws Error if OTP sending fails, verification fails, or API key generation fails
|
|
44
|
+
*/
|
|
45
|
+
export async function handleEmailAuth() {
|
|
46
|
+
// Step 1: Collect email
|
|
47
|
+
const { email } = await inquirer.prompt([
|
|
48
|
+
{
|
|
49
|
+
type: "input",
|
|
50
|
+
name: "email",
|
|
51
|
+
message: "Enter your email address:",
|
|
52
|
+
validate: (input) => {
|
|
53
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
54
|
+
return emailRegex.test(input) || "Please enter a valid email address";
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
]);
|
|
58
|
+
clearPromptLines(2);
|
|
59
|
+
// Step 2: Send OTP
|
|
60
|
+
writeProgress("📧 Sending OTP to your email...");
|
|
61
|
+
const otpSent = await requestEmailOTP(email);
|
|
62
|
+
if (!otpSent) {
|
|
63
|
+
throw new Error("Failed to send OTP. Please try again.");
|
|
64
|
+
}
|
|
65
|
+
writeProgress("✅ OTP sent successfully!");
|
|
66
|
+
// Step 3: Verify OTP with retry logic
|
|
67
|
+
const signInToken = await verifyOTPWithRetry(email);
|
|
68
|
+
// Step 4: Generate API key
|
|
69
|
+
writeProgress("🔑 Generating API key...");
|
|
70
|
+
const apiKey = await generateApiKey(signInToken);
|
|
71
|
+
if (!apiKey) {
|
|
72
|
+
throw new Error("Failed to generate API key. Please try again.");
|
|
73
|
+
}
|
|
74
|
+
// Step 5: Save API key
|
|
75
|
+
await saveApiKey(apiKey);
|
|
76
|
+
writeSuccess("✅ API key generated and saved securely.");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Verifies OTP with retry logic.
|
|
80
|
+
* Allows multiple attempts to enter the correct OTP.
|
|
81
|
+
*
|
|
82
|
+
* @param email - Email address for OTP verification
|
|
83
|
+
* @returns Sign-in token from successful verification
|
|
84
|
+
* @throws Error if maximum attempts are exceeded
|
|
85
|
+
*/
|
|
86
|
+
async function verifyOTPWithRetry(email) {
|
|
87
|
+
let otpVerified = false;
|
|
88
|
+
let attempts = 0;
|
|
89
|
+
let signInToken = null;
|
|
90
|
+
while (!otpVerified && attempts < OTP_CONFIG.MAX_ATTEMPTS) {
|
|
91
|
+
const { pin } = await inquirer.prompt([
|
|
92
|
+
{
|
|
93
|
+
type: "input",
|
|
94
|
+
name: "pin",
|
|
95
|
+
message: "Enter the OTP code:",
|
|
96
|
+
validate: (input) => {
|
|
97
|
+
return input.length === OTP_CONFIG.OTP_LENGTH || `OTP must be ${OTP_CONFIG.OTP_LENGTH} digits`;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
]);
|
|
101
|
+
clearPromptLines(2);
|
|
102
|
+
writeProgress("🔐 Verifying OTP...");
|
|
103
|
+
signInToken = await verifyOTPAndGetToken(email, pin);
|
|
104
|
+
if (signInToken) {
|
|
105
|
+
otpVerified = true;
|
|
106
|
+
writeProgress("✅ OTP verified successfully!");
|
|
107
|
+
}
|
|
108
|
+
else {
|
|
109
|
+
attempts++;
|
|
110
|
+
if (attempts < OTP_CONFIG.MAX_ATTEMPTS) {
|
|
111
|
+
console.log(`❌ Invalid OTP. ${OTP_CONFIG.MAX_ATTEMPTS - attempts} attempts remaining.`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
throw new Error("Invalid OTP. Maximum attempts reached. Please try again later.");
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!signInToken) {
|
|
119
|
+
throw new Error("OTP verification failed");
|
|
120
|
+
}
|
|
121
|
+
return signInToken;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* Prompts user to choose authentication method.
|
|
125
|
+
*
|
|
126
|
+
* @returns Selected authentication method ('api-key' or 'email')
|
|
127
|
+
*/
|
|
128
|
+
export async function promptAuthMethod() {
|
|
129
|
+
const { authMethod } = await inquirer.prompt([
|
|
130
|
+
{
|
|
131
|
+
type: "list",
|
|
132
|
+
name: "authMethod",
|
|
133
|
+
message: "Choose authentication method:",
|
|
134
|
+
choices: [
|
|
135
|
+
{ name: "API Key", value: "api-key" },
|
|
136
|
+
{ name: "Email", value: "email" }
|
|
137
|
+
]
|
|
138
|
+
}
|
|
139
|
+
]);
|
|
140
|
+
return authMethod;
|
|
141
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundling Utilities
|
|
3
|
+
* Handles esbuild bundling of tools and main index
|
|
4
|
+
*/
|
|
5
|
+
import { ToolInfo } from '../interfaces/compile.js';
|
|
6
|
+
import { Project } from "ts-morph";
|
|
7
|
+
/**
|
|
8
|
+
* Bundles a tool's TypeScript code into a standalone JavaScript file.
|
|
9
|
+
* Uses esbuild to:
|
|
10
|
+
* - Bundle all dependencies (except external packages)
|
|
11
|
+
* - Minify code for production
|
|
12
|
+
* - Wrap for VM execution
|
|
13
|
+
*
|
|
14
|
+
* @param tool - The tool to bundle
|
|
15
|
+
* @param distDir - The distribution directory for output
|
|
16
|
+
*/
|
|
17
|
+
export declare function bundleTool(tool: ToolInfo, distDir: string): Promise<void>;
|
|
18
|
+
/**
|
|
19
|
+
* Bundles the main index.ts file into a standalone JavaScript file.
|
|
20
|
+
* This creates the entry point for the skill.
|
|
21
|
+
*
|
|
22
|
+
* @param indexPath - Path to the index.ts file
|
|
23
|
+
* @param distDir - The distribution directory for output
|
|
24
|
+
*/
|
|
25
|
+
export declare function bundleMainIndex(indexPath: string, distDir: string): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* Extracts execute code and input schema from a tool.
|
|
28
|
+
* This function:
|
|
29
|
+
* 1. Reads the bundled tool code
|
|
30
|
+
* 2. Extracts the execute function
|
|
31
|
+
* 3. Converts Zod schema to JSON Schema format
|
|
32
|
+
*
|
|
33
|
+
* @param tool - The tool to extract metadata from (mutated with executeCode and inputSchema)
|
|
34
|
+
* @param project - The ts-morph Project instance for AST analysis
|
|
35
|
+
*/
|
|
36
|
+
export declare function extractExecuteCode(tool: ToolInfo, project: Project): Promise<void>;
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bundling Utilities
|
|
3
|
+
* Handles esbuild bundling of tools and main index
|
|
4
|
+
*/
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { build } from "esbuild";
|
|
8
|
+
import { writeProgress } from "./cli.js";
|
|
9
|
+
import { COMPILE_DIRS, COMPILE_FILES, ESBUILD_TOOL_CONFIG, ESBUILD_INDEX_CONFIG, DEFAULT_INPUT_SCHEMA, } from '../config/compile.constants.js';
|
|
10
|
+
import { wrapToolForVM, createExecuteFunction, evaluateZodSchemaToJsonSchema, } from './compile.js';
|
|
11
|
+
/**
|
|
12
|
+
* Bundles a tool's TypeScript code into a standalone JavaScript file.
|
|
13
|
+
* Uses esbuild to:
|
|
14
|
+
* - Bundle all dependencies (except external packages)
|
|
15
|
+
* - Minify code for production
|
|
16
|
+
* - Wrap for VM execution
|
|
17
|
+
*
|
|
18
|
+
* @param tool - The tool to bundle
|
|
19
|
+
* @param distDir - The distribution directory for output
|
|
20
|
+
*/
|
|
21
|
+
export async function bundleTool(tool, distDir) {
|
|
22
|
+
writeProgress(`📦 Bundling ${tool.className}...`);
|
|
23
|
+
try {
|
|
24
|
+
const outputPath = path.join(distDir, COMPILE_DIRS.TOOLS, `${tool.className}.js`);
|
|
25
|
+
await build({
|
|
26
|
+
...ESBUILD_TOOL_CONFIG,
|
|
27
|
+
entryPoints: [tool.filePath],
|
|
28
|
+
outfile: outputPath,
|
|
29
|
+
});
|
|
30
|
+
// Wrap the bundled code for VM execution environment
|
|
31
|
+
await wrapToolForVM(outputPath, tool);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
console.warn(`Warning: Failed to bundle ${tool.className}:`, error);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Bundles the main index.ts file into a standalone JavaScript file.
|
|
39
|
+
* This creates the entry point for the skill.
|
|
40
|
+
*
|
|
41
|
+
* @param indexPath - Path to the index.ts file
|
|
42
|
+
* @param distDir - The distribution directory for output
|
|
43
|
+
*/
|
|
44
|
+
export async function bundleMainIndex(indexPath, distDir) {
|
|
45
|
+
writeProgress("📦 Bundling main index...");
|
|
46
|
+
try {
|
|
47
|
+
await build({
|
|
48
|
+
...ESBUILD_INDEX_CONFIG,
|
|
49
|
+
entryPoints: [indexPath],
|
|
50
|
+
outfile: path.join(distDir, COMPILE_FILES.INDEX_JS),
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
catch (error) {
|
|
54
|
+
console.warn("Warning: Failed to bundle main index:", error);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Extracts execute code and input schema from a tool.
|
|
59
|
+
* This function:
|
|
60
|
+
* 1. Reads the bundled tool code
|
|
61
|
+
* 2. Extracts the execute function
|
|
62
|
+
* 3. Converts Zod schema to JSON Schema format
|
|
63
|
+
*
|
|
64
|
+
* @param tool - The tool to extract metadata from (mutated with executeCode and inputSchema)
|
|
65
|
+
* @param project - The ts-morph Project instance for AST analysis
|
|
66
|
+
*/
|
|
67
|
+
export async function extractExecuteCode(tool, project) {
|
|
68
|
+
try {
|
|
69
|
+
const toolSourceFile = project.getSourceFile(tool.filePath);
|
|
70
|
+
if (!toolSourceFile) {
|
|
71
|
+
console.warn(`Warning: Could not find source file for ${tool.className}`);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
74
|
+
const classDecl = toolSourceFile.getClass(tool.className);
|
|
75
|
+
if (!classDecl) {
|
|
76
|
+
console.warn(`Warning: Could not find class ${tool.className} in ${tool.filePath}`);
|
|
77
|
+
return;
|
|
78
|
+
}
|
|
79
|
+
// Verify execute method exists
|
|
80
|
+
const executeMethod = classDecl.getMethod('execute');
|
|
81
|
+
if (!executeMethod) {
|
|
82
|
+
console.warn(`Warning: Could not find execute method in ${tool.className}`);
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
const executeBody = executeMethod.getBodyText();
|
|
86
|
+
if (!executeBody) {
|
|
87
|
+
console.warn(`Warning: Execute method has no body in ${tool.className}`);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
// Extract execute code from bundled file
|
|
91
|
+
tool.executeCode = extractExecuteCodeFromBundledFile(tool);
|
|
92
|
+
// Extract and convert input schema
|
|
93
|
+
tool.inputSchema = await extractInputSchema(classDecl, tool);
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.warn(`Warning: Could not extract execute code for ${tool.className}:`, error);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Extracts execute code from the bundled tool file.
|
|
101
|
+
*
|
|
102
|
+
* @param tool - The tool whose bundled code to read
|
|
103
|
+
* @returns The execute function code or undefined if not found
|
|
104
|
+
*/
|
|
105
|
+
function extractExecuteCodeFromBundledFile(tool) {
|
|
106
|
+
const bundledPath = path.join(process.cwd(), COMPILE_DIRS.DIST, COMPILE_DIRS.TOOLS, `${tool.className}.js`);
|
|
107
|
+
if (fs.existsSync(bundledPath)) {
|
|
108
|
+
const bundledCode = fs.readFileSync(bundledPath, 'utf8');
|
|
109
|
+
return createExecuteFunction(bundledCode, tool);
|
|
110
|
+
}
|
|
111
|
+
return undefined;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Extracts and converts the input schema from a tool class.
|
|
115
|
+
* Converts Zod schemas to JSON Schema format.
|
|
116
|
+
*
|
|
117
|
+
* @param classDecl - The tool class declaration from ts-morph
|
|
118
|
+
* @param tool - The tool being analyzed (for logging)
|
|
119
|
+
* @returns The JSON Schema object or default schema
|
|
120
|
+
*/
|
|
121
|
+
async function extractInputSchema(classDecl, tool) {
|
|
122
|
+
const inputSchemaProperty = classDecl.getProperty('inputSchema');
|
|
123
|
+
if (inputSchemaProperty && inputSchemaProperty.getInitializer()) {
|
|
124
|
+
const initializer = inputSchemaProperty.getInitializer();
|
|
125
|
+
if (initializer) {
|
|
126
|
+
try {
|
|
127
|
+
const zodSchemaCode = initializer.getText();
|
|
128
|
+
return await evaluateZodSchemaToJsonSchema(zodSchemaCode);
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
console.warn(`Warning: Could not parse Zod schema for ${tool.className}:`, error);
|
|
132
|
+
return DEFAULT_INPUT_SCHEMA;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
return DEFAULT_INPUT_SCHEMA;
|
|
137
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for compile command
|
|
3
|
+
*/
|
|
4
|
+
import { Project } from "ts-morph";
|
|
5
|
+
import { ToolInfo } from "../interfaces/compile.js";
|
|
6
|
+
/**
|
|
7
|
+
* Compresses code using gzip and returns base64 encoded string
|
|
8
|
+
*/
|
|
9
|
+
export declare function compressCode(code: string): string;
|
|
10
|
+
/**
|
|
11
|
+
* Finds the index.ts file in the project
|
|
12
|
+
*/
|
|
13
|
+
export declare function findIndexFile(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Resolves import path from module specifier
|
|
16
|
+
*/
|
|
17
|
+
export declare function resolveImportPath(moduleSpecifier: string, currentFilePath: string): string;
|
|
18
|
+
/**
|
|
19
|
+
* Creates execute function wrapper from bundled code
|
|
20
|
+
*/
|
|
21
|
+
export declare function createExecuteFunction(bundledCode: string, tool: ToolInfo): string;
|
|
22
|
+
/**
|
|
23
|
+
* Evaluates Zod schema code and converts it to JSON Schema
|
|
24
|
+
*/
|
|
25
|
+
export declare function evaluateZodSchemaToJsonSchema(zodSchemaCode: string): Promise<any>;
|
|
26
|
+
/**
|
|
27
|
+
* Wraps bundled tool code for VM execution
|
|
28
|
+
*/
|
|
29
|
+
export declare function wrapToolForVM(outputPath: string, tool: ToolInfo): Promise<void>;
|
|
30
|
+
/**
|
|
31
|
+
* Extracts tool information from a new expression in the AST
|
|
32
|
+
*/
|
|
33
|
+
export declare function extractToolFromNewExpressionSync(newExpr: any, project: Project): ToolInfo | null;
|
|
34
|
+
/**
|
|
35
|
+
* Extracts skills metadata from index file
|
|
36
|
+
*/
|
|
37
|
+
export declare function extractSkillsMetadata(indexFile: any): any[];
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for compile command
|
|
3
|
+
*/
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import { gzipSync } from "zlib";
|
|
7
|
+
import { Node } from "ts-morph";
|
|
8
|
+
/**
|
|
9
|
+
* Compresses code using gzip and returns base64 encoded string
|
|
10
|
+
*/
|
|
11
|
+
export function compressCode(code) {
|
|
12
|
+
const compressed = gzipSync(code);
|
|
13
|
+
return compressed.toString('base64');
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Finds the index.ts file in the project
|
|
17
|
+
*/
|
|
18
|
+
export function findIndexFile() {
|
|
19
|
+
// Check for index.ts in current directory
|
|
20
|
+
let indexPath = path.join(process.cwd(), "index.ts");
|
|
21
|
+
if (fs.existsSync(indexPath)) {
|
|
22
|
+
return indexPath;
|
|
23
|
+
}
|
|
24
|
+
// Check for index.ts in src directory
|
|
25
|
+
indexPath = path.join(process.cwd(), "src", "index.ts");
|
|
26
|
+
if (fs.existsSync(indexPath)) {
|
|
27
|
+
return indexPath;
|
|
28
|
+
}
|
|
29
|
+
throw new Error("index.ts not found in current directory or src/ directory");
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Resolves import path from module specifier
|
|
33
|
+
*/
|
|
34
|
+
export function resolveImportPath(moduleSpecifier, currentFilePath) {
|
|
35
|
+
if (moduleSpecifier.startsWith('./') || moduleSpecifier.startsWith('../')) {
|
|
36
|
+
// Relative import - resolve relative to current file
|
|
37
|
+
const currentDir = path.dirname(currentFilePath);
|
|
38
|
+
return path.resolve(currentDir, moduleSpecifier + '.ts');
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
// Absolute import - assume it's in the project
|
|
42
|
+
return path.resolve(process.cwd(), 'src', moduleSpecifier + '.ts');
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Creates execute function wrapper from bundled code
|
|
47
|
+
*/
|
|
48
|
+
export function createExecuteFunction(bundledCode, tool) {
|
|
49
|
+
// The bundled code is already wrapped for VM execution by wrapToolForVM
|
|
50
|
+
// Just return it directly since it's already an async function
|
|
51
|
+
return bundledCode;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Evaluates Zod schema code and converts it to JSON Schema
|
|
55
|
+
*/
|
|
56
|
+
export async function evaluateZodSchemaToJsonSchema(zodSchemaCode) {
|
|
57
|
+
try {
|
|
58
|
+
// Import zod and zod-to-json-schema dynamically
|
|
59
|
+
const { z } = await import('zod');
|
|
60
|
+
const { zodToJsonSchema } = await import('zod-to-json-schema');
|
|
61
|
+
// Create a safe evaluation context using Function constructor
|
|
62
|
+
const evalFunction = new Function('z', `return ${zodSchemaCode}`);
|
|
63
|
+
const zodSchema = evalFunction(z);
|
|
64
|
+
// Convert to JSON Schema using the library
|
|
65
|
+
const jsonSchema = zodToJsonSchema(zodSchema, 'schema');
|
|
66
|
+
// Extract just the core schema, removing JSON Schema references and definitions
|
|
67
|
+
if (jsonSchema.$ref && jsonSchema.definitions && jsonSchema.definitions.schema) {
|
|
68
|
+
// Return just the schema definition without the wrapper
|
|
69
|
+
return jsonSchema.definitions.schema;
|
|
70
|
+
}
|
|
71
|
+
// Remove the top-level $schema and title properties that we don't need
|
|
72
|
+
const { $schema, title, definitions, $ref, ...cleanSchema } = jsonSchema;
|
|
73
|
+
return cleanSchema;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
console.warn('Warning: Could not evaluate Zod schema, falling back to basic parsing:', error);
|
|
77
|
+
// Fallback to basic parsing for simple cases
|
|
78
|
+
if (zodSchemaCode.includes('z.object({')) {
|
|
79
|
+
return { type: 'object' };
|
|
80
|
+
}
|
|
81
|
+
if (zodSchemaCode.includes('z.string()'))
|
|
82
|
+
return { type: 'string' };
|
|
83
|
+
if (zodSchemaCode.includes('z.number()'))
|
|
84
|
+
return { type: 'number' };
|
|
85
|
+
if (zodSchemaCode.includes('z.boolean()'))
|
|
86
|
+
return { type: 'boolean' };
|
|
87
|
+
return { type: 'object' };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Wraps bundled tool code for VM execution
|
|
92
|
+
*/
|
|
93
|
+
export async function wrapToolForVM(outputPath, tool) {
|
|
94
|
+
const bundledCode = fs.readFileSync(outputPath, 'utf8');
|
|
95
|
+
// Create a wrapper that's compatible with the existing sandbox.ts VM system
|
|
96
|
+
// The sandbox expects: const executeFunction = ${toolCode}; module.exports = async (input) => { return await executeFunction(input); };
|
|
97
|
+
const wrappedCode = `async (input) => {
|
|
98
|
+
|
|
99
|
+
// Execute the bundled tool code
|
|
100
|
+
${bundledCode}
|
|
101
|
+
|
|
102
|
+
// Get the tool class from exports
|
|
103
|
+
const ToolClass = module.exports.default || module.exports.${tool.className} || module.exports;
|
|
104
|
+
|
|
105
|
+
// Create and execute the tool
|
|
106
|
+
const toolInstance = new ToolClass();
|
|
107
|
+
return await toolInstance.execute(input);
|
|
108
|
+
}`;
|
|
109
|
+
fs.writeFileSync(outputPath, wrappedCode);
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Extracts tool information from a new expression in the AST
|
|
113
|
+
*/
|
|
114
|
+
export function extractToolFromNewExpressionSync(newExpr, project) {
|
|
115
|
+
try {
|
|
116
|
+
const expression = newExpr.getExpression();
|
|
117
|
+
const className = expression.getText();
|
|
118
|
+
// Find the import declaration for this class
|
|
119
|
+
const sourceFile = newExpr.getSourceFile();
|
|
120
|
+
const imports = sourceFile.getImportDeclarations();
|
|
121
|
+
for (const importDecl of imports) {
|
|
122
|
+
const namedImports = importDecl.getNamedImports();
|
|
123
|
+
const defaultImport = importDecl.getDefaultImport();
|
|
124
|
+
let toolFilePath = null;
|
|
125
|
+
// Check named imports
|
|
126
|
+
for (const namedImport of namedImports) {
|
|
127
|
+
if (namedImport.getName() === className) {
|
|
128
|
+
toolFilePath = resolveImportPath(importDecl.getModuleSpecifierValue(), sourceFile.getFilePath());
|
|
129
|
+
break;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
// Check default import
|
|
133
|
+
if (!toolFilePath && defaultImport && defaultImport.getText() === className) {
|
|
134
|
+
toolFilePath = resolveImportPath(importDecl.getModuleSpecifierValue(), sourceFile.getFilePath());
|
|
135
|
+
}
|
|
136
|
+
if (toolFilePath && fs.existsSync(toolFilePath)) {
|
|
137
|
+
// Extract tool metadata from the class file
|
|
138
|
+
try {
|
|
139
|
+
const toolSourceFile = project.addSourceFileAtPath(toolFilePath);
|
|
140
|
+
const classDecl = toolSourceFile.getClass(className);
|
|
141
|
+
if (classDecl) {
|
|
142
|
+
const nameProperty = classDecl.getProperty('name');
|
|
143
|
+
const descProperty = classDecl.getProperty('description');
|
|
144
|
+
let toolName = className.replace(/Tool$/, '').toLowerCase();
|
|
145
|
+
let description = '';
|
|
146
|
+
// Extract name from property if available
|
|
147
|
+
if (nameProperty && nameProperty.getInitializer()) {
|
|
148
|
+
const nameValue = nameProperty.getInitializer()?.getText();
|
|
149
|
+
if (nameValue) {
|
|
150
|
+
toolName = nameValue.replace(/['"]/g, '');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
// Extract description from property if available
|
|
154
|
+
if (descProperty && descProperty.getInitializer()) {
|
|
155
|
+
const descValue = descProperty.getInitializer()?.getText();
|
|
156
|
+
if (descValue) {
|
|
157
|
+
description = descValue.replace(/['"]/g, '');
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
const toolInfo = {
|
|
161
|
+
name: toolName,
|
|
162
|
+
className,
|
|
163
|
+
filePath: toolFilePath,
|
|
164
|
+
description
|
|
165
|
+
};
|
|
166
|
+
return toolInfo;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
catch (fileError) {
|
|
170
|
+
console.warn(`Warning: Could not load tool file ${toolFilePath}:`, fileError);
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
return null;
|
|
175
|
+
}
|
|
176
|
+
catch (error) {
|
|
177
|
+
console.warn(`Warning: Could not extract tool info for ${newExpr.getText()}:`, error);
|
|
178
|
+
return null;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
/**
|
|
182
|
+
* Extracts skills metadata from index file
|
|
183
|
+
*/
|
|
184
|
+
export function extractSkillsMetadata(indexFile) {
|
|
185
|
+
const skills = [];
|
|
186
|
+
// Find all LuaSkill constructor calls
|
|
187
|
+
indexFile.forEachDescendant((node) => {
|
|
188
|
+
if (Node.isNewExpression(node)) {
|
|
189
|
+
const expression = node.getExpression();
|
|
190
|
+
if (expression.getText() === 'LuaSkill') {
|
|
191
|
+
const args = node.getArguments();
|
|
192
|
+
if (args.length > 0 && Node.isObjectLiteralExpression(args[0])) {
|
|
193
|
+
const configObj = args[0];
|
|
194
|
+
let skillName = '';
|
|
195
|
+
let skillVersion = '';
|
|
196
|
+
let description = '';
|
|
197
|
+
let context = '';
|
|
198
|
+
let constructorTools = [];
|
|
199
|
+
// Extract properties
|
|
200
|
+
configObj.getProperties().forEach((prop) => {
|
|
201
|
+
if (Node.isPropertyAssignment(prop)) {
|
|
202
|
+
const name = prop.getName();
|
|
203
|
+
const value = prop.getInitializer();
|
|
204
|
+
if (name === 'name' && value) {
|
|
205
|
+
skillName = value.getText().replace(/['"]/g, '');
|
|
206
|
+
}
|
|
207
|
+
else if (name === 'version' && value) {
|
|
208
|
+
skillVersion = value.getText().replace(/['"]/g, '');
|
|
209
|
+
}
|
|
210
|
+
else if (name === 'description' && value) {
|
|
211
|
+
description = value.getText().replace(/['"]/g, '');
|
|
212
|
+
}
|
|
213
|
+
else if (name === 'context' && value) {
|
|
214
|
+
context = value.getText().replace(/['"]/g, '');
|
|
215
|
+
}
|
|
216
|
+
else if (name === 'tools' && value && Node.isArrayLiteralExpression(value)) {
|
|
217
|
+
// Extract tools from constructor array
|
|
218
|
+
const toolsArray = value;
|
|
219
|
+
constructorTools = toolsArray.getElements().map((element) => {
|
|
220
|
+
if (Node.isNewExpression(element)) {
|
|
221
|
+
return element.getExpression().getText();
|
|
222
|
+
}
|
|
223
|
+
return '';
|
|
224
|
+
}).filter(name => name);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
});
|
|
228
|
+
if (skillName) {
|
|
229
|
+
skills.push({
|
|
230
|
+
name: skillName,
|
|
231
|
+
version: skillVersion || '1.0.0',
|
|
232
|
+
description,
|
|
233
|
+
context,
|
|
234
|
+
constructorTools
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
return skills;
|
|
242
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy API Utilities
|
|
3
|
+
* Handles API calls for deployment operations
|
|
4
|
+
*/
|
|
5
|
+
import { VersionsResponse, PublishResponse } from '../interfaces/deploy.js';
|
|
6
|
+
/**
|
|
7
|
+
* Fetches available versions for a skill.
|
|
8
|
+
*
|
|
9
|
+
* @param apiKey - User's API key
|
|
10
|
+
* @param agentId - Agent ID
|
|
11
|
+
* @param skillId - Skill ID
|
|
12
|
+
* @returns Versions response containing array of versions
|
|
13
|
+
* @throws Error if API call fails
|
|
14
|
+
*/
|
|
15
|
+
export declare function fetchVersions(apiKey: string, agentId: string, skillId: string): Promise<VersionsResponse>;
|
|
16
|
+
/**
|
|
17
|
+
* Publishes a specific version to production.
|
|
18
|
+
*
|
|
19
|
+
* @param apiKey - User's API key
|
|
20
|
+
* @param agentId - Agent ID
|
|
21
|
+
* @param skillId - Skill ID
|
|
22
|
+
* @param version - Version to publish
|
|
23
|
+
* @returns Publish response with deployment details
|
|
24
|
+
* @throws Error if API call fails
|
|
25
|
+
*/
|
|
26
|
+
export declare function publishVersion(apiKey: string, agentId: string, skillId: string, version: string): Promise<PublishResponse>;
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Deploy API Utilities
|
|
3
|
+
* Handles API calls for deployment operations
|
|
4
|
+
*/
|
|
5
|
+
import SkillApi from '../api/skills.api.service.js';
|
|
6
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
7
|
+
/**
|
|
8
|
+
* Fetches available versions for a skill.
|
|
9
|
+
*
|
|
10
|
+
* @param apiKey - User's API key
|
|
11
|
+
* @param agentId - Agent ID
|
|
12
|
+
* @param skillId - Skill ID
|
|
13
|
+
* @returns Versions response containing array of versions
|
|
14
|
+
* @throws Error if API call fails
|
|
15
|
+
*/
|
|
16
|
+
export async function fetchVersions(apiKey, agentId, skillId) {
|
|
17
|
+
try {
|
|
18
|
+
const skillApi = new SkillApi(BASE_URLS.API, apiKey, agentId);
|
|
19
|
+
const response = await skillApi.getSkillVersions(skillId);
|
|
20
|
+
if (!response.success) {
|
|
21
|
+
throw new Error(`Failed to fetch versions: ${response.error?.message || 'Unknown error'}`);
|
|
22
|
+
}
|
|
23
|
+
return response.data;
|
|
24
|
+
}
|
|
25
|
+
catch (error) {
|
|
26
|
+
console.error("❌ Error fetching versions:", error);
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Publishes a specific version to production.
|
|
32
|
+
*
|
|
33
|
+
* @param apiKey - User's API key
|
|
34
|
+
* @param agentId - Agent ID
|
|
35
|
+
* @param skillId - Skill ID
|
|
36
|
+
* @param version - Version to publish
|
|
37
|
+
* @returns Publish response with deployment details
|
|
38
|
+
* @throws Error if API call fails
|
|
39
|
+
*/
|
|
40
|
+
export async function publishVersion(apiKey, agentId, skillId, version) {
|
|
41
|
+
try {
|
|
42
|
+
const skillApi = new SkillApi(BASE_URLS.API, apiKey, agentId);
|
|
43
|
+
const response = await skillApi.publishSkillVersion(skillId, version);
|
|
44
|
+
if (!response.success) {
|
|
45
|
+
throw new Error(`Failed to publish version: ${response.error?.message || 'Unknown error'}`);
|
|
46
|
+
}
|
|
47
|
+
return response.data;
|
|
48
|
+
}
|
|
49
|
+
catch (error) {
|
|
50
|
+
console.error("❌ Error publishing version:", error);
|
|
51
|
+
throw error;
|
|
52
|
+
}
|
|
53
|
+
}
|