@tiledesk/tiledesk-tybot-connector 2.0.29-rc5 → 2.0.29

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/CHANGELOG.md CHANGED
@@ -5,9 +5,10 @@
5
5
  available on:
6
6
  ▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
7
7
 
8
- # 2.0.28
8
+ # 2.0.29
9
+ - added: support for reranking in DirAskKBV2
9
10
 
10
- # 2.0.28-rc1
11
+ # 2.0.28
11
12
  - bug-fixed: action-model not filled in dirAiPrompt
12
13
 
13
14
  # 2.0.27
@@ -15,9 +16,6 @@ available on:
15
16
 
16
17
  # 2.0.26
17
18
 
18
- # 2.0.26-rc1
19
- - added: check and skip private message from internal-notes
20
-
21
19
  # 2.0.9
22
20
 
23
21
  # 2.0.9-rc1
@@ -33,8 +31,6 @@ available on:
33
31
 
34
32
  # v0.5.0
35
33
  - added: AI_ENDPOINT env var
36
-
37
- # v0.5.0-rc1
38
34
  - added: ability to get 'none' as bodytype in webresponse
39
35
 
40
36
  # v0.4.2
@@ -49,19 +45,6 @@ available on:
49
45
  - changed: refactoring of DIrWebRequestv2
50
46
  - bug-fixed: erro while parsing webrequestv2 body
51
47
 
52
- # v0.3.5-rc4
53
- - added: webhook action (same as intent one)
54
-
55
- # v0.3.5-rc3
56
- - bug-fixed: jsonBody parse error in web-request-v2
57
-
58
- # v0.3.5-rc2
59
- - bug-fixed: cannot set status of undefined reading res.status in DirAssistant
60
-
61
- # v0.3.5-rc1
62
- - changed: refactoring web-request-v2
63
- - bug-fixed: jsonBody parse error in web-request-v2
64
-
65
48
  # v0.3.4
66
49
  -bug-fixed: slit is undefined in TiledeskChatbotUtils
67
50
 
@@ -71,18 +54,6 @@ available on:
71
54
  # v0.3.2
72
55
  - bug-fixed: minor improvement
73
56
 
74
- # v0.2.153-rc9
75
- - changed: updated tiledesk-multi-worker to 0.2.1-rc2
76
-
77
- # v0.2.153-rc8
78
- - added: fixToken function in TiledeskService utils class
79
-
80
- # v0.2.153-rc4
81
- - log added
82
-
83
- # v0.2.153-rc3
84
- - added: specchToText function to transcript audio file
85
-
86
57
  # v0.2.153-rc1
87
58
  - changed: context for gpt-40 and gpt-40-mini
88
59
 
