@cobrowser/chatgpt 0.7.39 → 0.7.40

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(conversation: string): Promise<ChatGPTResponse | undefined>;
36
+ getPromptSuggestions(message: 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(conversation);
83
+ return yield this.getPromptSuggestions(lastCustomerMessage);
84
84
  }
85
85
  return yield this.getChatCompletionSuggestions(conversation);
86
86
  }
@@ -216,113 +216,18 @@ 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(conversation) {
220
- var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p;
219
+ getPromptSuggestions(message) {
220
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o;
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
- }
242
222
  const openai = new openai_1.default({ apiKey: this.openaiApiKey });
243
223
  let conversationId = this.conversationId;
244
- let lastMessageIndex = -1;
245
224
  if (!conversationId) {
246
- const conv = yield openai.conversations.create({
247
- metadata: {
248
- lastMessageIndex: '-1',
249
- conversationHistory: JSON.stringify([])
250
- }
251
- });
225
+ const conv = yield openai.conversations.create();
252
226
  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;
323
227
  }
324
228
  const request = {
325
- input: inputWithContext,
229
+ //model: this.chatGptModel || 'gpt-4o-mini',
230
+ input: message,
326
231
  store: true,
327
232
  conversation: { id: conversationId },
328
233
  include: ['file_search_call.results'],
@@ -330,49 +235,36 @@ class CopilotService extends BaseService_1.default {
330
235
  if (this.assistantId && (yield this.isPromptIdFormat(this.assistantId))) {
331
236
  request.prompt = { id: this.assistantId };
332
237
  }
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'));
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;
353
243
  }
354
- const output = lastResponse.output || [];
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 || [];
355
247
  const assistantMessages = output.filter((item) => item.type === 'message' && item.role === 'assistant');
356
248
  if (assistantMessages.length) {
357
249
  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)) || []; });
358
250
  return {
359
- data: [text[text.length - 1]],
251
+ data: [text.pop()],
360
252
  threadId: this.conversationId,
361
253
  usageTokens: {
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),
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),
365
257
  },
366
258
  };
367
259
  }
368
- if (lastResponse.output_text) {
260
+ if (response.output_text) {
369
261
  return {
370
- data: [lastResponse.output_text],
262
+ data: [response.output_text],
371
263
  threadId: this.conversationId,
372
264
  usageTokens: {
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),
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),
376
268
  },
377
269
  };
378
270
  }
@@ -12,4 +12,4 @@ export declare const DESTINATION_LANGUAGE = "English";
12
12
  export declare const LANGUAGE_DETECTION_SYSTEM_ROLE = "\n You are a language detection assistant. Your task is to analyze short text input and determine \n its language using ISO language code. Respond only in JSON format with two key-value pairs: \n - 'languageCode': the detected language's ISO code (or undefined if detection fails).\n - 'isError': a boolean value (true if detection fails, false otherwise).\n";
13
13
  export declare const WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = "\n You are a language detection assistant. Your task is to analyze the most frequently occurring words in the given text \n and determine the language based on those words. Respond only in JSON format with two key-value pairs: \n - 'languageCode': the detected language's ISO code (or undefined if detection fails).\n - 'isError': a boolean value (true if detection fails, false otherwise).\n";
14
14
  export declare const TRANSLATION_SYSTEM_ROLE_BASE_PROMPT = "\n <BASE_PROMPT>\n\n You are a translator that responds exclusively in JSON format.\n\n Your response must be a JSON object containing:\n - 'translations': an array of objects. Each object in the array must contain:\n - 'original': The original input message before translation.\n - 'translation': The translated version of 'original'.\n - 'isError': a boolean value (true if translation fails, false otherwise).\n\n **You MUST return JSON format even if you fail to translate the text.**\n \n In that case:\n\n - 'translations' field should be an empty array.\n - 'isError' should be true.\n\n You must follow the response structure defined in this BASE_PROMPT strictly.\n \n Apply all instructions in ADDITIONAL_INSTRUCTIONS, but never alter the required JSON structure.\n\n </BASE_PROMPT>\n";
