@cobrowser/chatgpt 0.7.39-beta.1 → 0.7.39

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.
@@ -33,5 +33,5 @@ export declare class CopilotService extends BaseService {
33
33
  getAssistantSuggestions(conversation: string): Promise<ChatGPTResponse | undefined>;
34
34
  private isAssistantIdFormat;
35
35
  private isPromptIdFormat;
36
- getPromptSuggestions(message: string): Promise<ChatGPTResponse | undefined>;
36
+ getPromptSuggestions(conversation: string): Promise<ChatGPTResponse | undefined>;
37
37
  }
@@ -80,7 +80,7 @@ class CopilotService extends BaseService_1.default {
80
80
  if (yield this.isAssistantIdFormat(this.assistantId)) {
81
81
  return yield this.getAssistantSuggestions(conversation);
82
82
  }
83
- return yield this.getPromptSuggestions(lastCustomerMessage);
83
+ return yield this.getPromptSuggestions(conversation);
84
84
  }
85
85
  return yield this.getChatCompletionSuggestions(conversation);
86
86
  }
@@ -216,18 +216,113 @@ class CopilotService extends BaseService_1.default {
216
216
  isPromptIdFormat(id) {
217
217
  return !!id && /^pmpt_[A-Za-z0-9]+$/.test(id);
218
218
  }
219
- getPromptSuggestions(message) {
220
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
219
+ getPromptSuggestions(conversation) {
220
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
221
221
  return __awaiter(this, void 0, void 0, function* () {
222
+ const conversationLines = conversation.split('\n').filter(line => line.trim());
223
+ const messages = [];
224
+ for (const line of conversationLines) {
225
+ if (line.includes('customer:')) {
226
+ messages.push({
227
+ role: 'user',
228
+ content: line.replace(/^customer:\s*/, '').trim()
229
+ });
230
+ }
231
+ else if (line.includes('agent:')) {
232
+ messages.push({
233
+ role: 'assistant',
234
+ content: line.replace(/^agent:\s*/, '').trim()
235
+ });
236
+ }
237
+ }
238
+ if (messages.length === 0) {
239
+ logger_1.default.error('No valid messages found in conversation');
240
+ return Promise.reject(new Error('No valid messages found in conversation'));
241
+ }
222
242
  const openai = new openai_1.default({ apiKey: this.openaiApiKey });
223
243
  let conversationId = this.conversationId;
244
+ let lastMessageIndex = -1;
224
245
  if (!conversationId) {
225
- const conv = yield openai.conversations.create();
246
+ const conv = yield openai.conversations.create({
247
+ metadata: {
248
+ lastMessageIndex: '-1',
249
+ conversationHistory: JSON.stringify([])
250
+ }
251
+ });
226
252
  conversationId = conv.id;
253
+ this.conversationId = conversationId;
254
+ }
255
+ else {
256
+ // Retrieve conversation to get metadata
257
+ try {
258
+ const conv = yield openai.conversations.retrieve(conversationId);
259
+ lastMessageIndex = parseInt(((_a = conv.metadata) === null || _a === void 0 ? void 0 : _a.lastMessageIndex) || '-1', 10);
260
+ }
261
+ catch (e) {
262
+ logger_1.default.error('Failed to retrieve conversation metadata', e);
263
+ lastMessageIndex = -1;
264
+ }
265
+ }
266
+ // Get new messages that haven't been sent yet
267
+ const newMessages = messages.slice(lastMessageIndex + 1);
268
+ if (newMessages.length === 0) {
269
+ // Retrieve the last response from the conversation
270
+ try {
271
+ const convHistory = yield openai.conversations.retrieve(conversationId);
272
+ const lastResponse = convHistory.last_response;
273
+ if (lastResponse) {
274
+ const output = lastResponse.output || [];
275
+ const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
276
+ if (assistantMessages.length) {
277
+ const text = assistantMessages.flatMap((m) => { var _a, _b; return ((_b = (_a = m.content) === null || _a === void 0 ? void 0 : _a.filter((c) => c.type === 'output_text')) === null || _b === void 0 ? void 0 : _b.map((c) => c.text)) || []; });
278
+ return {
279
+ data: [text[text.length - 1]],
280
+ threadId: this.conversationId,
281
+ usageTokens: undefined,
282
+ };
283
+ }
284
+ }
285
+ }
286
+ catch (e) {
287
+ logger_1.default.error('Failed to retrieve last response from conversation', e);
288
+ }
289
+ return Promise.reject(new Error('No new messages to process and no previous response found'));
290
+ }
291
+ const allPreviousMessages = messages.slice(0, lastMessageIndex + 1);
292
+ const contextMessages = [];
293
+ for (const msg of allPreviousMessages) {
294
+ const roleLabel = msg.role === 'user' ? 'customer' : 'agent';
295
+ contextMessages.push(`${roleLabel}: ${msg.content}`);
296
+ }
297
+ const lastUserMessage = newMessages.filter(m => m.role === 'user').pop();
298
+ if (!lastUserMessage) {
299
+ if (conversationId) {
300
+ try {
301
+ yield openai.conversations.update(conversationId, {
302
+ metadata: {
303
+ lastMessageIndex: (messages.length - 1).toString(),
304
+ conversationHistory: JSON.stringify(messages)
305
+ }
306
+ });
307
+ }
308
+ catch (e) {
309
+ logger_1.default.error('Failed to update conversation metadata', e);
310
+ }
311
+ }
312
+ return Promise.reject(new Error('No new user messages to process'));
313
+ }
314
+ let inputWithContext = lastUserMessage.content;
315
+ if (contextMessages.length > 0 || newMessages.length > 1) {
316
+ const allNewMessages = [];
317
+ for (const msg of newMessages) {
318
+ const roleLabel = msg.role === 'user' ? 'customer' : 'agent';
319
+ allNewMessages.push(`${roleLabel}: ${msg.content}`);
320
+ }
321
+ const fullContext = [...contextMessages, ...allNewMessages].join('\n');
322
+ inputWithContext = fullContext;
227
323
  }
228
324
  const request = {
229
- //model: this.chatGptModel || 'gpt-4o-mini',
230
- input: message,
325
+ input: inputWithContext,
231
326
  store: true,
232
327
  conversation: { id: conversationId },
233
328
  include: ['file_search_call.results'],
@@ -235,36 +330,49 @@ class CopilotService extends BaseService_1.default {
235
330
  if (this.assistantId && (yield this.isPromptIdFormat(this.assistantId))) {
236
331
  request.prompt = { id: this.assistantId };
237
332
  }
238
- const response = yield openai.responses.create(request);
239
- response.output.forEach((item, index) => {
240
- });
241
- if ((_a = response.conversation) === null || _a === void 0 ? void 0 : _a.id) {
242
- this.conversationId = response.conversation.id;
333
+ const lastResponse = yield openai.responses.create(request);
334
+ if ((_b = lastResponse.conversation) === null || _b === void 0 ? void 0 : _b.id) {
335
+ this.conversationId = lastResponse.conversation.id;
336
+ conversationId = this.conversationId;
337
+ }
338
+ if (conversationId) {
339
+ try {
340
+ yield openai.conversations.update(conversationId, {
341
+ metadata: {
342
+ lastMessageIndex: (messages.length - 1).toString(),
343
+ conversationHistory: JSON.stringify(messages)
344
+ }
345
+ });
346
+ }
347
+ catch (e) {
348
+ logger_1.default.error('Failed to update conversation metadata', e);
349
+ }
350
+ }
351
+ if (!lastResponse) {
352
+ return Promise.reject(new Error('No response generated'));
243
353
  }
244
- // Sometimes if the prompt needs a file search, the output will be an array of messages
245
- // which includes multiple messages (some of them are not useful for the user, but the last one is)
246
- const output = response.output || [];
354
+ const output = lastResponse.output || [];
247
355
  const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
248
356
  if (assistantMessages.length) {
249
357
  const text = assistantMessages.flatMap((m) => { var _a, _b; return ((_b = (_a = m.content) === null || _a === void 0 ? void 0 : _a.filter((c) => c.type === 'output_text')) === null || _b === void 0 ? void 0 : _b.map((c) => c.text)) || []; });
250
358
  return {
251
- data: [text.pop()],
359
+ data: [text[text.length - 1]],
252
360
  threadId: this.conversationId,
253
361
  usageTokens: {
254
- prompt_tokens: Number((_c = ((_b = response.usage) === null || _b === void 0 ? void 0 : _b.prompt_tokens)) !== null && _c !== void 0 ? _c : 0),
255
- completion_tokens: Number((_e = ((_d = response.usage) === null || _d === void 0 ? void 0 : _d.completion_tokens)) !== null && _e !== void 0 ? _e : 0),
256
- total_tokens: Number((_g = ((_f = response.usage) === null || _f === void 0 ? void 0 : _f.total_tokens)) !== null && _g !== void 0 ? _g : 0),
362
+ prompt_tokens: Number((_d = ((_c = lastResponse.usage) === null || _c === void 0 ? void 0 : _c.prompt_tokens)) !== null && _d !== void 0 ? _d : 0),
363
+ completion_tokens: Number((_f = ((_e = lastResponse.usage) === null || _e === void 0 ? void 0 : _e.completion_tokens)) !== null && _f !== void 0 ? _f : 0),
364
+ total_tokens: Number((_h = ((_g = lastResponse.usage) === null || _g === void 0 ? void 0 : _g.total_tokens)) !== null && _h !== void 0 ? _h : 0),
257
365
  },
258
366
  };
259
367
  }
260
- if (response.output_text) {
368
+ if (lastResponse.output_text) {
261
369
  return {
262
- data: [response.output_text],
370
+ data: [lastResponse.output_text],
263
371
  threadId: this.conversationId,
264
372
  usageTokens: {
265
- prompt_tokens: Number((_j = ((_h = response.usage) === null || _h === void 0 ? void 0 : _h.prompt_tokens)) !== null && _j !== void 0 ? _j : 0),
266
- completion_tokens: Number((_l = ((_k = response.usage) === null || _k === void 0 ? void 0 : _k.completion_tokens)) !== null && _l !== void 0 ? _l : 0),
267
- total_tokens: Number((_o = ((_m = response.usage) === null || _m === void 0 ? void 0 : _m.total_tokens)) !== null && _o !== void 0 ? _o : 0),
373
+ prompt_tokens: Number((_k = ((_j = lastResponse.usage) === null || _j === void 0 ? void 0 : _j.prompt_tokens)) !== null && _k !== void 0 ? _k : 0),
374
+ completion_tokens: Number((_m = ((_l = lastResponse.usage) === null || _l === void 0 ? void 0 : _l.completion_tokens)) !== null && _m !== void 0 ? _m : 0),
375
+ total_tokens: Number((_p = ((_o = lastResponse.usage) === null || _o === void 0 ? void 0 : _o.total_tokens)) !== null && _p !== void 0 ? _p : 0),
268
376
  },
269
377
  };
270
378
  }
@@ -36,7 +36,7 @@ class TranslationService extends BaseService_1.default {
36
36
  return Promise.reject(new Error('Text must be provided'));
37
37
  }
38
38
  const translateText = `
39
- Translate the following text to ${toLanguage} if it's not already in ${toLanguage}: ${text}.
39
+ Translate the following text from ${fromLanguage} to ${toLanguage} if it's not already in ${toLanguage}: ${text}.
40
40
  `;
41
41
  const requestBody = {
42
42
  model: this.chatGPTModel,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cobrowser/chatgpt",
3
- "version": "0.7.39-beta.1",
3
+ "version": "0.7.39",
4
4
  "description": "chatgpt services to connect our projects with chatgpt api",
5
5
  "keywords": [
6
6
  "chatgpt",
@@ -40,5 +40,5 @@
40
40
  "bugs": {
41
41
  "url": "https://bitbucket.org/cobrowser/cb_utils/issues"
42
42
  },
43
- "gitHead": "d3086da041359550490fc14c143a3fc79ee7603e"
43
+ "gitHead": "ada34db58368358b736fa33775e0a84d00a7efea"
44
44
  }