@cobrowser/chatgpt 0.7.25 → 0.7.27

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.
@@ -6,8 +6,9 @@ export declare const MESSAGE_TYPES: {
6
6
  text: string;
7
7
  button: string;
8
8
  };
9
- export declare const DEFAULT_PROMPT = "You are a helpful assistant. Your role is to address visitor \nqueries related to the ongoing conversation and the last message received. Please ensure \nthat responses remain within the ongoing conversation. Politely decline any user queries \nthat is not present in the ongoing conversation. \n\nYou will always respond with a JSON. It will be in the format: \n\n{ answer: '', suggestions: [], connectWithAgent: true or false }\n\nFields in the JSON:\n\nAnswer: It will consist of the user's query answer based on the ongoing conversation. \nRestrict this field to 100 characters.\n\nSuggestions: Request 2 suggestions from user's perspective that he can ask. \nIt should be an array of strings. Restrict each suggestion to 50 characters.\n \nConnectWithAgent: It is a boolean. It should be set to true if the user's query is \nnot found in the ongoing conversation. Politely tell the user to talk to a real agent. \nAlso when it is true, do not provide any suggestions.\n";
9
+ export declare const SECURITY_PROMPT = "\n **SECURITY \u2014 XSS PROTECTION (MANDATORY, HIGHEST PRIORITY)**\n\n 1. **CANONICALIZE INPUT**: decode HTML entities, percent-decode, decode `\\x..` / `\\u....`, normalize Unicode (NFKC), collapse whitespace and hidden chars.\n\n 2. **DETECT & REMOVE**: detect any HTML tags, suspicious URIs, data: URIs, event handlers (`on*`), `javascript:`, `data:`, `vbscript:`, inline SVG/CSS payloads, or any obfuscated variant (e.g. encoded, spaced, or double-encoded). \n\n If detected \u2192 **OMIT COMPLETELY**. Do **NOT** echo, describe, forward, or reproduce the removed content in any form.\n\n 3. **ALLOWED URLS**: plain URL strings (e.g. `https://example.com`, `www.example.com`) may be shown **only as plain text**. **Do not render as markdown links, HTML anchors, or any clickable element**.\n\n 4. **NEVER GENERATE** any HTML/markup that can execute (no `<script>`, `<img>`, `<svg>`, `<iframe>`, `<style>`, `<a>` with hrefs, data: URIs, `<object>`, `javascript:`, etc.).\n\n 5. **IF UNCERTAIN** about safety, **do not reproduce the fragment** \u2014 return the useful reply with the unsafe portion removed. If you must note removal, use a generic message **without** including the removed content, e.g.:\n \"[Removed for security \u2014 potential XSS]\"\n\n 6. **OUTPUT FORMAT**: final response must be plain text with no active HTML/HTML-like anchors. Escape or remove `<`, `>`, `&` if they would render as HTML.\n\n **ENFORCE THESE BEFORE ANY OTHER TASK** \u2014 XSS protection takes precedence over fidelity or literal echoing.\n";
10
+ export declare const DEFAULT_PROMPT: string;
10
11
  export declare const DESTINATION_LANGUAGE = "English";
