lua-cli 2.5.4 → 2.5.5
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/api/developer.api.service.d.ts +54 -0
- package/dist/api/developer.api.service.js +51 -0
- package/dist/api/skills.api.service.d.ts +16 -0
- package/dist/api/skills.api.service.js +23 -0
- package/dist/commands/compile.d.ts +7 -0
- package/dist/commands/compile.js +18 -0
- package/dist/commands/env.js +42 -26
- package/dist/interfaces/skills.d.ts +51 -0
- package/dist/interfaces/skills.js +5 -0
- package/dist/utils/skill-management.d.ts +20 -0
- package/dist/utils/skill-management.js +159 -0
- package/package.json +1 -1
- package/template/package.json +1 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { HttpClient } from "../common/http.client.js";
|
|
2
|
+
import { ApiResponse } from "../interfaces/common.js";
|
|
3
|
+
/**
|
|
4
|
+
* Environment variables response structure from the API
|
|
5
|
+
* The actual environment variables are nested in the 'data' property
|
|
6
|
+
*/
|
|
7
|
+
interface EnvironmentVariablesResponse {
|
|
8
|
+
data: Record<string, string>;
|
|
9
|
+
_id?: string;
|
|
10
|
+
agentId?: string;
|
|
11
|
+
createdAt?: string;
|
|
12
|
+
updatedAt?: string;
|
|
13
|
+
__v?: number;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Developer API calls for agent management and configuration
|
|
17
|
+
*/
|
|
18
|
+
export default class DeveloperApi extends HttpClient {
|
|
19
|
+
private apiKey;
|
|
20
|
+
private agentId;
|
|
21
|
+
/**
|
|
22
|
+
* Creates an instance of DeveloperApi
|
|
23
|
+
* @param baseUrl - The base URL for the API
|
|
24
|
+
* @param apiKey - The API key for authentication
|
|
25
|
+
* @param agentId - The unique identifier of the agent
|
|
26
|
+
*/
|
|
27
|
+
constructor(baseUrl: string, apiKey: string, agentId: string);
|
|
28
|
+
/**
|
|
29
|
+
* Retrieves all environment variables for the agent in production
|
|
30
|
+
* The response includes metadata (_id, agentId, timestamps) and the actual env vars in the 'data' property
|
|
31
|
+
* @returns Promise resolving to an ApiResponse containing environment variables and metadata
|
|
32
|
+
* @throws Error if the API request fails or the agent is not found
|
|
33
|
+
*/
|
|
34
|
+
getEnvironmentVariables(): Promise<ApiResponse<EnvironmentVariablesResponse>>;
|
|
35
|
+
/**
|
|
36
|
+
* Updates all environment variables for the agent in production
|
|
37
|
+
* This operation replaces all existing environment variables with the provided set
|
|
38
|
+
* @param envData - Object containing environment variable key-value pairs
|
|
39
|
+
* @returns Promise resolving to an ApiResponse with the updated environment variables and metadata
|
|
40
|
+
* @throws Error if the API request fails or the agent is not found
|
|
41
|
+
*/
|
|
42
|
+
updateEnvironmentVariables(envData: Record<string, string>): Promise<ApiResponse<EnvironmentVariablesResponse>>;
|
|
43
|
+
/**
|
|
44
|
+
* Deletes a specific environment variable by key
|
|
45
|
+
* @param key - The environment variable key to delete
|
|
46
|
+
* @returns Promise resolving to an ApiResponse with confirmation
|
|
47
|
+
* @throws Error if the API request fails, the agent is not found, or the key doesn't exist
|
|
48
|
+
*/
|
|
49
|
+
deleteEnvironmentVariable(key: string): Promise<ApiResponse<{
|
|
50
|
+
message: string;
|
|
51
|
+
key: string;
|
|
52
|
+
}>>;
|
|
53
|
+
}
|
|
54
|
+
export {};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { HttpClient } from "../common/http.client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Developer API calls for agent management and configuration
|
|
4
|
+
*/
|
|
5
|
+
export default class DeveloperApi extends HttpClient {
|
|
6
|
+
/**
|
|
7
|
+
* Creates an instance of DeveloperApi
|
|
8
|
+
* @param baseUrl - The base URL for the API
|
|
9
|
+
* @param apiKey - The API key for authentication
|
|
10
|
+
* @param agentId - The unique identifier of the agent
|
|
11
|
+
*/
|
|
12
|
+
constructor(baseUrl, apiKey, agentId) {
|
|
13
|
+
super(baseUrl);
|
|
14
|
+
this.apiKey = apiKey;
|
|
15
|
+
this.agentId = agentId;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves all environment variables for the agent in production
|
|
19
|
+
* The response includes metadata (_id, agentId, timestamps) and the actual env vars in the 'data' property
|
|
20
|
+
* @returns Promise resolving to an ApiResponse containing environment variables and metadata
|
|
21
|
+
* @throws Error if the API request fails or the agent is not found
|
|
22
|
+
*/
|
|
23
|
+
async getEnvironmentVariables() {
|
|
24
|
+
return this.httpGet(`/developer/agents/${this.agentId}/env`, {
|
|
25
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Updates all environment variables for the agent in production
|
|
30
|
+
* This operation replaces all existing environment variables with the provided set
|
|
31
|
+
* @param envData - Object containing environment variable key-value pairs
|
|
32
|
+
* @returns Promise resolving to an ApiResponse with the updated environment variables and metadata
|
|
33
|
+
* @throws Error if the API request fails or the agent is not found
|
|
34
|
+
*/
|
|
35
|
+
async updateEnvironmentVariables(envData) {
|
|
36
|
+
return this.httpPost(`/developer/agents/${this.agentId}/env`, envData, {
|
|
37
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Deletes a specific environment variable by key
|
|
42
|
+
* @param key - The environment variable key to delete
|
|
43
|
+
* @returns Promise resolving to an ApiResponse with confirmation
|
|
44
|
+
* @throws Error if the API request fails, the agent is not found, or the key doesn't exist
|
|
45
|
+
*/
|
|
46
|
+
async deleteEnvironmentVariable(key) {
|
|
47
|
+
return this.httpDelete(`/developer/agents/${this.agentId}/env/${key}`, {
|
|
48
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { DevVersionResponse, UpdateDevVersionResponse } from "../interfaces/dev.js";
|
|
2
2
|
import { HttpClient } from "../common/http.client.js";
|
|
3
3
|
import { ApiResponse } from "../interfaces/common.js";
|
|
4
|
+
import { GetSkillsResponse, DeleteSkillResponse } from "../interfaces/skills.js";
|
|
4
5
|
/**
|
|
5
6
|
* Skill API calls
|
|
6
7
|
*/
|
|
@@ -14,6 +15,12 @@ export default class SkillApi extends HttpClient {
|
|
|
14
15
|
* @param agentId - The unique identifier of the agent
|
|
15
16
|
*/
|
|
16
17
|
constructor(baseUrl: string, apiKey: string, agentId: string);
|
|
18
|
+
/**
|
|
19
|
+
* Retrieves all skills for the agent
|
|
20
|
+
* @returns Promise resolving to an ApiResponse containing an array of skills with their versions and tools
|
|
21
|
+
* @throws Error if the API request fails or the agent is not found
|
|
22
|
+
*/
|
|
23
|
+
getSkills(): Promise<ApiResponse<GetSkillsResponse>>;
|
|
17
24
|
/**
|
|
18
25
|
* Creates a new skill for the agent
|
|
19
26
|
* @param skillData - The skill data including name, description, and optional context
|
|
@@ -74,4 +81,13 @@ export default class SkillApi extends HttpClient {
|
|
|
74
81
|
activeVersionId: string;
|
|
75
82
|
publishedAt: string;
|
|
76
83
|
}>>;
|
|
84
|
+
/**
|
|
85
|
+
* Deletes a skill and all its versions, or deactivates it if it has versions
|
|
86
|
+
* @param skillId - The unique identifier of the skill to delete
|
|
87
|
+
* @returns Promise resolving to an ApiResponse with deletion status
|
|
88
|
+
* - If deleted is true: skill was successfully deleted
|
|
89
|
+
* - If deleted is false and deactivated is true: skill has versions and was deactivated instead
|
|
90
|
+
* @throws Error if the skill is not found or the delete operation fails
|
|
91
|
+
*/
|
|
92
|
+
deleteSkill(skillId: string): Promise<ApiResponse<DeleteSkillResponse>>;
|
|
77
93
|
}
|
|
@@ -14,6 +14,16 @@ export default class SkillApi extends HttpClient {
|
|
|
14
14
|
this.apiKey = apiKey;
|
|
15
15
|
this.agentId = agentId;
|
|
16
16
|
}
|
|
17
|
+
/**
|
|
18
|
+
* Retrieves all skills for the agent
|
|
19
|
+
* @returns Promise resolving to an ApiResponse containing an array of skills with their versions and tools
|
|
20
|
+
* @throws Error if the API request fails or the agent is not found
|
|
21
|
+
*/
|
|
22
|
+
async getSkills() {
|
|
23
|
+
return this.httpGet(`/developer/skills/${this.agentId}`, {
|
|
24
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
25
|
+
});
|
|
26
|
+
}
|
|
17
27
|
/**
|
|
18
28
|
* Creates a new skill for the agent
|
|
19
29
|
* @param skillData - The skill data including name, description, and optional context
|
|
@@ -85,4 +95,17 @@ export default class SkillApi extends HttpClient {
|
|
|
85
95
|
Authorization: `Bearer ${this.apiKey}`,
|
|
86
96
|
});
|
|
87
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* Deletes a skill and all its versions, or deactivates it if it has versions
|
|
100
|
+
* @param skillId - The unique identifier of the skill to delete
|
|
101
|
+
* @returns Promise resolving to an ApiResponse with deletion status
|
|
102
|
+
* - If deleted is true: skill was successfully deleted
|
|
103
|
+
* - If deleted is false and deactivated is true: skill has versions and was deactivated instead
|
|
104
|
+
* @throws Error if the skill is not found or the delete operation fails
|
|
105
|
+
*/
|
|
106
|
+
async deleteSkill(skillId) {
|
|
107
|
+
return this.httpDelete(`/developer/skills/${this.agentId}/${skillId}`, {
|
|
108
|
+
Authorization: `Bearer ${this.apiKey}`,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
88
111
|
}
|
|
@@ -12,6 +12,8 @@
|
|
|
12
12
|
* 4. Extracts execute code and schemas from bundled tools
|
|
13
13
|
* 5. Bundles the main index file
|
|
14
14
|
* 6. Creates deployment data in both new and legacy formats
|
|
15
|
+
* 7. Syncs lua.skill.yaml with deploy.json (removes deleted skills from YAML)
|
|
16
|
+
* 8. Syncs server with YAML (deletes/deactivates skills not in YAML)
|
|
15
17
|
*
|
|
16
18
|
* Output:
|
|
17
19
|
* - dist/deployment.json - New deployment format with tool references
|
|
@@ -19,6 +21,11 @@
|
|
|
19
21
|
* - dist/index.js - Main skill entry point
|
|
20
22
|
* - .lua/deploy.json - Legacy deployment format with compressed tools
|
|
21
23
|
* - .lua/*.js - Individual uncompressed tool files for debugging
|
|
24
|
+
* - lua.skill.yaml - Updated to match compiled skills
|
|
25
|
+
*
|
|
26
|
+
* Server Sync:
|
|
27
|
+
* - Skills deleted from code are removed from YAML
|
|
28
|
+
* - Skills not in YAML are deleted from server (or deactivated if they have versions)
|
|
22
29
|
*
|
|
23
30
|
* @returns Promise that resolves when compilation is complete
|
|
24
31
|
*/
|
package/dist/commands/compile.js
CHANGED
|
@@ -10,6 +10,8 @@ import { findIndexFile } from '../utils/compile.js';
|
|
|
10
10
|
import { detectTools } from '../utils/tool-detection.js';
|
|
11
11
|
import { bundleTool, bundleMainIndex, extractExecuteCode } from '../utils/bundling.js';
|
|
12
12
|
import { createDeploymentData, createLegacyDeploymentData } from '../utils/deployment.js';
|
|
13
|
+
import { syncYamlWithDeployJson, syncServerSkillsWithYaml } from '../utils/skill-management.js';
|
|
14
|
+
import { readSkillConfig } from '../utils/files.js';
|
|
13
15
|
import { COMPILE_DIRS, COMPILE_FILES } from '../config/compile.constants.js';
|
|
14
16
|
/**
|
|
15
17
|
* Main compile command - orchestrates the entire skill compilation process.
|
|
@@ -21,6 +23,8 @@ import { COMPILE_DIRS, COMPILE_FILES } from '../config/compile.constants.js';
|
|
|
21
23
|
* 4. Extracts execute code and schemas from bundled tools
|
|
22
24
|
* 5. Bundles the main index file
|
|
23
25
|
* 6. Creates deployment data in both new and legacy formats
|
|
26
|
+
* 7. Syncs lua.skill.yaml with deploy.json (removes deleted skills from YAML)
|
|
27
|
+
* 8. Syncs server with YAML (deletes/deactivates skills not in YAML)
|
|
24
28
|
*
|
|
25
29
|
* Output:
|
|
26
30
|
* - dist/deployment.json - New deployment format with tool references
|
|
@@ -28,6 +32,11 @@ import { COMPILE_DIRS, COMPILE_FILES } from '../config/compile.constants.js';
|
|
|
28
32
|
* - dist/index.js - Main skill entry point
|
|
29
33
|
* - .lua/deploy.json - Legacy deployment format with compressed tools
|
|
30
34
|
* - .lua/*.js - Individual uncompressed tool files for debugging
|
|
35
|
+
* - lua.skill.yaml - Updated to match compiled skills
|
|
36
|
+
*
|
|
37
|
+
* Server Sync:
|
|
38
|
+
* - Skills deleted from code are removed from YAML
|
|
39
|
+
* - Skills not in YAML are deleted from server (or deactivated if they have versions)
|
|
31
40
|
*
|
|
32
41
|
* @returns Promise that resolves when compilation is complete
|
|
33
42
|
*/
|
|
@@ -52,6 +61,15 @@ export async function compileCommand() {
|
|
|
52
61
|
// Step 5: Create deployment data in both formats
|
|
53
62
|
await createDeploymentData(tools, distDir);
|
|
54
63
|
await createLegacyDeploymentData(tools, luaDir, indexFile);
|
|
64
|
+
// Step 6: Sync YAML with deploy.json
|
|
65
|
+
writeProgress("🔄 Syncing YAML with deploy.json...");
|
|
66
|
+
const deployJsonPath = path.join(luaDir, COMPILE_FILES.DEPLOY_JSON);
|
|
67
|
+
const config = readSkillConfig();
|
|
68
|
+
await syncYamlWithDeployJson(deployJsonPath, config);
|
|
69
|
+
// Step 7: Sync server with YAML (delete skills not in YAML)
|
|
70
|
+
writeProgress("🔄 Syncing server with YAML...");
|
|
71
|
+
const updatedConfig = readSkillConfig(); // Re-read config after YAML sync
|
|
72
|
+
await syncServerSkillsWithYaml(updatedConfig);
|
|
55
73
|
writeSuccess(`✅ Skill compiled successfully - ${tools.length} tools bundled`);
|
|
56
74
|
}, "compilation");
|
|
57
75
|
}
|
package/dist/commands/env.js
CHANGED
|
@@ -10,6 +10,7 @@ import { readSkillConfig } from '../utils/files.js';
|
|
|
10
10
|
import { withErrorHandling, writeProgress, writeSuccess } from '../utils/cli.js';
|
|
11
11
|
import { BASE_URLS } from '../config/constants.js';
|
|
12
12
|
import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
|
|
13
|
+
import DeveloperApi from '../api/developer.api.service.js';
|
|
13
14
|
/**
|
|
14
15
|
* Main env command - manages environment variables
|
|
15
16
|
*
|
|
@@ -57,6 +58,7 @@ export async function envCommand() {
|
|
|
57
58
|
}
|
|
58
59
|
await checkApiKey(apiKey);
|
|
59
60
|
context.apiKey = apiKey;
|
|
61
|
+
context.developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
|
|
60
62
|
writeProgress("✅ Authenticated");
|
|
61
63
|
}
|
|
62
64
|
// Step 4: Start management loop
|
|
@@ -160,19 +162,22 @@ function loadSandboxEnvVariables() {
|
|
|
160
162
|
*/
|
|
161
163
|
async function loadProductionEnvVariables(context) {
|
|
162
164
|
try {
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
});
|
|
170
|
-
if (!response.ok) {
|
|
171
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
165
|
+
if (!context.developerApi) {
|
|
166
|
+
throw new Error('Developer API not initialized');
|
|
167
|
+
}
|
|
168
|
+
const response = await context.developerApi.getEnvironmentVariables();
|
|
169
|
+
if (!response.success) {
|
|
170
|
+
throw new Error(response.error?.message || 'Failed to load environment variables');
|
|
172
171
|
}
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
172
|
+
// The API returns environment variables nested in a 'data' property
|
|
173
|
+
// Response structure: { success: true, data: { data: { KEY: "value", ... }, _id: "...", ... } }
|
|
174
|
+
const envData = response.data?.data || response.data;
|
|
175
|
+
if (envData && typeof envData === 'object') {
|
|
176
|
+
// Filter out metadata fields like _id, agentId, createdAt, updatedAt, __v
|
|
177
|
+
const metadataKeys = ['_id', 'agentId', 'data', 'createdAt', 'updatedAt', '__v'];
|
|
178
|
+
return Object.entries(envData)
|
|
179
|
+
.filter(([key]) => !metadataKeys.includes(key))
|
|
180
|
+
.map(([key, value]) => ({
|
|
176
181
|
key,
|
|
177
182
|
value: String(value)
|
|
178
183
|
}));
|
|
@@ -231,23 +236,18 @@ function saveSandboxEnvVariables(variables) {
|
|
|
231
236
|
*/
|
|
232
237
|
async function saveProductionEnvVariables(context, variables) {
|
|
233
238
|
try {
|
|
239
|
+
if (!context.developerApi) {
|
|
240
|
+
throw new Error('Developer API not initialized');
|
|
241
|
+
}
|
|
234
242
|
const envData = {};
|
|
235
243
|
variables.forEach(v => {
|
|
236
244
|
if (v.key.trim()) {
|
|
237
245
|
envData[v.key.trim()] = v.value;
|
|
238
246
|
}
|
|
239
247
|
});
|
|
240
|
-
const response = await
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
'accept': 'application/json',
|
|
244
|
-
'Authorization': `Bearer ${context.apiKey}`,
|
|
245
|
-
'Content-Type': 'application/json'
|
|
246
|
-
},
|
|
247
|
-
body: JSON.stringify(envData)
|
|
248
|
-
});
|
|
249
|
-
if (!response.ok) {
|
|
250
|
-
throw new Error(`HTTP error! status: ${response.status}`);
|
|
248
|
+
const response = await context.developerApi.updateEnvironmentVariables(envData);
|
|
249
|
+
if (!response.success) {
|
|
250
|
+
throw new Error(response.error?.message || 'Failed to save environment variables');
|
|
251
251
|
}
|
|
252
252
|
return true;
|
|
253
253
|
}
|
|
@@ -383,14 +383,30 @@ async function deleteVariable(context, currentVariables) {
|
|
|
383
383
|
console.log("\nℹ️ Deletion cancelled.\n");
|
|
384
384
|
return;
|
|
385
385
|
}
|
|
386
|
-
|
|
387
|
-
writeProgress("🔄 Saving...");
|
|
386
|
+
writeProgress("🔄 Deleting...");
|
|
388
387
|
let success = false;
|
|
389
388
|
if (context.environment === 'sandbox') {
|
|
389
|
+
const updatedVariables = currentVariables.filter(v => v.key !== selectedKey);
|
|
390
390
|
success = saveSandboxEnvVariables(updatedVariables);
|
|
391
391
|
}
|
|
392
392
|
else {
|
|
393
|
-
|
|
393
|
+
// Use the dedicated delete API endpoint for production
|
|
394
|
+
if (!context.developerApi) {
|
|
395
|
+
console.error("❌ Developer API not initialized");
|
|
396
|
+
return;
|
|
397
|
+
}
|
|
398
|
+
try {
|
|
399
|
+
const response = await context.developerApi.deleteEnvironmentVariable(selectedKey);
|
|
400
|
+
if (response.success) {
|
|
401
|
+
success = true;
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
console.error(`❌ ${response.error?.message || 'Failed to delete variable'}`);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
catch (error) {
|
|
408
|
+
console.error('❌ Error deleting production env variable:', error);
|
|
409
|
+
}
|
|
394
410
|
}
|
|
395
411
|
if (success) {
|
|
396
412
|
writeSuccess(`✅ Variable "${selectedKey}" deleted successfully`);
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skills Interfaces
|
|
3
|
+
* Structures for skill management
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Tool definition within a skill version
|
|
7
|
+
*/
|
|
8
|
+
export interface SkillTool {
|
|
9
|
+
name: string;
|
|
10
|
+
description: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Skill version information
|
|
14
|
+
*/
|
|
15
|
+
export interface SkillVersion {
|
|
16
|
+
id: string;
|
|
17
|
+
version: string;
|
|
18
|
+
description: string;
|
|
19
|
+
active: boolean;
|
|
20
|
+
context: string;
|
|
21
|
+
tools: SkillTool[];
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Skill information
|
|
25
|
+
*/
|
|
26
|
+
export interface Skill {
|
|
27
|
+
id: string;
|
|
28
|
+
name: string;
|
|
29
|
+
description: string;
|
|
30
|
+
public: boolean;
|
|
31
|
+
active: boolean;
|
|
32
|
+
createdAt: string;
|
|
33
|
+
updatedAt: string;
|
|
34
|
+
versions: SkillVersion[];
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Response from get all skills API endpoint
|
|
38
|
+
*/
|
|
39
|
+
export interface GetSkillsResponse {
|
|
40
|
+
skills: Skill[];
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Response from delete skill API endpoint
|
|
44
|
+
* If deleted is false and deactivated is true, the skill has versions
|
|
45
|
+
* and cannot be deleted, so it was deactivated instead
|
|
46
|
+
*/
|
|
47
|
+
export interface DeleteSkillResponse {
|
|
48
|
+
message: string;
|
|
49
|
+
deleted: boolean;
|
|
50
|
+
deactivated: boolean;
|
|
51
|
+
}
|
|
@@ -12,3 +12,23 @@ import { SkillConfig } from '../types/compile.types.js';
|
|
|
12
12
|
* @returns Updated skills array with valid skill IDs
|
|
13
13
|
*/
|
|
14
14
|
export declare function ensureSkillsExistInYaml(skillsArray: any[], config: SkillConfig): Promise<any[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Updates the YAML file with skills from the deploy.json file.
|
|
17
|
+
* This ensures the YAML reflects what's actually in the compiled code.
|
|
18
|
+
* Only updates skill entries that already exist in YAML (preserves skillId).
|
|
19
|
+
* Removes skills from YAML that are no longer in deploy.json.
|
|
20
|
+
*
|
|
21
|
+
* @param deployJsonPath - Path to the deploy.json file
|
|
22
|
+
* @param config - Current skill configuration
|
|
23
|
+
*/
|
|
24
|
+
export declare function syncYamlWithDeployJson(deployJsonPath: string, config: SkillConfig): Promise<void>;
|
|
25
|
+
/**
|
|
26
|
+
* Syncs the server skills with the YAML configuration.
|
|
27
|
+
* Performs a two-way sync:
|
|
28
|
+
* 1. Deletes/deactivates skills from server that aren't in YAML
|
|
29
|
+
* 2. Updates YAML with active version numbers from server
|
|
30
|
+
*
|
|
31
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
32
|
+
* @returns Array of messages about sync operations
|
|
33
|
+
*/
|
|
34
|
+
export declare function syncServerSkillsWithYaml(config: SkillConfig): Promise<string[]>;
|
|
@@ -146,3 +146,162 @@ async function updateYamlWithSkills(skills, config) {
|
|
|
146
146
|
});
|
|
147
147
|
fs.writeFileSync(yamlPath, yamlContent);
|
|
148
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Updates the YAML file with skills from the deploy.json file.
|
|
151
|
+
* This ensures the YAML reflects what's actually in the compiled code.
|
|
152
|
+
* Only updates skill entries that already exist in YAML (preserves skillId).
|
|
153
|
+
* Removes skills from YAML that are no longer in deploy.json.
|
|
154
|
+
*
|
|
155
|
+
* @param deployJsonPath - Path to the deploy.json file
|
|
156
|
+
* @param config - Current skill configuration
|
|
157
|
+
*/
|
|
158
|
+
export async function syncYamlWithDeployJson(deployJsonPath, config) {
|
|
159
|
+
try {
|
|
160
|
+
// Read deploy.json
|
|
161
|
+
if (!fs.existsSync(deployJsonPath)) {
|
|
162
|
+
console.warn("⚠️ deploy.json not found. Skipping YAML sync.");
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
const deployData = JSON.parse(fs.readFileSync(deployJsonPath, 'utf8'));
|
|
166
|
+
const deploySkills = deployData.skills || [];
|
|
167
|
+
// Create map of deploy skills by name
|
|
168
|
+
const deploySkillsMap = new Map();
|
|
169
|
+
deploySkills.forEach((skill) => {
|
|
170
|
+
deploySkillsMap.set(skill.name, skill);
|
|
171
|
+
});
|
|
172
|
+
// Get existing YAML skills
|
|
173
|
+
const existingYamlSkills = config?.skills || [];
|
|
174
|
+
// Update YAML skills to match deploy.json
|
|
175
|
+
const updatedSkills = existingYamlSkills
|
|
176
|
+
.filter((yamlSkill) => {
|
|
177
|
+
// Keep only skills that exist in deploy.json
|
|
178
|
+
return deploySkillsMap.has(yamlSkill.name);
|
|
179
|
+
})
|
|
180
|
+
.map((yamlSkill) => {
|
|
181
|
+
// Update version and description from deploy.json if available
|
|
182
|
+
const deploySkill = deploySkillsMap.get(yamlSkill.name);
|
|
183
|
+
return {
|
|
184
|
+
name: yamlSkill.name,
|
|
185
|
+
version: deploySkill?.version || yamlSkill.version || SKILL_DEFAULTS.VERSION,
|
|
186
|
+
skillId: yamlSkill.skillId || ''
|
|
187
|
+
};
|
|
188
|
+
});
|
|
189
|
+
// Add new skills from deploy.json that aren't in YAML yet
|
|
190
|
+
deploySkills.forEach((deploySkill) => {
|
|
191
|
+
const existsInYaml = updatedSkills.some((s) => s.name === deploySkill.name);
|
|
192
|
+
if (!existsInYaml) {
|
|
193
|
+
updatedSkills.push({
|
|
194
|
+
name: deploySkill.name,
|
|
195
|
+
version: deploySkill.version || SKILL_DEFAULTS.VERSION,
|
|
196
|
+
skillId: '' // Will be created via API later
|
|
197
|
+
});
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
// Update YAML file
|
|
201
|
+
await updateYamlWithSkills(updatedSkills, config);
|
|
202
|
+
console.log("✅ YAML synced with deploy.json");
|
|
203
|
+
}
|
|
204
|
+
catch (error) {
|
|
205
|
+
console.error("❌ Error syncing YAML with deploy.json:", error);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* Syncs the server skills with the YAML configuration.
|
|
210
|
+
* Performs a two-way sync:
|
|
211
|
+
* 1. Deletes/deactivates skills from server that aren't in YAML
|
|
212
|
+
* 2. Updates YAML with active version numbers from server
|
|
213
|
+
*
|
|
214
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
215
|
+
* @returns Array of messages about sync operations
|
|
216
|
+
*/
|
|
217
|
+
export async function syncServerSkillsWithYaml(config) {
|
|
218
|
+
const messages = [];
|
|
219
|
+
let yamlNeedsUpdate = false;
|
|
220
|
+
try {
|
|
221
|
+
// Validate prerequisites
|
|
222
|
+
const apiKey = await loadApiKey();
|
|
223
|
+
if (!apiKey) {
|
|
224
|
+
console.warn("⚠️ No API key found. Skipping server sync.");
|
|
225
|
+
return messages;
|
|
226
|
+
}
|
|
227
|
+
const agentId = config?.agent?.agentId;
|
|
228
|
+
if (!agentId) {
|
|
229
|
+
console.warn("⚠️ No agent ID found in lua.skill.yaml. Skipping server sync.");
|
|
230
|
+
return messages;
|
|
231
|
+
}
|
|
232
|
+
// Get skills from server
|
|
233
|
+
const skillApi = new SkillApi(BASE_URLS.API, apiKey, agentId);
|
|
234
|
+
const serverSkillsResponse = await skillApi.getSkills();
|
|
235
|
+
if (!serverSkillsResponse.success || !serverSkillsResponse.data?.skills) {
|
|
236
|
+
console.warn("⚠️ Could not retrieve server skills. Skipping server sync.");
|
|
237
|
+
return messages;
|
|
238
|
+
}
|
|
239
|
+
const serverSkills = serverSkillsResponse.data.skills;
|
|
240
|
+
const yamlSkills = config?.skills || [];
|
|
241
|
+
// Create maps for efficient lookup
|
|
242
|
+
const yamlSkillsMap = new Map(yamlSkills
|
|
243
|
+
.filter((skill) => skill.skillId)
|
|
244
|
+
.map((skill) => [skill.skillId, skill]));
|
|
245
|
+
const serverSkillsMap = new Map(serverSkills.map(skill => [skill.id, skill]));
|
|
246
|
+
// Part 1: Delete skills from server that aren't in YAML
|
|
247
|
+
const skillsToDelete = serverSkills.filter(serverSkill => !yamlSkillsMap.has(serverSkill.id));
|
|
248
|
+
for (const skill of skillsToDelete) {
|
|
249
|
+
try {
|
|
250
|
+
const deleteResponse = await skillApi.deleteSkill(skill.id);
|
|
251
|
+
if (deleteResponse.success && deleteResponse.data) {
|
|
252
|
+
if (deleteResponse.data.deleted) {
|
|
253
|
+
const msg = `✅ Deleted skill "${skill.name}" from server`;
|
|
254
|
+
messages.push(msg);
|
|
255
|
+
console.log(msg);
|
|
256
|
+
}
|
|
257
|
+
else if (deleteResponse.data.deactivated) {
|
|
258
|
+
const msg = `⚠️ Skill "${skill.name}" has versions and cannot be deleted. It has been deactivated instead.`;
|
|
259
|
+
messages.push(msg);
|
|
260
|
+
console.warn(msg);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
const msg = `❌ Failed to delete skill "${skill.name}": ${deleteResponse.error?.message || 'Unknown error'}`;
|
|
265
|
+
messages.push(msg);
|
|
266
|
+
console.error(msg);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
catch (error) {
|
|
270
|
+
const msg = `❌ Error deleting skill "${skill.name}": ${error}`;
|
|
271
|
+
messages.push(msg);
|
|
272
|
+
console.error(msg);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
// Part 2: Sync version numbers from server to YAML
|
|
276
|
+
const updatedYamlSkills = yamlSkills.map((yamlSkill) => {
|
|
277
|
+
const serverSkill = serverSkillsMap.get(yamlSkill.skillId);
|
|
278
|
+
if (serverSkill && serverSkill.versions && serverSkill.versions.length > 0) {
|
|
279
|
+
// Find the active version on the server
|
|
280
|
+
const activeVersion = serverSkill.versions.find((v) => v.active);
|
|
281
|
+
if (activeVersion && activeVersion.version !== yamlSkill.version) {
|
|
282
|
+
const msg = `📝 Updated "${yamlSkill.name}" version in YAML: ${yamlSkill.version} → ${activeVersion.version}`;
|
|
283
|
+
messages.push(msg);
|
|
284
|
+
console.log(msg);
|
|
285
|
+
yamlNeedsUpdate = true;
|
|
286
|
+
return {
|
|
287
|
+
...yamlSkill,
|
|
288
|
+
version: activeVersion.version
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
return yamlSkill;
|
|
293
|
+
});
|
|
294
|
+
// Update YAML file if versions changed
|
|
295
|
+
if (yamlNeedsUpdate) {
|
|
296
|
+
await updateYamlWithSkills(updatedYamlSkills, config);
|
|
297
|
+
console.log("✅ YAML versions synced with server");
|
|
298
|
+
}
|
|
299
|
+
if (skillsToDelete.length === 0 && !yamlNeedsUpdate) {
|
|
300
|
+
console.log("✅ Server and YAML are fully in sync");
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
catch (error) {
|
|
304
|
+
console.error("❌ Error syncing server skills:", error);
|
|
305
|
+
}
|
|
306
|
+
return messages;
|
|
307
|
+
}
|
package/package.json
CHANGED