Enhance workflow routing and agent configuration management
- Introduce WorkflowLLMRouter for pre-response LLM routing, allowing agents to determine the appropriate function to call based on user input. - Implement UserTurnRoutingProcessor to manage user turns before reaching the LLM, ensuring proper routing and handling of user messages. - Refactor WorkflowBrain to integrate new routing logic and enhance agent stage configuration, including entry modes and resource management. - Update service factory to support dynamic LLM resource configuration based on workflow settings. - Add tests for new routing functionality and ensure proper handling of user messages in various scenarios.
This commit is contained in:
@@ -21,7 +21,6 @@ import {
|
||||
Save,
|
||||
Mic,
|
||||
Send,
|
||||
HelpCircle,
|
||||
Waypoints,
|
||||
AudioLines,
|
||||
Terminal,
|
||||
@@ -87,12 +86,6 @@ import { PageHeader } from "@/components/ui/page-header";
|
||||
import { FilterPills } from "@/components/ui/filter-pills";
|
||||
import { SearchInput } from "@/components/ui/search-input";
|
||||
import { ListToolbar } from "@/components/ui/list-toolbar";
|
||||
import {
|
||||
Card,
|
||||
CardContent,
|
||||
CardHeader,
|
||||
CardTitle,
|
||||
} from "@/components/ui/card";
|
||||
import { useCallback, useEffect, useRef, useState } from "react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import {
|
||||
@@ -124,6 +117,7 @@ import {
|
||||
WorkflowEditor,
|
||||
type WorkflowSettings,
|
||||
} from "@/components/workflow/WorkflowEditor";
|
||||
import { HelpHint, SectionCard } from "@/components/editor/section-card";
|
||||
import {
|
||||
defaultGraph,
|
||||
type WorkflowGraph,
|
||||
@@ -362,7 +356,7 @@ type AssistantTypeOption = {
|
||||
label: string;
|
||||
description: string;
|
||||
icon: React.ReactNode;
|
||||
/** 提示词、Dify、FastGPT 类型已落地,工作流暂时显示占位页 */
|
||||
/** 提示词、工作流、Dify、FastGPT 已落地;OpenCode 暂时显示即将上线 */
|
||||
available: boolean;
|
||||
};
|
||||
|
||||
@@ -379,7 +373,7 @@ const assistantTypeOptions: AssistantTypeOption[] = [
|
||||
label: "使用工作流构建",
|
||||
description: "用可视化编排串联多个节点,适合多步骤、带分支的复杂流程。",
|
||||
icon: <Workflow size={20} />,
|
||||
available: false,
|
||||
available: true,
|
||||
},
|
||||
{
|
||||
type: "Dify",
|
||||
@@ -400,7 +394,7 @@ const assistantTypeOptions: AssistantTypeOption[] = [
|
||||
label: "使用 OpenCode 构建",
|
||||
description: "对接 OpenCode 服务,通过提示词驱动代码助手并支持实时语音对话。",
|
||||
icon: <Terminal size={20} />,
|
||||
available: true,
|
||||
available: false,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -472,12 +466,23 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
);
|
||||
const [workflowSettings, setWorkflowSettings] = useState<WorkflowSettings>({
|
||||
globalPrompt: defaultGraph().settings.globalPrompt,
|
||||
llm: defaultGraph().settings.defaultLlmResourceId,
|
||||
asr: defaultGraph().settings.defaultAsrResourceId,
|
||||
tts: defaultGraph().settings.defaultTtsResourceId,
|
||||
toolIds: defaultGraph().settings.toolIds,
|
||||
knowledgeBaseId: defaultGraph().settings.knowledgeBaseId,
|
||||
knowledgeRetrievalConfig: {
|
||||
mode: defaultGraph().settings.knowledgeMode,
|
||||
topN: defaultGraph().settings.knowledgeTopN,
|
||||
scoreThreshold: defaultGraph().settings.knowledgeScoreThreshold,
|
||||
},
|
||||
allowInterrupt: true,
|
||||
turnConfig: defaultTurnConfig(),
|
||||
});
|
||||
const [workflowDynamicVariableDefinitions, setWorkflowDynamicVariableDefinitions] =
|
||||
useState<Record<string, DynamicVariableDefinition>>({});
|
||||
const [workflowDebugOpen, setWorkflowDebugOpen] = useState(false);
|
||||
const [workflowSettingsOpen, setWorkflowSettingsOpen] = useState(false);
|
||||
const [workflowEditingNodeId, setWorkflowEditingNodeId] = useState<string | null>(null);
|
||||
const [workflowEditingEdgeId, setWorkflowEditingEdgeId] = useState<string | null>(null);
|
||||
const [activeNodeId, setActiveNodeId] = useState<string | null>(null);
|
||||
@@ -847,9 +852,25 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
? (assistant.graph as WorkflowGraph)
|
||||
: defaultGraph();
|
||||
const wfSettings: WorkflowSettings = {
|
||||
llm: assistant.modelResourceIds.LLM,
|
||||
llm:
|
||||
graph.settings?.defaultLlmResourceId ||
|
||||
assistant.modelResourceIds.LLM,
|
||||
asr: graph.settings?.defaultAsrResourceId || assistant.modelResourceIds.ASR,
|
||||
tts: graph.settings?.defaultTtsResourceId || assistant.modelResourceIds.TTS,
|
||||
toolIds: graph.settings?.toolIds ?? [],
|
||||
knowledgeBaseId:
|
||||
graph.settings?.knowledgeBaseId || assistant.knowledgeBaseId || "",
|
||||
knowledgeRetrievalConfig: {
|
||||
mode:
|
||||
graph.settings?.knowledgeMode ||
|
||||
assistant.knowledgeRetrievalConfig.mode,
|
||||
topN:
|
||||
graph.settings?.knowledgeTopN ??
|
||||
assistant.knowledgeRetrievalConfig.topN,
|
||||
scoreThreshold:
|
||||
graph.settings?.knowledgeScoreThreshold ??
|
||||
assistant.knowledgeRetrievalConfig.scoreThreshold,
|
||||
},
|
||||
globalPrompt: graph.settings?.globalPrompt ?? "",
|
||||
allowInterrupt: assistant.enableInterrupt,
|
||||
turnConfig: assistant.turnConfig,
|
||||
@@ -916,6 +937,9 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
...(workflowSettings.asr ? { ASR: workflowSettings.asr } : {}),
|
||||
...(workflowSettings.tts ? { TTS: workflowSettings.tts } : {}),
|
||||
},
|
||||
knowledgeBaseId: workflowSettings.knowledgeBaseId || null,
|
||||
knowledgeRetrievalConfig: workflowSettings.knowledgeRetrievalConfig,
|
||||
toolIds: workflowSettings.toolIds,
|
||||
graph: workflowGraph as unknown as Record<string, unknown>,
|
||||
dynamicVariableDefinitions: workflowDynamicVariableDefinitions,
|
||||
}),
|
||||
@@ -1386,7 +1410,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
<span
|
||||
role="alert"
|
||||
title={saveError}
|
||||
className="line-clamp-2 max-w-[min(42vw,560px)] self-center text-right text-sm leading-5 text-destructive"
|
||||
className="line-clamp-1 max-w-[min(42vw,560px)] self-center text-right text-sm leading-5 text-destructive"
|
||||
>
|
||||
{saveError}
|
||||
</span>
|
||||
@@ -1396,6 +1420,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
className="gap-2 border-hairline-strong text-foreground hover:bg-surface-strong"
|
||||
disabled={!editingId}
|
||||
onClick={() => {
|
||||
setWorkflowSettingsOpen(false);
|
||||
setWorkflowEditingNodeId(null);
|
||||
setWorkflowEditingEdgeId(null);
|
||||
setWorkflowDebugOpen(true);
|
||||
@@ -1430,6 +1455,8 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
onEditingNodeIdChange={setWorkflowEditingNodeId}
|
||||
editingEdgeId={workflowEditingEdgeId}
|
||||
onEditingEdgeIdChange={setWorkflowEditingEdgeId}
|
||||
settingsOpen={workflowSettingsOpen}
|
||||
onSettingsOpenChange={setWorkflowSettingsOpen}
|
||||
debugOpen={workflowDebugOpen}
|
||||
onDebugOpenChange={(open) => {
|
||||
setWorkflowDebugOpen(open);
|
||||
@@ -1508,10 +1535,10 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-1 gap-6">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-5 overflow-y-auto pr-1">
|
||||
<div className="flex min-h-0 flex-1 gap-4">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
|
||||
<SectionCard
|
||||
icon={<Boxes size={18} />}
|
||||
icon={<Boxes size={15} />}
|
||||
title="Dify 应用配置"
|
||||
description="从「模型资源」中选择 Dify 应用。开场白、知识库、提示词等对话编排请在 Dify 平台配置,本页不重复设置。"
|
||||
>
|
||||
@@ -1525,7 +1552,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Brain size={18} />}
|
||||
icon={<Brain size={15} />}
|
||||
title="语音配置"
|
||||
description="从「模型资源」中选择语音识别与语音合成。大模型、知识库与开场白由 Dify 应用提供,请前往 Dify 平台配置。"
|
||||
>
|
||||
@@ -1546,7 +1573,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Sparkles size={18} />}
|
||||
icon={<Sparkles size={15} />}
|
||||
title="交互策略"
|
||||
description="设置实时视频对话时的交互体验"
|
||||
>
|
||||
@@ -1604,10 +1631,10 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-1 gap-6">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-5 overflow-y-auto pr-1">
|
||||
<div className="flex min-h-0 flex-1 gap-4">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
|
||||
<SectionCard
|
||||
icon={<Database size={18} />}
|
||||
icon={<Database size={15} />}
|
||||
title="FastGPT 应用配置"
|
||||
description="从「模型资源」中选择 FastGPT 应用。开场白、知识库、提示词等对话编排请在 FastGPT 平台配置,本页不重复设置。"
|
||||
>
|
||||
@@ -1621,7 +1648,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Brain size={18} />}
|
||||
icon={<Brain size={15} />}
|
||||
title="语音配置"
|
||||
description="从「模型资源」中选择语音识别与语音合成。大模型、知识库与开场白由 FastGPT 应用提供,请前往 FastGPT 平台配置。"
|
||||
>
|
||||
@@ -1642,7 +1669,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Sparkles size={18} />}
|
||||
icon={<Sparkles size={15} />}
|
||||
title="交互策略"
|
||||
description="设置实时视频对话时的交互体验"
|
||||
>
|
||||
@@ -1704,10 +1731,10 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="flex min-h-0 flex-1 gap-6">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-5 overflow-y-auto pr-1">
|
||||
<div className="flex min-h-0 flex-1 gap-4">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
|
||||
<SectionCard
|
||||
icon={<Terminal size={18} />}
|
||||
icon={<Terminal size={15} />}
|
||||
title="OpenCode 服务配置"
|
||||
description="从「模型资源」中选择 OpenCode 服务资源。"
|
||||
>
|
||||
@@ -1721,7 +1748,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<MessageSquareText size={18} />}
|
||||
icon={<MessageSquareText size={15} />}
|
||||
title="提示词"
|
||||
description="描述助手的角色、能力和回答要求"
|
||||
>
|
||||
@@ -1734,7 +1761,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Brain size={18} />}
|
||||
icon={<Brain size={15} />}
|
||||
title="模型与语音配置"
|
||||
description="配置 OpenCode 使用的大语言模型、语音识别与语音合成资源。"
|
||||
>
|
||||
@@ -1779,7 +1806,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Sparkles size={18} />}
|
||||
icon={<Sparkles size={15} />}
|
||||
title="交互策略"
|
||||
description="设置实时视频对话时的交互体验"
|
||||
>
|
||||
@@ -1843,10 +1870,10 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="flex min-h-0 flex-1 gap-6">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-5 overflow-y-auto pr-1">
|
||||
<div className="flex min-h-0 flex-1 gap-4">
|
||||
<div className="scrollbar-subtle min-w-0 flex-1 space-y-3 overflow-y-auto pr-1">
|
||||
<SectionCard>
|
||||
<div className="grid grid-cols-1 gap-4 md:grid-cols-2">
|
||||
<div className="grid grid-cols-1 gap-3 md:grid-cols-2">
|
||||
<div
|
||||
role="button"
|
||||
tabIndex={0}
|
||||
@@ -1858,25 +1885,25 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
}
|
||||
}}
|
||||
className={[
|
||||
"cursor-pointer rounded-2xl border p-5 text-left transition-colors",
|
||||
"cursor-pointer rounded-xl border p-3.5 text-left transition-colors",
|
||||
form.runtimeMode === "pipeline"
|
||||
? "border-primary bg-primary/5 ring-1 ring-primary"
|
||||
: "border-hairline bg-canvas-soft hover:border-hairline-strong",
|
||||
].join(" ")}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
<Waypoints size={18} />
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
<Waypoints size={15} />
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="font-medium text-foreground">Pipeline 模式</span>
|
||||
<span className="text-sm font-medium text-foreground">Pipeline 模式</span>
|
||||
<HelpHint text="通过 ASR、LLM 和 TTS 级联组成语音管线,灵活选配各模块。" />
|
||||
</div>
|
||||
</div>
|
||||
{form.runtimeMode === "pipeline" && (
|
||||
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground">
|
||||
<Check size={14} />
|
||||
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground">
|
||||
<Check size={12} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1893,25 +1920,25 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
}
|
||||
}}
|
||||
className={[
|
||||
"cursor-pointer rounded-2xl border p-5 text-left transition-colors",
|
||||
"cursor-pointer rounded-xl border p-3.5 text-left transition-colors",
|
||||
form.runtimeMode === "realtime"
|
||||
? "border-primary bg-primary/5 ring-1 ring-primary"
|
||||
: "border-hairline bg-canvas-soft hover:border-hairline-strong",
|
||||
].join(" ")}
|
||||
>
|
||||
<div className="flex items-center justify-between gap-3">
|
||||
<div className="flex items-center gap-3">
|
||||
<div className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
<AudioLines size={18} />
|
||||
<div className="flex items-center gap-2.5">
|
||||
<div className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
<AudioLines size={15} />
|
||||
</div>
|
||||
<div className="flex items-center gap-1.5">
|
||||
<span className="font-medium text-foreground">Realtime 模式</span>
|
||||
<span className="text-sm font-medium text-foreground">Realtime 模式</span>
|
||||
<HelpHint text="使用原生实时语音模型,模型直接处理音频输入并生成语音回复。" />
|
||||
</div>
|
||||
</div>
|
||||
{form.runtimeMode === "realtime" && (
|
||||
<span className="flex h-6 w-6 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground">
|
||||
<Check size={14} />
|
||||
<span className="flex h-5 w-5 shrink-0 items-center justify-center rounded-full bg-primary text-primary-foreground">
|
||||
<Check size={12} />
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
@@ -1920,7 +1947,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<MessageSquareText size={18} />}
|
||||
icon={<MessageSquareText size={15} />}
|
||||
title="提示词"
|
||||
description="描述助手的角色、能力和回答要求"
|
||||
>
|
||||
@@ -1938,7 +1965,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
|
||||
{form.runtimeMode === "pipeline" ? (
|
||||
<SectionCard
|
||||
icon={<Brain size={18} />}
|
||||
icon={<Brain size={15} />}
|
||||
title="模型配置"
|
||||
description="从「模型资源」中选择大语言模型、语音识别与语音合成"
|
||||
>
|
||||
@@ -1983,7 +2010,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
) : (
|
||||
<SectionCard
|
||||
icon={<Brain size={18} />}
|
||||
icon={<Brain size={15} />}
|
||||
title="模型配置"
|
||||
description="当前模式下 ASR 与 TTS 由 Realtime 模型内置完成"
|
||||
>
|
||||
@@ -1998,7 +2025,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
)}
|
||||
|
||||
<SectionCard
|
||||
icon={<Bot size={18} />}
|
||||
icon={<Bot size={15} />}
|
||||
title="开场白"
|
||||
description="助手与用户首次对话时的开场语"
|
||||
>
|
||||
@@ -2015,7 +2042,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
|
||||
{form.runtimeMode === "pipeline" && (
|
||||
<SectionCard
|
||||
icon={<Database size={18} />}
|
||||
icon={<Database size={15} />}
|
||||
title="知识库配置"
|
||||
description="选择助手回答时可检索的业务知识来源"
|
||||
>
|
||||
@@ -2041,7 +2068,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
)}
|
||||
|
||||
<SectionCard
|
||||
icon={<Wrench size={18} />}
|
||||
icon={<Wrench size={15} />}
|
||||
title="工具"
|
||||
description="配置该提示词助手可以调用的工具"
|
||||
>
|
||||
@@ -2053,7 +2080,7 @@ export function AssistantPage(props: AssistantPageProps) {
|
||||
</SectionCard>
|
||||
|
||||
<SectionCard
|
||||
icon={<Sparkles size={18} />}
|
||||
icon={<Sparkles size={15} />}
|
||||
title="交互策略"
|
||||
description="设置实时视频对话时的交互体验"
|
||||
>
|
||||
@@ -3377,29 +3404,6 @@ function EditableTitle({
|
||||
);
|
||||
}
|
||||
|
||||
function HelpHint({ text }: { text: string }) {
|
||||
return (
|
||||
<Popover>
|
||||
<PopoverTrigger asChild>
|
||||
<button
|
||||
type="button"
|
||||
aria-label="查看说明"
|
||||
onClick={(event) => event.stopPropagation()}
|
||||
className="flex h-5 w-5 items-center justify-center rounded-full text-muted-soft transition-colors hover:bg-surface-strong hover:text-foreground"
|
||||
>
|
||||
<HelpCircle size={14} />
|
||||
</button>
|
||||
</PopoverTrigger>
|
||||
<PopoverContent
|
||||
align="start"
|
||||
className="w-72 text-sm leading-6 text-muted-foreground"
|
||||
>
|
||||
{text}
|
||||
</PopoverContent>
|
||||
</Popover>
|
||||
);
|
||||
}
|
||||
|
||||
function DynamicVariableEditorHint({
|
||||
count,
|
||||
onOpen,
|
||||
@@ -3657,45 +3661,6 @@ function DynamicVariablesDialog({
|
||||
);
|
||||
}
|
||||
|
||||
function SectionCard({
|
||||
icon,
|
||||
title,
|
||||
description,
|
||||
children,
|
||||
}: {
|
||||
icon?: React.ReactNode;
|
||||
title?: string;
|
||||
description?: string;
|
||||
children: React.ReactNode;
|
||||
}) {
|
||||
const hasHeader = Boolean(title);
|
||||
|
||||
return (
|
||||
<Card className="rounded-2xl border-hairline bg-card text-card-foreground shadow-sm">
|
||||
{hasHeader && (
|
||||
<CardHeader>
|
||||
<div className="flex items-center gap-3">
|
||||
{icon && (
|
||||
<div className="flex h-10 w-10 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
{icon}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<div className="flex items-center gap-1.5">
|
||||
<CardTitle className="text-base font-medium">{title}</CardTitle>
|
||||
{description && <HelpHint text={description} />}
|
||||
</div>
|
||||
</div>
|
||||
</CardHeader>
|
||||
)}
|
||||
|
||||
<CardContent className={hasHeader ? "space-y-4" : undefined}>
|
||||
{children}
|
||||
</CardContent>
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
function TextAreaField({
|
||||
label,
|
||||
value,
|
||||
@@ -3712,7 +3677,7 @@ function TextAreaField({
|
||||
return (
|
||||
<label className="block">
|
||||
{label && (
|
||||
<div className="mb-2 text-sm font-medium text-foreground">{label}</div>
|
||||
<div className="mb-1.5 text-sm font-medium text-foreground">{label}</div>
|
||||
)}
|
||||
<Textarea
|
||||
value={value}
|
||||
@@ -3721,7 +3686,7 @@ function TextAreaField({
|
||||
rows={rows}
|
||||
// Override ui/textarea's field-sizing-content so `rows` sets a real height
|
||||
// instead of collapsing to min-h-16 when the value is short.
|
||||
className="field-sizing-fixed min-h-32 resize-y border-hairline-strong bg-background text-foreground placeholder:text-muted-soft"
|
||||
className="field-sizing-fixed min-h-28 resize-y border-hairline-strong bg-background text-sm text-foreground placeholder:text-muted-soft"
|
||||
/>
|
||||
</label>
|
||||
);
|
||||
@@ -3747,7 +3712,7 @@ function ResourceSelectField({
|
||||
return (
|
||||
<div className="block">
|
||||
{label && (
|
||||
<div className="mb-2 text-sm font-medium text-foreground">{label}</div>
|
||||
<div className="mb-1.5 text-sm font-medium text-foreground">{label}</div>
|
||||
)}
|
||||
|
||||
<Select
|
||||
@@ -4056,18 +4021,18 @@ function ToggleRow({
|
||||
<div
|
||||
className={[
|
||||
"flex items-center justify-between border border-hairline bg-canvas-soft",
|
||||
hasIcon ? "rounded-2xl p-5" : "rounded-xl p-4",
|
||||
hasIcon ? "rounded-xl p-3.5" : "rounded-xl px-3.5 py-3",
|
||||
].join(" ")}
|
||||
>
|
||||
<div>
|
||||
<div
|
||||
className={[
|
||||
"flex items-center font-medium text-foreground",
|
||||
hasIcon ? "gap-3" : "gap-1.5",
|
||||
"flex items-center text-sm font-medium text-foreground",
|
||||
hasIcon ? "gap-2.5" : "gap-1.5",
|
||||
].join(" ")}
|
||||
>
|
||||
{icon && (
|
||||
<span className="flex h-10 w-10 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
<span className="flex h-8 w-8 shrink-0 items-center justify-center rounded-full bg-surface-strong text-foreground">
|
||||
{icon}
|
||||
</span>
|
||||
)}
|
||||
@@ -4077,7 +4042,7 @@ function ToggleRow({
|
||||
</span>
|
||||
</div>
|
||||
{description && (
|
||||
<div className="mt-1 text-sm text-muted-foreground">
|
||||
<div className="mt-1 text-xs text-muted-foreground">
|
||||
{description}
|
||||
</div>
|
||||
)}
|
||||
|
||||
Reference in New Issue
Block a user