lua-cli 3.1.0-alpha.3 ā 3.1.0-alpha.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/README.md +0 -4
- package/dist/api/cdn.api.service.d.ts +18 -0
- package/dist/api/cdn.api.service.js +43 -0
- package/dist/api/custom.data.api.service.d.ts +4 -3
- package/dist/api/custom.data.api.service.js +4 -3
- package/dist/api/developer.api.service.d.ts +54 -1
- package/dist/api/developer.api.service.js +89 -0
- package/dist/api/job.api.service.d.ts +33 -100
- package/dist/api/job.api.service.js +27 -11
- package/dist/api/lazy-instances.d.ts +16 -0
- package/dist/api/lazy-instances.js +32 -0
- package/dist/api/postprocessor.api.service.d.ts +3 -13
- package/dist/api/postprocessor.api.service.js +2 -4
- package/dist/api/preprocessor.api.service.d.ts +1 -8
- package/dist/api/preprocessor.api.service.js +1 -2
- package/dist/api/webhook.api.service.d.ts +1 -3
- package/dist/api/webhook.api.service.js +1 -1
- package/dist/api/whatsapp-templates.api.service.d.ts +40 -0
- package/dist/api/whatsapp-templates.api.service.js +78 -0
- package/dist/api-exports.d.ts +153 -6
- package/dist/api-exports.js +177 -21
- package/dist/cli/command-definitions.js +34 -7
- package/dist/commands/admin.js +1 -1
- package/dist/commands/channels.js +1 -1
- package/dist/commands/chat.js +2 -4
- package/dist/commands/compile.js +23 -4
- package/dist/commands/evals.d.ts +8 -0
- package/dist/commands/evals.js +41 -0
- package/dist/commands/index.d.ts +2 -0
- package/dist/commands/index.js +2 -0
- package/dist/commands/init.d.ts +10 -1
- package/dist/commands/init.js +23 -46
- package/dist/commands/jobs.js +5 -5
- package/dist/commands/mcp.d.ts +18 -0
- package/dist/commands/mcp.js +393 -0
- package/dist/commands/push.js +174 -23
- package/dist/common/data.entry.instance.d.ts +1 -1
- package/dist/common/data.entry.instance.js +4 -4
- package/dist/common/job.instance.d.ts +59 -7
- package/dist/common/job.instance.js +84 -19
- package/dist/config/constants.d.ts +1 -0
- package/dist/config/constants.js +1 -0
- package/dist/index.js +1 -0
- package/dist/interfaces/agent.d.ts +0 -3
- package/dist/interfaces/cdn.d.ts +24 -0
- package/dist/interfaces/cdn.js +5 -0
- package/dist/interfaces/compile.d.ts +1 -0
- package/dist/interfaces/custom.data.d.ts +3 -3
- package/dist/interfaces/index.d.ts +2 -1
- package/dist/interfaces/init.d.ts +0 -1
- package/dist/interfaces/jobs.d.ts +88 -132
- package/dist/interfaces/jobs.js +1 -1
- package/dist/interfaces/mcp.d.ts +64 -0
- package/dist/interfaces/mcp.js +5 -0
- package/dist/interfaces/postprocessors.d.ts +0 -3
- package/dist/interfaces/preprocessors.d.ts +0 -3
- package/dist/interfaces/webhooks.d.ts +0 -5
- package/dist/interfaces/whatsapp-templates.d.ts +104 -0
- package/dist/interfaces/whatsapp-templates.js +5 -0
- package/dist/types/api-contracts.d.ts +68 -14
- package/dist/types/compile.types.d.ts +5 -6
- package/dist/types/index.d.ts +2 -2
- package/dist/types/index.js +3 -1
- package/dist/types/skill.d.ts +181 -103
- package/dist/types/skill.js +123 -91
- package/dist/utils/agent-management.d.ts +3 -5
- package/dist/utils/agent-management.js +6 -8
- package/dist/utils/bundling.d.ts +4 -11
- package/dist/utils/bundling.js +24 -33
- package/dist/utils/compile.d.ts +17 -9
- package/dist/utils/compile.js +72 -88
- package/dist/utils/deployment.js +13 -7
- package/dist/utils/dev-api.js +1 -4
- package/dist/utils/dev-server.js +1 -1
- package/dist/utils/files.d.ts +11 -4
- package/dist/utils/files.js +17 -14
- package/dist/utils/init-agent.d.ts +1 -2
- package/dist/utils/init-agent.js +4 -6
- package/dist/utils/init-helpers.d.ts +4 -4
- package/dist/utils/init-helpers.js +10 -11
- package/dist/utils/job-management.js +0 -2
- package/dist/utils/mcp-server-management.d.ts +23 -0
- package/dist/utils/mcp-server-management.js +212 -0
- package/dist/utils/postprocessor-management.js +2 -4
- package/dist/utils/preprocessor-management.js +2 -4
- package/dist/utils/sandbox.d.ts +4 -2
- package/dist/utils/sandbox.js +38 -9
- package/dist/utils/webhook-management.js +1 -3
- package/dist/web/app.css +1505 -14
- package/dist/web/app.js +79 -64
- package/package.json +2 -6
- package/template/QUICKSTART.md +57 -774
- package/template/README.md +80 -907
- package/template/examples/README.md +106 -0
- package/template/{src ā examples}/jobs/AbandonedBasketProcessorJob.ts +67 -14
- package/template/{src ā examples}/jobs/DailyCleanupJob.ts +0 -3
- package/template/{src ā examples}/jobs/DataMigrationJob.ts +0 -3
- package/template/{src ā examples}/jobs/HealthCheckJob.ts +0 -3
- package/template/{src ā examples}/postprocessors/modifyResponse.ts +3 -4
- package/template/examples/preprocessors/messageMatching.ts +35 -0
- package/template/{src ā examples}/skills/basket.skill.ts +0 -1
- package/template/{src ā examples}/skills/product.skill.ts +0 -1
- package/template/{src ā examples}/skills/tools/GameScoreTrackerTool.ts +11 -15
- package/template/{src ā examples}/skills/tools/OrderTool.ts +25 -0
- package/template/examples/skills/tools/PremiumFeatureTool.ts +98 -0
- package/template/{src ā examples}/skills/tools/UserDataTool.ts +34 -0
- package/template/{src ā examples}/skills/user.skill.ts +0 -1
- package/template/examples/webhooks/FileUploadWebhook.ts +86 -0
- package/template/{src ā examples}/webhooks/PaymentWebhook.ts +12 -9
- package/template/examples/webhooks/UserEventWebhook.ts +105 -0
- package/template/package-lock.json +7895 -0
- package/template/package.json +1 -1
- package/template/src/index.ts +40 -22
- package/template/src/preprocessors/messageMatching.ts +0 -22
- package/template/src/webhooks/UserEventWebhook.ts +0 -77
- /package/template/{src ā examples}/services/ApiService.ts +0 -0
- /package/template/{src ā examples}/services/GetWeather.ts +0 -0
- /package/template/{src ā examples}/skills/tools/BasketTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/CreateInlineJob.ts +0 -0
- /package/template/{src ā examples}/skills/tools/CreatePostTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/CustomDataTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/GetWeatherTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/PaymentTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/ProductsTool.ts +0 -0
- /package/template/{src ā examples}/skills/tools/SmartBasketTool.ts +0 -0
package/dist/commands/init.js
CHANGED
|
@@ -29,10 +29,13 @@ import { readSkillYaml, updateYamlAgent } from "../utils/files.js";
|
|
|
29
29
|
* - Feature configuration
|
|
30
30
|
* - Automatic project scaffolding
|
|
31
31
|
* - Dependency installation
|
|
32
|
+
* - Optional example code with --with-examples flag
|
|
32
33
|
*
|
|
34
|
+
* @param options - Command options including --with-examples
|
|
33
35
|
* @returns Promise that resolves when initialization is complete
|
|
34
36
|
*/
|
|
35
|
-
export async function initCommand() {
|
|
37
|
+
export async function initCommand(options = {}) {
|
|
38
|
+
const withExamples = options.withExamples ?? false;
|
|
36
39
|
return withErrorHandling(async () => {
|
|
37
40
|
// Step 1: Authenticate
|
|
38
41
|
const apiKey = await loadApiKey();
|
|
@@ -111,7 +114,6 @@ export async function initCommand() {
|
|
|
111
114
|
let selectedAgent;
|
|
112
115
|
let selectedOrg;
|
|
113
116
|
let persona;
|
|
114
|
-
let welcomeMessage;
|
|
115
117
|
let skipProjectInit = false;
|
|
116
118
|
if (agentChoice === "existing") {
|
|
117
119
|
// Step 4a: Select existing agent
|
|
@@ -119,7 +121,6 @@ export async function initCommand() {
|
|
|
119
121
|
selectedAgent = result.agent;
|
|
120
122
|
selectedOrg = result.org;
|
|
121
123
|
persona = result.persona;
|
|
122
|
-
welcomeMessage = result.welcomeMessage;
|
|
123
124
|
}
|
|
124
125
|
else {
|
|
125
126
|
// Step 4b: Create new agent
|
|
@@ -127,35 +128,41 @@ export async function initCommand() {
|
|
|
127
128
|
selectedAgent = result.agent;
|
|
128
129
|
selectedOrg = result.org;
|
|
129
130
|
persona = result.persona;
|
|
130
|
-
welcomeMessage = result.welcomeMessage;
|
|
131
131
|
}
|
|
132
132
|
// Step 5: Initialize or update project
|
|
133
133
|
if (yamlExists) {
|
|
134
134
|
// Update existing YAML and LuaAgent in index.ts
|
|
135
135
|
writeInfo("š Updating existing lua.skill.yaml with new agent...");
|
|
136
|
-
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, persona
|
|
136
|
+
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, persona);
|
|
137
137
|
// Also update LuaAgent in index.ts if it exists
|
|
138
138
|
const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
|
|
139
|
-
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, persona
|
|
139
|
+
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, persona);
|
|
140
140
|
writeSuccess("ā
lua.skill.yaml updated successfully!");
|
|
141
141
|
writeSuccess("ā
LuaAgent configuration updated!");
|
|
142
142
|
}
|
|
143
143
|
else {
|
|
144
144
|
// Full project initialization
|
|
145
|
-
const currentDir = initializeProject(selectedAgent.agentId, selectedOrg.id, persona,
|
|
145
|
+
const currentDir = initializeProject(selectedAgent.agentId, selectedOrg.id, persona, selectedAgent.name, withExamples);
|
|
146
146
|
// Step 6: Install dependencies
|
|
147
147
|
await installDependencies(currentDir);
|
|
148
|
-
|
|
148
|
+
if (withExamples) {
|
|
149
|
+
writeSuccess("ā
Lua skill project initialized with examples!");
|
|
150
|
+
writeInfo("š” Check the examples/ folder for sample skills, tools, jobs, and webhooks");
|
|
151
|
+
}
|
|
152
|
+
else {
|
|
153
|
+
writeSuccess("ā
Lua skill project initialized successfully!");
|
|
154
|
+
writeInfo("š” Tip: Use `lua init --with-examples` to include example code");
|
|
155
|
+
}
|
|
149
156
|
}
|
|
150
157
|
}, "initialization");
|
|
151
158
|
}
|
|
152
159
|
/**
|
|
153
160
|
* Handles the flow for selecting an existing agent.
|
|
154
|
-
* Fetches the agent details from the server to get persona
|
|
161
|
+
* Fetches the agent details from the server to get persona.
|
|
155
162
|
*
|
|
156
163
|
* @param userData - User's data
|
|
157
164
|
* @param apiKey - User's API key
|
|
158
|
-
* @returns Selected agent, organization, and optional persona
|
|
165
|
+
* @returns Selected agent, organization, and optional persona
|
|
159
166
|
*/
|
|
160
167
|
async function selectExistingAgent(userData, apiKey) {
|
|
161
168
|
// Extract organizations
|
|
@@ -167,13 +174,12 @@ async function selectExistingAgent(userData, apiKey) {
|
|
|
167
174
|
const selectedOrg = await promptOrganizationSelection(orgs);
|
|
168
175
|
// Select agent from organization
|
|
169
176
|
const selectedAgent = await promptAgentSelection(selectedOrg);
|
|
170
|
-
// Fetch agent details to get persona
|
|
177
|
+
// Fetch agent details to get persona
|
|
171
178
|
const agentDetails = await fetchExistingAgentDetails(apiKey, selectedAgent.agentId);
|
|
172
179
|
return {
|
|
173
180
|
agent: selectedAgent,
|
|
174
181
|
org: selectedOrg,
|
|
175
|
-
persona: agentDetails.persona
|
|
176
|
-
welcomeMessage: agentDetails.welcomeMessage
|
|
182
|
+
persona: agentDetails.persona
|
|
177
183
|
};
|
|
178
184
|
}
|
|
179
185
|
/**
|
|
@@ -181,7 +187,7 @@ async function selectExistingAgent(userData, apiKey) {
|
|
|
181
187
|
*
|
|
182
188
|
* @param apiKey - User's API key
|
|
183
189
|
* @param userData - User data containing organizations
|
|
184
|
-
* @returns Created agent, organization, and optional persona
|
|
190
|
+
* @returns Created agent, organization, and optional persona
|
|
185
191
|
*/
|
|
186
192
|
async function createNewAgentFlow(apiKey, userData) {
|
|
187
193
|
// Fetch and select agent type
|
|
@@ -275,14 +281,12 @@ async function handleAgentSwitch(userData, apiKey, existingYaml) {
|
|
|
275
281
|
let selectedAgent;
|
|
276
282
|
let selectedOrg;
|
|
277
283
|
let persona;
|
|
278
|
-
let welcomeMessage;
|
|
279
284
|
if (agentChoice === "existing") {
|
|
280
285
|
// Select existing agent
|
|
281
286
|
const result = await selectExistingAgent(userData, apiKey);
|
|
282
287
|
selectedAgent = result.agent;
|
|
283
288
|
selectedOrg = result.org;
|
|
284
289
|
persona = result.persona;
|
|
285
|
-
welcomeMessage = result.welcomeMessage;
|
|
286
290
|
}
|
|
287
291
|
else {
|
|
288
292
|
// Create new agent
|
|
@@ -290,17 +294,15 @@ async function handleAgentSwitch(userData, apiKey, existingYaml) {
|
|
|
290
294
|
selectedAgent = result.agent;
|
|
291
295
|
selectedOrg = result.org;
|
|
292
296
|
persona = result.persona;
|
|
293
|
-
welcomeMessage = result.welcomeMessage;
|
|
294
297
|
}
|
|
295
|
-
// Ask about persona
|
|
298
|
+
// Ask about persona
|
|
296
299
|
const finalPersona = await promptPersonaReplacement(existingYaml, persona);
|
|
297
|
-
const finalWelcomeMessage = await promptWelcomeMessageReplacement(existingYaml, welcomeMessage);
|
|
298
300
|
// Update existing YAML file with new agent
|
|
299
301
|
writeInfo("\nš Updating lua.skill.yaml with new agent...");
|
|
300
|
-
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, finalPersona
|
|
302
|
+
updateYamlAgent(selectedAgent.agentId, selectedOrg.id, finalPersona);
|
|
301
303
|
// Also update LuaAgent in index.ts if it exists
|
|
302
304
|
const { updateLuaAgentInIndexFile } = await import("../utils/init-helpers.js");
|
|
303
|
-
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, finalPersona
|
|
305
|
+
updateLuaAgentInIndexFile(process.cwd(), selectedAgent.name, finalPersona);
|
|
304
306
|
writeSuccess("ā
lua.skill.yaml updated successfully!");
|
|
305
307
|
writeSuccess("ā
LuaAgent configuration updated!");
|
|
306
308
|
writeInfo("\nš” Your project now uses the new agent. Run 'lua compile' to update your skills.\n");
|
|
@@ -331,28 +333,3 @@ async function promptPersonaReplacement(existingYaml, newPersona) {
|
|
|
331
333
|
]);
|
|
332
334
|
return replacePersona ? newPersona : existingPersona;
|
|
333
335
|
}
|
|
334
|
-
/**
|
|
335
|
-
* Prompt user about replacing existing welcome message
|
|
336
|
-
*/
|
|
337
|
-
async function promptWelcomeMessageReplacement(existingYaml, newWelcomeMessage) {
|
|
338
|
-
const existingWelcomeMessage = existingYaml?.agent?.welcomeMessage;
|
|
339
|
-
// If no existing welcome message, use new one
|
|
340
|
-
if (!existingWelcomeMessage) {
|
|
341
|
-
return newWelcomeMessage;
|
|
342
|
-
}
|
|
343
|
-
// If no new welcome message, keep existing
|
|
344
|
-
if (!newWelcomeMessage) {
|
|
345
|
-
return existingWelcomeMessage;
|
|
346
|
-
}
|
|
347
|
-
// Both exist - ask user
|
|
348
|
-
writeInfo(" Existing welcome message found in project");
|
|
349
|
-
const { replaceWelcomeMessage } = await inquirer.prompt([
|
|
350
|
-
{
|
|
351
|
-
type: 'confirm',
|
|
352
|
-
name: 'replaceWelcomeMessage',
|
|
353
|
-
message: 'Replace existing welcome message with the new agent\'s welcome message?',
|
|
354
|
-
default: false
|
|
355
|
-
}
|
|
356
|
-
]);
|
|
357
|
-
return replaceWelcomeMessage ? newWelcomeMessage : existingWelcomeMessage;
|
|
358
|
-
}
|
package/dist/commands/jobs.js
CHANGED
|
@@ -203,8 +203,8 @@ async function viewJobVersions(context, config) {
|
|
|
203
203
|
if (!response.success || !response.data) {
|
|
204
204
|
throw new Error(response.error?.message || 'Failed to fetch versions');
|
|
205
205
|
}
|
|
206
|
-
const versions = response.data
|
|
207
|
-
const activeVersionId =
|
|
206
|
+
const versions = response.data;
|
|
207
|
+
const activeVersionId = selectedJob.activeVersionId;
|
|
208
208
|
if (versions.length === 0) {
|
|
209
209
|
console.log(`\nā¹ļø No versions found for ${selectedJob.name}.\n`);
|
|
210
210
|
console.log("š” Push a version first using 'lua push job'.\n");
|
|
@@ -270,8 +270,8 @@ async function deployJobVersion(context, config) {
|
|
|
270
270
|
if (!response.success || !response.data) {
|
|
271
271
|
throw new Error(response.error?.message || 'Failed to fetch versions');
|
|
272
272
|
}
|
|
273
|
-
const versions = response.data
|
|
274
|
-
const activeVersionId =
|
|
273
|
+
const versions = response.data;
|
|
274
|
+
const activeVersionId = selectedJob.activeVersionId;
|
|
275
275
|
if (versions.length === 0) {
|
|
276
276
|
console.log(`\nā¹ļø No versions found for ${selectedJob.name}.\n`);
|
|
277
277
|
console.log("š” Push a version first using 'lua push job'.\n");
|
|
@@ -434,7 +434,7 @@ async function triggerJob(context, config) {
|
|
|
434
434
|
const response = await jobApi.triggerJob(jobAnswer.selectedJob.jobId);
|
|
435
435
|
if (response.success && response.data) {
|
|
436
436
|
writeSuccess(`ā
Job "${jobAnswer.selectedJob.name}" triggered successfully`);
|
|
437
|
-
writeInfo(`š Execution ID: ${response.data.
|
|
437
|
+
writeInfo(`š Execution ID: ${response.data.id || 'N/A'}`);
|
|
438
438
|
}
|
|
439
439
|
else {
|
|
440
440
|
console.error(`ā Failed to trigger job: ${response.error?.message || 'Unknown error'}`);
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Command
|
|
3
|
+
* Manages Model Context Protocol (MCP) servers for agents
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Main MCP command - manages MCP servers
|
|
7
|
+
*
|
|
8
|
+
* Subcommands:
|
|
9
|
+
* - lua mcp list - List all MCP servers
|
|
10
|
+
* - lua mcp activate - Activate an MCP server
|
|
11
|
+
* - lua mcp deactivate - Deactivate an MCP server
|
|
12
|
+
* - lua mcp delete - Delete an MCP server
|
|
13
|
+
*
|
|
14
|
+
* @param action - Optional action ('list', 'activate', 'deactivate', 'delete')
|
|
15
|
+
* @param serverName - Optional server name for actions
|
|
16
|
+
* @returns Promise that resolves when command completes
|
|
17
|
+
*/
|
|
18
|
+
export declare function mcpCommand(action?: string, serverName?: string): Promise<void>;
|
|
@@ -0,0 +1,393 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* MCP Command
|
|
3
|
+
* Manages Model Context Protocol (MCP) servers for agents
|
|
4
|
+
*/
|
|
5
|
+
import { loadApiKey, checkApiKey } from '../services/auth.js';
|
|
6
|
+
import { readSkillConfig } from '../utils/files.js';
|
|
7
|
+
import { withErrorHandling, writeProgress, writeSuccess, writeInfo } from '../utils/cli.js';
|
|
8
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
9
|
+
import { safePrompt } from '../utils/prompt-handler.js';
|
|
10
|
+
import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
|
|
11
|
+
import DeveloperApi from '../api/developer.api.service.js';
|
|
12
|
+
/**
|
|
13
|
+
* Main MCP command - manages MCP servers
|
|
14
|
+
*
|
|
15
|
+
* Subcommands:
|
|
16
|
+
* - lua mcp list - List all MCP servers
|
|
17
|
+
* - lua mcp activate - Activate an MCP server
|
|
18
|
+
* - lua mcp deactivate - Deactivate an MCP server
|
|
19
|
+
* - lua mcp delete - Delete an MCP server
|
|
20
|
+
*
|
|
21
|
+
* @param action - Optional action ('list', 'activate', 'deactivate', 'delete')
|
|
22
|
+
* @param serverName - Optional server name for actions
|
|
23
|
+
* @returns Promise that resolves when command completes
|
|
24
|
+
*/
|
|
25
|
+
export async function mcpCommand(action, serverName) {
|
|
26
|
+
return withErrorHandling(async () => {
|
|
27
|
+
// Step 1: Load configuration
|
|
28
|
+
const config = readSkillConfig();
|
|
29
|
+
validateConfig(config);
|
|
30
|
+
validateAgentConfig(config);
|
|
31
|
+
const agentId = config.agent.agentId;
|
|
32
|
+
// Step 2: Authenticate
|
|
33
|
+
const apiKey = await loadApiKey();
|
|
34
|
+
if (!apiKey) {
|
|
35
|
+
console.error("ā No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
36
|
+
process.exit(1);
|
|
37
|
+
}
|
|
38
|
+
await checkApiKey(apiKey);
|
|
39
|
+
writeProgress("ā
Authenticated");
|
|
40
|
+
const developerApi = new DeveloperApi(BASE_URLS.API, apiKey, agentId);
|
|
41
|
+
const context = {
|
|
42
|
+
agentId,
|
|
43
|
+
apiKey,
|
|
44
|
+
developerApi,
|
|
45
|
+
};
|
|
46
|
+
// Step 3: Handle action or show interactive menu
|
|
47
|
+
if (action) {
|
|
48
|
+
const normalizedAction = action.toLowerCase();
|
|
49
|
+
switch (normalizedAction) {
|
|
50
|
+
case 'list':
|
|
51
|
+
case 'ls':
|
|
52
|
+
await listMCPServers(context);
|
|
53
|
+
break;
|
|
54
|
+
case 'activate':
|
|
55
|
+
case 'enable':
|
|
56
|
+
await activateMCPServer(context, serverName);
|
|
57
|
+
break;
|
|
58
|
+
case 'deactivate':
|
|
59
|
+
case 'disable':
|
|
60
|
+
await deactivateMCPServer(context, serverName);
|
|
61
|
+
break;
|
|
62
|
+
case 'delete':
|
|
63
|
+
case 'rm':
|
|
64
|
+
await deleteMCPServer(context, serverName);
|
|
65
|
+
break;
|
|
66
|
+
default:
|
|
67
|
+
console.error(`ā Unknown action: "${action}"`);
|
|
68
|
+
showUsage();
|
|
69
|
+
process.exit(1);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
else {
|
|
73
|
+
// Interactive mode
|
|
74
|
+
await interactiveMCPManagement(context);
|
|
75
|
+
}
|
|
76
|
+
}, "mcp");
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Show usage information
|
|
80
|
+
*/
|
|
81
|
+
function showUsage() {
|
|
82
|
+
console.log('\nUsage:');
|
|
83
|
+
console.log(' lua mcp - Interactive MCP server management');
|
|
84
|
+
console.log(' lua mcp list - List all MCP servers');
|
|
85
|
+
console.log(' lua mcp activate [name] - Activate an MCP server');
|
|
86
|
+
console.log(' lua mcp deactivate [name] - Deactivate an MCP server');
|
|
87
|
+
console.log(' lua mcp delete [name] - Delete an MCP server');
|
|
88
|
+
console.log('\nAliases:');
|
|
89
|
+
console.log(' list ā ls');
|
|
90
|
+
console.log(' activate ā enable');
|
|
91
|
+
console.log(' deactivate ā disable');
|
|
92
|
+
console.log(' delete ā rm');
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Interactive MCP management
|
|
96
|
+
*/
|
|
97
|
+
async function interactiveMCPManagement(context) {
|
|
98
|
+
let continueManaging = true;
|
|
99
|
+
while (continueManaging) {
|
|
100
|
+
console.log("\n" + "=".repeat(60));
|
|
101
|
+
console.log("š MCP Server Management");
|
|
102
|
+
console.log("=".repeat(60) + "\n");
|
|
103
|
+
const actionAnswer = await safePrompt([
|
|
104
|
+
{
|
|
105
|
+
type: 'list',
|
|
106
|
+
name: 'action',
|
|
107
|
+
message: 'What would you like to do?',
|
|
108
|
+
choices: [
|
|
109
|
+
{ name: 'š List MCP servers', value: 'list' },
|
|
110
|
+
{ name: 'ā
Activate a server', value: 'activate' },
|
|
111
|
+
{ name: 'āøļø Deactivate a server', value: 'deactivate' },
|
|
112
|
+
{ name: 'šļø Delete a server', value: 'delete' },
|
|
113
|
+
{ name: 'ā Exit', value: 'exit' }
|
|
114
|
+
]
|
|
115
|
+
}
|
|
116
|
+
]);
|
|
117
|
+
if (!actionAnswer)
|
|
118
|
+
return;
|
|
119
|
+
const { action } = actionAnswer;
|
|
120
|
+
switch (action) {
|
|
121
|
+
case 'list':
|
|
122
|
+
await listMCPServers(context);
|
|
123
|
+
break;
|
|
124
|
+
case 'activate':
|
|
125
|
+
await activateMCPServer(context);
|
|
126
|
+
break;
|
|
127
|
+
case 'deactivate':
|
|
128
|
+
await deactivateMCPServer(context);
|
|
129
|
+
break;
|
|
130
|
+
case 'delete':
|
|
131
|
+
await deleteMCPServer(context);
|
|
132
|
+
break;
|
|
133
|
+
case 'exit':
|
|
134
|
+
continueManaging = false;
|
|
135
|
+
console.log("\nš Goodbye!\n");
|
|
136
|
+
break;
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* List all MCP servers
|
|
142
|
+
*/
|
|
143
|
+
async function listMCPServers(context) {
|
|
144
|
+
writeProgress("š Loading MCP servers...");
|
|
145
|
+
try {
|
|
146
|
+
const result = await context.developerApi.getMCPServers();
|
|
147
|
+
if (!result.success) {
|
|
148
|
+
console.error(`\nā Failed to load MCP servers: ${result.error?.message}\n`);
|
|
149
|
+
return;
|
|
150
|
+
}
|
|
151
|
+
const servers = result.data || [];
|
|
152
|
+
console.log("\n" + "=".repeat(60));
|
|
153
|
+
console.log("š MCP Servers");
|
|
154
|
+
console.log("=".repeat(60) + "\n");
|
|
155
|
+
if (servers.length === 0) {
|
|
156
|
+
console.log("ā¹ļø No MCP servers found.");
|
|
157
|
+
console.log("š” Define MCP servers in your LuaAgent configuration and run 'lua push all'.\n");
|
|
158
|
+
return;
|
|
159
|
+
}
|
|
160
|
+
// Separate active and inactive servers
|
|
161
|
+
const activeServers = servers.filter((s) => s.active);
|
|
162
|
+
const inactiveServers = servers.filter((s) => !s.active);
|
|
163
|
+
if (activeServers.length > 0) {
|
|
164
|
+
console.log("ā
Active Servers:\n");
|
|
165
|
+
activeServers.forEach((server) => {
|
|
166
|
+
printServerInfo(server);
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
if (inactiveServers.length > 0) {
|
|
170
|
+
if (activeServers.length > 0)
|
|
171
|
+
console.log("ā".repeat(40) + "\n");
|
|
172
|
+
console.log("āøļø Inactive Servers:\n");
|
|
173
|
+
inactiveServers.forEach((server) => {
|
|
174
|
+
printServerInfo(server);
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
console.log("=".repeat(60) + "\n");
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
console.error('\nā Error loading MCP servers:', error.message);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Print server information
|
|
185
|
+
*/
|
|
186
|
+
function printServerInfo(server) {
|
|
187
|
+
const statusIcon = server.active ? 'š¢' : 'āŖ';
|
|
188
|
+
console.log(`${statusIcon} ${server.name}`);
|
|
189
|
+
console.log(` Transport: ${server.transport}`);
|
|
190
|
+
if (server.transport === 'stdio') {
|
|
191
|
+
console.log(` Command: ${server.command} ${(server.args || []).join(' ')}`);
|
|
192
|
+
}
|
|
193
|
+
else {
|
|
194
|
+
console.log(` URL: ${server.url}`);
|
|
195
|
+
}
|
|
196
|
+
console.log(` ID: ${server.id}`);
|
|
197
|
+
console.log();
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* Activate an MCP server
|
|
201
|
+
*/
|
|
202
|
+
async function activateMCPServer(context, serverName) {
|
|
203
|
+
try {
|
|
204
|
+
// Get all servers
|
|
205
|
+
const result = await context.developerApi.getMCPServers();
|
|
206
|
+
if (!result.success) {
|
|
207
|
+
console.error(`\nā Failed to load MCP servers: ${result.error?.message}\n`);
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
const servers = result.data || [];
|
|
211
|
+
const inactiveServers = servers.filter((s) => !s.active);
|
|
212
|
+
if (inactiveServers.length === 0) {
|
|
213
|
+
console.log("\nā¹ļø All MCP servers are already active.\n");
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
let serverToActivate;
|
|
217
|
+
if (serverName) {
|
|
218
|
+
// Find by name
|
|
219
|
+
const server = inactiveServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
220
|
+
if (!server) {
|
|
221
|
+
console.error(`\nā Inactive MCP server "${serverName}" not found.\n`);
|
|
222
|
+
console.log("Available inactive servers:");
|
|
223
|
+
inactiveServers.forEach((s) => console.log(` - ${s.name}`));
|
|
224
|
+
return;
|
|
225
|
+
}
|
|
226
|
+
serverToActivate = server;
|
|
227
|
+
}
|
|
228
|
+
else {
|
|
229
|
+
// Prompt for selection
|
|
230
|
+
const answer = await safePrompt([
|
|
231
|
+
{
|
|
232
|
+
type: 'list',
|
|
233
|
+
name: 'server',
|
|
234
|
+
message: 'Select an MCP server to activate:',
|
|
235
|
+
choices: inactiveServers.map((s) => ({
|
|
236
|
+
name: `${s.name} (${s.transport})`,
|
|
237
|
+
value: s
|
|
238
|
+
}))
|
|
239
|
+
}
|
|
240
|
+
]);
|
|
241
|
+
if (!answer)
|
|
242
|
+
return;
|
|
243
|
+
serverToActivate = answer.server;
|
|
244
|
+
}
|
|
245
|
+
writeProgress(`š Activating ${serverToActivate.name}...`);
|
|
246
|
+
const activateResult = await context.developerApi.activateMCPServer(serverToActivate.id);
|
|
247
|
+
if (activateResult.success) {
|
|
248
|
+
writeSuccess(`\nā
MCP server "${serverToActivate.name}" activated successfully!\n`);
|
|
249
|
+
writeInfo("š” The server's tools are now available to your agent.");
|
|
250
|
+
}
|
|
251
|
+
else {
|
|
252
|
+
console.error(`\nā Failed to activate: ${activateResult.error?.message}\n`);
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
catch (error) {
|
|
256
|
+
console.error('\nā Error activating MCP server:', error.message);
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Deactivate an MCP server
|
|
261
|
+
*/
|
|
262
|
+
async function deactivateMCPServer(context, serverName) {
|
|
263
|
+
try {
|
|
264
|
+
// Get all servers
|
|
265
|
+
const result = await context.developerApi.getMCPServers();
|
|
266
|
+
if (!result.success) {
|
|
267
|
+
console.error(`\nā Failed to load MCP servers: ${result.error?.message}\n`);
|
|
268
|
+
return;
|
|
269
|
+
}
|
|
270
|
+
const servers = result.data || [];
|
|
271
|
+
const activeServers = servers.filter((s) => s.active);
|
|
272
|
+
if (activeServers.length === 0) {
|
|
273
|
+
console.log("\nā¹ļø No active MCP servers to deactivate.\n");
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
let serverToDeactivate;
|
|
277
|
+
if (serverName) {
|
|
278
|
+
// Find by name
|
|
279
|
+
const server = activeServers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
280
|
+
if (!server) {
|
|
281
|
+
console.error(`\nā Active MCP server "${serverName}" not found.\n`);
|
|
282
|
+
console.log("Available active servers:");
|
|
283
|
+
activeServers.forEach((s) => console.log(` - ${s.name}`));
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
serverToDeactivate = server;
|
|
287
|
+
}
|
|
288
|
+
else {
|
|
289
|
+
// Prompt for selection
|
|
290
|
+
const answer = await safePrompt([
|
|
291
|
+
{
|
|
292
|
+
type: 'list',
|
|
293
|
+
name: 'server',
|
|
294
|
+
message: 'Select an MCP server to deactivate:',
|
|
295
|
+
choices: activeServers.map((s) => ({
|
|
296
|
+
name: `${s.name} (${s.transport})`,
|
|
297
|
+
value: s
|
|
298
|
+
}))
|
|
299
|
+
}
|
|
300
|
+
]);
|
|
301
|
+
if (!answer)
|
|
302
|
+
return;
|
|
303
|
+
serverToDeactivate = answer.server;
|
|
304
|
+
}
|
|
305
|
+
writeProgress(`š Deactivating ${serverToDeactivate.name}...`);
|
|
306
|
+
const deactivateResult = await context.developerApi.deactivateMCPServer(serverToDeactivate.id);
|
|
307
|
+
if (deactivateResult.success) {
|
|
308
|
+
writeSuccess(`\nā
MCP server "${serverToDeactivate.name}" deactivated successfully!\n`);
|
|
309
|
+
writeInfo("š” The server's tools are no longer available to your agent.");
|
|
310
|
+
}
|
|
311
|
+
else {
|
|
312
|
+
console.error(`\nā Failed to deactivate: ${deactivateResult.error?.message}\n`);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
catch (error) {
|
|
316
|
+
console.error('\nā Error deactivating MCP server:', error.message);
|
|
317
|
+
}
|
|
318
|
+
}
|
|
319
|
+
/**
|
|
320
|
+
* Delete an MCP server
|
|
321
|
+
*/
|
|
322
|
+
async function deleteMCPServer(context, serverName) {
|
|
323
|
+
try {
|
|
324
|
+
// Get all servers
|
|
325
|
+
const result = await context.developerApi.getMCPServers();
|
|
326
|
+
if (!result.success) {
|
|
327
|
+
console.error(`\nā Failed to load MCP servers: ${result.error?.message}\n`);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const servers = result.data || [];
|
|
331
|
+
if (servers.length === 0) {
|
|
332
|
+
console.log("\nā¹ļø No MCP servers to delete.\n");
|
|
333
|
+
return;
|
|
334
|
+
}
|
|
335
|
+
let serverToDelete;
|
|
336
|
+
if (serverName) {
|
|
337
|
+
// Find by name
|
|
338
|
+
const server = servers.find((s) => s.name.toLowerCase() === serverName.toLowerCase());
|
|
339
|
+
if (!server) {
|
|
340
|
+
console.error(`\nā MCP server "${serverName}" not found.\n`);
|
|
341
|
+
console.log("Available servers:");
|
|
342
|
+
servers.forEach((s) => console.log(` - ${s.name}`));
|
|
343
|
+
return;
|
|
344
|
+
}
|
|
345
|
+
serverToDelete = server;
|
|
346
|
+
}
|
|
347
|
+
else {
|
|
348
|
+
// Prompt for selection
|
|
349
|
+
const answer = await safePrompt([
|
|
350
|
+
{
|
|
351
|
+
type: 'list',
|
|
352
|
+
name: 'server',
|
|
353
|
+
message: 'Select an MCP server to delete:',
|
|
354
|
+
choices: servers.map((s) => ({
|
|
355
|
+
name: `${s.name} (${s.transport}) ${s.active ? 'š¢' : 'āŖ'}`,
|
|
356
|
+
value: s
|
|
357
|
+
}))
|
|
358
|
+
}
|
|
359
|
+
]);
|
|
360
|
+
if (!answer)
|
|
361
|
+
return;
|
|
362
|
+
serverToDelete = answer.server;
|
|
363
|
+
}
|
|
364
|
+
// Confirm deletion
|
|
365
|
+
console.log(`\nā ļø You are about to delete MCP server: ${serverToDelete.name}`);
|
|
366
|
+
if (serverToDelete.active) {
|
|
367
|
+
console.log("ā ļø WARNING: This server is currently ACTIVE!");
|
|
368
|
+
}
|
|
369
|
+
const confirmAnswer = await safePrompt([
|
|
370
|
+
{
|
|
371
|
+
type: 'confirm',
|
|
372
|
+
name: 'confirm',
|
|
373
|
+
message: 'Are you sure you want to delete this MCP server?',
|
|
374
|
+
default: false
|
|
375
|
+
}
|
|
376
|
+
]);
|
|
377
|
+
if (!confirmAnswer || !confirmAnswer.confirm) {
|
|
378
|
+
console.log("\nā Deletion cancelled.\n");
|
|
379
|
+
return;
|
|
380
|
+
}
|
|
381
|
+
writeProgress(`š Deleting ${serverToDelete.name}...`);
|
|
382
|
+
const deleteResult = await context.developerApi.deleteMCPServer(serverToDelete.id);
|
|
383
|
+
if (deleteResult.success) {
|
|
384
|
+
writeSuccess(`\nā
MCP server "${serverToDelete.name}" deleted successfully!\n`);
|
|
385
|
+
}
|
|
386
|
+
else {
|
|
387
|
+
console.error(`\nā Failed to delete: ${deleteResult.error?.message}\n`);
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
catch (error) {
|
|
391
|
+
console.error('\nā Error deleting MCP server:', error.message);
|
|
392
|
+
}
|
|
393
|
+
}
|