@tiledesk/tiledesk-tybot-connector 0.2.63 → 0.2.64
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 +5 -0
- package/index.js +6 -1
- package/package.json +1 -1
- package/tiledeskChatbotPlugs/DirectivesChatbotPlug.js +15 -0
- package/tiledeskChatbotPlugs/directives/DirAssistant.js +637 -0
- package/tiledeskChatbotPlugs/directives/DirWebRequestV2.js +151 -99
- package/tiledeskChatbotPlugs/directives/Directives.js +1 -0
package/CHANGELOG.md
CHANGED
|
@@ -6,6 +6,11 @@ available on:
|
|
|
6
6
|
▶️ https://www.npmjs.com/package/@tiledesk/tiledesk-tybot-connector
|
|
7
7
|
|
|
8
8
|
|
|
9
|
+
# v0.2.64
|
|
10
|
+
- removed system parameters from /reserved/parameters
|
|
11
|
+
- Web Request Action: added multipart form-data support with files binary from URL source
|
|
12
|
+
- Added DirAssistant Action
|
|
13
|
+
|
|
9
14
|
# v0.2.63
|
|
10
15
|
- BUG fix on /ext/parameters/requests/:requestid
|
|
11
16
|
- Moved getChatbotParameters function in TiledeskChatbotUtil
|
package/index.js
CHANGED
|
@@ -395,7 +395,12 @@ router.get('/ext/reserved/parameters/requests/:requestid', async (req, res) => {
|
|
|
395
395
|
"lastUserImageType", // image
|
|
396
396
|
"lastUserDocumentURL", // file
|
|
397
397
|
"lastUserDocumentName", // file
|
|
398
|
-
"lastUserDocumentType" // file
|
|
398
|
+
"lastUserDocumentType", // file
|
|
399
|
+
"ticketId",
|
|
400
|
+
TiledeskChatbotConst.REQ_CHAT_CHANNEL,
|
|
401
|
+
"user_lead_id",
|
|
402
|
+
"lastUserText",
|
|
403
|
+
TiledeskChatbotConst.REQ_REQUESTER_IS_AUTHENTICATED_KEY
|
|
399
404
|
]
|
|
400
405
|
let userParams = {};
|
|
401
406
|
if (parameters) {
|
package/package.json
CHANGED
|
@@ -46,6 +46,7 @@ const { DirHubspot } = require('./directives/DirHubspot');
|
|
|
46
46
|
const { DirCustomerio } = require('./directives/DirCustomerio');
|
|
47
47
|
const { DirBrevo } = require('./directives/DirBrevo');
|
|
48
48
|
const { DirAskGPTV2 } = require('./directives/DirAskGPTV2');
|
|
49
|
+
const { DirAssistant } = require('./directives/DirAssistant');
|
|
49
50
|
|
|
50
51
|
class DirectivesChatbotPlug {
|
|
51
52
|
|
|
@@ -727,6 +728,20 @@ class DirectivesChatbotPlug {
|
|
|
727
728
|
this.process(next_dir);
|
|
728
729
|
})
|
|
729
730
|
}
|
|
731
|
+
else if (directive_name === Directives.GPT_ASSISTANT) {
|
|
732
|
+
// console.log("...GPT_ASSISTANT");
|
|
733
|
+
new DirAssistant(context).execute(directive, async (stop) => {
|
|
734
|
+
if (context.log) { console.log("stop on condition?", stop);}
|
|
735
|
+
if (stop == true) {
|
|
736
|
+
if (context.log) { console.log("Stopping Actions on:", JSON.stringify(directive));}
|
|
737
|
+
this.theend();
|
|
738
|
+
}
|
|
739
|
+
else {
|
|
740
|
+
let next_dir = await this.nextDirective(this.directives);
|
|
741
|
+
this.process(next_dir);
|
|
742
|
+
}
|
|
743
|
+
});
|
|
744
|
+
}
|
|
730
745
|
else {
|
|
731
746
|
//console.log("Unhandled Post-message Directive:", directive_name);
|
|
732
747
|
let next_dir = await this.nextDirective(this.directives);
|
|
@@ -0,0 +1,637 @@
|
|
|
1
|
+
let axios = require('axios');
|
|
2
|
+
let https = require("https");
|
|
3
|
+
const { Filler } = require('../Filler');
|
|
4
|
+
const { TiledeskChatbot } = require('../../models/TiledeskChatbot');
|
|
5
|
+
const { DirIntent } = require('./DirIntent');
|
|
6
|
+
|
|
7
|
+
class DirAssistant {
|
|
8
|
+
constructor(context) {
|
|
9
|
+
if (!context) {
|
|
10
|
+
throw new Error('context object is mandatory.');
|
|
11
|
+
}
|
|
12
|
+
this.context = context;
|
|
13
|
+
this.tdclient = context.tdclient;
|
|
14
|
+
this.tdcache = context.tdcache;
|
|
15
|
+
this.requestId = context.requestId;
|
|
16
|
+
this.intentDir = new DirIntent(context);
|
|
17
|
+
this.log = context.log;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
execute(directive, callback) {
|
|
21
|
+
let action;
|
|
22
|
+
if (directive.action) {
|
|
23
|
+
action = directive.action;
|
|
24
|
+
}
|
|
25
|
+
else {
|
|
26
|
+
console.error("Incorrect directive:", JSON.stringify(directive));
|
|
27
|
+
callback();
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
this.go(action, (stop) => {
|
|
31
|
+
if (this.log) {console.log("(DirAssistant, stop?", stop); }
|
|
32
|
+
callback(stop);
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async go(action, callback) {
|
|
37
|
+
if (this.log) {console.log("DirAssistant action:", JSON.stringify(action));}
|
|
38
|
+
let requestAttributes = null;
|
|
39
|
+
if (this.tdcache) {
|
|
40
|
+
requestAttributes =
|
|
41
|
+
await TiledeskChatbot.allParametersStatic(
|
|
42
|
+
this.tdcache, this.requestId
|
|
43
|
+
);
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
const filler = new Filler();
|
|
47
|
+
const url = filler.fill(action.url, requestAttributes);
|
|
48
|
+
// prompt => Mandatory
|
|
49
|
+
// assistantId => Mandatory
|
|
50
|
+
// threadIdAttributeName => Optional // default "firstThread"
|
|
51
|
+
// assignResultTo => Optional // default "assistantReply"
|
|
52
|
+
// assignErrorTo => Optional // default "assistantError"
|
|
53
|
+
// action.settings.timeout => Optional
|
|
54
|
+
|
|
55
|
+
let assignResultTo = "assistantReply";
|
|
56
|
+
if (action.assignResultTo) {
|
|
57
|
+
assignResultTo = action.assignResultTo;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
let assignErrorTo = "assistantError";
|
|
61
|
+
if (action.assignErrorTo) {
|
|
62
|
+
assignErrorTo = action.assignErrorTo;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
let threadIdAttribute = "firstThread";
|
|
66
|
+
if (action.threadIdAttribute) {
|
|
67
|
+
threadIdAttribute = action.threadIdAttribute;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
let _assistantId = null;
|
|
71
|
+
if (action.assistantId) { // mandatory
|
|
72
|
+
_assistantId = action.assistantId;
|
|
73
|
+
}
|
|
74
|
+
else {
|
|
75
|
+
// TODO: LOG SETTINGS ERROR
|
|
76
|
+
console.error("DirAssistant error: no assistantId.");
|
|
77
|
+
callback();
|
|
78
|
+
return;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
let _prompt = null;
|
|
82
|
+
if (action.prompt) { // mandatory
|
|
83
|
+
_prompt = action.prompt;
|
|
84
|
+
}
|
|
85
|
+
else {
|
|
86
|
+
// TODO: LOG SETTINGS ERROR
|
|
87
|
+
console.error("DirAssistant error: no prompt.");
|
|
88
|
+
callback();
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
let assistantId = _assistantId;
|
|
93
|
+
try {
|
|
94
|
+
assistantId = filler.fill(_assistantId, requestAttributes);
|
|
95
|
+
}
|
|
96
|
+
catch(error) {
|
|
97
|
+
console.error("Error while filling assistantId:", error);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
let prompt = _prompt;
|
|
101
|
+
try {
|
|
102
|
+
prompt = filler.fill(_prompt, requestAttributes);
|
|
103
|
+
}
|
|
104
|
+
catch(error) {
|
|
105
|
+
console.error("Error while filling prompt:", error);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (this.log) {
|
|
109
|
+
console.log("settings ok");
|
|
110
|
+
console.log("prompt:", prompt);
|
|
111
|
+
console.log("assistantId:", assistantId);
|
|
112
|
+
}
|
|
113
|
+
// Condition branches
|
|
114
|
+
let trueIntent = action.trueIntent;
|
|
115
|
+
let falseIntent = action.falseIntent;
|
|
116
|
+
if (trueIntent && trueIntent.trim() === "") {
|
|
117
|
+
trueIntent = null;
|
|
118
|
+
}
|
|
119
|
+
if (falseIntent && falseIntent.trim() === "") {
|
|
120
|
+
falseIntent = null;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
this.timeout = this.#webrequest_timeout(action, 20000, 1, 300000);
|
|
124
|
+
|
|
125
|
+
const apikey = await this.getGPT_APIKEY();
|
|
126
|
+
if (this.log) {console.log("apikey:", apikey);}
|
|
127
|
+
if (!apikey) {
|
|
128
|
+
const reply = "DirAssistant gptkey is mandatory in Integrations";
|
|
129
|
+
if (this.log) { console.error(reply); };
|
|
130
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, assignErrorTo, reply);
|
|
131
|
+
if (falseIntent) {
|
|
132
|
+
await this.#executeCondition(false, trueIntent, null, falseIntent, null);
|
|
133
|
+
callback(true);
|
|
134
|
+
}
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
let threadId = null;
|
|
138
|
+
try {
|
|
139
|
+
threadId = requestAttributes[threadIdAttribute];
|
|
140
|
+
if (!threadId || (threadId && threadId.trim() === '') ) {
|
|
141
|
+
// create thread if it doesn't exist
|
|
142
|
+
if (this.log) {console.log("Creating thread");}
|
|
143
|
+
const thread = await this.createThread(apikey);
|
|
144
|
+
if (this.log) {console.log("Thread crated.");}
|
|
145
|
+
threadId = thread.id;
|
|
146
|
+
if (this.log) {
|
|
147
|
+
console.log("thread:", thread);
|
|
148
|
+
console.log("threadId:", threadId);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
await this.addMessage(prompt, threadId, apikey);
|
|
152
|
+
if (this.log) {console.log("Message added.");}
|
|
153
|
+
await this.runThreadOnAssistant(assistantId, threadId, apikey);
|
|
154
|
+
let messages = await this.threadMessages(threadId, apikey);
|
|
155
|
+
let lastMessage = null;
|
|
156
|
+
if (messages && messages.data && messages.data.length > 0 && messages.data[0]) {
|
|
157
|
+
if (messages.data[0].content.length > 0 && messages.data[0].content[0] && messages.data[0].content[0].text) {
|
|
158
|
+
lastMessage = messages.data[0].content[0].text.value;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
console.log("lastMessage:", lastMessage);
|
|
162
|
+
// process.exit(0);
|
|
163
|
+
if (lastMessage !== null) {
|
|
164
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, assignResultTo, lastMessage);
|
|
165
|
+
if (trueIntent) {
|
|
166
|
+
await this.#executeCondition(true, trueIntent, null, falseIntent, null);
|
|
167
|
+
callback(true);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
callback(false);
|
|
171
|
+
return;
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, assignResultTo, null);
|
|
176
|
+
if (falseIntent) {
|
|
177
|
+
await this.#executeCondition(false, trueIntent, null, falseIntent, null);
|
|
178
|
+
callback(true);
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
callback(false);
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
if (this.log) { console.error("error:", error); }
|
|
188
|
+
await TiledeskChatbot.addParameterStatic(this.context.tdcache, this.context.requestId, assignErrorTo, error);
|
|
189
|
+
if (falseIntent) {
|
|
190
|
+
await this.#executeCondition(false, trueIntent, null, falseIntent, null);
|
|
191
|
+
}
|
|
192
|
+
callback(true);
|
|
193
|
+
return;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async #executeCondition(result, trueIntent, trueIntentAttributes, falseIntent, falseIntentAttributes, callback) {
|
|
199
|
+
let trueIntentDirective = null;
|
|
200
|
+
if (trueIntent) {
|
|
201
|
+
trueIntentDirective = DirIntent.intentDirectiveFor(trueIntent, trueIntentAttributes);
|
|
202
|
+
}
|
|
203
|
+
let falseIntentDirective = null;
|
|
204
|
+
if (falseIntent) {
|
|
205
|
+
falseIntentDirective = DirIntent.intentDirectiveFor(falseIntent, falseIntentAttributes);
|
|
206
|
+
}
|
|
207
|
+
if (result === true) {
|
|
208
|
+
if (trueIntentDirective) {
|
|
209
|
+
this.intentDir.execute(trueIntentDirective, () => {
|
|
210
|
+
if (callback) {
|
|
211
|
+
callback();
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
if (this.log) {console.log("No trueIntentDirective specified");}
|
|
217
|
+
if (callback) {
|
|
218
|
+
callback();
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
if (falseIntentDirective) {
|
|
224
|
+
this.intentDir.execute(falseIntentDirective, () => {
|
|
225
|
+
if (callback) {
|
|
226
|
+
callback();
|
|
227
|
+
}
|
|
228
|
+
});
|
|
229
|
+
}
|
|
230
|
+
else {
|
|
231
|
+
if (this.log) {console.log("No falseIntentDirective specified");}
|
|
232
|
+
if (callback) {
|
|
233
|
+
callback();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
#webrequest_timeout(action, default_timeout, min, max) {
|
|
240
|
+
let timeout = default_timeout;
|
|
241
|
+
if (!action.settings) {
|
|
242
|
+
return timeout;
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
if (action.settings.timeout) {
|
|
246
|
+
if ((typeof action.settings.timeout === "number") && action.settings.timeout > min && action.settings.timeout < max) {
|
|
247
|
+
timeout = Math.round(action.settings.timeout)
|
|
248
|
+
// console.log("new timeout:", timeout);
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
return timeout
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
async getGPT_APIKEY() {
|
|
255
|
+
if (process.env.TEST_OPENAI_APIKEY) {
|
|
256
|
+
return process.env.TEST_OPENAI_APIKEY
|
|
257
|
+
}
|
|
258
|
+
else {
|
|
259
|
+
const server_base_url = process.env.API_ENDPOINT || process.env.API_URL;
|
|
260
|
+
return await this.getKeyFromIntegrations(server_base_url);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
async createThread(apikey) {
|
|
265
|
+
if (this.log) { console.log("creating thread..."); }
|
|
266
|
+
return new Promise( async (resolve, reject) => {
|
|
267
|
+
const url = "https://api.openai.com/v1/threads";
|
|
268
|
+
const headers = {
|
|
269
|
+
"Authorization": apikey,
|
|
270
|
+
"OpenAI-Beta": "assistants=v2"
|
|
271
|
+
}
|
|
272
|
+
const HTTPREQUEST = {
|
|
273
|
+
url: url,
|
|
274
|
+
headers: headers,
|
|
275
|
+
json: '', // no old messages on creation
|
|
276
|
+
method: "POST",
|
|
277
|
+
timeout: this.timeout
|
|
278
|
+
};
|
|
279
|
+
if (this.log) {console.log("DirAssistant HTTPREQUEST", HTTPREQUEST);}
|
|
280
|
+
this.#myrequest(
|
|
281
|
+
HTTPREQUEST, async (err, res) => {
|
|
282
|
+
let status = res.status;
|
|
283
|
+
if (err) {
|
|
284
|
+
if (this.log) {console.error("DirAssistant error:", err);}
|
|
285
|
+
reject(err);
|
|
286
|
+
}
|
|
287
|
+
else if(res.status >= 200 && res.status <= 299) {
|
|
288
|
+
if (this.log) {console.log("got threadid res:", res);}
|
|
289
|
+
let thread = res.data;
|
|
290
|
+
resolve(thread)
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
reject(new Error("Thread creation status != 200:", status));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
);
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
async addMessage(prompt, threadId, apikey) {
|
|
301
|
+
|
|
302
|
+
// POST https://api.openai.com/v1/threads/{{threadID}}/messages
|
|
303
|
+
|
|
304
|
+
// JSON
|
|
305
|
+
/*
|
|
306
|
+
{
|
|
307
|
+
"role": "user",
|
|
308
|
+
"content": {{last_user_text | json}},
|
|
309
|
+
"attachments": [
|
|
310
|
+
{
|
|
311
|
+
"file_id": "file-9rf2OwoLy22Q6bePkO0Zmhlc",
|
|
312
|
+
"tools": [
|
|
313
|
+
{
|
|
314
|
+
"type": "code_interpreter"
|
|
315
|
+
}
|
|
316
|
+
]
|
|
317
|
+
}
|
|
318
|
+
]
|
|
319
|
+
}
|
|
320
|
+
*/
|
|
321
|
+
const json_payload = {
|
|
322
|
+
"role": "user",
|
|
323
|
+
"content": prompt
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
return new Promise( async (resolve, reject) => {
|
|
327
|
+
const url = `https://api.openai.com/v1/threads/${threadId}/messages`;
|
|
328
|
+
const headers = {
|
|
329
|
+
"Authorization": apikey,
|
|
330
|
+
"OpenAI-Beta": "assistants=v2"
|
|
331
|
+
}
|
|
332
|
+
const HTTPREQUEST = {
|
|
333
|
+
url: url,
|
|
334
|
+
headers: headers,
|
|
335
|
+
json: json_payload,
|
|
336
|
+
method: "POST",
|
|
337
|
+
timeout: this.timeout
|
|
338
|
+
};
|
|
339
|
+
if (this.log) {console.log("DirAssistant HTTPREQUEST", HTTPREQUEST);}
|
|
340
|
+
this.#myrequest(
|
|
341
|
+
HTTPREQUEST, async (err, res) => {
|
|
342
|
+
let status = res.status;
|
|
343
|
+
if (err) {
|
|
344
|
+
if (this.log) {console.error("DirAssistant error:", err);}
|
|
345
|
+
reject(err);
|
|
346
|
+
}
|
|
347
|
+
else if(res.status >= 200 && res.status <= 299) {
|
|
348
|
+
if (this.log) {console.log("got response data:", res.data);}
|
|
349
|
+
// let return_body = res.data;
|
|
350
|
+
resolve();
|
|
351
|
+
}
|
|
352
|
+
else {
|
|
353
|
+
reject(new Error("Message add status != 200:", status));
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
);
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
async runThreadOnAssistant(assistantId, threadId, apikey) {
|
|
361
|
+
let _run = await this.createRun(threadId, assistantId, apikey);
|
|
362
|
+
if (this.log) {console.log("Got run:", _run);}
|
|
363
|
+
let runId = _run.id;
|
|
364
|
+
if (this.log) {console.log("runId:", runId);}
|
|
365
|
+
let status = null;
|
|
366
|
+
do {
|
|
367
|
+
if (this.log) {console.log("Getting run...");}
|
|
368
|
+
const wait_for = 2000;
|
|
369
|
+
if (this.log) {console.log("Waiting:", wait_for);}
|
|
370
|
+
await new Promise(resolve => setTimeout(resolve, wait_for));
|
|
371
|
+
let run = await this.getRun(threadId, runId, apikey);
|
|
372
|
+
status = run.status;
|
|
373
|
+
if (this.log) {console.log("Run status:", status);}
|
|
374
|
+
}
|
|
375
|
+
while (status === "queued" || status === "in_progress" || status === "requires_action" && status === "cancelling");
|
|
376
|
+
// while (status != "completed" && status != "cancelled" && status != "failed" && status != "expired");
|
|
377
|
+
// queued, in_progress, requires_action, cancelling
|
|
378
|
+
if (this.log) {console.log("Run end.");}
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
async createRun(threadId, assistantId, apikey) {
|
|
382
|
+
const json_payload = {
|
|
383
|
+
"assistant_id": assistantId
|
|
384
|
+
}
|
|
385
|
+
|
|
386
|
+
return new Promise( async (resolve, reject) => {
|
|
387
|
+
if (this.log) {console.log("adding message to thread...");}
|
|
388
|
+
const url = `https://api.openai.com/v1/threads/${threadId}/runs`;
|
|
389
|
+
const headers = {
|
|
390
|
+
"Authorization": apikey,
|
|
391
|
+
"OpenAI-Beta": "assistants=v2"
|
|
392
|
+
}
|
|
393
|
+
const HTTPREQUEST = {
|
|
394
|
+
url: url,
|
|
395
|
+
headers: headers,
|
|
396
|
+
json: json_payload,
|
|
397
|
+
method: "POST",
|
|
398
|
+
timeout: this.timeout
|
|
399
|
+
};
|
|
400
|
+
if (this.log) {console.log("DirAssistant HTTPREQUEST", HTTPREQUEST);}
|
|
401
|
+
this.#myrequest(
|
|
402
|
+
HTTPREQUEST, async (err, res) => {
|
|
403
|
+
let status = res.status;
|
|
404
|
+
if (err) {
|
|
405
|
+
if (this.log) {console.error("DirAssistant error:", err);}
|
|
406
|
+
reject(err);
|
|
407
|
+
}
|
|
408
|
+
else if(res.status >= 200 && res.status <= 299) {
|
|
409
|
+
if (this.log) {console.log("got response data:", res.data);}
|
|
410
|
+
// let return_body = res.data;
|
|
411
|
+
resolve(res.data);
|
|
412
|
+
}
|
|
413
|
+
else {
|
|
414
|
+
reject(new Error("Message add status != 200:", status));
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
);
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
async getRun(threadId, runId, apikey) {
|
|
422
|
+
return new Promise( async (resolve, reject) => {
|
|
423
|
+
const url = `https://api.openai.com/v1/threads/${threadId}/runs/${runId}`;
|
|
424
|
+
const headers = {
|
|
425
|
+
"Authorization": apikey,
|
|
426
|
+
"OpenAI-Beta": "assistants=v2"
|
|
427
|
+
}
|
|
428
|
+
const HTTPREQUEST = {
|
|
429
|
+
url: url,
|
|
430
|
+
headers: headers,
|
|
431
|
+
json: null,
|
|
432
|
+
method: "GET",
|
|
433
|
+
timeout: this.timeout
|
|
434
|
+
};
|
|
435
|
+
if (this.log) {console.log("DirAssistant HTTPREQUEST", HTTPREQUEST);}
|
|
436
|
+
this.#myrequest(
|
|
437
|
+
HTTPREQUEST, async (err, res) => {
|
|
438
|
+
let status = res.status;
|
|
439
|
+
if (err) {
|
|
440
|
+
if (this.log) {console.error("DirAssistant error:", err);}
|
|
441
|
+
reject(err);
|
|
442
|
+
}
|
|
443
|
+
else if(res.status >= 200 && res.status <= 299) {
|
|
444
|
+
if (this.log) {console.log("got response data:", res.data);}
|
|
445
|
+
// let return_body = res.data;
|
|
446
|
+
resolve(res.data);
|
|
447
|
+
}
|
|
448
|
+
else {
|
|
449
|
+
reject(new Error("Message add status != 200:", status));
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
);
|
|
453
|
+
});
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
async threadMessages(threadId, apikey) {
|
|
457
|
+
return new Promise( async (resolve, reject) => {
|
|
458
|
+
const url = `https://api.openai.com/v1/threads/${threadId}/messages`;
|
|
459
|
+
const headers = {
|
|
460
|
+
"Authorization": apikey,
|
|
461
|
+
"OpenAI-Beta": "assistants=v2"
|
|
462
|
+
}
|
|
463
|
+
const HTTPREQUEST = {
|
|
464
|
+
url: url,
|
|
465
|
+
headers: headers,
|
|
466
|
+
json: null,
|
|
467
|
+
method: "GET",
|
|
468
|
+
timeout: this.timeout
|
|
469
|
+
};
|
|
470
|
+
if (this.log) {console.log("DirAssistant HTTPREQUEST", HTTPREQUEST);}
|
|
471
|
+
this.#myrequest(
|
|
472
|
+
HTTPREQUEST, async (err, res) => {
|
|
473
|
+
let status = res.status;
|
|
474
|
+
if (err) {
|
|
475
|
+
if (this.log) {console.error("DirAssistant error:", err);}
|
|
476
|
+
reject(err);
|
|
477
|
+
}
|
|
478
|
+
else if(res.status >= 200 && res.status <= 299) {
|
|
479
|
+
if (this.log) {console.log("got response data:", res.data);}
|
|
480
|
+
// let return_body = res.data;
|
|
481
|
+
resolve(res.data);
|
|
482
|
+
}
|
|
483
|
+
else {
|
|
484
|
+
reject(new Error("Message add status != 200:", status));
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
);
|
|
488
|
+
});
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
async getKeyFromIntegrations(server_base_url) {
|
|
492
|
+
return new Promise((resolve) => {
|
|
493
|
+
|
|
494
|
+
const INTEGRATIONS_HTTPREQUEST = {
|
|
495
|
+
url: server_base_url + "/" + this.context.projectId + "/integration/name/openai",
|
|
496
|
+
headers: {
|
|
497
|
+
'Content-Type': 'application/json',
|
|
498
|
+
'Authorization': 'JWT ' + this.context.token
|
|
499
|
+
},
|
|
500
|
+
method: "GET"
|
|
501
|
+
}
|
|
502
|
+
if (this.log) { console.log("DirAssistant INTEGRATIONS_HTTPREQUEST ", INTEGRATIONS_HTTPREQUEST) }
|
|
503
|
+
|
|
504
|
+
this.#myrequest(
|
|
505
|
+
INTEGRATIONS_HTTPREQUEST, async (err, integration) => {
|
|
506
|
+
if (err) {
|
|
507
|
+
resolve(null);
|
|
508
|
+
} else {
|
|
509
|
+
|
|
510
|
+
if (integration &&
|
|
511
|
+
integration.value) {
|
|
512
|
+
resolve(integration.value.apikey)
|
|
513
|
+
}
|
|
514
|
+
else {
|
|
515
|
+
resolve(null)
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
})
|
|
519
|
+
})
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
#myrequest(options, callback) {
|
|
523
|
+
try {
|
|
524
|
+
if (this.log) {
|
|
525
|
+
console.log("API URL:", options.url);
|
|
526
|
+
//console.log("** Options:", JSON.stringify(options));
|
|
527
|
+
// Stringify "options". FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
528
|
+
let cache = [];
|
|
529
|
+
let str_Options = JSON.stringify(options, function(key, value) { // try to use a separate function
|
|
530
|
+
if (typeof value === 'object' && value != null) {
|
|
531
|
+
if (cache.indexOf(value) !== -1) {
|
|
532
|
+
return;
|
|
533
|
+
}
|
|
534
|
+
cache.push(value);
|
|
535
|
+
}
|
|
536
|
+
return value;
|
|
537
|
+
});
|
|
538
|
+
console.log("** Options:", str_Options);
|
|
539
|
+
|
|
540
|
+
|
|
541
|
+
}
|
|
542
|
+
let axios_options = {
|
|
543
|
+
url: options.url,
|
|
544
|
+
method: options.method,
|
|
545
|
+
params: options.params,
|
|
546
|
+
headers: options.headers,
|
|
547
|
+
timeout: options.timeout
|
|
548
|
+
}
|
|
549
|
+
|
|
550
|
+
if (options.json !== null) {
|
|
551
|
+
axios_options.data = options.json
|
|
552
|
+
}
|
|
553
|
+
// if (this.log) {
|
|
554
|
+
// console.log("axios_options:", JSON.stringify(axios_options));
|
|
555
|
+
// }
|
|
556
|
+
if (options.url.startsWith("https:")) {
|
|
557
|
+
const httpsAgent = new https.Agent({
|
|
558
|
+
rejectUnauthorized: false,
|
|
559
|
+
});
|
|
560
|
+
axios_options.httpsAgent = httpsAgent;
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
axios(axios_options)
|
|
564
|
+
.then((res) => {
|
|
565
|
+
if (this.log) {
|
|
566
|
+
console.log("Success Response:", res);
|
|
567
|
+
console.log("Response for url:", options.url);
|
|
568
|
+
console.log("Response headers:\n", JSON.stringify(res.headers));
|
|
569
|
+
}
|
|
570
|
+
if (callback) {
|
|
571
|
+
callback(null, res);
|
|
572
|
+
}
|
|
573
|
+
})
|
|
574
|
+
.catch( (err) => {
|
|
575
|
+
if (this.log) {
|
|
576
|
+
if (err.response) {
|
|
577
|
+
console.log("Error Response data:", err.response.data);
|
|
578
|
+
}
|
|
579
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
580
|
+
let cache = [];
|
|
581
|
+
let error_log = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
582
|
+
if (typeof value === 'object' && value != null) {
|
|
583
|
+
if (cache.indexOf(value) !== -1) {
|
|
584
|
+
return;
|
|
585
|
+
}
|
|
586
|
+
cache.push(value);
|
|
587
|
+
}
|
|
588
|
+
return value;
|
|
589
|
+
});
|
|
590
|
+
console.error("An error occurred: ", error_log);
|
|
591
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - END
|
|
592
|
+
// console.error("An error occurred:", JSON.stringify(err));
|
|
593
|
+
}
|
|
594
|
+
if (callback) {
|
|
595
|
+
let status = 1000;
|
|
596
|
+
let cache = [];
|
|
597
|
+
let str_error = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
598
|
+
if (typeof value === 'object' && value != null) {
|
|
599
|
+
if (cache.indexOf(value) !== -1) {
|
|
600
|
+
return;
|
|
601
|
+
}
|
|
602
|
+
cache.push(value);
|
|
603
|
+
}
|
|
604
|
+
return value;
|
|
605
|
+
});
|
|
606
|
+
let error = JSON.parse(str_error) // "status" disappears without this trick
|
|
607
|
+
let errorMessage = JSON.stringify(error);
|
|
608
|
+
if (error.status) {
|
|
609
|
+
status = error.status;
|
|
610
|
+
}
|
|
611
|
+
if (error.message) {
|
|
612
|
+
errorMessage = error.message;
|
|
613
|
+
}
|
|
614
|
+
let data = null;
|
|
615
|
+
if (err.response) {
|
|
616
|
+
data = err.response.data;
|
|
617
|
+
}
|
|
618
|
+
callback(
|
|
619
|
+
null, {
|
|
620
|
+
status: status,
|
|
621
|
+
data: data,
|
|
622
|
+
error: errorMessage
|
|
623
|
+
}
|
|
624
|
+
);
|
|
625
|
+
}
|
|
626
|
+
});
|
|
627
|
+
}
|
|
628
|
+
catch(error) {
|
|
629
|
+
console.error("Error:", error);
|
|
630
|
+
}
|
|
631
|
+
}
|
|
632
|
+
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
|
|
636
|
+
|
|
637
|
+
module.exports = { DirAssistant };
|
|
@@ -35,36 +35,80 @@ class DirWebRequestV2 {
|
|
|
35
35
|
|
|
36
36
|
async go(action, callback) {
|
|
37
37
|
if (this.log) {console.log("webRequest action:", JSON.stringify(action));}
|
|
38
|
-
let
|
|
38
|
+
let requestAttributes = null;
|
|
39
39
|
if (this.tdcache) {
|
|
40
|
-
|
|
40
|
+
requestAttributes =
|
|
41
41
|
await TiledeskChatbot.allParametersStatic(
|
|
42
42
|
this.tdcache, this.requestId
|
|
43
43
|
);
|
|
44
44
|
}
|
|
45
45
|
const filler = new Filler();
|
|
46
|
-
const url = filler.fill(action.url,
|
|
46
|
+
const url = filler.fill(action.url, requestAttributes);
|
|
47
47
|
|
|
48
48
|
let headers = {};
|
|
49
49
|
if (action.headersString) {
|
|
50
50
|
let headersDict = action.headersString
|
|
51
51
|
for (const [key, value] of Object.entries(headersDict)) {
|
|
52
52
|
if (this.log) {console.log("header:", key, "value:", value)}
|
|
53
|
-
let filled_value = filler.fill(value,
|
|
53
|
+
let filled_value = filler.fill(value, requestAttributes);
|
|
54
54
|
headers[key] = filled_value;
|
|
55
55
|
}
|
|
56
56
|
}
|
|
57
|
+
|
|
57
58
|
let json = null;
|
|
58
|
-
|
|
59
|
-
if (
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
59
|
+
try {
|
|
60
|
+
if (action.jsonBody && action.bodyType == "json") {
|
|
61
|
+
if (this.log) {console.log("action.body is:", action.jsonBody);}
|
|
62
|
+
let jsonBody = filler.fill(action.jsonBody, requestAttributes);
|
|
63
|
+
try {
|
|
64
|
+
json = JSON.parse(jsonBody);
|
|
65
|
+
if (this.log) {console.log("json is:", json);}
|
|
66
|
+
}
|
|
67
|
+
catch(err) {
|
|
68
|
+
console.error("Error parsing webRequest jsonBody:", jsonBody);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
else if (action.formData && action.bodyType == "form-data") {
|
|
72
|
+
let formData = filler.fill(action.formData, requestAttributes);
|
|
73
|
+
if (this.log) {console.log("action.body is form-data:", formData);}
|
|
74
|
+
// // fill
|
|
75
|
+
if (formData && formData.length > 0) {
|
|
76
|
+
for (let i = 0; i < formData.length; i++) {
|
|
77
|
+
let field = formData[i];
|
|
78
|
+
if (field.value) {
|
|
79
|
+
field.value = filler.fill(field.value, requestAttributes);
|
|
80
|
+
if (this.log) {console.log("field filled:", field.value);}
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
json = {};
|
|
85
|
+
for (let i = 0; i < formData.length; i++) {
|
|
86
|
+
let field = formData[i];
|
|
87
|
+
if (field.enabled && field.value && field.type === "URL") {
|
|
88
|
+
if (this.log) {console.log("Getting file:", field.value);}
|
|
89
|
+
let response = await axios.get(field.value,
|
|
90
|
+
{
|
|
91
|
+
responseType: 'stream'
|
|
92
|
+
}
|
|
93
|
+
);
|
|
94
|
+
let stream = response.data;
|
|
95
|
+
// if (this.log) {console.log("Stream data:", stream);}
|
|
96
|
+
json[field.name] = stream;
|
|
97
|
+
// process.exit(0);
|
|
98
|
+
}
|
|
99
|
+
else if (field.enabled && field.value && field.type === "Text") {
|
|
100
|
+
json[field.name] = field.value;
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
if (this.log) {console.log("final json:", json);}
|
|
64
104
|
}
|
|
65
|
-
|
|
66
|
-
console.
|
|
105
|
+
else {
|
|
106
|
+
if (this.log) {console.log("no action upload parts");}
|
|
67
107
|
}
|
|
108
|
+
|
|
109
|
+
}
|
|
110
|
+
catch(error) {
|
|
111
|
+
console.error("Error", error);
|
|
68
112
|
}
|
|
69
113
|
|
|
70
114
|
// Condition branches
|
|
@@ -81,8 +125,9 @@ class DirWebRequestV2 {
|
|
|
81
125
|
}
|
|
82
126
|
|
|
83
127
|
let timeout = this.#webrequest_timeout(action, 20000, 1, 300000);
|
|
84
|
-
|
|
128
|
+
|
|
85
129
|
if (this.log) {console.log("webRequest URL", url);}
|
|
130
|
+
|
|
86
131
|
const HTTPREQUEST = {
|
|
87
132
|
url: url,
|
|
88
133
|
headers: headers,
|
|
@@ -90,6 +135,7 @@ class DirWebRequestV2 {
|
|
|
90
135
|
method: action.method,
|
|
91
136
|
timeout: timeout
|
|
92
137
|
};
|
|
138
|
+
|
|
93
139
|
if (this.log) {console.log("webRequest HTTPREQUEST", HTTPREQUEST);}
|
|
94
140
|
this.#myrequest(
|
|
95
141
|
HTTPREQUEST, async (err, res) => {
|
|
@@ -203,63 +249,13 @@ class DirWebRequestV2 {
|
|
|
203
249
|
}
|
|
204
250
|
|
|
205
251
|
#myrequest(options, callback) {
|
|
206
|
-
|
|
207
|
-
console.log("API URL:", options.url);
|
|
208
|
-
console.log("** Options:", JSON.stringify(options));
|
|
209
|
-
}
|
|
210
|
-
let axios_options = {
|
|
211
|
-
url: options.url,
|
|
212
|
-
method: options.method,
|
|
213
|
-
params: options.params,
|
|
214
|
-
headers: options.headers,
|
|
215
|
-
timeout: options.timeout
|
|
216
|
-
}
|
|
217
|
-
if (options.json !== null) {
|
|
218
|
-
axios_options.data = options.json
|
|
219
|
-
}
|
|
220
|
-
if (this.log) {
|
|
221
|
-
console.log("axios_options:", JSON.stringify(axios_options));
|
|
222
|
-
}
|
|
223
|
-
if (options.url.startsWith("https:")) {
|
|
224
|
-
const httpsAgent = new https.Agent({
|
|
225
|
-
rejectUnauthorized: false,
|
|
226
|
-
});
|
|
227
|
-
axios_options.httpsAgent = httpsAgent;
|
|
228
|
-
}
|
|
229
|
-
axios(axios_options)
|
|
230
|
-
.then((res) => {
|
|
252
|
+
try {
|
|
231
253
|
if (this.log) {
|
|
232
|
-
console.log("
|
|
233
|
-
console.log("
|
|
234
|
-
|
|
235
|
-
}
|
|
236
|
-
if (callback) {
|
|
237
|
-
callback(null, res);
|
|
238
|
-
}
|
|
239
|
-
// if (callback) {
|
|
240
|
-
// let data = null;
|
|
241
|
-
// let status = 1000;
|
|
242
|
-
// if (res) {
|
|
243
|
-
// status = res.status;
|
|
244
|
-
// data = res.data;
|
|
245
|
-
// }
|
|
246
|
-
// callback(
|
|
247
|
-
// {
|
|
248
|
-
// status: status,
|
|
249
|
-
// data: data
|
|
250
|
-
// }, null
|
|
251
|
-
// );
|
|
252
|
-
// }
|
|
253
|
-
|
|
254
|
-
})
|
|
255
|
-
.catch( (err) => {
|
|
256
|
-
if (this.log) {
|
|
257
|
-
if (err.response) {
|
|
258
|
-
console.log("Error Response data:", err.response.data);
|
|
259
|
-
}
|
|
260
|
-
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
254
|
+
console.log("API URL:", options.url);
|
|
255
|
+
//console.log("** Options:", JSON.stringify(options));
|
|
256
|
+
// Stringify "options". FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
261
257
|
let cache = [];
|
|
262
|
-
let
|
|
258
|
+
let str_Options = JSON.stringify(options, function(key, value) { // try to use a separate function
|
|
263
259
|
if (typeof value === 'object' && value != null) {
|
|
264
260
|
if (cache.indexOf(value) !== -1) {
|
|
265
261
|
return;
|
|
@@ -268,43 +264,99 @@ class DirWebRequestV2 {
|
|
|
268
264
|
}
|
|
269
265
|
return value;
|
|
270
266
|
});
|
|
271
|
-
console.
|
|
272
|
-
|
|
273
|
-
|
|
267
|
+
console.log("** Options:", str_Options);
|
|
268
|
+
|
|
269
|
+
|
|
274
270
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
271
|
+
let axios_options = {
|
|
272
|
+
url: options.url,
|
|
273
|
+
method: options.method,
|
|
274
|
+
params: options.params,
|
|
275
|
+
headers: options.headers,
|
|
276
|
+
timeout: options.timeout
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
if (options.json !== null) {
|
|
280
|
+
axios_options.data = options.json
|
|
281
|
+
}
|
|
282
|
+
// if (this.log) {
|
|
283
|
+
// console.log("axios_options:", JSON.stringify(axios_options));
|
|
284
|
+
// }
|
|
285
|
+
if (options.url.startsWith("https:")) {
|
|
286
|
+
const httpsAgent = new https.Agent({
|
|
287
|
+
rejectUnauthorized: false,
|
|
286
288
|
});
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
289
|
+
axios_options.httpsAgent = httpsAgent;
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
axios(axios_options)
|
|
293
|
+
.then((res) => {
|
|
294
|
+
if (this.log) {
|
|
295
|
+
console.log("Success Response:", res);
|
|
296
|
+
console.log("Response for url:", options.url);
|
|
297
|
+
console.log("Response headers:\n", JSON.stringify(res.headers));
|
|
291
298
|
}
|
|
292
|
-
if (
|
|
293
|
-
|
|
299
|
+
if (callback) {
|
|
300
|
+
callback(null, res);
|
|
294
301
|
}
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
302
|
+
})
|
|
303
|
+
.catch( (err) => {
|
|
304
|
+
if (this.log) {
|
|
305
|
+
if (err.response) {
|
|
306
|
+
console.log("Error Response data:", err.response.data);
|
|
307
|
+
}
|
|
308
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - START
|
|
309
|
+
let cache = [];
|
|
310
|
+
let error_log = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
311
|
+
if (typeof value === 'object' && value != null) {
|
|
312
|
+
if (cache.indexOf(value) !== -1) {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
cache.push(value);
|
|
316
|
+
}
|
|
317
|
+
return value;
|
|
318
|
+
});
|
|
319
|
+
console.error("An error occurred: ", error_log);
|
|
320
|
+
// FIX THE STRINGIFY OF CIRCULAR STRUCTURE BUG - END
|
|
321
|
+
// console.error("An error occurred:", JSON.stringify(err));
|
|
298
322
|
}
|
|
299
|
-
callback
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
323
|
+
if (callback) {
|
|
324
|
+
let status = 1000;
|
|
325
|
+
let cache = [];
|
|
326
|
+
let str_error = JSON.stringify(err, function(key, value) { // try to use a separate function
|
|
327
|
+
if (typeof value === 'object' && value != null) {
|
|
328
|
+
if (cache.indexOf(value) !== -1) {
|
|
329
|
+
return;
|
|
330
|
+
}
|
|
331
|
+
cache.push(value);
|
|
332
|
+
}
|
|
333
|
+
return value;
|
|
334
|
+
});
|
|
335
|
+
let error = JSON.parse(str_error) // "status" disappears without this trick
|
|
336
|
+
let errorMessage = JSON.stringify(error);
|
|
337
|
+
if (error.status) {
|
|
338
|
+
status = error.status;
|
|
304
339
|
}
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
340
|
+
if (error.message) {
|
|
341
|
+
errorMessage = error.message;
|
|
342
|
+
}
|
|
343
|
+
let data = null;
|
|
344
|
+
if (err.response) {
|
|
345
|
+
data = err.response.data;
|
|
346
|
+
}
|
|
347
|
+
callback(
|
|
348
|
+
null, {
|
|
349
|
+
status: status,
|
|
350
|
+
data: data,
|
|
351
|
+
error: errorMessage
|
|
352
|
+
}
|
|
353
|
+
);
|
|
354
|
+
}
|
|
355
|
+
});
|
|
356
|
+
}
|
|
357
|
+
catch(error) {
|
|
358
|
+
console.error("Error:", error);
|
|
359
|
+
}
|
|
308
360
|
}
|
|
309
361
|
|
|
310
362
|
#webrequest_timeout(action, default_timeout, min, max) {
|
|
@@ -46,6 +46,7 @@ class Directives {
|
|
|
46
46
|
static BLIND_TRANSFER = 'blind_transfer';
|
|
47
47
|
static SPEECH_FORM = 'speech_form';
|
|
48
48
|
static PLAY_PROMPT = 'play_prompt';
|
|
49
|
+
static GPT_ASSISTANT = 'gpt_assistant';
|
|
49
50
|
|
|
50
51
|
// static WHEN_ONLINE_MOVE_TO_AGENT = "whenonlinemovetoagent"; // DEPRECATED?
|
|
51
52
|
// static WHEN_OFFLINE_HOURS = "whenofflinehours"; // DEPRECATED // adds a message on top of the original message when offline hours opts: --replace
|