Update assistant tool setting ui
This commit is contained in:
@@ -65,6 +65,7 @@ export const AssistantsPage: React.FC = () => {
|
||||
const [activeTab, setActiveTab] = useState<TabValue>(TabValue.GLOBAL);
|
||||
const [debugOpen, setDebugOpen] = useState(false);
|
||||
const [hotwordInput, setHotwordInput] = useState('');
|
||||
const [toolPickerOpen, setToolPickerOpen] = useState(false);
|
||||
|
||||
// Publish Modal State
|
||||
const [isPublishModalOpen, setIsPublishModalOpen] = useState(false);
|
||||
@@ -235,6 +236,11 @@ export const AssistantsPage: React.FC = () => {
|
||||
|
||||
const systemTools = tools.filter((t) => t.enabled !== false && t.category === 'system');
|
||||
const queryTools = tools.filter((t) => t.enabled !== false && t.category === 'query');
|
||||
const selectedToolIds = selectedAssistant?.tools || [];
|
||||
const activeSystemTools = systemTools.filter((tool) => selectedToolIds.includes(tool.id));
|
||||
const activeQueryTools = queryTools.filter((tool) => selectedToolIds.includes(tool.id));
|
||||
const availableSystemTools = systemTools.filter((tool) => !selectedToolIds.includes(tool.id));
|
||||
const availableQueryTools = queryTools.filter((tool) => !selectedToolIds.includes(tool.id));
|
||||
|
||||
const isExternalConfig = selectedAssistant?.configMode === 'dify' || selectedAssistant?.configMode === 'fastgpt';
|
||||
const isNoneConfig = selectedAssistant?.configMode === 'none' || !selectedAssistant?.configMode;
|
||||
@@ -742,6 +748,20 @@ export const AssistantsPage: React.FC = () => {
|
||||
|
||||
{activeTab === TabValue.TOOLS && selectedAssistant.configMode === 'platform' && (
|
||||
<div className="space-y-8 animate-in fade-in">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-[10px] font-black flex items-center text-white uppercase tracking-[0.2em]">
|
||||
<Wrench className="w-3.5 h-3.5 mr-2 text-primary" /> 已启用工具
|
||||
</h3>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setToolPickerOpen((v) => !v)}
|
||||
className="h-7 w-7 rounded-full border border-white/15 bg-white/5 text-muted-foreground hover:text-white hover:border-primary/50 hover:bg-primary/10 flex items-center justify-center transition-colors"
|
||||
title="添加工具"
|
||||
>
|
||||
<Plus className="w-3.5 h-3.5" />
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div className="space-y-4">
|
||||
<div className="flex items-center justify-between">
|
||||
<h3 className="text-[10px] font-black flex items-center text-primary uppercase tracking-[0.2em]">
|
||||
@@ -749,35 +769,33 @@ export const AssistantsPage: React.FC = () => {
|
||||
</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
{systemTools.map(tool => (
|
||||
<div
|
||||
{activeSystemTools.map(tool => (
|
||||
<div
|
||||
key={tool.id}
|
||||
onClick={() => toggleTool(tool.id)}
|
||||
className={`p-4 rounded-xl border transition-all cursor-pointer group relative flex items-start space-x-3 ${selectedAssistant.tools?.includes(tool.id) ? 'bg-primary/10 border-primary/40 shadow-[0_0_15px_rgba(6,182,212,0.1)]' : 'bg-card/30 border-white/5 hover:bg-white/5 hover:border-white/10'}`}
|
||||
className="p-4 rounded-xl border border-primary/40 bg-primary/10 shadow-[0_0_15px_rgba(6,182,212,0.1)] relative flex items-start space-x-3"
|
||||
>
|
||||
<div className={`p-2 rounded-lg shrink-0 transition-colors ${selectedAssistant.tools?.includes(tool.id) ? 'bg-primary text-primary-foreground' : 'bg-white/5 text-muted-foreground'}`}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => removeImportedTool(e, tool)}
|
||||
className="absolute -top-1 -right-1 p-0.5 rounded-full bg-destructive text-white hover:scale-110 transition-transform shadow-lg z-10"
|
||||
title="移除工具"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
<div className="p-2 rounded-lg shrink-0 bg-primary text-primary-foreground">
|
||||
{renderToolIcon(tool.icon)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between mb-0.5">
|
||||
<span className="text-sm font-bold text-white">{tool.name}</span>
|
||||
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center transition-all ${selectedAssistant.tools?.includes(tool.id) ? 'border-primary bg-primary' : 'border-white/10'}`}>
|
||||
{selectedAssistant.tools?.includes(tool.id) && <div className="w-1.5 h-1.5 bg-white rounded-full"></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-white">{tool.name}</div>
|
||||
<p className="text-[10px] text-muted-foreground line-clamp-1 opacity-70">{tool.description}</p>
|
||||
</div>
|
||||
{selectedAssistant.tools?.includes(tool.id) && (
|
||||
<button
|
||||
onClick={(e) => removeImportedTool(e, tool)}
|
||||
className="absolute -top-1 -right-1 p-0.5 rounded-full bg-destructive text-white opacity-0 group-hover:opacity-100 transition-opacity hover:scale-110 shadow-lg z-10"
|
||||
title="从当前小助手移除"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{activeSystemTools.length === 0 && (
|
||||
<div className="col-span-full p-4 rounded-xl border border-dashed border-white/10 text-xs text-muted-foreground">
|
||||
暂未启用系统指令工具
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -788,37 +806,98 @@ export const AssistantsPage: React.FC = () => {
|
||||
</h3>
|
||||
</div>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||||
{queryTools.map(tool => (
|
||||
<div
|
||||
{activeQueryTools.map(tool => (
|
||||
<div
|
||||
key={tool.id}
|
||||
onClick={() => toggleTool(tool.id)}
|
||||
className={`p-4 rounded-xl border transition-all cursor-pointer group relative flex items-start space-x-3 ${selectedAssistant.tools?.includes(tool.id) ? 'bg-blue-500/10 border-blue-500/40 shadow-[0_0_15px_rgba(59,130,246,0.1)]' : 'bg-card/30 border-white/5 hover:bg-white/5 hover:border-white/10'}`}
|
||||
className="p-4 rounded-xl border border-blue-500/40 bg-blue-500/10 shadow-[0_0_15px_rgba(59,130,246,0.1)] relative flex items-start space-x-3"
|
||||
>
|
||||
<div className={`p-2 rounded-lg shrink-0 transition-colors ${selectedAssistant.tools?.includes(tool.id) ? 'bg-blue-500 text-white' : 'bg-white/5 text-muted-foreground'}`}>
|
||||
<button
|
||||
type="button"
|
||||
onClick={(e) => removeImportedTool(e, tool)}
|
||||
className="absolute -top-1 -right-1 p-0.5 rounded-full bg-destructive text-white hover:scale-110 transition-transform shadow-lg z-10"
|
||||
title="移除工具"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
<div className="p-2 rounded-lg shrink-0 bg-blue-500 text-white">
|
||||
{renderToolIcon(tool.icon)}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between mb-0.5">
|
||||
<span className="text-sm font-bold text-white">{tool.name}</span>
|
||||
<div className={`w-4 h-4 rounded-full border-2 flex items-center justify-center transition-all ${selectedAssistant.tools?.includes(tool.id) ? 'border-blue-500 bg-blue-500' : 'border-white/10'}`}>
|
||||
{selectedAssistant.tools?.includes(tool.id) && <div className="w-1.5 h-1.5 bg-white rounded-full"></div>}
|
||||
</div>
|
||||
</div>
|
||||
<div className="text-sm font-bold text-white">{tool.name}</div>
|
||||
<p className="text-[10px] text-muted-foreground line-clamp-1 opacity-70">{tool.description}</p>
|
||||
</div>
|
||||
{selectedAssistant.tools?.includes(tool.id) && (
|
||||
<button
|
||||
onClick={(e) => removeImportedTool(e, tool)}
|
||||
className="absolute -top-1 -right-1 p-0.5 rounded-full bg-destructive text-white opacity-0 group-hover:opacity-100 transition-opacity hover:scale-110 shadow-lg z-10"
|
||||
title="从当前小助手移除"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{activeQueryTools.length === 0 && (
|
||||
<div className="col-span-full p-4 rounded-xl border border-dashed border-white/10 text-xs text-muted-foreground">
|
||||
暂未启用信息查询工具
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{toolPickerOpen && (
|
||||
<div className="space-y-6 p-4 rounded-xl border border-white/10 bg-black/20">
|
||||
<div className="flex items-center justify-between">
|
||||
<h4 className="text-[10px] font-black uppercase tracking-[0.2em] text-muted-foreground">添加工具</h4>
|
||||
<button
|
||||
type="button"
|
||||
onClick={() => setToolPickerOpen(false)}
|
||||
className="h-6 w-6 rounded-full border border-white/10 bg-white/5 text-muted-foreground hover:text-white hover:border-white/30 flex items-center justify-center"
|
||||
>
|
||||
<X className="w-3 h-3" />
|
||||
</button>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<h5 className="text-[10px] font-black flex items-center text-primary uppercase tracking-[0.2em]">
|
||||
<Wrench className="w-3.5 h-3.5 mr-2" /> 系统指令可选
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{availableSystemTools.map((tool) => (
|
||||
<button
|
||||
key={tool.id}
|
||||
type="button"
|
||||
onClick={() => toggleTool(tool.id)}
|
||||
className="text-left p-3 rounded-lg border border-white/10 bg-white/5 hover:bg-primary/10 hover:border-primary/40 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-md bg-white/10 text-primary">{renderToolIcon(tool.icon)}</div>
|
||||
<div className="text-sm font-bold text-white">{tool.name}</div>
|
||||
</div>
|
||||
<p className="text-[10px] text-muted-foreground mt-1 line-clamp-1">{tool.description}</p>
|
||||
</button>
|
||||
))}
|
||||
{availableSystemTools.length === 0 && (
|
||||
<div className="col-span-full text-xs text-muted-foreground">没有可添加的系统指令工具</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
<div className="space-y-3">
|
||||
<h5 className="text-[10px] font-black flex items-center text-blue-400 uppercase tracking-[0.2em]">
|
||||
<TrendingUp className="w-3.5 h-3.5 mr-2" /> 信息查询可选
|
||||
</h5>
|
||||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-3">
|
||||
{availableQueryTools.map((tool) => (
|
||||
<button
|
||||
key={tool.id}
|
||||
type="button"
|
||||
onClick={() => toggleTool(tool.id)}
|
||||
className="text-left p-3 rounded-lg border border-white/10 bg-white/5 hover:bg-blue-500/10 hover:border-blue-500/40 transition-colors"
|
||||
>
|
||||
<div className="flex items-center gap-2">
|
||||
<div className="p-1.5 rounded-md bg-white/10 text-blue-300">{renderToolIcon(tool.icon)}</div>
|
||||
<div className="text-sm font-bold text-white">{tool.name}</div>
|
||||
</div>
|
||||
<p className="text-[10px] text-muted-foreground mt-1 line-clamp-1">{tool.description}</p>
|
||||
</button>
|
||||
))}
|
||||
{availableQueryTools.length === 0 && (
|
||||
<div className="col-span-full text-xs text-muted-foreground">没有可添加的信息查询工具</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
<div className="p-4 bg-white/5 border border-white/5 rounded-xl text-[10px] text-muted-foreground flex items-center gap-3">
|
||||
<Rocket className="w-4 h-4 text-primary shrink-0" />
|
||||
<span>提示:此处仅导入工具库中的已有工具。移除仅对当前小助手生效,不会删除工具库。</span>
|
||||
|
||||
@@ -92,6 +92,57 @@ export const ToolLibraryPage: React.FC = () => {
|
||||
const matchesCategory = categoryFilter === 'all' || tool.category === categoryFilter;
|
||||
return matchesSearch && matchesCategory;
|
||||
});
|
||||
const systemTools = filteredTools.filter((tool) => tool.category === 'system');
|
||||
const queryTools = filteredTools.filter((tool) => tool.category === 'query');
|
||||
|
||||
const renderToolCard = (tool: Tool) => (
|
||||
<div
|
||||
key={tool.id}
|
||||
className="p-5 rounded-xl border transition-all relative bg-card/30 border-white/5 hover:bg-white/5 hover:border-white/10 hover:shadow-lg"
|
||||
>
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className={`p-3 rounded-lg shrink-0 transition-colors ${tool.category === 'system' ? 'bg-primary/10 text-primary' : 'bg-blue-500/10 text-blue-400'}`}>
|
||||
{iconMap[tool.icon] || <Box className="w-5 h-5" />}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between mb-1 gap-2">
|
||||
<span className="text-base font-bold text-white truncate">{tool.name}</span>
|
||||
{tool.isSystem ? <Badge variant="outline" className="text-[9px] h-4 px-1">SYSTEM</Badge> : <Badge variant="outline" className="text-[9px] h-4 px-1">CUSTOM</Badge>}
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Badge variant="outline" className={`text-[10px] border-0 px-0 ${tool.category === 'system' ? 'text-primary' : 'text-blue-400'}`}>
|
||||
{tool.category === 'system' ? 'SYSTEM' : 'QUERY'}
|
||||
</Badge>
|
||||
<span className="text-[10px] text-muted-foreground font-mono opacity-50 truncate">ID: {tool.id}</span>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed opacity-80">{tool.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 pt-3 border-t border-white/10 flex items-center justify-between">
|
||||
<span className="text-[11px] text-muted-foreground">system/query 仅表示执行类型</span>
|
||||
<div className="flex space-x-1">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openEdit(tool);
|
||||
}}
|
||||
title="编辑工具"
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-primary/20 text-muted-foreground hover:text-primary"
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => handleDeleteTool(e, tool)}
|
||||
title="删除工具"
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-destructive/20 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
const handleSaveTool = async () => {
|
||||
if (!toolName.trim()) {
|
||||
@@ -202,70 +253,51 @@ export const ToolLibraryPage: React.FC = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{!isLoading && filteredTools.map((tool) => (
|
||||
<div
|
||||
key={tool.id}
|
||||
className="p-5 rounded-xl border transition-all relative bg-card/30 border-white/5 hover:bg-white/5 hover:border-white/10 hover:shadow-lg"
|
||||
>
|
||||
<div className="flex items-start space-x-4">
|
||||
<div className={`p-3 rounded-lg shrink-0 transition-colors ${tool.category === 'system' ? 'bg-primary/10 text-primary' : 'bg-blue-500/10 text-blue-400'}`}>
|
||||
{iconMap[tool.icon] || <Box className="w-5 h-5" />}
|
||||
</div>
|
||||
<div className="flex-1 min-w-0">
|
||||
<div className="flex items-center justify-between mb-1 gap-2">
|
||||
<span className="text-base font-bold text-white truncate">{tool.name}</span>
|
||||
{tool.isSystem ? <Badge variant="outline" className="text-[9px] h-4 px-1">SYSTEM</Badge> : <Badge variant="outline" className="text-[9px] h-4 px-1">CUSTOM</Badge>}
|
||||
{isLoading ? (
|
||||
<div className="py-12 flex flex-col items-center justify-center text-muted-foreground opacity-70">
|
||||
<Wrench className="w-12 h-12 mb-4 stroke-1 animate-pulse" />
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
) : filteredTools.length === 0 ? (
|
||||
<div className="py-12 flex flex-col items-center justify-center text-muted-foreground opacity-50">
|
||||
<Wrench className="w-12 h-12 mb-4 stroke-1" />
|
||||
<p>未找到相关工具</p>
|
||||
</div>
|
||||
) : (
|
||||
<div className="space-y-8">
|
||||
{(categoryFilter === 'all' || categoryFilter === 'system') && (
|
||||
<section className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-sm font-black uppercase tracking-wider text-primary">System Command</h2>
|
||||
<Badge variant="outline" className="text-[10px]">{systemTools.length} tools</Badge>
|
||||
</div>
|
||||
<div className="flex items-center gap-2 mb-2">
|
||||
<Badge variant="outline" className={`text-[10px] border-0 px-0 ${tool.category === 'system' ? 'text-primary' : 'text-blue-400'}`}>
|
||||
{tool.category === 'system' ? 'SYSTEM' : 'QUERY'}
|
||||
</Badge>
|
||||
<span className="text-[10px] text-muted-foreground font-mono opacity-50 truncate">ID: {tool.id}</span>
|
||||
{systemTools.length === 0 ? (
|
||||
<div className="rounded-lg border border-white/10 bg-black/20 p-4 text-xs text-muted-foreground">当前筛选条件下无系统指令工具。</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{systemTools.map(renderToolCard)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
|
||||
{(categoryFilter === 'all' || categoryFilter === 'query') && (
|
||||
<section className="space-y-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<h2 className="text-sm font-black uppercase tracking-wider text-blue-300">Information Query</h2>
|
||||
<Badge variant="outline" className="text-[10px]">{queryTools.length} tools</Badge>
|
||||
</div>
|
||||
<p className="text-xs text-muted-foreground line-clamp-2 leading-relaxed opacity-80">{tool.description}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className="mt-4 pt-3 border-t border-white/10 flex items-center justify-between">
|
||||
<span className="text-[11px] text-muted-foreground">system/query 仅表示执行类型</span>
|
||||
<div className="flex space-x-1">
|
||||
<button
|
||||
onClick={(e) => {
|
||||
e.stopPropagation();
|
||||
openEdit(tool);
|
||||
}}
|
||||
title="编辑工具"
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-primary/20 text-muted-foreground hover:text-primary"
|
||||
>
|
||||
<Edit2 className="w-4 h-4" />
|
||||
</button>
|
||||
<button
|
||||
onClick={(e) => handleDeleteTool(e, tool)}
|
||||
title="删除工具"
|
||||
className="p-1.5 rounded-md transition-colors hover:bg-destructive/20 text-muted-foreground hover:text-destructive"
|
||||
>
|
||||
<Trash2 className="w-4 h-4" />
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
|
||||
{!isLoading && filteredTools.length === 0 && (
|
||||
<div className="col-span-full py-12 flex flex-col items-center justify-center text-muted-foreground opacity-50">
|
||||
<Wrench className="w-12 h-12 mb-4 stroke-1" />
|
||||
<p>未找到相关工具</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{isLoading && (
|
||||
<div className="col-span-full py-12 flex flex-col items-center justify-center text-muted-foreground opacity-70">
|
||||
<Wrench className="w-12 h-12 mb-4 stroke-1 animate-pulse" />
|
||||
<p>加载中...</p>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
{queryTools.length === 0 ? (
|
||||
<div className="rounded-lg border border-white/10 bg-black/20 p-4 text-xs text-muted-foreground">当前筛选条件下无信息查询工具。</div>
|
||||
) : (
|
||||
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
{queryTools.map(renderToolCard)}
|
||||
</div>
|
||||
)}
|
||||
</section>
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
|
||||
<Dialog
|
||||
isOpen={isToolModalOpen}
|
||||
|
||||
Reference in New Issue
Block a user