feat: align browser callback runtime and export flows
Consolidate the browser task runtime around the callback path, add safer artifact opening for Zhihu exports, and cover the new service/browser flows with focused tests and supporting docs. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -1,45 +1,16 @@
|
||||
pub mod planner;
|
||||
pub mod runtime;
|
||||
pub mod task_runner;
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use crate::browser::ws_backend::WsBrowserBackend;
|
||||
use crate::browser::{BrowserBackend, PipeBrowserBackend};
|
||||
use crate::pipe::{AgentMessage, BrowserMessage, BrowserPipeTool, PipeError, Transport};
|
||||
use crate::pipe::{BrowserMessage, BrowserPipeTool, PipeError, Transport};
|
||||
|
||||
pub use task_runner::{
|
||||
run_submit_task, run_submit_task_with_browser_backend, AgentEventSink, AgentRuntimeContext,
|
||||
SubmitTaskRequest,
|
||||
};
|
||||
|
||||
fn execute_plan<T: Transport>(
|
||||
transport: &T,
|
||||
browser_tool: &BrowserPipeTool<T>,
|
||||
plan: &planner::TaskPlan,
|
||||
) -> Result<String, PipeError> {
|
||||
for step in &plan.steps {
|
||||
transport.send(&AgentMessage::LogEntry {
|
||||
level: "info".to_string(),
|
||||
message: step.log_message.clone(),
|
||||
})?;
|
||||
|
||||
let result = browser_tool.invoke(
|
||||
step.action.clone(),
|
||||
step.params.clone(),
|
||||
&step.expected_domain,
|
||||
)?;
|
||||
if !result.success {
|
||||
return Err(PipeError::Protocol(format!(
|
||||
"browser action failed: {}",
|
||||
result.data
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(plan.summary.clone())
|
||||
}
|
||||
|
||||
fn normalize_optional_submit_field(value: String) -> Option<String> {
|
||||
let trimmed = value.trim();
|
||||
(!trimmed.is_empty()).then(|| trimmed.to_string())
|
||||
@@ -82,21 +53,11 @@ fn configured_browser_ws_url(context: &AgentRuntimeContext) -> Option<String> {
|
||||
}
|
||||
|
||||
fn send_status_changed<T: Transport>(transport: &T, state: &str) -> Result<(), PipeError> {
|
||||
transport.send(&AgentMessage::StatusChanged {
|
||||
transport.send(&crate::pipe::AgentMessage::StatusChanged {
|
||||
state: state.to_string(),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn execute_task<T: Transport>(
|
||||
transport: &T,
|
||||
browser_tool: &BrowserPipeTool<T>,
|
||||
instruction: &str,
|
||||
) -> Result<String, PipeError> {
|
||||
let plan = planner::plan_instruction(instruction)
|
||||
.map_err(|err| PipeError::Protocol(err.to_string()))?;
|
||||
execute_plan(transport, browser_tool, &plan)
|
||||
}
|
||||
|
||||
pub fn handle_browser_message<T: Transport + 'static>(
|
||||
transport: &T,
|
||||
browser_tool: &BrowserPipeTool<T>,
|
||||
@@ -151,6 +112,8 @@ pub fn handle_browser_message_with_context<T: Transport + 'static>(
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::normalize_optional_submit_field;
|
||||
use std::fs;
|
||||
use std::path::PathBuf;
|
||||
|
||||
#[test]
|
||||
fn normalize_optional_submit_field_trims_and_drops_blank_values() {
|
||||
@@ -160,4 +123,21 @@ mod tests {
|
||||
Some("https://example.com/page".to_string())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn agent_module_cleanup_removes_legacy_runtime_and_planner_sources() {
|
||||
let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR"));
|
||||
let agent_module = fs::read_to_string(manifest_dir.join("src/agent/mod.rs")).unwrap();
|
||||
let top_lines = agent_module
|
||||
.lines()
|
||||
.take(10)
|
||||
.map(str::trim)
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
assert!(!manifest_dir.join("src/agent/runtime.rs").exists());
|
||||
assert!(!manifest_dir.join("src/agent/planner.rs").exists());
|
||||
assert!(!top_lines.iter().any(|line| *line == "pub mod runtime;"));
|
||||
assert!(!top_lines.iter().any(|line| *line == "pub mod planner;"));
|
||||
assert!(top_lines.iter().any(|line| *line == "pub mod task_runner;"));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user