11
- 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";
12
- 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";
13
- export declare const TRANSLATION_SYSTEM_ROLE = "\n You are a translator that responds exclusively in JSON format. Your response must be a JSON object containing:\n - 'data': it is an array of objects. Each object in the array must contain:\n - 'translated_message': The original input message before translation.\n - 'translation: The translated version of 'translated_message', ensuring it is natural, culturally appropriate, and commonly used by native speakers.\n - 'isError': a boolean value (true if translation fails, false otherwise).\n\n Ensure that 'translation' accurately represents the meaning of 'translated_message' while considering cultural nuances, usual expressions, and natural phrasing in the target language. \n Your response must follow this structure strictly.\n";
12
+ export declare const LANGUAGE_DETECTION_SYSTEM_ROLE: string;
13
+ export declare const WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE: string;
14
+ export declare const TRANSLATION_SYSTEM_ROLE: string;
package/dist/constants.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TRANSLATION_SYSTEM_ROLE = exports.WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = exports.LANGUAGE_DETECTION_SYSTEM_ROLE = exports.DESTINATION_LANGUAGE = exports.DEFAULT_PROMPT = exports.MESSAGE_TYPES = exports.MESSAGE_SENDER = void 0;
3
+ exports.TRANSLATION_SYSTEM_ROLE = exports.WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = exports.LANGUAGE_DETECTION_SYSTEM_ROLE = exports.DESTINATION_LANGUAGE = exports.DEFAULT_PROMPT = exports.SECURITY_PROMPT = exports.MESSAGE_TYPES = exports.MESSAGE_SENDER = void 0;
4
4
  // Message sender in conversation history
