lua-cli 2.3.0 → 2.3.2
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/commands/deploy.d.ts +7 -5
- package/dist/commands/deploy.js +34 -15
- package/dist/commands/init.js +6 -6
- package/dist/commands/push.d.ts +7 -5
- package/dist/commands/push.js +44 -21
- package/dist/common/http.client.js +7 -0
- package/dist/errors/auth.error.d.ts +15 -0
- package/dist/errors/auth.error.js +27 -0
- package/dist/errors/index.d.ts +4 -0
- package/dist/errors/index.js +4 -0
- package/dist/index.js +1 -1
- package/dist/interfaces/agent.d.ts +33 -49
- package/dist/services/auth.d.ts +1 -2
- package/dist/services/auth.js +3 -4
- package/dist/utils/cli.js +6 -0
- package/dist/utils/deploy-helpers.d.ts +22 -0
- package/dist/utils/deploy-helpers.js +61 -2
- package/dist/utils/deployment.js +33 -1
- package/dist/utils/dev-server.js +255 -0
- package/dist/utils/init-agent.js +3 -3
- package/dist/utils/push-helpers.d.ts +47 -3
- package/dist/utils/push-helpers.js +162 -10
- package/dist/utils/sandbox.js +18 -5
- package/dist/web/app.css +1302 -465
- package/dist/web/app.js +53 -46
- package/package.json +1 -1
- package/template/package.json +1 -1
- package/dist/web/tools-page.css +0 -381
package/dist/utils/deployment.js
CHANGED
|
@@ -62,9 +62,11 @@ export async function createLegacyDeploymentData(tools, luaDir, indexFile) {
|
|
|
62
62
|
const skillsArray = buildSkillsArray(skillsMetadata, skillToTools, tools);
|
|
63
63
|
// Ensure all skills exist in YAML config and have valid IDs
|
|
64
64
|
const updatedSkillsArray = await ensureSkillsExistInYaml(skillsArray, config);
|
|
65
|
+
// Override versions from YAML config if they exist
|
|
66
|
+
const finalSkillsArray = overrideVersionsFromConfig(updatedSkillsArray, config);
|
|
65
67
|
// Write deployment data
|
|
66
68
|
const deployData = {
|
|
67
|
-
skills:
|
|
69
|
+
skills: finalSkillsArray
|
|
68
70
|
};
|
|
69
71
|
fs.writeFileSync(path.join(luaDir, COMPILE_FILES.DEPLOY_JSON), JSON.stringify(deployData, null, JSON_FORMAT.INDENT));
|
|
70
72
|
// Write individual tool files (uncompressed for debugging)
|
|
@@ -144,6 +146,36 @@ function buildSkillsArray(skillsMetadata, skillToTools, tools) {
|
|
|
144
146
|
};
|
|
145
147
|
});
|
|
146
148
|
}
|
|
149
|
+
/**
|
|
150
|
+
* Overrides skill versions from YAML config.
|
|
151
|
+
* This ensures that any version updates in the YAML take precedence over code versions.
|
|
152
|
+
*
|
|
153
|
+
* @param skillsArray - Array of skills from code
|
|
154
|
+
* @param config - Skill configuration from YAML
|
|
155
|
+
* @returns Skills array with versions overridden from config
|
|
156
|
+
*/
|
|
157
|
+
function overrideVersionsFromConfig(skillsArray, config) {
|
|
158
|
+
// Get version map from YAML config
|
|
159
|
+
const configVersionMap = new Map();
|
|
160
|
+
if (config.skills && Array.isArray(config.skills)) {
|
|
161
|
+
config.skills.forEach((skill) => {
|
|
162
|
+
if (skill.name && skill.version) {
|
|
163
|
+
configVersionMap.set(skill.name, skill.version);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
// Override versions in skills array
|
|
168
|
+
return skillsArray.map(skill => {
|
|
169
|
+
const configVersion = configVersionMap.get(skill.name);
|
|
170
|
+
if (configVersion) {
|
|
171
|
+
return {
|
|
172
|
+
...skill,
|
|
173
|
+
version: configVersion
|
|
174
|
+
};
|
|
175
|
+
}
|
|
176
|
+
return skill;
|
|
177
|
+
});
|
|
178
|
+
}
|
|
147
179
|
/**
|
|
148
180
|
* Writes individual tool files to the .lua directory for debugging.
|
|
149
181
|
* These are uncompressed versions of the tool code.
|
package/dist/utils/dev-server.js
CHANGED
|
@@ -12,6 +12,11 @@ import { executeTool, createBroadcastConsole, loadEnvironmentVariables } from '.
|
|
|
12
12
|
import { getSandboxSkillId } from './sandbox-storage.js';
|
|
13
13
|
import { sendChatMessage } from './dev-api.js';
|
|
14
14
|
import { CORS_HEADERS, HTTP_STATUS, DEV_DEFAULTS } from '../config/dev.constants.js';
|
|
15
|
+
import { BASE_URLS } from '../config/constants.js';
|
|
16
|
+
import ProductApi from '../api/products.api.service.js';
|
|
17
|
+
import BasketApi from '../api/basket.api.service.js';
|
|
18
|
+
import OrderApi from '../api/order.api.service.js';
|
|
19
|
+
import CustomDataApi from '../api/custom.data.api.service.js';
|
|
15
20
|
const __filename = fileURLToPath(import.meta.url);
|
|
16
21
|
const __dirname = path.dirname(__filename);
|
|
17
22
|
/**
|
|
@@ -86,6 +91,26 @@ export function createChatServer(apiKey, agentId, skillId, sandboxId, port) {
|
|
|
86
91
|
handleToolTestEndpoint(req, res, apiKey, agentId, wss);
|
|
87
92
|
return;
|
|
88
93
|
}
|
|
94
|
+
// Products routes
|
|
95
|
+
if (req.url?.startsWith('/api/products')) {
|
|
96
|
+
handleProductsEndpoint(req, res, apiKey, agentId);
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
// Baskets routes
|
|
100
|
+
if (req.url?.startsWith('/api/baskets')) {
|
|
101
|
+
handleBasketsEndpoint(req, res, apiKey, agentId);
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
// Orders routes
|
|
105
|
+
if (req.url?.startsWith('/api/orders')) {
|
|
106
|
+
handleOrdersEndpoint(req, res, apiKey, agentId);
|
|
107
|
+
return;
|
|
108
|
+
}
|
|
109
|
+
// Custom Data routes
|
|
110
|
+
if (req.url?.startsWith('/api/custom-data')) {
|
|
111
|
+
handleCustomDataEndpoint(req, res, apiKey, agentId);
|
|
112
|
+
return;
|
|
113
|
+
}
|
|
89
114
|
if (req.method === 'GET' && req.url === '/') {
|
|
90
115
|
handleIndexEndpoint(req, res, apiKey, agentId, skillId, sandboxId);
|
|
91
116
|
return;
|
|
@@ -553,3 +578,233 @@ function handleStaticFile(req, res, filename, contentType) {
|
|
|
553
578
|
res.end(`${filename} not found`);
|
|
554
579
|
}
|
|
555
580
|
}
|
|
581
|
+
/**
|
|
582
|
+
* Handler for products API using ProductApi service
|
|
583
|
+
*/
|
|
584
|
+
async function handleProductsEndpoint(req, res, apiKey, agentId) {
|
|
585
|
+
const productApi = new ProductApi(BASE_URLS.API, apiKey, agentId);
|
|
586
|
+
try {
|
|
587
|
+
let result;
|
|
588
|
+
if (req.method === 'GET') {
|
|
589
|
+
if (req.url.includes('/search')) {
|
|
590
|
+
const searchQuery = new URL(req.url, 'http://localhost').searchParams.get('searchQuery') || '';
|
|
591
|
+
result = await productApi.search(searchQuery);
|
|
592
|
+
}
|
|
593
|
+
else if (req.url.match(/\/api\/products\/[^/]+$/)) {
|
|
594
|
+
const productId = req.url.split('/').pop();
|
|
595
|
+
result = await productApi.getById(productId);
|
|
596
|
+
}
|
|
597
|
+
else {
|
|
598
|
+
const url = new URL(req.url, 'http://localhost');
|
|
599
|
+
const page = parseInt(url.searchParams.get('page') || '1');
|
|
600
|
+
const limit = parseInt(url.searchParams.get('limit') || '20');
|
|
601
|
+
result = await productApi.get(page, limit);
|
|
602
|
+
}
|
|
603
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
604
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
605
|
+
}
|
|
606
|
+
else if (req.method === 'POST') {
|
|
607
|
+
const body = await new Promise((resolve) => {
|
|
608
|
+
let data = '';
|
|
609
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
610
|
+
req.on('end', () => resolve(data));
|
|
611
|
+
});
|
|
612
|
+
const productData = JSON.parse(body);
|
|
613
|
+
result = await productApi.create(productData);
|
|
614
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
615
|
+
res.end(JSON.stringify({ success: true, data: { product: result } }));
|
|
616
|
+
}
|
|
617
|
+
else if (req.method === 'PUT') {
|
|
618
|
+
const body = await new Promise((resolve) => {
|
|
619
|
+
let data = '';
|
|
620
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
621
|
+
req.on('end', () => resolve(data));
|
|
622
|
+
});
|
|
623
|
+
const productData = JSON.parse(body);
|
|
624
|
+
result = await productApi.update(productData, productData.id);
|
|
625
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
626
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
627
|
+
}
|
|
628
|
+
else if (req.method === 'DELETE') {
|
|
629
|
+
const productId = req.url.split('/').pop();
|
|
630
|
+
result = await productApi.delete(productId);
|
|
631
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
632
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
catch (error) {
|
|
636
|
+
res.writeHead(HTTP_STATUS.SERVER_ERROR, { 'Content-Type': 'application/json' });
|
|
637
|
+
res.end(JSON.stringify({ success: false, error: error.message || 'API error' }));
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
/**
|
|
641
|
+
* Handler for baskets API using BasketApi service
|
|
642
|
+
*/
|
|
643
|
+
async function handleBasketsEndpoint(req, res, apiKey, agentId) {
|
|
644
|
+
const basketApi = new BasketApi(BASE_URLS.API, apiKey, agentId);
|
|
645
|
+
try {
|
|
646
|
+
let result;
|
|
647
|
+
if (req.method === 'GET') {
|
|
648
|
+
if (req.url.match(/\/api\/baskets\/[^/]+$/)) {
|
|
649
|
+
const basketId = req.url.split('/').pop();
|
|
650
|
+
result = await basketApi.getById(basketId);
|
|
651
|
+
}
|
|
652
|
+
else {
|
|
653
|
+
const url = new URL(req.url, 'http://localhost');
|
|
654
|
+
const status = url.searchParams.get('status');
|
|
655
|
+
result = await basketApi.get(status);
|
|
656
|
+
}
|
|
657
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
658
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
659
|
+
}
|
|
660
|
+
else if (req.method === 'POST') {
|
|
661
|
+
const body = await new Promise((resolve) => {
|
|
662
|
+
let data = '';
|
|
663
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
664
|
+
req.on('end', () => resolve(data));
|
|
665
|
+
});
|
|
666
|
+
const basketData = JSON.parse(body);
|
|
667
|
+
result = await basketApi.create(basketData);
|
|
668
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
669
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
670
|
+
}
|
|
671
|
+
else if (req.method === 'DELETE') {
|
|
672
|
+
const basketId = req.url.split('/').pop();
|
|
673
|
+
// Baskets don't have a direct delete in the API, use clear instead
|
|
674
|
+
result = await basketApi.clear(basketId);
|
|
675
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
676
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
catch (error) {
|
|
680
|
+
res.writeHead(HTTP_STATUS.SERVER_ERROR, { 'Content-Type': 'application/json' });
|
|
681
|
+
res.end(JSON.stringify({ success: false, error: error.message || 'API error' }));
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
/**
|
|
685
|
+
* Handler for orders API using OrderApi service
|
|
686
|
+
*/
|
|
687
|
+
async function handleOrdersEndpoint(req, res, apiKey, agentId) {
|
|
688
|
+
const orderApi = new OrderApi(BASE_URLS.API, apiKey, agentId);
|
|
689
|
+
try {
|
|
690
|
+
let result;
|
|
691
|
+
if (req.method === 'GET') {
|
|
692
|
+
if (req.url.match(/\/api\/orders\/[^/]+$/)) {
|
|
693
|
+
const orderId = req.url.split('/').pop();
|
|
694
|
+
result = await orderApi.getById(orderId);
|
|
695
|
+
}
|
|
696
|
+
else {
|
|
697
|
+
const url = new URL(req.url, 'http://localhost');
|
|
698
|
+
const status = url.searchParams.get('status');
|
|
699
|
+
result = await orderApi.get(status);
|
|
700
|
+
}
|
|
701
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
702
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
703
|
+
}
|
|
704
|
+
else if (req.method === 'POST') {
|
|
705
|
+
const body = await new Promise((resolve) => {
|
|
706
|
+
let data = '';
|
|
707
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
708
|
+
req.on('end', () => resolve(data));
|
|
709
|
+
});
|
|
710
|
+
const orderData = JSON.parse(body);
|
|
711
|
+
result = await orderApi.create(orderData);
|
|
712
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
713
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
714
|
+
}
|
|
715
|
+
else if (req.method === 'PUT') {
|
|
716
|
+
if (req.url.includes('/status')) {
|
|
717
|
+
const orderId = req.url.split('/')[3];
|
|
718
|
+
const body = await new Promise((resolve) => {
|
|
719
|
+
let data = '';
|
|
720
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
721
|
+
req.on('end', () => resolve(data));
|
|
722
|
+
});
|
|
723
|
+
const { status } = JSON.parse(body);
|
|
724
|
+
result = await orderApi.updateStatus(status, orderId);
|
|
725
|
+
}
|
|
726
|
+
else {
|
|
727
|
+
const body = await new Promise((resolve) => {
|
|
728
|
+
let data = '';
|
|
729
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
730
|
+
req.on('end', () => resolve(data));
|
|
731
|
+
});
|
|
732
|
+
const orderData = JSON.parse(body);
|
|
733
|
+
const orderId = req.url.split('/').pop();
|
|
734
|
+
result = await orderApi.updateData(orderData, orderId);
|
|
735
|
+
}
|
|
736
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
737
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
catch (error) {
|
|
741
|
+
res.writeHead(HTTP_STATUS.SERVER_ERROR, { 'Content-Type': 'application/json' });
|
|
742
|
+
res.end(JSON.stringify({ success: false, error: error.message || 'API error' }));
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
/**
|
|
746
|
+
* Handler for custom data API using CustomDataApi service
|
|
747
|
+
*/
|
|
748
|
+
async function handleCustomDataEndpoint(req, res, apiKey, agentId) {
|
|
749
|
+
const customDataApi = new CustomDataApi(BASE_URLS.API, apiKey, agentId);
|
|
750
|
+
try {
|
|
751
|
+
let result;
|
|
752
|
+
const pathParts = req.url.split('/');
|
|
753
|
+
const collectionName = pathParts[3]; // /api/custom-data/{collection}
|
|
754
|
+
if (req.method === 'GET') {
|
|
755
|
+
if (req.url.includes('/search')) {
|
|
756
|
+
const url = new URL(req.url, 'http://localhost');
|
|
757
|
+
const searchText = url.searchParams.get('searchText') || '';
|
|
758
|
+
const limit = parseInt(url.searchParams.get('limit') || '10');
|
|
759
|
+
const scoreThreshold = parseFloat(url.searchParams.get('scoreThreshold') || '0.7');
|
|
760
|
+
result = await customDataApi.search(collectionName, searchText, limit, scoreThreshold);
|
|
761
|
+
}
|
|
762
|
+
else if (pathParts.length > 4) {
|
|
763
|
+
const entryId = pathParts[4];
|
|
764
|
+
result = await customDataApi.getEntry(collectionName, entryId);
|
|
765
|
+
}
|
|
766
|
+
else {
|
|
767
|
+
const url = new URL(req.url, 'http://localhost');
|
|
768
|
+
const filter = url.searchParams.get('filter') ? JSON.parse(url.searchParams.get('filter')) : undefined;
|
|
769
|
+
const page = parseInt(url.searchParams.get('page') || '1');
|
|
770
|
+
const limit = parseInt(url.searchParams.get('limit') || '10');
|
|
771
|
+
result = await customDataApi.get(collectionName, filter, page, limit);
|
|
772
|
+
}
|
|
773
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
774
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
775
|
+
}
|
|
776
|
+
else if (req.method === 'POST') {
|
|
777
|
+
const body = await new Promise((resolve) => {
|
|
778
|
+
let data = '';
|
|
779
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
780
|
+
req.on('end', () => resolve(data));
|
|
781
|
+
});
|
|
782
|
+
const { data, searchText } = JSON.parse(body);
|
|
783
|
+
result = await customDataApi.create(collectionName, data, searchText);
|
|
784
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
785
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
786
|
+
}
|
|
787
|
+
else if (req.method === 'PUT') {
|
|
788
|
+
const entryId = pathParts[4];
|
|
789
|
+
const body = await new Promise((resolve) => {
|
|
790
|
+
let data = '';
|
|
791
|
+
req.on('data', (chunk) => { data += chunk; });
|
|
792
|
+
req.on('end', () => resolve(data));
|
|
793
|
+
});
|
|
794
|
+
const updateData = JSON.parse(body);
|
|
795
|
+
result = await customDataApi.update(collectionName, entryId, updateData);
|
|
796
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
797
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
798
|
+
}
|
|
799
|
+
else if (req.method === 'DELETE') {
|
|
800
|
+
const entryId = pathParts[4];
|
|
801
|
+
result = await customDataApi.delete(collectionName, entryId);
|
|
802
|
+
res.writeHead(HTTP_STATUS.OK, { 'Content-Type': 'application/json' });
|
|
803
|
+
res.end(JSON.stringify({ success: true, data: result }));
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
catch (error) {
|
|
807
|
+
res.writeHead(HTTP_STATUS.SERVER_ERROR, { 'Content-Type': 'application/json' });
|
|
808
|
+
res.end(JSON.stringify({ success: false, error: error.message || 'API error' }));
|
|
809
|
+
}
|
|
810
|
+
}
|
package/dist/utils/init-agent.js
CHANGED
|
@@ -80,9 +80,9 @@ export async function createNewAgent(apiKey, agentType, businessConfig, metadata
|
|
|
80
80
|
// Wait for agent to be ready
|
|
81
81
|
await waitForAgentReady();
|
|
82
82
|
// Validate required fields from API response
|
|
83
|
-
const agentId = createAgentResult.data?.
|
|
84
|
-
const agentName = createAgentResult.data?.
|
|
85
|
-
const orgId = createAgentResult.data?.
|
|
83
|
+
const agentId = createAgentResult.data?.agentId;
|
|
84
|
+
const agentName = createAgentResult.data?.name;
|
|
85
|
+
const orgId = createAgentResult.data?.org?.id;
|
|
86
86
|
if (!agentId || !agentName || !orgId) {
|
|
87
87
|
throw new Error("Failed to create agent: Missing required fields in API response");
|
|
88
88
|
}
|
|
@@ -2,6 +2,28 @@
|
|
|
2
2
|
* Push Helper Utilities
|
|
3
3
|
* Helper functions for the push command
|
|
4
4
|
*/
|
|
5
|
+
/**
|
|
6
|
+
* Selected skill for pushing.
|
|
7
|
+
*/
|
|
8
|
+
export interface SelectedSkill {
|
|
9
|
+
name: string;
|
|
10
|
+
version: string;
|
|
11
|
+
skillId: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Prompts user to select a skill from available skills.
|
|
15
|
+
*
|
|
16
|
+
* @param skills - Array of available skills
|
|
17
|
+
* @returns Selected skill
|
|
18
|
+
*/
|
|
19
|
+
export declare function promptSkillSelection(skills: SelectedSkill[]): Promise<SelectedSkill>;
|
|
20
|
+
/**
|
|
21
|
+
* Prompts user to confirm or update the version.
|
|
22
|
+
*
|
|
23
|
+
* @param currentVersion - Current version of the skill
|
|
24
|
+
* @returns Confirmed or updated version
|
|
25
|
+
*/
|
|
26
|
+
export declare function promptVersionConfirmOrUpdate(currentVersion: string): Promise<string>;
|
|
5
27
|
/**
|
|
6
28
|
* Reads the version from skill configuration.
|
|
7
29
|
*
|
|
@@ -29,10 +51,32 @@ export declare function confirmVersionPush(version: string): Promise<boolean>;
|
|
|
29
51
|
*/
|
|
30
52
|
export declare function validatePushConfig(config: any): void;
|
|
31
53
|
/**
|
|
32
|
-
*
|
|
54
|
+
* Gets available skills from configuration.
|
|
55
|
+
*
|
|
56
|
+
* @param config - Skill configuration
|
|
57
|
+
* @returns Array of available skills
|
|
58
|
+
*/
|
|
59
|
+
export declare function getAvailableSkills(config: any): SelectedSkill[];
|
|
60
|
+
/**
|
|
61
|
+
* Updates a skill's version in the YAML configuration file.
|
|
62
|
+
*
|
|
63
|
+
* @param skillName - Name of the skill to update
|
|
64
|
+
* @param newVersion - New version to set
|
|
65
|
+
*/
|
|
66
|
+
export declare function updateSkillVersionInYaml(skillName: string, newVersion: string): void;
|
|
67
|
+
/**
|
|
68
|
+
* Validates that deploy data matches configuration for a specific skill.
|
|
33
69
|
*
|
|
34
70
|
* @param deployData - Deploy data from deploy.json
|
|
35
|
-
* @param
|
|
71
|
+
* @param selectedSkill - The selected skill to validate
|
|
36
72
|
* @throws Error if deploy data is invalid or version mismatch
|
|
37
73
|
*/
|
|
38
|
-
export declare function validateDeployData(deployData: any,
|
|
74
|
+
export declare function validateDeployData(deployData: any, selectedSkill: SelectedSkill): void;
|
|
75
|
+
/**
|
|
76
|
+
* Extracts the deploy data for a specific skill from the deploy.json.
|
|
77
|
+
*
|
|
78
|
+
* @param deployData - Deploy data from deploy.json
|
|
79
|
+
* @param skillName - Name of the skill to extract
|
|
80
|
+
* @returns The deploy data for the specific skill
|
|
81
|
+
*/
|
|
82
|
+
export declare function getSkillDeployData(deployData: any, skillName: string): any;
|
|
@@ -7,6 +7,72 @@ import path from 'path';
|
|
|
7
7
|
import inquirer from 'inquirer';
|
|
8
8
|
import { readSkillConfig } from './files.js';
|
|
9
9
|
import { clearPromptLines } from './cli.js';
|
|
10
|
+
/**
|
|
11
|
+
* Prompts user to select a skill from available skills.
|
|
12
|
+
*
|
|
13
|
+
* @param skills - Array of available skills
|
|
14
|
+
* @returns Selected skill
|
|
15
|
+
*/
|
|
16
|
+
export async function promptSkillSelection(skills) {
|
|
17
|
+
const skillChoices = skills.map((skill) => ({
|
|
18
|
+
name: `${skill.name} (v${skill.version})`,
|
|
19
|
+
value: skill
|
|
20
|
+
}));
|
|
21
|
+
const { selectedSkill } = await inquirer.prompt([
|
|
22
|
+
{
|
|
23
|
+
type: "list",
|
|
24
|
+
name: "selectedSkill",
|
|
25
|
+
message: "Select a skill to push:",
|
|
26
|
+
choices: skillChoices
|
|
27
|
+
}
|
|
28
|
+
]);
|
|
29
|
+
clearPromptLines(2);
|
|
30
|
+
return selectedSkill;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Prompts user to confirm or update the version.
|
|
34
|
+
*
|
|
35
|
+
* @param currentVersion - Current version of the skill
|
|
36
|
+
* @returns Confirmed or updated version
|
|
37
|
+
*/
|
|
38
|
+
export async function promptVersionConfirmOrUpdate(currentVersion) {
|
|
39
|
+
const { versionAction } = await inquirer.prompt([
|
|
40
|
+
{
|
|
41
|
+
type: "list",
|
|
42
|
+
name: "versionAction",
|
|
43
|
+
message: `Current version is ${currentVersion}. What would you like to do?`,
|
|
44
|
+
choices: [
|
|
45
|
+
{ name: `Keep current version (${currentVersion})`, value: "keep" },
|
|
46
|
+
{ name: "Update version", value: "update" }
|
|
47
|
+
]
|
|
48
|
+
}
|
|
49
|
+
]);
|
|
50
|
+
clearPromptLines(2);
|
|
51
|
+
if (versionAction === "update") {
|
|
52
|
+
const { newVersion } = await inquirer.prompt([
|
|
53
|
+
{
|
|
54
|
+
type: "input",
|
|
55
|
+
name: "newVersion",
|
|
56
|
+
message: "Enter new version:",
|
|
57
|
+
default: currentVersion,
|
|
58
|
+
validate: (input) => {
|
|
59
|
+
if (!input || input.trim() === "") {
|
|
60
|
+
return "Version cannot be empty";
|
|
61
|
+
}
|
|
62
|
+
// Basic semver validation
|
|
63
|
+
const semverRegex = /^\d+\.\d+\.\d+(-[a-zA-Z0-9.-]+)?$/;
|
|
64
|
+
if (!semverRegex.test(input.trim())) {
|
|
65
|
+
return "Version must follow semver format (e.g., 1.0.0, 1.0.0-alpha.1)";
|
|
66
|
+
}
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
]);
|
|
71
|
+
clearPromptLines(2);
|
|
72
|
+
return newVersion.trim();
|
|
73
|
+
}
|
|
74
|
+
return currentVersion;
|
|
75
|
+
}
|
|
10
76
|
/**
|
|
11
77
|
* Reads the version from skill configuration.
|
|
12
78
|
*
|
|
@@ -57,28 +123,114 @@ export function validatePushConfig(config) {
|
|
|
57
123
|
if (!config) {
|
|
58
124
|
throw new Error("No lua.skill.yaml found. Please run this command from a skill directory.");
|
|
59
125
|
}
|
|
60
|
-
if (!config.skill?.version) {
|
|
61
|
-
throw new Error("No version found in skill configuration");
|
|
62
|
-
}
|
|
63
126
|
if (!config.agent?.agentId) {
|
|
64
127
|
throw new Error("Missing agentId in skill configuration");
|
|
65
128
|
}
|
|
66
|
-
|
|
67
|
-
|
|
129
|
+
// Check for new multi-skill format
|
|
130
|
+
if (config.skills && Array.isArray(config.skills) && config.skills.length > 0) {
|
|
131
|
+
return; // Valid multi-skill config
|
|
132
|
+
}
|
|
133
|
+
// Check for legacy single-skill format
|
|
134
|
+
if (config.skill?.version && config.skill?.skillId) {
|
|
135
|
+
return; // Valid legacy config
|
|
68
136
|
}
|
|
137
|
+
throw new Error("No skills found in configuration. Please compile your skill first.");
|
|
69
138
|
}
|
|
70
139
|
/**
|
|
71
|
-
*
|
|
140
|
+
* Gets available skills from configuration.
|
|
141
|
+
*
|
|
142
|
+
* @param config - Skill configuration
|
|
143
|
+
* @returns Array of available skills
|
|
144
|
+
*/
|
|
145
|
+
export function getAvailableSkills(config) {
|
|
146
|
+
// Check for new multi-skill format
|
|
147
|
+
if (config.skills && Array.isArray(config.skills) && config.skills.length > 0) {
|
|
148
|
+
return config.skills.map((skill) => ({
|
|
149
|
+
name: skill.name,
|
|
150
|
+
version: skill.version,
|
|
151
|
+
skillId: skill.skillId
|
|
152
|
+
}));
|
|
153
|
+
}
|
|
154
|
+
// Fallback to legacy single-skill format
|
|
155
|
+
if (config.skill) {
|
|
156
|
+
return [{
|
|
157
|
+
name: config.skill.name || 'unnamed-skill',
|
|
158
|
+
version: config.skill.version,
|
|
159
|
+
skillId: config.skill.skillId
|
|
160
|
+
}];
|
|
161
|
+
}
|
|
162
|
+
return [];
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Updates a skill's version in the YAML configuration file.
|
|
166
|
+
*
|
|
167
|
+
* @param skillName - Name of the skill to update
|
|
168
|
+
* @param newVersion - New version to set
|
|
169
|
+
*/
|
|
170
|
+
export function updateSkillVersionInYaml(skillName, newVersion) {
|
|
171
|
+
const yamlPath = path.join(process.cwd(), 'lua.skill.yaml');
|
|
172
|
+
if (!fs.existsSync(yamlPath)) {
|
|
173
|
+
throw new Error("lua.skill.yaml not found");
|
|
174
|
+
}
|
|
175
|
+
const yamlContent = fs.readFileSync(yamlPath, 'utf8');
|
|
176
|
+
// Simple regex-based replacement to preserve formatting
|
|
177
|
+
// Match the skill entry and update its version
|
|
178
|
+
const skillPattern = new RegExp(`(- name: ${skillName.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')}\\s+version: )[^\\n]+`, 'g');
|
|
179
|
+
const updatedContent = yamlContent.replace(skillPattern, `$1${newVersion}`);
|
|
180
|
+
if (updatedContent === yamlContent) {
|
|
181
|
+
// Try legacy format
|
|
182
|
+
const legacyPattern = /(\s+version: )[^\n]+/;
|
|
183
|
+
const legacyUpdated = yamlContent.replace(legacyPattern, `$1${newVersion}`);
|
|
184
|
+
fs.writeFileSync(yamlPath, legacyUpdated, 'utf8');
|
|
185
|
+
}
|
|
186
|
+
else {
|
|
187
|
+
fs.writeFileSync(yamlPath, updatedContent, 'utf8');
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Validates that deploy data matches configuration for a specific skill.
|
|
72
192
|
*
|
|
73
193
|
* @param deployData - Deploy data from deploy.json
|
|
74
|
-
* @param
|
|
194
|
+
* @param selectedSkill - The selected skill to validate
|
|
75
195
|
* @throws Error if deploy data is invalid or version mismatch
|
|
76
196
|
*/
|
|
77
|
-
export function validateDeployData(deployData,
|
|
197
|
+
export function validateDeployData(deployData, selectedSkill) {
|
|
78
198
|
if (!deployData) {
|
|
79
199
|
throw new Error("No deploy.json found. Compilation may have failed.");
|
|
80
200
|
}
|
|
81
|
-
|
|
82
|
-
|
|
201
|
+
// Handle multi-skill format
|
|
202
|
+
if (deployData.skills && Array.isArray(deployData.skills)) {
|
|
203
|
+
const skillData = deployData.skills.find((s) => s.name === selectedSkill.name);
|
|
204
|
+
if (!skillData) {
|
|
205
|
+
throw new Error(`Skill "${selectedSkill.name}" not found in deploy.json. Compilation may have failed.`);
|
|
206
|
+
}
|
|
207
|
+
if (skillData.version !== selectedSkill.version) {
|
|
208
|
+
throw new Error(`Version mismatch for "${selectedSkill.name}": ` +
|
|
209
|
+
`config has ${selectedSkill.version}, deploy.json has ${skillData.version || 'undefined'}`);
|
|
210
|
+
}
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
// Handle legacy single-skill format
|
|
214
|
+
if (deployData.version !== selectedSkill.version) {
|
|
215
|
+
throw new Error(`Version mismatch: config has ${selectedSkill.version}, deploy.json has ${deployData.version || 'undefined'}`);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
/**
|
|
219
|
+
* Extracts the deploy data for a specific skill from the deploy.json.
|
|
220
|
+
*
|
|
221
|
+
* @param deployData - Deploy data from deploy.json
|
|
222
|
+
* @param skillName - Name of the skill to extract
|
|
223
|
+
* @returns The deploy data for the specific skill
|
|
224
|
+
*/
|
|
225
|
+
export function getSkillDeployData(deployData, skillName) {
|
|
226
|
+
// Handle multi-skill format
|
|
227
|
+
if (deployData.skills && Array.isArray(deployData.skills)) {
|
|
228
|
+
const skillData = deployData.skills.find((s) => s.name === skillName);
|
|
229
|
+
if (!skillData) {
|
|
230
|
+
throw new Error(`Skill "${skillName}" not found in deploy.json`);
|
|
231
|
+
}
|
|
232
|
+
return skillData;
|
|
83
233
|
}
|
|
234
|
+
// Handle legacy single-skill format
|
|
235
|
+
return deployData;
|
|
84
236
|
}
|
package/dist/utils/sandbox.js
CHANGED
|
@@ -131,6 +131,19 @@ export function createSandbox(options) {
|
|
|
131
131
|
// };
|
|
132
132
|
// Create console object (use custom console if provided, otherwise default)
|
|
133
133
|
const consoleObj = customConsole || console;
|
|
134
|
+
// Create API service instances
|
|
135
|
+
const userService = new UserDataApiService(BASE_URLS.API, apiKey, agentId);
|
|
136
|
+
const productService = new ProductApiService(BASE_URLS.API, apiKey, agentId);
|
|
137
|
+
const dataService = new CustomDataApiService(BASE_URLS.API, apiKey, agentId);
|
|
138
|
+
const basketsService = new BasketApiService(BASE_URLS.API, apiKey, agentId);
|
|
139
|
+
const orderService = new OrderApiService(BASE_URLS.API, apiKey, agentId);
|
|
140
|
+
// Override User service methods if needed
|
|
141
|
+
// Example: Override the update method
|
|
142
|
+
// const originalUpdate = userService.update.bind(userService);
|
|
143
|
+
// userService.update = async (data: any) => {
|
|
144
|
+
// console.log('Custom update logic here');
|
|
145
|
+
// return await originalUpdate(data);
|
|
146
|
+
// };
|
|
134
147
|
// Create comprehensive polyfills for browser/Node.js APIs
|
|
135
148
|
const polyfills = {
|
|
136
149
|
// AbortController polyfill
|
|
@@ -257,11 +270,11 @@ export function createSandbox(options) {
|
|
|
257
270
|
null: null,
|
|
258
271
|
Infinity: Infinity,
|
|
259
272
|
NaN: NaN,
|
|
260
|
-
User:
|
|
261
|
-
Product:
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
Order:
|
|
273
|
+
User: userService,
|
|
274
|
+
Product: productService,
|
|
275
|
+
Data: dataService,
|
|
276
|
+
Baskets: basketsService,
|
|
277
|
+
Order: orderService,
|
|
265
278
|
// Environment variables function
|
|
266
279
|
env: (key) => envVars[key]
|
|
267
280
|
};
|