@smarter.sh/ui-chat 0.0.1
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.
- package/LICENSE +671 -0
- package/README.md +143 -0
- package/dist/smarter-chat-library.es.js +28850 -0
- package/dist/smarter-chat-library.es.js.map +1 -0
- package/dist/smarter-chat-library.umd.js +807 -0
- package/dist/smarter-chat-library.umd.js.map +1 -0
- package/dist/ui-chat.css +1 -0
- package/package.json +91 -0
- package/src/components/ErrorModal/ErrorModal.css +35 -0
- package/src/components/ErrorModal/ErrorModal.jsx +56 -0
- package/src/components/ErrorModal/index.js +3 -0
- package/src/components/SmarterChat/ErrorBoundary.jsx +32 -0
- package/src/components/SmarterChat/SmarterChat.jsx +419 -0
- package/src/components/SmarterChat/api.js +233 -0
- package/src/components/SmarterChat/enums.js +17 -0
- package/src/components/SmarterChat/index.js +3 -0
- package/src/components/SmarterChat/styles.css +148 -0
- package/src/components/SmarterChat/utils.jsx +158 -0
- package/src/components/enums.js +1 -0
- package/src/components/index.js +2 -0
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
.SmarterChat a {
|
|
2
|
+
text-decoration: inherit;
|
|
3
|
+
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
|
|
4
|
+
line-height: 1.5;
|
|
5
|
+
font-weight: 400;
|
|
6
|
+
|
|
7
|
+
font-synthesis: none;
|
|
8
|
+
text-rendering: optimizeLegibility;
|
|
9
|
+
-webkit-font-smoothing: antialiased;
|
|
10
|
+
-moz-osx-font-smoothing: grayscale;
|
|
11
|
+
-webkit-text-size-adjust: 100%;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.SmarterChat {
|
|
15
|
+
border: 1px solid rgba(255, 87, 51, 0.75);
|
|
16
|
+
height: 100%;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
.app-title {
|
|
20
|
+
text-align: center;
|
|
21
|
+
background-color: rgba(255, 87, 51, 0.75);
|
|
22
|
+
width: 100%;
|
|
23
|
+
padding: 0;
|
|
24
|
+
margin: 0;
|
|
25
|
+
color: whitesmoke;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
h5 {
|
|
29
|
+
color: whitesmoke;
|
|
30
|
+
margin-left: 10px;
|
|
31
|
+
margin-bottom: 0;
|
|
32
|
+
}
|
|
33
|
+
.app-logo {
|
|
34
|
+
width: 75px;
|
|
35
|
+
margin: 0 auto;
|
|
36
|
+
display: block;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.container {
|
|
40
|
+
display: flex;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.chat-app {
|
|
44
|
+
position: relative;
|
|
45
|
+
height: 100%;
|
|
46
|
+
width: 100%;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
.cs-message-separator::before,
|
|
50
|
+
.cs-message-separator::after {
|
|
51
|
+
background-color: lightgray !important;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
.cs-conversation-header {
|
|
55
|
+
text-align: center;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
div.cs-message__html-content a {
|
|
59
|
+
text-decoration: underline !important;
|
|
60
|
+
color: #333333;
|
|
61
|
+
}
|
|
62
|
+
div.cs-message__html-content a:hover {
|
|
63
|
+
text-decoration: underline;
|
|
64
|
+
color: midnightblue;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
section.smarter-message .cs-message__html-content {
|
|
68
|
+
color: brown !important;
|
|
69
|
+
background-color: blanchedalmond;
|
|
70
|
+
font-family: "Courier New", Courier, monospace;
|
|
71
|
+
font-weight: bold;
|
|
72
|
+
text-align: center;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
section.smarter-message .cs-message__content {
|
|
76
|
+
color: brown !important;
|
|
77
|
+
background-color: blanchedalmond;
|
|
78
|
+
border: 1px solid brown;
|
|
79
|
+
margin-top: 10px;
|
|
80
|
+
margin-bottom: 10px;
|
|
81
|
+
border-radius: 10px;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
section.system-message .cs-message__html-content {
|
|
85
|
+
color: beige !important;
|
|
86
|
+
background-color: rgb(39, 40, 34);
|
|
87
|
+
font-family: "Courier New", Courier, monospace;
|
|
88
|
+
font-weight: bold;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
section.system-message .cs-message__content {
|
|
92
|
+
color: beige !important;
|
|
93
|
+
background-color: rgb(39, 40, 34);
|
|
94
|
+
border: 1px solid brown;
|
|
95
|
+
margin-top: 10px;
|
|
96
|
+
margin-bottom: 10px;
|
|
97
|
+
border-radius: 10px;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/*-------------- Responsive Styling -----------------------
|
|
101
|
+
|
|
102
|
+
xs = Extra small <576px. Max container width None (auto)
|
|
103
|
+
sm = Small ≥576px. Max container width 540px.
|
|
104
|
+
md = Medium ≥768px. Max container width 720px.
|
|
105
|
+
lg = Large ≥992px. Max container width 960px.
|
|
106
|
+
xl = Extra large ≥1200px. Max container width 1140px.
|
|
107
|
+
|
|
108
|
+
*/
|
|
109
|
+
|
|
110
|
+
/********** Extra large devices only **********/
|
|
111
|
+
@media (min-width: 1200px) {
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/********** Large devices only **********/
|
|
115
|
+
@media (min-width: 992px) and (max-width: 1199px) {
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/********** Medium devices only **********/
|
|
119
|
+
@media (min-width: 768px) and (max-width: 991px) {
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
/********** Small devices only **********/
|
|
123
|
+
@media (min-width: 576) and (max-width: 767px) {
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/********** Extra small devices only **********/
|
|
127
|
+
@media (min-width: 480px) and (max-width: 575px) {
|
|
128
|
+
}
|
|
129
|
+
/********** Super extra small devices Only :-) (e.g., iPhone 4) **********/
|
|
130
|
+
@media (max-width: 479px) {
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ------------ MCDANIEL ------------------ */
|
|
134
|
+
@media (max-width: 991px) {
|
|
135
|
+
.hide-medium {
|
|
136
|
+
display: none;
|
|
137
|
+
width: 0 !important;
|
|
138
|
+
height: 0 !important;
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
@media (max-width: 767px) {
|
|
143
|
+
.hide-small {
|
|
144
|
+
display: none;
|
|
145
|
+
width: 0 !important;
|
|
146
|
+
height: 0 !important;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { MessageDirectionEnum, SenderRoleEnum, ValidMessageRolesEnum } from "./enums.js";
|
|
2
|
+
|
|
3
|
+
export function cookieMetaFactory(cookieName, cookieExpiration) {
|
|
4
|
+
/*
|
|
5
|
+
Create a cookie object.
|
|
6
|
+
*/
|
|
7
|
+
return {
|
|
8
|
+
name: cookieName,
|
|
9
|
+
expiration: cookieExpiration,
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export function chatRestoreFromBackend(chat_history, last_response) {
|
|
14
|
+
/*
|
|
15
|
+
Rebuild the message thread from the most recently persisted chat history.
|
|
16
|
+
*/
|
|
17
|
+
try {
|
|
18
|
+
const messages = (chat_history ? chat_history : [])
|
|
19
|
+
.map((chat) => {
|
|
20
|
+
if (chat.role === SenderRoleEnum.USER) {
|
|
21
|
+
return messageFactory(chat, chat.content, MessageDirectionEnum.OUTGOING, chat.role);
|
|
22
|
+
} else if (chat.role === SenderRoleEnum.SYSTEM) {
|
|
23
|
+
return messageFactory(chat, chat.content, MessageDirectionEnum.INCOMING, chat.role);
|
|
24
|
+
} else if (chat.role === SenderRoleEnum.ASSISTANT) {
|
|
25
|
+
return messageFactory(chat, chat.content, MessageDirectionEnum.INCOMING, chat.role);
|
|
26
|
+
} else if (chat.role === SenderRoleEnum.SMARTER) {
|
|
27
|
+
return messageFactory(chat, chat.content, MessageDirectionEnum.INCOMING, chat.role);
|
|
28
|
+
} else if (chat.role === SenderRoleEnum.TOOL) {
|
|
29
|
+
return messageFactory(chat, chat.content, MessageDirectionEnum.INCOMING, chat.role);
|
|
30
|
+
}
|
|
31
|
+
console.error(`chatRestoreFromBackend() Invalid role received: ${chat.role}`);
|
|
32
|
+
})
|
|
33
|
+
.filter((message) => message && typeof message === "object" && !Array.isArray(message));
|
|
34
|
+
|
|
35
|
+
if (last_response?.choices?.[0]?.message?.content) {
|
|
36
|
+
const last_message = last_response.choices[0].message;
|
|
37
|
+
const last_message_content = last_message.content;
|
|
38
|
+
messages.push(
|
|
39
|
+
messageFactory(last_message, last_message_content, MessageDirectionEnum.INCOMING, SenderRoleEnum.ASSISTANT),
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
return messages;
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error(`chatRestoreFromBackend() Error occurred while restoring chat from backend: ${error}`);
|
|
46
|
+
return []; // return an empty array in case of error
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const examplePrompts = (prompts) => {
|
|
51
|
+
/*
|
|
52
|
+
If we have no chat history, and the Application configuration includes
|
|
53
|
+
example prompts, we can display them to the user to help them get started.
|
|
54
|
+
*/
|
|
55
|
+
if (prompts.length == 0) {
|
|
56
|
+
return "";
|
|
57
|
+
} else
|
|
58
|
+
return (
|
|
59
|
+
"Some example prompts to get you started:\r\n\r\n" +
|
|
60
|
+
prompts
|
|
61
|
+
.map((prompt) => {
|
|
62
|
+
return prompt + "\r\n";
|
|
63
|
+
})
|
|
64
|
+
.join("")
|
|
65
|
+
);
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export function chatIntro(welcome_message, system_role, example_prompts) {
|
|
69
|
+
/*
|
|
70
|
+
Generate the initial message thread for the chat window. This includes the
|
|
71
|
+
welcome message, and any example prompts that are configured in the
|
|
72
|
+
Application settings.
|
|
73
|
+
*/
|
|
74
|
+
let messages = [messageFactory({}, system_role, MessageDirectionEnum.INCOMING, SenderRoleEnum.SYSTEM)];
|
|
75
|
+
messages.push(messageFactory({}, welcome_message, MessageDirectionEnum.INCOMING, SenderRoleEnum.ASSISTANT));
|
|
76
|
+
|
|
77
|
+
const examples = examplePrompts(example_prompts);
|
|
78
|
+
if (examples) {
|
|
79
|
+
messages.push(messageFactory({}, examples, MessageDirectionEnum.INCOMING, SenderRoleEnum.ASSISTANT));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return messages;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
export function convertMarkdownLinksToHTML(message) {
|
|
86
|
+
/*
|
|
87
|
+
Convert markdown links to HTML links.
|
|
88
|
+
*/
|
|
89
|
+
if (typeof message !== "string") {
|
|
90
|
+
console.error(`convertMarkdownLinksToHTML() Expected a string but received ${typeof message}`);
|
|
91
|
+
console.error("convertMarkdownLinksToHTML() broke here", message);
|
|
92
|
+
return message; // or return a default value
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
96
|
+
return message.replace(markdownLinkRegex, '<a href="$2">$1</a>');
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
export function messageFactory(originalMessage, content, direction, sender) {
|
|
100
|
+
/*
|
|
101
|
+
Create a new message object.
|
|
102
|
+
*/
|
|
103
|
+
const display = typeof content === "string" && content !== null;
|
|
104
|
+
const converted_content = display ? convertMarkdownLinksToHTML(content) : content;
|
|
105
|
+
const retVal = {
|
|
106
|
+
message: converted_content,
|
|
107
|
+
direction: direction,
|
|
108
|
+
sender: sender,
|
|
109
|
+
sentTime: new Date().toLocaleString(),
|
|
110
|
+
display: display,
|
|
111
|
+
};
|
|
112
|
+
if (originalMessage) {
|
|
113
|
+
retVal.originalMessage = originalMessage;
|
|
114
|
+
} else {
|
|
115
|
+
retVal.originalMessage = retVal;
|
|
116
|
+
}
|
|
117
|
+
return retVal;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
function requestMessageFactory(message) {
|
|
121
|
+
let retVal = message.originalMessage || {};
|
|
122
|
+
retVal.role = message.originalMessage && message.originalMessage.role ? message.originalMessage.role : message.sender;
|
|
123
|
+
retVal.content =
|
|
124
|
+
message.originalMessage && message.originalMessage.message ? message.originalMessage.message : message.message;
|
|
125
|
+
return retVal;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function chatMessages2RequestMessages(messages) {
|
|
129
|
+
/*
|
|
130
|
+
Transform the chat message thread into a list of request messages for the
|
|
131
|
+
backend API.
|
|
132
|
+
*/
|
|
133
|
+
return (
|
|
134
|
+
messages
|
|
135
|
+
// filter out smarter messages
|
|
136
|
+
.filter((message) => ValidMessageRolesEnum.includes(message.sender))
|
|
137
|
+
.map((message, index) => {
|
|
138
|
+
return requestMessageFactory(message);
|
|
139
|
+
})
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
export function chatInit(welcome_message, system_role, example_prompts, chat_id, chat_history, last_response) {
|
|
144
|
+
/*
|
|
145
|
+
Initialize the chat message thread. This function is called when the chat
|
|
146
|
+
window is first opened, or when the chat window is restored from the
|
|
147
|
+
backend.
|
|
148
|
+
*/
|
|
149
|
+
|
|
150
|
+
let messages = [];
|
|
151
|
+
messages = chatRestoreFromBackend(chat_history, last_response);
|
|
152
|
+
|
|
153
|
+
if (messages.length === 0) {
|
|
154
|
+
messages = chatIntro(welcome_message, system_role, example_prompts);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return messages;
|
|
158
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export { MessageDirectionEnum, SenderRoleEnum, ValidMessageRolesEnum } from "./SmarterChat/enums";
|