package/ExtApi.js CHANGED
@@ -32,6 +32,7 @@ class ExtApi {
32
32
  * @param {string} token. User token
33
33
  */
34
34
  sendSupportMessageExt(message, projectId, requestId, token, callback) {
35
+ const t4 = Date.now();
35
36
  const jwt_token = this.fixToken(token);
36
37
  const url = `${this.TILEBOT_ENDPOINT}/ext/${projectId}/requests/${requestId}/messages`;
37
38
  winston.verbose("(ExtApi) sendSupportMessageExt URL" + url);
@@ -53,6 +54,8 @@ class ExtApi {
53
54
  }
54
55
  }
55
56
  else {
57
+ const t4e = Date.now();
58
+ console.log(`[TIMER] sendSupportMessageExt in ${t4e - t4}ms ------ ${requestId}`);
56
59
  if (callback) {
57
60
  callback(null, resbody);
58
61
  }
@@ -0,0 +1,242 @@
1
+ const redis = require('redis');
2
+
3
+ class TdCache {
4
+
5
+ constructor(config) {
6
+ this.redis_host = config.host;
7
+ this.redis_port = config.port;
8
+ this.redis_password = config.password;
9
+ this.client = null;
10
+ }
11
+
12
+ async connect(callback) {
13
+ // client = redis.createClient();
14
+ return new Promise( async (resolve, reject) => {
15
+ this.client = redis.createClient(
16
+ {
17
+ host: this.redis_host,
18
+ port: this.redis_port,
19
+ password: this.redis_password
20
+ });
21
+ this.client.on('error', err => {
22
+ reject(err);
23
+ if (callback) {
24
+ callback(err);
25
+ }
26
+ });
27
+ // this.client.on('connect', function() {
28
+ // console.log('Redis Connected!');
29
+ // });
30
+ this.client.on('ready',function() {
31
+ console.log("connected")
32
+ resolve();
33
+ if (callback) {
34
+ callback();
35
+ }
36
+ //console.log("Redis is ready.");
37
+ });
38
+ });
39
+ }
40
+
41
+ async set(key, value, options) {
42
+ //console.log("setting key value", key, value)
43
+ if (!options) {
44
+ options = {EX: 86400}
45
+ }
46
+ return new Promise( async (resolve, reject) => {
47
+ if (options && options.EX) {
48
+ //console.log("expires:", options.EX)
49
+ try {
50
+ await this.client.set(
51
+ key,
52
+ value,
53
+ 'EX', options.EX);
54
+ }
55
+ catch(error) {
56
+ reject(error)
57
+ }
58
+ }
59
+ else {
60
+ try {
61
+ //console.log("setting here...key", key, value)
62
+ await this.client.set(
63
+ key,
64
+ value);
65
+ }
66
+ catch(error) {
67
+ console.error("Error", error);
68
+ reject(error)
69
+ }
70
+ }
71
+ if (options && options.callback) {
72
+ options.callback();
73
+ }
74
+ //console.log("resolving...", key);
75
+ return resolve();
76
+ });
77
+ }
78
+
79
+ async incr(key) {
80
+ // console.log("incr key:", key)
81
+ return new Promise( async (resolve, reject) => {
82
+ try {
83
+ // console.log("incr here...key", key)
84
+ await this.client.incr(key);
85
+ }
86
+ catch(error) {
87
+ console.error("Error on incr:", error);
88
+ reject(error)
89
+ }
90
+ return resolve();
91
+ });
92
+ }
93
+
94
+ async hset(dict_key, key, value, options) {
95
+ //console.log("hsetting dict_key key value", dict_key, key, value)
96
+ return new Promise( async (resolve, reject) => {
97
+ if (options && options.EX) {
98
+ //console.log("expires:", options.EX)
99
+ try {
100
+ await this.client.hset(
101
+ dict_key,
102
+ key,
103
+ value,
104
+ 'EX', options.EX);
105
+ }
106
+ catch(error) {
107
+ reject(error)
108
+ }
109
+ }
110
+ else {
111
+ try {
112
+ //console.log("setting here...key", key, value)
113
+ await this.client.hset(
114
+ dict_key,
115
+ key,
116
+ value);
117
+ }
118
+ catch(error) {
119
+ console.error("Error", error);
120
+ reject(error)
121
+ }
122
+ }
123
+ if (options && options.callback) {
124
+ options.callback();
125
+ }
126
+ return resolve();
127
+ });
128
+ }
129
+
130
+ async hdel(dict_key, key, options) {
131
+ //console.log("hsetting dict_key key value", dict_key, key, value)
132
+ return new Promise( async (resolve, reject) => {
133
+ if (options && options.EX) {
134
+ //console.log("expires:", options.EX)
135
+ try {
136
+ await this.client.hdel(
137
+ dict_key,
138
+ key,
139
+ 'EX', options.EX);
140
+ }
141
+ catch(error) {
142
+ reject(error)
143
+ }
144
+ }
145
+ else {
146
+ try {
147
+ //console.log("setting here...key", key, value)
148
+ await this.client.hdel(
149
+ dict_key,
150
+ key);
151
+ }
152
+ catch(error) {
153
+ console.error("Error", error);
154
+ reject(error);
155
+ }
156
+ }
157
+ if (options && options.callback) {
158
+ options.callback();
159
+ }
160
+ return resolve();
161
+ });
162
+ }
163
+
164
+ async setJSON(key, value, options) {
165
+ const _string = JSON.stringify(value);
166
+ return await this.set(key, _string, options);
167
+ }
168
+
169
+ async get(key, callback) {
170
+ //console.log("getting key", key)
171
+ return new Promise( async (resolve, reject) => {
172
+ this.client.get(key, (err, value) => {
173
+ if (err) {
174
+ reject(err);
175
+ }
176
+ else {
177
+ if (callback) {
178
+ callback(value);
179
+ }
180
+ return resolve(value);
181
+ }
182
+ });
183
+ });
184
+ }
185
+
186
+ async hgetall(dict_key, callback) {
187
+ //console.log("hgetting dics", dict_key);
188
+ return new Promise( async (resolve, reject) => {
189
+ this.client.hgetall(dict_key, (err, value) => {
190
+ if (err) {
191
+ reject(err);
192
+ if (callback) {
193
+ callback(err, null);
194
+ }
195
+ }
196
+ else {
197
+ if (callback) {
198
+ callback(null, value);
199
+ }
200
+ resolve(value);
201
+ }
202
+ });
203
+ });
204
+ }
205
+
206
+ async hget(dict_key, key, callback) {
207
+ //console.log("hgetting dics", dict_key);
208
+ return new Promise( async (resolve, reject) => {
209
+ this.client.hget(dict_key, key, (err, value) => {
210
+ if (err) {
211
+ reject(err);
212
+ if (callback) {
213
+ callback(err, null);
214
+ }
215
+ }
216
+ else {
217
+ if (callback) {
218
+ callback(null, value);
219
+ }
220
+ resolve(value);
221
+ }
222
+ });
223
+ });
224
+ }
225
+
226
+ async getJSON(key, callback) {
227
+ const value = await this.get(key);
228
+ return JSON.parse(value);
229
+ }
230
+
231
+ async del(key, callback) {
232
+ return new Promise( async (resolve, reject) => {
233
+ await this.client.del(key);
234
+ if (callback) {
235
+ callback();
236
+ }
237
+ return resolve();
238
+ })
239
+ }
240
+ }
241
+
242
+ module.exports = { TdCache };
@@ -42,14 +42,7 @@ class TiledeskChatbotConst {
42
42
  static REQ_LAST_USER_DOCUMENT_URL = 'lastUserDocumentURL';
43
43
  static REQ_LAST_USER_DOCUMENT_NAME = 'lastUserDocumentName';
44
44
  static REQ_LAST_USER_DOCUMENT_TYPE = 'lastUserDocumentType';
45
- static REQ_EMAIL_SUBJECT = 'email_subject';
46
- static REQ_EMAIL_TO = 'email_toEmail';
47
- static REQ_EMAIL_FROM = 'email_fromEmail';
48
- static REQ_EMAIL_MESSAGE_ID = 'email_messageId';
49
- static REQ_EMAIL_REPLY_TO = 'email_replyTo';
50
- static REQ_EMAIL_EML = 'email_eml';
51
- static REQ_EMAIL_ATTACHMENTS_LINK = 'link';
52
- static REQ_EMAIL_ATTACHMENTS_FILES = 'attachments'
45
+
53
46
  }
54
47
 
55
48
  module.exports = { TiledeskChatbotConst };
@@ -24,7 +24,8 @@ class MockBotsDataSource {
24
24
  }catch(err){
25
25
  reject(err);
26
26
  }
27
- })
27
+
28
+ })
28
29
  }
