@inductiv/node-red-openai-api 1.103.0-patch.1 → 6.22.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.
Files changed (57) hide show
  1. package/README.md +165 -100
  2. package/examples/responses/mcp.json +1 -1
  3. package/lib.js +6917 -13226
  4. package/locales/en-US/node.json +48 -1
  5. package/node.html +1513 -962
  6. package/node.js +194 -54
  7. package/package.json +8 -7
  8. package/src/assistants/help.html +1 -77
  9. package/src/audio/help.html +1 -37
  10. package/src/batch/help.html +3 -17
  11. package/src/chat/help.html +11 -89
  12. package/src/container-files/help.html +1 -27
  13. package/src/containers/help.html +8 -18
  14. package/src/conversations/help.html +135 -0
  15. package/src/conversations/methods.js +73 -0
  16. package/src/conversations/template.html +10 -0
  17. package/src/embeddings/help.html +1 -11
  18. package/src/evals/help.html +249 -0
  19. package/src/evals/methods.js +114 -0
  20. package/src/evals/template.html +14 -0
  21. package/src/files/help.html +4 -17
  22. package/src/fine-tuning/help.html +1 -35
  23. package/src/images/help.html +1 -45
  24. package/src/lib.js +51 -1
  25. package/src/messages/help.html +1 -41
  26. package/src/models/help.html +1 -5
  27. package/src/moderations/help.html +1 -5
  28. package/src/node.html +126 -37
  29. package/src/realtime/help.html +129 -0
  30. package/src/realtime/methods.js +45 -0
  31. package/src/realtime/template.html +7 -0
  32. package/src/responses/help.html +203 -61
  33. package/src/responses/methods.js +49 -16
  34. package/src/responses/template.html +16 -1
  35. package/src/runs/help.html +1 -123
  36. package/src/skills/help.html +183 -0
  37. package/src/skills/methods.js +99 -0
  38. package/src/skills/template.html +13 -0
  39. package/src/threads/help.html +1 -15
  40. package/src/uploads/help.html +1 -21
  41. package/src/vector-store-file-batches/help.html +1 -27
  42. package/src/vector-store-file-batches/methods.js +1 -1
  43. package/src/vector-store-files/help.html +1 -25
  44. package/src/vector-store-files/methods.js +5 -2
  45. package/src/vector-stores/help.html +2 -31
  46. package/src/videos/help.html +113 -0
  47. package/src/videos/methods.js +50 -0
  48. package/src/videos/template.html +8 -0
  49. package/src/webhooks/help.html +61 -0
  50. package/src/webhooks/methods.js +40 -0
  51. package/src/webhooks/template.html +4 -0
  52. package/test/openai-methods-mapping.test.js +1220 -0
  53. package/test/openai-node-auth-routing.test.js +203 -0
  54. package/test/service-host-editor-template.test.js +53 -0
  55. package/test/service-host-node.test.js +182 -0
  56. package/test/services.test.js +147 -0
  57. package/test/utils.test.js +75 -0
package/src/node.html CHANGED
@@ -84,17 +84,23 @@
84
84
  @@include('./chat/template.html')
85
85
  @@include('./container-files/template.html')
86
86
  @@include('./containers/template.html')
87
+ @@include('./conversations/template.html')
87
88
  @@include('./embeddings/template.html')
89
+ @@include('./evals/template.html')
88
90
  @@include('./files/template.html')
89
91
  @@include('./fine-tuning/template.html')
90
92
  @@include('./images/template.html')
91
93
  @@include('./messages/template.html')
92
94
  @@include('./models/template.html')
93
95
  @@include('./moderations/template.html')
96
+ @@include('./realtime/template.html')
94
97
  @@include('./responses/template.html')
95
98
  @@include('./runs/template.html')
99
+ @@include('./skills/template.html')
96
100
  @@include('./threads/template.html')
97
101
  @@include('./uploads/template.html')
102
+ @@include('./videos/template.html')
103
+ @@include('./webhooks/template.html')
98
104
  @@include('./vector-stores/template.html')
99
105
  @@include('./vector-store-files/template.html')
100
106
  @@include('./vector-store-file-batches/template.html')
@@ -105,7 +111,7 @@
105
111
  <script type="text/html" data-help-name="OpenAI API">
106
112
  <p>
107
113
  OpenAI Platform Services API. Please see the
108
- <a href="https://platform.openai.com/docs/api-reference" target="_blank"
114
+ <a href="https://developers.openai.com/api/reference" target="_blank"
109
115
  >OpenAI API Reference</a
