@crewdle/mist-connector-openai 1.0.20 → 1.0.22
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.
|
@@ -55,7 +55,12 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
55
55
|
let file;
|
|
56
56
|
for (const message of parameters.prompt) {
|
|
57
57
|
if (message.type === 'input_audio') {
|
|
58
|
-
|
|
58
|
+
const dataParts = message.input_audio.data.split(',');
|
|
59
|
+
const data = dataParts[1];
|
|
60
|
+
const type = dataParts[0].replace('data:', '').replace(';base64', '');
|
|
61
|
+
const byteArray = Uint8Array.from(Buffer.from(data, 'base64'));
|
|
62
|
+
const blob = new Blob([byteArray], { type });
|
|
63
|
+
file = new File([blob], `audio.${message.input_audio.format}`, { type });
|
|
59
64
|
}
|
|
60
65
|
}
|
|
61
66
|
if (!file) {
|
|
@@ -72,7 +77,7 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
72
77
|
console.log('OpenAIGenerativeAIWorkerConnector.processJob audio transcription response');
|
|
73
78
|
return {
|
|
74
79
|
type: "prompt" /* GenerativeAIJobType.Prompt */,
|
|
75
|
-
output: (!parameters.responseFormat || parameters.responseFormat
|
|
80
|
+
output: (!parameters.responseFormat || parameters.responseFormat === 'json') ? response.text : JSON.stringify(response),
|
|
76
81
|
inputTokens: response.usage?.type === 'tokens' ? response.usage.input_tokens : 0,
|
|
77
82
|
outputTokens: response.usage?.type === 'tokens' ? response.usage.output_tokens : 0,
|
|
78
83
|
};
|
|
@@ -127,25 +132,50 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
127
132
|
};
|
|
128
133
|
}
|
|
129
134
|
}
|
|
130
|
-
const responseFormat = this.getResponseFormat(parameters);
|
|
135
|
+
const responseFormat = this.getResponseFormat(parameters, options.model.id);
|
|
131
136
|
const tools = this.getTools(parameters);
|
|
132
137
|
const messages = this.getMessages(parameters);
|
|
138
|
+
const reasoning = this.getReasoning(parameters, options.model.id);
|
|
133
139
|
let inputTokens = 0;
|
|
134
140
|
let outputTokens = 0;
|
|
135
141
|
let output = '';
|
|
136
142
|
let resultFile;
|
|
143
|
+
let partial = '';
|
|
144
|
+
let responseId;
|
|
145
|
+
let continuationCount = 0;
|
|
146
|
+
const MAX_CONTINUATIONS = 5;
|
|
137
147
|
while (true) {
|
|
138
148
|
console.log('OpenAIGenerativeAIWorkerConnector.processJob', options.model.id);
|
|
139
149
|
const response = await this.client.responses.create({
|
|
140
150
|
model: options.model.id,
|
|
141
|
-
input:
|
|
142
|
-
|
|
143
|
-
|
|
151
|
+
input: responseId
|
|
152
|
+
? [
|
|
153
|
+
{
|
|
154
|
+
role: 'developer',
|
|
155
|
+
content: [
|
|
156
|
+
{
|
|
157
|
+
type: "input_text",
|
|
158
|
+
text: `Continue exactly after the following already-emitted text (do NOT repeat any of it).
|
|
159
|
+
ANCHOR START:
|
|
160
|
+
${partial.slice(-400)}
|
|
161
|
+
ANCHOR END.
|
|
162
|
+
Only output the missing remainder. Do not restart or re-open tags already emitted.`,
|
|
163
|
+
},
|
|
164
|
+
],
|
|
165
|
+
},
|
|
166
|
+
]
|
|
167
|
+
: messages,
|
|
168
|
+
max_output_tokens: !options.model.id.startsWith('gpt-5') ? parameters.maxTokens : Math.max(parameters.maxTokens ?? 0, 30000),
|
|
169
|
+
temperature: !options.model.id.startsWith('gpt-5') ? parameters.temperature : undefined,
|
|
144
170
|
text: responseFormat,
|
|
145
171
|
tools,
|
|
172
|
+
previous_response_id: responseId,
|
|
173
|
+
reasoning,
|
|
146
174
|
store: parameters.privacy === true ? false : true,
|
|
147
175
|
});
|
|
148
176
|
console.log('OpenAIGenerativeAIWorkerConnector.processJob response');
|
|
177
|
+
responseId = undefined;
|
|
178
|
+
partial = '';
|
|
149
179
|
inputTokens += response.usage?.input_tokens ?? 0;
|
|
150
180
|
outputTokens += response.usage?.output_tokens ?? 0;
|
|
151
181
|
const promises = [];
|
|
@@ -154,6 +184,7 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
154
184
|
for (const message of content.content) {
|
|
155
185
|
if (message.type === 'output_text') {
|
|
156
186
|
output += message.text;
|
|
187
|
+
partial += message.text;
|
|
157
188
|
}
|
|
158
189
|
}
|
|
159
190
|
}
|
|
@@ -164,8 +195,22 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
164
195
|
promises.push(this.processToolCall(parameters, messages, content.name, content.call_id, content.arguments));
|
|
165
196
|
}
|
|
166
197
|
}
|
|
198
|
+
if (response.status === 'incomplete') {
|
|
199
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJob response.incomplete', response.incomplete_details?.reason, parameters.maxTokens);
|
|
200
|
+
if (response.incomplete_details?.reason === 'max_output_tokens') {
|
|
201
|
+
if (continuationCount < MAX_CONTINUATIONS) {
|
|
202
|
+
responseId = response.id;
|
|
203
|
+
continuationCount++;
|
|
204
|
+
continue;
|
|
205
|
+
}
|
|
206
|
+
else {
|
|
207
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJob max continuations reached');
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
167
211
|
if (promises.length > 0) {
|
|
168
212
|
await Promise.all(promises);
|
|
213
|
+
output += '\n\n';
|
|
169
214
|
continue;
|
|
170
215
|
}
|
|
171
216
|
return {
|
|
@@ -290,25 +335,56 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
290
335
|
return;
|
|
291
336
|
}
|
|
292
337
|
}
|
|
293
|
-
const responseFormat = this.getResponseFormat(parameters);
|
|
338
|
+
const responseFormat = this.getResponseFormat(parameters, options.model.id);
|
|
294
339
|
const tools = this.getTools(parameters);
|
|
295
340
|
const messages = this.getMessages(parameters);
|
|
341
|
+
const reasoning = this.getReasoning(parameters, options.model.id);
|
|
342
|
+
let firstChunk = true;
|
|
343
|
+
let responseId;
|
|
344
|
+
let partial = '';
|
|
345
|
+
let continuationCount = 0;
|
|
346
|
+
const MAX_CONTINUATIONS = 5;
|
|
296
347
|
while (true) {
|
|
297
348
|
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream', options.model.id);
|
|
298
349
|
const stream = await this.client.responses.create({
|
|
299
350
|
model: options.model.id,
|
|
300
|
-
input:
|
|
301
|
-
|
|
302
|
-
|
|
351
|
+
input: responseId
|
|
352
|
+
? [
|
|
353
|
+
{
|
|
354
|
+
role: 'developer',
|
|
355
|
+
content: [
|
|
356
|
+
{
|
|
357
|
+
type: "input_text",
|
|
358
|
+
text: `Continue exactly after the following already-emitted text (do NOT repeat any of it).
|
|
359
|
+
ANCHOR START:
|
|
360
|
+
${partial.slice(-400)}
|
|
361
|
+
ANCHOR END.
|
|
362
|
+
Only output the missing remainder. Do not restart or re-open tags already emitted.`,
|
|
363
|
+
},
|
|
364
|
+
],
|
|
365
|
+
},
|
|
366
|
+
]
|
|
367
|
+
: messages,
|
|
368
|
+
max_output_tokens: !options.model.id.startsWith('gpt-5') ? parameters.maxTokens : Math.max(parameters.maxTokens ?? 0, 30000),
|
|
369
|
+
temperature: !options.model.id.startsWith('gpt-5') ? parameters.temperature : undefined,
|
|
303
370
|
text: responseFormat,
|
|
304
371
|
tools,
|
|
372
|
+
previous_response_id: responseId,
|
|
373
|
+
reasoning,
|
|
305
374
|
stream: true,
|
|
306
375
|
store: parameters.privacy === true ? false : true,
|
|
307
376
|
});
|
|
308
377
|
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream response');
|
|
378
|
+
responseId = undefined;
|
|
379
|
+
partial = '';
|
|
309
380
|
const promises = [];
|
|
310
381
|
for await (const chunk of stream) {
|
|
311
382
|
if (chunk.type === 'response.output_text.delta') {
|
|
383
|
+
if (firstChunk && chunk.delta.trim()) {
|
|
384
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream first chunk');
|
|
385
|
+
firstChunk = false;
|
|
386
|
+
}
|
|
387
|
+
partial += chunk.delta;
|
|
312
388
|
yield {
|
|
313
389
|
type: "prompt" /* GenerativeAIJobType.Prompt */,
|
|
314
390
|
output: chunk.delta,
|
|
@@ -324,6 +400,24 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
324
400
|
outputTokens: chunk.response.usage?.output_tokens ?? 0,
|
|
325
401
|
};
|
|
326
402
|
}
|
|
403
|
+
if (chunk.type === 'response.incomplete') {
|
|
404
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream response.incomplete', chunk.response.incomplete_details?.reason, parameters.maxTokens);
|
|
405
|
+
yield {
|
|
406
|
+
type: "prompt" /* GenerativeAIJobType.Prompt */,
|
|
407
|
+
output: '',
|
|
408
|
+
inputTokens: chunk.response.usage?.input_tokens ?? 0,
|
|
409
|
+
outputTokens: chunk.response.usage?.output_tokens ?? 0,
|
|
410
|
+
};
|
|
411
|
+
if (!parameters.privacy && chunk.response.incomplete_details?.reason === 'max_output_tokens') {
|
|
412
|
+
if (continuationCount < MAX_CONTINUATIONS) {
|
|
413
|
+
responseId = chunk.response.id;
|
|
414
|
+
continuationCount++;
|
|
415
|
+
}
|
|
416
|
+
else {
|
|
417
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream max continuations reached');
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
}
|
|
327
421
|
if (chunk.type === 'response.output_item.done') {
|
|
328
422
|
if (chunk.item.type === 'function_call') {
|
|
329
423
|
promises.push(this.processToolCall(parameters, messages, chunk.item.name, chunk.item.call_id, chunk.item.arguments));
|
|
@@ -339,6 +433,10 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
339
433
|
}
|
|
340
434
|
}
|
|
341
435
|
}
|
|
436
|
+
if (responseId) {
|
|
437
|
+
console.log('OpenAIGenerativeAIWorkerConnector.processJobStream needContinue');
|
|
438
|
+
continue;
|
|
439
|
+
}
|
|
342
440
|
if (promises.length > 0) {
|
|
343
441
|
await Promise.all(promises);
|
|
344
442
|
yield {
|
|
@@ -412,7 +510,7 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
412
510
|
for (const message of parameters.history) {
|
|
413
511
|
messages.push({
|
|
414
512
|
role: message.source === 'human' ? 'user' : 'assistant',
|
|
415
|
-
content: message.message,
|
|
513
|
+
content: this.getInnerMessages(message.message),
|
|
416
514
|
});
|
|
417
515
|
}
|
|
418
516
|
}
|
|
@@ -486,8 +584,22 @@ export class OpenAIGenerativeAIWorkerConnector {
|
|
|
486
584
|
}
|
|
487
585
|
return tools;
|
|
488
586
|
}
|
|
489
|
-
|
|
490
|
-
if (!
|
|
587
|
+
getReasoning(parameters, modelId) {
|
|
588
|
+
if (!modelId.startsWith('gpt-5')) {
|
|
589
|
+
return undefined;
|
|
590
|
+
}
|
|
591
|
+
if (!parameters.reasoning) {
|
|
592
|
+
return undefined;
|
|
593
|
+
}
|
|
594
|
+
return {
|
|
595
|
+
effort: parameters.reasoning,
|
|
596
|
+
};
|
|
597
|
+
}
|
|
598
|
+
getResponseFormat(parameters, modelId) {
|
|
599
|
+
if (!parameters.grammar || parameters.grammar === 'default') {
|
|
600
|
+
if (modelId.startsWith('gpt-5') && parameters.verbosity) {
|
|
601
|
+
return { verbosity: parameters.verbosity };
|
|
602
|
+
}
|
|
491
603
|
return undefined;
|
|
492
604
|
}
|
|
493
605
|
if (parameters.grammar === 'json') {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@crewdle/mist-connector-openai",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.22",
|
|
4
4
|
"description": "",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/types/index.d.ts",
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
"dist/"
|
|
16
16
|
],
|
|
17
17
|
"devDependencies": {
|
|
18
|
-
"@crewdle/web-sdk-types": "^1.0.
|
|
18
|
+
"@crewdle/web-sdk-types": "^1.0.55",
|
|
19
19
|
"@types/node": "^22.13.9",
|
|
20
20
|
"typescript": "^5.8.2"
|
|
21
21
|
},
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"openai": "^
|
|
23
|
+
"openai": "^6.1.0"
|
|
24
24
|
}
|
|
25
25
|
}
|