fix(toolset): 启动时自动补种系统工具集,工具集页面移至智能体侧边栏
- init_state_machine 启动时检查 DB 并补种 system_basic/system_chat/system_workflow - 修复 postgres facade 缺少 is_system/category 参数的问题 - 前端工具集从"插件"独立为侧边栏"工具集"tab,位于智能体和插件之间 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,7 @@ import { SetupGuideModal } from './components/Layout/SetupGuideModal';
|
|||||||
import { SettingsLayout } from './components/Settings/SettingsLayout';
|
import { SettingsLayout } from './components/Settings/SettingsLayout';
|
||||||
import { AgentLayout } from './components/Agent/AgentLayout';
|
import { AgentLayout } from './components/Agent/AgentLayout';
|
||||||
import { PluginLayout } from './components/Plugin/PluginLayout';
|
import { PluginLayout } from './components/Plugin/PluginLayout';
|
||||||
|
import { ToolSettings } from './components/Plugin/ToolSettings';
|
||||||
import { WorkflowConfigSettings } from './components/Agent/WorkflowConfigSettings';
|
import { WorkflowConfigSettings } from './components/Agent/WorkflowConfigSettings';
|
||||||
import { SystemLogsView } from './components/Agent/SystemLogsView';
|
import { SystemLogsView } from './components/Agent/SystemLogsView';
|
||||||
import { LeftPanel } from './components/Chat/LeftPanel';
|
import { LeftPanel } from './components/Chat/LeftPanel';
|
||||||
@@ -97,6 +98,12 @@ function App() {
|
|||||||
|
|
||||||
{mode === 'agent' && agentTab === 'agents' && <AgentLayout />}
|
{mode === 'agent' && agentTab === 'agents' && <AgentLayout />}
|
||||||
|
|
||||||
|
{mode === 'agent' && agentTab === 'toolsets' && (
|
||||||
|
<div className="flex-1 overflow-y-auto p-8">
|
||||||
|
<ToolSettings />
|
||||||
|
</div>
|
||||||
|
)}
|
||||||
|
|
||||||
{mode === 'agent' && agentTab === 'plugin' && <PluginLayout />}
|
{mode === 'agent' && agentTab === 'plugin' && <PluginLayout />}
|
||||||
|
|
||||||
{mode === 'agent' && agentTab === 'config' && (
|
{mode === 'agent' && agentTab === 'config' && (
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { MessageSquare, Workflow, Box, Bot, ChevronLeft, ChevronRight, Settings, ScrollText } from 'lucide-react';
|
import { MessageSquare, Workflow, Box, Bot, ChevronLeft, ChevronRight, Settings, ScrollText, Wrench } from 'lucide-react';
|
||||||
import { useAppStore } from '../../store/useAppStore';
|
import { useAppStore } from '../../store/useAppStore';
|
||||||
|
|
||||||
export function CollapsibleSidebar() {
|
export function CollapsibleSidebar() {
|
||||||
@@ -20,8 +20,9 @@ export function CollapsibleSidebar() {
|
|||||||
{ key: 'workflow', label: t('nav.workflow'), icon: Workflow },
|
{ key: 'workflow', label: t('nav.workflow'), icon: Workflow },
|
||||||
]
|
]
|
||||||
: [
|
: [
|
||||||
{ key: 'plugin', label: t('nav.plugin'), icon: Box },
|
|
||||||
{ key: 'agents', label: t('nav.agents'), icon: Bot },
|
{ key: 'agents', label: t('nav.agents'), icon: Bot },
|
||||||
|
{ key: 'toolsets', label: t('nav.toolsets'), icon: Wrench },
|
||||||
|
{ key: 'plugin', label: t('nav.plugin'), icon: Box },
|
||||||
{ key: 'config', label: t('nav.config'), icon: Settings },
|
{ key: 'config', label: t('nav.config'), icon: Settings },
|
||||||
{ key: 'logs', label: t('nav.logs'), icon: ScrollText },
|
{ key: 'logs', label: t('nav.logs'), icon: ScrollText },
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,37 +1,16 @@
|
|||||||
import { useTranslation } from 'react-i18next';
|
import { useTranslation } from 'react-i18next';
|
||||||
import { useAppStore } from '../../store/useAppStore';
|
|
||||||
import { SkillSettings } from './SkillSettings';
|
import { SkillSettings } from './SkillSettings';
|
||||||
import { ToolSettings } from './ToolSettings';
|
|
||||||
|
|
||||||
export function PluginLayout() {
|
export function PluginLayout() {
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const { resourceTab, setResourceTab } = useAppStore();
|
|
||||||
|
|
||||||
const tabs = [
|
|
||||||
{ key: 'skill', label: t('agent.skills') },
|
|
||||||
{ key: 'tool', label: t('agent.tools') },
|
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex-1 flex flex-col bg-bg-secondary overflow-hidden">
|
<div className="flex-1 flex flex-col bg-bg-secondary overflow-hidden">
|
||||||
<div className="h-12 border-b border-border-primary bg-bg-card/80 backdrop-blur flex items-center px-6 shrink-0 gap-1">
|
<div className="h-12 border-b border-border-primary bg-bg-card/80 backdrop-blur flex items-center px-6 shrink-0">
|
||||||
{tabs.map((tab) => (
|
<span className="text-xs font-semibold text-text-primary">{t('plugin.skillManagement')}</span>
|
||||||
<button
|
|
||||||
key={tab.key}
|
|
||||||
onClick={() => setResourceTab(tab.key)}
|
|
||||||
className={`px-4 py-2 text-xs font-semibold rounded-lg transition-all ${
|
|
||||||
resourceTab === tab.key
|
|
||||||
? 'bg-accent-light text-accent'
|
|
||||||
: 'text-text-muted hover:text-text-secondary hover:bg-bg-hover'
|
|
||||||
}`}
|
|
||||||
>
|
|
||||||
{tab.label}
|
|
||||||
</button>
|
|
||||||
))}
|
|
||||||
</div>
|
</div>
|
||||||
<div className="flex-1 overflow-y-auto p-8">
|
<div className="flex-1 overflow-y-auto p-8">
|
||||||
{resourceTab === 'skill' && <SkillSettings />}
|
<SkillSettings />
|
||||||
{resourceTab === 'tool' && <ToolSettings />}
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"workflow": "Workflow",
|
"workflow": "Workflow",
|
||||||
"plugin": "Plugin",
|
"plugin": "Plugin",
|
||||||
"agents": "Agents",
|
"agents": "Agents",
|
||||||
|
"toolsets": "Toolsets",
|
||||||
"config": "Config",
|
"config": "Config",
|
||||||
"logs": "Logs",
|
"logs": "Logs",
|
||||||
"settings": "Settings"
|
"settings": "Settings"
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"workflow": "工作流",
|
"workflow": "工作流",
|
||||||
"plugin": "插件",
|
"plugin": "插件",
|
||||||
"agents": "智能体",
|
"agents": "智能体",
|
||||||
|
"toolsets": "工具集",
|
||||||
"config": "配置",
|
"config": "配置",
|
||||||
"logs": "日志",
|
"logs": "日志",
|
||||||
"settings": "设置"
|
"settings": "设置"
|
||||||
|
|||||||
@@ -67,14 +67,58 @@ class GlobalStateMachine:
|
|||||||
# Tool configs
|
# Tool configs
|
||||||
cfg_rows = await self.postgres_database.list_tool_configs_db.remote()
|
cfg_rows = await self.postgres_database.list_tool_configs_db.remote()
|
||||||
self._tool_configs = {row["tool_name"]: row["config"] for row in cfg_rows}
|
self._tool_configs = {row["tool_name"]: row["config"] for row in cfg_rows}
|
||||||
# Custom toolsets
|
# Custom toolsets(含系统预置)
|
||||||
ts_rows = await self.postgres_database.list_custom_toolsets.remote()
|
ts_rows = await self.postgres_database.list_custom_toolsets.remote()
|
||||||
self._custom_toolsets = {row["toolset_id"]: row for row in ts_rows}
|
self._custom_toolsets = {row["toolset_id"]: row for row in ts_rows}
|
||||||
|
# 补种系统预置工具集(首次启动或 DB 被 create_all 重建后)
|
||||||
|
await self._seed_system_toolsets()
|
||||||
# 让 tool_manager 立刻把 custom toolset 装配成 FunctionToolset
|
# 让 tool_manager 立刻把 custom toolset 装配成 FunctionToolset
|
||||||
self._global_tool_manager.rebuild_custom_toolsets(self._custom_toolsets)
|
self._global_tool_manager.rebuild_custom_toolsets(self._custom_toolsets)
|
||||||
# 启动期一次性发布 v1 快照,让等待中的读端立刻可用
|
# 启动期一次性发布 v1 快照,让等待中的读端立刻可用
|
||||||
self._publish_snapshot()
|
self._publish_snapshot()
|
||||||
|
|
||||||
|
_SYSTEM_TOOLSETS = [
|
||||||
|
{
|
||||||
|
"toolset_id": "system_basic",
|
||||||
|
"name": "系统基础工具集",
|
||||||
|
"description": "文件读写、搜索、代码执行等基础能力",
|
||||||
|
"tools": ["file_reader", "write_file", "edit_file", "search_file", "python_executor", "shell_executor"],
|
||||||
|
"is_system": True,
|
||||||
|
"category": "system_basic",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"toolset_id": "system_chat",
|
||||||
|
"name": "系统对话工具集",
|
||||||
|
"description": "对话场景专用工具(发送文件等)",
|
||||||
|
"tools": ["send_file"],
|
||||||
|
"is_system": True,
|
||||||
|
"category": "system_chat",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"toolset_id": "system_workflow",
|
||||||
|
"name": "系统工作流工具集",
|
||||||
|
"description": "工作流场景专用工具(审批等)",
|
||||||
|
"tools": ["approval"],
|
||||||
|
"is_system": True,
|
||||||
|
"category": "system_workflow",
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
async def _seed_system_toolsets(self):
|
||||||
|
"""若 DB 中缺少系统预置工具集则自动补种。"""
|
||||||
|
for seed in self._SYSTEM_TOOLSETS:
|
||||||
|
if seed["toolset_id"] not in self._custom_toolsets:
|
||||||
|
await self.postgres_database.upsert_custom_toolset.remote(
|
||||||
|
toolset_id=seed["toolset_id"],
|
||||||
|
name=seed["name"],
|
||||||
|
tools=seed["tools"],
|
||||||
|
description=seed["description"],
|
||||||
|
owner_id=None,
|
||||||
|
is_system=True,
|
||||||
|
category=seed["category"],
|
||||||
|
)
|
||||||
|
self._custom_toolsets[seed["toolset_id"]] = seed
|
||||||
|
|
||||||
# ─── Snapshot 发布(Object Store 读路径) ────────────────────
|
# ─── Snapshot 发布(Object Store 读路径) ────────────────────
|
||||||
|
|
||||||
def _build_snapshot(self) -> GSMSnapshot:
|
def _build_snapshot(self) -> GSMSnapshot:
|
||||||
|
|||||||
@@ -376,8 +376,10 @@ class PostgresDatabase:
|
|||||||
tools: list,
|
tools: list,
|
||||||
description: str = None,
|
description: str = None,
|
||||||
owner_id: str = None,
|
owner_id: str = None,
|
||||||
|
is_system: bool = False,
|
||||||
|
category: str = "user",
|
||||||
):
|
):
|
||||||
"""插入或更新一个用户自定义工具组。"""
|
"""插入或更新一个工具组(系统预置或用户自定义)。"""
|
||||||
await self.ready_event.wait()
|
await self.ready_event.wait()
|
||||||
return await self._custom_toolset_database.upsert(
|
return await self._custom_toolset_database.upsert(
|
||||||
toolset_id=toolset_id,
|
toolset_id=toolset_id,
|
||||||
@@ -385,6 +387,8 @@ class PostgresDatabase:
|
|||||||
tools=tools,
|
tools=tools,
|
||||||
description=description,
|
description=description,
|
||||||
owner_id=owner_id,
|
owner_id=owner_id,
|
||||||
|
is_system=is_system,
|
||||||
|
category=category,
|
||||||
)
|
)
|
||||||
|
|
||||||
async def get_custom_toolset(self, toolset_id: str):
|
async def get_custom_toolset(self, toolset_id: str):
|
||||||
|
|||||||
Reference in New Issue
Block a user