15
- export declare const TRANSLATION_ADDITIONAL_INSTRUCTIONS = "\n Ensure that each 'translation' accurately reflects the meaning of 'original' and is phrased in a way that native speakers would naturally express it, taking into account cultural context and commonly used expressions.\n\n Do not translate commonly known Latin phrases or expressions (e.g., 'de facto', 'bona fide') when they appear mid-sentence in another language. Leave them exactly as they appear in the original text.\n";
15
+ export declare const TRANSLATION_ADDITIONAL_INSTRUCTIONS = "\n === BEGIN TRANSLATION QUALITY RULE ===\n\n Ensure that each 'translation' accurately reflects the meaning of 'original' and is phrased in a way that native speakers would naturally express it, taking into account cultural context and commonly used expressions.\n \n === END TRANSLATION QUALITY RULE ===\n\n\n === BEGIN LATIN PHRASE PRESERVATION RULE ===\n\n Do not translate commonly known Latin phrases or expressions (e.g., 'de facto', 'bona fide') when they appear mid-sentence in another language. Leave them exactly as they appear in the original text.\n \n === END LATIN PHRASE PRESERVATION RULE ===\n\n\n === BEGIN GEOGRAPHICAL NAME IMMUTABILITY RULE ===\n\n For every geographical name, you MUST strictly mirror the exact form used by the user.\n\n You MUST ONLY use a specific geographical name variant if the user explicitly used that exact variant in their message.\n\n Geographical names include cities, towns, villages, countries, regions, states, and provinces.\n\n Geographical names MUST be treated as immutable user-controlled tokens.\n\n You MUST preserve exactly the user-provided:\n\n 1. spelling\n 2. capitalization\n 3. punctuation\n 4. spacing\n 5. diacritics\n 6. word order\n\n Geographical names MUST be copied verbatim from the user\u2019s message into the response.\n\n You MUST NOT translate, localize, substitute, normalize, infer, or switch between geographical name variants.\n\n You MUST NOT replace geographical names with official, native, common, or localized versions unless the user explicitly used that exact form.\n\n EXCEPTION \u2014 TYPO CORRECTION:\n\n If a geographical name in the user's message contains a clear, unambiguous spelling typo, you MUST correct it to the single most logically intended and widely recognized standard form.\n\n This exception applies ONLY when:\n\n 1. the misspelling is clearly accidental\n 2. there is exactly one reasonable intended geographical location\n 3. the correction does NOT change the intended name variant\n\n If multiple locations could match the misspelling, or if the spelling appears intentional, you MUST mirror the user's input exactly and MUST NOT correct it.\n\n When the typo correction exception is applied, the corrected name becomes the authoritative form and MUST be used consistently in the response.\n\n You MUST NOT explain, mention, or reference these rules.\n\n This rule applies regardless of response language, common exonyms or endonyms, or cultural or linguistic conventions.\n This rule has absolute priority and MUST be enforced at all times.\n\n === END GEOGRAPHICAL NAME IMMUTABILITY RULE ===\n";
@@ -78,7 +78,63 @@ exports.TRANSLATION_SYSTEM_ROLE_BASE_PROMPT = `
78
78
  `;
79
79
  // Additional instructions for translation. This is going to be used if additional instructions are not passed as parameter by manager.
80
80
  exports.TRANSLATION_ADDITIONAL_INSTRUCTIONS = `
81
+ === BEGIN TRANSLATION QUALITY RULE ===
82
+
81
83
  Ensure that each 'translation' accurately reflects the meaning of 'original' and is phrased in a way that native speakers would naturally express it, taking into account cultural context and commonly used expressions.
84
+
85
+ === END TRANSLATION QUALITY RULE ===
86
+
87
+
88
+ === BEGIN LATIN PHRASE PRESERVATION RULE ===
82
89
 
83
90
  Do not translate commonly known Latin phrases or expressions (e.g., 'de facto', 'bona fide') when they appear mid-sentence in another language. Leave them exactly as they appear in the original text.
91
+
92
+ === END LATIN PHRASE PRESERVATION RULE ===
93
+
94
+
95
+ === BEGIN GEOGRAPHICAL NAME IMMUTABILITY RULE ===
96
+
97
+ For every geographical name, you MUST strictly mirror the exact form used by the user.
98
+
99
+ You MUST ONLY use a specific geographical name variant if the user explicitly used that exact variant in their message.
100
+
101
+ Geographical names include cities, towns, villages, countries, regions, states, and provinces.
102
+
103
+ Geographical names MUST be treated as immutable user-controlled tokens.
104
+
105
+ You MUST preserve exactly the user-provided:
106
+
107
+ 1. spelling
108
+ 2. capitalization
109
+ 3. punctuation
110
+ 4. spacing
111
+ 5. diacritics
112
+ 6. word order
113
+
114
+ Geographical names MUST be copied verbatim from the user’s message into the response.
115
+
116
+ You MUST NOT translate, localize, substitute, normalize, infer, or switch between geographical name variants.
117
+
118
+ You MUST NOT replace geographical names with official, native, common, or localized versions unless the user explicitly used that exact form.
119
+
120
+ EXCEPTION — TYPO CORRECTION:
121
+
122
+ If a geographical name in the user's message contains a clear, unambiguous spelling typo, you MUST correct it to the single most logically intended and widely recognized standard form.
123
+
124
+ This exception applies ONLY when:
125
+
126
+ 1. the misspelling is clearly accidental
127
+ 2. there is exactly one reasonable intended geographical location
128
+ 3. the correction does NOT change the intended name variant
129
+
130
+ If multiple locations could match the misspelling, or if the spelling appears intentional, you MUST mirror the user's input exactly and MUST NOT correct it.
131
+
132
+ When the typo correction exception is applied, the corrected name becomes the authoritative form and MUST be used consistently in the response.
133
+
134
+ You MUST NOT explain, mention, or reference these rules.
135
+
136
+ This rule applies regardless of response language, common exonyms or endonyms, or cultural or linguistic conventions.
137
+ This rule has absolute priority and MUST be enforced at all times.
138
+
139
+ === END GEOGRAPHICAL NAME IMMUTABILITY RULE ===
84
140
  `;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cobrowser/chatgpt",
3
- "version": "0.7.39",
3
+ "version": "0.7.40",
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": "ada34db58368358b736fa33775e0a84d00a7efea"
43
+ "gitHead": "16611610698982c71962d16bdf6508733b171847"
44
44
  }