mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-09-27 20:06:39 +08:00
style(assistant): compact model picker in header
This commit is contained in:
@@ -205,34 +205,16 @@ function AssistantPanel({ storageKey }: { storageKey: string }) {
|
|||||||
<header className="flex items-center gap-2 border-b p-3">
|
<header className="flex items-center gap-2 border-b p-3">
|
||||||
<MessageCircle className="size-5 text-primary" />
|
<MessageCircle className="size-5 text-primary" />
|
||||||
<div className="min-w-0 flex-1">
|
<div className="min-w-0 flex-1">
|
||||||
<h2 className="font-semibold">{t('assistant.title')}</h2>
|
<h2 className="truncate font-semibold">{t('assistant.title')}</h2>
|
||||||
<p className="truncate text-xs text-muted-foreground">
|
<p className="truncate text-xs text-muted-foreground">
|
||||||
{t('assistant.subtitle')}
|
{t('assistant.subtitle')}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
disabled={busy}
|
|
||||||
onClick={reset}
|
|
||||||
aria-label={t('assistant.newChat')}
|
|
||||||
>
|
|
||||||
<Plus />
|
|
||||||
</Button>
|
|
||||||
<Button
|
|
||||||
variant="ghost"
|
|
||||||
size="icon"
|
|
||||||
onClick={() => setOpen(false)}
|
|
||||||
aria-label={t('assistant.close')}
|
|
||||||
>
|
|
||||||
<X />
|
|
||||||
</Button>
|
|
||||||
</header>
|
|
||||||
{open && (
|
{open && (
|
||||||
<div className="space-y-1 border-b px-3 py-2">
|
<div
|
||||||
<span className="text-xs text-muted-foreground">
|
className="w-28 min-w-0 shrink-0"
|
||||||
{t('assistant.modelHint')}
|
title={t('assistant.modelHint')}
|
||||||
</span>
|
>
|
||||||
<DynamicFormItemComponent
|
<DynamicFormItemComponent
|
||||||
config={{
|
config={{
|
||||||
id: 'assistant-model',
|
id: 'assistant-model',
|
||||||
@@ -249,12 +231,34 @@ function AssistantPanel({ storageKey }: { storageKey: string }) {
|
|||||||
onBlur: () => {},
|
onBlur: () => {},
|
||||||
ref: () => {},
|
ref: () => {},
|
||||||
disabled:
|
disabled:
|
||||||
busy || (!!conversation && conversation.status !== 'ready'),
|
busy ||
|
||||||
|
(!!conversation && conversation.status !== 'ready'),
|
||||||
}}
|
}}
|
||||||
requiredModelAbility="func_call"
|
requiredModelAbility="func_call"
|
||||||
|
compactModelSelector
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
)}
|
)}
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="size-7 shrink-0"
|
||||||
|
disabled={busy}
|
||||||
|
onClick={reset}
|
||||||
|
aria-label={t('assistant.newChat')}
|
||||||
|
>
|
||||||
|
<Plus />
|
||||||
|
</Button>
|
||||||
|
<Button
|
||||||
|
variant="ghost"
|
||||||
|
size="icon"
|
||||||
|
className="size-7 shrink-0"
|
||||||
|
onClick={() => setOpen(false)}
|
||||||
|
aria-label={t('assistant.close')}
|
||||||
|
>
|
||||||
|
<X />
|
||||||
|
</Button>
|
||||||
|
</header>
|
||||||
<div
|
<div
|
||||||
className="flex-1 space-y-3 overflow-y-auto p-4"
|
className="flex-1 space-y-3 overflow-y-auto p-4"
|
||||||
aria-live="polite"
|
aria-live="polite"
|
||||||
|
|||||||
@@ -89,6 +89,7 @@ export default function DynamicFormItemComponent({
|
|||||||
setFormValue,
|
setFormValue,
|
||||||
systemContext,
|
systemContext,
|
||||||
requiredModelAbility,
|
requiredModelAbility,
|
||||||
|
compactModelSelector = false,
|
||||||
}: {
|
}: {
|
||||||
config: IDynamicFormItemSchema;
|
config: IDynamicFormItemSchema;
|
||||||
field: ControllerRenderProps<any, any>;
|
field: ControllerRenderProps<any, any>;
|
||||||
@@ -97,6 +98,7 @@ export default function DynamicFormItemComponent({
|
|||||||
setFormValue?: (name: string, value: unknown) => void;
|
setFormValue?: (name: string, value: unknown) => void;
|
||||||
systemContext?: Record<string, unknown>;
|
systemContext?: Record<string, unknown>;
|
||||||
requiredModelAbility?: string;
|
requiredModelAbility?: string;
|
||||||
|
compactModelSelector?: boolean;
|
||||||
}) {
|
}) {
|
||||||
const [llmModels, setLlmModels] = useState<LLMModel[]>([]);
|
const [llmModels, setLlmModels] = useState<LLMModel[]>([]);
|
||||||
const [embeddingModels, setEmbeddingModels] = useState<EmbeddingModel[]>([]);
|
const [embeddingModels, setEmbeddingModels] = useState<EmbeddingModel[]>([]);
|
||||||
@@ -468,7 +470,14 @@ export default function DynamicFormItemComponent({
|
|||||||
onValueChange={field.onChange}
|
onValueChange={field.onChange}
|
||||||
disabled={field.disabled}
|
disabled={field.disabled}
|
||||||
>
|
>
|
||||||
<SelectTrigger className="min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]">
|
<SelectTrigger
|
||||||
|
aria-label={t('models.selectModel')}
|
||||||
|
className={
|
||||||
|
compactModelSelector
|
||||||
|
? 'w-full min-w-0 gap-1 border-0 bg-transparent px-1 text-xs text-muted-foreground shadow-none hover:bg-muted data-[size=default]:h-7 [&_[data-slot=select-value]_svg]:hidden'
|
||||||
|
: 'min-w-0 bg-[#ffffff] dark:bg-[#2a2a2e]'
|
||||||
|
}
|
||||||
|
>
|
||||||
<SelectValue placeholder={t('models.selectModel')} />
|
<SelectValue placeholder={t('models.selectModel')} />
|
||||||
</SelectTrigger>
|
</SelectTrigger>
|
||||||
<SelectContent>
|
<SelectContent>
|
||||||
@@ -605,7 +614,7 @@ export default function DynamicFormItemComponent({
|
|||||||
type="button"
|
type="button"
|
||||||
variant="ghost"
|
variant="ghost"
|
||||||
size="icon"
|
size="icon"
|
||||||
className="h-9 w-9 shrink-0"
|
className={compactModelSelector ? 'hidden' : 'h-9 w-9 shrink-0'}
|
||||||
onClick={() => {
|
onClick={() => {
|
||||||
setSettingsSection('models');
|
setSettingsSection('models');
|
||||||
setModelsDialogOpen(true);
|
setModelsDialogOpen(true);
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const enUS = {
|
const enUS = {
|
||||||
assistant: {
|
assistant: {
|
||||||
modelHint:
|
modelHint: 'Switch assistant model for your next message',
|
||||||
'Assistant model · Space recommendation by default; changes apply to your next message',
|
|
||||||
details: 'View raw data',
|
details: 'View raw data',
|
||||||
found: 'Found {{count}} items',
|
found: 'Found {{count}} items',
|
||||||
completed: 'Completed',
|
completed: 'Completed',
|
||||||
@@ -29,8 +28,8 @@ const enUS = {
|
|||||||
knowledge_bases: 'Find knowledge bases',
|
knowledge_bases: 'Find knowledge bases',
|
||||||
knowledge_engines: 'Find knowledge engines',
|
knowledge_engines: 'Find knowledge engines',
|
||||||
},
|
},
|
||||||
title: 'Workspace assistant · Experimental',
|
title: 'Workspace assistant',
|
||||||
subtitle: 'Build with your Space model',
|
subtitle: 'Build and manage your apps',
|
||||||
newChat: 'New conversation',
|
newChat: 'New conversation',
|
||||||
close: 'Close',
|
close: 'Close',
|
||||||
welcome:
|
welcome:
|
||||||
@@ -43,7 +42,7 @@ const enUS = {
|
|||||||
decline: 'Decline',
|
decline: 'Decline',
|
||||||
working: 'Working…',
|
working: 'Working…',
|
||||||
modelUnavailable:
|
modelUnavailable:
|
||||||
'The Space model is unavailable. Check your Space account and model access in Settings, then start a new conversation.',
|
'Model unavailable. Check its configuration and access, then start a new conversation.',
|
||||||
error:
|
error:
|
||||||
'This turn did not complete. Check the resource results before starting a new conversation; changes are not retried automatically.',
|
'This turn did not complete. Check the resource results before starting a new conversation; changes are not retried automatically.',
|
||||||
running:
|
running:
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
const jaJP = {
|
const jaJP = {
|
||||||
assistant: {
|
assistant: {
|
||||||
modelHint:
|
modelHint: '次のメッセージからモデルを切り替え',
|
||||||
'アシスタントモデル · 既定は Space 推奨。変更は次のメッセージから適用',
|
|
||||||
details: '元のデータを見る',
|
details: '元のデータを見る',
|
||||||
found: '{{count}} 件見つかりました',
|
found: '{{count}} 件見つかりました',
|
||||||
completed: '完了',
|
completed: '完了',
|
||||||
@@ -29,8 +28,8 @@ const jaJP = {
|
|||||||
knowledge_bases: 'ナレッジベース検索',
|
knowledge_bases: 'ナレッジベース検索',
|
||||||
knowledge_engines: 'エンジン検索',
|
knowledge_engines: 'エンジン検索',
|
||||||
},
|
},
|
||||||
title: 'ワークスペースアシスタント · 実験版',
|
title: 'ワークスペースアシスタント',
|
||||||
subtitle: 'Space モデルでアプリを構築',
|
subtitle: 'アプリを構築・管理',
|
||||||
newChat: '新しい会話',
|
newChat: '新しい会話',
|
||||||
close: '閉じる',
|
close: '閉じる',
|
||||||
welcome:
|
welcome:
|
||||||
@@ -43,7 +42,7 @@ const jaJP = {
|
|||||||
decline: '拒否',
|
decline: '拒否',
|
||||||
working: '処理中…',
|
working: '処理中…',
|
||||||
modelUnavailable:
|
modelUnavailable:
|
||||||
'Space モデルを利用できません。設定でログインとモデルの権限を確認して、新しい会話を開始してください。',
|
'モデルを利用できません。設定と権限を確認して、新しい会話を開始してください。',
|
||||||
error:
|
error:
|
||||||
'処理が完了しませんでした。新しい会話の前にリソースを確認してください。変更は自動で再試行されません。',
|
'処理が完了しませんでした。新しい会話の前にリソースを確認してください。変更は自動で再試行されません。',
|
||||||
running:
|
running:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
const zhHans = {
|
const zhHans = {
|
||||||
assistant: {
|
assistant: {
|
||||||
modelHint: '助手模型 · 默认使用 Space 推荐模型,切换从下一条消息生效',
|
modelHint: '切换助手模型,从下一条消息生效',
|
||||||
details: '查看原始数据',
|
details: '查看原始数据',
|
||||||
found: '找到 {{count}} 项',
|
found: '找到 {{count}} 项',
|
||||||
completed: '已完成',
|
completed: '已完成',
|
||||||
@@ -26,8 +26,8 @@ const zhHans = {
|
|||||||
knowledge_bases: '查询知识库',
|
knowledge_bases: '查询知识库',
|
||||||
knowledge_engines: '查询知识引擎',
|
knowledge_engines: '查询知识引擎',
|
||||||
},
|
},
|
||||||
title: '工作区助手 · 实验版',
|
title: '工作区助手',
|
||||||
subtitle: '使用 Space 模型构建应用',
|
subtitle: '构建和管理你的应用',
|
||||||
newChat: '新对话',
|
newChat: '新对话',
|
||||||
close: '关闭',
|
close: '关闭',
|
||||||
welcome:
|
welcome:
|
||||||
@@ -40,7 +40,7 @@ const zhHans = {
|
|||||||
decline: '拒绝',
|
decline: '拒绝',
|
||||||
working: '正在处理…',
|
working: '正在处理…',
|
||||||
modelUnavailable:
|
modelUnavailable:
|
||||||
'Space 模型暂不可用。请在设置中检查 Space 登录和模型权限,然后开启新对话。',
|
'模型暂不可用。请检查模型配置和访问权限,然后开启新对话。',
|
||||||
error:
|
error:
|
||||||
'本轮未完成。请先检查资源和操作结果,再开启新对话;系统不会自动重试变更。',
|
'本轮未完成。请先检查资源和操作结果,再开启新对话;系统不会自动重试变更。',
|
||||||
running:
|
running:
|
||||||
|
|||||||
Reference in New Issue
Block a user