wip: checkpoint 2026-03-29 runtime work

This commit is contained in:
zyl
2026-03-29 22:44:30 +08:00
parent 7d9036b2d4
commit e294fbb9b1
30 changed files with 6759 additions and 161 deletions

View File

@@ -4,10 +4,11 @@ pub mod runtime;
use std::ffi::OsString;
use std::path::PathBuf;
use crate::compat::config_adapter::resolve_skills_dir_from_sgclaw_settings;
use crate::compat::runtime::CompatTaskContext;
use crate::config::DeepSeekSettings;
use crate::config::SgClawSettings;
use crate::pipe::{
AgentMessage, BrowserMessage, BrowserPipeTool, ConversationMessage, PipeError, Transport,
AgentMessage, BrowserMessage, BrowserPipeTool, PipeError, Transport,
};
#[derive(Debug, Clone, PartialEq, Eq)]
@@ -58,12 +59,12 @@ impl AgentRuntimeContext {
Ok(Self::new(config_path, workspace_root))
}
fn load_deepseek_settings(&self) -> Result<Option<DeepSeekSettings>, PipeError> {
DeepSeekSettings::load(self.config_path.as_deref())
fn load_sgclaw_settings(&self) -> Result<Option<SgClawSettings>, PipeError> {
SgClawSettings::load(self.config_path.as_deref())
.map_err(|err| PipeError::Protocol(err.to_string()))
}
fn deepseek_source_label(&self) -> String {
fn settings_source_label(&self) -> String {
match &self.config_path {
Some(path) if path.exists() => path.display().to_string(),
_ => "environment".to_string(),
@@ -88,39 +89,9 @@ fn send_mode_log<T: Transport>(transport: &T, mode: &str) -> Result<(), PipeErro
})
}
fn explicit_non_task_response(history: &[ConversationMessage], instruction: &str) -> Option<String> {
if !history.is_empty() {
return None;
}
let trimmed = instruction.trim();
if trimmed.is_empty() {
return Some("sgClaw 目前只处理浏览器任务,请直接描述要打开、搜索、点击或提取的网页操作。".to_string());
}
const TASK_HINTS: &[&str] = &[
"打开", "搜索", "点击", "输入", "导航", "跳转", "访问", "提取", "获取", "网页", "页面",
"标签页", "百度", "知乎", "google", "open", "search", "click", "type", "navigate",
];
if TASK_HINTS.iter().any(|hint| trimmed.contains(hint)) {
return None;
}
const CHITCHAT_INPUTS: &[&str] = &[
"hi", "hello", "hey", "你好", "您好", "", "在吗", "你是谁", "介绍一下你自己",
];
if CHITCHAT_INPUTS
.iter()
.any(|candidate| trimmed.eq_ignore_ascii_case(candidate) || trimmed == *candidate)
{
return Some("sgClaw 现在是浏览器任务入口,不做通用闲聊。请直接说你想在网页上执行什么操作,例如“打开百度搜索天气”。".to_string());
}
if trimmed.chars().count() <= 8 {
return Some("sgClaw 现在只处理浏览器任务。请直接描述网页操作目标,例如“打开知乎搜索天气”或“提取当前页面标题”。".to_string());
}
None
fn missing_llm_configuration_summary() -> String {
"未配置大语言模型。请先在 sgclaw_config.json 或环境变量中配置 apiKey、baseUrl 与 model。"
.to_string()
}
fn execute_plan<T: Transport>(
@@ -187,10 +158,11 @@ pub fn handle_browser_message_with_context<T: Transport + 'static>(
page_url,
page_title,
} => {
if let Some(summary) = explicit_non_task_response(&messages, &instruction) {
let instruction = instruction.trim().to_string();
if instruction.is_empty() {
return transport.send(&AgentMessage::TaskComplete {
success: false,
summary,
summary: "请输入任务内容。".to_string(),
});
}
@@ -210,19 +182,64 @@ pub fn handle_browser_message_with_context<T: Transport + 'static>(
),
});
}
let completion = match context.load_deepseek_settings() {
let completion = match context.load_sgclaw_settings() {
Ok(Some(settings)) => {
let resolved_skills_dir =
resolve_skills_dir_from_sgclaw_settings(&context.workspace_root, &settings);
let _ = transport.send(&AgentMessage::LogEntry {
level: "info".to_string(),
message: format!(
"DeepSeek config loaded from {} model={} base_url={}",
context.deepseek_source_label(),
settings.model,
settings.base_url
context.settings_source_label(),
settings.provider_model,
settings.provider_base_url
),
});
let _ = transport.send(&AgentMessage::LogEntry {
level: "info".to_string(),
message: format!(
"skills dir resolved to {}",
resolved_skills_dir.display()
),
});
let _ = transport.send(&AgentMessage::LogEntry {
level: "info".to_string(),
message: format!(
"runtime profile={:?} skills_prompt_mode={:?}",
settings.runtime_profile,
settings.skills_prompt_mode
),
});
if crate::compat::orchestration::should_use_primary_orchestration(
&instruction,
task_context.page_url.as_deref(),
task_context.page_title.as_deref(),
) {
let _ = send_mode_log(transport, "zeroclaw_process_message_primary");
match crate::compat::orchestration::execute_task_with_sgclaw_settings(
transport,
browser_tool.clone(),
&instruction,
&task_context,
&context.workspace_root,
&settings,
) {
Ok(summary) => {
return transport.send(&AgentMessage::TaskComplete {
success: true,
summary,
})
}
Err(err) => {
return transport.send(&AgentMessage::TaskComplete {
success: false,
summary: err.to_string(),
})
}
}
}
let _ = send_mode_log(transport, "compat_llm_primary");
match crate::compat::runtime::execute_task(
match crate::compat::runtime::execute_task_with_sgclaw_settings(
transport,
browser_tool.clone(),
&instruction,
@@ -240,24 +257,9 @@ pub fn handle_browser_message_with_context<T: Transport + 'static>(
},
}
}
Ok(None) => match planner::plan_instruction(&instruction) {
Ok(plan) => {
let _ = send_mode_log(transport, "deterministic_planner");
match execute_plan(transport, browser_tool, &plan) {
Ok(summary) => AgentMessage::TaskComplete {
success: true,
summary,
},
Err(err) => AgentMessage::TaskComplete {
success: false,
summary: err.to_string(),
},
}
}
Err(err) => AgentMessage::TaskComplete {
success: false,
summary: PipeError::Protocol(err.to_string()).to_string(),
},
Ok(None) => AgentMessage::TaskComplete {
success: false,
summary: missing_llm_configuration_summary(),
},
Err(err) => {
let _ = transport.send(&AgentMessage::LogEntry {