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/services/api.js
CHANGED
|
@@ -197,6 +197,33 @@ export class ToolApi {
|
|
|
197
197
|
});
|
|
198
198
|
}
|
|
199
199
|
}
|
|
200
|
+
// User Data API calls
|
|
201
|
+
export class UserDataApi {
|
|
202
|
+
static async getUserData(apiKey, agentId) {
|
|
203
|
+
const response = await httpClient.get(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
|
|
204
|
+
Authorization: `Bearer ${apiKey}`,
|
|
205
|
+
});
|
|
206
|
+
return response;
|
|
207
|
+
}
|
|
208
|
+
static async createUserData(apiKey, agentId, data) {
|
|
209
|
+
const response = await httpClient.put(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
|
|
210
|
+
Authorization: `Bearer ${apiKey}`,
|
|
211
|
+
});
|
|
212
|
+
return response.data.data;
|
|
213
|
+
}
|
|
214
|
+
static async updateUserData(apiKey, agentId, data) {
|
|
215
|
+
const response = await httpClient.put(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
|
|
216
|
+
Authorization: `Bearer ${apiKey}`,
|
|
217
|
+
});
|
|
218
|
+
return response.data.data;
|
|
219
|
+
}
|
|
220
|
+
static async deleteUserData(apiKey, agentId) {
|
|
221
|
+
const response = await httpClient.delete(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
|
|
222
|
+
Authorization: `Bearer ${apiKey}`,
|
|
223
|
+
});
|
|
224
|
+
return response;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
200
227
|
/**
|
|
201
228
|
* Main API service that exports all API classes
|
|
202
229
|
*/
|
package/dist/skill.d.ts
CHANGED
|
@@ -1,6 +1,20 @@
|
|
|
1
1
|
import { ZodType } from "zod";
|
|
2
2
|
import { LuaTool } from "./types/index.js";
|
|
3
3
|
export { LuaTool };
|
|
4
|
+
/**
|
|
5
|
+
* Safe environment variable access function
|
|
6
|
+
* Gets injected at runtime with skill-specific environment variables
|
|
7
|
+
*
|
|
8
|
+
* @param key - The environment variable key to retrieve
|
|
9
|
+
* @returns The environment variable value or undefined if not found
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* ```typescript
|
|
13
|
+
* const baseUrl = env('BASE_URL');
|
|
14
|
+
* const apiKey = env('API_KEY');
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare const env: (key: string) => string | undefined;
|
|
4
18
|
export interface LuaSkillConfig {
|
|
5
19
|
description: string;
|
|
6
20
|
context: string;
|
|
@@ -25,6 +39,7 @@ export declare class LuaSkill {
|
|
|
25
39
|
* ```
|
|
26
40
|
*/
|
|
27
41
|
constructor(config: LuaSkillConfig);
|
|
28
|
-
addTool<TInput extends ZodType
|
|
42
|
+
addTool<TInput extends ZodType>(tool: LuaTool<TInput>): void;
|
|
43
|
+
addTools(tools: LuaTool<any>[]): void;
|
|
29
44
|
run(input: Record<string, any>): Promise<any>;
|
|
30
45
|
}
|
package/dist/skill.js
CHANGED
|
@@ -1,4 +1,46 @@
|
|
|
1
1
|
import { assertValidToolName } from "./types/index.js";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import yaml from "js-yaml";
|
|
5
|
+
/**
|
|
6
|
+
* Safe environment variable access function
|
|
7
|
+
* Gets injected at runtime with skill-specific environment variables
|
|
8
|
+
*
|
|
9
|
+
* @param key - The environment variable key to retrieve
|
|
10
|
+
* @returns The environment variable value or undefined if not found
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```typescript
|
|
14
|
+
* const baseUrl = env('BASE_URL');
|
|
15
|
+
* const apiKey = env('API_KEY');
|
|
16
|
+
* ```
|
|
17
|
+
*/
|
|
18
|
+
export const env = (key) => {
|
|
19
|
+
// Try to load environment variables from lua.skill.yaml
|
|
20
|
+
try {
|
|
21
|
+
// Look for lua.skill.yaml in current directory and parent directories
|
|
22
|
+
let currentDir = process.cwd();
|
|
23
|
+
let yamlPath = null;
|
|
24
|
+
while (currentDir !== path.dirname(currentDir)) {
|
|
25
|
+
const potentialPath = path.join(currentDir, 'lua.skill.yaml');
|
|
26
|
+
if (fs.existsSync(potentialPath)) {
|
|
27
|
+
yamlPath = potentialPath;
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
currentDir = path.dirname(currentDir);
|
|
31
|
+
}
|
|
32
|
+
if (yamlPath) {
|
|
33
|
+
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
34
|
+
const config = yaml.load(yamlContent);
|
|
35
|
+
return config?.skill?.env?.[key];
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
// If we can't load the YAML, fall back to undefined
|
|
40
|
+
console.warn(`Warning: Could not load environment variables from lua.skill.yaml: ${error}`);
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
};
|
|
2
44
|
export class LuaSkill {
|
|
3
45
|
/**
|
|
4
46
|
* Creates a new LuaSkill instance
|
|
@@ -25,6 +67,13 @@ export class LuaSkill {
|
|
|
25
67
|
assertValidToolName(tool.name);
|
|
26
68
|
this.tools.push(tool);
|
|
27
69
|
}
|
|
70
|
+
addTools(tools) {
|
|
71
|
+
// Validate all tool names before adding them
|
|
72
|
+
for (const tool of tools) {
|
|
73
|
+
assertValidToolName(tool.name);
|
|
74
|
+
}
|
|
75
|
+
this.tools.push(...tools);
|
|
76
|
+
}
|
|
28
77
|
async run(input) {
|
|
29
78
|
const tool = this.tools.find(tool => tool.name === input.tool);
|
|
30
79
|
if (!tool) {
|
package/dist/types/index.d.ts
CHANGED
|
@@ -62,11 +62,10 @@ export declare function validateToolName(name: string): boolean;
|
|
|
62
62
|
* Throws an error if the tool name is invalid
|
|
63
63
|
*/
|
|
64
64
|
export declare function assertValidToolName(name: string): void;
|
|
65
|
-
export interface LuaTool<TInput extends ZodType = ZodType
|
|
65
|
+
export interface LuaTool<TInput extends ZodType = ZodType> {
|
|
66
66
|
name: string;
|
|
67
67
|
description: string;
|
|
68
68
|
inputSchema: TInput;
|
|
69
|
-
outputSchema: TOutput;
|
|
70
69
|
execute: (input: any) => Promise<any>;
|
|
71
70
|
}
|
|
72
71
|
export interface LuaSkillConfig {
|
|
@@ -78,6 +77,7 @@ export declare class LuaSkill {
|
|
|
78
77
|
private readonly description;
|
|
79
78
|
private readonly context;
|
|
80
79
|
constructor(config: LuaSkillConfig);
|
|
81
|
-
addTool<TInput extends ZodType
|
|
80
|
+
addTool<TInput extends ZodType>(tool: LuaTool<TInput>): void;
|
|
81
|
+
addTools(tools: LuaTool<any>[]): void;
|
|
82
82
|
run(input: Record<string, any>): Promise<any>;
|
|
83
83
|
}
|
package/dist/user-data-api.d.ts
CHANGED
|
@@ -3,14 +3,8 @@
|
|
|
3
3
|
* Provides methods to interact with user data stored in the Lua system
|
|
4
4
|
*/
|
|
5
5
|
export declare class UserDataAPI {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
constructor(apiKey?: string, agentId?: string);
|
|
9
|
-
/**
|
|
10
|
-
* Initialize the API with credentials
|
|
11
|
-
* If not provided, will attempt to load from stored configuration
|
|
12
|
-
*/
|
|
13
|
-
initialize(): Promise<void>;
|
|
6
|
+
userData: any;
|
|
7
|
+
constructor();
|
|
14
8
|
/**
|
|
15
9
|
* Get user data for the current agent
|
|
16
10
|
* @returns Promise<UserDataResponse>
|
|
@@ -43,10 +37,3 @@ export declare class UserDataAPI {
|
|
|
43
37
|
export declare const user: {
|
|
44
38
|
data: UserDataAPI;
|
|
45
39
|
};
|
|
46
|
-
/**
|
|
47
|
-
* Create a new UserDataAPI instance with custom credentials
|
|
48
|
-
* @param apiKey - Optional API key
|
|
49
|
-
* @param agentId - Optional agent ID
|
|
50
|
-
* @returns UserDataAPI instance
|
|
51
|
-
*/
|
|
52
|
-
export declare function createUserDataAPI(apiKey?: string, agentId?: string): UserDataAPI;
|
package/dist/user-data-api.js
CHANGED
|
@@ -1,60 +1,17 @@
|
|
|
1
|
-
import { readSkillConfig } from './utils/files.js';
|
|
2
|
-
import { loadApiKey } from './services/auth.js';
|
|
3
1
|
/**
|
|
4
2
|
* User Data API for Lua CLI projects
|
|
5
3
|
* Provides methods to interact with user data stored in the Lua system
|
|
6
4
|
*/
|
|
7
5
|
export class UserDataAPI {
|
|
8
|
-
constructor(
|
|
9
|
-
this.
|
|
10
|
-
this.agentId = agentId || '';
|
|
11
|
-
}
|
|
12
|
-
/**
|
|
13
|
-
* Initialize the API with credentials
|
|
14
|
-
* If not provided, will attempt to load from stored configuration
|
|
15
|
-
*/
|
|
16
|
-
async initialize() {
|
|
17
|
-
if (!this.apiKey) {
|
|
18
|
-
this.apiKey = await loadApiKey() || '';
|
|
19
|
-
}
|
|
20
|
-
if (!this.agentId) {
|
|
21
|
-
const config = await readSkillConfig();
|
|
22
|
-
this.agentId = config.agent.agentId;
|
|
23
|
-
}
|
|
24
|
-
if (!this.apiKey || !this.agentId) {
|
|
25
|
-
throw new Error('API key and agent ID are required. Please run "lua auth configure" first.');
|
|
26
|
-
}
|
|
6
|
+
constructor() {
|
|
7
|
+
this.userData = {};
|
|
27
8
|
}
|
|
28
9
|
/**
|
|
29
10
|
* Get user data for the current agent
|
|
30
11
|
* @returns Promise<UserDataResponse>
|
|
31
12
|
*/
|
|
32
13
|
async get() {
|
|
33
|
-
|
|
34
|
-
const response = await fetch(`http://localhost:3022/developer/user/data/agent/${this.agentId}`, {
|
|
35
|
-
method: 'GET',
|
|
36
|
-
headers: {
|
|
37
|
-
'accept': '*/*',
|
|
38
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
if (!response.ok) {
|
|
42
|
-
// Try alternative authentication method if Bearer fails
|
|
43
|
-
if (response.status === 401) {
|
|
44
|
-
const altResponse = await fetch(`http://localhost:3022/developer/user/data/agent/${this.agentId}`, {
|
|
45
|
-
method: 'GET',
|
|
46
|
-
headers: {
|
|
47
|
-
'accept': '*/*',
|
|
48
|
-
'Authorization': this.apiKey
|
|
49
|
-
}
|
|
50
|
-
});
|
|
51
|
-
if (altResponse.ok) {
|
|
52
|
-
return await altResponse.json();
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
throw new Error(`Failed to get user data: ${response.status} ${response.statusText}`);
|
|
56
|
-
}
|
|
57
|
-
return await response.json();
|
|
14
|
+
return { success: true, data: this.userData };
|
|
58
15
|
}
|
|
59
16
|
/**
|
|
60
17
|
* Create or update user data for the current agent
|
|
@@ -62,35 +19,8 @@ export class UserDataAPI {
|
|
|
62
19
|
* @returns Promise<UserDataResponse>
|
|
63
20
|
*/
|
|
64
21
|
async create(data) {
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
method: 'PUT',
|
|
68
|
-
headers: {
|
|
69
|
-
'accept': '*/*',
|
|
70
|
-
'Authorization': `Bearer ${this.apiKey}`,
|
|
71
|
-
'Content-Type': 'application/json'
|
|
72
|
-
},
|
|
73
|
-
body: JSON.stringify(data)
|
|
74
|
-
});
|
|
75
|
-
if (!response.ok) {
|
|
76
|
-
// Try alternative authentication method if Bearer fails
|
|
77
|
-
if (response.status === 401) {
|
|
78
|
-
const altResponse = await fetch(`http://localhost:3022/developer/user/data/agent/${this.agentId}`, {
|
|
79
|
-
method: 'PUT',
|
|
80
|
-
headers: {
|
|
81
|
-
'accept': '*/*',
|
|
82
|
-
'Authorization': this.apiKey,
|
|
83
|
-
'Content-Type': 'application/json'
|
|
84
|
-
},
|
|
85
|
-
body: JSON.stringify(data)
|
|
86
|
-
});
|
|
87
|
-
if (altResponse.ok) {
|
|
88
|
-
return await altResponse.json();
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
throw new Error(`Failed to create user data: ${response.status} ${response.statusText}`);
|
|
92
|
-
}
|
|
93
|
-
return await response.json();
|
|
22
|
+
this.userData = data;
|
|
23
|
+
return { success: true, data: this.userData };
|
|
94
24
|
}
|
|
95
25
|
/**
|
|
96
26
|
* Update existing user data for the current agent
|
|
@@ -99,38 +29,16 @@ export class UserDataAPI {
|
|
|
99
29
|
*/
|
|
100
30
|
async update(data) {
|
|
101
31
|
// Update is the same as create for this API
|
|
102
|
-
|
|
32
|
+
this.userData = { ...this.userData, ...data };
|
|
33
|
+
return { success: true, data: this.userData };
|
|
103
34
|
}
|
|
104
35
|
/**
|
|
105
36
|
* Clear all user data for the current agent
|
|
106
37
|
* @returns Promise<{success: boolean}>
|
|
107
38
|
*/
|
|
108
39
|
async clear() {
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
method: 'DELETE',
|
|
112
|
-
headers: {
|
|
113
|
-
'accept': '*/*',
|
|
114
|
-
'Authorization': `Bearer ${this.apiKey}`
|
|
115
|
-
}
|
|
116
|
-
});
|
|
117
|
-
if (!response.ok) {
|
|
118
|
-
// Try alternative authentication method if Bearer fails
|
|
119
|
-
if (response.status === 401) {
|
|
120
|
-
const altResponse = await fetch(`http://localhost:3022/developer/user/data/agent/${this.agentId}`, {
|
|
121
|
-
method: 'DELETE',
|
|
122
|
-
headers: {
|
|
123
|
-
'accept': '*/*',
|
|
124
|
-
'Authorization': this.apiKey
|
|
125
|
-
}
|
|
126
|
-
});
|
|
127
|
-
if (altResponse.ok) {
|
|
128
|
-
return await altResponse.json();
|
|
129
|
-
}
|
|
130
|
-
}
|
|
131
|
-
throw new Error(`Failed to clear user data: ${response.status} ${response.statusText}`);
|
|
132
|
-
}
|
|
133
|
-
return await response.json();
|
|
40
|
+
this.userData = {};
|
|
41
|
+
return { success: true };
|
|
134
42
|
}
|
|
135
43
|
}
|
|
136
44
|
/**
|
|
@@ -140,12 +48,3 @@ export class UserDataAPI {
|
|
|
140
48
|
export const user = {
|
|
141
49
|
data: new UserDataAPI()
|
|
142
50
|
};
|
|
143
|
-
/**
|
|
144
|
-
* Create a new UserDataAPI instance with custom credentials
|
|
145
|
-
* @param apiKey - Optional API key
|
|
146
|
-
* @param agentId - Optional agent ID
|
|
147
|
-
* @returns UserDataAPI instance
|
|
148
|
-
*/
|
|
149
|
-
export function createUserDataAPI(apiKey, agentId) {
|
|
150
|
-
return new UserDataAPI(apiKey, agentId);
|
|
151
|
-
}
|
package/dist/utils/files.js
CHANGED
|
@@ -27,10 +27,30 @@ export function copyTemplateFiles(templateDir, targetDir) {
|
|
|
27
27
|
function updatePackageJson(srcPath, destPath) {
|
|
28
28
|
// Read the template package.json
|
|
29
29
|
const templatePackageJson = JSON.parse(fs.readFileSync(srcPath, 'utf8'));
|
|
30
|
-
// Get the current CLI version from the
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
// Get the current CLI version from the CLI's own package.json
|
|
31
|
+
// We need to find the CLI's package.json, not the current working directory's
|
|
32
|
+
let currentCliVersion = '1.3.2-alpha.0'; // Default fallback version
|
|
33
|
+
try {
|
|
34
|
+
// Try to find the CLI's package.json by looking for it in common locations
|
|
35
|
+
const possiblePaths = [
|
|
36
|
+
path.join(__dirname, '..', '..', 'package.json'), // From dist/utils/
|
|
37
|
+
path.join(process.cwd(), 'package.json'), // Current directory (fallback)
|
|
38
|
+
path.join(process.env.HOME || '', '.npm-global', 'lib', 'node_modules', 'lua-cli', 'package.json'), // Global install
|
|
39
|
+
];
|
|
40
|
+
for (const packagePath of possiblePaths) {
|
|
41
|
+
if (fs.existsSync(packagePath)) {
|
|
42
|
+
const mainPackageJson = JSON.parse(fs.readFileSync(packagePath, 'utf8'));
|
|
43
|
+
if (mainPackageJson.name === 'lua-cli') {
|
|
44
|
+
currentCliVersion = mainPackageJson.version;
|
|
45
|
+
break;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
// If we can't read any package.json, use the fallback version
|
|
52
|
+
console.log(`Using fallback CLI version: ${currentCliVersion}`);
|
|
53
|
+
}
|
|
34
54
|
// Update the lua-cli dependency version
|
|
35
55
|
if (templatePackageJson.dependencies && templatePackageJson.dependencies['lua-cli']) {
|
|
36
56
|
templatePackageJson.dependencies['lua-cli'] = `^${currentCliVersion}`;
|
|
@@ -50,7 +70,15 @@ ${personaSection}${welcomeMessageSection}
|
|
|
50
70
|
skill:
|
|
51
71
|
name: "${skillName}"
|
|
52
72
|
version: "0.0.1"
|
|
53
|
-
${skillIdSection}
|
|
73
|
+
${skillIdSection} env:
|
|
74
|
+
# Example environment variables - customize these for your skill
|
|
75
|
+
API_URL: "https://api.example.com"
|
|
76
|
+
API_KEY: "your-api-key-here"
|
|
77
|
+
DEBUG_MODE: "false"
|
|
78
|
+
MAX_RETRIES: "3"
|
|
79
|
+
TIMEOUT_MS: "5000"
|
|
80
|
+
# Add your own environment variables below
|
|
81
|
+
# CUSTOM_VAR: "custom-value"`;
|
|
54
82
|
fs.writeFileSync("lua.skill.yaml", yamlContent);
|
|
55
83
|
}
|
|
56
84
|
export function readSkillYaml() {
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
export interface SandboxOptions {
|
|
2
|
+
apiKey: string;
|
|
3
|
+
agentId: string;
|
|
4
|
+
customConsole?: any;
|
|
5
|
+
broadcastLog?: (logData: any) => void;
|
|
6
|
+
}
|
|
7
|
+
export interface ExecuteToolOptions extends SandboxOptions {
|
|
8
|
+
toolCode: string;
|
|
9
|
+
inputs: any;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Creates a VM sandbox context with all necessary globals and utilities
|
|
13
|
+
*/
|
|
14
|
+
export declare function createSandbox(options: SandboxOptions): {
|
|
15
|
+
require: NodeJS.Require;
|
|
16
|
+
console: any;
|
|
17
|
+
Buffer: BufferConstructor;
|
|
18
|
+
setTimeout: typeof setTimeout;
|
|
19
|
+
setInterval: typeof setInterval;
|
|
20
|
+
clearTimeout: typeof clearTimeout;
|
|
21
|
+
clearInterval: typeof clearInterval;
|
|
22
|
+
process: NodeJS.Process;
|
|
23
|
+
global: typeof globalThis;
|
|
24
|
+
__dirname: string;
|
|
25
|
+
__filename: string;
|
|
26
|
+
module: {
|
|
27
|
+
exports: {};
|
|
28
|
+
};
|
|
29
|
+
exports: {};
|
|
30
|
+
fetch: typeof fetch;
|
|
31
|
+
URLSearchParams: {
|
|
32
|
+
new (init?: string[][] | Record<string, string> | string | URLSearchParams): URLSearchParams;
|
|
33
|
+
prototype: URLSearchParams;
|
|
34
|
+
};
|
|
35
|
+
URL: {
|
|
36
|
+
new (url: string | URL, base?: string | URL): URL;
|
|
37
|
+
prototype: URL;
|
|
38
|
+
canParse(url: string | URL, base?: string | URL): boolean;
|
|
39
|
+
createObjectURL(obj: Blob | MediaSource): string;
|
|
40
|
+
parse(url: string | URL, base?: string | URL): URL | null;
|
|
41
|
+
revokeObjectURL(url: string): void;
|
|
42
|
+
};
|
|
43
|
+
Headers: {
|
|
44
|
+
new (init?: HeadersInit): Headers;
|
|
45
|
+
prototype: Headers;
|
|
46
|
+
};
|
|
47
|
+
Request: {
|
|
48
|
+
new (input: RequestInfo | URL, init?: RequestInit): Request;
|
|
49
|
+
prototype: Request;
|
|
50
|
+
};
|
|
51
|
+
Response: {
|
|
52
|
+
new (body?: BodyInit | null, init?: ResponseInit): Response;
|
|
53
|
+
prototype: Response;
|
|
54
|
+
error(): Response;
|
|
55
|
+
json(data: any, init?: ResponseInit): Response;
|
|
56
|
+
redirect(url: string | URL, status?: number): Response;
|
|
57
|
+
};
|
|
58
|
+
Object: ObjectConstructor;
|
|
59
|
+
Array: ArrayConstructor;
|
|
60
|
+
String: StringConstructor;
|
|
61
|
+
Number: NumberConstructor;
|
|
62
|
+
Boolean: BooleanConstructor;
|
|
63
|
+
Date: DateConstructor;
|
|
64
|
+
Math: Math;
|
|
65
|
+
JSON: JSON;
|
|
66
|
+
Error: ErrorConstructor;
|
|
67
|
+
TypeError: TypeErrorConstructor;
|
|
68
|
+
ReferenceError: ReferenceErrorConstructor;
|
|
69
|
+
SyntaxError: SyntaxErrorConstructor;
|
|
70
|
+
globalThis: typeof globalThis;
|
|
71
|
+
undefined: undefined;
|
|
72
|
+
null: null;
|
|
73
|
+
Infinity: number;
|
|
74
|
+
NaN: number;
|
|
75
|
+
user: {
|
|
76
|
+
data: {
|
|
77
|
+
update: (data: any) => Promise<import("../services/api.js").ApiResponse<any>>;
|
|
78
|
+
get: () => Promise<any>;
|
|
79
|
+
create: (data: any) => Promise<any>;
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
env: (key: string) => string;
|
|
83
|
+
};
|
|
84
|
+
/**
|
|
85
|
+
* Executes a tool in a VM sandbox
|
|
86
|
+
*/
|
|
87
|
+
export declare function executeTool(options: ExecuteToolOptions): Promise<any>;
|
|
88
|
+
/**
|
|
89
|
+
* Creates a custom console that broadcasts logs via WebSocket
|
|
90
|
+
*/
|
|
91
|
+
export declare function createBroadcastConsole(broadcastLog: (logData: any) => void): {
|
|
92
|
+
log: (...args: any[]) => void;
|
|
93
|
+
error: (...args: any[]) => void;
|
|
94
|
+
warn: (...args: any[]) => void;
|
|
95
|
+
info: (...args: any[]) => void;
|
|
96
|
+
};
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
import { createRequire } from "module";
|
|
2
|
+
import vm from "vm";
|
|
3
|
+
import path from "path";
|
|
4
|
+
import { UserDataApi } from "../services/api.js";
|
|
5
|
+
import { readSkillConfig } from "./files.js";
|
|
6
|
+
/**
|
|
7
|
+
* Creates a VM sandbox context with all necessary globals and utilities
|
|
8
|
+
*/
|
|
9
|
+
export function createSandbox(options) {
|
|
10
|
+
const { apiKey, agentId, customConsole, broadcastLog } = options;
|
|
11
|
+
// Extract environment variables from YAML config
|
|
12
|
+
const config = readSkillConfig();
|
|
13
|
+
const envVars = {};
|
|
14
|
+
if (config?.skill?.env) {
|
|
15
|
+
for (const [key, value] of Object.entries(config.skill.env)) {
|
|
16
|
+
envVars[key] = value;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
// Create a CommonJS context for execution
|
|
20
|
+
const require = createRequire(process.cwd() + '/package.json');
|
|
21
|
+
const updateUserData = async (data) => {
|
|
22
|
+
return await UserDataApi.updateUserData(apiKey, agentId, data);
|
|
23
|
+
};
|
|
24
|
+
const getUserData = async () => {
|
|
25
|
+
return await UserDataApi.getUserData(apiKey, agentId);
|
|
26
|
+
};
|
|
27
|
+
const linkUserData = async (data) => {
|
|
28
|
+
return await UserDataApi.createUserData(apiKey, agentId, data);
|
|
29
|
+
};
|
|
30
|
+
// Create console object (use custom console if provided, otherwise default)
|
|
31
|
+
const consoleObj = customConsole || console;
|
|
32
|
+
// Create a sandbox context
|
|
33
|
+
const sandbox = {
|
|
34
|
+
require,
|
|
35
|
+
console: consoleObj,
|
|
36
|
+
Buffer,
|
|
37
|
+
setTimeout,
|
|
38
|
+
setInterval,
|
|
39
|
+
clearTimeout,
|
|
40
|
+
clearInterval,
|
|
41
|
+
process,
|
|
42
|
+
global: globalThis,
|
|
43
|
+
__dirname: process.cwd(),
|
|
44
|
+
__filename: path.join(process.cwd(), 'index.ts'),
|
|
45
|
+
module: { exports: {} },
|
|
46
|
+
exports: {},
|
|
47
|
+
// Web APIs
|
|
48
|
+
fetch: globalThis.fetch,
|
|
49
|
+
URLSearchParams: globalThis.URLSearchParams,
|
|
50
|
+
URL: globalThis.URL,
|
|
51
|
+
Headers: globalThis.Headers,
|
|
52
|
+
Request: globalThis.Request,
|
|
53
|
+
Response: globalThis.Response,
|
|
54
|
+
// Additional globals
|
|
55
|
+
Object,
|
|
56
|
+
Array,
|
|
57
|
+
String,
|
|
58
|
+
Number,
|
|
59
|
+
Boolean,
|
|
60
|
+
Date,
|
|
61
|
+
Math,
|
|
62
|
+
JSON,
|
|
63
|
+
Error,
|
|
64
|
+
TypeError,
|
|
65
|
+
ReferenceError,
|
|
66
|
+
SyntaxError,
|
|
67
|
+
globalThis,
|
|
68
|
+
undefined: undefined,
|
|
69
|
+
null: null,
|
|
70
|
+
Infinity: Infinity,
|
|
71
|
+
NaN: NaN,
|
|
72
|
+
user: {
|
|
73
|
+
data: {
|
|
74
|
+
update: updateUserData,
|
|
75
|
+
get: getUserData,
|
|
76
|
+
create: linkUserData
|
|
77
|
+
}
|
|
78
|
+
},
|
|
79
|
+
// Environment variables function
|
|
80
|
+
env: (key) => envVars[key]
|
|
81
|
+
};
|
|
82
|
+
return sandbox;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Executes a tool in a VM sandbox
|
|
86
|
+
*/
|
|
87
|
+
export async function executeTool(options) {
|
|
88
|
+
const { toolCode, inputs } = options;
|
|
89
|
+
// Create sandbox
|
|
90
|
+
const sandbox = createSandbox(options);
|
|
91
|
+
// Create the CommonJS wrapper code
|
|
92
|
+
const commonJsWrapper = `
|
|
93
|
+
const executeFunction = ${toolCode};
|
|
94
|
+
|
|
95
|
+
// Export the function for testing
|
|
96
|
+
module.exports = async (input) => {
|
|
97
|
+
return await executeFunction(input);
|
|
98
|
+
};
|
|
99
|
+
`;
|
|
100
|
+
// Execute the code in the sandbox
|
|
101
|
+
const context = vm.createContext(sandbox);
|
|
102
|
+
vm.runInContext(commonJsWrapper, context);
|
|
103
|
+
// Get the exported function and execute it
|
|
104
|
+
const executeFunction = context.module.exports;
|
|
105
|
+
return await executeFunction(inputs);
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Creates a custom console that broadcasts logs via WebSocket
|
|
109
|
+
*/
|
|
110
|
+
export function createBroadcastConsole(broadcastLog) {
|
|
111
|
+
return {
|
|
112
|
+
log: (...args) => {
|
|
113
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
114
|
+
broadcastLog({
|
|
115
|
+
type: 'log',
|
|
116
|
+
subType: 'info',
|
|
117
|
+
message: message,
|
|
118
|
+
timestamp: new Date().toISOString(),
|
|
119
|
+
id: Date.now().toString()
|
|
120
|
+
});
|
|
121
|
+
// Also log to server console
|
|
122
|
+
console.log(...args);
|
|
123
|
+
},
|
|
124
|
+
error: (...args) => {
|
|
125
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
126
|
+
broadcastLog({
|
|
127
|
+
type: 'log',
|
|
128
|
+
subType: 'error',
|
|
129
|
+
message: message,
|
|
130
|
+
timestamp: new Date().toISOString(),
|
|
131
|
+
id: Date.now().toString()
|
|
132
|
+
});
|
|
133
|
+
// Also log to server console
|
|
134
|
+
console.error(...args);
|
|
135
|
+
},
|
|
136
|
+
warn: (...args) => {
|
|
137
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
138
|
+
broadcastLog({
|
|
139
|
+
type: 'log',
|
|
140
|
+
subType: 'warn',
|
|
141
|
+
message: message,
|
|
142
|
+
timestamp: new Date().toISOString(),
|
|
143
|
+
id: Date.now().toString()
|
|
144
|
+
});
|
|
145
|
+
// Also log to server console
|
|
146
|
+
console.warn(...args);
|
|
147
|
+
},
|
|
148
|
+
info: (...args) => {
|
|
149
|
+
const message = args.map(arg => typeof arg === 'object' ? JSON.stringify(arg) : String(arg)).join(' ');
|
|
150
|
+
broadcastLog({
|
|
151
|
+
type: 'log',
|
|
152
|
+
subType: 'info',
|
|
153
|
+
message: message,
|
|
154
|
+
timestamp: new Date().toISOString(),
|
|
155
|
+
id: Date.now().toString()
|
|
156
|
+
});
|
|
157
|
+
// Also log to server console
|
|
158
|
+
console.info(...args);
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
}
|