lua-cli 3.1.0 ā 3.2.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/README.md +2 -5
- package/dist/api/marketplace.api.service.d.ts +4 -2
- package/dist/api/marketplace.api.service.js +6 -0
- package/dist/api/persona.api.service.d.ts +54 -0
- package/dist/api/persona.api.service.js +89 -0
- package/dist/api-exports.d.ts +19 -0
- package/dist/api-exports.js +21 -0
- package/dist/cli/command-definitions.js +29 -1
- package/dist/commands/chat.js +2 -3
- package/dist/commands/chatClear.d.ts +5 -1
- package/dist/commands/chatClear.js +19 -8
- package/dist/commands/compile.d.ts +4 -1
- package/dist/commands/compile.js +27 -4
- package/dist/commands/index.d.ts +1 -0
- package/dist/commands/index.js +1 -0
- package/dist/commands/init.js +4 -4
- package/dist/commands/marketplace.js +87 -42
- package/dist/commands/persona.js +7 -49
- package/dist/commands/push.js +3 -2
- package/dist/commands/sync.d.ts +29 -0
- package/dist/commands/sync.js +194 -0
- package/dist/commands/test.js +3 -5
- package/dist/interfaces/index.d.ts +2 -0
- package/dist/interfaces/lua.d.ts +26 -0
- package/dist/interfaces/lua.js +5 -0
- package/dist/interfaces/marketplace.d.ts +20 -0
- package/dist/interfaces/persona.d.ts +42 -0
- package/dist/interfaces/persona.js +5 -0
- package/dist/interfaces/user.d.ts +21 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/skill.d.ts +1 -3
- package/dist/types/skill.js +3 -32
- package/dist/utils/agent-code-utils.d.ts +24 -0
- package/dist/utils/agent-code-utils.js +96 -0
- package/dist/utils/compile.js +8 -8
- package/dist/utils/dev-server.js +5 -4
- package/dist/utils/files.d.ts +1 -3
- package/dist/utils/files.js +1 -39
- package/dist/utils/init-helpers.d.ts +0 -8
- package/dist/utils/init-helpers.js +4 -37
- package/dist/utils/job-management.js +1 -2
- package/dist/utils/sandbox.d.ts +4 -3
- package/dist/utils/sandbox.js +5 -9
- package/dist/utils/sync-helpers.d.ts +61 -0
- package/dist/utils/sync-helpers.js +190 -0
- package/dist/utils/test-helpers.d.ts +0 -7
- package/dist/utils/test-helpers.js +0 -9
- package/package.json +3 -1
- package/template/README.md +1 -1
- package/template/lua.skill.yaml +10 -0
- package/template/package.json +1 -1
- package/dist/utils/agent-management.d.ts +0 -23
- package/dist/utils/agent-management.js +0 -67
|
@@ -897,8 +897,9 @@ async function handleInstallerActions(marketplaceApi, config, apiKey) {
|
|
|
897
897
|
}
|
|
898
898
|
}
|
|
899
899
|
}
|
|
900
|
+
const MARKETPLACE_PAGE_SIZE = 10;
|
|
900
901
|
/**
|
|
901
|
-
* Browse and select a skill from marketplace (with optional search)
|
|
902
|
+
* Browse and select a skill from marketplace (with optional search and pagination)
|
|
902
903
|
* Returns the selected skill or null if cancelled
|
|
903
904
|
*/
|
|
904
905
|
async function browseAndSelectSkill(marketplaceApi, purpose, publishedVersionsOnly) {
|
|
@@ -914,49 +915,93 @@ async function browseAndSelectSkill(marketplaceApi, purpose, publishedVersionsOn
|
|
|
914
915
|
if (searchAnswer === null)
|
|
915
916
|
return null; // User cancelled
|
|
916
917
|
const searchQuery = searchAnswer?.query?.trim() || "";
|
|
917
|
-
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
918
|
+
let currentPage = 1;
|
|
919
|
+
// Pagination loop
|
|
920
|
+
while (true) {
|
|
921
|
+
// 2. Search/browse marketplace skills with pagination
|
|
922
|
+
writeProgress(searchQuery
|
|
923
|
+
? `\nš Searching for "${searchQuery}"...`
|
|
924
|
+
: "\nš Loading marketplace skills...");
|
|
925
|
+
const filters = {
|
|
926
|
+
limit: MARKETPLACE_PAGE_SIZE,
|
|
927
|
+
page: currentPage
|
|
928
|
+
};
|
|
929
|
+
if (searchQuery)
|
|
930
|
+
filters.search = searchQuery;
|
|
931
|
+
if (publishedVersionsOnly !== undefined)
|
|
932
|
+
filters.publishedVersionsOnly = publishedVersionsOnly;
|
|
933
|
+
const searchResults = await marketplaceApi.searchSkills(filters);
|
|
934
|
+
const skills = searchResults?.data || [];
|
|
935
|
+
const pagination = searchResults?.pagination;
|
|
936
|
+
const totalCount = pagination?.totalCount || skills.length;
|
|
937
|
+
const totalPages = pagination?.totalPages || 1;
|
|
938
|
+
const hasNextPage = pagination?.hasNextPage || false;
|
|
939
|
+
const hasPrevPage = pagination?.hasPrevPage || false;
|
|
940
|
+
if (skills.length === 0 && currentPage === 1) {
|
|
941
|
+
if (searchQuery) {
|
|
942
|
+
writeInfo(`\nš¦ No skills found matching "${searchQuery}".`);
|
|
943
|
+
}
|
|
944
|
+
else {
|
|
945
|
+
writeInfo("\nš¦ No skills available on the marketplace yet.");
|
|
946
|
+
}
|
|
947
|
+
writeInfo("š” Be the first to publish a skill!\n");
|
|
948
|
+
return null;
|
|
931
949
|
}
|
|
932
|
-
|
|
933
|
-
|
|
950
|
+
// 3. Display results with pagination info
|
|
951
|
+
const pageInfo = totalPages > 1 ? ` (Page ${currentPage}/${totalPages})` : "";
|
|
952
|
+
console.log(`\nš Found ${totalCount} skill${totalCount === 1 ? "" : "s"}${pageInfo}:\n`);
|
|
953
|
+
// 4. Build choices with pagination navigation
|
|
954
|
+
const choices = [
|
|
955
|
+
...skills.map((s) => ({
|
|
956
|
+
name: `${s.displayName} - ${s.description || "No description"}`,
|
|
957
|
+
value: { type: "skill", skill: s },
|
|
958
|
+
})),
|
|
959
|
+
];
|
|
960
|
+
// Add pagination options
|
|
961
|
+
if (hasNextPage || hasPrevPage) {
|
|
962
|
+
choices.push(new inquirer.Separator());
|
|
963
|
+
if (hasPrevPage) {
|
|
964
|
+
choices.push({
|
|
965
|
+
name: `ā Previous page (${currentPage - 1}/${totalPages})`,
|
|
966
|
+
value: { type: "prev" }
|
|
967
|
+
});
|
|
968
|
+
}
|
|
969
|
+
if (hasNextPage) {
|
|
970
|
+
choices.push({
|
|
971
|
+
name: `ā Next page (${currentPage + 1}/${totalPages})`,
|
|
972
|
+
value: { type: "next" }
|
|
973
|
+
});
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
choices.push(new inquirer.Separator());
|
|
977
|
+
choices.push({ name: "ā Back to menu", value: { type: "back" } });
|
|
978
|
+
// 5. Prompt user to select
|
|
979
|
+
const message = purpose || "Select a skill:";
|
|
980
|
+
const answer = await safePrompt([
|
|
981
|
+
{
|
|
982
|
+
type: "list",
|
|
983
|
+
name: "selection",
|
|
984
|
+
message,
|
|
985
|
+
choices,
|
|
986
|
+
pageSize: MARKETPLACE_PAGE_SIZE + 5, // Show all items + navigation options
|
|
987
|
+
},
|
|
988
|
+
]);
|
|
989
|
+
if (!answer || !answer.selection)
|
|
990
|
+
return null;
|
|
991
|
+
const { selection } = answer;
|
|
992
|
+
if (selection.type === "skill" && selection.skill) {
|
|
993
|
+
return selection.skill;
|
|
994
|
+
}
|
|
995
|
+
else if (selection.type === "next") {
|
|
996
|
+
currentPage++;
|
|
997
|
+
}
|
|
998
|
+
else if (selection.type === "prev") {
|
|
999
|
+
currentPage--;
|
|
1000
|
+
}
|
|
1001
|
+
else if (selection.type === "back") {
|
|
1002
|
+
return null;
|
|
934
1003
|
}
|
|
935
|
-
writeInfo("š” Be the first to publish a skill!\n");
|
|
936
|
-
return null;
|
|
937
1004
|
}
|
|
938
|
-
// 3. Display results
|
|
939
|
-
console.log(`\nš Found ${skills.length} skill${skills.length === 1 ? "" : "s"}:\n`);
|
|
940
|
-
// 4. Prompt user to select a skill
|
|
941
|
-
const message = purpose || "Select a skill (or press ESC to go back):";
|
|
942
|
-
const skillAnswer = await safePrompt([
|
|
943
|
-
{
|
|
944
|
-
type: "list",
|
|
945
|
-
name: "skill",
|
|
946
|
-
message,
|
|
947
|
-
choices: [
|
|
948
|
-
...skills.map((s) => ({
|
|
949
|
-
name: `${s.displayName} - ${s.description || "No description"}`,
|
|
950
|
-
value: s,
|
|
951
|
-
})),
|
|
952
|
-
new inquirer.Separator(),
|
|
953
|
-
{ name: "ā Back to menu", value: null },
|
|
954
|
-
],
|
|
955
|
-
},
|
|
956
|
-
]);
|
|
957
|
-
if (!skillAnswer || !skillAnswer.skill)
|
|
958
|
-
return null;
|
|
959
|
-
return skillAnswer.skill;
|
|
960
1005
|
}
|
|
961
1006
|
catch (error) {
|
|
962
1007
|
console.error(`\nā Error browsing marketplace: ${error.message}\n`);
|
|
@@ -1123,7 +1168,7 @@ async function installMarketplaceSkill(marketplaceApi, config, apiKey) {
|
|
|
1123
1168
|
creatorId: directAnswer.creatorId,
|
|
1124
1169
|
publishedVersionsOnly: true,
|
|
1125
1170
|
});
|
|
1126
|
-
const skills = searchResults || [];
|
|
1171
|
+
const skills = searchResults?.data || [];
|
|
1127
1172
|
if (skills.length === 0) {
|
|
1128
1173
|
console.error(`\nā Skill "${directAnswer.name}" by creator "${directAnswer.creatorId}" not found on the marketplace.\n`);
|
|
1129
1174
|
return;
|
package/dist/commands/persona.js
CHANGED
|
@@ -2,9 +2,6 @@
|
|
|
2
2
|
* Persona Command
|
|
3
3
|
* Manages agent persona for sandbox and production environments
|
|
4
4
|
*/
|
|
5
|
-
import fs from 'fs';
|
|
6
|
-
import path from 'path';
|
|
7
|
-
import yaml from 'js-yaml';
|
|
8
5
|
import inquirer from 'inquirer';
|
|
9
6
|
import { loadApiKey, checkApiKey } from '../services/auth.js';
|
|
10
7
|
import { readSkillConfig } from '../utils/files.js';
|
|
@@ -12,6 +9,7 @@ import { withErrorHandling, writeProgress, writeSuccess, writeInfo } from '../ut
|
|
|
12
9
|
import { BASE_URLS } from '../config/constants.js';
|
|
13
10
|
import { safePrompt } from '../utils/prompt-handler.js';
|
|
14
11
|
import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
|
|
12
|
+
import { loadPersonaFromCode, savePersonaToCode } from '../utils/agent-code-utils.js';
|
|
15
13
|
/**
|
|
16
14
|
* Main persona command - manages agent persona
|
|
17
15
|
*
|
|
@@ -96,8 +94,8 @@ export async function personaCommand(env) {
|
|
|
96
94
|
async function manageSandboxPersona(context) {
|
|
97
95
|
let continueManaging = true;
|
|
98
96
|
while (continueManaging) {
|
|
99
|
-
// Load current persona
|
|
100
|
-
const currentPersona =
|
|
97
|
+
// Load current persona directly from code
|
|
98
|
+
const currentPersona = loadPersonaFromCode();
|
|
101
99
|
// Show menu
|
|
102
100
|
console.log("\n" + "=".repeat(60));
|
|
103
101
|
console.log("š Sandbox Persona Management");
|
|
@@ -188,46 +186,6 @@ async function manageProductionPersona(context) {
|
|
|
188
186
|
}
|
|
189
187
|
}
|
|
190
188
|
}
|
|
191
|
-
/**
|
|
192
|
-
* Load sandbox persona from lua.skill.yaml
|
|
193
|
-
*/
|
|
194
|
-
function loadSandboxPersona() {
|
|
195
|
-
try {
|
|
196
|
-
const config = readSkillConfig();
|
|
197
|
-
return config.agent?.persona || '';
|
|
198
|
-
}
|
|
199
|
-
catch (error) {
|
|
200
|
-
return '';
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
/**
|
|
204
|
-
* Save sandbox persona to lua.skill.yaml
|
|
205
|
-
*/
|
|
206
|
-
function saveSandboxPersona(persona) {
|
|
207
|
-
try {
|
|
208
|
-
const configPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
209
|
-
// Read current config
|
|
210
|
-
const fileContent = fs.readFileSync(configPath, 'utf8');
|
|
211
|
-
const config = yaml.load(fileContent);
|
|
212
|
-
// Ensure agent object exists
|
|
213
|
-
if (!config.agent) {
|
|
214
|
-
config.agent = {};
|
|
215
|
-
}
|
|
216
|
-
// Update persona
|
|
217
|
-
config.agent.persona = persona;
|
|
218
|
-
// Write back to file
|
|
219
|
-
const newContent = yaml.dump(config, {
|
|
220
|
-
lineWidth: -1,
|
|
221
|
-
noRefs: true
|
|
222
|
-
});
|
|
223
|
-
fs.writeFileSync(configPath, newContent, 'utf8');
|
|
224
|
-
return true;
|
|
225
|
-
}
|
|
226
|
-
catch (error) {
|
|
227
|
-
console.error('ā Error saving persona to lua.skill.yaml:', error);
|
|
228
|
-
return false;
|
|
229
|
-
}
|
|
230
|
-
}
|
|
231
189
|
/**
|
|
232
190
|
* View full persona content
|
|
233
191
|
*/
|
|
@@ -287,13 +245,13 @@ async function editSandboxPersona(context, currentPersona) {
|
|
|
287
245
|
return;
|
|
288
246
|
const { newPersona } = personaAnswer;
|
|
289
247
|
const trimmedPersona = newPersona.trim();
|
|
290
|
-
writeProgress("š Saving persona to
|
|
291
|
-
const success =
|
|
248
|
+
writeProgress("š Saving persona to code (LuaAgent)...");
|
|
249
|
+
const success = savePersonaToCode(trimmedPersona);
|
|
292
250
|
if (success) {
|
|
293
|
-
writeSuccess("ā
Persona saved to
|
|
251
|
+
writeSuccess("ā
Persona saved to code successfully");
|
|
294
252
|
}
|
|
295
253
|
else {
|
|
296
|
-
console.error("ā Failed to save persona to
|
|
254
|
+
console.error("ā Failed to save persona to code");
|
|
297
255
|
}
|
|
298
256
|
}
|
|
299
257
|
/**
|
package/dist/commands/push.js
CHANGED
|
@@ -17,6 +17,7 @@ import { BASE_URLS } from '../config/constants.js';
|
|
|
17
17
|
import PreProcessorApi from '../api/preprocessor.api.service.js';
|
|
18
18
|
import PostProcessorApi from '../api/postprocessor.api.service.js';
|
|
19
19
|
import DeveloperApi from '../api/developer.api.service.js';
|
|
20
|
+
import { loadPersonaFromCode } from '../utils/agent-code-utils.js';
|
|
20
21
|
/**
|
|
21
22
|
* Main push command - pushes a skill or persona version to the server.
|
|
22
23
|
*
|
|
@@ -239,8 +240,8 @@ async function pushPersonaVersion() {
|
|
|
239
240
|
console.error("ā No agent configuration found. Please run 'lua init' first.");
|
|
240
241
|
process.exit(1);
|
|
241
242
|
}
|
|
242
|
-
// Step 2: Load current persona
|
|
243
|
-
const currentPersona =
|
|
243
|
+
// Step 2: Load current persona from code
|
|
244
|
+
const currentPersona = loadPersonaFromCode();
|
|
244
245
|
if (!currentPersona || !currentPersona.trim()) {
|
|
245
246
|
console.error("ā No persona found in configuration. Please edit your persona first using 'lua persona'.");
|
|
246
247
|
process.exit(1);
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Command
|
|
3
|
+
* Detects drift between server state and local code, allowing users to sync
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Main sync command - detects and resolves drift between server and local code.
|
|
7
|
+
*
|
|
8
|
+
* Features:
|
|
9
|
+
* - Fetches current deployed state from server
|
|
10
|
+
* - Compares with local code
|
|
11
|
+
* - Shows diff for drifted components
|
|
12
|
+
* - Allows user to update local code from server
|
|
13
|
+
*
|
|
14
|
+
* @returns Promise that resolves when sync completes
|
|
15
|
+
*/
|
|
16
|
+
export declare function syncCommand(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Run sync check during compile flow (non-interactive or with prompts).
|
|
19
|
+
* Returns true if compilation should continue, false if user cancelled.
|
|
20
|
+
*
|
|
21
|
+
* @param apiKey - API key for authentication
|
|
22
|
+
* @param agentId - Agent ID
|
|
23
|
+
* @param options - Sync options
|
|
24
|
+
* @returns Promise<boolean> - true to continue, false to cancel
|
|
25
|
+
*/
|
|
26
|
+
export declare function runSyncCheck(apiKey: string, agentId: string, options?: {
|
|
27
|
+
noSync?: boolean;
|
|
28
|
+
forceSync?: boolean;
|
|
29
|
+
}): Promise<boolean>;
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sync Command
|
|
3
|
+
* Detects drift between server state and local code, allowing users to sync
|
|
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 { safePrompt } from '../utils/prompt-handler.js';
|
|
9
|
+
import { validateConfig, validateAgentConfig, } from '../utils/dev-helpers.js';
|
|
10
|
+
import { savePersonaToCode, saveNameToCode } from '../utils/agent-code-utils.js';
|
|
11
|
+
import { checkPersonaDrift, checkNameDrift, showPersonaDiff, showNameDiff, } from '../utils/sync-helpers.js';
|
|
12
|
+
/**
|
|
13
|
+
* Main sync command - detects and resolves drift between server and local code.
|
|
14
|
+
*
|
|
15
|
+
* Features:
|
|
16
|
+
* - Fetches current deployed state from server
|
|
17
|
+
* - Compares with local code
|
|
18
|
+
* - Shows diff for drifted components
|
|
19
|
+
* - Allows user to update local code from server
|
|
20
|
+
*
|
|
21
|
+
* @returns Promise that resolves when sync completes
|
|
22
|
+
*/
|
|
23
|
+
export async function syncCommand() {
|
|
24
|
+
return withErrorHandling(async () => {
|
|
25
|
+
writeProgress('š Checking for drift between server and local code...');
|
|
26
|
+
// Step 1: Load configuration
|
|
27
|
+
const config = readSkillConfig();
|
|
28
|
+
validateConfig(config);
|
|
29
|
+
validateAgentConfig(config);
|
|
30
|
+
const agentId = config.agent.agentId;
|
|
31
|
+
// Step 2: Authenticate
|
|
32
|
+
const apiKey = await loadApiKey();
|
|
33
|
+
if (!apiKey) {
|
|
34
|
+
console.error("ā No API key found. Please run 'lua auth configure' to set up your API key.");
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
await checkApiKey(apiKey);
|
|
38
|
+
// Step 3: Check for drift
|
|
39
|
+
const nameDrift = await checkNameDrift(apiKey, agentId);
|
|
40
|
+
const personaDrift = await checkPersonaDrift(apiKey, agentId);
|
|
41
|
+
if (!nameDrift && !personaDrift) {
|
|
42
|
+
writeSuccess('ā
No drift detected. Local code is in sync with server.');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
// Step 4: Handle name drift
|
|
46
|
+
if (nameDrift) {
|
|
47
|
+
await handleNameDrift(nameDrift);
|
|
48
|
+
}
|
|
49
|
+
// Step 5: Handle persona drift
|
|
50
|
+
if (personaDrift) {
|
|
51
|
+
await handlePersonaDrift(personaDrift);
|
|
52
|
+
}
|
|
53
|
+
writeSuccess('\nā
Sync complete.');
|
|
54
|
+
}, 'sync');
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Handle name drift interactively.
|
|
58
|
+
*/
|
|
59
|
+
async function handleNameDrift(drift) {
|
|
60
|
+
showNameDiff(drift.serverName, drift.localName);
|
|
61
|
+
const answer = await safePrompt([
|
|
62
|
+
{
|
|
63
|
+
type: 'list',
|
|
64
|
+
name: 'action',
|
|
65
|
+
message: 'What would you like to do with the name?',
|
|
66
|
+
choices: [
|
|
67
|
+
{ name: 'š„ Update local from server', value: 'update' },
|
|
68
|
+
{ name: 'āļø Skip (keep local)', value: 'skip' },
|
|
69
|
+
],
|
|
70
|
+
},
|
|
71
|
+
]);
|
|
72
|
+
if (!answer || answer.action === 'skip') {
|
|
73
|
+
writeInfo('Skipped name sync.');
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
if (answer.action === 'update' && drift.serverName) {
|
|
77
|
+
writeProgress('š Updating name in code...');
|
|
78
|
+
const success = saveNameToCode(drift.serverName);
|
|
79
|
+
if (success) {
|
|
80
|
+
writeSuccess('ā
Name updated in src/index.ts');
|
|
81
|
+
}
|
|
82
|
+
else {
|
|
83
|
+
console.error('ā Failed to update name in code.');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Handle persona drift interactively.
|
|
89
|
+
*/
|
|
90
|
+
async function handlePersonaDrift(drift) {
|
|
91
|
+
// Show diff
|
|
92
|
+
showPersonaDiff(drift.serverPersona, drift.localPersona);
|
|
93
|
+
// Prompt user for action
|
|
94
|
+
const answer = await safePrompt([
|
|
95
|
+
{
|
|
96
|
+
type: 'list',
|
|
97
|
+
name: 'action',
|
|
98
|
+
message: 'What would you like to do with persona?',
|
|
99
|
+
choices: [
|
|
100
|
+
{ name: 'š„ Update local from server', value: 'update' },
|
|
101
|
+
{ name: 'āļø Skip (keep local)', value: 'skip' },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
]);
|
|
105
|
+
if (!answer || answer.action === 'skip') {
|
|
106
|
+
writeInfo('Skipped persona sync.');
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
if (answer.action === 'update') {
|
|
110
|
+
if (drift.serverPersona) {
|
|
111
|
+
writeProgress('š Updating persona in code...');
|
|
112
|
+
const success = savePersonaToCode(drift.serverPersona);
|
|
113
|
+
if (success) {
|
|
114
|
+
writeSuccess('ā
Persona updated in src/index.ts');
|
|
115
|
+
}
|
|
116
|
+
else {
|
|
117
|
+
console.error('ā Failed to update persona in code.');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
else {
|
|
121
|
+
writeInfo('ā¹ļø No server persona to sync from.');
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
/**
|
|
126
|
+
* Run sync check during compile flow (non-interactive or with prompts).
|
|
127
|
+
* Returns true if compilation should continue, false if user cancelled.
|
|
128
|
+
*
|
|
129
|
+
* @param apiKey - API key for authentication
|
|
130
|
+
* @param agentId - Agent ID
|
|
131
|
+
* @param options - Sync options
|
|
132
|
+
* @returns Promise<boolean> - true to continue, false to cancel
|
|
133
|
+
*/
|
|
134
|
+
export async function runSyncCheck(apiKey, agentId, options = {}) {
|
|
135
|
+
// Skip sync if --no-sync flag is set
|
|
136
|
+
if (options.noSync) {
|
|
137
|
+
return true;
|
|
138
|
+
}
|
|
139
|
+
// Check for drift
|
|
140
|
+
const nameDrift = await checkNameDrift(apiKey, agentId);
|
|
141
|
+
const personaDrift = await checkPersonaDrift(apiKey, agentId);
|
|
142
|
+
if (!nameDrift && !personaDrift) {
|
|
143
|
+
return true; // No drift, continue
|
|
144
|
+
}
|
|
145
|
+
// If --force-sync, auto-update without prompting
|
|
146
|
+
if (options.forceSync) {
|
|
147
|
+
if (nameDrift?.serverName) {
|
|
148
|
+
writeProgress('š Auto-syncing name from server (--force-sync)...');
|
|
149
|
+
saveNameToCode(nameDrift.serverName);
|
|
150
|
+
writeSuccess('ā
Name synced from server');
|
|
151
|
+
}
|
|
152
|
+
if (personaDrift?.serverPersona) {
|
|
153
|
+
writeProgress('š Auto-syncing persona from server (--force-sync)...');
|
|
154
|
+
savePersonaToCode(personaDrift.serverPersona);
|
|
155
|
+
writeSuccess('ā
Persona synced from server');
|
|
156
|
+
}
|
|
157
|
+
return true;
|
|
158
|
+
}
|
|
159
|
+
// Show diffs
|
|
160
|
+
console.log('\nā ļø Drift detected!\n');
|
|
161
|
+
if (nameDrift) {
|
|
162
|
+
showNameDiff(nameDrift.serverName, nameDrift.localName);
|
|
163
|
+
}
|
|
164
|
+
if (personaDrift) {
|
|
165
|
+
showPersonaDiff(personaDrift.serverPersona, personaDrift.localPersona);
|
|
166
|
+
}
|
|
167
|
+
const answer = await safePrompt([
|
|
168
|
+
{
|
|
169
|
+
type: 'list',
|
|
170
|
+
name: 'action',
|
|
171
|
+
message: 'How would you like to proceed?',
|
|
172
|
+
choices: [
|
|
173
|
+
{ name: 'š„ Update local from server', value: 'update' },
|
|
174
|
+
{ name: 'āļø Continue with local (will overwrite server on push)', value: 'continue' },
|
|
175
|
+
{ name: 'ā Cancel', value: 'cancel' },
|
|
176
|
+
],
|
|
177
|
+
},
|
|
178
|
+
]);
|
|
179
|
+
if (!answer || answer.action === 'cancel') {
|
|
180
|
+
console.log('\nā Compilation cancelled due to unresolved drift.');
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
if (answer.action === 'update') {
|
|
184
|
+
if (nameDrift?.serverName) {
|
|
185
|
+
saveNameToCode(nameDrift.serverName);
|
|
186
|
+
writeSuccess('ā
Name synced from server');
|
|
187
|
+
}
|
|
188
|
+
if (personaDrift?.serverPersona) {
|
|
189
|
+
savePersonaToCode(personaDrift.serverPersona);
|
|
190
|
+
writeSuccess('ā
Persona synced from server');
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
return true;
|
|
194
|
+
}
|
package/dist/commands/test.js
CHANGED
|
@@ -10,7 +10,7 @@ import { loadApiKey } from "../services/auth.js";
|
|
|
10
10
|
import { executeTool, executeWebhook, executeJob, executePreProcessor, executePostProcessor, loadEnvironmentVariables } from "../utils/sandbox.js";
|
|
11
11
|
import { readSkillConfig } from "../utils/files.js";
|
|
12
12
|
import { safePrompt } from "../utils/prompt-handler.js";
|
|
13
|
-
import { decompressCode, readDeployJson, extractToolsFromDeployData, hasEnvFile,
|
|
13
|
+
import { decompressCode, readDeployJson, extractToolsFromDeployData, hasEnvFile, } from "../utils/test-helpers.js";
|
|
14
14
|
import { promptToolSelection, generatePromptsForObject } from "../utils/test-prompts.js";
|
|
15
15
|
/**
|
|
16
16
|
* Main test command - tests tools, webhooks, jobs, preprocessors, or postprocessors.
|
|
@@ -110,9 +110,6 @@ async function testSkill() {
|
|
|
110
110
|
if (hasEnvFile()) {
|
|
111
111
|
writeProgress(`š Loaded environment variables from .env file`);
|
|
112
112
|
}
|
|
113
|
-
if (hasConfigEnvVars(config)) {
|
|
114
|
-
writeProgress(`š Loaded environment variables from lua.skill.yaml`);
|
|
115
|
-
}
|
|
116
113
|
// Step 5: Let user select a tool
|
|
117
114
|
const selectedTool = await promptToolSelection(allTools);
|
|
118
115
|
clearPromptLines(2);
|
|
@@ -138,7 +135,8 @@ async function testSkill() {
|
|
|
138
135
|
toolCode,
|
|
139
136
|
inputs: inputValues,
|
|
140
137
|
apiKey,
|
|
141
|
-
agentId
|
|
138
|
+
agentId,
|
|
139
|
+
channel: 'dev',
|
|
142
140
|
});
|
|
143
141
|
writeSuccess("ā
Tool execution successful!");
|
|
144
142
|
console.log(`Output: ${JSON.stringify(result, null, 2)}`);
|
|
@@ -10,3 +10,5 @@ export { ApiResponse, Pagination } from "./common.js";
|
|
|
10
10
|
export { SkillTool, SkillVersion, Skill, GetSkillsResponse, DeleteSkillResponse, } from "./skills.js";
|
|
11
11
|
export { ImmutableUserProfile, UserAgentData } from "./user.js";
|
|
12
12
|
export { MCPServerResponse, MCPServerStdioResponse, MCPServerSSEResponse, CreateMCPServerRequest, UpdateMCPServerRequest, } from "./mcp.js";
|
|
13
|
+
export { PersonaVersion, PersonaVersionsResponse, CreatePersonaVersionResponse, SetPersonaVersionResponse, } from "./persona.js";
|
|
14
|
+
export { Channel, LuaRequest, LuaRuntime, } from "./lua.js";
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Lua Runtime Interfaces
|
|
3
|
+
* Request-level runtime information available in the execution sandbox
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Channel type.
|
|
7
|
+
* Represents the communication channel through which a request originated.
|
|
8
|
+
* Known channels are typed as string literals, unrecognized channels are unknown.
|
|
9
|
+
*/
|
|
10
|
+
export type Channel = 'web' | 'whatsapp' | 'facebook' | 'instagram' | 'slack' | 'api' | 'dev' | 'email' | string;
|
|
11
|
+
/**
|
|
12
|
+
* Lua request context.
|
|
13
|
+
* Contains information about the current request.
|
|
14
|
+
*/
|
|
15
|
+
export interface LuaRequest {
|
|
16
|
+
/** The channel through which the request originated */
|
|
17
|
+
channel: Channel;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Lua runtime API.
|
|
21
|
+
* Provides access to request-level runtime information.
|
|
22
|
+
*/
|
|
23
|
+
export interface LuaRuntime {
|
|
24
|
+
/** Request context information */
|
|
25
|
+
request: LuaRequest;
|
|
26
|
+
}
|
|
@@ -97,3 +97,23 @@ export interface UnlistSkillResponse {
|
|
|
97
97
|
unlisted: boolean;
|
|
98
98
|
versionsUnpublished: number;
|
|
99
99
|
}
|
|
100
|
+
/**
|
|
101
|
+
* Pagination metadata
|
|
102
|
+
*/
|
|
103
|
+
export interface MarketplacePaginationResponse {
|
|
104
|
+
currentPage: number;
|
|
105
|
+
totalPages: number;
|
|
106
|
+
totalCount: number;
|
|
107
|
+
limit: number;
|
|
108
|
+
hasNextPage: boolean;
|
|
109
|
+
hasPrevPage: boolean;
|
|
110
|
+
nextPage: number | null;
|
|
111
|
+
prevPage: number | null;
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Paginated marketplace skills response
|
|
115
|
+
*/
|
|
116
|
+
export interface PaginatedMarketplaceSkillsResponse {
|
|
117
|
+
data: MarketplaceSkillWithVersionsResponse[];
|
|
118
|
+
pagination: MarketplacePaginationResponse;
|
|
119
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persona Interfaces
|
|
3
|
+
* Matches lua-api/src/dto/persona.dto.ts
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* Persona version structure
|
|
7
|
+
* Matches PersonaVersionDto
|
|
8
|
+
*/
|
|
9
|
+
export interface PersonaVersion {
|
|
10
|
+
version: number;
|
|
11
|
+
persona: string;
|
|
12
|
+
createdDate: number;
|
|
13
|
+
createdBy?: string;
|
|
14
|
+
isCurrent: boolean;
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Response for getVersions
|
|
18
|
+
* Matches PersonaVersionsResponseDto
|
|
19
|
+
*/
|
|
20
|
+
export interface PersonaVersionsResponse {
|
|
21
|
+
status: string;
|
|
22
|
+
message: string;
|
|
23
|
+
versions: PersonaVersion[];
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Response for createVersion
|
|
27
|
+
* Matches CreatePersonaVersionResponseDto
|
|
28
|
+
*/
|
|
29
|
+
export interface CreatePersonaVersionResponse {
|
|
30
|
+
status: string;
|
|
31
|
+
message: string;
|
|
32
|
+
version: number;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Response for deployVersion (setPersonaVersion)
|
|
36
|
+
* Matches SetPersonaVersionResponseDto
|
|
37
|
+
*/
|
|
38
|
+
export interface SetPersonaVersionResponse {
|
|
39
|
+
status: string;
|
|
40
|
+
message: string;
|
|
41
|
+
version: number;
|
|
42
|
+
}
|
|
@@ -17,3 +17,24 @@ export interface UserAgentData extends Record<string, any> {
|
|
|
17
17
|
*/
|
|
18
18
|
userId?: string;
|
|
19
19
|
}
|
|
20
|
+
/**
|
|
21
|
+
* Profile response from user lookup endpoints
|
|
22
|
+
*/
|
|
23
|
+
export interface ProfileResponse {
|
|
24
|
+
id: string;
|
|
25
|
+
fullName: string;
|
|
26
|
+
mobileNumbers: Array<{
|
|
27
|
+
number: string;
|
|
28
|
+
validated: boolean;
|
|
29
|
+
validatedAt: number;
|
|
30
|
+
}>;
|
|
31
|
+
emailAddresses: Array<{
|
|
32
|
+
address: string;
|
|
33
|
+
validated: boolean;
|
|
34
|
+
validatedAt: number;
|
|
35
|
+
}>;
|
|
36
|
+
country?: {
|
|
37
|
+
code?: string;
|
|
38
|
+
name?: string;
|
|
39
|
+
};
|
|
40
|
+
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -23,3 +23,4 @@ export { BasketStatus, BasketItem, Basket } from '../interfaces/baskets.js';
|
|
|
23
23
|
export { OrderStatus, OrderResponse } from '../interfaces/orders.js';
|
|
24
24
|
export { Product } from '../interfaces/product.js';
|
|
25
25
|
export { ApiResponse, Pagination } from '../interfaces/common.js';
|
|
26
|
+
export { Channel, LuaRequest, LuaRuntime } from '../interfaces/lua.js';
|
package/dist/types/skill.d.ts
CHANGED
|
@@ -9,9 +9,7 @@ import { JobInstance } from "../common/job.instance.js";
|
|
|
9
9
|
* Safe environment variable access function.
|
|
10
10
|
* Gets injected at runtime with skill-specific environment variables.
|
|
11
11
|
*
|
|
12
|
-
* Checks
|
|
13
|
-
* 1. Process environment variables (.env file)
|
|
14
|
-
* 2. lua.skill.yaml configuration
|
|
12
|
+
* Checks process environment variables (.env file)
|
|
15
13
|
*
|
|
16
14
|
* @param key - The environment variable key to retrieve
|
|
17
15
|
* @returns The environment variable value or undefined if not found
|