v0.7.5-rc2 (#3976)

*  v0.7.5-rc2

* docs: update README

* refactor(settings): Update rememberForkOption default value

* a11y: proper screen reader announcements for content blocks

* Update version to 0.7.423 in package-lock.json and packages/data-provider/package.json

* chore: rename rememberForkOption -> rememberDefaultFork to apply new default value

* fix: headlessui menu stealing focus from Settings Dialog when pressing Enter
This commit is contained in:
Danny Avila 2024-09-10 19:00:27 -04:00 committed by GitHub
parent d6c0121b19
commit 020995514e
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
23 changed files with 92 additions and 43 deletions

View file

@ -1,4 +1,4 @@
# v0.7.5-rc1
# v0.7.5-rc2
# Base node image
FROM node:20-alpine AS node

View file

@ -1,5 +1,5 @@
# Dockerfile.multi
# v0.7.5-rc1
# v0.7.5-rc2
# Base for all builds
FROM node:20-alpine AS base

View file

@ -42,10 +42,10 @@
- 🖥️ UI matching ChatGPT, including Dark mode, Streaming, and latest updates
- 🤖 AI model selection:
- OpenAI, Azure OpenAI, BingAI, ChatGPT, Google Vertex AI, Anthropic (Claude), Plugins, Assistants API (including Azure Assistants)
- Anthropic (Claude), AWS Bedrock, OpenAI, Azure OpenAI, BingAI, ChatGPT, Google Vertex AI, Plugins, Assistants API (including Azure Assistants)
- ✅ Compatible across both **[Remote & Local AI services](https://www.librechat.ai/docs/configuration/librechat_yaml/ai_endpoints):**
- groq, Ollama, Cohere, Mistral AI, Apple MLX, koboldcpp, OpenRouter, together.ai, Perplexity, ShuttleAI, and more
- 🪄 Generative UI with [Code Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3)
- 🪄 Generative UI with **[Code Artifacts](https://youtu.be/GfTj7O4gmd0?si=WJbdnemZpJzBrJo3)**
- Create React, HTML code, and Mermaid diagrams right in chat
- 💾 Create, Save, & Share Custom Presets
- 🔀 Switch between AI Endpoints and Presets, mid-chat

View file

@ -1,6 +1,6 @@
{
"name": "@librechat/backend",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"description": "",
"scripts": {
"start": "echo 'please run this from the root directory'",

View file

@ -1,6 +1,6 @@
{
"name": "@librechat/frontend",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"description": "",
"type": "module",
"scripts": {

View file

@ -1,10 +1,6 @@
// AnnouncerContext.tsx
import React from 'react';
export interface AnnounceOptions {
message: string;
isStatus?: boolean;
}
import type { AnnounceOptions } from '~/common';
interface AnnouncerContextType {
announceAssertive: (options: AnnounceOptions) => void;

View file

@ -0,0 +1,6 @@
export interface AnnounceOptions {
message: string;
isStatus?: boolean;
}
export const MESSAGE_UPDATE_INTERVAL = 7000;

View file

@ -1,3 +1,4 @@
export * from './a11y';
export * from './artifacts';
export * from './types';
export * from './assistants-types';

View file

@ -116,7 +116,7 @@ export default function Fork({
const [forkSetting, setForkSetting] = useRecoilState(store.forkSetting);
const [activeSetting, setActiveSetting] = useState(optionLabels.default);
const [splitAtTarget, setSplitAtTarget] = useRecoilState(store.splitAtTarget);
const [rememberGlobal, setRememberGlobal] = useRecoilState(store.rememberForkOption);
const [rememberGlobal, setRememberGlobal] = useRecoilState(store.rememberDefaultFork);
const forkConvo = useForkConvoMutation({
onSuccess: (data) => {
if (data) {

View file

@ -120,7 +120,9 @@ function AccountSettings() {
className={focus ? 'bg-surface-hover' : ''}
svg={() => <GearIcon className="icon-md" />}
text={localize('com_nav_settings')}
clickHandler={() => setShowSettings(true)}
clickHandler={() => {
setTimeout(() => setShowSettings(true), 50);
}}
/>
)}
</MenuItem>

View file

@ -1,10 +1,10 @@
import { FC, forwardRef } from 'react';
import React, { FC, forwardRef } from 'react';
import { cn } from '~/utils/';
interface Props {
svg: () => JSX.Element;
text: string;
clickHandler?: () => void;
clickHandler?: React.MouseEventHandler<HTMLButtonElement>;
className?: string;
disabled?: boolean;
}
@ -13,7 +13,7 @@ const NavLink: FC<Props> = forwardRef<HTMLButtonElement, Props>((props, ref) =>
const { svg, text, clickHandler, disabled, className = '' } = props;
const defaultProps: {
className: string;
onClick?: () => void;
onClick?: React.MouseEventHandler<HTMLButtonElement>;
} = {
className: cn(
'w-full flex gap-2 rounded p-2.5 text-sm cursor-pointer group items-center transition-colors duration-200 text-text-primary hover:bg-surface-hover',

View file

@ -9,7 +9,7 @@ export const ForkSettings = () => {
const localize = useLocalize();
const [forkSetting, setForkSetting] = useRecoilState(store.forkSetting);
const [splitAtTarget, setSplitAtTarget] = useRecoilState(store.splitAtTarget);
const [remember, setRemember] = useRecoilState<boolean>(store.rememberForkOption);
const [remember, setRemember] = useRecoilState<boolean>(store.rememberDefaultFork);
const forkOptions = [
{ value: ForkOptions.DIRECT_PATH, label: localize('com_ui_fork_visible') },
@ -39,11 +39,11 @@ export const ForkSettings = () => {
<div className="flex items-center justify-between">
<div> {localize('com_ui_fork_default')} </div>
<Switch
id="rememberForkOption"
id="rememberDefaultFork"
checked={remember}
onCheckedChange={setRemember}
className="ml-4 mt-2"
data-testid="rememberForkOption"
data-testid="rememberDefaultFork"
/>
</div>
</div>

View file

@ -23,6 +23,7 @@ import type { TGenTitleMutation } from '~/data-provider';
import {
scrollToEnd,
addConversation,
getAllContentText,
deleteConversation,
updateConversation,
getConversationById,
@ -30,6 +31,7 @@ import {
import useContentHandler from '~/hooks/SSE/useContentHandler';
import useStepHandler from '~/hooks/SSE/useStepHandler';
import { useAuthContext } from '~/hooks/AuthContext';
import { MESSAGE_UPDATE_INTERVAL } from '~/common';
import { useLiveAnnouncer } from '~/Providers';
import store from '~/store';
@ -55,8 +57,6 @@ export type EventHandlerParams = {
resetLatestMessage?: Resetter;
};
const MESSAGE_UPDATE_INTERVAL = 7000;
export default function useEventHandlers({
genTitle,
setMessages,
@ -78,7 +78,13 @@ export default function useEventHandlers({
const { token } = useAuthContext();
const contentHandler = useContentHandler({ setMessages, getMessages });
const stepHandler = useStepHandler({ setMessages, getMessages });
const stepHandler = useStepHandler({
setMessages,
getMessages,
announcePolite,
setIsSubmitting,
lastAnnouncementTimeRef,
});
const messageHandler = useCallback(
(data: string | undefined, submission: EventSubmission) => {
@ -356,7 +362,7 @@ export default function useEventHandlers({
});
announcePolite({
message: responseMessage?.text ?? '',
message: getAllContentText(responseMessage),
});
/* Update messages; if assistants endpoint, client doesn't receive responseMessage */

View file

@ -1,17 +1,22 @@
import { useCallback, useRef } from 'react';
import { StepTypes, ContentTypes, ToolCallTypes } from 'librechat-data-provider';
import { StepTypes, ContentTypes, ToolCallTypes, getNonEmptyValue } from 'librechat-data-provider';
import type {
Agents,
PartMetadata,
TMessage,
TMessageContentParts,
PartMetadata,
EventSubmission,
TMessageContentParts,
} from 'librechat-data-provider';
import { getNonEmptyValue } from 'librechat-data-provider';
import type { SetterOrUpdater } from 'recoil';
import type { AnnounceOptions } from '~/common';
import { MESSAGE_UPDATE_INTERVAL } from '~/common';
type TUseStepHandler = {
announcePolite: (options: AnnounceOptions) => void;
setMessages: (messages: TMessage[]) => void;
getMessages: () => TMessage[] | undefined;
setIsSubmitting: SetterOrUpdater<boolean>;
lastAnnouncementTimeRef: React.MutableRefObject<number>;
};
type TStepEvent = {
@ -28,7 +33,13 @@ type AllContentTypes =
| ContentTypes.IMAGE_URL
| ContentTypes.ERROR;
export default function useStepHandler({ setMessages, getMessages }: TUseStepHandler) {
export default function useStepHandler({
setMessages,
getMessages,
setIsSubmitting,
announcePolite,
lastAnnouncementTimeRef,
}: TUseStepHandler) {
const toolCallIdMap = useRef(new Map<string, string | undefined>());
const messageMap = useRef(new Map<string, TMessage>());
const stepMap = useRef(new Map<string, Agents.RunStep>());
@ -112,6 +123,13 @@ export default function useStepHandler({ setMessages, getMessages }: TUseStepHan
({ event, data }: TStepEvent, submission: EventSubmission) => {
const messages = getMessages() || [];
const { userMessage } = submission;
setIsSubmitting(true);
const currentTime = Date.now();
if (currentTime - lastAnnouncementTimeRef.current > MESSAGE_UPDATE_INTERVAL) {
announcePolite({ message: 'composing', isStatus: true });
lastAnnouncementTimeRef.current = currentTime;
}
if (event === 'on_run_step') {
const runStep = data as Agents.RunStep;
@ -249,6 +267,6 @@ export default function useStepHandler({ setMessages, getMessages }: TUseStepHan
stepMap.current.clear();
};
},
[getMessages, stepMap, messageMap, setMessages, toolCallIdMap],
[getMessages, setIsSubmitting, lastAnnouncementTimeRef, announcePolite, setMessages],
);
}

View file

@ -1,5 +1,5 @@
import { atom } from 'recoil';
import { SettingsViews } from 'librechat-data-provider';
import { SettingsViews, LocalStorageKeys } from 'librechat-data-provider';
import { atomWithLocalStorage } from '~/store/utils';
import type { TOptionSettings } from '~/common';
@ -32,7 +32,7 @@ const localStorageAtoms = {
forkSetting: atomWithLocalStorage('forkSetting', ''),
splitAtTarget: atomWithLocalStorage('splitAtTarget', false),
rememberForkOption: atomWithLocalStorage('rememberForkOption', true),
rememberDefaultFork: atomWithLocalStorage(LocalStorageKeys.REMEMBER_FORK_OPTION, false),
// Beta features settings
modularChat: atomWithLocalStorage('modularChat', true),

View file

@ -40,6 +40,26 @@ export const getLatestText = (message?: TMessage | null, includeIndex?: boolean)
return '';
};
export const getAllContentText = (message?: TMessage | null): string => {
if (!message) {
return '';
}
if (message.text) {
return message.text;
}
if (message.content && message.content.length > 0) {
return message.content
.filter((part) => part.type === ContentTypes.TEXT)
.map((part) => (typeof part.text === 'string' ? part.text : part.text.value) ?? '')
.filter((text) => text.length > 0)
.join('\n');
}
return '';
};
export const getTextKey = (message?: TMessage | null, convoId?: string | null) => {
if (!message) {
return '';

View file

@ -1,3 +1,3 @@
// v0.7.5-rc1
// v0.7.5-rc2
// See .env.test.example for an example of the '.env.test' file.
require('dotenv').config({ path: './e2e/.env.test' });

View file

@ -1,4 +1,4 @@
<!-- v0.7.5-rc1 -->
<!-- v0.7.5-rc2 -->
<!DOCTYPE html>
<html>
<head>

10
package-lock.json generated
View file

@ -1,12 +1,12 @@
{
"name": "LibreChat",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "LibreChat",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"license": "ISC",
"workspaces": [
"api",
@ -40,7 +40,7 @@
},
"api": {
"name": "@librechat/backend",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"license": "ISC",
"dependencies": {
"@anthropic-ai/sdk": "^0.16.1",
@ -1220,7 +1220,7 @@
},
"client": {
"name": "@librechat/frontend",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"license": "ISC",
"dependencies": {
"@ariakit/react": "^0.4.8",
@ -36399,7 +36399,7 @@
},
"packages/data-provider": {
"name": "librechat-data-provider",
"version": "0.7.422",
"version": "0.7.423",
"license": "ISC",
"dependencies": {
"@types/js-yaml": "^4.0.9",

View file

@ -1,6 +1,6 @@
{
"name": "LibreChat",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"description": "",
"workspaces": [
"api",

View file

@ -1,6 +1,6 @@
{
"name": "librechat-data-provider",
"version": "0.7.422",
"version": "0.7.423",
"description": "data services for librechat apps",
"main": "dist/index.js",
"module": "dist/index.es.js",

View file

@ -1060,7 +1060,7 @@ export enum TTSProviders {
/** Enum for app-wide constants */
export enum Constants {
/** Key for the app's version. */
VERSION = 'v0.7.5-rc1',
VERSION = 'v0.7.5-rc2',
/** Key for the Custom Config's version (librechat.yaml). */
CONFIG_VERSION = '1.1.7',
/** Standard value for the first message's `parentMessageId` value, to indicate no parent exists. */
@ -1107,7 +1107,7 @@ export enum LocalStorageKeys {
/** Key for the last selected fork setting */
FORK_SETTING = 'forkSetting',
/** Key for remembering the last selected option, instead of manually selecting */
REMEMBER_FORK_OPTION = 'rememberForkOption',
REMEMBER_FORK_OPTION = 'rememberDefaultFork',
/** Key for remembering the split at target fork option modifier */
FORK_SPLIT_AT_TARGET = 'splitAtTarget',
/** Key for saving text drafts */

View file

@ -1,4 +1,4 @@
// v0.7.5-rc1
// v0.7.5-rc2
module.exports = {
tailwindConfig: './client/tailwind.config.cjs',
printWidth: 100,