@tiledesk/tiledesk-server 2.15.8 → 2.17.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/routes/request.js CHANGED
@@ -318,6 +318,10 @@ router.patch('/:requestid', function (req, res) {
318
318
  return res.status(404).send({ success: false, msg: 'Request not found' });
319
319
  }
320
320
 
321
+ if (update.workingStatus !== undefined) {
322
+ requestEvent.emit('request.workingStatus.update', { request });
323
+ }
324
+
321
325
  requestEvent.emit("request.update", request);
322
326
  requestEvent.emit("request.update.comment", { comment: "PATCH", request: request }); //Deprecated
323
327
  requestEvent.emit("request.updated", { comment: "PATCH", request: request, patch: update });
@@ -1376,6 +1380,10 @@ router.get('/', function (req, res, next) {
1376
1380
  }
1377
1381
  }
1378
1382
 
1383
+ if (req.query.workingStatus?.ne) {
1384
+ query.workingStatus = { $ne: req.query.workingStatus.ne };
1385
+ }
1386
+
1379
1387
  if (req.query.priority) {
1380
1388
  query.priority = req.query.priority;
1381
1389
  }
@@ -1421,10 +1429,31 @@ router.get('/', function (req, res, next) {
1421
1429
  query["attributes.fully_abandoned"] = true
1422
1430
  }
1423
1431
 
1432
+ if (req.query.rated && (req.query.rated === true || req.query.rated === 'true')) {
1433
+ query.rating = { $exists: true }
1434
+ }
1435
+
1424
1436
  if (req.query.draft && (req.query.draft === 'false' || req.query.draft === false)) {
1425
1437
  query.draft = { $in: [false, null] }
1426
1438
  }
1427
1439
 
1440
+ let inWStatus = req.query.workingStatus?.in?.split(',').map(s => s.trim()).filter(Boolean);
1441
+ let ninWStatus = req.query.workingStatus?.nin?.split(',').map(s => s.trim()).filter(Boolean);
1442
+
1443
+ if (ninWStatus && ninWStatus.length > 0) {
1444
+ if (ninWStatus.length === 1) {
1445
+ query.workingStatus = { $ne: ninWStatus[0] };
1446
+ } else {
1447
+ query.workingStatus = { $nin: ninWStatus };
1448
+ }
1449
+ } else if (inWStatus && inWStatus.length > 0) {
1450
+ if (inWStatus.length === 1) {
1451
+ query.workingStatus = inWStatus[0];
1452
+ } else {
1453
+ query.workingStatus = { $in: inWStatus };
1454
+ }
1455
+ }
1456
+
1428
1457
  var projection = undefined;
1429
1458
 
1430
1459
  if (req.query.full_text) {
@@ -1872,57 +1901,67 @@ router.get('/csv', function (req, res, next) {
1872
1901
 
1873
1902
  var limit = 100000; // Number of request per page
1874
1903
  var page = 0;
1904
+ var skip = 0;
1905
+ let statusArray = [];
1906
+ var projectuser = req.projectuser;
1907
+ let filterRangeField = req.query.filterRangeField || 'createdAt';
1875
1908
 
1876
1909
  if (req.query.page) {
1877
1910
  page = req.query.page;
1878
1911
  }
1879
1912
 
1880
- var skip = page * limit;
1913
+ skip = page * limit;
1881
1914
  winston.debug('REQUEST ROUTE - SKIP PAGE ', skip);
1882
1915
 
1883
- let statusArray = [];
1916
+ // Default query (same as GET /)
1917
+ var query = { "id_project": req.projectid, "status": { $lt: 1000, $nin: [50, 150] }, preflight: false };
1884
1918
 
1885
- var query = { "id_project": req.projectid };
1919
+ if (req.user instanceof Subscription) {
1920
+ // All request
1921
+ } else if (projectuser && (projectuser.role == "owner" || projectuser.role == "admin")) {
1922
+ if (req.query.mine) {
1923
+ query["$or"] = [{ "snapshot.agents.id_user": req.user.id }, { "participants": req.user.id }];
1924
+ }
1925
+ } else {
1926
+ query["$or"] = [{ "snapshot.agents.id_user": req.user.id }, { "participants": req.user.id }];
1927
+ }
1886
1928
 
1887
1929
  if (req.query.dept_id) {
1888
1930
  query.department = req.query.dept_id;
1889
1931
  winston.debug('REQUEST ROUTE - QUERY DEPT ID', query.department);
1890
1932
  }
1891
1933
 
1934
+ if (req.query.requester_email) {
1935
+ query["snapshot.lead.email"] = req.query.requester_email;
1936
+ }
1937
+
1892
1938
  if (req.query.full_text) {
1893
1939
  winston.debug('req.query.fulltext', req.query.full_text);
1894
1940
  query.$text = { "$search": req.query.full_text };
1895
1941
  }
1896
1942
 
1897
- if (req.query.status) {
1943
+ if (req.query.phone) {
1944
+ var phoneDigits = req.query.phone.replace(/\D/g, '');
1945
+ if (phoneDigits.length > 0) {
1946
+ query["contact.phone"] = new RegExp(phoneDigits);
1947
+ }
1948
+ }
1949
+
1950
+ var history_search = false;
1898
1951
 
1952
+ // Multiple status management (same as GET /)
1953
+ if (req.query.status) {
1899
1954
  if (req.query.status === 'all') {
1900
1955
  delete query.status;
1901
1956
  } else {
1902
- let statusArray = req.query.status.split(',').map(Number);
1903
- statusArray = statusArray.map(status => { return isNaN(status) ? null : status }).filter(status => status !== null)
1957
+ statusArray = req.query.status.split(',').map(Number);
1958
+ statusArray = statusArray.map(status => { return isNaN(status) ? null : status }).filter(status => status !== null);
1904
1959
  if (statusArray.length > 0) {
1905
- query.status = {
1906
- $in: statusArray
1907
- }
1960
+ query.status = { $in: statusArray };
1908
1961
  } else {
1909
1962
  delete query.status;
1910
1963
  }
1911
1964
  }
1912
-
1913
- if (statusArray.length > 0) {
1914
- query.status = {
1915
- $in: statusArray
1916
- }
1917
- }
1918
-
1919
- }
1920
-
1921
- if (req.query.preflight) {
1922
- let preflight = (req.query.preflight === 'false');
1923
- if (preflight) {
1924
- query.preflight = false;
1925
- }
1926
1965
  }
1927
1966
 
1928
1967
  if (req.query.lead) {
@@ -1942,49 +1981,96 @@ router.get('/csv', function (req, res, next) {
1942
1981
  query.hasBot = req.query.hasbot;
1943
1982
  }
1944
1983
 
1945
- /**
1946
- * DATE RANGE */
1947
- if (req.query.start_date && req.query.end_date) {
1948
- winston.debug('REQUEST ROUTE - REQ QUERY start_date ', req.query.start_date);
1949
- winston.debug('REQUEST ROUTE - REQ QUERY end_date ', req.query.end_date);
1984
+ if (req.query.tags) {
1985
+ query["tags.tag"] = req.query.tags;
1986
+ }
1987
+
1988
+ if (req.query.location) {
1989
+ query.location = req.query.location;
1990
+ }
1991
+
1992
+ if (req.query.ticket_id) {
1993
+ query.ticket_id = req.query.ticket_id;
1994
+ }
1995
+
1996
+ if (req.query.preflight && (req.query.preflight === 'true' || req.query.preflight === true)) {
1997
+ delete query.preflight;
1998
+ }
1999
+
2000
+ let timezone = req.query.timezone || 'Europe/Rome';
2001
+ let queryDateRange = false;
2002
+ let queryStartDate;
2003
+ let queryEndDate;
2004
+
2005
+ if (history_search === true && req.project && req.project.profile && ((req.project.profile.type === 'free' && req.project.trialExpired === true) || (req.project.profile.type === 'payment' && req.project.isActiveSubscription === false))) {
2006
+ queryDateRange = true;
2007
+ queryStartDate = moment().subtract(14, "days").format("YYYY/MM/DD");
2008
+ queryEndDate = null;
2009
+ }
1950
2010
 
1951
- /**
1952
- * USING TIMESTAMP in MS */
1953
- // var formattedStartDate = new Date(+req.query.start_date);
1954
- // var formattedEndDate = new Date(+req.query.end_date);
1955
- // query.createdAt = { $gte: formattedStartDate, $lte: formattedEndDate }
2011
+ if (req.query.start_date || req.query.end_date) {
2012
+ queryDateRange = true;
2013
+ queryStartDate = req.query.start_date;
2014
+ queryEndDate = req.query.end_date;
2015
+ } else if (req.query.start_date_time || req.query.end_date_time) {
2016
+ queryDateRange = true;
2017
+ queryStartDate = req.query.start_date_time;
2018
+ queryEndDate = req.query.end_date_time;
2019
+ }
1956
2020
 
2021
+ if (queryDateRange) {
2022
+ try {
2023
+ let rangeQuery = datesUtil.createDateRangeQuery(queryStartDate, queryEndDate, timezone, filterRangeField);
2024
+ Object.assign(query, rangeQuery);
2025
+ } catch (error) {
2026
+ winston.error('Error creating date range query: ', error);
2027
+ return res.status(500).send({ success: false, error: error?.message });
2028
+ }
2029
+ }
1957
2030
 
1958
- /**
1959
- * USING MOMENT */
1960
- var startDate = moment(req.query.start_date, 'DD/MM/YYYY').format('YYYY-MM-DD');
1961
- var endDate = moment(req.query.end_date, 'DD/MM/YYYY').format('YYYY-MM-DD');
2031
+ if (req.query.snap_department_routing) {
2032
+ query["snapshot.department.routing"] = req.query.snap_department_routing;
2033
+ }
1962
2034
 
1963
- winston.debug('REQUEST ROUTE - REQ QUERY FORMATTED START DATE ', startDate);
1964
- winston.debug('REQUEST ROUTE - REQ QUERY FORMATTED END DATE ', endDate);
2035
+ if (req.query.snap_department_default) {
2036
+ query["snapshot.department.default"] = req.query.snap_department_default;
2037
+ }
2038
+
2039
+ if (req.query.snap_department_id_bot) {
2040
+ query["snapshot.department.id_bot"] = req.query.snap_department_id_bot;
2041
+ }
1965
2042
 
1966
- // ADD ONE DAY TO THE END DAY
1967
- var date = new Date(endDate);
1968
- var newdate = new Date(date);
1969
- var endDate_plusOneDay = newdate.setDate(newdate.getDate() + 1);
1970
- winston.debug('REQUEST ROUTE - REQ QUERY FORMATTED END DATE + 1 DAY ', endDate_plusOneDay);
1971
- // var endDate_plusOneDay = moment('2018-09-03').add(1, 'd')
1972
- // var endDate_plusOneDay = endDate.add(1).day();
1973
- // var toDate = new Date(Date.parse(endDate_plusOneDay)).toISOString()
2043
+ if (req.query.snap_department_id_bot_exists) {
2044
+ query["snapshot.department.id_bot"] = { "$exists": req.query.snap_department_id_bot_exists };
2045
+ }
1974
2046
 
1975
- query.createdAt = { $gte: new Date(Date.parse(startDate)).toISOString(), $lte: new Date(endDate_plusOneDay).toISOString() }
1976
- winston.debug('REQUEST ROUTE - QUERY CREATED AT ', query.createdAt);
2047
+ if (req.query.snap_lead_lead_id) {
2048
+ query["snapshot.lead.lead_id"] = req.query.snap_lead_lead_id;
2049
+ }
1977
2050
 
1978
- } else if (req.query.start_date && !req.query.end_date) {
1979
- winston.debug('REQUEST ROUTE - REQ QUERY END DATE IS EMPTY (so search only for start date)');
1980
- var startDate = moment(req.query.start_date, 'DD/MM/YYYY').format('YYYY-MM-DD');
2051
+ if (req.query.snap_lead_email) {
2052
+ query["snapshot.lead.email"] = req.query.snap_lead_email;
2053
+ }
1981
2054
 
1982
- query.createdAt = { $gte: new Date(Date.parse(startDate)).toISOString() };
1983
- winston.debug('REQUEST ROUTE - QUERY CREATED AT (only for start date)', query.createdAt);
2055
+ if (req.query.smartAssignment) {
2056
+ query.smartAssignment = req.query.smartAssignment;
1984
2057
  }
1985
- winston.debug("csv query", query);
1986
2058
 
1987
- var direction = 1; //-1 descending , 1 ascending
2059
+ if (req.query.channel) {
2060
+ if (req.query.channel === "offline") {
2061
+ query["channel.name"] = { "$in": ["email", "form"] };
2062
+ } else if (req.query.channel === "online") {
2063
+ query["channel.name"] = { "$nin": ["email", "form"] };
2064
+ } else {
2065
+ query["channel.name"] = req.query.channel;
2066
+ }
2067
+ }
2068
+
2069
+ if (req.query.priority) {
2070
+ query.priority = req.query.priority;
2071
+ }
2072
+
2073
+ var direction = -1; // same default as GET /
1988
2074
  if (req.query.direction) {
1989
2075
  direction = req.query.direction;
1990
2076
  }
@@ -1998,20 +2084,9 @@ router.get('/csv', function (req, res, next) {
1998
2084
 
1999
2085
  var sortQuery = {};
2000
2086
  sortQuery[sortField] = direction;
2001
-
2002
2087
  winston.debug("sort query", sortQuery);
2003
2088
 
2004
- if (req.query.channel) {
2005
- if (req.query.channel === "offline") {
2006
- query["channel.name"] = { "$in": ["email", "form"] }
2007
- } else if (req.query.channel === "online") {
2008
- query["channel.name"] = { "$nin": ["email", "form"] }
2009
- } else {
2010
- query["channel.name"] = req.query.channel
2011
- }
2012
- }
2013
-
2014
- // VOICE FILTERS - Start
2089
+ // VOICE FILTERS
2015
2090
  if (req.query.caller) {
2016
2091
  query["attributes.caller_phone"] = req.query.caller;
2017
2092
  }
@@ -2021,45 +2096,52 @@ router.get('/csv', function (req, res, next) {
2021
2096
  if (req.query.call_id) {
2022
2097
  query["attributes.call_id"] = req.query.call_id;
2023
2098
  }
2024
- // VOICE FILTERS - End
2025
-
2026
- // TODO ORDER BY SCORE
2027
- // return Faq.find(query, {score: { $meta: "textScore" } })
2028
- // .sort( { score: { $meta: "textScore" } } ) //https://docs.mongodb.com/manual/reference/operator/query/text/#sort-by-text-search-score
2029
-
2030
- // aggiungi filtro per data marco
2031
2099
 
2032
2100
  if (req.query.duration && req.query.duration_op) {
2033
2101
  let duration = Number(req.query.duration) * 60 * 1000;
2034
2102
  if (req.query.duration_op === 'gt') {
2035
- query.duration = { $gte: duration }
2103
+ query.duration = { $gte: duration };
2036
2104
  } else if (req.query.duration_op === 'lt') {
2037
- query.duration = { $lte: duration }
2105
+ query.duration = { $lte: duration };
2038
2106
  } else {
2039
- winston.verbose("Duration operator can be 'gt' or 'lt'. Skip duration_op " + req.query.duration_op)
2107
+ winston.verbose("Duration operator can be 'gt' or 'lt'. Skip duration_op " + req.query.duration_op);
2040
2108
  }
2041
2109
  }
2042
2110
 
2111
+ if (req.query.abandonded && (req.query.abandoned === true || req.query.abandoned === 'true')) {
2112
+ query["attributes.fully_abandoned"] = true;
2113
+ }
2114
+
2115
+ if (req.query.rated && (req.query.rated === true || req.query.rated === 'true')) {
2116
+ query.rating = { $exists: true };
2117
+ }
2118
+
2043
2119
  if (req.query.draft && (req.query.draft === 'false' || req.query.draft === false)) {
2044
- query.draft = { $in: [false, null] }
2120
+ query.draft = { $in: [false, null] };
2045
2121
  }
2046
2122
 
2047
- winston.debug('REQUEST ROUTE - REQUEST FIND ', query)
2048
- return Request.find(query, '-transcript -status -__v').
2123
+ var csvProjection = '-transcript -status -__v';
2124
+ if (req.query.full_text && req.query.no_textscore != "true" && req.query.no_textscore != true) {
2125
+ winston.verbose('fulltext projection on');
2126
+ csvProjection = { transcript: 0, status: 0, __v: 0, score: { $meta: "textScore" } };
2127
+ }
2128
+
2129
+ winston.debug("csv query", query);
2130
+ winston.debug('REQUEST ROUTE - REQUEST FIND ', query);
2131
+
2132
+ var q = Request.find(query, csvProjection).
2049
2133
  skip(skip).limit(limit).
2050
- //populate('department', {'_id':-1, 'name':1}).
2051
2134
  populate('department').
2052
2135
  populate('lead').
2053
- // populate('participatingBots').
2054
- // populate('participatingAgents').
2055
- lean().
2056
- // populate({
2057
- // path: 'department',
2058
- // //select: { '_id': -1,'name':1}
2059
- // select: {'name':1}
2060
- // }).
2061
- sort(sortQuery).
2062
- exec(function (err, requests) {
2136
+ lean();
2137
+
2138
+ if (req.query.full_text && req.query.no_textscore != "true" && req.query.no_textscore != true) {
2139
+ q.sort({ score: { $meta: "textScore" } });
2140
+ } else {
2141
+ q.sort(sortQuery);
2142
+ }
2143
+
2144
+ return q.exec(function (err, requests) {
2063
2145
  if (err) {
2064
2146
  winston.error('REQUEST ROUTE - REQUEST FIND ERR ', err)
2065
2147
  return res.status(500).send({ success: false, msg: 'Error getting csv requests.', err: err });
package/routes/webhook.js CHANGED
@@ -193,6 +193,11 @@ router.post('/kb/reindex', async (req, res) => {
193
193
  embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
194
194
  json.embedding = embedding;
195
195
 
196
+ const situated_context = aiManager.normalizeSituatedContext();
197
+ if (situated_context) {
198
+ json.situated_context = situated_context;
199
+ }
200
+
196
201
  let resources = [];
197
202
  resources.push(json);
198
203
 
@@ -5,6 +5,7 @@ const { Scheduler } = require("./Scheduler");
5
5
  const { default: Sitemapper } = require('sitemapper');
6
6
  const winston = require('../config/winston');
7
7
  const configGlobal = require('../config/global');
8
+ const _ = require('lodash');
8
9
  const JobManager = require('../utils/jobs-worker-queue-manager/JobManagerV2');
9
10
 
10
11
  // Constants
@@ -19,6 +20,7 @@ const default_engine = require('../config/kb/engine');
19
20
  const default_engine_hybrid = require('../config/kb/engine.hybrid');
20
21
  const default_embedding = require('../config/kb/embedding');
21
22
  const integrationService = require('./integrationService');
23
+ const situatedContext = require('../config/kb/situatedContext');
22
24
 
23
25
  // Job managers
24
26
  let jobManager = new JobManager(AMQP_MANAGER_URL, {
@@ -92,11 +94,22 @@ class AiManager {
92
94
  let engine = namespace.engine || default_engine;
93
95
  let embedding = namespace.embedding || default_embedding;
94
96
  embedding.api_key = process.env.EMBEDDING_API_KEY || process.env.GPTKEY;
97
+
98
+ let situated_context = this.normalizeSituatedContext();
99
+
95
100
  let webhook = apiUrl + '/webhook/kb/status?token=' + KB_WEBHOOK_TOKEN;
96
101
 
97
102
  let resources = result.map(({ name, status, __v, createdAt, updatedAt, id_project, ...keepAttrs }) => keepAttrs)
98
103
  resources = resources.map(({ _id, scrape_options, ...rest }) => {
99
- return { id: _id, webhook: webhook, parameters_scrape_type_4: scrape_options, embedding: embedding, engine: engine, hybrid: hybrid, ...rest}
104
+ return {
105
+ id: _id,
106
+ webhook: webhook,
107
+ parameters_scrape_type_4: scrape_options,
108
+ embedding: embedding,
109
+ engine: engine,
110
+ hybrid: hybrid,
111
+ ...(situated_context && { situated_context }),
112
+ ...rest}
100
113
  });
101
114
 
102
115
  winston.verbose("resources to be sent to worker: ", resources);
@@ -119,6 +132,8 @@ class AiManager {
119
132
  async scheduleSitemap(namespace, sitemap_content, options) {
120
133
  return new Promise((resolve, reject) => {
121
134
 
135
+ const situated_context = this.normalizeSituatedContext();
136
+
122
137
  let kb = {
123
138
  id: sitemap_content._id,
124
139
  source: sitemap_content.source,
@@ -129,6 +144,7 @@ class AiManager {
129
144
  engine: namespace.engine,
130
145
  embedding: namespace.embedding,
131
146
  hybrid: namespace.hybrid,
147
+ ...(situated_context && { situated_context }),
132
148
  }
133
149
 
134
150
  if (process.env.NODE_ENV === 'test') {
@@ -142,6 +158,73 @@ class AiManager {
142
158
  })
143
159
  }
144
160
 
161
+ async updateSitemap(id_project, namespace, old_sitemap, new_sitemap) {
162
+
163
+ let fieldsToCheck = ['scrape_type', 'scrape_options', 'refresh_rate', 'tags'];
164
+ let { stop } = this.shouldStop(old_sitemap, new_sitemap, fieldsToCheck);
165
+
166
+ let updated_sitemap;
167
+ try {
168
+ updated_sitemap = await KB.findOneAndUpdate({ id_project, namespace: namespace.id, _id: old_sitemap._id }, new_sitemap, { new: true });
169
+ } catch (err) {
170
+ winston.error("Error updating sitemap: ", err);
171
+ throw err;
172
+ }
173
+
174
+ if (stop) {
175
+ return;
176
+ }
177
+
178
+ // Find all url contents with sitemap_origin_id
179
+ let urlContents = await KB.find({ id_project, namespace: namespace.id, sitemap_origin_id: old_sitemap._id }).lean().exec();
180
+ if (urlContents.length === 0) {
181
+ winston.error("No url contents found with sitemap_origin_id: ", old_sitemap._id);
182
+ throw new Error("No url contents found with sitemap_origin_id: " + old_sitemap._id);
183
+ }
184
+
185
+ // Remove all url contents found with sitemap_origin_id
186
+ try {
187
+ await this.removeMultipleContents(namespace, urlContents);
188
+ } catch (err) {
189
+ winston.error("Error removing multiple contents: ", err);
190
+ throw err;
191
+ }
192
+
193
+ // Recreate all url contents with sitemap_origin_id
194
+ let result;
195
+ try {
196
+ result = await this.addMultipleUrls(namespace, urlContents.map(urlContent => urlContent.source), {
197
+ sitemap_origin_id: updated_sitemap._id,
198
+ sitemap_origin: updated_sitemap.source,
199
+ scrape_type: updated_sitemap.scrape_type,
200
+ scrape_options: updated_sitemap.scrape_options,
201
+ refresh_rate: updated_sitemap.refresh_rate,
202
+ tags: updated_sitemap.tags,
203
+ });
204
+ } catch (err) {
205
+ winston.error("Error recreating multiple contents: ", err);
206
+ throw err;
207
+ }
208
+
209
+ return result;
210
+
211
+ }
212
+
213
+
214
+
215
+ shouldStop(oldObj, newObj, fieldsToCheck) {
216
+ for (const field of fieldsToCheck) {
217
+ const oldValue = _.get(oldObj, field);
218
+ const newValue = _.get(newObj, field);
219
+
220
+ if (!_.isEqual(oldValue, newValue)) {
221
+ return { stop: false };
222
+ }
223
+ }
224
+
225
+ return { stop: true };
226
+ }
227
+
145
228
  async checkNamespace(id_project, namespace_id) {
146
229
  return new Promise( async (resolve, reject) => {
147
230
 
@@ -484,6 +567,15 @@ class AiManager {
484
567
  })
485
568
  }
486
569
 
570
+ normalizeSituatedContext() {
571
+ return situatedContext.enable
572
+ ? {
573
+ ...situatedContext,
574
+ api_key: process.env.SITUATED_CONTEXT_API_KEY || process.env.GPTKEY
575
+ }
576
+ : undefined;
577
+ }
578
+
487
579
  }
488
580
 
489
581
  const aiManager = new AiManager();
@@ -206,16 +206,18 @@ class AiService {
206
206
  }
207
207
  winston.debug("[OPENAI SERVICE] kb endpoint: " + base_url);
208
208
 
209
+ const config = {
210
+ url: base_url + "/qa",
211
+ headers: {
212
+ 'Content-Type': 'application/json'
213
+ },
214
+ data: data,
215
+ method: 'POST'
216
+ };
217
+
209
218
  return new Promise((resolve, reject) => {
210
219
 
211
- axios({
212
- url: base_url + "/qa",
213
- headers: {
214
- 'Content-Type': 'application/json'
215
- },
216
- data: data,
217
- method: 'POST'
218
- }).then((resbody) => {
220
+ axios(config).then((resbody) => {
219
221
  resolve(resbody);
220
222
  }).catch((err) => {
221
223
  reject(err);
@@ -224,6 +226,29 @@ class AiService {
224
226
  })
225
227
  }
226
228
 
229
+ /**
230
+ * Stream /qa from KB service. Uses Axios with responseType: 'stream'.
231
+ * Returns the raw Axios response (resp.data is the Node.js Readable stream).
232
+ */
233
+ askStream(data) {
234
+ winston.debug("askStream data: ", data);
235
+ let base_url = kb_endpoint_qa;
236
+ if (data.hybrid || data.search_type === 'hybrid') {
237
+ base_url = kb_endpoint_qa_gpu;
238
+ }
239
+ winston.debug("[OPENAI SERVICE] kb stream endpoint: " + base_url);
240
+
241
+ return axios({
242
+ url: base_url + "/qa",
243
+ headers: {
244
+ 'Content-Type': 'application/json'
245
+ },
246
+ data: data,
247
+ method: 'POST',
248
+ responseType: 'stream'
249
+ });
250
+ }
251
+
227
252
  getContentChunks(namespace_id, content_id, engine, hybrid) {
228
253
  let base_url = kb_endpoint_train;
229
254
  winston.debug("[OPENAI SERVICE] kb endpoint: " + base_url);
@@ -177,10 +177,9 @@ class FileGridFsService extends FileService {
177
177
  return reject(e);
178
178
  })
179
179
  stream.on('data', (data) => {
180
- bufs.push(data);
180
+ bufs.push(Buffer.isBuffer(data) ? data : Buffer.from(data));
181
181
  });
182
182
  stream.on('end', () => {
183
-
184
183
  var buffer = Buffer.concat(bufs);
185
184
  return resolve(buffer);
186
185
  });