110
116
  >
111
117
  for more details.
@@ -118,17 +124,23 @@
118
124
  @@include('./chat/help.html')
119
125
  @@include('./container-files/help.html')
120
126
  @@include('./containers/help.html')
127
+ @@include('./conversations/help.html')
121
128
  @@include('./embeddings/help.html')
129
+ @@include('./evals/help.html')
122
130
  @@include('./files/help.html')
123
131
  @@include('./fine-tuning/help.html')
124
132
  @@include('./images/help.html')
125
133
  @@include('./messages/help.html')
126
134
  @@include('./models/help.html')
127
135
  @@include('./moderations/help.html')
136
+ @@include('./realtime/help.html')
128
137
  @@include('./responses/help.html')
129
138
  @@include('./runs/help.html')
139
+ @@include('./skills/help.html')
130
140
  @@include('./threads/help.html')
131
141
  @@include('./uploads/help.html')
142
+ @@include('./videos/help.html')
143
+ @@include('./webhooks/help.html')
132
144
  @@include('./vector-stores/help.html')
133
145
  @@include('./vector-store-files/help.html')
134
146
  @@include('./vector-store-file-batches/help.html')
@@ -139,9 +151,14 @@
139
151
  category: "config",
140
152
  defaults: {
141
153
  apiBase: { value: "https://api.openai.com/v1", required: true },
154
+ apiBaseType: { value: "str" },
142
155
  secureApiKeyHeaderOrQueryName: { value: "Authorization" },
156
+ secureApiKeyHeaderOrQueryNameType: { value: "str" },
143
157
  organizationId: { value: "" },
158
+ organizationIdType: { value: "str" },
144
159
  secureApiKeyIsQuery: { value: false },
160
+ secureApiKeyValueType: { value: "cred" },
161
+ secureApiKeyValueRef: { value: "" },
145
162
  name: { value: "" },
146
163
  },
147
164
  credentials: {
@@ -162,61 +179,132 @@
162
179
  );
163
180
  if (!selected.val()) {
164
181
  $("#node-config-input-secureApiKeyIsQuery").val(false);
182
+ }
183
+
184
+ const apiKeyInput = $("#node-config-input-secureApiKeyValue");
185
+ const apiKeyType = $("#node-config-input-secureApiKeyValueType");
186
+ const apiKeyRef = $("#node-config-input-secureApiKeyValueRef");
187
+
188
+ // Preserve existing credential value before initializing typedInput
189
+ const existingCredValue = apiKeyInput.val();
190
+
191
+ apiKeyInput.typedInput({
192
+ default: "cred",
193
+ types: ["cred", "env", "msg", "flow", "global"],
194
+ typeField: "#node-config-input-secureApiKeyValueType",
195
+ });
196
+
197
+ // Restore credential value if it was populated by Node-RED
198
+ if (apiKeyType.val() === "cred" && existingCredValue) {
199
+ apiKeyInput.typedInput("value", existingCredValue);
200
+ }
201
+
202
+ let previousApiKeyType = apiKeyInput.typedInput("type");
203
+ const syncApiKeyInputValue = function () {
204
+ const selectedType = apiKeyInput.typedInput("type");
205
+ const currentValue = apiKeyInput.typedInput("value");
206
+
207
+ if (selectedType !== "cred" && currentValue === "__PWRD__") {
208
+ apiKeyInput.typedInput("value", apiKeyRef.val() || "");
209
+ }
210
+
211
+ // Prevent moving a non-credential reference value into credentials.
212
+ if (selectedType === "cred" && previousApiKeyType !== "cred") {
213
+ if (currentValue === apiKeyRef.val()) {
214
+ apiKeyInput.typedInput("value", "");
215
+ }
216
+ }
217
+
218
+ previousApiKeyType = selectedType;
165
219
  };
