fix: adapt deepseek custom models and harden todo/tool gating
This commit is contained in:
parent
1b27b3ffa2
commit
070d77c070
2
.gitignore
vendored
2
.gitignore
vendored
@ -23,6 +23,7 @@ sub_agent/tasks/
|
|||||||
sub_agent/data/
|
sub_agent/data/
|
||||||
sub_agent/logs/
|
sub_agent/logs/
|
||||||
sub_agent/project/
|
sub_agent/project/
|
||||||
|
sub_agent_results/
|
||||||
|
|
||||||
# Misc
|
# Misc
|
||||||
*.pid
|
*.pid
|
||||||
@ -32,6 +33,7 @@ static/dist/
|
|||||||
*.tsbuildinfo
|
*.tsbuildinfo
|
||||||
user_upload/
|
user_upload/
|
||||||
skills/
|
skills/
|
||||||
|
ax_probe_chrome.py
|
||||||
|
|
||||||
# Ignore docs and runtime pid
|
# Ignore docs and runtime pid
|
||||||
webapp.pid
|
webapp.pid
|
||||||
|
|||||||
@ -25,21 +25,22 @@
|
|||||||
"enable_thinking": true
|
"enable_thinking": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extra_parameter": {}
|
"extra_parameter": {},
|
||||||
|
"model_description": "你的基础模型是 Kimi-k2.6(测试别名),底层与 Kimi-k2.5 一致,并通过 thinking 参数开启/关闭思考能力。"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"model_name": "kimi-k2.7",
|
"model_name": "DeepSeek-V4-Flash Max",
|
||||||
"description": "Kimi-k2.7(测试模型),仅快速模式",
|
"description": "DeepSeek V4 Flash(reasoning_effort=max),支持快速/思考/深度思考",
|
||||||
"visible": true,
|
"visible": true,
|
||||||
"url": "${API_BASE_KIMI_OFFICIAL}",
|
"url": "https://api.deepseek.com",
|
||||||
"apikey": "${API_KEY_KIMI_OFFICIAL}",
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
"multimodal": "none",
|
"multimodal": "none",
|
||||||
"reasoning_capability": "fast",
|
"reasoning_capability": "fast,thinking",
|
||||||
"context_window": 256000,
|
"context_window": 1000000,
|
||||||
"max_output_tokens": 32768,
|
"max_output_tokens": 384000,
|
||||||
"thinkmode_status": {
|
"thinkmode_status": {
|
||||||
"type": "param_toggle",
|
"type": "param_toggle",
|
||||||
"model_id": "kimi-k2.5",
|
"model_id": "deepseek-v4-flash",
|
||||||
"fast_extra_parameter": {
|
"fast_extra_parameter": {
|
||||||
"thinking": {
|
"thinking": {
|
||||||
"type": "disabled"
|
"type": "disabled"
|
||||||
@ -47,11 +48,97 @@
|
|||||||
},
|
},
|
||||||
"thinking_extra_parameter": {
|
"thinking_extra_parameter": {
|
||||||
"thinking": {
|
"thinking": {
|
||||||
"type": "disabled"
|
"type": "enabled"
|
||||||
}
|
},
|
||||||
|
"reasoning_effort": "max"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extra_parameter": {}
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Flash,一个快捷、高效的通用模型,具备接近旗舰级的推理能力,在简单到中等复杂度任务中表现出色,并支持 1M 上下文,适合追求响应速度与成本效率的使用场景。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Flah High",
|
||||||
|
"description": "DeepSeek V4 Flash(reasoning_effort=high),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-flash",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "high"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Flash,一个快捷、高效的通用模型,具备接近旗舰级的推理能力,在简单到中等复杂度任务中表现出色,并支持 1M 上下文,适合追求响应速度与成本效率的使用场景。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Pro Max",
|
||||||
|
"description": "DeepSeek V4 Pro(reasoning_effort=max),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-pro",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "max"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Pro,一个面向复杂任务的高性能通用模型,具备突出的 Agent 能力、丰富的世界知识和顶级推理表现,在编程、数学、STEM 与复杂问题分析场景中表现尤为出色,并支持 1M 上下文。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Pro High",
|
||||||
|
"description": "DeepSeek V4 Pro(reasoning_effort=high),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-pro",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "high"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Pro,一个面向复杂任务的高性能通用模型,具备突出的 Agent 能力、丰富的世界知识和顶级推理表现,在编程、数学、STEM 与复杂问题分析场景中表现尤为出色,并支持 1M 上下文。"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -25,21 +25,22 @@
|
|||||||
"enable_thinking": true
|
"enable_thinking": true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extra_parameter": {}
|
"extra_parameter": {},
|
||||||
|
"model_description": "你的基础模型是 Kimi-k2.6(测试别名),底层与 Kimi-k2.5 一致,并通过 thinking 参数开启/关闭思考能力。"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"model_name": "kimi-k2.7",
|
"model_name": "DeepSeek-V4-Flash Max",
|
||||||
"description": "Kimi-k2.7(测试模型),仅快速模式",
|
"description": "DeepSeek V4 Flash(reasoning_effort=max),支持快速/思考/深度思考",
|
||||||
"visible": true,
|
"visible": true,
|
||||||
"url": "${API_BASE_KIMI_OFFICIAL}",
|
"url": "https://api.deepseek.com",
|
||||||
"apikey": "${API_KEY_KIMI_OFFICIAL}",
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
"multimodal": "none",
|
"multimodal": "none",
|
||||||
"reasoning_capability": "fast",
|
"reasoning_capability": "fast,thinking",
|
||||||
"context_window": 256000,
|
"context_window": 1000000,
|
||||||
"max_output_tokens": 32768,
|
"max_output_tokens": 384000,
|
||||||
"thinkmode_status": {
|
"thinkmode_status": {
|
||||||
"type": "param_toggle",
|
"type": "param_toggle",
|
||||||
"model_id": "kimi-k2.5",
|
"model_id": "deepseek-v4-flash",
|
||||||
"fast_extra_parameter": {
|
"fast_extra_parameter": {
|
||||||
"thinking": {
|
"thinking": {
|
||||||
"type": "disabled"
|
"type": "disabled"
|
||||||
@ -47,11 +48,97 @@
|
|||||||
},
|
},
|
||||||
"thinking_extra_parameter": {
|
"thinking_extra_parameter": {
|
||||||
"thinking": {
|
"thinking": {
|
||||||
"type": "disabled"
|
"type": "enabled"
|
||||||
}
|
},
|
||||||
|
"reasoning_effort": "max"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"extra_parameter": {}
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Flash,一个快捷、高效的通用模型,具备接近旗舰级的推理能力,在简单到中等复杂度任务中表现出色,并支持 1M 上下文,适合追求响应速度与成本效率的使用场景。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Flah High",
|
||||||
|
"description": "DeepSeek V4 Flash(reasoning_effort=high),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-flash",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "high"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Flash,一个快捷、高效的通用模型,具备接近旗舰级的推理能力,在简单到中等复杂度任务中表现出色,并支持 1M 上下文,适合追求响应速度与成本效率的使用场景。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Pro Max",
|
||||||
|
"description": "DeepSeek V4 Pro(reasoning_effort=max),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-pro",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "max"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Pro,一个面向复杂任务的高性能通用模型,具备突出的 Agent 能力、丰富的世界知识和顶级推理表现,在编程、数学、STEM 与复杂问题分析场景中表现尤为出色,并支持 1M 上下文。"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"model_name": "DeepSeek-V4-Pro High",
|
||||||
|
"description": "DeepSeek V4 Pro(reasoning_effort=high),支持快速/思考/深度思考",
|
||||||
|
"visible": true,
|
||||||
|
"url": "https://api.deepseek.com",
|
||||||
|
"apikey": "${API_KEY_DEEPSEEK}",
|
||||||
|
"multimodal": "none",
|
||||||
|
"reasoning_capability": "fast,thinking",
|
||||||
|
"context_window": 1000000,
|
||||||
|
"max_output_tokens": 384000,
|
||||||
|
"thinkmode_status": {
|
||||||
|
"type": "param_toggle",
|
||||||
|
"model_id": "deepseek-v4-pro",
|
||||||
|
"fast_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "disabled"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"thinking_extra_parameter": {
|
||||||
|
"thinking": {
|
||||||
|
"type": "enabled"
|
||||||
|
},
|
||||||
|
"reasoning_effort": "high"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"extra_parameter": {},
|
||||||
|
"model_description": "你是DeepSeek-V4-Pro,一个面向复杂任务的高性能通用模型,具备突出的 Agent 能力、丰富的世界知识和顶级推理表现,在编程、数学、STEM 与复杂问题分析场景中表现尤为出色,并支持 1M 上下文。"
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|||||||
@ -400,6 +400,8 @@ def _build_custom_profile(item: Dict[str, Any]) -> Optional[Dict[str, Any]]:
|
|||||||
profile: Dict[str, Any] = {
|
profile: Dict[str, Any] = {
|
||||||
"name": key,
|
"name": key,
|
||||||
"description": str(item.get("description") or ""),
|
"description": str(item.get("description") or ""),
|
||||||
|
"model_description": str(item.get("model_description") or ""),
|
||||||
|
"is_custom_model": True,
|
||||||
"hidden": not bool(item.get("visible", True)),
|
"hidden": not bool(item.get("visible", True)),
|
||||||
"multimodal": _normalize_multimodal(item.get("multimodal")),
|
"multimodal": _normalize_multimodal(item.get("multimodal")),
|
||||||
"context_window": context_window,
|
"context_window": context_window,
|
||||||
@ -496,8 +498,23 @@ def get_model_prompt_replacements(key: str) -> dict:
|
|||||||
"""获取模型相关的提示词替换字段,若缺失则回退到 Kimi 版本。"""
|
"""获取模型相关的提示词替换字段,若缺失则回退到 Kimi 版本。"""
|
||||||
fallback = MODEL_PROMPT_OVERRIDES.get("kimi", {})
|
fallback = MODEL_PROMPT_OVERRIDES.get("kimi", {})
|
||||||
overrides = MODEL_PROMPT_OVERRIDES.get(key) or {}
|
overrides = MODEL_PROMPT_OVERRIDES.get(key) or {}
|
||||||
|
custom_model_description = ""
|
||||||
|
is_custom_model = False
|
||||||
|
try:
|
||||||
|
custom_profile = get_registered_model_profiles().get(key) or {}
|
||||||
|
custom_model_description = str(custom_profile.get("model_description") or "")
|
||||||
|
is_custom_model = bool(custom_profile.get("is_custom_model"))
|
||||||
|
except Exception:
|
||||||
|
custom_model_description = ""
|
||||||
|
is_custom_model = False
|
||||||
|
if is_custom_model:
|
||||||
|
return {
|
||||||
|
"model_description": custom_model_description or overrides.get("model_description") or fallback.get("model_description") or "",
|
||||||
|
"thinking_model_line": "",
|
||||||
|
"deep_thinking_line": "",
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
"model_description": overrides.get("model_description") or fallback.get("model_description") or "",
|
"model_description": custom_model_description or overrides.get("model_description") or fallback.get("model_description") or "",
|
||||||
"thinking_model_line": overrides.get("thinking_model_line") or fallback.get("thinking_model_line") or "",
|
"thinking_model_line": overrides.get("thinking_model_line") or fallback.get("thinking_model_line") or "",
|
||||||
"deep_thinking_line": overrides.get("deep_thinking_line") or fallback.get("deep_thinking_line") or ""
|
"deep_thinking_line": overrides.get("deep_thinking_line") or fallback.get("deep_thinking_line") or ""
|
||||||
}
|
}
|
||||||
|
|||||||
@ -143,6 +143,7 @@
|
|||||||
3. **诚实守信**:做不到的事情坦白说,不编造
|
3. **诚实守信**:做不到的事情坦白说,不编造
|
||||||
4. **用户友好**:用简单的语言解释复杂的操作
|
4. **用户友好**:用简单的语言解释复杂的操作
|
||||||
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
||||||
|
6. **沟通原则**:使用用户使用的语言进行思考和交流
|
||||||
|
|
||||||
## 8. 个性化配置
|
## 8. 个性化配置
|
||||||
|
|
||||||
|
|||||||
@ -161,6 +161,7 @@
|
|||||||
3. **诚实守信**:做不到的事情坦白说,不编造
|
3. **诚实守信**:做不到的事情坦白说,不编造
|
||||||
4. **用户友好**:用简单的语言解释复杂的操作
|
4. **用户友好**:用简单的语言解释复杂的操作
|
||||||
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
5. **正确执行**:主动确认细节,获得明确许可后再开始
|
||||||
|
6. **沟通原则**:使用用户使用的语言进行思考和交流
|
||||||
|
|
||||||
## 8. 个性化配置
|
## 8. 个性化配置
|
||||||
|
|
||||||
|
|||||||
@ -151,6 +151,16 @@ async def _wait_for_tool_approval(*, approval_id: str, username: str, timeout_se
|
|||||||
async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, client_sid: str, username: str, iteration: int, conversation_id: Optional[str], last_tool_call_time: float, process_sub_agent_updates, process_background_command_updates, maybe_mark_failure_from_message, mark_force_thinking, get_stop_flag, clear_stop_flag, workspace=None):
|
async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, client_sid: str, username: str, iteration: int, conversation_id: Optional[str], last_tool_call_time: float, process_sub_agent_updates, process_background_command_updates, maybe_mark_failure_from_message, mark_force_thinking, get_stop_flag, clear_stop_flag, workspace=None):
|
||||||
previous_tool_loop_active = getattr(web_terminal, "_tool_loop_active", False)
|
previous_tool_loop_active = getattr(web_terminal, "_tool_loop_active", False)
|
||||||
web_terminal._tool_loop_active = True
|
web_terminal._tool_loop_active = True
|
||||||
|
allowed_tool_names = set()
|
||||||
|
try:
|
||||||
|
defined_tools = web_terminal.define_tools() or []
|
||||||
|
for tool in defined_tools:
|
||||||
|
name = ((tool or {}).get("function") or {}).get("name")
|
||||||
|
if isinstance(name, str) and name:
|
||||||
|
allowed_tool_names.add(name)
|
||||||
|
except Exception as exc:
|
||||||
|
debug_log(f"构建工具白名单失败(降级继续): {exc}")
|
||||||
|
|
||||||
# 执行每个工具
|
# 执行每个工具
|
||||||
for tool_call in tool_calls:
|
for tool_call in tool_calls:
|
||||||
# 检查停止标志
|
# 检查停止标志
|
||||||
@ -310,6 +320,49 @@ async def execute_tool_calls(*, web_terminal, tool_calls, sender, messages, clie
|
|||||||
})
|
})
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
# 严格校验:只允许执行当前回合明确下发给模型的工具。
|
||||||
|
# 某些模型会“幻觉”调用未下发工具(如 view_image),必须在执行层拦截。
|
||||||
|
if allowed_tool_names and function_name not in allowed_tool_names:
|
||||||
|
if function_name == "view_image" and "vlm_analyze" in allowed_tool_names:
|
||||||
|
if not arguments.get("prompt"):
|
||||||
|
arguments["prompt"] = "请详细分析这张图片的内容,包括关键文字、主体对象与场景信息。"
|
||||||
|
debug_log(
|
||||||
|
"工具名自动纠正: view_image -> vlm_analyze (模型未获授权 view_image)"
|
||||||
|
)
|
||||||
|
function_name = "vlm_analyze"
|
||||||
|
else:
|
||||||
|
denied_message = (
|
||||||
|
f"工具 {function_name} 不在当前模型可用工具列表中,已拒绝执行。"
|
||||||
|
)
|
||||||
|
denied_payload = {
|
||||||
|
"success": False,
|
||||||
|
"status": "denied",
|
||||||
|
"code": "tool_not_allowed",
|
||||||
|
"tool": function_name,
|
||||||
|
"message": denied_message,
|
||||||
|
}
|
||||||
|
sender('update_action', {
|
||||||
|
'preparing_id': tool_call_id,
|
||||||
|
'status': 'completed',
|
||||||
|
'result': denied_payload,
|
||||||
|
'message': denied_message,
|
||||||
|
'conversation_id': conversation_id
|
||||||
|
})
|
||||||
|
denied_content = json.dumps(denied_payload, ensure_ascii=False)
|
||||||
|
web_terminal.context_manager.add_conversation(
|
||||||
|
"tool",
|
||||||
|
denied_content,
|
||||||
|
tool_call_id=tool_call_id,
|
||||||
|
name=function_name
|
||||||
|
)
|
||||||
|
messages.append({
|
||||||
|
"role": "tool",
|
||||||
|
"tool_call_id": tool_call_id,
|
||||||
|
"name": function_name,
|
||||||
|
"content": denied_content
|
||||||
|
})
|
||||||
|
continue
|
||||||
|
|
||||||
debug_log(f"执行工具: {function_name} (ID: {tool_call_id})")
|
debug_log(f"执行工具: {function_name} (ID: {tool_call_id})")
|
||||||
|
|
||||||
permission_eval = web_terminal.evaluate_tool_permission(function_name, arguments)
|
permission_eval = web_terminal.evaluate_tool_permission(function_name, arguments)
|
||||||
|
|||||||
@ -65,6 +65,8 @@ Terminal 工具提供了一个可以持续存在的终端会话,命令在其
|
|||||||
- top、htop
|
- top、htop
|
||||||
- 任何需要完整 TTY 的程序
|
- 任何需要完整 TTY 的程序
|
||||||
|
|
||||||
|
# 简单的交互程序 如只需要输入输出内容的py,node程序等可以使用
|
||||||
|
|
||||||
## 三步工作流
|
## 三步工作流
|
||||||
|
|
||||||
使用 terminal 工具的标准流程:
|
使用 terminal 工具的标准流程:
|
||||||
|
|||||||
@ -91,6 +91,11 @@ export async function mounted() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function beforeUnmount() {
|
export function beforeUnmount() {
|
||||||
|
if (this._todoRefreshTimer) {
|
||||||
|
clearTimeout(this._todoRefreshTimer);
|
||||||
|
this._todoRefreshTimer = null;
|
||||||
|
}
|
||||||
|
|
||||||
// 停止任务轮询
|
// 停止任务轮询
|
||||||
try {
|
try {
|
||||||
const { useTaskStore } = require('../stores/task');
|
const { useTaskStore } = require('../stores/task');
|
||||||
|
|||||||
@ -44,6 +44,20 @@ function isEmptyAssistantPlaceholderMessage(message: any): boolean {
|
|||||||
* 将从 REST API 轮询获取的事件转换为前端状态更新
|
* 将从 REST API 轮询获取的事件转换为前端状态更新
|
||||||
*/
|
*/
|
||||||
export const taskPollingMethods = {
|
export const taskPollingMethods = {
|
||||||
|
scheduleTodoListRefresh(delayMs = 120) {
|
||||||
|
const delay = Number.isFinite(delayMs) ? Math.max(0, Number(delayMs)) : 120;
|
||||||
|
if (this._todoRefreshTimer) {
|
||||||
|
clearTimeout(this._todoRefreshTimer);
|
||||||
|
this._todoRefreshTimer = null;
|
||||||
|
}
|
||||||
|
this._todoRefreshTimer = setTimeout(() => {
|
||||||
|
this._todoRefreshTimer = null;
|
||||||
|
if (typeof this.fetchTodoList === 'function') {
|
||||||
|
Promise.resolve(this.fetchTodoList()).catch(() => {});
|
||||||
|
}
|
||||||
|
}, delay);
|
||||||
|
},
|
||||||
|
|
||||||
cleanupTrailingEmptyAssistantPlaceholder(reason = 'unspecified') {
|
cleanupTrailingEmptyAssistantPlaceholder(reason = 'unspecified') {
|
||||||
if (!Array.isArray(this.messages) || !this.messages.length) {
|
if (!Array.isArray(this.messages) || !this.messages.length) {
|
||||||
return false;
|
return false;
|
||||||
@ -912,6 +926,13 @@ export const taskPollingMethods = {
|
|||||||
targetAction.tool.content = data.content;
|
targetAction.tool.content = data.content;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 待办工具执行完成后主动刷新左侧待办列表(网页端不再依赖 websocket todo_updated)
|
||||||
|
if (data.status === 'completed') {
|
||||||
|
const toolName = String(targetAction?.tool?.name || '').toLowerCase();
|
||||||
|
if (toolName.startsWith('todo_') || toolName === 'todo_create' || toolName === 'todo_update_task') {
|
||||||
|
this.scheduleTodoListRefresh(80);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
this.conditionalScrollToBottom();
|
this.conditionalScrollToBottom();
|
||||||
@ -1063,6 +1084,7 @@ export const taskPollingMethods = {
|
|||||||
this.updateCurrentContextTokens();
|
this.updateCurrentContextTokens();
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
|
this.scheduleTodoListRefresh(100);
|
||||||
const pendingToolsAfter =
|
const pendingToolsAfter =
|
||||||
typeof this.hasPendingToolActions === 'function' ? this.hasPendingToolActions() : null;
|
typeof this.hasPendingToolActions === 'function' ? this.hasPendingToolActions() : null;
|
||||||
jsonDebug('handleTaskComplete:after', {
|
jsonDebug('handleTaskComplete:after', {
|
||||||
@ -1099,6 +1121,7 @@ export const taskPollingMethods = {
|
|||||||
if (typeof this.clearPendingTools === 'function') {
|
if (typeof this.clearPendingTools === 'function') {
|
||||||
this.clearPendingTools('task_stopped');
|
this.clearPendingTools('task_stopped');
|
||||||
}
|
}
|
||||||
|
this.scheduleTodoListRefresh(100);
|
||||||
this.$forceUpdate();
|
this.$forceUpdate();
|
||||||
|
|
||||||
this.clearTaskState();
|
this.clearTaskState();
|
||||||
|
|||||||
@ -1600,7 +1600,6 @@ export const uiMethods = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const focusPromise = this.focusFetchFiles();
|
const focusPromise = this.focusFetchFiles();
|
||||||
const todoPromise = this.fileFetchTodoList();
|
|
||||||
let treePromise: Promise<any> | null = null;
|
let treePromise: Promise<any> | null = null;
|
||||||
const isHostMode = statusData?.container?.mode === 'host';
|
const isHostMode = statusData?.container?.mode === 'host';
|
||||||
this.versioningHostMode = !!isHostMode;
|
this.versioningHostMode = !!isHostMode;
|
||||||
@ -1672,6 +1671,9 @@ export const uiMethods = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 待办数据依赖当前会话上下文,放在会话恢复/切换之后拉取,避免初始化早期拿到空快照
|
||||||
|
const todoPromise = this.fileFetchTodoList();
|
||||||
|
|
||||||
// 等待其他加载项完成(允许部分失败不阻塞模式切换)
|
// 等待其他加载项完成(允许部分失败不阻塞模式切换)
|
||||||
const pendingPromises = [focusPromise, todoPromise];
|
const pendingPromises = [focusPromise, todoPromise];
|
||||||
if (treePromise) {
|
if (treePromise) {
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user