添加代理执行和模型配置:创建代理执行控制台UI和API,扩展config模型添加default_model/default_temperature/enable_streaming字段
This commit is contained in:
parent
ee4b416b50
commit
3e33bc0924
@ -80,6 +80,29 @@
|
|||||||
"nullable": "no",
|
"nullable": "no",
|
||||||
"default": "30"
|
"default": "30"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name": "default_model",
|
||||||
|
"title": "Default LLM model for agent tasks",
|
||||||
|
"type": "str",
|
||||||
|
"length": 64,
|
||||||
|
"nullable": "yes",
|
||||||
|
"default": "qwen3-max"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_temperature",
|
||||||
|
"title": "Default temperature for LLM calls",
|
||||||
|
"type": "float",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "0.7"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enable_streaming",
|
||||||
|
"title": "Enable streaming response for LLM calls",
|
||||||
|
"type": "str",
|
||||||
|
"length": "1",
|
||||||
|
"nullable": "no",
|
||||||
|
"default": "1"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name": "created_at",
|
"name": "created_at",
|
||||||
"title": "Creation timestamp",
|
"title": "Creation timestamp",
|
||||||
|
|||||||
@ -12,10 +12,14 @@
|
|||||||
"css": "ios-navbar",
|
"css": "ios-navbar",
|
||||||
"items": [
|
"items": [
|
||||||
{
|
{
|
||||||
"text": "Configuration",
|
"widgettype": "Text",
|
||||||
"icon": "settings",
|
"options": {
|
||||||
"css": "ios-navbar-title",
|
"text": "Configuration",
|
||||||
"disabled": true
|
"css": "ios-navbar-title",
|
||||||
|
"fontSize": "18px",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
"color": "#059669"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@ -23,7 +27,7 @@
|
|||||||
{
|
{
|
||||||
"widgettype": "urlwidget",
|
"widgettype": "urlwidget",
|
||||||
"options": {
|
"options": {
|
||||||
"url": "{{entire_url('harnessed_agent_config_view')}}",
|
"url": "{{entire_url('agent_config_form.ui')}}",
|
||||||
"width": "100%",
|
"width": "100%",
|
||||||
"height": "100%"
|
"height": "100%"
|
||||||
}
|
}
|
||||||
|
|||||||
114
wwwroot/agent_config_form.ui
Normal file
114
wwwroot/agent_config_form.ui
Normal file
@ -0,0 +1,114 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "TabPanel",
|
||||||
|
"options": {
|
||||||
|
"tab_pos": "top",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"name": "agent_config",
|
||||||
|
"label": "代理配置",
|
||||||
|
"icon": "settings",
|
||||||
|
"content": {
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"padding": "16px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Form",
|
||||||
|
"id": "agent_config_form",
|
||||||
|
"options": {
|
||||||
|
"data_url": "{{entire_url('../api/agent_config_get.dspy')}}",
|
||||||
|
"data_method": "GET",
|
||||||
|
"submit_url": "{{entire_url('../api/agent_config_save.dspy')}}",
|
||||||
|
"method": "POST",
|
||||||
|
"layout": "vertical",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "work_dir",
|
||||||
|
"label": "工作目录",
|
||||||
|
"uitype": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "skills_path",
|
||||||
|
"label": "技能路径",
|
||||||
|
"uitype": "text",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "max_memory_tokens",
|
||||||
|
"label": "最大记忆 token 数",
|
||||||
|
"uitype": "int",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_priority",
|
||||||
|
"label": "默认优先级",
|
||||||
|
"uitype": "int",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "high_priority_threshold",
|
||||||
|
"label": "高优先级阈值",
|
||||||
|
"uitype": "int",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "low_priority_threshold",
|
||||||
|
"label": "低优先级阈值",
|
||||||
|
"uitype": "int",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "auto_cleanup_enabled",
|
||||||
|
"label": "启用自动清理",
|
||||||
|
"uitype": "check"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "min_retention_days",
|
||||||
|
"label": "最小保留天数",
|
||||||
|
"uitype": "int",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_model",
|
||||||
|
"label": "默认模型",
|
||||||
|
"uitype": "text",
|
||||||
|
"placeholder": "qwen3-max"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "default_temperature",
|
||||||
|
"label": "默认温度",
|
||||||
|
"uitype": "float",
|
||||||
|
"required": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "enable_streaming",
|
||||||
|
"label": "启用流式输出",
|
||||||
|
"uitype": "check"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"type": "submit",
|
||||||
|
"label": "保存代理配置",
|
||||||
|
"variant": "primary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxWidth": "500px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "submited",
|
||||||
|
"actiontype": "script",
|
||||||
|
"script": "await bricks.show_resp_message_or_error(event.params)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
88
wwwroot/agent_console.ui
Normal file
88
wwwroot/agent_console.ui
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"height": "100%",
|
||||||
|
"padding": "16px",
|
||||||
|
"spacing": "16px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "代理执行控制台",
|
||||||
|
"fontSize": "20px",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
"color": "#059669"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Form",
|
||||||
|
"id": "agent_execute_form",
|
||||||
|
"options": {
|
||||||
|
"submit_url": "{{entire_url('api/agent_execute.dspy')}}",
|
||||||
|
"method": "POST",
|
||||||
|
"layout": "vertical",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"name": "tool_name",
|
||||||
|
"label": "工具名称",
|
||||||
|
"uitype": "text",
|
||||||
|
"required": true,
|
||||||
|
"placeholder": "例如: memory, skill_view, terminal, read_file"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "parameters",
|
||||||
|
"label": "工具参数 (JSON)",
|
||||||
|
"uitype": "textarea",
|
||||||
|
"rows": 6,
|
||||||
|
"placeholder": "{\"key\": \"value\"}"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"buttons": [
|
||||||
|
{
|
||||||
|
"type": "submit",
|
||||||
|
"label": "执行工具",
|
||||||
|
"variant": "primary"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"maxWidth": "700px"
|
||||||
|
},
|
||||||
|
"binds": [
|
||||||
|
{
|
||||||
|
"wid": "self",
|
||||||
|
"event": "submited",
|
||||||
|
"actiontype": "script",
|
||||||
|
"script": "await bricks.show_resp_message_or_error(event.params)"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "VBox",
|
||||||
|
"options": {
|
||||||
|
"width": "100%",
|
||||||
|
"padding": "16px"
|
||||||
|
},
|
||||||
|
"subwidgets": [
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "可用工具列表",
|
||||||
|
"fontSize": "16px",
|
||||||
|
"fontWeight": "bold",
|
||||||
|
"color": "#374151",
|
||||||
|
"marginBottom": "8px"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"widgettype": "Text",
|
||||||
|
"options": {
|
||||||
|
"text": "memory: 保存和检索记忆 | skill_view: 查看技能 | skill_manage: 管理技能 | session_search: 搜索历史会话 | delegate_task: 委托任务 | execute_code: 执行代码 | terminal: 运行命令 | read_file: 读取文件 | write_file: 写入文件 | search_files: 搜索文件 | patch: 修改文件 | vision_analyze: 图像分析 | cronjob: 定时任务 | todo: 任务管理",
|
||||||
|
"fontSize": "12px",
|
||||||
|
"color": "#6B7280"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
43
wwwroot/api/agent_config_get.dspy
Normal file
43
wwwroot/api/agent_config_get.dspy
Normal file
@ -0,0 +1,43 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Get agent configuration for current user"""
|
||||||
|
import json
|
||||||
|
|
||||||
|
result = {'success': False, 'config': {}}
|
||||||
|
|
||||||
|
try:
|
||||||
|
dbname = get_module_dbname('harnessed_agent')
|
||||||
|
user_id = await get_user()
|
||||||
|
|
||||||
|
sql = """SELECT * FROM harnessed_agent_config
|
||||||
|
WHERE user_id = ${user_id}$
|
||||||
|
ORDER BY updated_at DESC
|
||||||
|
LIMIT 1"""
|
||||||
|
|
||||||
|
async with DBPools().sqlorContext(dbname) as sor:
|
||||||
|
rows = await sor.sqlExe(sql, {'user_id': user_id})
|
||||||
|
if rows and len(rows) > 0:
|
||||||
|
config = dict(rows[0])
|
||||||
|
config['auto_cleanup_enabled'] = config.get('auto_cleanup_enabled', '1') == '1'
|
||||||
|
config['enable_streaming'] = config.get('enable_streaming', '1') == '1'
|
||||||
|
result['config'] = config
|
||||||
|
else:
|
||||||
|
result['config'] = {
|
||||||
|
'work_dir': './hermes_work',
|
||||||
|
'skills_path': '~/.hermes/skills',
|
||||||
|
'max_memory_tokens': 2000,
|
||||||
|
'default_priority': 50,
|
||||||
|
'high_priority_threshold': 70,
|
||||||
|
'low_priority_threshold': 30,
|
||||||
|
'auto_cleanup_enabled': True,
|
||||||
|
'min_retention_days': 30,
|
||||||
|
'default_model': 'qwen3-max',
|
||||||
|
'default_temperature': 0.7,
|
||||||
|
'enable_streaming': True
|
||||||
|
}
|
||||||
|
result['success'] = True
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['error'] = str(e)
|
||||||
|
|
||||||
|
return json.dumps(result, ensure_ascii=False, default=str)
|
||||||
91
wwwroot/api/agent_config_save.dspy
Normal file
91
wwwroot/api/agent_config_save.dspy
Normal file
@ -0,0 +1,91 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Save agent configuration for current user"""
|
||||||
|
import json, uuid, time
|
||||||
|
|
||||||
|
result = {'widgettype': 'Message', 'options': {'title': 'Error', 'message': 'Invalid request', 'type': 'error'}}
|
||||||
|
|
||||||
|
try:
|
||||||
|
dbname = get_module_dbname('harnessed_agent')
|
||||||
|
user_id = await get_user()
|
||||||
|
now = time.strftime('%Y-%m-%d %H:%M:%S')
|
||||||
|
|
||||||
|
work_dir = params_kw.get('work_dir', './hermes_work').strip()
|
||||||
|
skills_path = params_kw.get('skills_path', '~/.hermes/skills').strip()
|
||||||
|
max_memory_tokens = int(params_kw.get('max_memory_tokens', 2000))
|
||||||
|
default_priority = int(params_kw.get('default_priority', 50))
|
||||||
|
high_priority_threshold = int(params_kw.get('high_priority_threshold', 70))
|
||||||
|
low_priority_threshold = int(params_kw.get('low_priority_threshold', 30))
|
||||||
|
auto_cleanup_enabled = '1' if params_kw.get('auto_cleanup_enabled') == '1' else '0'
|
||||||
|
min_retention_days = int(params_kw.get('min_retention_days', 30))
|
||||||
|
default_model = params_kw.get('default_model', 'qwen3-max').strip()
|
||||||
|
default_temperature = float(params_kw.get('default_temperature', 0.7))
|
||||||
|
enable_streaming = '1' if params_kw.get('enable_streaming') == '1' else '0'
|
||||||
|
|
||||||
|
async with DBPools().sqlorContext(dbname) as sor:
|
||||||
|
rows = await sor.sqlExe("SELECT id FROM harnessed_agent_config WHERE user_id = ${user_id}$", {'user_id': user_id})
|
||||||
|
|
||||||
|
if rows and len(rows) > 0:
|
||||||
|
config_id = rows[0]['id']
|
||||||
|
await sor.sqlExe("""UPDATE harnessed_agent_config SET
|
||||||
|
work_dir = ${work_dir}$,
|
||||||
|
skills_path = ${skills_path}$,
|
||||||
|
max_memory_tokens = ${max_memory_tokens}$,
|
||||||
|
default_priority = ${default_priority}$,
|
||||||
|
high_priority_threshold = ${high_priority_threshold}$,
|
||||||
|
low_priority_threshold = ${low_priority_threshold}$,
|
||||||
|
auto_cleanup_enabled = ${auto_cleanup_enabled}$,
|
||||||
|
min_retention_days = ${min_retention_days}$,
|
||||||
|
default_model = ${default_model}$,
|
||||||
|
default_temperature = ${default_temperature}$,
|
||||||
|
enable_streaming = ${enable_streaming}$,
|
||||||
|
updated_at = ${updated_at}$
|
||||||
|
WHERE id = ${id}$""", {
|
||||||
|
'id': config_id,
|
||||||
|
'work_dir': work_dir,
|
||||||
|
'skills_path': skills_path,
|
||||||
|
'max_memory_tokens': max_memory_tokens,
|
||||||
|
'default_priority': default_priority,
|
||||||
|
'high_priority_threshold': high_priority_threshold,
|
||||||
|
'low_priority_threshold': low_priority_threshold,
|
||||||
|
'auto_cleanup_enabled': auto_cleanup_enabled,
|
||||||
|
'min_retention_days': min_retention_days,
|
||||||
|
'default_model': default_model,
|
||||||
|
'default_temperature': default_temperature,
|
||||||
|
'enable_streaming': enable_streaming,
|
||||||
|
'updated_at': now
|
||||||
|
})
|
||||||
|
else:
|
||||||
|
config_id = str(uuid.uuid4()).replace('-', '')[:32]
|
||||||
|
await sor.sqlExe("""INSERT INTO harnessed_agent_config
|
||||||
|
(id, user_id, work_dir, skills_path, max_memory_tokens,
|
||||||
|
default_priority, high_priority_threshold, low_priority_threshold,
|
||||||
|
auto_cleanup_enabled, min_retention_days, default_model,
|
||||||
|
default_temperature, enable_streaming, created_at, updated_at)
|
||||||
|
VALUES (${id}$, ${user_id}$, ${work_dir}$, ${skills_path}$, ${max_memory_tokens}$,
|
||||||
|
${default_priority}$, ${high_priority_threshold}$, ${low_priority_threshold}$,
|
||||||
|
${auto_cleanup_enabled}$, ${min_retention_days}$, ${default_model}$,
|
||||||
|
${default_temperature}$, ${enable_streaming}$, ${created_at}$, ${updated_at}$)""", {
|
||||||
|
'id': config_id,
|
||||||
|
'user_id': user_id,
|
||||||
|
'work_dir': work_dir,
|
||||||
|
'skills_path': skills_path,
|
||||||
|
'max_memory_tokens': max_memory_tokens,
|
||||||
|
'default_priority': default_priority,
|
||||||
|
'high_priority_threshold': high_priority_threshold,
|
||||||
|
'low_priority_threshold': low_priority_threshold,
|
||||||
|
'auto_cleanup_enabled': auto_cleanup_enabled,
|
||||||
|
'min_retention_days': min_retention_days,
|
||||||
|
'default_model': default_model,
|
||||||
|
'default_temperature': default_temperature,
|
||||||
|
'enable_streaming': enable_streaming,
|
||||||
|
'created_at': now,
|
||||||
|
'updated_at': now
|
||||||
|
})
|
||||||
|
|
||||||
|
result = {'widgettype': 'Message', 'options': {'title': 'Success', 'message': '配置保存成功', 'type': 'success'}}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['options'] = {'title': 'Error', 'message': '保存失败: ' + str(e), 'type': 'error'}
|
||||||
|
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
51
wwwroot/api/agent_execute.dspy
Normal file
51
wwwroot/api/agent_execute.dspy
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""Execute agent task - call tool/skill with given parameters"""
|
||||||
|
import json, time
|
||||||
|
|
||||||
|
result = {'widgettype': 'Message', 'options': {'title': 'Error', 'message': 'Invalid request', 'type': 'error'}}
|
||||||
|
|
||||||
|
try:
|
||||||
|
tool_name = params_kw.get('tool_name', '').strip()
|
||||||
|
parameters = params_kw.get('parameters', '{}').strip()
|
||||||
|
|
||||||
|
if not tool_name:
|
||||||
|
result['options'] = {'title': 'Error', 'message': '请指定工具名称', 'type': 'error'}
|
||||||
|
else:
|
||||||
|
user_id = await get_user()
|
||||||
|
|
||||||
|
try:
|
||||||
|
tool_params = json.loads(parameters)
|
||||||
|
except:
|
||||||
|
tool_params = {}
|
||||||
|
|
||||||
|
context = {'user_id': user_id}
|
||||||
|
|
||||||
|
# Call agent tool execution
|
||||||
|
exec_result = await harnessed_execute_tool(
|
||||||
|
tool_name=tool_name,
|
||||||
|
parameters=tool_params,
|
||||||
|
context=context
|
||||||
|
)
|
||||||
|
|
||||||
|
if exec_result.get('success'):
|
||||||
|
output = json.dumps(exec_result, ensure_ascii=False, indent=2)
|
||||||
|
result = {
|
||||||
|
'widgettype': 'Message',
|
||||||
|
'options': {
|
||||||
|
'title': '执行成功',
|
||||||
|
'message': f'工具: {tool_name}\n\n结果:\n{output}',
|
||||||
|
'type': 'success'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
result['options'] = {
|
||||||
|
'title': '执行失败',
|
||||||
|
'message': exec_result.get('error', '未知错误'),
|
||||||
|
'type': 'error'
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['options'] = {'title': 'Error', 'message': '执行异常: ' + str(e), 'type': 'error'}
|
||||||
|
|
||||||
|
return json.dumps(result, ensure_ascii=False)
|
||||||
@ -10,6 +10,21 @@
|
|||||||
"cwidth":10,
|
"cwidth":10,
|
||||||
"items":[
|
"items":[
|
||||||
{% if get_user() %}
|
{% if get_user() %}
|
||||||
|
{
|
||||||
|
"name":"hermes_agent",
|
||||||
|
"label":"代理控制台",
|
||||||
|
"url":"{{entire_url('/harnessed_agent/hermes_agent.ui')}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"agent_console",
|
||||||
|
"label":"代理执行",
|
||||||
|
"url":"{{entire_url('/harnessed_agent/agent_console.ui')}}"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name":"agent_config",
|
||||||
|
"label":"代理配置",
|
||||||
|
"url":"{{entire_url('/harnessed_agent/agent_config.ui')}}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"sessions",
|
"name":"sessions",
|
||||||
"label":"会话管理",
|
"label":"会话管理",
|
||||||
@ -25,31 +40,21 @@
|
|||||||
"label":"记忆管理",
|
"label":"记忆管理",
|
||||||
"url":"{{entire_url('/harnessed_agent/hermes_memory')}}"
|
"url":"{{entire_url('/harnessed_agent/hermes_memory')}}"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name":"tasks",
|
|
||||||
"label":"任务管理",
|
|
||||||
"url":"{{entire_url('/harnessed_agent/hermes_tasks')}}"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name":"workflows",
|
"name":"workflows",
|
||||||
"label":"工作流管理",
|
"label":"工作流管理",
|
||||||
"url":"{{entire_url('/harnessed_agent/hermes_workflows')}}"
|
"url":"{{entire_url('/harnessed_agent/hermes_workflows')}}"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"name":"tasks",
|
||||||
|
"label":"任务管理",
|
||||||
|
"url":"{{entire_url('/harnessed_agent/hermes_tasks')}}"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"name":"remote_skills",
|
"name":"remote_skills",
|
||||||
"label":"远程技能",
|
"label":"远程技能",
|
||||||
"url":"{{entire_url('/harnessed_agent/harnessed_remote_skills')}}"
|
"url":"{{entire_url('/harnessed_agent/harnessed_remote_skills')}}"
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"name":"agent_config",
|
|
||||||
"label":"代理配置",
|
|
||||||
"url":"{{entire_url('/harnessed_agent/harnessed_agent_config_view')}}"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name":"hermes_agent",
|
|
||||||
"label":"代理控制台",
|
|
||||||
"url":"{{entire_url('/harnessed_agent/hermes_agent.ui')}}"
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name":"tools",
|
"name":"tools",
|
||||||
"label":"工具管理",
|
"label":"工具管理",
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user