feat(ChatNavbar): add session workspace metadata display in navbar

This commit is contained in:
Vaayne 2025-09-27 16:53:49 +08:00
parent 1b705edb06
commit ae1c1409e1
3 changed files with 56 additions and 6 deletions

View File

@ -21,8 +21,8 @@
}
.lucide:not(.lucide-custom) {
color: var(--color-icon);
}
color: var(--color-icon);
}
}
*:focus {

View File

@ -153,7 +153,7 @@ const PopupContainer: React.FC<Props> = ({ model, apiFilter, modelFilter, showTa
// 获取可选择的模型项(过滤掉分组标题)
const modelItems = items.filter((item) => item.type === 'model')
return { listItems: items, modelItems }
}, [searchFilter, adaptedModels, showTagFilter, tagFilter, createModelItem])
}, [searchFilter, adaptedModels, showTagFilter, tagFilter, createModelItem, modelFilter])
const listHeight = useMemo(() => {
return Math.min(PAGE_SIZE, listItems.length) * ITEM_HEIGHT

View File

@ -1,7 +1,9 @@
import { NavbarHeader } from '@renderer/components/app/Navbar'
import { HStack } from '@renderer/components/Layout'
import SearchPopup from '@renderer/components/Popups/SearchPopup'
import { permissionModeCards } from '@renderer/constants/permissionModes'
import { useAgent } from '@renderer/hooks/agents/useAgent'
import { useSession } from '@renderer/hooks/agents/useSession'
import { useUpdateAgent } from '@renderer/hooks/agents/useUpdateAgent'
import { useAssistant } from '@renderer/hooks/useAssistant'
import { modelGenerating, useRuntime } from '@renderer/hooks/useRuntime'
@ -11,12 +13,12 @@ import { useShowAssistants, useShowTopics } from '@renderer/hooks/useStore'
import { EVENT_NAMES, EventEmitter } from '@renderer/services/EventService'
import { useAppDispatch } from '@renderer/store'
import { setNarrowMode } from '@renderer/store/settings'
import { ApiModel, Assistant, Topic } from '@renderer/types'
import { ApiModel, Assistant, PermissionMode, Topic } from '@renderer/types'
import { Tooltip } from 'antd'
import { t } from 'i18next'
import { Menu, PanelLeftClose, PanelRightClose, Search } from 'lucide-react'
import { AnimatePresence, motion } from 'motion/react'
import { FC, useCallback } from 'react'
import { FC, ReactNode, useCallback } from 'react'
import styled from 'styled-components'
import AssistantsDrawer from './components/AssistantsDrawer'
@ -40,6 +42,7 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
const dispatch = useAppDispatch()
const { chat } = useRuntime()
const { activeTopicOrSession, activeAgentId } = chat
const sessionId = activeAgentId ? (chat.activeSessionId[activeAgentId] ?? null) : null
const { agent } = useAgent(activeAgentId)
const { updateModel } = useUpdateAgent()
@ -111,7 +114,10 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
</AnimatePresence>
{activeTopicOrSession === 'topic' && <SelectModelButton assistant={assistant} />}
{activeTopicOrSession === 'session' && agent && (
<SelectAgentModelButton agent={agent} onSelect={handleUpdateModel} />
<>
<SelectAgentModelButton agent={agent} onSelect={handleUpdateModel} />
{activeAgentId && sessionId && <SessionWorkspaceMeta agentId={activeAgentId} sessionId={sessionId} />}
</>
)}
</div>
<HStack alignItems="center" gap={8}>
@ -145,6 +151,50 @@ const HeaderNavbar: FC<Props> = ({ activeAssistant, setActiveAssistant, activeTo
)
}
const SessionWorkspaceMeta: FC<{ agentId: string; sessionId: string }> = ({ agentId, sessionId }) => {
const { session } = useSession(agentId, sessionId)
if (!session) {
return null
}
const firstAccessiblePath = session.accessible_paths?.[0]
const permissionMode = (session.configuration?.permission_mode ?? 'default') as PermissionMode
const permissionModeCard = permissionModeCards.find((card) => card.mode === permissionMode)
const permissionModeLabel = permissionModeCard
? t(permissionModeCard.titleKey, permissionModeCard.titleFallback)
: permissionMode
const infoItems: ReactNode[] = []
if (firstAccessiblePath) {
infoItems.push(
<div
key="path"
className="rounded-medium border border-default-200 px-2 py-1 text-foreground-500 text-xs dark:text-foreground-400"
title={firstAccessiblePath}
style={{ maxWidth: 240 }}>
<span className="block truncate">{firstAccessiblePath}</span>
</div>
)
}
infoItems.push(
<div
key="permission-mode"
className="rounded-medium border border-default-200 px-2 py-1 text-foreground-500 text-xs dark:text-foreground-400"
title={permissionModeLabel}
style={{ maxWidth: 200 }}>
<span className="block truncate">{permissionModeLabel}</span>
</div>
)
if (infoItems.length === 0) {
return null
}
return <div className="ml-2 flex items-center gap-2">{infoItems}</div>
}
export const NavbarIcon = styled.div`
-webkit-app-region: none;
border-radius: 8px;