refactor(service): unify submit bootstrap target resolution

Use page context, deterministic plans, and direct-skill metadata as the service-owned bootstrap target precedence so callback-host startup no longer relies on line-loss text matching or the old request-url helper.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
木炎
2026-04-14 20:23:24 +08:00
parent 044d38003d
commit bd83d92480
8 changed files with 498 additions and 49 deletions

View File

@@ -194,12 +194,34 @@ fn start_callback_host_hotlist_browser_server(
.send(CallbackHostBrowserEvent::BrowserFrame(first_action.clone()))
.unwrap();
let Some(values) = first_action.as_array() else {
let second_action = match websocket.read().unwrap() {
Message::Text(text) => serde_json::from_str::<Value>(&text).unwrap(),
other => panic!("expected second browser action frame, got {other:?}"),
};
event_tx
.send(CallbackHostBrowserEvent::BrowserFrame(second_action.clone()))
.unwrap();
let Some(close_values) = first_action.as_array() else {
websocket.close(None).ok();
return;
};
let is_helper_close = close_values.len() >= 3
&& close_values[1] == json!("sgHideBrowerserClosePage")
&& close_values[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html"));
if !is_helper_close {
websocket.close(None).ok();
return;
}
let Some(values) = second_action.as_array() else {
websocket.close(None).ok();
return;
};
let is_helper_open = values.len() >= 3
&& values[1] == json!("sgBrowerserOpenPage")
&& values[1] == json!("sgHideBrowerserOpenPage")
&& values[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html"));
@@ -873,6 +895,7 @@ fn service_binary_submit_flow_routes_zhihu_through_callback_host() {
browser_server.join().unwrap();
let register = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let bootstrap_close = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let bootstrap = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let pre_ready = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let open_page = event_rx.recv_timeout(Duration::from_secs(4)).unwrap();
@@ -902,12 +925,22 @@ fn service_binary_submit_flow_routes_zhihu_through_callback_host() {
};
assert_eq!(register, json!({ "type": "register", "role": "web" }));
let bootstrap_close = match bootstrap_close {
CallbackHostBrowserEvent::BrowserFrame(value) => value,
other => panic!("expected helper close frame, got {other:?}"),
};
assert_eq!(bootstrap_close[0], json!("https://www.zhihu.com"));
assert_eq!(bootstrap_close[1], json!("sgHideBrowerserClosePage"));
assert!(bootstrap_close[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html")));
let bootstrap = match bootstrap {
CallbackHostBrowserEvent::BrowserFrame(value) => value,
other => panic!("expected helper bootstrap frame, got {other:?}"),
};
assert_eq!(bootstrap[0], json!("https://www.zhihu.com"));
assert_eq!(bootstrap[1], json!("sgBrowerserOpenPage"));
assert_eq!(bootstrap[1], json!("sgHideBrowerserOpenPage"));
assert!(bootstrap[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html")));
@@ -1046,6 +1079,7 @@ fn service_binary_submit_flow_uses_callback_host_command_semantics_for_zhihu() {
browser_server.join().unwrap();
let register = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let bootstrap_close = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let bootstrap = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let pre_ready = event_rx.recv_timeout(Duration::from_secs(2)).unwrap();
let open_page = event_rx.recv_timeout(Duration::from_secs(4)).unwrap();
@@ -1075,12 +1109,22 @@ fn service_binary_submit_flow_uses_callback_host_command_semantics_for_zhihu() {
};
assert_eq!(register, json!({ "type": "register", "role": "web" }));
let bootstrap_close = match bootstrap_close {
CallbackHostBrowserEvent::BrowserFrame(value) => value,
other => panic!("expected helper close frame, got {other:?}"),
};
assert_eq!(bootstrap_close[0], json!("https://www.zhihu.com"));
assert_eq!(bootstrap_close[1], json!("sgHideBrowerserClosePage"));
assert!(bootstrap_close[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html")));
let bootstrap = match bootstrap {
CallbackHostBrowserEvent::BrowserFrame(value) => value,
other => panic!("expected helper bootstrap frame, got {other:?}"),
};
assert_eq!(bootstrap[0], json!("https://www.zhihu.com"));
assert_eq!(bootstrap[1], json!("sgBrowerserOpenPage"));
assert_eq!(bootstrap[1], json!("sgHideBrowerserOpenPage"));
assert!(bootstrap[2]
.as_str()
.is_some_and(|url| url.ends_with("/sgclaw/browser-helper.html")));