5
5
  exports.MESSAGE_SENDER = {
6
6
  visitor: 'visitor',
@@ -11,32 +11,58 @@ exports.MESSAGE_TYPES = {
11
11
  text: 'text',
12
12
  button: 'button'
13
13
  };
14
+ // Security Prompt
15
+ exports.SECURITY_PROMPT = `
16
+ **SECURITY — XSS PROTECTION (MANDATORY, HIGHEST PRIORITY)**
17
+
18
+ 1. **CANONICALIZE INPUT**: decode HTML entities, percent-decode, decode \`\\x..\` / \`\\u....\`, normalize Unicode (NFKC), collapse whitespace and hidden chars.
19
+
20
+ 2. **DETECT & REMOVE**: detect any HTML tags, suspicious URIs, data: URIs, event handlers (\`on*\`), \`javascript:\`, \`data:\`, \`vbscript:\`, inline SVG/CSS payloads, or any obfuscated variant (e.g. encoded, spaced, or double-encoded).
21
+
22
+ If detected → **OMIT COMPLETELY**. Do **NOT** echo, describe, forward, or reproduce the removed content in any form.
23
+
24
+ 3. **ALLOWED URLS**: plain URL strings (e.g. \`https://example.com\`, \`www.example.com\`) may be shown **only as plain text**. **Do not render as markdown links, HTML anchors, or any clickable element**.
25
+
26
+ 4. **NEVER GENERATE** any HTML/markup that can execute (no \`<script>\`, \`<img>\`, \`<svg>\`, \`<iframe>\`, \`<style>\`, \`<a>\` with hrefs, data: URIs, \`<object>\`, \`javascript:\`, etc.).
27
+
28
+ 5. **IF UNCERTAIN** about safety, **do not reproduce the fragment** — return the useful reply with the unsafe portion removed. If you must note removal, use a generic message **without** including the removed content, e.g.:
29
+ "[Removed for security — potential XSS]"
30
+
31
+ 6. **OUTPUT FORMAT**: final response must be plain text with no active HTML/HTML-like anchors. Escape or remove \`<\`, \`>\`, \`&\` if they would render as HTML.
32
+
33
+ **ENFORCE THESE BEFORE ANY OTHER TASK** — XSS protection takes precedence over fidelity or literal echoing.
34
+ `;
14
35
  // Default prompt for ChatGPT
15
- exports.DEFAULT_PROMPT = `You are a helpful assistant. Your role is to address visitor
16
- queries related to the ongoing conversation and the last message received. Please ensure
17
- that responses remain within the ongoing conversation. Politely decline any user queries
18
- that is not present in the ongoing conversation.
36
+ exports.DEFAULT_PROMPT = `
37
+ ${exports.SECURITY_PROMPT}
38
+
39
+ You are a helpful assistant. Your role is to address visitor
40
+ queries related to the ongoing conversation and the last message received. Please ensure
41
+ that responses remain within the ongoing conversation. Politely decline any user queries
42
+ that is not present in the ongoing conversation.
19
43
 
20
- You will always respond with a JSON. It will be in the format:
44
+ You will always respond with a JSON. It will be in the format:
21
45
 
22
- { answer: '', suggestions: [], connectWithAgent: true or false }
46
+ { answer: '', suggestions: [], connectWithAgent: true or false }
23
47
 
24
- Fields in the JSON:
48
+ Fields in the JSON:
25
49
 
26
- Answer: It will consist of the user's query answer based on the ongoing conversation.
27
- Restrict this field to 100 characters.
50
+ Answer: It will consist of the user's query answer based on the ongoing conversation.
51
+ Restrict this field to 100 characters.
28
52
 
29
- Suggestions: Request 2 suggestions from user's perspective that he can ask.
30
- It should be an array of strings. Restrict each suggestion to 50 characters.
31
-
32
- ConnectWithAgent: It is a boolean. It should be set to true if the user's query is
33
- not found in the ongoing conversation. Politely tell the user to talk to a real agent.
34
- Also when it is true, do not provide any suggestions.
53
+ Suggestions: Request 2 suggestions from user's perspective that he can ask.
54
+ It should be an array of strings. Restrict each suggestion to 50 characters.
55
+
56
+ ConnectWithAgent: It is a boolean. It should be set to true if the user's query is
57
+ not found in the ongoing conversation. Politely tell the user to talk to a real agent.
58
+ Also when it is true, do not provide any suggestions.
35
59
  `;
36
60
  // Default destination language
37
61
  exports.DESTINATION_LANGUAGE = 'English';
38
62
  // Language detection system role
39
63
  exports.LANGUAGE_DETECTION_SYSTEM_ROLE = `
64
+ ${exports.SECURITY_PROMPT}
65
+
40
66
  You are a language detection assistant. Your task is to analyze short text input and determine
41
67
  its language using ISO language code. Respond only in JSON format with two key-value pairs:
42
68
  - 'languageCode': the detected language's ISO code (or undefined if detection fails).
@@ -44,6 +70,8 @@ exports.LANGUAGE_DETECTION_SYSTEM_ROLE = `
44
70
  `;
45
71
  // Word frequency language detection system role
46
72
  exports.WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = `
73
+ ${exports.SECURITY_PROMPT}
74
+
47
75
  You are a language detection assistant. Your task is to analyze the most frequently occurring words in the given text
48
76
  and determine the language based on those words. Respond only in JSON format with two key-value pairs:
49
77
  - 'languageCode': the detected language's ISO code (or undefined if detection fails).
@@ -51,6 +79,8 @@ exports.WORD_FREQUENCY_LANGUAGE_DETECTION_SYSTEM_ROLE = `
51
79
  `;
52
80
  // Message translation system role
53
81
  exports.TRANSLATION_SYSTEM_ROLE = `
82
+ ${exports.SECURITY_PROMPT}
83
+
54
84
  You are a translator that responds exclusively in JSON format. Your response must be a JSON object containing:
55
85
  - 'data': it is an array of objects. Each object in the array must contain:
56
86
  - 'translated_message': The original input message before translation.
@@ -1,6 +1,6 @@
1
+ import { AssistantResponseFormatOption } from 'openai/resources/beta/threads/threads';
1
2
  import ChatGptResponse from '../../models/ChatGptResponse';
2
3
  import BaseService from '../BaseService/BaseService';
3
- import { AssistantResponseFormatOption } from 'openai/resources/beta/threads/threads';
4
4
  export declare class AssistantService extends BaseService {
5
5
  assistantId: string | undefined;
6
6
  threadId: string | undefined;
@@ -99,7 +99,7 @@ class AssistantService extends BaseService_1.default {
99
99
  const messages = data.flatMap((message) => message === null || message === void 0 ? void 0 : message.content.map((content) => ((content.type === 'text' && message.role === 'assistant') ? content.text : '')));
100
100
  const assistantMessages = messages.filter(message => typeof message === 'object' && 'value' in message && typeof message.value === 'string');
101
101
  if (assistantMessages.length) {
102
- let answer = assistantMessages.map(message => message.value).join('\n');
102
+ let answer = assistantMessages.map(message => this.output(message.value, true)).join('\n');
103
103
  return {
104
104
  firstChoice: answer.replace(/【.*?】/g, ''),
105
105
  threadId: run.thread_id,
@@ -35,6 +35,6 @@ declare class BaseService {
35
35
  *
36
36
  * @param data
37
37
  */
38
- output(data: string | undefined): string | undefined;
38
+ output(data: any, shouldStringify?: boolean): any;
39
39
  }
40
40
  export default BaseService;
@@ -105,14 +105,23 @@ class BaseService {
105
105
  *
106
106
  * @param data
107
107
  */
108
- output(data) {
108
+ output(data, shouldStringify = false) {
109
+ console.log('DATA: ', data);
109
110
  if (!data) {
110
111
  return;
111
112
  }
112
- const parsed = JSON.parse(data), text = parsed.data[0].translation, sanitized = xss_validation_1.XSSProtector.sanitize(text), encoded = xss_validation_1.XSSProtector.encode(sanitized);
113
- parsed.data[0].translation = encoded;
114
- logger_1.default.info({ data, parsed, sanitized, encoded }, ':: Sanitized Response ::');
115
- return JSON.stringify(parsed);
113
+ // Data could be plain string or JSON string.
114
+ if (typeof data === 'string') {
115
+ try {
116
+ data = JSON.parse(data);
117
+ }
118
+ catch (error) { }
119
+ }
120
+ const sanitized = xss_validation_1.XSSProtector.sanitize(data), encoded = xss_validation_1.XSSProtector.encode(sanitized);
121
+ console.log('sanitized: ', sanitized);
122
+ console.log('encoded: ', encoded);
123
+ logger_1.default.info({ data, sanitized, encoded }, ':: Sanitized Response ::');
124
+ return shouldStringify ? JSON.stringify(encoded) : encoded;
116
125
  }
117
126
  }
118
127
  exports.default = BaseService;
@@ -48,7 +48,7 @@ class ChatService extends BaseService_1.default {
48
48
  logger_1.default.info(`:: ChatService.ask :: ${JSON.stringify(requestBody)}`);
49
49
  try {
50
50
  const response = yield this.request.post('', requestBody);
51
- return this.getResponseFirstChoice(response);
51
+ return this.output(this.getResponseFirstChoice(response), true);
52
52
  }
53
53
  catch (e) {
54
54
  this.handleErrors(e);
@@ -1,7 +1,7 @@
1
- import ChatGptResponse from '../../models/ChatGptResponse';
2
- import BaseService from '../BaseService/BaseService';
3
1
  import ChatGptMessage from '../../models/ChatGptMessage';
4
2
  import Item from '../../models/Item';
3
+ import BaseService from '../BaseService/BaseService';
4
+ import ChatGptResponse from '../../models/ChatGptResponse';
5
5
  export declare class CopilotService extends BaseService {
6
6
  assistantId: string | undefined;
7
7
  threadId: string | undefined;
@@ -24,7 +24,7 @@ export declare class CopilotService extends BaseService {
24
24
  * @param conversation the whole chat conversation
25
25
  * @param items the items to recommend from
26
26
  */
27
- recommend(conversation: ChatGptMessage[], items: Item[]): Promise<string | undefined>;
27
+ recommend(conversation: ChatGptMessage[], items: Item[]): Promise<any>;
28
28
  /**
29
29
  * Get the reply of the assistant if the assistant_id is available
30
30
  *
@@ -13,10 +13,10 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
13
13
  };
14
14
  Object.defineProperty(exports, "__esModule", { value: true });
15
15
  exports.CopilotService = void 0;
16
- const BaseService_1 = __importDefault(require("../BaseService/BaseService"));
17
- const logger_1 = __importDefault(require("../logger"));
18
16
  const ChatGptMessage_1 = require("../../models/ChatGptMessage");
17
+ const logger_1 = __importDefault(require("../logger"));
19
18
  const openai_1 = __importDefault(require("openai"));
19
+ const BaseService_1 = __importDefault(require("../BaseService/BaseService"));
20
20
  class CopilotService extends BaseService_1.default {
21
21
  constructor(apiKey, model, assistantId, threadId, apiUrl, maxNumberOfChoices) {
22
22
  super(apiKey, model, apiUrl, maxNumberOfChoices);
@@ -80,7 +80,7 @@ class CopilotService extends BaseService_1.default {
80
80
  messages: [mainPromptMessage],
81
81
  }, response = yield this.request.post('', requestBody);
82
82
  return {
83
- firstChoice: this.getResponseFirstChoice(response),
83
+ firstChoice: this.output(this.getResponseFirstChoice(response), true),
84
84
  usageTokens: this.getResponseUsageTokens(response),
85
85
  };
86
86
  }
@@ -114,7 +114,7 @@ class CopilotService extends BaseService_1.default {
114
114
  model: this.chatGptModel,
115
115
  messages: [firstMessage, ...conversation],
116
116
  }, response = yield this.request.post('', requestBody);
117
- return this.getResponseFirstChoice(response);
117
+ return this.output(this.getResponseFirstChoice(response), true);
118
118
  }
119
119
  catch (e) {
120
120
  this.handleErrors(e);
@@ -158,7 +158,7 @@ class CopilotService extends BaseService_1.default {
158
158
  if (assistantMessages.length) {
159
159
  let answers = assistantMessages.map(message => message.value);
160
160
  return {
161
- firstChoice: JSON.stringify(answers),
161
+ firstChoice: this.output((answers), true),
162
162
  threadId: run.thread_id,
163
163
  usageTokens: run.usage,
164
164
  };
@@ -55,7 +55,7 @@ class TranslationService extends BaseService_1.default {
55
55
  logger_1.default.info({ requestBody }, ':: TranslationServicee.translate :: Translating ::');
56
56
  const response = yield this.request.post('', requestBody);
57
57
  return {
58
- firstChoice: this.output(this.getResponseFirstChoice(response)),
58
+ firstChoice: this.output(this.getResponseFirstChoice(response), true),
59
59
  usageTokens: this.getResponseUsageTokens(response),
60
60
  };
61
61
  }
@@ -94,7 +94,7 @@ class TranslationService extends BaseService_1.default {
94
94
  logger_1.default.info({ requestBody }, ':: TranslationServicee.findTextLanguage :: Finding text language ::');
95
95
  const response = yield this.request.post('', requestBody);
96
96
  return {
97
- firstChoice: this.getResponseFirstChoice(response),
97
+ firstChoice: this.output(this.getResponseFirstChoice(response), true),
98
98
  usageTokens: this.getResponseUsageTokens(response),
99
99
  };
100
100
  }
@@ -133,7 +133,7 @@ class TranslationService extends BaseService_1.default {
133
133
  logger_1.default.info({ requestBody }, ':: TranslationServicee.findTextLanguageBasedOnFrequency :: Finding text language ::');
134
134
  const response = yield this.request.post('', requestBody);
135
135
  return {
136
- firstChoice: this.getResponseFirstChoice(response),
136
+ firstChoice: this.output(this.getResponseFirstChoice(response), true),
137
137
  usageTokens: this.getResponseUsageTokens(response),
138
138
  };
139
139
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@cobrowser/chatgpt",
3
- "version": "0.7.25",
3
+ "version": "0.7.27",
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": "57125454a3d76587d6c7a193ce382c98c14c978d"
43
+ "gitHead": "c626a06693076aba35e66006e8561bb2dc87e1fa"
44
44
  }