Skip to content

Commit

Permalink
Merge pull request #6 from nlxai/failure-message-revamp
Browse files Browse the repository at this point in the history
Add separate handling for failure messages
  • Loading branch information
peterszerzo authored Jan 2, 2024
2 parents 45cf3de + 68a0153 commit 5175eb1
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 158 deletions.
50 changes: 16 additions & 34 deletions packages/chat-core/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,17 @@ export type UserResponsePayload =
context?: Context;
} & StructuredRequest);

export type Response = BotResponse | UserResponse;
// Failure message

export interface FailureMessage {
type: "failure";
payload: {
text: string;
};
receivedAt: Time;
}

export type Response = BotResponse | UserResponse | FailureMessage;

export type Time = number;

Expand All @@ -88,8 +98,7 @@ export interface Config {
conversationId?: string;
userId?: string;
responses?: Response[];
failureMessages?: string[];
greetingMessages?: string[];
failureMessage?: string;
environment?: Environment;
headers?: {
[key: string]: string;
Expand All @@ -106,9 +115,7 @@ export interface Config {

const welcomeIntent = "NLX.Welcome";

const defaultFailureMessages = [
"We encountered an issue. Please try again soon.",
];
const defaultFailureMessage = "We encountered an issue. Please try again soon.";

export type State = Response[];

Expand Down Expand Up @@ -214,27 +221,7 @@ export const createConversation = (config: Config): ConversationHandler => {
const initialConversationId = config.conversationId || uuid();

let state: InternalState = {
responses:
config.responses ||
(config.greetingMessages && config.greetingMessages.length > 0
? [
{
type: "bot",
receivedAt: new Date().getTime(),
payload: {
conversationId: initialConversationId,
messages: config.greetingMessages.map(
(greetingMessage: string) => ({
messageId: undefined,
text: greetingMessage,
choices: [] as Array<Choice>,
selectedChoiceId: undefined,
}),
),
},
},
]
: []),
responses: config.responses || [],
userId: config.userId,
conversationId: initialConversationId,
};
Expand All @@ -255,15 +242,10 @@ export const createConversation = (config: Config): ConversationHandler => {

const failureHandler = () => {
const newResponse: Response = {
type: "bot",
type: "failure",
receivedAt: new Date().getTime(),
payload: {
messages: (config.failureMessages || defaultFailureMessages).map(
(messageBody: string): BotMessage => ({
text: messageBody,
choices: [] as Array<Choice>,
}),
),
text: config.failureMessage || defaultFailureMessage,
},
};
setState(
Expand Down
6 changes: 6 additions & 0 deletions packages/chat-widget/src/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,3 +23,9 @@ export const DownloadIcon = () => (
<path d="M320,320.496l-280,0l0,-40l280,0l0,40Zm-120,-148.284l40,-40c9.428,9.428 18.856,18.856 28.284,28.284l-88.284,88.284l-28.284,-28.284l0,0l-60,-60l28.284,-28.284l40,40l0,-131.716l40,0l0,131.716Z" />
</svg>
);

export const ErrorOutlineIcon = () => (
<svg viewBox="0 0 24 24" stroke="none" fill="currentColor">
<path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z" />
</svg>
);
136 changes: 76 additions & 60 deletions packages/chat-widget/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import { createRoot } from "react-dom/client";
import { ThemeProvider } from "@emotion/react";
import { useChat, type ChatHook } from "@nlxai/chat-react";
import { type Response, type ConversationHandler } from "@nlxai/chat-core";
import { CloseIcon, ChatIcon, AirplaneIcon } from "./icons";
import { CloseIcon, ChatIcon, AirplaneIcon, ErrorOutlineIcon } from "./icons";
import * as constants from "./ui/constants";
import {
type Props,
Expand Down Expand Up @@ -110,70 +110,86 @@ const MessageGroups: FC<{
customModalities: Record<string, CustomModalityComponent>;
}> = (props) => (
<C.MessageGroups>
{props.chat.responses.map((response, responseIndex) =>
response.type === "bot" ? (
<C.MessageGroup key={responseIndex}>
{response.payload.messages.map((botMessage, botMessageIndex) => (
<C.Message type="bot" key={botMessageIndex}>
{props.chat.responses.map((response, responseIndex) => {
if (response.type === "bot") {
return (
<C.MessageGroup key={responseIndex}>
{response.payload.messages.map((botMessage, botMessageIndex) => (
<C.Message type="bot" key={botMessageIndex}>
<C.MessageBody
dangerouslySetInnerHTML={{
__html: marked(botMessage.text),
}}
/>
{botMessage.choices.length > 0 && (
<C.ChoicesContainer>
{botMessage.choices.map((choice, choiceIndex) => (
<C.ChoiceButton
key={choiceIndex}
{...(() => {
return botMessage.selectedChoiceId
? {
disabled: true,
selected:
botMessage.selectedChoiceId ===
choice.choiceId,
}
: {
onClick: () => {
props.chat.conversationHandler.sendChoice(
choice.choiceId,
);
},
};
})()}
dangerouslySetInnerHTML={{
__html: marked(
choice.choiceText +
(false ? " asdf fadsfds fdsa fdsa fdsa " : ""),
),
}}
></C.ChoiceButton>
))}
</C.ChoicesContainer>
)}
</C.Message>
))}
{Object.entries(response.payload.modalities || {}).map(
([key, value]) => {
const Component = props.customModalities[key];
if (Component) {
return <Component key={key} data={value} />;
}
return null;
},
)}
</C.MessageGroup>
);
}

if (response.type === "failure") {
return (
<C.FailureMessage key={responseIndex}>
<ErrorOutlineIcon />
<span>{response.payload.text}</span>
</C.FailureMessage>
);
}

if (response.type === "user" && response.payload.type === "text") {
return (
<C.MessageGroup key={responseIndex}>
<C.Message type="user">
<C.MessageBody
dangerouslySetInnerHTML={{
__html: marked(botMessage.text),
__html: marked(response.payload.text),
}}
/>
{botMessage.choices.length > 0 && (
<C.ChoicesContainer>
{botMessage.choices.map((choice, choiceIndex) => (
<C.ChoiceButton
key={choiceIndex}
{...(() => {
return botMessage.selectedChoiceId
? {
disabled: true,
selected:
botMessage.selectedChoiceId === choice.choiceId,
}
: {
onClick: () => {
props.chat.conversationHandler.sendChoice(
choice.choiceId,
);
},
};
})()}
dangerouslySetInnerHTML={{
__html: marked(
choice.choiceText +
(false ? " asdf fadsfds fdsa fdsa fdsa " : ""),
),
}}
></C.ChoiceButton>
))}
</C.ChoicesContainer>
)}
</C.Message>
))}
{Object.entries(response.payload.modalities || {}).map(
([key, value]) => {
const Component = props.customModalities[key];
if (Component) {
return <Component key={key} data={value} />;
}
return null;
},
)}
</C.MessageGroup>
) : response.payload.type === "text" ? (
<C.MessageGroup key={responseIndex}>
<C.Message type="user">
<C.MessageBody
dangerouslySetInnerHTML={{
__html: marked(response.payload.text),
}}
/>
</C.Message>
</C.MessageGroup>
) : null,
)}
</C.MessageGroup>
);
}
})}
{props.children}
</C.MessageGroups>
);
Expand Down
Loading

0 comments on commit 5175eb1

Please sign in to comment.