diff --git a/packages/basic.gblib/services/GBVMService.ts b/packages/basic.gblib/services/GBVMService.ts index a6b8f596..8f23e85b 100644 --- a/packages/basic.gblib/services/GBVMService.ts +++ b/packages/basic.gblib/services/GBVMService.ts @@ -285,7 +285,7 @@ export class GBVMService extends GBService { // Loads storage custom connections. const path = DialogKeywords.getGBAIPath(min.botId, null); const filePath = Path.join('work', path, 'connections.json'); - let connections = null; + let connections = []; if (Fs.existsSync(filePath)) { connections = JSON.parse(Fs.readFileSync(filePath, 'utf8')); } diff --git a/packages/basic.gblib/services/SystemKeywords.ts b/packages/basic.gblib/services/SystemKeywords.ts index e93dccb3..daefd69a 100644 --- a/packages/basic.gblib/services/SystemKeywords.ts +++ b/packages/basic.gblib/services/SystemKeywords.ts @@ -1745,24 +1745,27 @@ export class SystemKeywords { private flattenJSON(obj, res = {}, separator = '_', parent = null) { for (let key in obj) { - if (typeof obj[key] === 'function') { - continue; - } - if (typeof obj[key] !== 'object' || obj[key] instanceof Date) { - // If not defined already add the flattened field. - - const newKey = `${parent ? parent + separator : ''}${key}`; - if (!res[newKey]) { - res[newKey] = obj[key]; - } else { - GBLog.verbose(`Ignoring duplicated field in flatten operation to storage: ${key}.`); + if (!obj.hasOwnProperty(key) || typeof obj[key] === 'function') { + continue; + } + if (typeof obj[key] !== 'object' || obj[key] instanceof Date) { + // If not defined already, add the flattened field. + const newKey = `${parent ? parent + separator : ''}${key}`; + if (!res.hasOwnProperty(newKey)) { + res[newKey] = obj[key]; + } else { + GBLog.verbose(`Ignoring duplicated field in flatten operation to storage: ${key}.`); + } + } else { + // Create a temporary reference to the nested object to prevent memory leaks. + const tempObj = obj[key]; + this.flattenJSON(tempObj, res, separator, `${parent ? parent + separator : ''}${key}`); + // Clear the reference to avoid holding unnecessary objects in memory. + obj[key] = null; } - } else { - obj[key] = this.flattenJSON(obj[key], res, separator, `${parent ? parent + separator : ''}${key}`); - } } return res; - } +} public async getCustomToken({ pid, tokenName }) { const { min } = await DialogKeywords.getProcessInfo(pid); diff --git a/packages/core.gbapp/services/GBConfigService.ts b/packages/core.gbapp/services/GBConfigService.ts index 9ce9698a..dc56c124 100644 --- a/packages/core.gbapp/services/GBConfigService.ts +++ b/packages/core.gbapp/services/GBConfigService.ts @@ -81,6 +81,9 @@ export class GBConfigService { if (!value) { switch (key) { + case 'PORT': + value = this.getServerPort(); + break; case 'STORAGE_NAME': value = null; break; @@ -105,13 +108,13 @@ export class GBConfigService { case 'MARKETPLACE_ID': value = undefined; break; - case 'LOG_ON_STORAGE': - value = false; - break; - case 'MARKETPLACE_SECRET': + case 'LOG_ON_STORAGE': + value = false; + break; + case 'MARKETPLACE_SECRET': value = undefined; break; - + case 'STORAGE_DIALECT': value = 'sqlite'; break; diff --git a/packages/core.gbapp/services/GBCoreService.ts b/packages/core.gbapp/services/GBCoreService.ts index 7374fa83..bdc02c76 100644 --- a/packages/core.gbapp/services/GBCoreService.ts +++ b/packages/core.gbapp/services/GBCoreService.ts @@ -872,7 +872,7 @@ ENDPOINT_UPDATE=true Fs.cpSync(Path.join(base, `default.gbdialog`), Path.join(gbaiPath, `default.gbdialog`), { errorOnExist: false, force: true, - recursive: true + recursive: true, }); Fs.cpSync(Path.join(base, `default.gbdrive`), Path.join(gbaiPath, `default.gbdrive`), { errorOnExist: false, diff --git a/packages/core.gbapp/services/GBDeployer.ts b/packages/core.gbapp/services/GBDeployer.ts index b67b3789..8aa69217 100644 --- a/packages/core.gbapp/services/GBDeployer.ts +++ b/packages/core.gbapp/services/GBDeployer.ts @@ -422,43 +422,53 @@ export class GBDeployer implements IGBDeployer { /** * Loads all para from tabular file Config.xlsx. */ - public async loadParamsFromTabular(min: GBMinInstance, path): Promise { - const workbook = new Excel.Workbook(); - const data = await workbook.xlsx.readFile(Path.join(path, 'Config.xlsx')); - - let worksheet: any; - for (let t = 0; t < data.worksheets.length; t++) { - worksheet = data.worksheets[t]; - if (worksheet) { - break; + + public async loadParamsFromTabular(min: GBMinInstance, filePath: string): Promise { + if (!Fs.existsSync(filePath)) { + return []; } - } - const rows = worksheet._rows; - GBLogEx.info(min, `Processing ${rows.length} rows from Config file ${path}...`); - let list = []; - - // Skips the header lines. - - for (let index = 0; index < 6; index++) { - rows.shift(); - } - - - let obj = {}; - await asyncPromise.eachSeries(rows, async line => { - - if (line && line._cells[0] && line._cells[1] && line._cells[0].text) { - - // Extracts values from columns in the current line. - - obj[line._cells[0].text] = line._cells[1].text; + + const ext = Path.extname(filePath).toLowerCase(); + let rows: any[] = []; + + const workbook = new Excel.Workbook(); + + if (ext === '.xlsx') { + await workbook.xlsx.readFile(filePath); + let worksheet: any; + for (let t = 0; t < workbook.worksheets.length; t++) { + worksheet = workbook.worksheets[t]; + if (worksheet) { + break; + } + } + rows = worksheet.getSheetValues(); + } else if (ext === '.csv') { + await workbook.csv.readFile(filePath); + let worksheet = workbook.worksheets[0]; // Assuming the CSV file has only one sheet + rows = worksheet.getSheetValues(); + } else { + return []; } - }); - - GBLogEx.info(min, GBUtil.toYAML(list)); - return obj; + + GBLogEx.info(min, `Processing ${rows.length} rows from Config file ${filePath}...`); + + // Skips the header lines. + for (let index = 0; index < 6; index++) { + rows.shift(); + } + + let obj: any = {}; + await asyncPromise.eachSeries(rows, async (line: any) => { + if (line && line._cells[0] && line._cells[1] && line._cells[0].text) { + obj[line._cells[0].text] = line._cells[1].text; + } + }); + + GBLogEx.info(min, GBUtil.toYAML(obj)); + return obj; } - + /** */ public async downloadFolder( @@ -614,9 +624,12 @@ export class GBDeployer implements IGBDeployer { switch (packageType) { case '.gbot': + + // Extracts configuration information from .gbot files. min.instance.params = await this.loadParamsFromTabular(min, localPath); + if (min.instance.params.length){ let connections = []; @@ -643,7 +656,7 @@ export class GBDeployer implements IGBDeployer { // Updates instance object. await this.core.saveInstance(min.instance); - + } break; case '.gbkb': diff --git a/packages/core.gbapp/services/GBMinService.ts b/packages/core.gbapp/services/GBMinService.ts index f0eb1ce3..35d3909f 100644 --- a/packages/core.gbapp/services/GBMinService.ts +++ b/packages/core.gbapp/services/GBMinService.ts @@ -700,7 +700,7 @@ export class GBMinService { }; if (!GBConfigService.get('STORAGE_NAME')) { - config['domain'] = `http://localhost:${process.env.PORT}/directline/${botId}`; + config['domain'] = `http://localhost:${GBConfigService.get('PORT')}/directline/${botId}`; } else { const webchatTokenContainer = await this.getWebchatToken(instance); (config['conversationId'] = webchatTokenContainer.conversationId), @@ -773,7 +773,7 @@ export class GBMinService { }; if (!GBConfigService.get('STORAGE_NAME')) { startRouter(GBServer.globals.server, instance.botId); - config['clientOptions'] = { baseUri: `http://localhost:${process.env.PORT}` }; + config['clientOptions'] = { baseUri: `http://localhost:${GBConfigService.get('PORT')}` }; } const adapter = new BotFrameworkAdapter(config); diff --git a/packages/llm.gblib/services/ChatServices.ts b/packages/llm.gblib/services/ChatServices.ts index dc2f74bc..1a2e3f2f 100644 --- a/packages/llm.gblib/services/ChatServices.ts +++ b/packages/llm.gblib/services/ChatServices.ts @@ -492,7 +492,7 @@ export class ChatServices { }); } else { dataSource = new DataSource({ - type: dialect === dialect as any, + type: dialect as any, host: host, port: port, database: storageName,