29
30
 
30
31
  async getBotByIdCache(botId, tdcache) {
package/index.js CHANGED
@@ -42,6 +42,8 @@ let TILEBOT_ENDPOINT = null;
42
42
  let staticBots;
43
43
 
44
44
  router.post('/ext/:botid', async (req, res) => {
45
+ const ttotal = Date.now()
46
+ const t1 = Date.now();
45
47
  const botId = req.params.botid;
46
48
  winston.verbose("(tybotRoute) POST /ext/:botid called: " + botId)
47
49
  if(!botId || botId === "null" || botId === "undefined"){
@@ -104,9 +106,6 @@ router.post('/ext/:botid', async (req, res) => {
104
106
  Promise.reject(err);
105
107
  return;
106
108
  });
107
-
108
- winston.debug("(tybotRoute) Bot found: ", bot)
109
-
110
109
 
111
110
  let intentsMachine;
112
111
  let backupMachine;
@@ -173,10 +172,12 @@ router.post('/ext/:botid', async (req, res) => {
173
172
  cache: tdcache
174
173
  }
175
174
  );
176
-
177
-
175
+ const t1e = Date.now();
176
+ console.log(`[TIMER] Preparation phase in ${t1e - t1}ms ------ ${requestId}`);
177
+ const t2 = Date.now();
178
178
  directivesPlug.processDirectives( () => {
179
-
179
+ const t2e = Date.now();
180
+ console.log(`[TIMER] Directives executed in ${t2e - t2}ms ------ ${requestId}`);
180
181
  winston.verbose("(tybotRoute) Actions - Directives executed.");
181
182
  });
182
183
  }
@@ -199,7 +200,8 @@ router.post('/ext/:botid', async (req, res) => {
199
200
  TILEBOT_ENDPOINT: TILEBOT_ENDPOINT
200
201
  });
201
202
  apiext.sendSupportMessageExt(reply, projectId, requestId, token, () => {
202
-
203
+ const ttotale = Date.now()
204
+ console.log(`[TIMER] Directives executed in ${ttotal - ttotale}ms ------ ${requestId}`);
203
205
  winston.verbose("(tybotRoute) sendSupportMessageExt reply sent: ", reply)
204
206
  });
205
207
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tiledesk/tiledesk-tybot-connector",
3
- "version": "2.0.29-rc5",
3
+ "version": "2.0.29",
4
4
  "description": "Tiledesk Tybot connector",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -15,7 +15,7 @@
15
15
  "@tiledesk/tiledesk-chatbot-client": "^0.5.30",
16
16
  "@tiledesk/tiledesk-chatbot-util": "^0.8.39",
17
17
  "@tiledesk/tiledesk-client": "^0.10.13",
18
- "@tiledesk/tiledesk-multi-worker": "^0.3.3",
18
+ "@tiledesk/tiledesk-multi-worker": "^0.3.2",
19
19
  "accept-language-parser": "^1.5.0",
20
20
  "app-root-path": "^3.1.0",
21
21
  "axios": "^1.7.7",
@@ -2,7 +2,7 @@ const httpUtils = require('../utils/HttpUtils');
2
2
  const winston = require('../utils/winston');
3
3
  const API_ENDPOINT = process.env.API_ENDPOINT;
4
4
 
5
- class LLMService {
5
+ class KBService {
6
6
 
7
7
  constructor() { }
8
8
 
@@ -101,5 +101,5 @@ class LLMService {
101
101
  }
102
102
  }
103
103
 
104
- const llmService = new LLMService();
105
- module.exports = llmService;
104
+ const kbService = new KBService();
105
+ module.exports = kbService;
@@ -54,14 +54,13 @@ const { DirMoveToUnassigned } = require('./directives/DirMoveToUnassigned');
54
54
  const { DirAddTags } = require('./directives/DirAddTags');
55
55
  const { DirSendWhatsapp } = require('./directives/DirSendWhatsapp');
56
56
  const { DirReplaceBotV3 } = require('./directives/DirReplaceBotV3');
57
- const { DirAiPrompt } = require('./directives/DirAiPrompt');
57
+ const { DirAiTask, DirAiPrompt } = require('./directives/DirAiPrompt');
58
58
  const { DirWebResponse } = require('./directives/DirWebResponse');
59
59
  const { DirConnectBlock } = require('./directives/DirConnectBlock');
60
- const { DirAiCondition } = require('./directives/DirAiCondition');
61
- const { DirAddKbContent } = require('./directives/DirAddKbContent');
62
- const { DirFlowLog } = require('./directives/DirFlowLog');
63
60
 
64
61
  const winston = require('../utils/winston');
62
+ const { DirFlowLog } = require('./directives/DirFlowLog');
63
+ const { DirAddKbContent } = require('./directives/DirAddKbContent');
65
64
 
66
65
  class DirectivesChatbotPlug {
67
66
 
@@ -211,7 +210,7 @@ class DirectivesChatbotPlug {
211
210
  }
212
211
 
213
212
  async process(directive) {
214
-
213
+ const t3 = Date.now();
215
214
  let context = this.context;
216
215
  if (directive) {
217
216
  winston.verbose("(DirectivesChatbotPlug) directive['name']: " + directive["name"]);
@@ -221,13 +220,14 @@ class DirectivesChatbotPlug {
221
220
  directive_name = directive.name.toLowerCase();
222
221
  }
223
222
  if (directive && directive.action) {
224
- const action_id = directive.action["_tdActionId"];
225
- const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
226
- if ( locked_action_id && (locked_action_id !== action_id) ) {
227
- let next_dir = await this.nextDirective(this.directives);
228
- this.process(next_dir);
229
- return;
230
- }
223
+ const action_id = directive.action["_tdActionId"];
224
+ const locked_action_id = await this.chatbot.currentLockedAction(this.supportRequest.request_id);
225
+ if ( locked_action_id && (locked_action_id !== action_id) ) {
226
+ let next_dir = await this.nextDirective(this.directives);
227
+ this.process(next_dir);
228
+ return;
229
+ }
230
+
231
231
  }
232
232
  if (directive == null || (directive !== null && directive["name"] === undefined)) {
233
233
  winston.debug("(DirectivesChatbotPlug) stop process(). directive is (null?): ", directive);
@@ -452,7 +452,8 @@ class DirectivesChatbotPlug {
452
452
  else if (directive_name === Directives.WAIT) {
453
453
  new DirWait(context).execute(directive, async () => {
454
454
  let next_dir = await this.nextDirective(this.directives);
455
-
455
+ const t3e = Date.now();
456
+ console.log(`[TIMER] Single wait executed in ${t3e - t3}ms`);
456
457
  this.process(next_dir);
457
458
  });
458
459
  }
@@ -594,18 +595,6 @@ class DirectivesChatbotPlug {
594
595
  }
595
596
  });
596
597
  }
597
- else if (directive_name === Directives.AI_CONDITION) {
598
- new DirAiCondition(context).execute(directive, async (stop) => {
599
- if (stop == true) {
600
- winston.debug("(DirectivesChatbotPlug) DirAskGPTV2 Stopping Actions on: ", directive);
601
- this.theend();
602
- }
603
- else {
604
- let next_dir = await this.nextDirective(this.directives);
605
- this.process(next_dir);
606
- }
607
- });
608
- }
609
598
  else if (directive_name === Directives.WHATSAPP_ATTRIBUTE) {
610
599
  new DirWhatsappByAttribute(context).execute(directive, async (stop) => {
611
600
  let next_dir = await this.nextDirective(this.directives);
@@ -718,18 +707,6 @@ class DirectivesChatbotPlug {
718
707
  }
719
708
  });
720
709
  }
721
- else if (directive_name === Directives.WEBHOOK) {
722
- new DirIntent(context).execute(directive, async (stop) => {
723
- if (stop) {
724
- if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
725
- this.theend();
726
- }
727
- else {
728
- let next_dir = await this.nextDirective(this.directives);
729
- this.process(next_dir);
730
- }
731
- });
732
- }
733
710
  else if (directive_name === Directives.WEB_RESPONSE) {
734
711
  new DirWebResponse(context).execute(directive, async () => {
735
712
  let next_dir = await this.nextDirective(this.directives);
@@ -742,12 +719,6 @@ class DirectivesChatbotPlug {
742
719
  this.process(next_dir);
743
720
  })
744
721
  }
745
- else if (directive_name === Directives.ADD_KB_CONTENT) {
746
- new DirAddKbContent(context).execute(directive, async () => {
747
- let next_dir = await this.nextDirective(this.directives);
748
- this.process(next_dir);
749
- });
750
- }
751
722
  else {
752
723
  let next_dir = await this.nextDirective(this.directives);
753
724
  this.process(next_dir);
@@ -13,7 +13,6 @@ const httpUtils = require("../../utils/HttpUtils");
13
13
  const integrationService = require("../../services/IntegrationService");
14
14
  const { Logger } = require("../../Logger");
15
15
  const assert = require("assert");
16
- const quotasService = require("../../services/QuotasService");
17
16
 
18
17
 
19
18
  class DirAiPrompt {
@@ -118,7 +117,6 @@ class DirAiPrompt {
118
117
  }
119
118
 
120
119
  let key;
121
- let publicKey = false;
122
120
  let ollama_integration;
123
121
 
124
122
  if (action.llm === 'ollama') {
@@ -137,13 +135,7 @@ class DirAiPrompt {
137
135
 
138
136
  } else {
139
137
  key = await integrationService.getKeyFromIntegrations(this.projectId, action.llm, this.token);
140
-
141
- if (!key && action.llm === "openai") {
142
- this.logger.native("[AI Prompt] OpenAI key not found in Integration. Retrieve shared OpenAI key.")
143
- key = process.env.GPTKEY;
144
- publicKey = true;
145
- }
146
-
138
+
147
139
  if (!key) {
148
140
  this.logger.error("[AI Prompt] llm key not found in integrations");
149
141
  winston.error("Error: DirAiPrompt llm key not found in integrations");
@@ -158,33 +150,6 @@ class DirAiPrompt {
158
150
  }
159
151
  }
160
152
 
161
- if (publicKey === true) {
162
- try {
163
- let keep_going = await quotasService.checkQuoteAvailability(this.projectId, this.token)
164
- if (keep_going === false) {
165
- this.logger.warn("[AI Prompt] OpenAI tokens quota exceeded");
166
- await this.chatbot.addParameter("flowError", "GPT Error: tokens quota exceeded");
167
- if (falseIntent) {
168
- await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
169
- callback();
170
- return;
171
- }
172
- callback();
173
- return;
174
- }
175
- } catch (err) {
176
- this.logger.error("An error occured on checking token quota availability");
177
- await this.chatbot.addParameter("flowError", "An error occured on checking token quota availability");
178
- if (falseIntent) {
179
- await this.#executeCondition(false, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes);
180
- callback();
181
- return;
182
- }
183
- callback();
184
- return;
185
- }
186
- }
187
-
188
153
  let json = {
189
154
  question: filled_question,
190
155
  llm: action.llm,
@@ -249,14 +214,6 @@ class DirAiPrompt {
249
214
  winston.debug("DirAiPrompt resbody: ", resbody);
250
215
  answer = resbody.answer;
251
216
  this.logger.native("[AI Prompt] answer: ", answer);
252
-
253
- // if (publicKey === true) {
254
- // let tokens_usage = {
255
- // tokens: resbody.usage.total_token,
256
- // model: json.model
257
- // }
258
- // quotasService.updateQuote(this.projectId, this.token, tokens_usage);
259
- // }
260
217
 
261
218
  await this.#assignAttributes(action, answer);
262
219
 
@@ -11,10 +11,8 @@ const winston = require('../../utils/winston');
11
11
  const httpUtils = require("../../utils/HttpUtils");
12
12
  const integrationService = require("../../services/IntegrationService");
13
13
  const { Logger } = require("../../Logger");
14
+ const kbService = require("../../services/KbService");
14
15
  const quotasService = require("../../services/QuotasService");
15
- const llmService = require("../../services/LLMService");
16
-
17
-
18
16
 
19
17
  class DirAskGPTV2 {
20
18
 
@@ -178,7 +176,7 @@ class DirAskGPTV2 {
178
176
  if (!key) {
179
177
  this.logger.native("[Ask Knowledge Base] OpenAI key not found in Integration. Using shared OpenAI key");
180
178
  winston.verbose("DirAskGPTV2 - Key not found in Integrations. Searching in kb settings...");
181
- key = await llmService.getKeyFromKbSettings(this.projectId, this.token);
179
+ key = await kbService.getKeyFromKbSettings(this.projectId, this.token);
182
180
  }
183
181
 
184
182
  if (!key) {
@@ -375,7 +373,7 @@ class DirAskGPTV2 {
375
373
  }
376
374
  } else {
377
375
  await this.#assignAttributes(action, answer, source);
378
- llmService.addUnansweredQuestion(this.projectId, json.namespace, json.question, this.token).catch((err) => {
376
+ kbService.addUnansweredQuestion(this.projectId, json.namespace, json.question, this.token).catch((err) => {
379
377
  winston.error("DirAskGPTV2 - Error adding unanswered question: ", err);
380
378
  this.logger.warn("[Ask Knowledge Base] Unable to add unanswered question", json.question, "to namespacae", json.namespace);
381
379
  })
@@ -118,7 +118,7 @@ class DirWebRequestV2 {
118
118
  this.logger.native("[Web Request] resbody: ", resbody);
119
119
 
120
120
  if (err) {
121
- this.logger.error("[Web Request] error: ", err);
121
+ this.logger.error("WebRequest error: ", err);
122
122
  winston.log("webRequest error: ", err);
123
123
  if (callback) {
124
124
  if (falseIntent) {