lua-cli 1.2.1 → 1.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.
@@ -1,29 +1,34 @@
1
1
  import inquirer from "inquirer";
2
2
  import { loadApiKey, deleteApiKey } from "../services/auth.js";
3
+ import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from "../utils/cli.js";
3
4
  export async function destroyCommand() {
4
- const apiKey = await loadApiKey();
5
- if (!apiKey) {
6
- console.log("ℹ️ No API key found to delete.");
7
- return;
8
- }
9
- const { confirm } = await inquirer.prompt([
10
- {
11
- type: "confirm",
12
- name: "confirm",
13
- message: "Are you sure you want to delete your API key? This action cannot be undone.",
14
- default: false
5
+ return withErrorHandling(async () => {
6
+ const apiKey = await loadApiKey();
7
+ if (!apiKey) {
8
+ writeProgress("ℹ️ No API key found to delete.");
9
+ return;
15
10
  }
16
- ]);
17
- if (confirm) {
18
- const deleted = await deleteApiKey();
19
- if (deleted) {
20
- console.log(" API key deleted successfully.");
11
+ const { confirm } = await inquirer.prompt([
12
+ {
13
+ type: "confirm",
14
+ name: "confirm",
15
+ message: "Are you sure you want to delete your API key? This action cannot be undone.",
16
+ default: false
17
+ }
18
+ ]);
19
+ // Clear the confirmation prompt lines
20
+ clearPromptLines(2);
21
+ if (confirm) {
22
+ const deleted = await deleteApiKey();
23
+ if (deleted) {
24
+ writeSuccess("✅ API key deleted successfully.");
25
+ }
26
+ else {
27
+ writeProgress("❌ Failed to delete API key.");
28
+ }
21
29
  }
22
30
  else {
23
- console.log(" Failed to delete API key.");
31
+ writeProgress("ℹ️ API key deletion cancelled.");
24
32
  }
25
- }
26
- else {
27
- console.log("ℹ️ API key deletion cancelled.");
28
- }
33
+ }, "logout");
29
34
  }
@@ -2,6 +2,7 @@ export { configureCommand } from "./configure.js";
2
2
  export { initCommand } from "./init.js";
3
3
  export { destroyCommand } from "./destroy.js";
4
4
  export { apiKeyCommand } from "./apiKey.js";
5
- export { agentsCommand } from "./agents.js";
6
- export { deployCommand } from "./deploy.js";
5
+ export { compileCommand } from "./compile.js";
7
6
  export { testCommand } from "./test.js";
7
+ export { pushCommand } from "./push.js";
8
+ export { deployCommand } from "./deploy.js";
@@ -2,6 +2,7 @@ export { configureCommand } from "./configure.js";
2
2
  export { initCommand } from "./init.js";
3
3
  export { destroyCommand } from "./destroy.js";
4
4
  export { apiKeyCommand } from "./apiKey.js";
5
- export { agentsCommand } from "./agents.js";
6
- export { deployCommand } from "./deploy.js";
5
+ export { compileCommand } from "./compile.js";
7
6
  export { testCommand } from "./test.js";
7
+ export { pushCommand } from "./push.js";
8
+ export { deployCommand } from "./deploy.js";
@@ -1,70 +1,117 @@
1
1
  import inquirer from "inquirer";
2
2
  import { fileURLToPath } from "url";
3
3
  import path from "path";
4
- import { loadApiKey, checkApiKey } from "../services/auth.js";
4
+ import { loadApiKey, checkApiKey, createSkill } from "../services/auth.js";
5
5
  import { copyTemplateFiles, createSkillToml } from "../utils/files.js";
6
+ import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from "../utils/cli.js";
7
+ function getTemplateDir() {
8
+ const __filename = fileURLToPath(import.meta.url);
9
+ const __dirname = path.dirname(__filename);
10
+ return path.join(__dirname, "..", "..", "template");
11
+ }
6
12
  export async function initCommand() {
7
- const apiKey = await loadApiKey();
8
- if (!apiKey) {
9
- console.error("❌ No API key found. Run `lua configure` first.");
10
- process.exit(1);
11
- }
12
- // Get user data from API
13
- const userData = await checkApiKey(apiKey);
14
- // Extract organizations and create choices for selection
15
- const orgs = userData.admin.orgs;
16
- const orgChoices = orgs.map((org) => ({
17
- name: org.registeredName,
18
- value: org
19
- }));
20
- // Select organization
21
- const { selectedOrg } = await inquirer.prompt([
22
- {
23
- type: "list",
24
- name: "selectedOrg",
25
- message: "Select an organization:",
26
- choices: orgChoices
13
+ return withErrorHandling(async () => {
14
+ const apiKey = await loadApiKey();
15
+ if (!apiKey) {
16
+ console.error("❌ No API key found. Run `lua configure` first.");
17
+ process.exit(1);
27
18
  }
28
- ]);
29
- // Extract agents from selected organization
30
- const agentChoices = selectedOrg.agents.map((agent) => ({
31
- name: agent.name,
32
- value: agent
33
- }));
34
- // Select agent
35
- const { selectedAgent } = await inquirer.prompt([
36
- {
37
- type: "list",
38
- name: "selectedAgent",
39
- message: "Select an agent:",
40
- choices: agentChoices
19
+ // Get user data from API
20
+ const userData = await checkApiKey(apiKey);
21
+ writeProgress("✅ Authenticated");
22
+ // Extract organizations and create choices for selection
23
+ const orgs = userData.admin.orgs;
24
+ if (!orgs || orgs.length === 0) {
25
+ console.error("❌ No organizations found.");
26
+ process.exit(1);
41
27
  }
42
- ]);
43
- // Get skill details
44
- const { skillName, skillDescription } = await inquirer.prompt([
45
- {
46
- type: "input",
47
- name: "skillName",
48
- message: "Enter a name for your skill:",
49
- default: "My Lua Skill"
50
- },
51
- {
52
- type: "input",
53
- name: "skillDescription",
54
- message: "Describe your skill:",
55
- default: "A Lua skill for automation"
28
+ const orgChoices = orgs.map((org) => ({
29
+ name: org.registeredName,
30
+ value: org
31
+ }));
32
+ // Select organization
33
+ const { selectedOrg } = await inquirer.prompt([
34
+ {
35
+ type: "list",
36
+ name: "selectedOrg",
37
+ message: "Select an organization:",
38
+ choices: orgChoices
39
+ }
40
+ ]);
41
+ // Clear the organization selection prompt lines
42
+ clearPromptLines(2);
43
+ // Extract agents from selected organization
44
+ if (!selectedOrg.agents || selectedOrg.agents.length === 0) {
45
+ console.error("❌ No agents found in the selected organization.");
46
+ process.exit(1);
56
47
  }
57
- ]);
58
- // Create lua.skill.toml file
59
- createSkillToml(selectedAgent.agentId, selectedOrg.id, skillName, skillDescription);
60
- console.log("✅ Created lua.skill.toml");
61
- // Copy template files
62
- const __filename = fileURLToPath(import.meta.url);
63
- const __dirname = path.dirname(__filename);
64
- const templateDir = path.join(__dirname, "..", "..", "template");
65
- const currentDir = process.cwd();
66
- copyTemplateFiles(templateDir, currentDir);
67
- console.log("✅ Copied template files");
68
- console.log("🎉 Lua skill project initialized successfully!");
69
- console.log("📦 Run `npm install` to install dependencies");
48
+ const agentChoices = selectedOrg.agents.map((agent) => ({
49
+ name: agent.name,
50
+ value: agent
51
+ }));
52
+ // Select agent
53
+ const { selectedAgent } = await inquirer.prompt([
54
+ {
55
+ type: "list",
56
+ name: "selectedAgent",
57
+ message: "Select an agent:",
58
+ choices: agentChoices
59
+ }
60
+ ]);
61
+ // Clear the agent selection prompt lines
62
+ clearPromptLines(2);
63
+ // Get skill name and handle retries
64
+ let skillName = "";
65
+ let skillData = null;
66
+ let retry = true;
67
+ while (retry) {
68
+ const { skillName: inputSkillName } = await inquirer.prompt([
69
+ {
70
+ type: "input",
71
+ name: "skillName",
72
+ message: "Enter a name for your skill:",
73
+ default: "My Lua Skill"
74
+ }
75
+ ]);
76
+ skillName = inputSkillName;
77
+ // Create skill via API
78
+ writeProgress("🔄 Creating skill...");
79
+ const result = await createSkill(apiKey, selectedAgent.agentId, skillName);
80
+ if (result.success && result.data) {
81
+ skillData = result.data;
82
+ writeProgress("✅ Skill created successfully!");
83
+ retry = false;
84
+ }
85
+ else if (result.error) {
86
+ console.error(`❌ ${result.error.message}`);
87
+ const { shouldRetry } = await inquirer.prompt([
88
+ {
89
+ type: "confirm",
90
+ name: "shouldRetry",
91
+ message: "Would you like to try with a different name?",
92
+ default: true
93
+ }
94
+ ]);
95
+ // Clear the retry prompt lines
96
+ clearPromptLines(2);
97
+ if (!shouldRetry) {
98
+ writeProgress("❌ Skill creation cancelled.");
99
+ process.exit(1);
100
+ }
101
+ }
102
+ else {
103
+ console.error("❌ Failed to create skill. Please try again.");
104
+ process.exit(1);
105
+ }
106
+ }
107
+ // Create lua.skill.toml file with skill ID
108
+ createSkillToml(selectedAgent.agentId, selectedOrg.id, skillName, skillData?.id);
109
+ writeProgress("✅ Created lua.skill.toml");
110
+ // Copy template files
111
+ const templateDir = getTemplateDir();
112
+ const currentDir = process.cwd();
113
+ copyTemplateFiles(templateDir, currentDir);
114
+ writeProgress("✅ Copied template files");
115
+ writeSuccess("✅ Lua skill project initialized successfully!");
116
+ }, "initialization");
70
117
  }
@@ -0,0 +1,22 @@
1
+ export interface PushVersionResponse {
2
+ success: boolean;
3
+ data?: {
4
+ skillsId: string;
5
+ version: string;
6
+ context: string;
7
+ description: string;
8
+ tools: any[];
9
+ _id: string;
10
+ id: string;
11
+ createdAt: string;
12
+ updatedAt: string;
13
+ __v: number;
14
+ };
15
+ error?: {
16
+ message: string;
17
+ error: string;
18
+ statusCode: number;
19
+ };
20
+ }
21
+ export declare function pushVersion(apiKey: string, agentId: string, skillId: string, versionData: any): Promise<PushVersionResponse>;
22
+ export declare function pushCommand(): Promise<void>;
@@ -0,0 +1,138 @@
1
+ import fs from 'fs';
2
+ import path from 'path';
3
+ import inquirer from 'inquirer';
4
+ import { compileCommand } from './compile.js';
5
+ import { checkApiKey, loadApiKey } from '../services/auth.js';
6
+ import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from '../utils/cli.js';
7
+ export async function pushVersion(apiKey, agentId, skillId, versionData) {
8
+ try {
9
+ const response = await fetch(`https://api.lua.dev/developer/skills/${agentId}/${skillId}/version`, {
10
+ method: "POST",
11
+ headers: {
12
+ "accept": "application/json",
13
+ "Authorization": `Bearer ${apiKey}`,
14
+ "Content-Type": "application/json"
15
+ },
16
+ body: JSON.stringify(versionData)
17
+ });
18
+ const data = await response.json();
19
+ if (response.ok) {
20
+ return {
21
+ success: true,
22
+ data: data
23
+ };
24
+ }
25
+ else {
26
+ return {
27
+ success: false,
28
+ error: data
29
+ };
30
+ }
31
+ }
32
+ catch (error) {
33
+ console.error("❌ Error pushing version:", error);
34
+ return {
35
+ success: false,
36
+ error: {
37
+ message: "Network error",
38
+ error: "Failed to connect to server",
39
+ statusCode: 500
40
+ }
41
+ };
42
+ }
43
+ }
44
+ function readTomlVersion() {
45
+ const tomlPath = path.join(process.cwd(), 'lua.skill.toml');
46
+ if (!fs.existsSync(tomlPath)) {
47
+ return null;
48
+ }
49
+ const tomlContent = fs.readFileSync(tomlPath, 'utf8');
50
+ const versionMatch = tomlContent.match(/version\s*=\s*["']([^"']+)["']/);
51
+ return versionMatch ? versionMatch[1] : null;
52
+ }
53
+ function readDeployJson() {
54
+ const deployPath = path.join(process.cwd(), '.lua', 'deploy.json');
55
+ if (!fs.existsSync(deployPath)) {
56
+ return null;
57
+ }
58
+ const deployContent = fs.readFileSync(deployPath, 'utf8');
59
+ return JSON.parse(deployContent);
60
+ }
61
+ export async function pushCommand() {
62
+ return withErrorHandling(async () => {
63
+ // Check if we're in a skill directory
64
+ const tomlPath = path.join(process.cwd(), 'lua.skill.toml');
65
+ if (!fs.existsSync(tomlPath)) {
66
+ console.error("❌ No lua.skill.toml found. Please run this command from a skill directory.");
67
+ process.exit(1);
68
+ }
69
+ // Read version from TOML
70
+ const version = readTomlVersion();
71
+ if (!version) {
72
+ console.error("❌ No version found in lua.skill.toml");
73
+ process.exit(1);
74
+ }
75
+ // Confirm with user
76
+ const { confirmed } = await inquirer.prompt([
77
+ {
78
+ type: "confirm",
79
+ name: "confirmed",
80
+ message: `Are you sure you want to push version ${version}?`,
81
+ default: false
82
+ }
83
+ ]);
84
+ // Clear the confirmation prompt lines
85
+ clearPromptLines(2);
86
+ if (!confirmed) {
87
+ console.log("❌ Push cancelled.");
88
+ process.exit(0);
89
+ }
90
+ // Load API key
91
+ const apiKey = await loadApiKey();
92
+ if (!apiKey) {
93
+ console.error("❌ No API key found. Please run 'lua configure' to set up your API key.");
94
+ process.exit(1);
95
+ }
96
+ // Validate API key
97
+ const userData = await checkApiKey(apiKey);
98
+ writeProgress("✅ Authenticated");
99
+ // Compile the skill first
100
+ writeProgress("🔄 Compiling skill...");
101
+ await compileCommand();
102
+ // Read deploy.json
103
+ const deployData = readDeployJson();
104
+ if (!deployData) {
105
+ console.error("❌ No deploy.json found. Compilation may have failed.");
106
+ process.exit(1);
107
+ }
108
+ // Verify version matches
109
+ if (deployData.version !== version) {
110
+ console.error(`❌ Version mismatch: TOML has ${version}, deploy.json has ${deployData.version}`);
111
+ process.exit(1);
112
+ }
113
+ // Extract agentId and skillId from TOML
114
+ const tomlContent = fs.readFileSync(tomlPath, 'utf8');
115
+ const agentIdMatch = tomlContent.match(/agentId\s*=\s*["']([^"']+)["']/);
116
+ const skillIdMatch = tomlContent.match(/skillId\s*=\s*["']([^"']+)["']/);
117
+ if (!agentIdMatch || !skillIdMatch) {
118
+ console.error("❌ Missing agentId or skillId in lua.skill.toml");
119
+ process.exit(1);
120
+ }
121
+ const agentId = agentIdMatch[1];
122
+ const skillId = skillIdMatch[1];
123
+ // Push version
124
+ writeProgress("🔄 Pushing version to server...");
125
+ const result = await pushVersion(apiKey, agentId, skillId, deployData);
126
+ if (result.success && result.data) {
127
+ writeSuccess(`✅ Version ${result.data.version} pushed successfully`);
128
+ }
129
+ else if (result.error) {
130
+ console.error(`❌ ${result.error.message}`);
131
+ process.exit(1);
132
+ }
133
+ else {
134
+ console.error("❌ Failed to push version. Please try again.");
135
+ process.exit(1);
136
+ }
137
+ }, "push");
138
+ }
@@ -1,22 +1,23 @@
1
1
  import fs from "fs";
2
2
  import path from "path";
3
3
  import inquirer from "inquirer";
4
- import { deployCommand } from "./deploy.js";
4
+ import { compileCommand } from "./compile.js";
5
5
  import { gunzipSync } from "zlib";
6
6
  import { Buffer } from "buffer";
7
7
  import { createRequire } from "module";
8
8
  import vm from "vm";
9
+ import { withErrorHandling, clearPromptLines, writeProgress, writeSuccess } from "../utils/cli.js";
9
10
  // Decompression utility
10
11
  function decompressCode(compressedCode) {
11
12
  const buffer = Buffer.from(compressedCode, 'base64');
12
13
  return gunzipSync(buffer).toString('utf8');
13
14
  }
14
15
  export async function testCommand() {
15
- try {
16
- console.log("🧪 Testing Lua skill...");
16
+ return withErrorHandling(async () => {
17
+ writeProgress("🧪 Testing Lua skill...");
17
18
  // First, compile the code
18
- console.log("📦 Compiling code first...");
19
- await deployCommand();
19
+ writeProgress("📦 Compiling code first...");
20
+ await compileCommand();
20
21
  // Check if .lua directory exists
21
22
  const luaDir = path.join(process.cwd(), ".lua");
22
23
  if (!fs.existsSync(luaDir)) {
@@ -45,12 +46,14 @@ export async function testCommand() {
45
46
  pageSize: 10
46
47
  }
47
48
  ]);
48
- console.log(`\n✅ Selected tool: ${selectedTool.name}`);
49
+ // Clear the tool selection prompt lines
50
+ clearPromptLines(2);
51
+ writeProgress(`✅ Selected tool: ${selectedTool.name}`);
49
52
  // Get input values for each required parameter using inquirer
50
53
  const inputValues = {};
51
54
  const inputSchema = selectedTool.inputSchema;
52
55
  if (inputSchema.properties) {
53
- console.log("\n📝 Enter input values:");
56
+ writeProgress("\n📝 Enter input values:");
54
57
  const inputPrompts = [];
55
58
  for (const [key, value] of Object.entries(inputSchema.properties)) {
56
59
  const property = value;
@@ -108,8 +111,8 @@ export async function testCommand() {
108
111
  }
109
112
  }
110
113
  }
111
- console.log("\n🚀 Executing tool...");
112
- console.log(`Input: ${JSON.stringify(inputValues, null, 2)}`);
114
+ writeProgress("\n🚀 Executing tool...");
115
+ writeProgress(`Input: ${JSON.stringify(inputValues, null, 2)}`);
113
116
  // Get the execute function string directly from the selected tool and decompress it
114
117
  const toolCode = decompressCode(selectedTool.execute);
115
118
  // Execute the tool
@@ -174,7 +177,7 @@ module.exports = async (input) => {
174
177
  // Get the exported function
175
178
  const executeFunction = context.module.exports;
176
179
  const result = await executeFunction(inputValues);
177
- console.log("\n✅ Tool execution successful!");
180
+ writeSuccess("✅ Tool execution successful!");
178
181
  console.log(`Output: ${JSON.stringify(result, null, 2)}`);
179
182
  }
180
183
  catch (executionError) {
@@ -184,9 +187,5 @@ module.exports = async (input) => {
184
187
  console.error(executionError.stack);
185
188
  }
186
189
  }
187
- }
188
- catch (error) {
189
- console.error("❌ Test failed:", error.message);
190
- process.exit(1);
191
- }
190
+ }, "testing");
192
191
  }
package/dist/index.js CHANGED
@@ -1,33 +1,43 @@
1
1
  #!/usr/bin/env node
2
2
  import { Command } from "commander";
3
- import { configureCommand, initCommand, destroyCommand, apiKeyCommand, agentsCommand, deployCommand, testCommand } from "./commands/index.js";
3
+ import { configureCommand, initCommand, destroyCommand, apiKeyCommand, compileCommand, testCommand, pushCommand, deployCommand } from "./commands/index.js";
4
4
  const program = new Command();
5
- program
6
- .command("init")
7
- .description("Initialize a new Lua skill project")
8
- .action(initCommand);
9
- program
10
- .command("destroy")
11
- .description("Delete your stored API key")
12
- .action(destroyCommand);
13
- program
5
+ const authCommand = program
6
+ .command("auth")
7
+ .description("Authentication management commands");
8
+ authCommand
14
9
  .command("configure")
15
10
  .description("Set up your API key")
16
11
  .action(configureCommand);
17
- program
18
- .command("apiKey")
12
+ authCommand
13
+ .command("logout")
14
+ .description("Delete your stored API key")
15
+ .action(destroyCommand);
16
+ authCommand
17
+ .command("key")
19
18
  .description("Display your stored API key")
20
19
  .action(apiKeyCommand);
21
- program
22
- .command("agents")
23
- .description("Fetch agents from HeyLua API")
24
- .action(agentsCommand);
25
- program
20
+ const skillCommand = program
21
+ .command("skill")
22
+ .description("Lua skill management commands");
23
+ skillCommand
24
+ .command("init")
25
+ .description("Initialize a new Lua skill project")
26
+ .action(initCommand);
27
+ skillCommand
26
28
  .command("compile")
27
29
  .description("Compile Lua skill to generate deployable format")
28
- .action(deployCommand);
29
- program
30
+ .action(compileCommand);
31
+ skillCommand
30
32
  .command("test")
31
33
  .description("Test Lua skill tools interactively")
32
34
  .action(testCommand);
35
+ skillCommand
36
+ .command("push")
37
+ .description("Push compiled skill version to server")
38
+ .action(pushCommand);
39
+ skillCommand
40
+ .command("deploy")
41
+ .description("Deploy a version to production")
42
+ .action(deployCommand);
33
43
  program.parse(process.argv);
@@ -6,3 +6,23 @@ export declare function checkApiKey(apiKey: string): Promise<UserData>;
6
6
  export declare function requestEmailOTP(email: string): Promise<boolean>;
7
7
  export declare function verifyOTPAndGetToken(email: string, pin: string): Promise<string | null>;
8
8
  export declare function generateApiKey(signInToken: string): Promise<string | null>;
9
+ export interface CreateSkillResponse {
10
+ success: boolean;
11
+ data?: {
12
+ name: string;
13
+ public: boolean;
14
+ agentId: string;
15
+ active: boolean;
16
+ _id: string;
17
+ id: string;
18
+ createdAt: string;
19
+ updatedAt: string;
20
+ __v: number;
21
+ };
22
+ error?: {
23
+ message: string;
24
+ error: string;
25
+ statusCode: number;
26
+ };
27
+ }
28
+ export declare function createSkill(apiKey: string, agentId: string, skillName: string): Promise<CreateSkillResponse>;
@@ -12,7 +12,7 @@ export async function deleteApiKey() {
12
12
  return keytar.deletePassword(SERVICE, ACCOUNT);
13
13
  }
14
14
  export async function checkApiKey(apiKey) {
15
- const response = await fetch("https://api.heylua.ai/admin", {
15
+ const response = await fetch("https://api.lua.dev/admin", {
16
16
  headers: {
17
17
  Authorization: `Bearer ${apiKey}`,
18
18
  },
@@ -25,7 +25,7 @@ export async function checkApiKey(apiKey) {
25
25
  }
26
26
  export async function requestEmailOTP(email) {
27
27
  try {
28
- const response = await fetch("https://auth.heylua.ai/otp", {
28
+ const response = await fetch("https://auth.lua.dev/otp", {
29
29
  method: "POST",
30
30
  headers: {
31
31
  "accept": "application/json",
@@ -45,7 +45,7 @@ export async function requestEmailOTP(email) {
45
45
  }
46
46
  export async function verifyOTPAndGetToken(email, pin) {
47
47
  try {
48
- const response = await fetch("https://auth.heylua.ai/otp/verify", {
48
+ const response = await fetch("https://auth.lua.dev/otp/verify", {
49
49
  method: "POST",
50
50
  headers: {
51
51
  "accept": "application/json",
@@ -70,7 +70,7 @@ export async function verifyOTPAndGetToken(email, pin) {
70
70
  }
71
71
  export async function generateApiKey(signInToken) {
72
72
  try {
73
- const response = await fetch("https://auth.heylua.ai/profile/apiKey", {
73
+ const response = await fetch("https://auth.lua.dev/profile/apiKey", {
74
74
  method: "POST",
75
75
  headers: {
76
76
  "Authorization": `Bearer ${signInToken}`,
@@ -89,3 +89,42 @@ export async function generateApiKey(signInToken) {
89
89
  return null;
90
90
  }
91
91
  }
92
+ export async function createSkill(apiKey, agentId, skillName) {
93
+ try {
94
+ const response = await fetch(`https://api.lua.dev/developer/skills/${agentId}`, {
95
+ method: "POST",
96
+ headers: {
97
+ "accept": "application/json",
98
+ "Authorization": `Bearer ${apiKey}`,
99
+ "Content-Type": "application/json"
100
+ },
101
+ body: JSON.stringify({
102
+ name: skillName
103
+ })
104
+ });
105
+ const data = await response.json();
106
+ if (response.ok) {
107
+ return {
108
+ success: true,
109
+ data: data
110
+ };
111
+ }
112
+ else {
113
+ return {
114
+ success: false,
115
+ error: data
116
+ };
117
+ }
118
+ }
119
+ catch (error) {
120
+ console.error("❌ Error creating skill:", error);
121
+ return {
122
+ success: false,
123
+ error: {
124
+ message: "Network error",
125
+ error: "Failed to connect to server",
126
+ statusCode: 500
127
+ }
128
+ };
129
+ }
130
+ }