220
+
221
+ if (apiKeyType.val() === "str") {
222
+ apiKeyInput.typedInput("type", "cred");
223
+ apiKeyType.val("cred");
224
+ }
225
+
226
+ if (apiKeyType.val() !== "cred" && apiKeyRef.val()) {
227
+ apiKeyInput.typedInput("value", apiKeyRef.val());
228
+ }
229
+ syncApiKeyInputValue();
230
+ apiKeyInput.on("change", function () {
231
+ syncApiKeyInputValue();
232
+ });
233
+
234
+ [
235
+ { input: "#node-config-input-apiBase", type: "#node-config-input-apiBaseType" },
236
+ { input: "#node-config-input-secureApiKeyHeaderOrQueryName", type: "#node-config-input-secureApiKeyHeaderOrQueryNameType" },
237
+ { input: "#node-config-input-organizationId", type: "#node-config-input-organizationIdType" }
238
+ ].forEach(function (field) {
239
+ $(field.input).typedInput({
240
+ default: "str",
241
+ types: ["str", "env", "msg", "flow", "global"],
242
+ typeField: field.type,
243
+ });
244
+ });
245
+ },
246
+ oneditsave: function () {
247
+ const apiKeyInput = $("#node-config-input-secureApiKeyValue");
248
+ const apiKeyType = $("#node-config-input-secureApiKeyValueType");
249
+ const apiKeyRef = $("#node-config-input-secureApiKeyValueRef");
250
+ const selectedType = apiKeyInput.typedInput("type");
251
+
252
+ apiKeyType.val(selectedType);
253
+
254
+ if (selectedType !== "cred") {
255
+ const inputValue = apiKeyInput.typedInput("value");
256
+ if (inputValue && inputValue !== "__PWRD__") {
257
+ apiKeyRef.val(inputValue);
258
+ apiKeyInput.typedInput("value", "");
259
+ }
260
+ } else {
261
+ apiKeyRef.val("");
262
+ }
166
263
  },
167
264
  });
168
265
  </script>
169
266
 
170
267
  <script type="text/html" data-template-name="Service Host">
171
268
  <div class="form-row">
172
- <label id="node-config-input-apiBase-label" for="node-config-input-apiBase"
173
- ><i class="fa fa-list"></i>
174
- <span data-i18n="OpenaiApi.label.apiBase"></span
175
- ></label>
269
+ <label id="node-config-input-apiBase-label" for="node-config-input-apiBase">
270
+ <i class="fa fa-list"></i>
271
+ <span data-i18n="OpenaiApi.label.apiBase"></span>
272
+ </label>
176
273
  <input
177
274
  type="text"
178
275
  id="node-config-input-apiBase"
179
276
  placeholder="https://api.openai.com/v1"
180
277
  />
278
+ <input type="hidden" id="node-config-input-apiBaseType" />
181
279
  </div>
182
280
  <div class="form-row">
183
- <label
184
- id="node-config-input-secureApiKeyHeaderOrQueryName-label"
185
- for="node-config-input-secureApiKeyHeaderOrQueryName"
186
- ><i class="fa fa-list"></i>
187
- <span data-i18n="OpenaiApi.label.header"></span
188
- ></label>
281
+ <label id="node-config-input-secureApiKeyHeaderOrQueryName-label" for="node-config-input-secureApiKeyHeaderOrQueryName">
282
+ <i class="fa fa-list"></i>
283
+ <span data-i18n="OpenaiApi.label.header"></span>
284
+ </label>
189
285
  <input
190
286
  type="text"
191
287
  id="node-config-input-secureApiKeyHeaderOrQueryName"
192
- placeholder=""
288
+ placeholder="Authorization"
193
289
  />
290
+ <input type="hidden" id="node-config-input-secureApiKeyHeaderOrQueryNameType" />
194
291
  </div>
195
292
  <div class="form-row">
196
- <label
197
- id="node-config-input-secureApiKeyValue-label"
198
- for="node-config-input-secureApiKeyValue"
199
- ><i class="fa fa-lock"></i>
200
- <span data-i18n="OpenaiApi.label.apiKey"></span
201
- ></label>
202
- <input
203
- type="password"
204
- id="node-config-input-secureApiKeyValue"
205
- placeholder=""
206
- />
293
+ <label id="node-config-input-secureApiKeyValue-label" for="node-config-input-secureApiKeyValue">
294
+ <i class="fa fa-lock"></i>
295
+ <span data-i18n="OpenaiApi.label.apiKey"></span>
296
+ </label>
297
+ <input type="text" id="node-config-input-secureApiKeyValue" placeholder="" />
298
+ <input type="hidden" id="node-config-input-secureApiKeyValueType" />
299
+ <input type="hidden" id="node-config-input-secureApiKeyValueRef" />
207
300
  </div>
208
301
  <div class="form-row">
