+
{endpoint && Icon && (
{
+ (data: string | undefined, submission: TSubmission) => {
const {
messages,
userMessage,
@@ -80,13 +82,20 @@ export default function useEventHandlers({
initialResponse,
isRegenerate = false,
} = submission;
+ const text = data ?? '';
+ if (text.length > 0) {
+ announcePolite({
+ message: text,
+ isStream: true,
+ });
+ }
if (isRegenerate) {
setMessages([
...messages,
{
...initialResponse,
- text: data,
+ text,
plugin: plugin ?? null,
plugins: plugins ?? [],
// unfinished: true
@@ -98,7 +107,7 @@ export default function useEventHandlers({
userMessage,
{
...initialResponse,
- text: data,
+ text,
plugin: plugin ?? null,
plugins: plugins ?? [],
// unfinished: true
@@ -106,7 +115,7 @@ export default function useEventHandlers({
]);
}
},
- [setMessages],
+ [setMessages, announcePolite],
);
const cancelHandler = useCallback(
@@ -136,7 +145,7 @@ export default function useEventHandlers({
}
// refresh title
- if (genTitle && isNewConvo && requestMessage?.parentMessageId === Constants.NO_PARENT) {
+ if (genTitle && isNewConvo && requestMessage.parentMessageId === Constants.NO_PARENT) {
setTimeout(() => {
genTitle.mutate({ conversationId: convoUpdate.conversationId as string });
}, 2500);
@@ -238,8 +247,8 @@ export default function useEventHandlers({
const { messages, userMessage, isRegenerate = false } = submission;
const initialResponse = {
...submission.initialResponse,
- parentMessageId: userMessage?.messageId,
- messageId: userMessage?.messageId + '_',
+ parentMessageId: userMessage.messageId,
+ messageId: userMessage.messageId + '_',
};
if (isRegenerate) {
setMessages([...messages, initialResponse]);
@@ -248,12 +257,16 @@ export default function useEventHandlers({
}
const { conversationId, parentMessageId } = userMessage;
+ announceAssertive({
+ message: 'The AI is generating a response.',
+ id: `ai-generating-${Date.now()}`,
+ });
let update = {} as TConversation;
if (setConversation && !isAddedRequest) {
setConversation((prevState) => {
let title = prevState?.title;
- const parentId = isRegenerate ? userMessage?.overrideParentMessageId : parentMessageId;
+ const parentId = isRegenerate ? userMessage.overrideParentMessageId : parentMessageId;
if (parentId !== Constants.NO_PARENT && title?.toLowerCase()?.includes('new chat')) {
const convos = queryClient.getQueryData([QueryKeys.allConversations]);
const cachedConvo = getConversationById(convos, conversationId);
@@ -295,7 +308,14 @@ export default function useEventHandlers({
scrollToEnd();
},
- [setMessages, setConversation, queryClient, isAddedRequest, resetLatestMessage],
+ [
+ setMessages,
+ setConversation,
+ queryClient,
+ isAddedRequest,
+ resetLatestMessage,
+ announceAssertive,
+ ],
);
const finalHandler = useCallback(
@@ -304,7 +324,7 @@ export default function useEventHandlers({
const { messages, conversation: submissionConvo, isRegenerate = false } = submission;
setShowStopButton(false);
- setCompleted((prev) => new Set(prev.add(submission?.initialResponse?.messageId)));
+ setCompleted((prev) => new Set(prev.add(submission.initialResponse.messageId)));
const currentMessages = getMessages();
// Early return if messages are empty; i.e., the user navigated away
@@ -312,6 +332,19 @@ export default function useEventHandlers({
return setIsSubmitting(false);
}
+ /* a11y announcements */
+ announcePolite({
+ message: '',
+ isComplete: true,
+ });
+
+ setTimeout(() => {
+ announcePolite({
+ message: 'The AI has finished generating a response.',
+ id: `ai-finished-${Date.now()}`,
+ });
+ }, 100);
+
// update the messages; if assistants endpoint, client doesn't receive responseMessage
if (runMessages) {
setMessages([...runMessages]);
@@ -367,6 +400,7 @@ export default function useEventHandlers({
setMessages,
setCompleted,
isAddedRequest,
+ announcePolite,
setConversation,
setIsSubmitting,
setShowStopButton,
@@ -379,7 +413,7 @@ export default function useEventHandlers({
setCompleted((prev) => new Set(prev.add(initialResponse.messageId)));
- const conversationId = userMessage?.conversationId ?? submission?.conversationId;
+ const conversationId = userMessage.conversationId ?? submission.conversationId;
const parseErrorResponse = (data: TResData | Partial) => {
const metadata = data['responseMessage'] ?? data;
@@ -387,7 +421,7 @@ export default function useEventHandlers({
...initialResponse,
...metadata,
error: true,
- parentMessageId: userMessage?.messageId,
+ parentMessageId: userMessage.messageId,
};
if (!errorMessage.messageId) {
@@ -408,7 +442,7 @@ export default function useEventHandlers({
if (newConversation) {
newConversation({
template: { conversationId: convoId },
- preset: tPresetSchema.parse(submission?.conversation),
+ preset: tPresetSchema.parse(submission.conversation),
});
}
setIsSubmitting(false);
@@ -422,7 +456,7 @@ export default function useEventHandlers({
if (newConversation) {
newConversation({
template: { conversationId: convoId },
- preset: tPresetSchema.parse(submission?.conversation),
+ preset: tPresetSchema.parse(submission.conversation),
});
}
setIsSubmitting(false);
@@ -438,14 +472,14 @@ export default function useEventHandlers({
const errorResponse = tMessageSchema.parse({
...data,
error: true,
- parentMessageId: userMessage?.messageId,
+ parentMessageId: userMessage.messageId,
});
setMessages([...messages, userMessage, errorResponse]);
if (data.conversationId && paramId === 'new' && newConversation) {
newConversation({
template: { conversationId: data.conversationId },
- preset: tPresetSchema.parse(submission?.conversation),
+ preset: tPresetSchema.parse(submission.conversation),
});
}
@@ -459,7 +493,7 @@ export default function useEventHandlers({
async (conversationId = '', submission: TSubmission, messages?: TMessage[]) => {
const runAbortKey = `${conversationId}:${messages?.[messages.length - 1]?.messageId ?? ''}`;
console.log({ conversationId, submission, messages, runAbortKey });
- const { endpoint: _endpoint, endpointType } = submission?.conversation || {};
+ const { endpoint: _endpoint, endpointType } = submission.conversation || {};
const endpoint = endpointType ?? _endpoint;
try {
const response = await fetch(`${EndpointURLs[endpoint ?? '']}/abort`, {
@@ -513,7 +547,7 @@ export default function useEventHandlers({
console.error(error);
const convoId = conversationId ?? v4();
const text =
- submission.initialResponse?.text?.length > 45 ? submission.initialResponse?.text : '';
+ submission.initialResponse.text.length > 45 ? submission.initialResponse.text : '';
const errorMessage = {
...submission,
...submission.initialResponse,
@@ -526,7 +560,7 @@ export default function useEventHandlers({
if (newConversation) {
newConversation({
template: { conversationId: convoId },
- preset: tPresetSchema.parse(submission?.conversation),
+ preset: tPresetSchema.parse(submission.conversation),
});
}
setIsSubmitting(false);
diff --git a/packages/data-provider/package.json b/packages/data-provider/package.json
index eff515da62..7c824fbf98 100644
--- a/packages/data-provider/package.json
+++ b/packages/data-provider/package.json
@@ -1,6 +1,6 @@
{
"name": "librechat-data-provider",
- "version": "0.7.41",
+ "version": "0.7.411",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",
diff --git a/packages/data-provider/src/parsers.ts b/packages/data-provider/src/parsers.ts
index 3406a33f65..4ddfa945cb 100644
--- a/packages/data-provider/src/parsers.ts
+++ b/packages/data-provider/src/parsers.ts
@@ -66,7 +66,7 @@ export function getEnabledEndpoints() {
if (endpointsEnv) {
enabledEndpoints = endpointsEnv
.split(',')
- .filter((endpoint) => endpoint?.trim())
+ .filter((endpoint) => endpoint.trim())
.map((endpoint) => endpoint.trim());
}
return enabledEndpoints;
@@ -347,3 +347,16 @@ export function parseTextParts(contentParts: a.TMessageContentParts[]): string {
return result;
}
+
+export const SEPARATORS = ['.', '?', '!', '۔', '。', '‥', ';', '¡', '¿', '\n', '```'];
+
+export function findLastSeparatorIndex(text: string, separators = SEPARATORS): number {
+ let lastIndex = -1;
+ for (const separator of separators) {
+ const index = text.lastIndexOf(separator);
+ if (index > lastIndex) {
+ lastIndex = index;
+ }
+ }
+ return lastIndex;
+}