Skip to content

Commit

Permalink
✨ v0.7.5-rc2 (#3976)
Browse files Browse the repository at this point in the history
* ✨ 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
  • Loading branch information
danny-avila authored Sep 10, 2024
1 parent d6c0121 commit 0209955
Show file tree
Hide file tree
Showing 23 changed files with 92 additions and 43 deletions.
2 changes: 1 addition & 1 deletion Dockerfile
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# v0.7.5-rc1
# v0.7.5-rc2

# Base node image
FROM node:20-alpine AS node
Expand Down
2 changes: 1 addition & 1 deletion Dockerfile.multi
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
# Dockerfile.multi
# v0.7.5-rc1
# v0.7.5-rc2

# Base for all builds
FROM node:20-alpine AS base
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion api/package.json
Original file line number Diff line number Diff line change
@@ -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'",
Expand Down
2 changes: 1 addition & 1 deletion client/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@librechat/frontend",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"description": "",
"type": "module",
"scripts": {
Expand Down
6 changes: 1 addition & 5 deletions client/src/Providers/AnnouncerContext.tsx
Original file line number Diff line number Diff line change
@@ -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;
Expand Down
6 changes: 6 additions & 0 deletions client/src/common/a11y.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
export interface AnnounceOptions {
message: string;
isStatus?: boolean;
}

export const MESSAGE_UPDATE_INTERVAL = 7000;
1 change: 1 addition & 0 deletions client/src/common/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from './a11y';
export * from './artifacts';
export * from './types';
export * from './assistants-types';
Expand Down
2 changes: 1 addition & 1 deletion client/src/components/Conversations/Fork.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
4 changes: 3 additions & 1 deletion client/src/components/Nav/AccountSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Nav/NavLink.tsx
Original file line number Diff line number Diff line change
@@ -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;
}
Expand All @@ -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',
Expand Down
6 changes: 3 additions & 3 deletions client/src/components/Nav/SettingsTabs/Chat/ForkSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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') },
Expand Down Expand Up @@ -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>
Expand Down
14 changes: 10 additions & 4 deletions client/src/hooks/SSE/useEventHandlers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,15 @@ import type { TGenTitleMutation } from '~/data-provider';
import {
scrollToEnd,
addConversation,
getAllContentText,
deleteConversation,
updateConversation,
getConversationById,
} from '~/utils';
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';

Expand All @@ -55,8 +57,6 @@ export type EventHandlerParams = {
resetLatestMessage?: Resetter;
};

const MESSAGE_UPDATE_INTERVAL = 7000;

export default function useEventHandlers({
genTitle,
setMessages,
Expand All @@ -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) => {
Expand Down Expand Up @@ -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 */
Expand Down
30 changes: 24 additions & 6 deletions client/src/hooks/SSE/useStepHandler.ts
Original file line number Diff line number Diff line change
@@ -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 = {
Expand All @@ -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>());
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -249,6 +267,6 @@ export default function useStepHandler({ setMessages, getMessages }: TUseStepHan
stepMap.current.clear();
};
},
[getMessages, stepMap, messageMap, setMessages, toolCallIdMap],
[getMessages, setIsSubmitting, lastAnnouncementTimeRef, announcePolite, setMessages],
);
}
4 changes: 2 additions & 2 deletions client/src/store/settings.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand Down Expand Up @@ -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),
Expand Down
20 changes: 20 additions & 0 deletions client/src/utils/messages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 '';
Expand Down
2 changes: 1 addition & 1 deletion e2e/jestSetup.js
Original file line number Diff line number Diff line change
@@ -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' });
2 changes: 1 addition & 1 deletion index.html
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
<!-- v0.7.5-rc1 -->
<!-- v0.7.5-rc2 -->
<!DOCTYPE html>
<html>
<head>
Expand Down
10 changes: 5 additions & 5 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "LibreChat",
"version": "v0.7.5-rc1",
"version": "v0.7.5-rc2",
"description": "",
"workspaces": [
"api",
Expand Down
2 changes: 1 addition & 1 deletion packages/data-provider/package.json
Original file line number Diff line number Diff line change
@@ -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",
Expand Down
4 changes: 2 additions & 2 deletions packages/data-provider/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand Down Expand Up @@ -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 */
Expand Down
2 changes: 1 addition & 1 deletion prettier.config.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// v0.7.5-rc1
// v0.7.5-rc2
module.exports = {
tailwindConfig: './client/tailwind.config.cjs',
printWidth: 100,
Expand Down

0 comments on commit 0209955

Please sign in to comment.