feat: persist sgclaw browser conversations

This commit is contained in:
zyl
2026-03-27 01:57:42 +08:00
parent bae0e452a5
commit d315c13f66
11 changed files with 402 additions and 20 deletions

View File

@@ -105,6 +105,7 @@ fn parse_browser_action_request(args: Value) -> Result<BrowserActionRequest, Bro
let action_name = take_required_string(&mut args, "action")?;
let expected_domain = take_required_string(&mut args, "expected_domain")?;
let action = parse_action(&action_name)?;
validate_action_params(&action_name, &args)?;
Ok(BrowserActionRequest {
action,
@@ -146,6 +147,37 @@ fn failed_tool_result(error: String) -> ToolResult {
}
}
fn validate_action_params(
action_name: &str,
args: &Map<String, Value>,
) -> Result<(), BrowserActionAdapterError> {
match action_name {
"click" | "getText" => require_non_empty_string(args, "selector", action_name),
"type" => {
require_non_empty_string(args, "selector", action_name)?;
require_non_empty_string(args, "text", action_name)
}
"navigate" => require_non_empty_string(args, "url", action_name),
_ => Ok(()),
}
}
fn require_non_empty_string(
args: &Map<String, Value>,
key: &'static str,
action_name: &str,
) -> Result<(), BrowserActionAdapterError> {
match args.get(key) {
Some(Value::String(value)) if !value.trim().is_empty() => Ok(()),
Some(other) => Err(BrowserActionAdapterError::InvalidArguments(format!(
"{action_name} requires a non-empty {key}, got {other}"
))),
None => Err(BrowserActionAdapterError::InvalidArguments(format!(
"{action_name} requires {key}"
))),
}
}
fn format_browser_action_error(data: &Value) -> String {
if let Some(error) = data.get("error") {
if let Some(message) = error.get("message").and_then(Value::as_str) {