lua-cli 2.5.7 → 3.0.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.
- package/dist/api/agent.api.service.d.ts +45 -0
- package/dist/api/agent.api.service.js +54 -0
- package/dist/api/job.api.service.d.ts +210 -0
- package/dist/api/job.api.service.js +200 -0
- package/dist/api/lazy-instances.d.ts +24 -0
- package/dist/api/lazy-instances.js +48 -0
- package/dist/api/postprocessor.api.service.d.ts +98 -0
- package/dist/api/postprocessor.api.service.js +76 -0
- package/dist/api/preprocessor.api.service.d.ts +98 -0
- package/dist/api/preprocessor.api.service.js +76 -0
- package/dist/api/user.data.api.service.d.ts +28 -0
- package/dist/api/user.data.api.service.js +51 -0
- package/dist/api/webhook.api.service.d.ts +151 -0
- package/dist/api/webhook.api.service.js +134 -0
- package/dist/api-exports.d.ts +156 -41
- package/dist/api-exports.js +182 -21
- package/dist/cli/command-definitions.js +149 -7
- package/dist/commands/compile.js +124 -5
- package/dist/commands/completion.d.ts +11 -0
- package/dist/commands/completion.js +209 -0
- package/dist/commands/env.d.ts +3 -2
- package/dist/commands/env.js +42 -17
- package/dist/commands/features.d.ts +16 -0
- package/dist/commands/features.js +352 -0
- package/dist/commands/index.d.ts +7 -0
- package/dist/commands/index.js +7 -0
- package/dist/commands/init.js +53 -7
- package/dist/commands/jobs.d.ts +20 -0
- package/dist/commands/jobs.js +533 -0
- package/dist/commands/logs.js +2 -5
- package/dist/commands/persona.d.ts +3 -2
- package/dist/commands/persona.js +43 -18
- package/dist/commands/postprocessors.d.ts +8 -0
- package/dist/commands/postprocessors.js +431 -0
- package/dist/commands/preprocessors.d.ts +8 -0
- package/dist/commands/preprocessors.js +431 -0
- package/dist/commands/push.d.ts +9 -13
- package/dist/commands/push.js +937 -69
- package/dist/commands/skills.d.ts +16 -0
- package/dist/commands/skills.js +438 -0
- package/dist/commands/test.d.ts +9 -18
- package/dist/commands/test.js +558 -82
- package/dist/commands/webhooks.d.ts +18 -0
- package/dist/commands/webhooks.js +424 -0
- package/dist/common/data.entry.instance.d.ts +7 -0
- package/dist/common/data.entry.instance.js +15 -0
- package/dist/common/job.instance.d.ts +77 -0
- package/dist/common/job.instance.js +108 -0
- package/dist/common/order.instance.d.ts +6 -0
- package/dist/common/order.instance.js +14 -0
- package/dist/common/product.instance.d.ts +6 -0
- package/dist/common/product.instance.js +14 -0
- package/dist/common/user.instance.d.ts +15 -0
- package/dist/common/user.instance.js +38 -0
- package/dist/config/constants.d.ts +2 -2
- package/dist/config/constants.js +4 -4
- package/dist/index.js +14 -3
- package/dist/interfaces/agent.d.ts +33 -1
- package/dist/interfaces/chat.d.ts +22 -0
- package/dist/interfaces/index.d.ts +10 -0
- package/dist/interfaces/index.js +7 -0
- package/dist/interfaces/jobs.d.ts +172 -0
- package/dist/interfaces/jobs.js +5 -0
- package/dist/interfaces/message.d.ts +18 -0
- package/dist/interfaces/message.js +1 -0
- package/dist/interfaces/postprocessors.d.ts +35 -0
- package/dist/interfaces/postprocessors.js +4 -0
- package/dist/interfaces/preprocessors.d.ts +35 -0
- package/dist/interfaces/preprocessors.js +4 -0
- package/dist/interfaces/webhooks.d.ts +104 -0
- package/dist/interfaces/webhooks.js +5 -0
- package/dist/types/api-contracts.d.ts +14 -0
- package/dist/types/api-contracts.js +0 -7
- package/dist/types/compile.types.d.ts +49 -0
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.js +1 -1
- package/dist/types/skill.d.ts +502 -0
- package/dist/types/skill.js +477 -0
- package/dist/utils/agent-management.d.ts +25 -0
- package/dist/utils/agent-management.js +67 -0
- package/dist/utils/bundling.d.ts +31 -1
- package/dist/utils/bundling.js +653 -10
- package/dist/utils/compile.d.ts +63 -0
- package/dist/utils/compile.js +691 -36
- package/dist/utils/deployment.d.ts +2 -1
- package/dist/utils/deployment.js +16 -2
- package/dist/utils/init-agent.d.ts +3 -1
- package/dist/utils/init-agent.js +6 -4
- package/dist/utils/init-prompts.d.ts +2 -1
- package/dist/utils/init-prompts.js +14 -9
- package/dist/utils/job-management.d.ts +24 -0
- package/dist/utils/job-management.js +264 -0
- package/dist/utils/postprocessor-management.d.ts +9 -0
- package/dist/utils/postprocessor-management.js +118 -0
- package/dist/utils/preprocessor-management.d.ts +9 -0
- package/dist/utils/preprocessor-management.js +118 -0
- package/dist/utils/sandbox.d.ts +61 -1
- package/dist/utils/sandbox.js +283 -72
- package/dist/utils/tool-detection.d.ts +3 -2
- package/dist/utils/tool-detection.js +18 -4
- package/dist/utils/webhook-management.d.ts +24 -0
- package/dist/utils/webhook-management.js +256 -0
- package/dist/web/app.css +152 -736
- package/dist/web/app.js +45 -45
- package/package.json +2 -2
- package/template/AGENT_CONFIGURATION.md +251 -0
- package/template/COMPLEX_JOB_EXAMPLES.md +795 -0
- package/template/DYNAMIC_JOB_CREATION.md +371 -0
- package/template/README.md +30 -2
- package/template/WEBHOOKS_JOBS_QUICKSTART.md +318 -0
- package/template/WEBHOOK_JOB_EXAMPLES.md +817 -0
- package/template/package.json +1 -1
- package/template/src/index-agent-example.ts +201 -0
- package/template/src/index.ts +39 -0
- package/template/src/jobs/AbandonedBasketProcessorJob.ts +139 -0
- package/template/src/jobs/DailyCleanupJob.ts +100 -0
- package/template/src/jobs/DataMigrationJob.ts +133 -0
- package/template/src/jobs/HealthCheckJob.ts +87 -0
- package/template/src/postprocessors/ResponseFormatter.ts +151 -0
- package/template/src/preprocessors/MessageFilter.ts +91 -0
- package/template/src/tools/GameScoreTrackerTool.ts +356 -0
- package/template/src/tools/SmartBasketTool.ts +188 -0
- package/template/src/webhooks/PaymentWebhook.ts +113 -0
- package/template/src/webhooks/UserEventWebhook.ts +77 -0
|
@@ -21,5 +21,6 @@ export declare function createDeploymentData(tools: ToolInfo[], distDir: string)
|
|
|
21
21
|
* @param tools - Array of detected tools
|
|
22
22
|
* @param luaDir - Legacy .lua directory for output
|
|
23
23
|
* @param indexFile - The TypeScript source file for the index
|
|
24
|
+
* @param agentData - Optional resolved agent data from LuaAgent (for new approach)
|
|
24
25
|
*/
|
|
25
|
-
export declare function createLegacyDeploymentData(tools: ToolInfo[], luaDir: string, indexFile: TypeScriptSourceFile): Promise<void>;
|
|
26
|
+
export declare function createLegacyDeploymentData(tools: ToolInfo[], luaDir: string, indexFile: TypeScriptSourceFile, agentData?: any): Promise<void>;
|
package/dist/utils/deployment.js
CHANGED
|
@@ -52,10 +52,24 @@ function readPackageJson() {
|
|
|
52
52
|
* @param tools - Array of detected tools
|
|
53
53
|
* @param luaDir - Legacy .lua directory for output
|
|
54
54
|
* @param indexFile - The TypeScript source file for the index
|
|
55
|
+
* @param agentData - Optional resolved agent data from LuaAgent (for new approach)
|
|
55
56
|
*/
|
|
56
|
-
export async function createLegacyDeploymentData(tools, luaDir, indexFile) {
|
|
57
|
+
export async function createLegacyDeploymentData(tools, luaDir, indexFile, agentData) {
|
|
57
58
|
const config = readSkillConfig();
|
|
58
|
-
|
|
59
|
+
let skillsMetadata;
|
|
60
|
+
// Check if we have agent data (from LuaAgent approach)
|
|
61
|
+
if (agentData && agentData.skills && agentData.skills.length > 0) {
|
|
62
|
+
// Use skills from LuaAgent
|
|
63
|
+
// Map 'tools' to 'constructorTools' for compatibility with buildSkillsArray
|
|
64
|
+
skillsMetadata = agentData.skills.map((skill) => ({
|
|
65
|
+
...skill,
|
|
66
|
+
constructorTools: skill.tools || []
|
|
67
|
+
}));
|
|
68
|
+
}
|
|
69
|
+
else {
|
|
70
|
+
// Fall back to legacy approach - extract from index file
|
|
71
|
+
skillsMetadata = extractSkillsMetadata(indexFile);
|
|
72
|
+
}
|
|
59
73
|
// Map tools to their parent skills
|
|
60
74
|
const skillToTools = mapToolsToSkills(indexFile);
|
|
61
75
|
// Build skills array with their associated tools
|
|
@@ -28,10 +28,12 @@ export declare function selectBaseAgentType(agentTypes: AgentType[]): AgentType;
|
|
|
28
28
|
* @param businessConfig - Business configuration
|
|
29
29
|
* @param metadata - Agent metadata
|
|
30
30
|
* @param features - Feature configuration
|
|
31
|
+
* @param existingOrgId - Optional existing organization ID to use
|
|
32
|
+
* @param newOrgName - Optional new organization name (if not using existing)
|
|
31
33
|
* @returns Agent creation result with agent and org details
|
|
32
34
|
* @throws Error if agent creation fails
|
|
33
35
|
*/
|
|
34
|
-
export declare function createNewAgent(apiKey: string, agentType: AgentType, businessConfig: BusinessConfig, metadata: Record<string, any>, features: Record<string, boolean
|
|
36
|
+
export declare function createNewAgent(apiKey: string, agentType: AgentType, businessConfig: BusinessConfig, metadata: Record<string, any>, features: Record<string, boolean>, existingOrgId?: string, newOrgName?: string): Promise<AgentCreationResult>;
|
|
35
37
|
/**
|
|
36
38
|
* Fetches detailed agent information for an existing agent.
|
|
37
39
|
* Used when selecting an existing agent during init.
|
package/dist/utils/init-agent.js
CHANGED
|
@@ -50,10 +50,12 @@ export function selectBaseAgentType(agentTypes) {
|
|
|
50
50
|
* @param businessConfig - Business configuration
|
|
51
51
|
* @param metadata - Agent metadata
|
|
52
52
|
* @param features - Feature configuration
|
|
53
|
+
* @param existingOrgId - Optional existing organization ID to use
|
|
54
|
+
* @param newOrgName - Optional new organization name (if not using existing)
|
|
53
55
|
* @returns Agent creation result with agent and org details
|
|
54
56
|
* @throws Error if agent creation fails
|
|
55
57
|
*/
|
|
56
|
-
export async function createNewAgent(apiKey, agentType, businessConfig, metadata, features) {
|
|
58
|
+
export async function createNewAgent(apiKey, agentType, businessConfig, metadata, features, existingOrgId, newOrgName) {
|
|
57
59
|
writeProgress("🔄 Creating agent...");
|
|
58
60
|
const agentData = {
|
|
59
61
|
id: `agent_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
|
|
@@ -67,9 +69,9 @@ export async function createNewAgent(apiKey, agentType, businessConfig, metadata
|
|
|
67
69
|
},
|
|
68
70
|
features,
|
|
69
71
|
channels: [],
|
|
70
|
-
org:
|
|
71
|
-
|
|
72
|
-
|
|
72
|
+
org: existingOrgId
|
|
73
|
+
? { id: existingOrgId } // Use existing org
|
|
74
|
+
: { registeredName: newOrgName || businessConfig.businessName } // Create new org
|
|
73
75
|
};
|
|
74
76
|
const agentApi = new AgentApi(BASE_URLS.API, apiKey);
|
|
75
77
|
const createAgentResult = await agentApi.createAgent(agentData);
|
|
@@ -42,6 +42,7 @@ export declare function promptFeatureConfiguration(agentType: AgentType): Promis
|
|
|
42
42
|
* Prompts for business and agent configuration.
|
|
43
43
|
* Collects business name, agent name, type, personality, and traits.
|
|
44
44
|
*
|
|
45
|
+
* @param skipBusinessName - If true, skips business name prompt (for existing orgs)
|
|
45
46
|
* @returns Complete business configuration
|
|
46
47
|
*/
|
|
47
|
-
export declare function promptBusinessConfiguration(): Promise<BusinessConfig>;
|
|
48
|
+
export declare function promptBusinessConfiguration(skipBusinessName?: boolean): Promise<BusinessConfig>;
|
|
@@ -115,17 +115,22 @@ export async function promptFeatureConfiguration(agentType) {
|
|
|
115
115
|
* Prompts for business and agent configuration.
|
|
116
116
|
* Collects business name, agent name, type, personality, and traits.
|
|
117
117
|
*
|
|
118
|
+
* @param skipBusinessName - If true, skips business name prompt (for existing orgs)
|
|
118
119
|
* @returns Complete business configuration
|
|
119
120
|
*/
|
|
120
|
-
export async function promptBusinessConfiguration() {
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
121
|
+
export async function promptBusinessConfiguration(skipBusinessName = false) {
|
|
122
|
+
let businessName = DEFAULT_BUSINESS_NAME;
|
|
123
|
+
if (!skipBusinessName) {
|
|
124
|
+
const result = await inquirer.prompt([
|
|
125
|
+
{
|
|
126
|
+
type: "input",
|
|
127
|
+
name: "businessName",
|
|
128
|
+
message: "Enter business name:",
|
|
129
|
+
default: DEFAULT_BUSINESS_NAME
|
|
130
|
+
}
|
|
131
|
+
]);
|
|
132
|
+
businessName = result.businessName;
|
|
133
|
+
}
|
|
129
134
|
const { agentName } = await inquirer.prompt([
|
|
130
135
|
{
|
|
131
136
|
type: "input",
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Management Utilities
|
|
3
|
+
* Handles job creation via API and YAML configuration management
|
|
4
|
+
*/
|
|
5
|
+
import { SkillConfig } from '../types/compile.types.js';
|
|
6
|
+
/**
|
|
7
|
+
* Ensures all detected jobs exist in the YAML config with valid job IDs.
|
|
8
|
+
* If a job doesn't exist or has no ID, creates it via the API.
|
|
9
|
+
*
|
|
10
|
+
* @param jobsArray - Array of jobs detected from source code
|
|
11
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
12
|
+
* @returns Updated jobs array with valid job IDs
|
|
13
|
+
*/
|
|
14
|
+
export declare function ensureJobsExistInYaml(jobsArray: any[], config: SkillConfig): Promise<any[]>;
|
|
15
|
+
/**
|
|
16
|
+
* Syncs the server jobs with the YAML configuration.
|
|
17
|
+
* Performs a two-way sync:
|
|
18
|
+
* 1. Deletes/deactivates jobs from server that aren't in YAML
|
|
19
|
+
* 2. Updates YAML with active version numbers from server
|
|
20
|
+
*
|
|
21
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
22
|
+
* @returns Array of messages about sync operations
|
|
23
|
+
*/
|
|
24
|
+
export declare function syncServerJobsWithYaml(config: SkillConfig): Promise<string[]>;
|
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Job Management Utilities
|
|
3
|
+
* Handles job creation via API and YAML configuration management
|
|
4
|
+
*/
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
import yaml from "js-yaml";
|
|
8
|
+
import JobApi from '../api/job.api.service.js';
|
|
9
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
10
|
+
import { loadApiKey } from '../services/auth.js';
|
|
11
|
+
import { COMPILE_FILES, SKILL_DEFAULTS, YAML_FORMAT, } from '../config/compile.constants.js';
|
|
12
|
+
/**
|
|
13
|
+
* Ensures all detected jobs exist in the YAML config with valid job IDs.
|
|
14
|
+
* If a job doesn't exist or has no ID, creates it via the API.
|
|
15
|
+
*
|
|
16
|
+
* @param jobsArray - Array of jobs detected from source code
|
|
17
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
18
|
+
* @returns Updated jobs array with valid job IDs
|
|
19
|
+
*/
|
|
20
|
+
export async function ensureJobsExistInYaml(jobsArray, config) {
|
|
21
|
+
const updatedJobsArray = [];
|
|
22
|
+
let yamlUpdated = false;
|
|
23
|
+
const existingJobs = config?.jobs || [];
|
|
24
|
+
const existingJobsMap = createJobsMap(existingJobs);
|
|
25
|
+
// Process each detected job
|
|
26
|
+
for (const job of jobsArray) {
|
|
27
|
+
const existingJob = existingJobsMap.get(job.name);
|
|
28
|
+
if (existingJob && existingJob.jobId && existingJob.jobId !== '') {
|
|
29
|
+
// Job exists with valid jobId - reuse it
|
|
30
|
+
updatedJobsArray.push({
|
|
31
|
+
...job,
|
|
32
|
+
jobId: existingJob.jobId
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Job doesn't exist or missing jobId - create via API
|
|
37
|
+
const createdJob = await createJobViaApi(job, config, existingJobs, existingJob);
|
|
38
|
+
updatedJobsArray.push(createdJob);
|
|
39
|
+
yamlUpdated = true;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Update YAML file if any changes were made
|
|
43
|
+
if (yamlUpdated) {
|
|
44
|
+
await updateYamlWithJobs(config);
|
|
45
|
+
}
|
|
46
|
+
return updatedJobsArray;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Creates a map of existing jobs for quick lookup by name.
|
|
50
|
+
*
|
|
51
|
+
* @param existingJobs - Array of jobs from YAML config
|
|
52
|
+
* @returns Map of job names to job objects
|
|
53
|
+
*/
|
|
54
|
+
function createJobsMap(existingJobs) {
|
|
55
|
+
const map = new Map();
|
|
56
|
+
existingJobs.forEach((job) => {
|
|
57
|
+
map.set(job.name, job);
|
|
58
|
+
});
|
|
59
|
+
return map;
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Creates a new job via the Lua API and updates the config.
|
|
63
|
+
*
|
|
64
|
+
* @param job - The job to create
|
|
65
|
+
* @param config - The skill configuration
|
|
66
|
+
* @param existingJobs - Array of existing jobs (mutated)
|
|
67
|
+
* @param existingJob - The existing job entry if one exists (may be without ID)
|
|
68
|
+
* @returns The job with its new ID
|
|
69
|
+
*/
|
|
70
|
+
async function createJobViaApi(job, config, existingJobs, existingJob) {
|
|
71
|
+
try {
|
|
72
|
+
// Validate prerequisites
|
|
73
|
+
const apiKey = await loadApiKey();
|
|
74
|
+
if (!apiKey) {
|
|
75
|
+
throw new Error("No API key found. Run 'lua auth configure' first.");
|
|
76
|
+
}
|
|
77
|
+
const agentId = config?.agent?.agentId;
|
|
78
|
+
if (!agentId) {
|
|
79
|
+
throw new Error("No agent ID found in lua.skill.yaml. Run 'lua init' first.");
|
|
80
|
+
}
|
|
81
|
+
// Create job via API
|
|
82
|
+
const jobPayload = {
|
|
83
|
+
name: job.name,
|
|
84
|
+
description: job.description || `A Lua job for ${job.name}`,
|
|
85
|
+
context: job.context || '',
|
|
86
|
+
schedule: job.schedule || { type: 'cron', expression: '0 0 * * *' },
|
|
87
|
+
timeout: job.timeout,
|
|
88
|
+
retry: job.retry,
|
|
89
|
+
metadata: job.metadata
|
|
90
|
+
};
|
|
91
|
+
const jobApi = new JobApi(BASE_URLS.API, apiKey, agentId);
|
|
92
|
+
const result = await jobApi.createJob(jobPayload);
|
|
93
|
+
if (result.success && result.data && result.data.id) {
|
|
94
|
+
const newJobId = result.data.id;
|
|
95
|
+
// Update YAML config with new job ID
|
|
96
|
+
if (!existingJob) {
|
|
97
|
+
existingJobs.push({
|
|
98
|
+
name: job.name || '',
|
|
99
|
+
version: job.version || SKILL_DEFAULTS.VERSION,
|
|
100
|
+
jobId: newJobId,
|
|
101
|
+
schedule: job.schedule
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
else {
|
|
105
|
+
existingJob.jobId = newJobId;
|
|
106
|
+
existingJob.schedule = job.schedule;
|
|
107
|
+
}
|
|
108
|
+
// Add jobs to config if not already present
|
|
109
|
+
if (!config.jobs) {
|
|
110
|
+
config.jobs = existingJobs;
|
|
111
|
+
}
|
|
112
|
+
return {
|
|
113
|
+
...job,
|
|
114
|
+
jobId: newJobId
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
else {
|
|
118
|
+
console.error(`❌ Failed to create job ${job.name}:`, result.error);
|
|
119
|
+
throw new Error(result.error?.message || 'Failed to create job - no ID returned from API');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
console.error(`❌ Failed to create job ${job.name}:`, error);
|
|
124
|
+
throw error;
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Updates the lua.skill.yaml file with the current jobs array.
|
|
129
|
+
* Ensures no undefined values are written to the YAML file.
|
|
130
|
+
*
|
|
131
|
+
* @param config - Current skill configuration to merge with
|
|
132
|
+
*/
|
|
133
|
+
async function updateYamlWithJobs(config) {
|
|
134
|
+
const jobs = config?.jobs || [];
|
|
135
|
+
// Clean jobs array to ensure no undefined values
|
|
136
|
+
const cleanedJobs = jobs.map(job => ({
|
|
137
|
+
name: job.name || '',
|
|
138
|
+
version: job.version || SKILL_DEFAULTS.VERSION,
|
|
139
|
+
jobId: job.jobId || '',
|
|
140
|
+
schedule: job.schedule || { type: 'cron', expression: '0 0 * * *' }
|
|
141
|
+
}));
|
|
142
|
+
// Update config with cleaned jobs array
|
|
143
|
+
const updatedConfig = {
|
|
144
|
+
...config,
|
|
145
|
+
jobs: cleanedJobs
|
|
146
|
+
};
|
|
147
|
+
// Write updated YAML with consistent formatting
|
|
148
|
+
const yamlPath = path.join(process.cwd(), COMPILE_FILES.LUA_SKILL_YAML);
|
|
149
|
+
const yamlContent = yaml.dump(updatedConfig, {
|
|
150
|
+
indent: YAML_FORMAT.INDENT,
|
|
151
|
+
lineWidth: YAML_FORMAT.LINE_WIDTH,
|
|
152
|
+
noRefs: YAML_FORMAT.NO_REFS,
|
|
153
|
+
replacer: (key, value) => {
|
|
154
|
+
// Replace undefined values with empty strings
|
|
155
|
+
return value === undefined ? '' : value;
|
|
156
|
+
}
|
|
157
|
+
});
|
|
158
|
+
fs.writeFileSync(yamlPath, yamlContent);
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Syncs the server jobs with the YAML configuration.
|
|
162
|
+
* Performs a two-way sync:
|
|
163
|
+
* 1. Deletes/deactivates jobs from server that aren't in YAML
|
|
164
|
+
* 2. Updates YAML with active version numbers from server
|
|
165
|
+
*
|
|
166
|
+
* @param config - The skill configuration from lua.skill.yaml
|
|
167
|
+
* @returns Array of messages about sync operations
|
|
168
|
+
*/
|
|
169
|
+
export async function syncServerJobsWithYaml(config) {
|
|
170
|
+
const messages = [];
|
|
171
|
+
let yamlNeedsUpdate = false;
|
|
172
|
+
try {
|
|
173
|
+
// Validate prerequisites
|
|
174
|
+
const apiKey = await loadApiKey();
|
|
175
|
+
if (!apiKey) {
|
|
176
|
+
console.warn("⚠️ No API key found. Skipping server job sync.");
|
|
177
|
+
return messages;
|
|
178
|
+
}
|
|
179
|
+
const agentId = config?.agent?.agentId;
|
|
180
|
+
if (!agentId) {
|
|
181
|
+
console.warn("⚠️ No agent ID found in lua.skill.yaml. Skipping server job sync.");
|
|
182
|
+
return messages;
|
|
183
|
+
}
|
|
184
|
+
// Get jobs from server
|
|
185
|
+
const jobApi = new JobApi(BASE_URLS.API, apiKey, agentId);
|
|
186
|
+
const serverJobsResponse = await jobApi.getJobs();
|
|
187
|
+
if (!serverJobsResponse.success || !serverJobsResponse.data?.jobs) {
|
|
188
|
+
console.warn("⚠️ Could not retrieve server jobs. Skipping server job sync.");
|
|
189
|
+
return messages;
|
|
190
|
+
}
|
|
191
|
+
const serverJobs = serverJobsResponse.data.jobs;
|
|
192
|
+
const yamlJobs = config?.jobs || [];
|
|
193
|
+
// Create maps for efficient lookup
|
|
194
|
+
const yamlJobsMap = new Map(yamlJobs
|
|
195
|
+
.filter((job) => job.jobId)
|
|
196
|
+
.map((job) => [job.jobId, job]));
|
|
197
|
+
const serverJobsMap = new Map(serverJobs.map(job => [job.id, job]));
|
|
198
|
+
// Part 1: Delete jobs from server that aren't in YAML
|
|
199
|
+
const jobsToDelete = serverJobs.filter(serverJob => !yamlJobsMap.has(serverJob.id));
|
|
200
|
+
for (const job of jobsToDelete) {
|
|
201
|
+
try {
|
|
202
|
+
const deleteResponse = await jobApi.deleteJob(job.id);
|
|
203
|
+
if (deleteResponse.success && deleteResponse.data) {
|
|
204
|
+
if (deleteResponse.data.deleted) {
|
|
205
|
+
const msg = `✅ Deleted job "${job.name}" from server`;
|
|
206
|
+
messages.push(msg);
|
|
207
|
+
console.log(msg);
|
|
208
|
+
}
|
|
209
|
+
else if (deleteResponse.data.deactivated) {
|
|
210
|
+
const msg = `⚠️ Job "${job.name}" has versions and cannot be deleted. It has been deactivated instead.`;
|
|
211
|
+
messages.push(msg);
|
|
212
|
+
console.warn(msg);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
const msg = `❌ Failed to delete job "${job.name}": ${deleteResponse.error?.message || 'Unknown error'}`;
|
|
217
|
+
messages.push(msg);
|
|
218
|
+
console.error(msg);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
const msg = `❌ Error deleting job "${job.name}": ${error}`;
|
|
223
|
+
messages.push(msg);
|
|
224
|
+
console.error(msg);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
// Part 2: Sync version numbers from server to YAML
|
|
228
|
+
const updatedYamlJobs = yamlJobs.map((yamlJob) => {
|
|
229
|
+
const serverJob = serverJobsMap.get(yamlJob.jobId);
|
|
230
|
+
if (serverJob && serverJob.versions && serverJob.versions.length > 0) {
|
|
231
|
+
// Find the active version on the server
|
|
232
|
+
const activeVersion = serverJob.versions.find((v) => v.isActive);
|
|
233
|
+
if (activeVersion && activeVersion.version !== yamlJob.version) {
|
|
234
|
+
const msg = `📝 Updated "${yamlJob.name}" job version in YAML: ${yamlJob.version} → ${activeVersion.version}`;
|
|
235
|
+
messages.push(msg);
|
|
236
|
+
console.log(msg);
|
|
237
|
+
yamlNeedsUpdate = true;
|
|
238
|
+
return {
|
|
239
|
+
...yamlJob,
|
|
240
|
+
version: activeVersion.version,
|
|
241
|
+
schedule: activeVersion.schedule || yamlJob.schedule
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return yamlJob;
|
|
246
|
+
});
|
|
247
|
+
// Update YAML file if versions changed
|
|
248
|
+
if (yamlNeedsUpdate) {
|
|
249
|
+
const updatedConfig = {
|
|
250
|
+
...config,
|
|
251
|
+
jobs: updatedYamlJobs
|
|
252
|
+
};
|
|
253
|
+
await updateYamlWithJobs(updatedConfig);
|
|
254
|
+
console.log("✅ YAML job versions synced with server");
|
|
255
|
+
}
|
|
256
|
+
if (jobsToDelete.length === 0 && !yamlNeedsUpdate) {
|
|
257
|
+
console.log("✅ Server jobs and YAML are fully in sync");
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
catch (error) {
|
|
261
|
+
console.error("❌ Error syncing server jobs:", error);
|
|
262
|
+
}
|
|
263
|
+
return messages;
|
|
264
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostProcessor Management Utilities
|
|
3
|
+
*/
|
|
4
|
+
import { SkillConfig } from '../types/compile.types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ensures all detected postprocessors exist in the YAML config with valid IDs.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ensurePostProcessorsExistInYaml(postprocessorsArray: any[], config: SkillConfig): Promise<any[]>;
|
|
9
|
+
export declare function syncServerPostProcessorsWithYaml(config: SkillConfig): Promise<string[]>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PostProcessor Management Utilities
|
|
3
|
+
*/
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import PostProcessorApi from '../api/postprocessor.api.service.js';
|
|
8
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
9
|
+
import { loadApiKey } from '../services/auth.js';
|
|
10
|
+
import { SKILL_DEFAULTS, YAML_FORMAT } from '../config/compile.constants.js';
|
|
11
|
+
/**
|
|
12
|
+
* Ensures all detected postprocessors exist in the YAML config with valid IDs.
|
|
13
|
+
*/
|
|
14
|
+
export async function ensurePostProcessorsExistInYaml(postprocessorsArray, config) {
|
|
15
|
+
const updatedPostProcessorsArray = [];
|
|
16
|
+
let yamlUpdated = false;
|
|
17
|
+
const existingPostProcessors = config?.postprocessors || [];
|
|
18
|
+
const existingMap = new Map(existingPostProcessors.map((p) => [p.name, p]));
|
|
19
|
+
for (const postprocessor of postprocessorsArray) {
|
|
20
|
+
const existing = existingMap.get(postprocessor.name);
|
|
21
|
+
if (existing && existing.postprocessorId) {
|
|
22
|
+
updatedPostProcessorsArray.push({
|
|
23
|
+
...postprocessor,
|
|
24
|
+
postprocessorId: existing.postprocessorId
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const created = await createPostProcessorViaApi(postprocessor, config, existingPostProcessors, existing);
|
|
29
|
+
updatedPostProcessorsArray.push(created);
|
|
30
|
+
yamlUpdated = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (yamlUpdated) {
|
|
34
|
+
await updateYamlWithPostProcessors(config);
|
|
35
|
+
}
|
|
36
|
+
return updatedPostProcessorsArray;
|
|
37
|
+
}
|
|
38
|
+
async function createPostProcessorViaApi(postprocessor, config, existingPostProcessors, existingPostProcessor) {
|
|
39
|
+
try {
|
|
40
|
+
const apiKey = await loadApiKey();
|
|
41
|
+
if (!apiKey)
|
|
42
|
+
throw new Error("No API key found. Run 'lua auth configure' first.");
|
|
43
|
+
const agentId = config?.agent?.agentId;
|
|
44
|
+
if (!agentId)
|
|
45
|
+
throw new Error("No agent ID found in lua.skill.yaml. Run 'lua init' first.");
|
|
46
|
+
const payload = {
|
|
47
|
+
name: postprocessor.name,
|
|
48
|
+
description: postprocessor.description || `A Lua postprocessor for ${postprocessor.name}`,
|
|
49
|
+
context: postprocessor.context || ''
|
|
50
|
+
};
|
|
51
|
+
const api = new PostProcessorApi(BASE_URLS.API, apiKey, agentId);
|
|
52
|
+
const result = await api.createPostProcessor(payload);
|
|
53
|
+
if (result.success && result.data && result.data.id) {
|
|
54
|
+
const newId = result.data.id;
|
|
55
|
+
if (!existingPostProcessor) {
|
|
56
|
+
existingPostProcessors.push({
|
|
57
|
+
name: postprocessor.name || '',
|
|
58
|
+
version: postprocessor.version || SKILL_DEFAULTS.VERSION,
|
|
59
|
+
postprocessorId: newId
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
existingPostProcessor.postprocessorId = newId;
|
|
64
|
+
}
|
|
65
|
+
if (!config.postprocessors) {
|
|
66
|
+
config.postprocessors = existingPostProcessors;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...postprocessor,
|
|
70
|
+
postprocessorId: newId
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw new Error(result.error?.message || "Failed to create postprocessor");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.warn(`Warning: Could not create postprocessor ${postprocessor.name}:`, error);
|
|
79
|
+
return postprocessor;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function updateYamlWithPostProcessors(config) {
|
|
83
|
+
const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
84
|
+
const yamlContent = yaml.dump(config, { ...YAML_FORMAT, sortKeys: (a, b) => {
|
|
85
|
+
const order = ['agent', 'skills', 'webhooks', 'jobs', 'preprocessors', 'postprocessors', 'skill'];
|
|
86
|
+
const aIndex = order.indexOf(a);
|
|
87
|
+
const bIndex = order.indexOf(b);
|
|
88
|
+
if (aIndex !== -1 && bIndex !== -1)
|
|
89
|
+
return aIndex - bIndex;
|
|
90
|
+
if (aIndex !== -1)
|
|
91
|
+
return -1;
|
|
92
|
+
if (bIndex !== -1)
|
|
93
|
+
return 1;
|
|
94
|
+
return a.localeCompare(b);
|
|
95
|
+
} });
|
|
96
|
+
fs.writeFileSync(yamlPath, yamlContent);
|
|
97
|
+
}
|
|
98
|
+
export async function syncServerPostProcessorsWithYaml(config) {
|
|
99
|
+
const messages = [];
|
|
100
|
+
try {
|
|
101
|
+
const apiKey = await loadApiKey();
|
|
102
|
+
if (!apiKey) {
|
|
103
|
+
console.warn("⚠️ No API key found. Skipping server postprocessor sync.");
|
|
104
|
+
return messages;
|
|
105
|
+
}
|
|
106
|
+
const agentId = config?.agent?.agentId;
|
|
107
|
+
if (!agentId) {
|
|
108
|
+
console.warn("⚠️ No agent ID found. Skipping server postprocessor sync.");
|
|
109
|
+
return messages;
|
|
110
|
+
}
|
|
111
|
+
// Server sync will be implemented when backend is ready
|
|
112
|
+
return messages;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.warn("⚠️ Error syncing postprocessors:", error);
|
|
116
|
+
return messages;
|
|
117
|
+
}
|
|
118
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PreProcessor Management Utilities
|
|
3
|
+
*/
|
|
4
|
+
import { SkillConfig } from '../types/compile.types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ensures all detected preprocessors exist in the YAML config with valid IDs.
|
|
7
|
+
*/
|
|
8
|
+
export declare function ensurePreProcessorsExistInYaml(preprocessorsArray: any[], config: SkillConfig): Promise<any[]>;
|
|
9
|
+
export declare function syncServerPreProcessorsWithYaml(config: SkillConfig): Promise<string[]>;
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PreProcessor Management Utilities
|
|
3
|
+
*/
|
|
4
|
+
import fs from "fs";
|
|
5
|
+
import path from "path";
|
|
6
|
+
import yaml from "js-yaml";
|
|
7
|
+
import PreProcessorApi from '../api/preprocessor.api.service.js';
|
|
8
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
9
|
+
import { loadApiKey } from '../services/auth.js';
|
|
10
|
+
import { SKILL_DEFAULTS, YAML_FORMAT } from '../config/compile.constants.js';
|
|
11
|
+
/**
|
|
12
|
+
* Ensures all detected preprocessors exist in the YAML config with valid IDs.
|
|
13
|
+
*/
|
|
14
|
+
export async function ensurePreProcessorsExistInYaml(preprocessorsArray, config) {
|
|
15
|
+
const updatedPreProcessorsArray = [];
|
|
16
|
+
let yamlUpdated = false;
|
|
17
|
+
const existingPreProcessors = config?.preprocessors || [];
|
|
18
|
+
const existingMap = new Map(existingPreProcessors.map((p) => [p.name, p]));
|
|
19
|
+
for (const preprocessor of preprocessorsArray) {
|
|
20
|
+
const existing = existingMap.get(preprocessor.name);
|
|
21
|
+
if (existing && existing.preprocessorId) {
|
|
22
|
+
updatedPreProcessorsArray.push({
|
|
23
|
+
...preprocessor,
|
|
24
|
+
preprocessorId: existing.preprocessorId
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const created = await createPreProcessorViaApi(preprocessor, config, existingPreProcessors, existing);
|
|
29
|
+
updatedPreProcessorsArray.push(created);
|
|
30
|
+
yamlUpdated = true;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (yamlUpdated) {
|
|
34
|
+
await updateYamlWithPreProcessors(config);
|
|
35
|
+
}
|
|
36
|
+
return updatedPreProcessorsArray;
|
|
37
|
+
}
|
|
38
|
+
async function createPreProcessorViaApi(preprocessor, config, existingPreProcessors, existingPreProcessor) {
|
|
39
|
+
try {
|
|
40
|
+
const apiKey = await loadApiKey();
|
|
41
|
+
if (!apiKey)
|
|
42
|
+
throw new Error("No API key found. Run 'lua auth configure' first.");
|
|
43
|
+
const agentId = config?.agent?.agentId;
|
|
44
|
+
if (!agentId)
|
|
45
|
+
throw new Error("No agent ID found in lua.skill.yaml. Run 'lua init' first.");
|
|
46
|
+
const payload = {
|
|
47
|
+
name: preprocessor.name,
|
|
48
|
+
description: preprocessor.description || `A Lua preprocessor for ${preprocessor.name}`,
|
|
49
|
+
context: preprocessor.context || ''
|
|
50
|
+
};
|
|
51
|
+
const api = new PreProcessorApi(BASE_URLS.API, apiKey, agentId);
|
|
52
|
+
const result = await api.createPreProcessor(payload);
|
|
53
|
+
if (result.success && result.data && result.data.id) {
|
|
54
|
+
const newId = result.data.id;
|
|
55
|
+
if (!existingPreProcessor) {
|
|
56
|
+
existingPreProcessors.push({
|
|
57
|
+
name: preprocessor.name || '',
|
|
58
|
+
version: preprocessor.version || SKILL_DEFAULTS.VERSION,
|
|
59
|
+
preprocessorId: newId
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
existingPreProcessor.preprocessorId = newId;
|
|
64
|
+
}
|
|
65
|
+
if (!config.preprocessors) {
|
|
66
|
+
config.preprocessors = existingPreProcessors;
|
|
67
|
+
}
|
|
68
|
+
return {
|
|
69
|
+
...preprocessor,
|
|
70
|
+
preprocessorId: newId
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
throw new Error(result.error?.message || "Failed to create preprocessor");
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (error) {
|
|
78
|
+
console.warn(`Warning: Could not create preprocessor ${preprocessor.name}:`, error);
|
|
79
|
+
return preprocessor;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
async function updateYamlWithPreProcessors(config) {
|
|
83
|
+
const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
84
|
+
const yamlContent = yaml.dump(config, { ...YAML_FORMAT, sortKeys: (a, b) => {
|
|
85
|
+
const order = ['agent', 'skills', 'webhooks', 'jobs', 'preprocessors', 'postprocessors', 'skill'];
|
|
86
|
+
const aIndex = order.indexOf(a);
|
|
87
|
+
const bIndex = order.indexOf(b);
|
|
88
|
+
if (aIndex !== -1 && bIndex !== -1)
|
|
89
|
+
return aIndex - bIndex;
|
|
90
|
+
if (aIndex !== -1)
|
|
91
|
+
return -1;
|
|
92
|
+
if (bIndex !== -1)
|
|
93
|
+
return 1;
|
|
94
|
+
return a.localeCompare(b);
|
|
95
|
+
} });
|
|
96
|
+
fs.writeFileSync(yamlPath, yamlContent);
|
|
97
|
+
}
|
|
98
|
+
export async function syncServerPreProcessorsWithYaml(config) {
|
|
99
|
+
const messages = [];
|
|
100
|
+
try {
|
|
101
|
+
const apiKey = await loadApiKey();
|
|
102
|
+
if (!apiKey) {
|
|
103
|
+
console.warn("⚠️ No API key found. Skipping server preprocessor sync.");
|
|
104
|
+
return messages;
|
|
105
|
+
}
|
|
106
|
+
const agentId = config?.agent?.agentId;
|
|
107
|
+
if (!agentId) {
|
|
108
|
+
console.warn("⚠️ No agent ID found. Skipping server preprocessor sync.");
|
|
109
|
+
return messages;
|
|
110
|
+
}
|
|
111
|
+
// Server sync will be implemented when backend is ready
|
|
112
|
+
return messages;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.warn("⚠️ Error syncing preprocessors:", error);
|
|
116
|
+
return messages;
|
|
117
|
+
}
|
|
118
|
+
}
|