mirror of
https://github.com/xszyou/Fay.git
synced 2026-03-12 17:51:28 +08:00
美化gui对预启动结果的显示;mcp 工具支持预启动及llm调用单独开关控制;预执行结果可以选择保存到记忆。
This commit is contained in:
@@ -167,6 +167,8 @@ def _attach_prestart_metadata(server_id: int, tools: List[Dict[str, Any]]) -> Li
|
||||
cfg = pre_map.get(name, {}) if name else {}
|
||||
item["prestart"] = bool(cfg)
|
||||
item["prestart_params"] = dict(cfg.get("params", {})) if isinstance(cfg, dict) else {}
|
||||
item["include_history"] = cfg.get("include_history", True) if isinstance(cfg, dict) else True
|
||||
item["allow_function_call"] = cfg.get("allow_function_call", False) if isinstance(cfg, dict) else False
|
||||
enriched.append(item)
|
||||
return enriched
|
||||
|
||||
@@ -852,6 +854,8 @@ def get_all_online_server_tools():
|
||||
name = tool.get('name')
|
||||
if not name:
|
||||
continue
|
||||
# Ensure server_id is included for filtering
|
||||
tool['server_id'] = server_id
|
||||
current = aggregated.get(name)
|
||||
if not current or tool.get('last_checked', 0.0) >= current.get('last_checked', 0.0):
|
||||
aggregated[name] = tool
|
||||
@@ -1106,6 +1110,9 @@ def set_prestart_tool(server_id, tool_name):
|
||||
data = request.json or {}
|
||||
enabled = bool(data.get("enabled", False))
|
||||
params = data.get("params", {}) or {}
|
||||
include_history = bool(data.get("include_history", True))
|
||||
allow_function_call = bool(data.get("allow_function_call", False))
|
||||
|
||||
if params and not isinstance(params, dict):
|
||||
return jsonify({
|
||||
"success": False,
|
||||
@@ -1113,7 +1120,13 @@ def set_prestart_tool(server_id, tool_name):
|
||||
}), 400
|
||||
|
||||
if enabled:
|
||||
prestart_registry.set_prestart(server_id, tool_name, params if isinstance(params, dict) else {})
|
||||
prestart_registry.set_prestart(
|
||||
server_id,
|
||||
tool_name,
|
||||
params if isinstance(params, dict) else {},
|
||||
include_history=include_history,
|
||||
allow_function_call=allow_function_call
|
||||
)
|
||||
action = "启用"
|
||||
else:
|
||||
prestart_registry.remove_prestart(server_id, tool_name)
|
||||
@@ -1132,6 +1145,8 @@ def set_prestart_tool(server_id, tool_name):
|
||||
"message": f"工具 {tool_name} 已{action}预启动",
|
||||
"prestart": enabled,
|
||||
"prestart_params": params if isinstance(params, dict) else {},
|
||||
"include_history": include_history if enabled else True,
|
||||
"allow_function_call": allow_function_call if enabled else False,
|
||||
"tools": tools
|
||||
})
|
||||
except Exception as e:
|
||||
@@ -1163,7 +1178,8 @@ def list_runnable_prestart_tools():
|
||||
available = {t.get("name"): t for t in snapshot or []}
|
||||
for tool_name, cfg in tool_map.items():
|
||||
entry = available.get(tool_name)
|
||||
if not entry or not entry.get("enabled", True):
|
||||
# 预启动工具只需要工具可用即可,不检查是否启用
|
||||
if not entry:
|
||||
continue
|
||||
params = cfg.get("params", {}) if isinstance(cfg, dict) else {}
|
||||
runnable.append({
|
||||
@@ -1171,6 +1187,8 @@ def list_runnable_prestart_tools():
|
||||
"server_name": server.get("name", f"Server {server_id}"),
|
||||
"tool": tool_name,
|
||||
"params": params if isinstance(params, dict) else {},
|
||||
"include_history": cfg.get("include_history", True),
|
||||
"allow_function_call": cfg.get("allow_function_call", False)
|
||||
})
|
||||
return jsonify({
|
||||
"success": True,
|
||||
|
||||
@@ -44,7 +44,13 @@ def _ensure_loaded() -> None:
|
||||
if not name:
|
||||
continue
|
||||
params = cfg.get("params", {}) if isinstance(cfg, Mapping) else {}
|
||||
normalized[str(name)] = {"params": params if isinstance(params, Mapping) else {}}
|
||||
include_history = cfg.get("include_history", True) if isinstance(cfg, Mapping) else True
|
||||
allow_function_call = cfg.get("allow_function_call", False) if isinstance(cfg, Mapping) else False
|
||||
normalized[str(name)] = {
|
||||
"params": params if isinstance(params, Mapping) else {},
|
||||
"include_history": include_history,
|
||||
"allow_function_call": allow_function_call
|
||||
}
|
||||
if normalized:
|
||||
loaded[server_id] = normalized
|
||||
_prestart = loaded
|
||||
@@ -77,14 +83,18 @@ def get_server_map(server_id: int) -> Dict[str, Dict[str, Any]]:
|
||||
return dict(_prestart.get(server_id, {}))
|
||||
|
||||
|
||||
def set_prestart(server_id: int, tool_name: str, params: Dict[str, Any]) -> None:
|
||||
"""Enable prestart for a tool with parameter template."""
|
||||
def set_prestart(server_id: int, tool_name: str, params: Dict[str, Any], include_history: bool = True, allow_function_call: bool = False) -> None:
|
||||
"""Enable prestart for a tool with parameter template and options."""
|
||||
if not tool_name:
|
||||
return
|
||||
_ensure_loaded()
|
||||
with _lock:
|
||||
server_map = _prestart.setdefault(int(server_id), {})
|
||||
server_map[str(tool_name)] = {"params": params or {}}
|
||||
server_map[str(tool_name)] = {
|
||||
"params": params or {},
|
||||
"include_history": include_history,
|
||||
"allow_function_call": allow_function_call
|
||||
}
|
||||
_save_locked()
|
||||
|
||||
|
||||
|
||||
@@ -357,18 +357,32 @@
|
||||
.tool-btn.enabled .tool-status-dot {
|
||||
background-color: #67c23a;
|
||||
}
|
||||
.tool-btn.prestart {
|
||||
/* 预启动工具 - 已启用状态(红色实心背景) */
|
||||
.tool-btn.prestart.enabled {
|
||||
border-color: #f56c6c !important;
|
||||
background-color: #f56c6c !important;
|
||||
color: #fff !important;
|
||||
}
|
||||
.tool-btn.prestart .tool-status-dot {
|
||||
background-color: #fff !important;
|
||||
.tool-btn.prestart.enabled .tool-status-dot {
|
||||
background-color: #67c23a !important; /* 绿色点表示已启用 */
|
||||
}
|
||||
.tool-btn.prestart:hover {
|
||||
.tool-btn.prestart.enabled:hover {
|
||||
background-color: #e64545 !important;
|
||||
border-color: #e64545 !important;
|
||||
}
|
||||
/* 预启动工具 - 未启用状态(红色边框,白色背景) */
|
||||
.tool-btn.prestart:not(.enabled) {
|
||||
border: 2px solid #f56c6c !important;
|
||||
background-color: #fff !important;
|
||||
color: #f56c6c !important;
|
||||
}
|
||||
.tool-btn.prestart:not(.enabled) .tool-status-dot {
|
||||
background-color: #c0c4cc !important; /* 灰色点表示未启用 */
|
||||
}
|
||||
.tool-btn.prestart:not(.enabled):hover {
|
||||
background-color: #fef0f0 !important;
|
||||
border-color: #f56c6c !important;
|
||||
}
|
||||
.prestart-tag {
|
||||
margin-left: auto;
|
||||
padding: 2px 8px;
|
||||
@@ -629,11 +643,15 @@
|
||||
<label class="mcp-label">工具:</label>
|
||||
<div class="mcp-info-value" id="prestartToolLabel">--</div>
|
||||
</div>
|
||||
<div class="prestart-hint">调用参数支持使用 {{question}} 占位符替换为用户问题。</div>
|
||||
<div class="prestart-required" id="prestartRequired"></div>
|
||||
<div id="prestartParamsWrapper">
|
||||
<textarea class="mcp-textarea" id="prestartParamsInput" placeholder='例如: {"query": "{{question}}"}'></textarea>
|
||||
</div>
|
||||
<div class="prestart-hint">调用参数支持使用 {{question}} 占位符替换为用户问题。</div>
|
||||
<div class="prestart-required" id="prestartRequired"></div>
|
||||
<div id="prestartParamsWrapper">
|
||||
<textarea class="mcp-textarea" id="prestartParamsInput" placeholder='例如: {"query": "{{question}}"}'></textarea>
|
||||
</div>
|
||||
<div class="mcp-form-item" style="margin-top: 10px;">
|
||||
<label class="mcp-label" style="width: auto; margin-right: 10px;">结果保存到记忆:</label>
|
||||
<input type="checkbox" id="prestartIncludeHistory" checked>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mcp-dialog-footer">
|
||||
<button class="add-server-btn" onclick="savePrestartConfig(true)">保存预启动</button>
|
||||
@@ -1422,7 +1440,8 @@
|
||||
let toolEnabled = true; // 默认启用
|
||||
let prestart = false;
|
||||
let prestartParams = {};
|
||||
|
||||
let includeHistory = true;
|
||||
|
||||
if (typeof tool === 'object' && tool !== null) {
|
||||
toolName = tool.name || '未知工具';
|
||||
if (typeof tool.enabled !== 'undefined') {
|
||||
@@ -1432,12 +1451,13 @@
|
||||
if (tool.prestart_params && typeof tool.prestart_params === 'object') {
|
||||
prestartParams = tool.prestart_params;
|
||||
}
|
||||
includeHistory = tool.include_history !== false;
|
||||
} else if (typeof tool === 'string') {
|
||||
toolName = tool;
|
||||
} else {
|
||||
toolName = '未知工具';
|
||||
}
|
||||
|
||||
|
||||
// 创建工具按钮
|
||||
const toolBtn = document.createElement('div');
|
||||
toolBtn.className = `tool-btn ${toolEnabled ? 'enabled' : ''} ${prestart ? 'prestart' : ''}`;
|
||||
@@ -1446,20 +1466,21 @@
|
||||
toolBtn.dataset.serverId = serverId;
|
||||
toolBtn.dataset.enabled = toolEnabled;
|
||||
toolBtn.dataset.prestartParams = JSON.stringify(prestartParams || {});
|
||||
toolBtn.dataset.includeHistory = includeHistory;
|
||||
|
||||
const statusDot = document.createElement('span');
|
||||
statusDot.className = 'tool-status-dot';
|
||||
|
||||
|
||||
const nameSpan = document.createElement('span');
|
||||
nameSpan.textContent = toolName;
|
||||
|
||||
const prestartTag = document.createElement('span');
|
||||
prestartTag.className = `prestart-tag ${prestart ? '' : 'inactive'}`;
|
||||
prestartTag.textContent = prestart ? '预启动' : '预启动?';
|
||||
prestartTag.title = '配置预启动参数(支持 {{question}} 占位符)';
|
||||
prestartTag.title = '配置预启动参数';
|
||||
prestartTag.addEventListener('click', function(event) {
|
||||
event.stopPropagation();
|
||||
showPrestartDialog(serverId, serverName, toolName, prestartParams, tool.inputSchema || {});
|
||||
showPrestartDialog(serverId, serverName, toolName, prestartParams, tool.inputSchema || {}, includeHistory);
|
||||
});
|
||||
|
||||
// 添加点击事件
|
||||
@@ -1487,54 +1508,59 @@
|
||||
}
|
||||
|
||||
|
||||
let prestartContext = { serverId: null, serverName: '', toolName: '', params: {} };
|
||||
let prestartContext = { serverId: null, serverName: '', toolName: '', params: {}, includeHistory: true };
|
||||
|
||||
function showPrestartDialog(serverId, serverName, toolName, params, inputSchema) {
|
||||
console.log('showPrestartDialog called with:', { serverId, serverName, toolName, params, inputSchema });
|
||||
function showPrestartDialog(serverId, serverName, toolName, params, inputSchema, includeHistory) {
|
||||
console.log('showPrestartDialog called with:', { serverId, serverName, toolName, params, inputSchema, includeHistory });
|
||||
prestartContext = {
|
||||
serverId,
|
||||
serverName: serverName || '',
|
||||
toolName,
|
||||
params: params || {},
|
||||
schema: inputSchema || {}
|
||||
schema: inputSchema || {},
|
||||
includeHistory: includeHistory !== false // default true
|
||||
};
|
||||
const dialog = document.getElementById('prestartDialog');
|
||||
if (!dialog) return;
|
||||
const serverLabel = document.getElementById('prestartServerLabel');
|
||||
const toolLabel = document.getElementById('prestartToolLabel');
|
||||
const input = document.getElementById('prestartParamsInput');
|
||||
const requiredBox = document.getElementById('prestartRequired');
|
||||
const paramsWrapper = document.getElementById('prestartParamsWrapper');
|
||||
const schema = inputSchema || {};
|
||||
const requiredList = Array.isArray(schema.required) ? schema.required : [];
|
||||
const properties = schema.properties || {};
|
||||
console.log('Schema properties:', properties, 'required:', requiredList);
|
||||
const toolLabel = document.getElementById('prestartToolLabel');
|
||||
const input = document.getElementById('prestartParamsInput');
|
||||
const requiredBox = document.getElementById('prestartRequired');
|
||||
const paramsWrapper = document.getElementById('prestartParamsWrapper');
|
||||
const includeHistoryCheck = document.getElementById('prestartIncludeHistory');
|
||||
|
||||
if (includeHistoryCheck) includeHistoryCheck.checked = prestartContext.includeHistory;
|
||||
|
||||
const schema = inputSchema || {};
|
||||
const requiredList = Array.isArray(schema.required) ? schema.required : [];
|
||||
const properties = schema.properties || {};
|
||||
console.log('Schema properties:', properties, 'required:', requiredList);
|
||||
|
||||
if (serverLabel) {
|
||||
serverLabel.textContent = serverName || serverId;
|
||||
}
|
||||
if (toolLabel) {
|
||||
toolLabel.textContent = toolName || '--';
|
||||
}
|
||||
if (requiredBox) {
|
||||
if (requiredList.length === 0) {
|
||||
requiredBox.textContent = '无必填参数';
|
||||
} else {
|
||||
}
|
||||
if (requiredBox) {
|
||||
if (requiredList.length === 0) {
|
||||
requiredBox.textContent = '无必填参数';
|
||||
} else {
|
||||
const items = requiredList.map(key => {
|
||||
const desc = properties[key]?.description || '';
|
||||
return desc ? `${key}: ${desc}` : key;
|
||||
});
|
||||
requiredBox.textContent = `必填参数:${items.join(',')}`;
|
||||
}
|
||||
}
|
||||
if (paramsWrapper) {
|
||||
paramsWrapper.style.display = requiredList.length === 0 ? 'none' : 'block';
|
||||
}
|
||||
const mergedParams = Object.assign({}, params || {});
|
||||
const defaultByType = (t) => {
|
||||
if (t === 'array') return [];
|
||||
if (t === 'object') return {};
|
||||
if (t === 'integer' || t === 'number') return 0;
|
||||
requiredBox.textContent = `必填参数:${items.join(',')}`;
|
||||
}
|
||||
}
|
||||
if (paramsWrapper) {
|
||||
paramsWrapper.style.display = requiredList.length === 0 ? 'none' : 'block';
|
||||
}
|
||||
const mergedParams = Object.assign({}, params || {});
|
||||
const defaultByType = (t) => {
|
||||
if (t === 'array') return [];
|
||||
if (t === 'object') return {};
|
||||
if (t === 'integer' || t === 'number') return 0;
|
||||
if (t === 'boolean') return false;
|
||||
return '';
|
||||
};
|
||||
@@ -1626,12 +1652,14 @@
|
||||
}
|
||||
}
|
||||
|
||||
const includeHistory = document.getElementById('prestartIncludeHistory').checked;
|
||||
|
||||
fetch(`/api/mcp/servers/${prestartContext.serverId}/tools/${encodeURIComponent(prestartContext.toolName)}/prestart`, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json'
|
||||
},
|
||||
body: JSON.stringify(enable ? { enabled: true, params } : { enabled: false })
|
||||
body: JSON.stringify(enable ? { enabled: true, params, include_history: includeHistory } : { enabled: false })
|
||||
})
|
||||
.then(resp => resp.json())
|
||||
.then(data => {
|
||||
@@ -1642,7 +1670,10 @@
|
||||
hidePrestartDialog();
|
||||
const btn = findToolButton(prestartContext.serverId, prestartContext.toolName);
|
||||
if (btn) {
|
||||
btn.dataset.prestartParams = JSON.stringify(params || {});
|
||||
// Update dataset with new values from response
|
||||
btn.dataset.prestartParams = JSON.stringify(data.prestart_params || {});
|
||||
btn.dataset.includeHistory = data.include_history;
|
||||
|
||||
const tag = btn.querySelector('.prestart-tag');
|
||||
if (enable) {
|
||||
btn.classList.add('prestart');
|
||||
@@ -1657,6 +1688,24 @@
|
||||
tag.classList.add('inactive');
|
||||
}
|
||||
}
|
||||
|
||||
// Update onclick listener to use new values (needs recreation or just rely on dataset/fetching again?
|
||||
// Recreating the onclick handler on the tag is tricky without removing old one.
|
||||
// Simplest is to refresh tools for this card, or update the click handler via a closure if possible.
|
||||
// But here we can just update the tag's click handler property if we stored it, or
|
||||
// since we used addEventListener with anonymous function, we can't remove it easily.
|
||||
// However, the `showPrestartDialog` is called with values from `tool` object in `onCardSelected`.
|
||||
// We need to update that `tool` object reference or reload the tools list.
|
||||
// Triggering a reload of the current card's tools is best.
|
||||
const card = document.querySelector(`.mcp-card[data-server-id="${prestartContext.serverId}"]`);
|
||||
if (card && card.classList.contains('selected')) {
|
||||
// Re-trigger selection logic to refresh tools list
|
||||
// onCardSelected(card); // But we don't have access to onCardSelected here easily?
|
||||
// It is defined in global scope.
|
||||
if (typeof onCardSelected === 'function') {
|
||||
onCardSelected(card);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
.catch(err => {
|
||||
|
||||
@@ -547,21 +547,21 @@ html {
|
||||
padding: 4px 8px;
|
||||
margin-top: 8px;
|
||||
margin-bottom: 6px;
|
||||
background-color: #f0fff4;
|
||||
background-color: #f7f7f7; /* 改为浅灰背景 */
|
||||
border-radius: 4px;
|
||||
border: 1px solid #a8e6cf;
|
||||
border: 1px solid #dcdcdc; /* 改为灰色边框 */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
.prestart-toggle:hover {
|
||||
background-color: #e0ffe8;
|
||||
background-color: #eeeeee; /* 悬停加深 */
|
||||
}
|
||||
|
||||
.prestart-arrow {
|
||||
display: inline-block;
|
||||
font-size: 10px;
|
||||
margin-right: 6px;
|
||||
color: #4caf50;
|
||||
color: #666666; /* 改为暗灰色 */
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
@@ -571,13 +571,13 @@ html {
|
||||
|
||||
.prestart-label {
|
||||
font-size: 12px;
|
||||
color: #4caf50;
|
||||
color: #666666; /* 改为暗灰色 */
|
||||
font-weight: 500;
|
||||
}
|
||||
|
||||
.prestart-content-inline {
|
||||
background-color: #f5fff7;
|
||||
border: 1px dashed #a8e6cf;
|
||||
background-color: #fafafa; /* 改为灰白背景 */
|
||||
border: 1px dashed #dcdcdc; /* 改为灰色虚线 */
|
||||
border-radius: 4px;
|
||||
padding: 8px 10px;
|
||||
margin-bottom: 8px;
|
||||
|
||||
@@ -714,13 +714,13 @@ unadoptText(id) {
|
||||
let prestartContent = '';
|
||||
|
||||
// 解析 prestart 标签 - 使用贪婪匹配确保匹配到最后一个 </prestart>
|
||||
// 同时支持多个 prestart 标签的情况
|
||||
const prestartRegex = /<prestart>([\s\S]*)<\/prestart>/i;
|
||||
// 同时支持多个 prestart 标签的情况,以及支持属性
|
||||
const prestartRegex = /<prestart(?:[^>]*)>([\s\S]*)<\/prestart>/i;
|
||||
const prestartMatch = mainContent.match(prestartRegex);
|
||||
if (prestartMatch && prestartMatch[1]) {
|
||||
prestartContent = this.trimThinkLines(prestartMatch[1]);
|
||||
// 移除所有 prestart 标签及其内容
|
||||
mainContent = mainContent.replace(/<prestart>[\s\S]*<\/prestart>/gi, '');
|
||||
mainContent = mainContent.replace(/<prestart(?:[^>]*)>[\s\S]*<\/prestart>/gi, '');
|
||||
}
|
||||
|
||||
// 先尝试匹配完整的 think 标签
|
||||
|
||||
@@ -301,8 +301,8 @@ def _remove_think_from_text(text: str) -> str:
|
||||
return re.sub(r'<think>[\s\S]*?</think>', '', text, flags=re.IGNORECASE).strip()
|
||||
|
||||
|
||||
def _run_prestart_tools(user_question: str) -> str:
|
||||
"""Call configured prestart MCP tools and return a summary string."""
|
||||
def _run_prestart_tools(user_question: str) -> List[Dict[str, Any]]:
|
||||
"""Call configured prestart MCP tools and return a list of result objects."""
|
||||
try:
|
||||
resp = requests.get(
|
||||
"http://127.0.0.1:5010/api/mcp/prestart/runnable",
|
||||
@@ -312,19 +312,21 @@ def _run_prestart_tools(user_question: str) -> str:
|
||||
payload = resp.json()
|
||||
except Exception as exc:
|
||||
util.log(1, f"获取预启动工具列表失败: {exc}")
|
||||
return ""
|
||||
return []
|
||||
|
||||
tools = payload.get("prestart_tools") or []
|
||||
if not tools:
|
||||
return ""
|
||||
return []
|
||||
|
||||
outputs: List[str] = []
|
||||
results: List[Dict[str, Any]] = []
|
||||
for item in tools:
|
||||
server_id = item.get("server_id")
|
||||
tool_name = item.get("tool")
|
||||
if not server_id or not tool_name:
|
||||
continue
|
||||
params = item.get("params") or {}
|
||||
include_history = item.get("include_history", True)
|
||||
|
||||
try:
|
||||
filled_params = _apply_question_placeholder(params, user_question)
|
||||
except Exception:
|
||||
@@ -355,16 +357,16 @@ def _run_prestart_tools(user_question: str) -> str:
|
||||
except Exception:
|
||||
pass
|
||||
|
||||
# 格式化为 "工具名(参数): 返回内容"
|
||||
outputs.append(f"【{tool_name}】{params_str}\n{output.strip()}")
|
||||
formatted_output = f"【{tool_name}】{params_str}\n{output.strip()}"
|
||||
results.append({
|
||||
"text": formatted_output,
|
||||
"include_history": include_history
|
||||
})
|
||||
else:
|
||||
error_msg = data.get("error") or "未知错误"
|
||||
util.log(1, f"预启动工具 {tool_name} 执行失败: {error_msg}")
|
||||
|
||||
if outputs:
|
||||
return "\n\n".join(outputs)
|
||||
|
||||
return ""
|
||||
return results
|
||||
|
||||
|
||||
def _truncate_history(history: List[ToolResult], limit: int = 6) -> str:
|
||||
@@ -1463,13 +1465,27 @@ def question(content, username, observation=None):
|
||||
util.log(1, f"获取相关记忆时出错: {exc}")
|
||||
|
||||
prestart_context = ""
|
||||
prestart_stream_text = ""
|
||||
try:
|
||||
prestart_context = _run_prestart_tools(content)
|
||||
if prestart_context:
|
||||
util.log(1, f"预启动工具输出 {len(prestart_context.splitlines())} 行")
|
||||
prestart_results = _run_prestart_tools(content)
|
||||
if prestart_results:
|
||||
# 提示词用的上下文(纯文本)
|
||||
prestart_context = "\n\n".join(r["text"] for r in prestart_results)
|
||||
|
||||
# 流式输出用的文本(带标签)
|
||||
stream_parts = []
|
||||
for r in prestart_results:
|
||||
if r.get("include_history"):
|
||||
stream_parts.append(f'<prestart keep="true">{r["text"]}</prestart>')
|
||||
else:
|
||||
stream_parts.append(f'<prestart>{r["text"]}</prestart>')
|
||||
prestart_stream_text = "\n".join(stream_parts)
|
||||
|
||||
util.log(1, f"预启动工具输出 {len(prestart_results)} 项")
|
||||
except Exception as exc:
|
||||
util.log(1, f"预启动工具执行失败: {exc}")
|
||||
prestart_context = f"- 预启动工具执行失败: {exc}"
|
||||
prestart_stream_text = f"<prestart>{prestart_context}</prestart>"
|
||||
|
||||
# 获取当前时间
|
||||
current_time = datetime.datetime.now().strftime("%Y年%m月%d日 %H:%M:%S")
|
||||
@@ -1667,10 +1683,10 @@ def question(content, username, observation=None):
|
||||
def send_prestart_content() -> None:
|
||||
"""在LLM生成之前先发送预启动工具结果"""
|
||||
nonlocal accumulated_text, full_response_text, is_first_sentence
|
||||
if prestart_context and prestart_context.strip():
|
||||
prestart_tag = f"<prestart>{prestart_context}</prestart>"
|
||||
write_sentence(prestart_tag, force_first=is_first_sentence)
|
||||
full_response_text += prestart_tag
|
||||
if prestart_stream_text and prestart_stream_text.strip():
|
||||
# prestart_stream_text 已经包含标签
|
||||
write_sentence(prestart_stream_text, force_first=is_first_sentence)
|
||||
full_response_text += prestart_stream_text
|
||||
is_first_sentence = False
|
||||
|
||||
def run_workflow(tool_registry: Dict[str, WorkflowToolSpec]) -> bool:
|
||||
@@ -2101,30 +2117,19 @@ def save_agent_memory():
|
||||
util.log(1, f"保存代理记忆失败: {str(e)}")
|
||||
|
||||
def get_mcp_tools() -> List[Dict[str, Any]]:
|
||||
"""
|
||||
从共享缓存获取所有可用且已启用的MCP工具列表。
|
||||
排除预启动工具,因为预启动工具会在LLM推理前自动执行,
|
||||
不需要作为可调用工具提供给规划器。
|
||||
"""
|
||||
"""Fetch all available MCP tools from the registry."""
|
||||
try:
|
||||
tools = mcp_tool_registry.get_enabled_tools()
|
||||
if not tools:
|
||||
return []
|
||||
# 过滤掉预启动工具
|
||||
filtered_tools = []
|
||||
for tool in tools:
|
||||
if not tool:
|
||||
continue
|
||||
server_id = tool.get("server_id")
|
||||
tool_name = tool.get("name")
|
||||
if server_id is not None and tool_name:
|
||||
if prestart_registry.is_prestart(server_id, tool_name):
|
||||
continue # 跳过预启动工具
|
||||
filtered_tools.append(tool)
|
||||
return filtered_tools
|
||||
resp = requests.get("http://127.0.0.1:5010/api/mcp/servers/online/tools", timeout=5)
|
||||
if resp.status_code == 200:
|
||||
data = resp.json()
|
||||
raw_tools = data.get("tools") or []
|
||||
# 只返回启用的工具,预启动工具只要启用也可以被LLM调用
|
||||
filtered = [tool for tool in raw_tools if tool.get("enabled", True)]
|
||||
return filtered
|
||||
except Exception as e:
|
||||
util.log(1, f"获取工具列表出错:{e}")
|
||||
util.log(1, f"Failed to fetch MCP tools: {e}")
|
||||
return []
|
||||
return []
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
Reference in New Issue
Block a user