@inductiv/node-red-openai-api 0.2.0 → 0.3.0
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 +13 -0
- package/.prettierrc +4 -0
- package/README.md +33 -0
- package/lib.js +474 -476
- package/locales/de-DE/node.json +4 -3
- package/locales/en-US/node.json +4 -3
- package/locales/ja/node.json +4 -3
- package/locales/zh-CN/node.json +4 -3
- package/node.html +11 -8
- package/node.js +79 -228
- package/package.json +6 -2
package/locales/de-DE/node.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"OpenaiApi": {
|
|
3
3
|
"label": {
|
|
4
|
-
"
|
|
4
|
+
"apiBase": "API Base",
|
|
5
|
+
"serviceHost": "Service Host",
|
|
5
6
|
"method": "Method",
|
|
6
7
|
"host": "Host",
|
|
7
|
-
"header": "Header",
|
|
8
|
-
"
|
|
8
|
+
"header": "Auth Header",
|
|
9
|
+
"apiKey": "API Key",
|
|
9
10
|
"isQuery": "isQuery"
|
|
10
11
|
},
|
|
11
12
|
"status": {
|
package/locales/en-US/node.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"OpenaiApi": {
|
|
3
3
|
"label": {
|
|
4
|
-
"
|
|
4
|
+
"apiBase": "API Base",
|
|
5
|
+
"serviceHost": "Service Host",
|
|
5
6
|
"method": "Method",
|
|
6
7
|
"host": "Host",
|
|
7
|
-
"header": "Header",
|
|
8
|
-
"
|
|
8
|
+
"header": "Auth Header",
|
|
9
|
+
"apiKey": "API Key",
|
|
9
10
|
"isQuery": "isQuery"
|
|
10
11
|
},
|
|
11
12
|
"status": {
|
package/locales/ja/node.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"OpenaiApi": {
|
|
3
3
|
"label": {
|
|
4
|
-
"
|
|
4
|
+
"apiBase": "API Base",
|
|
5
|
+
"serviceHost": "Service Host",
|
|
5
6
|
"method": "Method",
|
|
6
7
|
"host": "Host",
|
|
7
|
-
"header": "Header",
|
|
8
|
-
"
|
|
8
|
+
"header": "Auth Header",
|
|
9
|
+
"apiKey": "API Key",
|
|
9
10
|
"isQuery": "isQuery"
|
|
10
11
|
},
|
|
11
12
|
"status": {
|
package/locales/zh-CN/node.json
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"OpenaiApi": {
|
|
3
3
|
"label": {
|
|
4
|
-
"
|
|
4
|
+
"apiBase": "API Base",
|
|
5
|
+
"serviceHost": "Service Host",
|
|
5
6
|
"method": "Method",
|
|
6
7
|
"host": "Host",
|
|
7
|
-
"header": "Header",
|
|
8
|
-
"
|
|
8
|
+
"header": "Auth Header",
|
|
9
|
+
"apiKey": "API Key",
|
|
9
10
|
"isQuery": "isQuery"
|
|
10
11
|
},
|
|
11
12
|
"status": {
|
package/node.html
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
color: '#B8B1FB',
|
|
5
5
|
defaults: {
|
|
6
6
|
name: { value: "" },
|
|
7
|
-
service: { value: "", type: "
|
|
7
|
+
service: { value: "", type: "Service Host", required: true },
|
|
8
8
|
method: { value: "", required: true }
|
|
9
9
|
},
|
|
10
10
|
inputs: 1,
|
|
@@ -35,7 +35,7 @@
|
|
|
35
35
|
<hr/>
|
|
36
36
|
|
|
37
37
|
<div class="form-row">
|
|
38
|
-
<label for="node-input-service"><i class="fa fa-cloud"></i> <span data-i18n="OpenaiApi.label.
|
|
38
|
+
<label for="node-input-service"><i class="fa fa-cloud"></i> <span data-i18n="OpenaiApi.label.serviceHost"></span></label>
|
|
39
39
|
<input type="text" id="node-input-service">
|
|
40
40
|
</div>
|
|
41
41
|
|
|
@@ -710,13 +710,12 @@
|
|
|
710
710
|
</script>
|
|
711
711
|
|
|
712
712
|
<script type="text/javascript">
|
|
713
|
-
RED.nodes.registerType('
|
|
713
|
+
RED.nodes.registerType('Service Host', {
|
|
714
714
|
category: 'config',
|
|
715
715
|
defaults: {
|
|
716
|
-
|
|
716
|
+
apiBase: { value: "https://api.openai.com/v1", required: true },
|
|
717
717
|
secureApiKeyHeaderOrQueryName: { value: "Authorization" },
|
|
718
718
|
secureApiKeyIsQuery: { value: false },
|
|
719
|
-
|
|
720
719
|
name: { value: "" },
|
|
721
720
|
},
|
|
722
721
|
credentials: {
|
|
@@ -740,14 +739,18 @@
|
|
|
740
739
|
});
|
|
741
740
|
</script>
|
|
742
741
|
|
|
743
|
-
<script type="text/html" data-template-name="
|
|
742
|
+
<script type="text/html" data-template-name="Service Host">
|
|
744
743
|
|
|
744
|
+
<div class="form-row">
|
|
745
|
+
<label id="node-config-input-apiBase-label" for="node-config-input-apiBase"><i class="fa fa-list"></i> <span data-i18n="OpenaiApi.label.apiBase"></span></label>
|
|
746
|
+
<input type="text" id="node-config-input-apiBase" placeholder="https://api.openai.com/v1">
|
|
747
|
+
</div>
|
|
745
748
|
<div class="form-row">
|
|
746
749
|
<label id="node-config-input-secureApiKeyHeaderOrQueryName-label" for="node-config-input-secureApiKeyHeaderOrQueryName"><i class="fa fa-list"></i> <span data-i18n="OpenaiApi.label.header"></span></label>
|
|
747
750
|
<input type="text" id="node-config-input-secureApiKeyHeaderOrQueryName" placeholder="">
|
|
748
751
|
</div>
|
|
749
752
|
<div class="form-row">
|
|
750
|
-
<label id="node-config-input-secureApiKeyValue-label" for="node-config-input-secureApiKeyValue"><i class="fa fa-lock"></i> <span data-i18n="OpenaiApi.label.
|
|
753
|
+
<label id="node-config-input-secureApiKeyValue-label" for="node-config-input-secureApiKeyValue"><i class="fa fa-lock"></i> <span data-i18n="OpenaiApi.label.apiKey"></span></label>
|
|
751
754
|
<input type="password" id="node-config-input-secureApiKeyValue" placeholder="">
|
|
752
755
|
</div>
|
|
753
756
|
<div class="form-row">
|
|
@@ -764,7 +767,7 @@
|
|
|
764
767
|
</div>
|
|
765
768
|
</script>
|
|
766
769
|
|
|
767
|
-
<script type="text/html" data-help-name="
|
|
770
|
+
<script type="text/html" data-help-name="Service Host">
|
|
768
771
|
|
|
769
772
|
<p><b>Header</b>: Variable name to set API key</p>
|
|
770
773
|
<p><b>Value</b>: Value of API key</p>
|
package/node.js
CHANGED
|
@@ -1,253 +1,104 @@
|
|
|
1
1
|
'use strict';
|
|
2
|
-
const
|
|
3
|
-
var lib = require('./lib.js');
|
|
2
|
+
const lib = require('./lib.js');
|
|
4
3
|
|
|
5
4
|
module.exports = function (RED) {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
5
|
+
class OpenaiApiNode {
|
|
6
|
+
constructor(config) {
|
|
7
|
+
RED.nodes.createNode(this, config);
|
|
8
|
+
this.service = RED.nodes.getNode(config.service);
|
|
9
|
+
this.method = config.method;
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
createChatCompletion: {
|
|
13
|
-
body: 'msg',
|
|
14
|
-
},
|
|
15
|
-
createImage: {
|
|
16
|
-
body: 'msg'
|
|
17
|
-
},
|
|
18
|
-
createImageEdit: {
|
|
19
|
-
body: 'msg'
|
|
20
|
-
},
|
|
21
|
-
createImageVariation: {
|
|
22
|
-
body: 'msg'
|
|
23
|
-
},
|
|
24
|
-
createEmbedding: {
|
|
25
|
-
body: 'msg'
|
|
26
|
-
},
|
|
27
|
-
createSpeech: {
|
|
28
|
-
body: 'msg'
|
|
29
|
-
},
|
|
30
|
-
createTranscription: {
|
|
31
|
-
body: 'msg'
|
|
32
|
-
},
|
|
33
|
-
createTranslation: {
|
|
34
|
-
body: 'msg'
|
|
35
|
-
},
|
|
36
|
-
listFiles: {
|
|
37
|
-
body: 'msg'
|
|
38
|
-
},
|
|
39
|
-
createFile: {
|
|
40
|
-
body: 'msg'
|
|
41
|
-
},
|
|
42
|
-
deleteFile: {
|
|
43
|
-
body: 'msg'
|
|
44
|
-
},
|
|
45
|
-
retrieveFile: {
|
|
46
|
-
body: 'msg'
|
|
47
|
-
},
|
|
48
|
-
downloadFile: {
|
|
49
|
-
body: 'msg'
|
|
50
|
-
},
|
|
51
|
-
createFineTuningJob: {
|
|
52
|
-
body: 'msg'
|
|
53
|
-
},
|
|
54
|
-
listPaginatedFineTuningJobs: {
|
|
55
|
-
body: 'msg'
|
|
56
|
-
},
|
|
57
|
-
retrieveFineTuningJob: {
|
|
58
|
-
body: 'msg'
|
|
59
|
-
},
|
|
60
|
-
listFineTuningEvents: {
|
|
61
|
-
body: 'msg'
|
|
62
|
-
},
|
|
63
|
-
cancelFineTuningJob: {
|
|
64
|
-
body: 'msg'
|
|
65
|
-
},
|
|
66
|
-
retrieveModel: {
|
|
67
|
-
body: 'msg'
|
|
68
|
-
},
|
|
69
|
-
deleteModel: {
|
|
70
|
-
body: 'msg'
|
|
71
|
-
},
|
|
72
|
-
createModeration: {
|
|
73
|
-
body: 'msg'
|
|
74
|
-
},
|
|
75
|
-
listAssistants: {
|
|
76
|
-
body: 'msg'
|
|
77
|
-
},
|
|
78
|
-
createAssistant: {
|
|
79
|
-
body: 'msg'
|
|
80
|
-
},
|
|
81
|
-
getAssistant: {
|
|
82
|
-
body: 'msg'
|
|
83
|
-
},
|
|
84
|
-
modifyAssistant: {
|
|
85
|
-
body: 'msg'
|
|
86
|
-
},
|
|
87
|
-
deleteAssistant: {
|
|
88
|
-
body: 'msg'
|
|
89
|
-
},
|
|
90
|
-
createThread: {
|
|
91
|
-
body: 'msg'
|
|
92
|
-
},
|
|
93
|
-
getThread: {
|
|
94
|
-
body: 'msg'
|
|
95
|
-
},
|
|
96
|
-
modifyThread: {
|
|
97
|
-
body: 'msg'
|
|
98
|
-
},
|
|
99
|
-
deleteThread: {
|
|
100
|
-
body: 'msg'
|
|
101
|
-
},
|
|
102
|
-
listMessages: {
|
|
103
|
-
body: 'msg'
|
|
104
|
-
},
|
|
105
|
-
createMessage: {
|
|
106
|
-
body: 'msg'
|
|
107
|
-
},
|
|
108
|
-
getMessage: {
|
|
109
|
-
body: 'msg'
|
|
110
|
-
},
|
|
111
|
-
modifyMessage: {
|
|
112
|
-
body: 'msg'
|
|
113
|
-
},
|
|
114
|
-
createThreadAndRun: {
|
|
115
|
-
body: 'msg'
|
|
116
|
-
},
|
|
117
|
-
listRuns: {
|
|
118
|
-
body: 'msg'
|
|
119
|
-
},
|
|
120
|
-
createRun: {
|
|
121
|
-
body: 'msg'
|
|
122
|
-
},
|
|
123
|
-
getRun: {
|
|
124
|
-
body: 'msg'
|
|
125
|
-
},
|
|
126
|
-
modifyRun: {
|
|
127
|
-
body: 'msg'
|
|
128
|
-
},
|
|
129
|
-
submitToolOuputsToRun: {
|
|
130
|
-
body: 'msg'
|
|
131
|
-
},
|
|
132
|
-
cancelRun: {
|
|
133
|
-
body: 'msg'
|
|
134
|
-
},
|
|
135
|
-
listRunSteps: {
|
|
136
|
-
body: 'msg'
|
|
137
|
-
},
|
|
138
|
-
getRunStep: {
|
|
139
|
-
body: 'msg'
|
|
140
|
-
},
|
|
141
|
-
listAssistantFiles: {
|
|
142
|
-
body: 'msg'
|
|
143
|
-
},
|
|
144
|
-
createAssistantFile: {
|
|
145
|
-
body: 'msg'
|
|
146
|
-
},
|
|
147
|
-
getAssistantFile: {
|
|
148
|
-
body: 'msg'
|
|
149
|
-
},
|
|
150
|
-
deleteAssistantFile: {
|
|
151
|
-
body: 'msg'
|
|
152
|
-
},
|
|
153
|
-
listMessageFiles: {
|
|
154
|
-
body: 'msg'
|
|
155
|
-
},
|
|
156
|
-
getMessageFile: {
|
|
157
|
-
body: 'msg'
|
|
158
|
-
}
|
|
159
|
-
};
|
|
11
|
+
let node = this;
|
|
160
12
|
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
this
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
var node = this;
|
|
13
|
+
node.on('input', function (msg) {
|
|
14
|
+
let errorFlag = false;
|
|
15
|
+
let client = new lib.OpenaiApi();
|
|
16
|
+
if (!errorFlag && this.service) {
|
|
17
|
+
client.setApiBase(this.service.apiBase);
|
|
18
|
+
}
|
|
169
19
|
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
client.setApiKey(this.service.credentials.secureApiKeyValue,
|
|
179
|
-
this.service.secureApiKeyHeaderOrQueryName, false);
|
|
20
|
+
if (!errorFlag && this.service && this.service.credentials && this.service.credentials.secureApiKeyValue) {
|
|
21
|
+
if (this.service.secureApiKeyIsQuery) {
|
|
22
|
+
client.setApiKey(this.service.credentials.secureApiKeyValue,
|
|
23
|
+
this.service.secureApiKeyHeaderOrQueryName, true);
|
|
24
|
+
} else {
|
|
25
|
+
client.setApiKey(this.service.credentials.secureApiKeyValue,
|
|
26
|
+
this.service.secureApiKeyHeaderOrQueryName, false);
|
|
27
|
+
}
|
|
180
28
|
}
|
|
181
|
-
}
|
|
182
29
|
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
30
|
+
if (!errorFlag) {
|
|
31
|
+
client.body = msg.payload;
|
|
32
|
+
}
|
|
186
33
|
|
|
187
|
-
|
|
34
|
+
let result;
|
|
188
35
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
36
|
+
if (!errorFlag) {
|
|
37
|
+
const serviceName = node.method; // Specify the service you want to process
|
|
38
|
+
let serviceParametersObject = {};
|
|
192
39
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
40
|
+
// Dynamically call the function based on the service name
|
|
41
|
+
const functionName = `${serviceName}`;
|
|
42
|
+
if (typeof client[functionName] === 'function') {
|
|
43
|
+
serviceParametersObject.body = msg.payload || {};
|
|
44
|
+
result = client[functionName](serviceParametersObject);
|
|
45
|
+
} else {
|
|
46
|
+
console.error(`Function ${functionName} does not exist on client.`);
|
|
47
|
+
}
|
|
200
48
|
}
|
|
201
|
-
}
|
|
202
49
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
50
|
+
if (!errorFlag && result === undefined) {
|
|
51
|
+
node.error('Method is not specified.', msg);
|
|
52
|
+
errorFlag = true;
|
|
53
|
+
}
|
|
207
54
|
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
55
|
+
let setData = function (msg, response) {
|
|
56
|
+
if (response) {
|
|
57
|
+
if (response.status) {
|
|
58
|
+
msg.statusCode = response.status;
|
|
59
|
+
}
|
|
60
|
+
if (response.headers) {
|
|
61
|
+
msg.headers = response.headers;
|
|
62
|
+
}
|
|
63
|
+
if (response.config && response.config.url) {
|
|
64
|
+
msg.responseUrl = response.config.url;
|
|
65
|
+
}
|
|
66
|
+
if (response.data) {
|
|
67
|
+
msg.payload = response.data;
|
|
68
|
+
}
|
|
215
69
|
}
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
if (response.data) {
|
|
220
|
-
msg.payload = response.data;
|
|
221
|
-
}
|
|
222
|
-
}
|
|
223
|
-
return msg;
|
|
224
|
-
};
|
|
70
|
+
return msg;
|
|
71
|
+
};
|
|
225
72
|
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
73
|
+
if (!errorFlag) {
|
|
74
|
+
node.status({ fill: 'blue', shape: 'dot', text: 'OpenaiApi.status.requesting' });
|
|
75
|
+
result.then(function (response) {
|
|
76
|
+
node.send(setData(msg, response));
|
|
77
|
+
node.status({});
|
|
78
|
+
}).catch(function (error) {
|
|
79
|
+
let message = error.message;
|
|
80
|
+
let errorData = error.response || {}; // Fallback to an empty object if response is not available
|
|
81
|
+
node.error(message, setData(msg, errorData));
|
|
82
|
+
node.status({ fill: 'red', shape: 'ring', text: 'node-red:common.status.error' });
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
});
|
|
86
|
+
}
|
|
239
87
|
}
|
|
240
88
|
|
|
241
89
|
RED.nodes.registerType('OpenAI API', OpenaiApiNode);
|
|
242
|
-
|
|
243
|
-
|
|
90
|
+
class ServiceHostNode {
|
|
91
|
+
constructor(n) {
|
|
92
|
+
RED.nodes.createNode(this, n);
|
|
244
93
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
94
|
+
this.secureApiKeyValue = n.secureApiKeyValue;
|
|
95
|
+
this.apiBase = n.apiBase;
|
|
96
|
+
this.secureApiKeyHeaderOrQueryName = n.secureApiKeyHeaderOrQueryName;
|
|
97
|
+
this.secureApiKeyIsQuery = n.secureApiKeyIsQuery;
|
|
98
|
+
}
|
|
248
99
|
}
|
|
249
100
|
|
|
250
|
-
RED.nodes.registerType('
|
|
101
|
+
RED.nodes.registerType('Service Host', ServiceHostNode, {
|
|
251
102
|
credentials: {
|
|
252
103
|
secureApiKeyValue: { type: 'password' },
|
|
253
104
|
temp: { type: 'text' }
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@inductiv/node-red-openai-api",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"description": "Node-RED node for interfacing with OpenAI platform services",
|
|
5
5
|
"main": "node.js",
|
|
6
6
|
"engines": {
|
|
@@ -29,10 +29,14 @@
|
|
|
29
29
|
"axios": "^1.6.0",
|
|
30
30
|
"form-data": "^4.0.0"
|
|
31
31
|
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"eslint": "^8.54.0",
|
|
34
|
+
"prettier": "^3.1.0"
|
|
35
|
+
},
|
|
32
36
|
"author": "Allan Bunch",
|
|
33
37
|
"license": "MIT",
|
|
34
38
|
"repository": {
|
|
35
39
|
"type": "git",
|
|
36
40
|
"url": "git+https://github.com/allanbunch/node-red-openai-api.git"
|
|
37
41
|
}
|
|
38
|
-
}
|
|
42
|
+
}
|