@inductiv/node-red-openai-api 0.3.1 → 0.3.3

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/.eslintrc.json CHANGED
@@ -1,13 +1,12 @@
1
1
  {
2
2
  "env": {
3
- "browser": true,
4
3
  "commonjs": true,
5
- "es2021": true
4
+ "es2021": true,
5
+ "node": true
6
6
  },
7
7
  "extends": "eslint:recommended",
8
8
  "parserOptions": {
9
9
  "ecmaVersion": "latest"
10
10
  },
11
- "rules": {
12
- }
11
+ "rules": {}
13
12
  }
package/README.md CHANGED
@@ -31,7 +31,7 @@ New in version 0.3.0: You can now set a custom API service host base URL. This p
31
31
 
32
32
  To utilize this feature, simply specify the custom API service host base URL in the node configuration. This enhancement is built upon the existing framework, ensuring a smooth and intuitive user experience.
33
33
 
34
- #### Service HOst Configuration Examples
34
+ #### Service Host Configuration Examples
35
35
 
36
36
  <img width="371" alt="service host node config" src="https://github.com/allanbunch/node-red-openai-api/assets/4503640/256362c5-6e78-44c7-af6e-12d5830cdf32">
37
37
 
package/lib.js CHANGED
@@ -1,614 +1,721 @@
1
1
  var OpenaiApi = (function () {
2
- 'use strict';
3
-
4
- const axios = require('axios');
5
- const FormData = require('form-data'); // Only if you handle form data
6
-
7
- class OpenaiApi {
8
- constructor(options) {
9
- this.apiKey = (typeof options === 'object') ? (options.apiKey ? options.apiKey : {}) : {};
10
- }
11
- request(method, url, body, headers, queryParameters, form) {
12
- // Create an instance of axios with default headers
13
- const axiosInstance = axios.create({
14
- headers: headers
15
- });
16
-
17
- // Initialize the data to be sent
18
- let data = body;
19
-
20
- // Handle 'multipart/form-data'
21
- if (Object.keys(form).length > 0 && headers['Content-Type'] === 'multipart/form-data') {
22
- const formData = new FormData();
23
- for (const key of Object.keys(parameters)) {
24
- formData.append(key, parameters.body[key]);
25
- };
26
- data = formData;
27
- } else if (typeof body === 'object' && !(body instanceof Buffer)) {
28
- // Ensure the headers are set for JSON
29
- headers['Content-Type'] = 'application/json';
30
- }
2
+ "use strict";
3
+
4
+ const axios = require("axios");
5
+ const FormData = require("form-data"); // Only if you handle form data
6
+
7
+ class OpenaiApi {
8
+ constructor(options) {
9
+ this.apiKey =
10
+ typeof options === "object"
11
+ ? options.apiKey
12
+ ? options.apiKey
13
+ : {}
14
+ : {};
15
+ }
31
16
 
32
- // Remove body data for GET requests
33
- if (method === "GET") {
34
- data = undefined;
17
+ setApiKey(value, headerOrQueryName, isQuery) {
18
+ this.apiKey.value = value;
19
+ this.apiKey.headerOrQueryName = headerOrQueryName;
20
+ this.apiKey.isQuery = isQuery;
21
+ }
22
+ setApiBase(apiBase) {
23
+ this.domain = apiBase;
24
+ }
25
+ setAuthHeaders(headerParams) {
26
+ var headers = headerParams ? headerParams : {};
27
+ if (!this.apiKey.isQuery && this.apiKey.headerOrQueryName) {
28
+ headers[this.apiKey.headerOrQueryName] = `Bearer ${this.apiKey.value}`;
29
+ }
30
+ return headers;
31
+ }
32
+ getFromEndpoint(path, parameters, expectedQueryParams, customHeaders) {
33
+ return new Promise((resolve, reject) => {
34
+ var domain = this.domain;
35
+ var queryParameters = {},
36
+ baseHeaders = {};
37
+
38
+ baseHeaders = this.setAuthHeaders(headers);
39
+ baseHeaders["Accept"] = "application/json";
40
+
41
+ var headers = {
42
+ ...baseHeaders,
43
+ ...customHeaders,
44
+ };
45
+
46
+ // Only add query parameters if they are expected and exist
47
+ if (expectedQueryParams) {
48
+ expectedQueryParams.forEach((param) => {
49
+ if (parameters.body[param] !== undefined) {
50
+ queryParameters[param] = parameters.body[param];
35
51
  }
36
-
37
- // Make the axios request
38
- return axiosInstance({
39
- method: method,
40
- url: url,
41
- params: queryParameters,
42
- data: data
43
- })
44
- .then(response => {
45
- // Check for JSON response and parse if necessary
46
- if (/^application\/(.*\+)?json/.test(response.headers['content-type'])) {
47
- return { response: response, body: response.data };
48
- } else {
49
- // For non-JSON responses, resolve with the raw response
50
- return { response: response, body: response.data };
51
- }
52
- })
53
- .catch(error => {
54
- // Handle errors
55
- if (error.response) {
56
- // The server responded with a status code that falls out of the range of 2xx
57
- throw { response: error.response, body: error.response.data };
58
- } else if (error.request) {
59
- // The request was made but no response was received
60
- throw new Error('No response received');
61
- } else {
62
- // Something happened in setting up the request that triggered an Error
63
- throw new Error(error.message);
64
- }
65
- });
66
- }
67
- setApiKey(value, headerOrQueryName, isQuery) {
68
- this.apiKey.value = value;
69
- this.apiKey.headerOrQueryName = headerOrQueryName;
70
- this.apiKey.isQuery = isQuery;
71
- }
72
- setApiBase(apiBase) {
73
- this.domain = apiBase;
74
- }
75
- setAuthHeaders(headerParams) {
76
- var headers = headerParams ? headerParams : {};
77
- if (!this.apiKey.isQuery && this.apiKey.headerOrQueryName) {
78
- headers[this.apiKey.headerOrQueryName] = `Bearer ${this.apiKey.value}`;
52
+ });
53
+ }
54
+
55
+ // Merge any additional query parameters from the parameters object
56
+ queryParameters = mergeQueryParams(parameters, queryParameters);
57
+
58
+ // Axios request configuration
59
+ const config = {
60
+ method: "GET",
61
+ url: domain + path,
62
+ headers: headers,
63
+ params: queryParameters,
64
+ };
65
+
66
+ // Axios GET request
67
+ axios(config)
68
+ .then((response) => {
69
+ resolve(response);
70
+ })
71
+ .catch((error) => {
72
+ reject(error);
73
+ });
74
+ });
75
+ }
76
+ postToEndpoint(
77
+ path,
78
+ parameters,
79
+ expectedQueryParams,
80
+ contentType,
81
+ filePath,
82
+ customHeaders,
83
+ ) {
84
+ return new Promise((resolve, reject) => {
85
+ const _path = require("path");
86
+
87
+ parameters = parameters || {};
88
+ var domain = this.domain;
89
+ var queryParameters = {},
90
+ baseHeaders = {},
91
+ data;
92
+
93
+ baseHeaders = this.setAuthHeaders({});
94
+ baseHeaders["Accept"] = "application/json";
95
+
96
+ var headers = {
97
+ ...baseHeaders,
98
+ ...customHeaders,
99
+ };
100
+
101
+ // Determine the Content-Type
102
+ if (contentType === "form-data") {
103
+ var formData = new FormData();
104
+
105
+ Object.entries(parameters.body).forEach(([key, value]) => {
106
+ if (value instanceof Buffer) {
107
+ if (!filePath) {
108
+ throw new Error(
109
+ "msg.payload must include a `filename` property.",
110
+ );
111
+ }
112
+
113
+ const filename = _path.basename(filePath);
114
+ formData.append(key, value, filename);
115
+ } else {
116
+ if (parameters.body[key] !== undefined) {
117
+ formData.append(key, value);
118
+ }
79
119
  }
80
- return headers;
81
- }
82
- getFromEndpoint(path, parameters, expectedQueryParams, customHeaders) {
83
- return new Promise((resolve, reject) => {
84
- var domain = this.domain;
85
- var queryParameters = {}, baseHeaders = {};
86
-
87
- baseHeaders = this.setAuthHeaders(headers);
88
- baseHeaders['Accept'] = 'application/json';
89
-
90
- var headers = {
91
- ...baseHeaders,
92
- ...customHeaders
93
- };
94
-
95
-
96
- // Only add query parameters if they are expected and exist
97
- if (expectedQueryParams) {
98
- expectedQueryParams.forEach(param => {
99
- if (parameters.body[param] !== undefined) {
100
- queryParameters[param] = parameters.body[param];
101
- }
102
- });
103
- }
104
-
105
- // Merge any additional query parameters from the parameters object
106
- queryParameters = mergeQueryParams(parameters, queryParameters);
107
-
108
- // Axios request configuration
109
- const config = {
110
- method: 'GET',
111
- url: domain + path,
112
- headers: headers,
113
- params: queryParameters
114
- };
115
-
116
- // Axios GET request
117
- axios(config)
118
- .then(response => {
119
- resolve(response);
120
- })
121
- .catch(error => {
122
- reject(error);
123
- });
124
- });
125
- }
126
- postToEndpoint(path, parameters, expectedQueryParams, contentType, filePath, customHeaders) {
127
- return new Promise((resolve, reject) => {
128
- const _path = require('path');
129
-
130
- parameters = parameters || {};
131
- var domain = this.domain;
132
- var queryParameters = {}, baseHeaders = {}, data;
133
-
134
- baseHeaders = this.setAuthHeaders({});
135
- baseHeaders['Accept'] = 'application/json';
136
-
137
- var headers = {
138
- ...baseHeaders,
139
- ...customHeaders
140
- };
141
-
142
- // Determine the Content-Type
143
- if (contentType === 'form-data') {
144
- var formData = new FormData();
145
-
146
- Object.entries(parameters.body).forEach(([key, value]) => {
147
- if (value instanceof Buffer) {
148
- if (!filePath) {
149
- throw new Error('msg.payload must include a `filename` property.');
150
- }
151
-
152
- const filename = _path.basename(filePath);
153
- formData.append(key, value, filename);
154
- } else {
155
- if (parameters.body[key] !== undefined) {
156
- formData.append(key, value);
157
- }
158
- }
159
- });
160
-
161
- data = formData;
162
-
163
- let formHeaders = formData.getHeaders();
164
- Object.assign(headers, formHeaders);
165
- } else {
166
- // Handle JSON payloads
167
- headers['Content-Type'] = 'application/json';
168
- data = parameters.body || {};
169
- }
170
-
171
- // Add expected query parameters to the queryParameters object
172
- if (expectedQueryParams) {
173
- expectedQueryParams.forEach(param => {
174
- if (parameters.body[param] !== undefined) {
175
- queryParameters[param] = parameters.body[param];
176
- }
177
- });
178
- }
179
-
180
- // Merge any additional query parameters from the parameters object
181
- queryParameters = mergeQueryParams(parameters.body, queryParameters);
182
-
183
- // Axios request configuration
184
- const config = {
185
- method: 'POST',
186
- url: domain + path,
187
- headers: headers,
188
- params: queryParameters,
189
- data: data
190
- };
191
-
192
- // Axios POST request
193
- axios(config)
194
- .then(response => {
195
- resolve(response);
196
- })
197
- .catch(error => {
198
- reject(error);
199
- });
200
- });
201
- }
202
- deleteFromEndpoint(path, parameters, expectedQueryParams, customHeaders) {
203
- return new Promise((resolve, reject) => {
204
- parameters = parameters || {};
205
- var domain = this.domain;
206
- var queryParameters = {}, baseHeaders = {};
207
-
208
- baseHeaders = this.setAuthHeaders(headers);
209
- baseHeaders['Accept'] = 'application/json';
210
-
211
- var headers = {
212
- ...baseHeaders,
213
- ...customHeaders
214
- };
215
-
216
- // Only add query parameters if they are expected and exist
217
- if (expectedQueryParams) {
218
- expectedQueryParams.forEach(param => {
219
- if (parameters[param] !== undefined) {
220
- queryParameters[param] = parameters.body[param];
221
- }
222
- });
223
- }
224
-
225
- // Merge any additional query parameters from the parameters object
226
- queryParameters = mergeQueryParams(parameters, queryParameters);
227
-
228
- // Axios request configuration
229
- const config = {
230
- method: 'DELETE',
231
- url: domain + path,
232
- headers: headers,
233
- params: queryParameters
234
- };
235
-
236
- // Axios DELETE request
237
- axios(config)
238
- .then(response => {
239
- resolve(response);
240
- })
241
- .catch(error => {
242
- reject(error);
243
- });
244
- });
245
- }
246
- createChatCompletion(parameters) {
247
- const response = this.postToEndpoint('/chat/completions', parameters);
248
- return response;
249
- }
250
- createImage(parameters) {
251
- return this.postToEndpoint('/images/generations', parameters);
252
- }
253
- createImageEdit(parameters) {
254
- const filename = parameters.body.filename;
255
- delete parameters.body.filename;
256
-
257
- return this.postToEndpoint('/images/edits', parameters, null, 'form-data', filename);
258
- }
259
- createImageVariation(parameters) {
260
- const filename = parameters.body.filename;
261
- delete parameters.body.filename;
262
-
263
- return this.postToEndpoint('/images/variations', parameters, null, 'form-data', filename);
264
- }
265
- createEmbedding(parameters) {
266
- return this.postToEndpoint('/embeddings', parameters);
267
- }
268
- createSpeech(parameters) {
269
- return this.postToEndpoint('/audio/speech', parameters);
270
- }
271
- createTranscription(parameters) {
272
- const filename = parameters.body.filename;
273
- delete parameters.body.filename;
274
-
275
- return this.postToEndpoint('/audio/transcriptions', parameters, null, 'form-data', filename);
276
- }
277
- createTranslation(parameters) {
278
- const filename = parameters.body.filename;
279
- delete parameters.body.filename;
280
-
281
- return this.postToEndpoint('/audio/translations', parameters, null, 'form-data', filename);
282
- }
283
- listFiles(parameters) {
284
- const expectedQueryParameters = ['purpose'];
285
- return this.getFromEndpoint('/files', parameters, expectedQueryParameters);
286
- }
287
- createFile(parameters) {
288
- let filename;
289
-
290
- // reference the incoming filename
291
- filename = parameters.body.filename;
292
- delete parameters.body.filename;
293
-
294
- return this.postToEndpoint('/files', parameters, null, 'form-data', filename);
295
- }
296
- deleteFile(parameters) {
297
- const file_id = parameters.body.file_id;
298
- return this.deleteFromEndpoint(`/files/${file_id}`, parameters);
299
- }
300
- retrieveFile(parameters) {
301
- const file_id = parameters.body.file_id;
302
- return this.getFromEndpoint(`/files/${file_id}`, parameters);
303
- }
304
- downloadFile(parameters) {
305
- const file_id = parameters.body.file_id;
306
- return this.getFromEndpoint(`/files/${file_id}/content`, parameters);
307
- }
308
- createFineTuningJob(parameters) {
309
- return this.postToEndpoint('/fine_tuning/jobs', parameters);
310
- }
311
- listPaginatedFineTuningJobs(parameters) {
312
- const expectedQueryParameters = ['after', 'limit'];
313
- return this.getFromEndpoint('/fine_tuning/jobs', parameters, expectedQueryParameters);
314
- }
315
- retrieveFineTuningJob(parameters) {
316
- const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
317
- return this.getFromEndpoint(`/fine_tuning/jobs/${fine_tuning_job_id}`, parameters);
318
- }
319
- listFineTuningEvents(parameters) {
320
- const expectedQueryParameters = ['after', 'limit'];
321
- const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
322
-
323
- return this.getFromEndpoint(`/fine_tuning/jobs/${fine_tuning_job_id}/events`, parameters, expectedQueryParameters);
324
- }
325
- cancelFineTuningJob(parameters) {
326
- const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
327
- return this.postToEndpoint(`/fine_tuning/jobs/${fine_tuning_job_id}/cancel`, parameters);
328
- }
329
- listModels(parameters) {
330
- return this.getFromEndpoint('/models', parameters);
331
- }
332
- retrieveModel(parameters) {
333
- const model = parameters.body.model;
334
-
335
- return this.getFromEndpoint(`/models/${model}`, parameters);
336
- }
337
- deleteModel(parameters) {
338
- const model = parameters.body.model;
339
-
340
- return this.deleteFromEndpoint(`/models/${model}`, parameters);
341
- }
342
- createModeration(parameters) {
343
- return this.postToEndpoint('/moderations', parameters);
344
- }
345
- listAssistants(parameters) {
346
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
347
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
348
-
349
- return this.getFromEndpoint('/assistants', parameters, expectedQueryParameters, customHeaders);
350
- }
351
- createAssistant(parameters) {
352
- var customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
353
-
354
- return this.postToEndpoint('/assistants', parameters, null, null, null, customHeaders);
355
- }
356
- getAssistant(parameters) {
357
- const assistantId = parameters.body.assistant_id;
358
-
359
- var customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
360
-
361
- return this.getFromEndpoint(`/assistants/${assistantId}`, parameters, null, customHeaders);
362
- }
363
- modifyAssistant(parameters) {
364
-
365
- const assistant_id = parameters.body.assistant_id;
366
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
367
-
368
- return this.postToEndpoint(`/assistants/${assistant_id}`, parameters, null, null, null, customHeaders);
369
- }
370
- deleteAssistant(parameters) {
371
- const assistant_id = parameters.body.assistant_id;
372
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
373
-
374
- return this.deleteFromEndpoint(`/assistants/${assistant_id}`, parameters, null, customHeaders);
375
- }
376
- createThread(parameters) {
377
-
378
-
379
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
380
- return this.postToEndpoint('/threads', parameters, null, null, null, customHeaders);
381
- }
382
- getThread(parameters) {
383
- const threadId = parameters.body.thread_id;
384
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
385
-
386
- return this.getFromEndpoint(`/threads/${threadId}`, parameters, null, customHeaders);
387
- }
388
- modifyThread(parameters) {
389
- const threadId = parameters.body.thread_id;
390
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
391
-
392
- return this.postToEndpoint(`/threads/${threadId}`, parameters, null, null, null, customHeaders);
393
- }
394
- deleteThread(parameters) {
395
- const threadId = parameters.body.thread_id;
396
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
397
-
398
- return this.deleteFromEndpoint(`/threads/${threadId}`, parameters, null, customHeaders);
399
- }
400
- listMessages(parameters) {
401
- const threadId = parameters.body.thread_id;
402
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
403
-
404
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
405
-
406
- return this.getFromEndpoint(`/threads/${threadId}/messages`, parameters, expectedQueryParameters, customHeaders);
407
- }
408
- createMessage(parameters) {
409
- const threadId = parameters.body.thread_id;
410
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
411
-
412
- return this.postToEndpoint(`/threads/${threadId}/messages`, parameters, null, null, null, customHeaders);
413
- }
414
- getMessage(parameters) {
415
-
416
- const threadId = parameters.body.thread_id;
417
- const messageId = parameters.body.message_id;
418
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
419
-
420
- return this.getFromEndpoint(`/threads/${threadId}/messages/${messageId}`, parameters, null, customHeaders);
421
- }
422
- modifyMessage(parameters) {
423
-
424
- const threadId = parameters.body.thread_id;
425
- const messageId = parameters.body.message_id;
426
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
427
-
428
- return this.postToEndpoint(`/threads/${threadId}/messages/${messageId}`, parameters, null, null, null, customHeaders);
429
- }
430
- createThreadAndRun(parameters) {
431
-
432
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
433
-
434
- return this.postToEndpoint('/threads/runs', parameters, null, null, null, customHeaders);
435
- }
436
- listRuns(parameters) {
437
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
438
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
439
- const threadId = parameters.body.thread_id;
440
-
441
- return this.getFromEndpoint(`/threads/${threadId}/runs`, parameters, expectedQueryParameters, customHeaders);
442
- }
443
- createRun(parameters) {
444
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
445
- const threadId = parameters.body.thread_id;
446
-
447
- return this.postToEndpoint(`/threads/${threadId}/runs`, parameters, null, null, null, customHeaders);
448
- }
449
- getRun(parameters) {
450
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
451
- const threadId = parameters.body.thread_id;
452
- const runId = parameters.body.run_id;
453
-
454
- return this.getFromEndpoint(`/threads/${threadId}/runs/${runId}`, parameters, null, customHeaders);
455
- }
456
- modifyRun(parameters) {
457
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
458
- const threadId = parameters.body.thread_id;
459
- const runId = parameters.body.run_id;
460
-
461
- return this.postToEndpoint(`/threads/${threadId}/runs/${runId}`, parameters, null, null, null, customHeaders);
462
- }
463
- submitToolOuputsToRun(parameters) {
464
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
465
- const threadId = parameters.body.thread_id;
466
- const runId = parameters.body.run_id;
467
-
468
- return this.postToEndpoint(`/threads/${threadId}/runs/${runId}/submit_tool_outputs`, parameters, null, null, null, customHeaders);
469
- }
470
- cancelRun(parameters) {
471
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
472
- const threadId = parameters.body.thread_id;
473
- const runId = parameters.body.run_id;
474
-
475
- return this.postToEndpoint(`/threads/${threadId}/runs/${runId}/cancel`, parameters, null, null, null, customHeaders);
476
- }
477
- listRunSteps(parameters) {
478
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
479
- const threadId = parameters.body.thread_id;
480
- const runId = parameters.body.run_id;
481
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
482
-
483
- return this.getFromEndpoint(`/threads/${threadId}/runs/${runId}/steps`, parameters, null, customHeaders);
484
- }
485
- getRunStep(parameters) {
486
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
487
- const threadId = parameters.body.thread_id;
488
- const runId = parameters.body.run_id;
489
- const stepId = parameters.body.step_id;
490
-
491
- return this.getFromEndpoint(`/threads/${threadId}/runs/${runId}/steps/${stepId}`, parameters, null, customHeaders);
492
- }
493
- listAssistantFiles(parameters) {
494
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
495
- const assistantId = parameters.body.assistant_id;
496
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
497
-
498
- return this.getFromEndpoint(`/assistants/${assistantId}/files`, parameters, expectedQueryParameters, customHeaders);
499
- }
500
- createAssistantFile(parameters) {
501
-
502
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
503
- const assistantId = parameters.body.assistant_id;
504
-
505
- return this.postToEndpoint(`/assistants/${assistantId}/files`, parameters, null, null, null, customHeaders);
506
- }
507
- getAssistantFile(parameters) {
508
-
509
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
510
- const assistantId = parameters.body.assistant_id;
511
- const fileId = parameters.body.file_id;
512
-
513
- return this.getFromEndpoint(`/assistants/${assistantId}/files/${fileId}`, parameters, null, customHeaders);
514
- }
515
- deleteAssistantFile(parameters) {
516
-
517
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
518
- const assistantId = parameters.body.assistant_id;
519
- const fileId = parameters.body.file_id;
520
-
521
- return this.deleteFromEndpoint(`/assistants/${assistantId}/files/${fileId}`, parameters, null, customHeaders);
522
- }
523
- listMessageFiles(parameters) {
120
+ });
524
121
 
525
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
526
- const threadId = parameters.body.thread_id;
527
- const messageId = parameters.body.message_id;
528
- const expectedQueryParameters = ['limit', 'order', 'after', 'before'];
122
+ data = formData;
529
123
 
530
- return this.getFromEndpoint(`/threads/${threadId}/messages/${messageId}/files`, parameters, expectedQueryParameters, customHeaders);
124
+ let formHeaders = formData.getHeaders();
125
+ Object.assign(headers, formHeaders);
126
+ } else {
127
+ // Handle JSON payloads
128
+ headers["Content-Type"] = "application/json";
129
+ data = parameters.body || {};
531
130
  }
532
- getMessageFile(parameters) {
533
- const customHeaders = { 'OpenAI-Beta': 'assistants=v1' };
534
- const threadId = parameters.body.thread_id;
535
- const messageId = parameters.body.message_id;
536
- const fileId = parameters.body.file_id;
537
131
 
538
- return this.getFromEndpoint(`/threads/${threadId}/messages/${messageId}/files/${fileId}`, parameters, null, customHeaders);
539
- }
132
+ // Add expected query parameters to the queryParameters object
133
+ if (expectedQueryParams) {
134
+ expectedQueryParams.forEach((param) => {
135
+ if (parameters.body[param] !== undefined) {
136
+ queryParameters[param] = parameters.body[param];
137
+ }
138
+ });
139
+ }
140
+
141
+ // Merge any additional query parameters from the parameters object
142
+ queryParameters = mergeQueryParams(parameters.body, queryParameters);
143
+
144
+ // Axios request configuration
145
+ const config = {
146
+ method: "POST",
147
+ url: domain + path,
148
+ headers: headers,
149
+ params: queryParameters,
150
+ data: data,
151
+ };
152
+
153
+ // Axios POST request
154
+ axios(config)
155
+ .then((response) => {
156
+ resolve(response);
157
+ })
158
+ .catch((error) => {
159
+ reject(error);
160
+ });
161
+ });
540
162
  }
541
-
542
- function mergeQueryParams(parameters, queryParameters) {
543
- if (parameters.$queryParameters) {
544
- Object.keys(parameters.$queryParameters)
545
- .forEach(function (parameterName) {
546
- var parameter = parameters.$queryParameters[parameterName];
547
- queryParameters[parameterName] = parameter;
548
- });
549
- }
550
- return queryParameters;
163
+ deleteFromEndpoint(path, parameters, expectedQueryParams, customHeaders) {
164
+ return new Promise((resolve, reject) => {
165
+ parameters = parameters || {};
166
+ var domain = this.domain;
167
+ var queryParameters = {},
168
+ baseHeaders = {};
169
+
170
+ baseHeaders = this.setAuthHeaders(headers);
171
+ baseHeaders["Accept"] = "application/json";
172
+
173
+ var headers = {
174
+ ...baseHeaders,
175
+ ...customHeaders,
176
+ };
177
+
178
+ // Only add query parameters if they are expected and exist
179
+ if (expectedQueryParams) {
180
+ expectedQueryParams.forEach((param) => {
181
+ if (parameters[param] !== undefined) {
182
+ queryParameters[param] = parameters.body[param];
183
+ }
184
+ });
185
+ }
186
+
187
+ // Merge any additional query parameters from the parameters object
188
+ queryParameters = mergeQueryParams(parameters, queryParameters);
189
+
190
+ // Axios request configuration
191
+ const config = {
192
+ method: "DELETE",
193
+ url: domain + path,
194
+ headers: headers,
195
+ params: queryParameters,
196
+ };
197
+
198
+ // Axios DELETE request
199
+ axios(config)
200
+ .then((response) => {
201
+ resolve(response);
202
+ })
203
+ .catch((error) => {
204
+ reject(error);
205
+ });
206
+ });
551
207
  }
208
+ createChatCompletion(parameters) {
209
+ const response = this.postToEndpoint("/chat/completions", parameters);
210
+ return response;
211
+ }
212
+ createImage(parameters) {
213
+ return this.postToEndpoint("/images/generations", parameters);
214
+ }
215
+ createImageEdit(parameters) {
216
+ const filename = parameters.body.filename;
217
+ delete parameters.body.filename;
218
+
219
+ return this.postToEndpoint(
220
+ "/images/edits",
221
+ parameters,
222
+ null,
223
+ "form-data",
224
+ filename,
225
+ );
226
+ }
227
+ createImageVariation(parameters) {
228
+ const filename = parameters.body.filename;
229
+ delete parameters.body.filename;
230
+
231
+ return this.postToEndpoint(
232
+ "/images/variations",
233
+ parameters,
234
+ null,
235
+ "form-data",
236
+ filename,
237
+ );
238
+ }
239
+ createEmbedding(parameters) {
240
+ return this.postToEndpoint("/embeddings", parameters);
241
+ }
242
+ createSpeech(parameters) {
243
+ return this.postToEndpoint("/audio/speech", parameters);
244
+ }
245
+ createTranscription(parameters) {
246
+ const filename = parameters.body.filename;
247
+ delete parameters.body.filename;
248
+
249
+ return this.postToEndpoint(
250
+ "/audio/transcriptions",
251
+ parameters,
252
+ null,
253
+ "form-data",
254
+ filename,
255
+ );
256
+ }
257
+ createTranslation(parameters) {
258
+ const filename = parameters.body.filename;
259
+ delete parameters.body.filename;
260
+
261
+ return this.postToEndpoint(
262
+ "/audio/translations",
263
+ parameters,
264
+ null,
265
+ "form-data",
266
+ filename,
267
+ );
268
+ }
269
+ listFiles(parameters) {
270
+ const expectedQueryParameters = ["purpose"];
271
+ return this.getFromEndpoint(
272
+ "/files",
273
+ parameters,
274
+ expectedQueryParameters,
275
+ );
276
+ }
277
+ createFile(parameters) {
278
+ let filename;
279
+
280
+ // reference the incoming filename
281
+ filename = parameters.body.filename;
282
+ delete parameters.body.filename;
283
+
284
+ return this.postToEndpoint(
285
+ "/files",
286
+ parameters,
287
+ null,
288
+ "form-data",
289
+ filename,
290
+ );
291
+ }
292
+ deleteFile(parameters) {
293
+ const file_id = parameters.body.file_id;
294
+ return this.deleteFromEndpoint(`/files/${file_id}`, parameters);
295
+ }
296
+ retrieveFile(parameters) {
297
+ const file_id = parameters.body.file_id;
298
+ return this.getFromEndpoint(`/files/${file_id}`, parameters);
299
+ }
300
+ downloadFile(parameters) {
301
+ const file_id = parameters.body.file_id;
302
+ return this.getFromEndpoint(`/files/${file_id}/content`, parameters);
303
+ }
304
+ createFineTuningJob(parameters) {
305
+ return this.postToEndpoint("/fine_tuning/jobs", parameters);
306
+ }
307
+ listPaginatedFineTuningJobs(parameters) {
308
+ const expectedQueryParameters = ["after", "limit"];
309
+ return this.getFromEndpoint(
310
+ "/fine_tuning/jobs",
311
+ parameters,
312
+ expectedQueryParameters,
313
+ );
314
+ }
315
+ retrieveFineTuningJob(parameters) {
316
+ const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
317
+ return this.getFromEndpoint(
318
+ `/fine_tuning/jobs/${fine_tuning_job_id}`,
319
+ parameters,
320
+ );
321
+ }
322
+ listFineTuningEvents(parameters) {
323
+ const expectedQueryParameters = ["after", "limit"];
324
+ const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
325
+
326
+ return this.getFromEndpoint(
327
+ `/fine_tuning/jobs/${fine_tuning_job_id}/events`,
328
+ parameters,
329
+ expectedQueryParameters,
330
+ );
331
+ }
332
+ cancelFineTuningJob(parameters) {
333
+ const fine_tuning_job_id = parameters.body.fine_tuning_job_id;
334
+ return this.postToEndpoint(
335
+ `/fine_tuning/jobs/${fine_tuning_job_id}/cancel`,
336
+ parameters,
337
+ );
338
+ }
339
+ listModels(parameters) {
340
+ return this.getFromEndpoint("/models", parameters);
341
+ }
342
+ retrieveModel(parameters) {
343
+ const model = parameters.body.model;
552
344
 
345
+ return this.getFromEndpoint(`/models/${model}`, parameters);
346
+ }
347
+ deleteModel(parameters) {
348
+ const model = parameters.body.model;
553
349
 
350
+ return this.deleteFromEndpoint(`/models/${model}`, parameters);
351
+ }
352
+ createModeration(parameters) {
353
+ return this.postToEndpoint("/moderations", parameters);
354
+ }
355
+ listAssistants(parameters) {
356
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
357
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
358
+
359
+ return this.getFromEndpoint(
360
+ "/assistants",
361
+ parameters,
362
+ expectedQueryParameters,
363
+ customHeaders,
364
+ );
365
+ }
366
+ createAssistant(parameters) {
367
+ var customHeaders = { "OpenAI-Beta": "assistants=v1" };
368
+
369
+ return this.postToEndpoint(
370
+ "/assistants",
371
+ parameters,
372
+ null,
373
+ null,
374
+ null,
375
+ customHeaders,
376
+ );
377
+ }
378
+ getAssistant(parameters) {
379
+ const assistantId = parameters.body.assistant_id;
554
380
 
381
+ var customHeaders = { "OpenAI-Beta": "assistants=v1" };
555
382
 
383
+ return this.getFromEndpoint(
384
+ `/assistants/${assistantId}`,
385
+ parameters,
386
+ null,
387
+ customHeaders,
388
+ );
389
+ }
390
+ modifyAssistant(parameters) {
391
+ const assistant_id = parameters.body.assistant_id;
392
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
393
+
394
+ return this.postToEndpoint(
395
+ `/assistants/${assistant_id}`,
396
+ parameters,
397
+ null,
398
+ null,
399
+ null,
400
+ customHeaders,
401
+ );
402
+ }
403
+ deleteAssistant(parameters) {
404
+ const assistant_id = parameters.body.assistant_id;
405
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
406
+
407
+ return this.deleteFromEndpoint(
408
+ `/assistants/${assistant_id}`,
409
+ parameters,
410
+ null,
411
+ customHeaders,
412
+ );
413
+ }
414
+ createThread(parameters) {
415
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
416
+ return this.postToEndpoint(
417
+ "/threads",
418
+ parameters,
419
+ null,
420
+ null,
421
+ null,
422
+ customHeaders,
423
+ );
424
+ }
425
+ getThread(parameters) {
426
+ const threadId = parameters.body.thread_id;
427
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
428
+
429
+ return this.getFromEndpoint(
430
+ `/threads/${threadId}`,
431
+ parameters,
432
+ null,
433
+ customHeaders,
434
+ );
435
+ }
436
+ modifyThread(parameters) {
437
+ const threadId = parameters.body.thread_id;
438
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
439
+
440
+ return this.postToEndpoint(
441
+ `/threads/${threadId}`,
442
+ parameters,
443
+ null,
444
+ null,
445
+ null,
446
+ customHeaders,
447
+ );
448
+ }
449
+ deleteThread(parameters) {
450
+ const threadId = parameters.body.thread_id;
451
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
452
+
453
+ return this.deleteFromEndpoint(
454
+ `/threads/${threadId}`,
455
+ parameters,
456
+ null,
457
+ customHeaders,
458
+ );
459
+ }
460
+ listMessages(parameters) {
461
+ const threadId = parameters.body.thread_id;
462
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
463
+
464
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
465
+
466
+ return this.getFromEndpoint(
467
+ `/threads/${threadId}/messages`,
468
+ parameters,
469
+ expectedQueryParameters,
470
+ customHeaders,
471
+ );
472
+ }
473
+ createMessage(parameters) {
474
+ const threadId = parameters.body.thread_id;
475
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
476
+
477
+ return this.postToEndpoint(
478
+ `/threads/${threadId}/messages`,
479
+ parameters,
480
+ null,
481
+ null,
482
+ null,
483
+ customHeaders,
484
+ );
485
+ }
486
+ getMessage(parameters) {
487
+ const threadId = parameters.body.thread_id;
488
+ const messageId = parameters.body.message_id;
489
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
490
+
491
+ return this.getFromEndpoint(
492
+ `/threads/${threadId}/messages/${messageId}`,
493
+ parameters,
494
+ null,
495
+ customHeaders,
496
+ );
497
+ }
498
+ modifyMessage(parameters) {
499
+ const threadId = parameters.body.thread_id;
500
+ const messageId = parameters.body.message_id;
501
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
502
+
503
+ return this.postToEndpoint(
504
+ `/threads/${threadId}/messages/${messageId}`,
505
+ parameters,
506
+ null,
507
+ null,
508
+ null,
509
+ customHeaders,
510
+ );
511
+ }
512
+ createThreadAndRun(parameters) {
513
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
514
+
515
+ return this.postToEndpoint(
516
+ "/threads/runs",
517
+ parameters,
518
+ null,
519
+ null,
520
+ null,
521
+ customHeaders,
522
+ );
523
+ }
524
+ listRuns(parameters) {
525
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
526
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
527
+ const threadId = parameters.body.thread_id;
528
+
529
+ return this.getFromEndpoint(
530
+ `/threads/${threadId}/runs`,
531
+ parameters,
532
+ expectedQueryParameters,
533
+ customHeaders,
534
+ );
535
+ }
536
+ createRun(parameters) {
537
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
538
+ const threadId = parameters.body.thread_id;
539
+
540
+ return this.postToEndpoint(
541
+ `/threads/${threadId}/runs`,
542
+ parameters,
543
+ null,
544
+ null,
545
+ null,
546
+ customHeaders,
547
+ );
548
+ }
549
+ getRun(parameters) {
550
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
551
+ const threadId = parameters.body.thread_id;
552
+ const runId = parameters.body.run_id;
553
+
554
+ return this.getFromEndpoint(
555
+ `/threads/${threadId}/runs/${runId}`,
556
+ parameters,
557
+ null,
558
+ customHeaders,
559
+ );
560
+ }
561
+ modifyRun(parameters) {
562
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
563
+ const threadId = parameters.body.thread_id;
564
+ const runId = parameters.body.run_id;
565
+
566
+ return this.postToEndpoint(
567
+ `/threads/${threadId}/runs/${runId}`,
568
+ parameters,
569
+ null,
570
+ null,
571
+ null,
572
+ customHeaders,
573
+ );
574
+ }
575
+ submitToolOuputsToRun(parameters) {
576
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
577
+ const threadId = parameters.body.thread_id;
578
+ const runId = parameters.body.run_id;
579
+
580
+ return this.postToEndpoint(
581
+ `/threads/${threadId}/runs/${runId}/submit_tool_outputs`,
582
+ parameters,
583
+ null,
584
+ null,
585
+ null,
586
+ customHeaders,
587
+ );
588
+ }
589
+ cancelRun(parameters) {
590
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
591
+ const threadId = parameters.body.thread_id;
592
+ const runId = parameters.body.run_id;
593
+
594
+ return this.postToEndpoint(
595
+ `/threads/${threadId}/runs/${runId}/cancel`,
596
+ parameters,
597
+ null,
598
+ null,
599
+ null,
600
+ customHeaders,
601
+ );
602
+ }
603
+ listRunSteps(parameters) {
604
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
605
+ const threadId = parameters.body.thread_id;
606
+ const runId = parameters.body.run_id;
607
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
608
+
609
+ return this.getFromEndpoint(
610
+ `/threads/${threadId}/runs/${runId}/steps`,
611
+ parameters,
612
+ expectedQueryParameters,
613
+ customHeaders,
614
+ );
615
+ }
616
+ getRunStep(parameters) {
617
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
618
+ const threadId = parameters.body.thread_id;
619
+ const runId = parameters.body.run_id;
620
+ const stepId = parameters.body.step_id;
621
+
622
+ return this.getFromEndpoint(
623
+ `/threads/${threadId}/runs/${runId}/steps/${stepId}`,
624
+ parameters,
625
+ null,
626
+ customHeaders,
627
+ );
628
+ }
629
+ listAssistantFiles(parameters) {
630
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
631
+ const assistantId = parameters.body.assistant_id;
632
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
633
+
634
+ return this.getFromEndpoint(
635
+ `/assistants/${assistantId}/files`,
636
+ parameters,
637
+ expectedQueryParameters,
638
+ customHeaders,
639
+ );
640
+ }
641
+ createAssistantFile(parameters) {
642
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
643
+ const assistantId = parameters.body.assistant_id;
644
+
645
+ return this.postToEndpoint(
646
+ `/assistants/${assistantId}/files`,
647
+ parameters,
648
+ null,
649
+ null,
650
+ null,
651
+ customHeaders,
652
+ );
653
+ }
654
+ getAssistantFile(parameters) {
655
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
656
+ const assistantId = parameters.body.assistant_id;
657
+ const fileId = parameters.body.file_id;
658
+
659
+ return this.getFromEndpoint(
660
+ `/assistants/${assistantId}/files/${fileId}`,
661
+ parameters,
662
+ null,
663
+ customHeaders,
664
+ );
665
+ }
666
+ deleteAssistantFile(parameters) {
667
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
668
+ const assistantId = parameters.body.assistant_id;
669
+ const fileId = parameters.body.file_id;
670
+
671
+ return this.deleteFromEndpoint(
672
+ `/assistants/${assistantId}/files/${fileId}`,
673
+ parameters,
674
+ null,
675
+ customHeaders,
676
+ );
677
+ }
678
+ listMessageFiles(parameters) {
679
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
680
+ const threadId = parameters.body.thread_id;
681
+ const messageId = parameters.body.message_id;
682
+ const expectedQueryParameters = ["limit", "order", "after", "before"];
683
+
684
+ return this.getFromEndpoint(
685
+ `/threads/${threadId}/messages/${messageId}/files`,
686
+ parameters,
687
+ expectedQueryParameters,
688
+ customHeaders,
689
+ );
690
+ }
691
+ getMessageFile(parameters) {
692
+ const customHeaders = { "OpenAI-Beta": "assistants=v1" };
693
+ const threadId = parameters.body.thread_id;
694
+ const messageId = parameters.body.message_id;
695
+ const fileId = parameters.body.file_id;
696
+
697
+ return this.getFromEndpoint(
698
+ `/threads/${threadId}/messages/${messageId}/files/${fileId}`,
699
+ parameters,
700
+ null,
701
+ customHeaders,
702
+ );
703
+ }
704
+ }
705
+
706
+ function mergeQueryParams(parameters, queryParameters) {
707
+ if (parameters.$queryParameters) {
708
+ Object.keys(parameters.$queryParameters).forEach(
709
+ function (parameterName) {
710
+ var parameter = parameters.$queryParameters[parameterName];
711
+ queryParameters[parameterName] = parameter;
712
+ },
713
+ );
714
+ }
715
+ return queryParameters;
716
+ }
556
717
 
557
-
558
-
559
-
560
-
561
-
562
-
563
-
564
-
565
-
566
-
567
-
568
-
569
-
570
-
571
-
572
-
573
-
574
-
575
-
576
-
577
-
578
-
579
-
580
-
581
-
582
-
583
-
584
-
585
-
586
-
587
-
588
-
589
-
590
-
591
-
592
-
593
-
594
-
595
-
596
-
597
-
598
-
599
-
600
-
601
-
602
-
603
-
604
-
605
-
606
-
607
-
608
-
609
-
610
-
611
- return OpenaiApi;
718
+ return OpenaiApi;
612
719
  })();
613
720
 
614
721
  exports.OpenaiApi = OpenaiApi;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inductiv/node-red-openai-api",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Node-RED node for interfacing with OpenAI platform services",
5
5
  "main": "node.js",
6
6
  "engines": {
@@ -18,6 +18,7 @@
18
18
  "automation",
19
19
  "chatgpt",
20
20
  "llm",
21
+ "slm",
21
22
  "agent",
22
23
  "automation",
23
24
  "node-red",