209
- <label
210
- id="node-config-input-organizationId-label"
211
- for="node-config-input-organizationId"
212
- ><i class="fa fa-list"></i>
213
- <span data-i18n="OpenaiApi.label.organizationId"></span
214
- ></label>
215
- <input
216
- type="text"
217
- id="node-config-input-organizationId"
218
- placeholder="OpenAI Organization Id"
219
- />
302
+ <label id="node-config-input-organizationId-label" for="node-config-input-organizationId">
303
+ <i class="fa fa-list"></i>
304
+ <span data-i18n="OpenaiApi.label.organizationId"></span>
305
+ </label>
306
+ <input type="text" id="node-config-input-organizationId" />
307
+ <input type="hidden" id="node-config-input-organizationIdType" />
220
308
  </div>
221
309
  <div class="form-row">
222
310
  <label
@@ -245,6 +333,7 @@
245
333
  </script>
246
334
 
247
335
  <script type="text/html" data-help-name="Service Host">
248
- <p><b>Header</b>: Variable name to set API key</p>
249
- <p><b>Value</b>: Value of API key</p>
250
- </script>
336
+ <p><b>Auth Header</b>: Header name used to send the API key. Defaults to <code>Authorization</code>.</p>
337
+ <p><b>isQuery</b>: When true, the API key is sent as a query parameter using the Auth Header value as the parameter name.</p>
338
+ <p><b>API Key</b>: API key value or typed reference.</p>
339
+ </script>
@@ -0,0 +1,129 @@
1
+ <section>
2
+ <details>
3
+ <summary style="font-weight: bold;">📞 Realtime</summary>
4
+ <a href="https://developers.openai.com/api/reference/typescript/resources/realtime/" target="_blank">Official Documentation
5
+ <i class="fa fa-external-link fa-sm" aria-hidden="true"></i></a>
6
+
7
+ <h4 style="font-weight: bolder;"> ⋙ Create Realtime Client Secret</h4>
8
+ <p>Create an ephemeral client secret for browser/mobile realtime sessions.</p>
9
+ <dl class="message-properties">
10
+ <h4>msg.payload Properties</h4>
11
+ <dt class="optional">
12
+ model
13
+ <span class="property-type">string</span>
14
+ </dt>
15
+ <dd>Realtime model id.</dd>
16
+ <dt class="optional">
17
+ instructions
18
+ <span class="property-type">string</span>
19
+ </dt>
20
+ <dd>Default system instructions for the session.</dd>
21
+ <dt class="optional">
22
+ output_modalities
23
+ <span class="property-type">array</span>
24
+ </dt>
25
+ <dd>Output modalities such as <code>text</code> or <code>audio</code>.</dd>
26
+ <dt class="optional">
27
+ audio
28
+ <span class="property-type">object</span>
29
+ </dt>
30
+ <dd>Input/output audio config for the session.</dd>
31
+ <dt class="optional">
32
+ tools
33
+ <span class="property-type">array</span>
34
+ </dt>
35
+ <dd>Tools available to the realtime model.</dd>
36
+ <dt class="optional">
37
+ tool_choice
38
+ <span class="property-type">string | object</span>
39
+ </dt>
40
+ <dd>How tools are selected.</dd>
41
+ <dt class="optional">
42
+ tracing
43
+ <span class="property-type">string | object | null</span>
44
+ </dt>
45
+ <dd>Trace configuration for the realtime session.</dd>
46
+ </dl>
47
+
48
+ <h4 style="font-weight: bolder;"> ⋙ Accept Realtime Call</h4>
49
+ <p>Accept an incoming SIP call and attach it to a realtime session.</p>
50
+ <dl class="message-properties">
51
+ <h4>msg.payload Properties</h4>
52
+ <dt>
53
+ call_id
54
+ <span class="property-type">string</span>
55
+ </dt>
56
+ <dd>The incoming call id.</dd>
57
+ <dt>
58
+ type
59
+ <span class="property-type">string</span>
60
+ </dt>
61
+ <dd>Must be <code>realtime</code>.</dd>
62
+ <dt class="optional">
63
+ model
64
+ <span class="property-type">string</span>
65
+ </dt>
66
+ <dd>Realtime model id for the accepted call.</dd>
67
+ <dt class="optional">
68
+ instructions
69
+ <span class="property-type">string</span>
70
+ </dt>
71
+ <dd>System instructions for the call session.</dd>
72
+ <dt class="optional">
73
+ tools
74
+ <span class="property-type">array</span>
75
+ </dt>
76
+ <dd>Tools available in the call session.</dd>
77
+ <dt class="optional">
78
+ tool_choice
79
+ <span class="property-type">string | object</span>
80
+ </dt>
81
+ <dd>Tool selection strategy.</dd>
82
+ </dl>
83
+
84
+ <h4 style="font-weight: bolder;"> ⋙ Hangup Realtime Call</h4>
85
+ <p>Hang up an active realtime call.</p>
86
+ <dl class="message-properties">
87
+ <h4>msg.payload Properties</h4>
88
+ <dt>
89
+ call_id
90
+ <span class="property-type">string</span>
91
+ </dt>
92
+ <dd>The call id.</dd>
93
+ </dl>
94
+
95
+ <h4 style="font-weight: bolder;"> ⋙ Refer Realtime Call</h4>
96
+ <p>Transfer an active call using SIP REFER.</p>
97
+ <dl class="message-properties">
98
+ <h4>msg.payload Properties</h4>
99
+ <dt>
100
+ call_id
101
+ <span class="property-type">string</span>
102
+ </dt>
103
+ <dd>The call id.</dd>
104
+ <dt>
105
+ target_uri
106
+ <span class="property-type">string</span>
107
+ </dt>
108
+ <dd>Transfer target URI, for example <code>tel:+14155550123</code>.</dd>
109
+ </dl>
110
+
111
+ <h4 style="font-weight: bolder;"> ⋙ Reject Realtime Call</h4>
112
+ <p>Reject an incoming call.</p>
113
+ <dl class="message-properties">
114
+ <h4>msg.payload Properties</h4>
115
+ <dt>
116
+ call_id
117
+ <span class="property-type">string</span>
118
+ </dt>
119
+ <dd>The call id.</dd>
120
+ <dt class="optional">
121
+ status_code
122
+ <span class="property-type">integer</span>
123
+ </dt>
124
+ <dd>Optional SIP status code. Default is <code>603</code>.</dd>
125
+ </dl>
126
+
127
+ <p>Call operations return a small confirmation object in <code>msg.payload</code> when successful.</p>
128
+ </details>
129
+ </section>
@@ -0,0 +1,45 @@
1
+ const OpenAI = require("openai").OpenAI;
2
+
3
+ async function createRealtimeClientSecret(parameters) {
4
+ const openai = new OpenAI(this.clientParams);
5
+ const response = await openai.realtime.clientSecrets.create(
6
+ parameters.payload
7
+ );
8
+ return response;
9
+ }
10
+
11
+ async function acceptRealtimeCall(parameters) {
12
+ const openai = new OpenAI(this.clientParams);
13
+ const { call_id, ...body } = parameters.payload;
14
+ await openai.realtime.calls.accept(call_id, body);
15
+ return { call_id, status: "accepted" };
16
+ }
17
+
18
+ async function hangupRealtimeCall(parameters) {
19
+ const openai = new OpenAI(this.clientParams);
20
+ const { call_id, ...params } = parameters.payload;
21
+ await openai.realtime.calls.hangup(call_id, params);
22
+ return { call_id, status: "hung_up" };
23
+ }
24
+
25
+ async function referRealtimeCall(parameters) {
26
+ const openai = new OpenAI(this.clientParams);
27
+ const { call_id, ...body } = parameters.payload;
28
+ await openai.realtime.calls.refer(call_id, body);
29
+ return { call_id, status: "referred" };
30
+ }
31
+
32
+ async function rejectRealtimeCall(parameters) {
33
+ const openai = new OpenAI(this.clientParams);
34
+ const { call_id, ...body } = parameters.payload;
35
+ await openai.realtime.calls.reject(call_id, body);
36
+ return { call_id, status: "rejected" };
37
+ }
38
+
39
+ module.exports = {
40
+ createRealtimeClientSecret,
41
+ acceptRealtimeCall,
42
+ hangupRealtimeCall,
43
+ referRealtimeCall,
44
+ rejectRealtimeCall,
45
+ };
@@ -0,0 +1,7 @@
1
+ <optgroup style="font-style: normal;" label="📞 Realtime">
2
+ <option value="createRealtimeClientSecret" data-i18n="OpenaiApi.parameters.createRealtimeClientSecret"></option>
3
+ <option value="acceptRealtimeCall" data-i18n="OpenaiApi.parameters.acceptRealtimeCall"></option>
4
+ <option value="hangupRealtimeCall" data-i18n="OpenaiApi.parameters.hangupRealtimeCall"></option>
5
+ <option value="referRealtimeCall" data-i18n="OpenaiApi.parameters.referRealtimeCall"></option>
6
+ <option value="rejectRealtimeCall" data-i18n="OpenaiApi.parameters.rejectRealtimeCall"></option>
7
+ </optgroup>