diff --git a/.github/workflows/cache-integration-tests.yml b/.github/workflows/cache-integration-tests.yml index 7fda84602a..9634569cf5 100644 --- a/.github/workflows/cache-integration-tests.yml +++ b/.github/workflows/cache-integration-tests.yml @@ -45,9 +45,29 @@ jobs: node-version: '24.16.0' - name: Install Redis tools + timeout-minutes: 10 run: | - sudo apt-get update - sudo apt-get install -y redis-server redis-tools + # Same runner apt contention that broke the MCP job in + # playwright-mock.yml: apt-daily/unattended-upgrades hold + # /var/lib/apt/lists/lock at boot. Without a step timeout this hung + # until the job-level one fired, taking the whole leg with it. + sudo systemctl stop apt-daily.service apt-daily-upgrade.service \ + unattended-upgrades.service 2>/dev/null || true + sudo systemctl kill --kill-who=all apt-daily.service \ + apt-daily-upgrade.service 2>/dev/null || true + + apt_with_lock_wait() { + for attempt in $(seq 1 30); do + if sudo apt-get -o DPkg::Lock::Timeout=60 "$@"; then + return 0 + fi + echo "apt-get $1 could not take the lock (attempt ${attempt}/30), retrying" + sleep 10 + done + return 1 + } + apt_with_lock_wait update + apt_with_lock_wait install -y redis-server redis-tools - name: Start Single Redis Instance run: | diff --git a/client/src/components/Chat/Header.tsx b/client/src/components/Chat/Header.tsx index 454b872e0f..16a73ce600 100644 --- a/client/src/components/Chat/Header.tsx +++ b/client/src/components/Chat/Header.tsx @@ -1,6 +1,12 @@ import { memo, useMemo } from 'react'; import { useRecoilValue } from 'recoil'; -import { getConfigDefaults, PermissionTypes, Permissions } from 'librechat-data-provider'; +import { useParams } from 'react-router-dom'; +import { + getConfigDefaults, + Constants, + PermissionTypes, + Permissions, +} from 'librechat-data-provider'; import { OpenSidebar, PresetsMenu, NewChat, HeaderMenu } from './Menus'; import ModelSelector from './Menus/Endpoints/ModelSelector'; import { useGetStartupConfig } from '~/data-provider'; @@ -31,6 +37,13 @@ function Header({ const { data: startupConfig } = useGetStartupConfig(); const navVisible = useRecoilValue(store.sidebarExpanded); + /** The mobile row only offers a new chat when there is one to leave. Read + * from the route rather than the context conversation, which still holds the + * previous chat for a render after a history or link navigation. An unsaved + * conversation has no id in the route yet, so absence counts as new too. */ + const { conversationId: routeConversationId } = useParams(); + const isNewChat = routeConversationId == null || routeConversationId === Constants.NEW_CONVO; + const interfaceConfig = useMemo( () => startupConfig?.interface ?? defaultInterface, [startupConfig], @@ -90,7 +103,7 @@ function Header({
-
- @@ -66,7 +67,7 @@ export default function SkillList({ )) )}