lua-cli 1.3.2-alpha.0 → 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.
@@ -200,24 +200,28 @@ export class ToolApi {
200
200
  // User Data API calls
201
201
  export class UserDataApi {
202
202
  static async getUserData(apiKey, agentId) {
203
- return httpClient.get(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
203
+ const response = await httpClient.get(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
204
204
  Authorization: `Bearer ${apiKey}`,
205
205
  });
206
+ return response;
206
207
  }
207
208
  static async createUserData(apiKey, agentId, data) {
208
- return httpClient.post(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
209
+ const response = await httpClient.put(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
209
210
  Authorization: `Bearer ${apiKey}`,
210
211
  });
212
+ return response.data.data;
211
213
  }
212
214
  static async updateUserData(apiKey, agentId, data) {
213
- return httpClient.put(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
215
+ const response = await httpClient.put(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, data, {
214
216
  Authorization: `Bearer ${apiKey}`,
215
217
  });
218
+ return response.data.data;
216
219
  }
217
220
  static async deleteUserData(apiKey, agentId) {
218
- return httpClient.delete(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
221
+ const response = await httpClient.delete(`${BASE_URLS.LOCAL}/developer/user/data/agent/${agentId}`, {
219
222
  Authorization: `Bearer ${apiKey}`,
220
223
  });
224
+ return response;
221
225
  }
222
226
  }
223
227
  /**
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, TOutput extends ZodType>(tool: LuaTool<TInput, TOutput>): void;
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) {
@@ -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, TOutput 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, TOutput extends ZodType>(tool: LuaTool<TInput, TOutput>): void;
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
  }
@@ -3,6 +3,7 @@
3
3
  * Provides methods to interact with user data stored in the Lua system
4
4
  */
5
5
  export declare class UserDataAPI {
6
+ userData: any;
6
7
  constructor();
7
8
  /**
8
9
  * Get user data for the current agent
@@ -3,13 +3,15 @@
3
3
  * Provides methods to interact with user data stored in the Lua system
4
4
  */
5
5
  export class UserDataAPI {
6
- constructor() { }
6
+ constructor() {
7
+ this.userData = {};
8
+ }
7
9
  /**
8
10
  * Get user data for the current agent
9
11
  * @returns Promise<UserDataResponse>
10
12
  */
11
13
  async get() {
12
- return { success: true };
14
+ return { success: true, data: this.userData };
13
15
  }
14
16
  /**
15
17
  * Create or update user data for the current agent
@@ -17,7 +19,8 @@ export class UserDataAPI {
17
19
  * @returns Promise<UserDataResponse>
18
20
  */
19
21
  async create(data) {
20
- return { success: true };
22
+ this.userData = data;
23
+ return { success: true, data: this.userData };
21
24
  }
22
25
  /**
23
26
  * Update existing user data for the current agent
@@ -26,13 +29,15 @@ export class UserDataAPI {
26
29
  */
27
30
  async update(data) {
28
31
  // Update is the same as create for this API
29
- return { success: true };
32
+ this.userData = { ...this.userData, ...data };
33
+ return { success: true, data: this.userData };
30
34
  }
31
35
  /**
32
36
  * Clear all user data for the current agent
33
37
  * @returns Promise<{success: boolean}>
34
38
  */
35
39
  async clear() {
40
+ this.userData = {};
36
41
  return { success: true };
37
42
  }
38
43
  }
@@ -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 main package.json
31
- const mainPackageJsonPath = path.join(process.cwd(), 'package.json');
32
- const mainPackageJson = JSON.parse(fs.readFileSync(mainPackageJsonPath, 'utf8'));
33
- const currentCliVersion = mainPackageJson.version;
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
+ }