merge: integrate main deterministic submit into ws branch

Keep the ws submit path while bringing over main's deterministic lineloss routing and the focused merge verification updates.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
木炎
2026-04-12 14:05:55 +08:00
14 changed files with 3278 additions and 118 deletions

View File

@@ -132,6 +132,40 @@ impl<T: Transport + ?Sized> AgentEventSink for T {
}
}
fn resolve_submit_instruction(
instruction: String,
page_url: Option<&str>,
page_title: Option<&str>,
) -> Result<(String, Option<crate::compat::deterministic_submit::DeterministicExecutionPlan>), AgentMessage> {
let raw_instruction = instruction;
let trimmed_instruction = raw_instruction.trim().to_string();
if trimmed_instruction.is_empty() {
return Err(AgentMessage::TaskComplete {
success: false,
summary: "请输入任务内容。".to_string(),
});
}
match crate::compat::deterministic_submit::decide_deterministic_submit(
&raw_instruction,
page_url,
page_title,
) {
crate::compat::deterministic_submit::DeterministicSubmitDecision::NotDeterministic => {
Ok((trimmed_instruction, None))
}
crate::compat::deterministic_submit::DeterministicSubmitDecision::Prompt { summary } => {
Err(AgentMessage::TaskComplete {
success: false,
summary,
})
}
crate::compat::deterministic_submit::DeterministicSubmitDecision::Execute(plan) => {
Ok((plan.instruction.clone(), Some(plan)))
}
}
}
pub fn run_submit_task<T: Transport + 'static>(
transport: &T,
sink: &dyn AgentEventSink,
@@ -146,13 +180,6 @@ pub fn run_submit_task<T: Transport + 'static>(
page_url,
page_title,
} = request;
let instruction = instruction.trim().to_string();
if instruction.is_empty() {
return sink.send(&AgentMessage::TaskComplete {
success: false,
summary: "请输入任务内容。".to_string(),
});
}
let task_context = CompatTaskContext {
conversation_id,
@@ -160,6 +187,14 @@ pub fn run_submit_task<T: Transport + 'static>(
page_url,
page_title,
};
let (instruction, deterministic_plan) = match resolve_submit_instruction(
instruction,
task_context.page_url.as_deref(),
task_context.page_title.as_deref(),
) {
Ok(resolved) => resolved,
Err(completion) => return sink.send(&completion),
};
let _ = sink.send(&AgentMessage::LogEntry {
level: "info".to_string(),
message: runtime_version_log_message(),
@@ -198,7 +233,32 @@ pub fn run_submit_task<T: Transport + 'static>(
settings.runtime_profile, settings.skills_prompt_mode
),
});
if settings.direct_submit_skill.is_some() {
if let Some(plan) = deterministic_plan.as_ref() {
let _ = send_mode_log(sink, "direct_skill_primary");
let completion =
match crate::compat::deterministic_submit::execute_deterministic_submit(
browser_tool.clone(),
plan,
&context.workspace_root,
&settings,
) {
Ok(outcome) => AgentMessage::TaskComplete {
success: outcome.success,
summary: outcome.summary,
},
Err(err) => AgentMessage::TaskComplete {
success: false,
summary: err.to_string(),
},
};
return sink.send(&completion);
}
if settings
.direct_submit_skill
.as_deref()
.map(str::trim)
.is_some_and(|value| !value.is_empty())
{
match crate::compat::direct_skill_runtime::execute_direct_submit_skill(
browser_tool.clone(),
&instruction,
@@ -311,13 +371,6 @@ pub fn run_submit_task_with_browser_backend<T: Transport + 'static>(
page_url,
page_title,
} = request;
let instruction = instruction.trim().to_string();
if instruction.is_empty() {
return sink.send(&AgentMessage::TaskComplete {
success: false,
summary: "请输入任务内容。".to_string(),
});
}
let task_context = CompatTaskContext {
conversation_id,
@@ -325,6 +378,14 @@ pub fn run_submit_task_with_browser_backend<T: Transport + 'static>(
page_url,
page_title,
};
let (instruction, deterministic_plan) = match resolve_submit_instruction(
instruction,
task_context.page_url.as_deref(),
task_context.page_title.as_deref(),
) {
Ok(resolved) => resolved,
Err(completion) => return sink.send(&completion),
};
let _ = sink.send(&AgentMessage::LogEntry {
level: "info".to_string(),
message: runtime_version_log_message(),
@@ -363,6 +424,61 @@ pub fn run_submit_task_with_browser_backend<T: Transport + 'static>(
settings.runtime_profile, settings.skills_prompt_mode
),
});
if let Some(plan) = deterministic_plan.as_ref() {
let _ = send_mode_log(sink, "direct_skill_primary");
let completion = match crate::compat::deterministic_submit::execute_deterministic_submit_with_browser_backend(
browser_backend.clone(),
plan,
&context.workspace_root,
&settings,
) {
Ok(outcome) => AgentMessage::TaskComplete {
success: outcome.success,
summary: outcome.summary,
},
Err(err) => AgentMessage::TaskComplete {
success: false,
summary: err.to_string(),
},
};
return sink.send(&completion);
}
if settings
.direct_submit_skill
.as_deref()
.map(str::trim)
.is_some_and(|value| !value.is_empty())
{
match crate::compat::direct_skill_runtime::execute_direct_submit_skill_with_browser_backend(
browser_backend.clone(),
&instruction,
&task_context,
&context.workspace_root,
&settings,
) {
Ok(outcome) => {
let _ = send_mode_log(sink, "direct_skill_primary");
return sink.send(&AgentMessage::TaskComplete {
success: outcome.success,
summary: outcome.summary,
});
}
Err(PipeError::Protocol(message))
if message.contains("must use skill.tool format") =>
{
return sink.send(&AgentMessage::TaskComplete {
success: false,
summary: message,
});
}
Err(err) => {
return sink.send(&AgentMessage::TaskComplete {
success: false,
summary: err.to_string(),
});
}
}
}
if RuntimeEngine::new(settings.runtime_profile).browser_surface_enabled()
&& crate::compat::orchestration::should_use_primary_orchestration(
&instruction,