@crewdle/mist-connector-openai 1.0.21 → 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.
@@ -140,19 +140,42 @@ export class OpenAIGenerativeAIWorkerConnector {
140
140
  let outputTokens = 0;
141
141
  let output = '';
142
142
  let resultFile;
143
+ let partial = '';
144
+ let responseId;
145
+ let continuationCount = 0;
146
+ const MAX_CONTINUATIONS = 5;
143
147
  while (true) {
144
148
  console.log('OpenAIGenerativeAIWorkerConnector.processJob', options.model.id);
145
149
  const response = await this.client.responses.create({
146
150
  model: options.model.id,
147
- input: messages,
148
- max_output_tokens: parameters.maxTokens,
149
- temperature: parameters.temperature,
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,
150
170
  text: responseFormat,
151
171
  tools,
172
+ previous_response_id: responseId,
152
173
  reasoning,
153
174
  store: parameters.privacy === true ? false : true,
154
175
  });
155
176
  console.log('OpenAIGenerativeAIWorkerConnector.processJob response');
177
+ responseId = undefined;
178
+ partial = '';
156
179
  inputTokens += response.usage?.input_tokens ?? 0;
157
180
  outputTokens += response.usage?.output_tokens ?? 0;
158
181
  const promises = [];
@@ -161,6 +184,7 @@ export class OpenAIGenerativeAIWorkerConnector {
161
184
  for (const message of content.content) {
162
185
  if (message.type === 'output_text') {
163
186
  output += message.text;
187
+ partial += message.text;
164
188
  }
165
189
  }
166
190
  }
@@ -171,8 +195,22 @@ export class OpenAIGenerativeAIWorkerConnector {
171
195
  promises.push(this.processToolCall(parameters, messages, content.name, content.call_id, content.arguments));
172
196
  }
173
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
+ }
174
211
  if (promises.length > 0) {
175
212
  await Promise.all(promises);
213
+ output += '\n\n';
176
214
  continue;
177
215
  }
178
216
  return {
@@ -302,20 +340,43 @@ export class OpenAIGenerativeAIWorkerConnector {
302
340
  const messages = this.getMessages(parameters);
303
341
  const reasoning = this.getReasoning(parameters, options.model.id);
304
342
  let firstChunk = true;
343
+ let responseId;
344
+ let partial = '';
345
+ let continuationCount = 0;
346
+ const MAX_CONTINUATIONS = 5;
305
347
  while (true) {
306
348
  console.log('OpenAIGenerativeAIWorkerConnector.processJobStream', options.model.id);
307
349
  const stream = await this.client.responses.create({
308
350
  model: options.model.id,
309
- input: messages,
310
- max_output_tokens: parameters.maxTokens,
311
- temperature: parameters.temperature,
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,
312
370
  text: responseFormat,
313
371
  tools,
372
+ previous_response_id: responseId,
314
373
  reasoning,
315
374
  stream: true,
316
375
  store: parameters.privacy === true ? false : true,
317
376
  });
318
377
  console.log('OpenAIGenerativeAIWorkerConnector.processJobStream response');
378
+ responseId = undefined;
379
+ partial = '';
319
380
  const promises = [];
320
381
  for await (const chunk of stream) {
321
382
  if (chunk.type === 'response.output_text.delta') {
@@ -323,6 +384,7 @@ export class OpenAIGenerativeAIWorkerConnector {
323
384
  console.log('OpenAIGenerativeAIWorkerConnector.processJobStream first chunk');
324
385
  firstChunk = false;
325
386
  }
387
+ partial += chunk.delta;
326
388
  yield {
327
389
  type: "prompt" /* GenerativeAIJobType.Prompt */,
328
390
  output: chunk.delta,
@@ -338,6 +400,24 @@ export class OpenAIGenerativeAIWorkerConnector {
338
400
  outputTokens: chunk.response.usage?.output_tokens ?? 0,
339
401
  };
340
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
+ }
341
421
  if (chunk.type === 'response.output_item.done') {
342
422
  if (chunk.item.type === 'function_call') {
343
423
  promises.push(this.processToolCall(parameters, messages, chunk.item.name, chunk.item.call_id, chunk.item.arguments));
@@ -353,6 +433,10 @@ export class OpenAIGenerativeAIWorkerConnector {
353
433
  }
354
434
  }
355
435
  }
436
+ if (responseId) {
437
+ console.log('OpenAIGenerativeAIWorkerConnector.processJobStream needContinue');
438
+ continue;
439
+ }
356
440
  if (promises.length > 0) {
357
441
  await Promise.all(promises);
358
442
  yield {
@@ -426,7 +510,7 @@ export class OpenAIGenerativeAIWorkerConnector {
426
510
  for (const message of parameters.history) {
427
511
  messages.push({
428
512
  role: message.source === 'human' ? 'user' : 'assistant',
429
- content: message.message,
513
+ content: this.getInnerMessages(message.message),
430
514
  });
431
515
  }
432
516
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crewdle/mist-connector-openai",
3
- "version": "1.0.21",
3
+ "version": "1.0.22",
4
4
  "description": "",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/types/index.d.ts",
@@ -15,7 +15,7 @@
15
15
  "dist/"
16
16
  ],
17
17
  "devDependencies": {
18
- "@crewdle/web-sdk-types": "^1.0.54",
18
+ "@crewdle/web-sdk-types": "^1.0.55",
19
19
  "@types/node": "^22.13.9",
20
20
  "typescript": "^5.8.2"
21
21
  },