llmasaservice-ui 0.12.39 → 0.13.0
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/README.md +8 -0
- package/dist/index.css +31 -0
- package/dist/index.d.mts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +60 -3
- package/dist/index.mjs +60 -3
- package/package.json +2 -2
- package/src/ChatPanel.css +32 -0
- package/src/ChatPanel.tsx +78 -2
- package/src/stories/ChatPanel.stories.ts +28 -0
package/README.md
CHANGED
|
@@ -7,6 +7,7 @@ This library offers a pre-built panel for incorporating chat GPT style features
|
|
|
7
7
|
Features
|
|
8
8
|
- Multi-turn style chat interface
|
|
9
9
|
- Open with an initial prompt (for example, after a click on a Summarize button in your application, set the initialPrompt to "Summarize the following text ..." and the panel will automatically show the summary)
|
|
10
|
+
- New Conversation button to reset chat history while preserving customer information
|
|
10
11
|
- Light and dark theme
|
|
11
12
|
- Abort functionality
|
|
12
13
|
- Markdown response display
|
|
@@ -145,6 +146,13 @@ c) use prose as the class for the markdownStyle. This example is for dark mode
|
|
|
145
146
|
## Customization
|
|
146
147
|
You can customize the chat panel by passing props to the ChatPanel component. Refer to the library documentation for more details on available props and customization options.
|
|
147
148
|
|
|
149
|
+
### Button Controls
|
|
150
|
+
- `showSaveButton`: Show/hide the save conversation button (default: true)
|
|
151
|
+
- `showEmailButton`: Show/hide the email conversation button (default: true)
|
|
152
|
+
- `showNewConversationButton`: Show/hide the new conversation button (default: true)
|
|
153
|
+
|
|
154
|
+
The New Conversation button resets the chat history and state while preserving customer email and identification information. It requires two clicks for confirmation to prevent accidental resets - the first click changes the button to "Click to Confirm" and the second click performs the reset.
|
|
155
|
+
|
|
148
156
|
See our storybook documentation showing how to theme, size and use the variaous features in this component:
|
|
149
157
|
|
|
150
158
|
https://predictabilityatscale.github.io/llmasaservice-ui/?path=/docs/chatpanel--docs
|
package/dist/index.css
CHANGED
|
@@ -333,6 +333,37 @@
|
|
|
333
333
|
background-color: var(--button-background-color-hover);
|
|
334
334
|
color: var(--button-text-color-hover);
|
|
335
335
|
}
|
|
336
|
+
.llm-panel .new-conversation-button {
|
|
337
|
+
background-color: var(--prompt-background-color);
|
|
338
|
+
border-color: var(--button-border-color);
|
|
339
|
+
font-weight: 500;
|
|
340
|
+
}
|
|
341
|
+
.llm-panel .new-conversation-button:hover {
|
|
342
|
+
background-color: var(--button-background-color-hover);
|
|
343
|
+
color: var(--button-text-color-hover);
|
|
344
|
+
transform: translateY(-1px);
|
|
345
|
+
}
|
|
346
|
+
.llm-panel .new-conversation-button.confirm-state {
|
|
347
|
+
background-color: #ff6b35;
|
|
348
|
+
color: white;
|
|
349
|
+
border-color: #e55a2b;
|
|
350
|
+
animation: pulse-confirm 1s infinite;
|
|
351
|
+
}
|
|
352
|
+
.llm-panel .new-conversation-button.confirm-state:hover {
|
|
353
|
+
background-color: #e55a2b;
|
|
354
|
+
color: white;
|
|
355
|
+
}
|
|
356
|
+
@keyframes pulse-confirm {
|
|
357
|
+
0% {
|
|
358
|
+
opacity: 1;
|
|
359
|
+
}
|
|
360
|
+
50% {
|
|
361
|
+
opacity: 0.7;
|
|
362
|
+
}
|
|
363
|
+
100% {
|
|
364
|
+
opacity: 1;
|
|
365
|
+
}
|
|
366
|
+
}
|
|
336
367
|
.llm-panel .suggestion-button {
|
|
337
368
|
background-color: var(--button-background-color);
|
|
338
369
|
color: var(--button-text-color);
|
package/dist/index.d.mts
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -189,6 +189,7 @@ var ChatPanel = ({
|
|
|
189
189
|
actions,
|
|
190
190
|
showSaveButton = true,
|
|
191
191
|
showEmailButton = true,
|
|
192
|
+
showNewConversationButton = true,
|
|
192
193
|
followOnQuestions = [],
|
|
193
194
|
clearFollowOnQuestionsNextPrompt = false,
|
|
194
195
|
followOnPrompt = "",
|
|
@@ -247,6 +248,8 @@ var ChatPanel = ({
|
|
|
247
248
|
const [currentCustomer, setCurrentCustomer] = (0, import_react3.useState)(
|
|
248
249
|
customer
|
|
249
250
|
);
|
|
251
|
+
const [justReset, setJustReset] = (0, import_react3.useState)(false);
|
|
252
|
+
const [newConversationConfirm, setNewConversationConfirm] = (0, import_react3.useState)(false);
|
|
250
253
|
const [allActions, setAllActions] = (0, import_react3.useState)([]);
|
|
251
254
|
const [pendingToolRequests, setPendingToolRequests] = (0, import_react3.useState)([]);
|
|
252
255
|
const [followOnQuestionsState, setFollowOnQuestionsState] = (0, import_react3.useState)(followOnQuestions);
|
|
@@ -566,7 +569,7 @@ var ChatPanel = ({
|
|
|
566
569
|
});
|
|
567
570
|
fetchAndSetTools();
|
|
568
571
|
}, [mcpServers, publicAPIUrl]);
|
|
569
|
-
const { send, response, idle, stop, lastCallId } = (0, import_llmasaservice_client.useLLM)({
|
|
572
|
+
const { send, response, idle, stop, lastCallId, setResponse } = (0, import_llmasaservice_client.useLLM)({
|
|
570
573
|
project_id,
|
|
571
574
|
customer: currentCustomer,
|
|
572
575
|
url,
|
|
@@ -2004,7 +2007,7 @@ var ChatPanel = ({
|
|
|
2004
2007
|
var _a2, _b;
|
|
2005
2008
|
const isLastEntry = index === Object.keys(history).length - 1;
|
|
2006
2009
|
const hasToolData = !!((((_a2 = historyEntry == null ? void 0 : historyEntry.toolCalls) == null ? void 0 : _a2.length) || 0) > 0 || (((_b = historyEntry == null ? void 0 : historyEntry.toolResponses) == null ? void 0 : _b.length) || 0) > 0);
|
|
2007
|
-
return /* @__PURE__ */ import_react3.default.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ import_react3.default.createElement("div", { className: "prompt" }, formatPromptForDisplay(prompt)), /* @__PURE__ */ import_react3.default.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && (isLoading || !idle) ? /* @__PURE__ */ import_react3.default.createElement("div", { className: "streaming-response" }, (() => {
|
|
2010
|
+
return /* @__PURE__ */ import_react3.default.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ import_react3.default.createElement("div", { className: "prompt" }, formatPromptForDisplay(prompt)), /* @__PURE__ */ import_react3.default.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && (isLoading || !idle) && !justReset ? /* @__PURE__ */ import_react3.default.createElement("div", { className: "streaming-response" }, (() => {
|
|
2008
2011
|
const { cleanedText } = processThinkingTags(
|
|
2009
2012
|
response || ""
|
|
2010
2013
|
);
|
|
@@ -2249,7 +2252,61 @@ var ChatPanel = ({
|
|
|
2249
2252
|
},
|
|
2250
2253
|
"\u270E"
|
|
2251
2254
|
))),
|
|
2252
|
-
/* @__PURE__ */ import_react3.default.createElement("div", { className: "button-container-actions" },
|
|
2255
|
+
/* @__PURE__ */ import_react3.default.createElement("div", { className: "button-container-actions" }, showNewConversationButton && /* @__PURE__ */ import_react3.default.createElement(
|
|
2256
|
+
"button",
|
|
2257
|
+
{
|
|
2258
|
+
className: `save-button new-conversation-button ${newConversationConfirm ? "confirm-state" : ""}`,
|
|
2259
|
+
onClick: () => {
|
|
2260
|
+
if (!newConversationConfirm) {
|
|
2261
|
+
setNewConversationConfirm(true);
|
|
2262
|
+
setTimeout(() => {
|
|
2263
|
+
setNewConversationConfirm(false);
|
|
2264
|
+
}, 3e3);
|
|
2265
|
+
} else {
|
|
2266
|
+
setNewConversationConfirm(false);
|
|
2267
|
+
if (!idle) {
|
|
2268
|
+
stop(lastController);
|
|
2269
|
+
}
|
|
2270
|
+
setResponse("");
|
|
2271
|
+
setHistory({});
|
|
2272
|
+
setLastMessages([]);
|
|
2273
|
+
setNextPrompt("");
|
|
2274
|
+
setLastPrompt(null);
|
|
2275
|
+
setLastKey(null);
|
|
2276
|
+
setIsLoading(false);
|
|
2277
|
+
setCurrentConversation(null);
|
|
2278
|
+
setCallToActionSent(false);
|
|
2279
|
+
setEmailSent(false);
|
|
2280
|
+
setCTAClickedButNoEmail(false);
|
|
2281
|
+
setEmailClickedButNoEmail(false);
|
|
2282
|
+
setFollowOnQuestionsState(followOnQuestions);
|
|
2283
|
+
setSessionApprovedTools([]);
|
|
2284
|
+
setThinkingBlocks([]);
|
|
2285
|
+
setCurrentThinkingIndex(0);
|
|
2286
|
+
setPendingButtonAttachments([]);
|
|
2287
|
+
setPendingToolRequests([]);
|
|
2288
|
+
setIsEmailModalOpen(false);
|
|
2289
|
+
setIsToolInfoModalOpen(false);
|
|
2290
|
+
setToolInfoData(null);
|
|
2291
|
+
setJustReset(true);
|
|
2292
|
+
setLastController(new AbortController());
|
|
2293
|
+
buttonActionRegistry.current.clear();
|
|
2294
|
+
setTimeout(() => {
|
|
2295
|
+
setJustReset(false);
|
|
2296
|
+
const responseArea = responseAreaRef.current;
|
|
2297
|
+
if (responseArea) {
|
|
2298
|
+
responseArea.scrollTo({
|
|
2299
|
+
top: 0,
|
|
2300
|
+
behavior: "smooth"
|
|
2301
|
+
});
|
|
2302
|
+
}
|
|
2303
|
+
}, 100);
|
|
2304
|
+
}
|
|
2305
|
+
},
|
|
2306
|
+
title: newConversationConfirm ? "Click again to confirm reset" : "Start a new conversation"
|
|
2307
|
+
},
|
|
2308
|
+
newConversationConfirm ? "Click to Confirm" : "New Conversation"
|
|
2309
|
+
), showSaveButton && /* @__PURE__ */ import_react3.default.createElement(
|
|
2253
2310
|
"button",
|
|
2254
2311
|
{
|
|
2255
2312
|
className: "save-button",
|
package/dist/index.mjs
CHANGED
|
@@ -161,6 +161,7 @@ var ChatPanel = ({
|
|
|
161
161
|
actions,
|
|
162
162
|
showSaveButton = true,
|
|
163
163
|
showEmailButton = true,
|
|
164
|
+
showNewConversationButton = true,
|
|
164
165
|
followOnQuestions = [],
|
|
165
166
|
clearFollowOnQuestionsNextPrompt = false,
|
|
166
167
|
followOnPrompt = "",
|
|
@@ -219,6 +220,8 @@ var ChatPanel = ({
|
|
|
219
220
|
const [currentCustomer, setCurrentCustomer] = useState2(
|
|
220
221
|
customer
|
|
221
222
|
);
|
|
223
|
+
const [justReset, setJustReset] = useState2(false);
|
|
224
|
+
const [newConversationConfirm, setNewConversationConfirm] = useState2(false);
|
|
222
225
|
const [allActions, setAllActions] = useState2([]);
|
|
223
226
|
const [pendingToolRequests, setPendingToolRequests] = useState2([]);
|
|
224
227
|
const [followOnQuestionsState, setFollowOnQuestionsState] = useState2(followOnQuestions);
|
|
@@ -538,7 +541,7 @@ var ChatPanel = ({
|
|
|
538
541
|
});
|
|
539
542
|
fetchAndSetTools();
|
|
540
543
|
}, [mcpServers, publicAPIUrl]);
|
|
541
|
-
const { send, response, idle, stop, lastCallId } = useLLM({
|
|
544
|
+
const { send, response, idle, stop, lastCallId, setResponse } = useLLM({
|
|
542
545
|
project_id,
|
|
543
546
|
customer: currentCustomer,
|
|
544
547
|
url,
|
|
@@ -1976,7 +1979,7 @@ var ChatPanel = ({
|
|
|
1976
1979
|
var _a2, _b;
|
|
1977
1980
|
const isLastEntry = index === Object.keys(history).length - 1;
|
|
1978
1981
|
const hasToolData = !!((((_a2 = historyEntry == null ? void 0 : historyEntry.toolCalls) == null ? void 0 : _a2.length) || 0) > 0 || (((_b = historyEntry == null ? void 0 : historyEntry.toolResponses) == null ? void 0 : _b.length) || 0) > 0);
|
|
1979
|
-
return /* @__PURE__ */ React3.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ React3.createElement("div", { className: "prompt" }, formatPromptForDisplay(prompt)), /* @__PURE__ */ React3.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && (isLoading || !idle) ? /* @__PURE__ */ React3.createElement("div", { className: "streaming-response" }, (() => {
|
|
1982
|
+
return /* @__PURE__ */ React3.createElement("div", { className: "history-entry", key: index }, hideInitialPrompt && index === 0 ? null : /* @__PURE__ */ React3.createElement("div", { className: "prompt" }, formatPromptForDisplay(prompt)), /* @__PURE__ */ React3.createElement("div", { className: "response" }, index === Object.keys(history).length - 1 && (isLoading || !idle) && !justReset ? /* @__PURE__ */ React3.createElement("div", { className: "streaming-response" }, (() => {
|
|
1980
1983
|
const { cleanedText } = processThinkingTags(
|
|
1981
1984
|
response || ""
|
|
1982
1985
|
);
|
|
@@ -2221,7 +2224,61 @@ var ChatPanel = ({
|
|
|
2221
2224
|
},
|
|
2222
2225
|
"\u270E"
|
|
2223
2226
|
))),
|
|
2224
|
-
/* @__PURE__ */ React3.createElement("div", { className: "button-container-actions" },
|
|
2227
|
+
/* @__PURE__ */ React3.createElement("div", { className: "button-container-actions" }, showNewConversationButton && /* @__PURE__ */ React3.createElement(
|
|
2228
|
+
"button",
|
|
2229
|
+
{
|
|
2230
|
+
className: `save-button new-conversation-button ${newConversationConfirm ? "confirm-state" : ""}`,
|
|
2231
|
+
onClick: () => {
|
|
2232
|
+
if (!newConversationConfirm) {
|
|
2233
|
+
setNewConversationConfirm(true);
|
|
2234
|
+
setTimeout(() => {
|
|
2235
|
+
setNewConversationConfirm(false);
|
|
2236
|
+
}, 3e3);
|
|
2237
|
+
} else {
|
|
2238
|
+
setNewConversationConfirm(false);
|
|
2239
|
+
if (!idle) {
|
|
2240
|
+
stop(lastController);
|
|
2241
|
+
}
|
|
2242
|
+
setResponse("");
|
|
2243
|
+
setHistory({});
|
|
2244
|
+
setLastMessages([]);
|
|
2245
|
+
setNextPrompt("");
|
|
2246
|
+
setLastPrompt(null);
|
|
2247
|
+
setLastKey(null);
|
|
2248
|
+
setIsLoading(false);
|
|
2249
|
+
setCurrentConversation(null);
|
|
2250
|
+
setCallToActionSent(false);
|
|
2251
|
+
setEmailSent(false);
|
|
2252
|
+
setCTAClickedButNoEmail(false);
|
|
2253
|
+
setEmailClickedButNoEmail(false);
|
|
2254
|
+
setFollowOnQuestionsState(followOnQuestions);
|
|
2255
|
+
setSessionApprovedTools([]);
|
|
2256
|
+
setThinkingBlocks([]);
|
|
2257
|
+
setCurrentThinkingIndex(0);
|
|
2258
|
+
setPendingButtonAttachments([]);
|
|
2259
|
+
setPendingToolRequests([]);
|
|
2260
|
+
setIsEmailModalOpen(false);
|
|
2261
|
+
setIsToolInfoModalOpen(false);
|
|
2262
|
+
setToolInfoData(null);
|
|
2263
|
+
setJustReset(true);
|
|
2264
|
+
setLastController(new AbortController());
|
|
2265
|
+
buttonActionRegistry.current.clear();
|
|
2266
|
+
setTimeout(() => {
|
|
2267
|
+
setJustReset(false);
|
|
2268
|
+
const responseArea = responseAreaRef.current;
|
|
2269
|
+
if (responseArea) {
|
|
2270
|
+
responseArea.scrollTo({
|
|
2271
|
+
top: 0,
|
|
2272
|
+
behavior: "smooth"
|
|
2273
|
+
});
|
|
2274
|
+
}
|
|
2275
|
+
}, 100);
|
|
2276
|
+
}
|
|
2277
|
+
},
|
|
2278
|
+
title: newConversationConfirm ? "Click again to confirm reset" : "Start a new conversation"
|
|
2279
|
+
},
|
|
2280
|
+
newConversationConfirm ? "Click to Confirm" : "New Conversation"
|
|
2281
|
+
), showSaveButton && /* @__PURE__ */ React3.createElement(
|
|
2225
2282
|
"button",
|
|
2226
2283
|
{
|
|
2227
2284
|
className: "save-button",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "llmasaservice-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.13.0",
|
|
4
4
|
"description": "Prebuilt UI components for LLMAsAService.io",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"module": "dist/index.mjs",
|
|
@@ -47,7 +47,7 @@
|
|
|
47
47
|
"dependencies": {
|
|
48
48
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
49
49
|
"dotenv": "^16.4.7",
|
|
50
|
-
"llmasaservice-client": "^0.10.
|
|
50
|
+
"llmasaservice-client": "^0.10.1",
|
|
51
51
|
"process": "^0.11.10",
|
|
52
52
|
"react-markdown": "^9.0.1",
|
|
53
53
|
"react-syntax-highlighter": "^15.5.0",
|
package/src/ChatPanel.css
CHANGED
|
@@ -412,6 +412,38 @@
|
|
|
412
412
|
color: var(--button-text-color-hover);
|
|
413
413
|
}
|
|
414
414
|
|
|
415
|
+
/* New Conversation Button - distinct styling */
|
|
416
|
+
.llm-panel .new-conversation-button {
|
|
417
|
+
background-color: var(--prompt-background-color);
|
|
418
|
+
border-color: var(--button-border-color);
|
|
419
|
+
font-weight: 500;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.llm-panel .new-conversation-button:hover {
|
|
423
|
+
background-color: var(--button-background-color-hover);
|
|
424
|
+
color: var(--button-text-color-hover);
|
|
425
|
+
transform: translateY(-1px);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
/* Confirmation state styling */
|
|
429
|
+
.llm-panel .new-conversation-button.confirm-state {
|
|
430
|
+
background-color: #ff6b35;
|
|
431
|
+
color: white;
|
|
432
|
+
border-color: #e55a2b;
|
|
433
|
+
animation: pulse-confirm 1s infinite;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
.llm-panel .new-conversation-button.confirm-state:hover {
|
|
437
|
+
background-color: #e55a2b;
|
|
438
|
+
color: white;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
@keyframes pulse-confirm {
|
|
442
|
+
0% { opacity: 1; }
|
|
443
|
+
50% { opacity: 0.7; }
|
|
444
|
+
100% { opacity: 1; }
|
|
445
|
+
}
|
|
446
|
+
|
|
415
447
|
/* Suggestion Buttons */
|
|
416
448
|
.llm-panel .suggestion-button {
|
|
417
449
|
background-color: var(--button-background-color);
|
package/src/ChatPanel.tsx
CHANGED
|
@@ -59,6 +59,7 @@ export interface ChatPanelProps {
|
|
|
59
59
|
}[];
|
|
60
60
|
showSaveButton?: boolean;
|
|
61
61
|
showEmailButton?: boolean;
|
|
62
|
+
showNewConversationButton?: boolean;
|
|
62
63
|
followOnQuestions?: string[];
|
|
63
64
|
clearFollowOnQuestionsNextPrompt?: boolean;
|
|
64
65
|
followOnPrompt?: string;
|
|
@@ -117,6 +118,7 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
|
|
|
117
118
|
actions,
|
|
118
119
|
showSaveButton = true,
|
|
119
120
|
showEmailButton = true,
|
|
121
|
+
showNewConversationButton = true,
|
|
120
122
|
followOnQuestions = [],
|
|
121
123
|
clearFollowOnQuestionsNextPrompt = false,
|
|
122
124
|
followOnPrompt = "",
|
|
@@ -179,6 +181,8 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
|
|
|
179
181
|
const [currentCustomer, setCurrentCustomer] = useState<LLMAsAServiceCustomer>(
|
|
180
182
|
customer as LLMAsAServiceCustomer
|
|
181
183
|
);
|
|
184
|
+
const [justReset, setJustReset] = useState(false);
|
|
185
|
+
const [newConversationConfirm, setNewConversationConfirm] = useState(false);
|
|
182
186
|
const [allActions, setAllActions] = useState<
|
|
183
187
|
{
|
|
184
188
|
pattern: string;
|
|
@@ -658,7 +662,7 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
|
|
|
658
662
|
fetchAndSetTools();
|
|
659
663
|
}, [mcpServers, publicAPIUrl]);
|
|
660
664
|
|
|
661
|
-
const { send, response, idle, stop, lastCallId } = useLLM({
|
|
665
|
+
const { send, response, idle, stop, lastCallId, setResponse } = useLLM({
|
|
662
666
|
project_id: project_id,
|
|
663
667
|
customer: currentCustomer,
|
|
664
668
|
url: url,
|
|
@@ -2485,7 +2489,7 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
|
|
|
2485
2489
|
<div className="response">
|
|
2486
2490
|
{/* Show streaming response with thinking blocks displayed separately */}
|
|
2487
2491
|
{index === Object.keys(history).length - 1 &&
|
|
2488
|
-
(isLoading || !idle) ? (
|
|
2492
|
+
(isLoading || !idle) && !justReset ? (
|
|
2489
2493
|
<div className="streaming-response">
|
|
2490
2494
|
{/* Display current thinking block or thinking message */}
|
|
2491
2495
|
{(() => {
|
|
@@ -2850,6 +2854,78 @@ const ChatPanel: React.FC<ChatPanelProps & ExtraProps> = ({
|
|
|
2850
2854
|
</>
|
|
2851
2855
|
)}
|
|
2852
2856
|
<div className="button-container-actions">
|
|
2857
|
+
{showNewConversationButton && (
|
|
2858
|
+
<button
|
|
2859
|
+
className={`save-button new-conversation-button ${newConversationConfirm ? 'confirm-state' : ''}`}
|
|
2860
|
+
onClick={() => {
|
|
2861
|
+
if (!newConversationConfirm) {
|
|
2862
|
+
// First click - show confirmation state
|
|
2863
|
+
setNewConversationConfirm(true);
|
|
2864
|
+
|
|
2865
|
+
// Auto-reset confirmation after 3 seconds
|
|
2866
|
+
setTimeout(() => {
|
|
2867
|
+
setNewConversationConfirm(false);
|
|
2868
|
+
}, 3000);
|
|
2869
|
+
} else {
|
|
2870
|
+
// Second click - proceed with reset
|
|
2871
|
+
setNewConversationConfirm(false);
|
|
2872
|
+
|
|
2873
|
+
// Stop any current request first
|
|
2874
|
+
if (!idle) {
|
|
2875
|
+
stop(lastController);
|
|
2876
|
+
}
|
|
2877
|
+
|
|
2878
|
+
// Clear the current response from useLLM hook
|
|
2879
|
+
setResponse("");
|
|
2880
|
+
|
|
2881
|
+
// Reset conversation state while preserving customer info
|
|
2882
|
+
setHistory({});
|
|
2883
|
+
setLastMessages([]);
|
|
2884
|
+
setNextPrompt("");
|
|
2885
|
+
setLastPrompt(null);
|
|
2886
|
+
setLastKey(null);
|
|
2887
|
+
setIsLoading(false);
|
|
2888
|
+
setCurrentConversation(null);
|
|
2889
|
+
setCallToActionSent(false);
|
|
2890
|
+
setEmailSent(false);
|
|
2891
|
+
setCTAClickedButNoEmail(false);
|
|
2892
|
+
setEmailClickedButNoEmail(false);
|
|
2893
|
+
setFollowOnQuestionsState(followOnQuestions);
|
|
2894
|
+
setSessionApprovedTools([]);
|
|
2895
|
+
setThinkingBlocks([]);
|
|
2896
|
+
setCurrentThinkingIndex(0);
|
|
2897
|
+
setPendingButtonAttachments([]);
|
|
2898
|
+
setPendingToolRequests([]);
|
|
2899
|
+
setIsEmailModalOpen(false);
|
|
2900
|
+
setIsToolInfoModalOpen(false);
|
|
2901
|
+
setToolInfoData(null);
|
|
2902
|
+
setJustReset(true);
|
|
2903
|
+
|
|
2904
|
+
// Create a new AbortController for future requests
|
|
2905
|
+
setLastController(new AbortController());
|
|
2906
|
+
|
|
2907
|
+
// Clear button registry for new conversation
|
|
2908
|
+
buttonActionRegistry.current.clear();
|
|
2909
|
+
|
|
2910
|
+
// Force a small delay to ensure all state updates are processed
|
|
2911
|
+
setTimeout(() => {
|
|
2912
|
+
setJustReset(false);
|
|
2913
|
+
// Scroll to top after state updates
|
|
2914
|
+
const responseArea = responseAreaRef.current as any;
|
|
2915
|
+
if (responseArea) {
|
|
2916
|
+
responseArea.scrollTo({
|
|
2917
|
+
top: 0,
|
|
2918
|
+
behavior: "smooth",
|
|
2919
|
+
});
|
|
2920
|
+
}
|
|
2921
|
+
}, 100);
|
|
2922
|
+
}
|
|
2923
|
+
}}
|
|
2924
|
+
title={newConversationConfirm ? "Click again to confirm reset" : "Start a new conversation"}
|
|
2925
|
+
>
|
|
2926
|
+
{newConversationConfirm ? "Click to Confirm" : "New Conversation"}
|
|
2927
|
+
</button>
|
|
2928
|
+
)}
|
|
2853
2929
|
{showSaveButton && (
|
|
2854
2930
|
<button
|
|
2855
2931
|
className="save-button"
|
|
@@ -29,6 +29,34 @@ export const ChatPanelStory: Story = {
|
|
|
29
29
|
},
|
|
30
30
|
};
|
|
31
31
|
|
|
32
|
+
export const ChatPanelWithNewConversationButton: Story = {
|
|
33
|
+
args: {
|
|
34
|
+
title: "Chat Panel with New Conversation Button",
|
|
35
|
+
project_id: "[get this from your control panel]",
|
|
36
|
+
initialPrompt: "Hello! How can I help you today?",
|
|
37
|
+
hideInitialPrompt: false,
|
|
38
|
+
placeholder: "Type your message here...",
|
|
39
|
+
theme: "light",
|
|
40
|
+
messages: [
|
|
41
|
+
{ role: "assistant", content: "Welcome! This conversation has some history." },
|
|
42
|
+
{ role: "user", content: "Tell me about the weather" },
|
|
43
|
+
{ role: "assistant", content: "I'd be happy to help with weather information. However, I don't have access to real-time weather data. You might want to check a weather service like Weather.com or use a weather app on your device." }
|
|
44
|
+
],
|
|
45
|
+
width: "400px",
|
|
46
|
+
height: "600px",
|
|
47
|
+
showNewConversationButton: true,
|
|
48
|
+
showSaveButton: true,
|
|
49
|
+
showEmailButton: true,
|
|
50
|
+
initialMessage: "Try clicking the 'New Conversation' button - it requires two clicks to confirm the reset and prevent accidental conversation clearing!",
|
|
51
|
+
initialHistory: {
|
|
52
|
+
"Hello! How can I help you today?": {
|
|
53
|
+
content: "Welcome! This is a test conversation with some existing history. The 'New Conversation' button now requires double-click confirmation to prevent accidental resets.",
|
|
54
|
+
callId: "test-call-1"
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
},
|
|
58
|
+
};
|
|
59
|
+
|
|
32
60
|
export const ChatPanelThumbsStory: Story = {
|
|
33
61
|
args: {
|
|
34
62
|
title: "Chat",
|