feat: add deterministic tq lineloss submit path

Add the deterministic tq-lineloss routing and normalization flow so exact-suffix requests execute through the existing browser-script seam with canonical org and period arguments.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
木炎
2026-04-12 13:10:58 +08:00
parent 311cc1fee6
commit dd7805d341
12 changed files with 1727 additions and 276 deletions

View File

@@ -2,7 +2,7 @@ use std::path::Path;
use reqwest::Url;
use serde_json::{Map, Value};
use zeroclaw::skills::load_skills_from_directory;
use zeroclaw::skills::{load_skills_from_directory, SkillTool};
use crate::compat::browser_script_skill_tool::execute_browser_script_tool;
use crate::compat::config_adapter::resolve_skills_dir_from_sgclaw_settings;
@@ -29,9 +29,32 @@ pub fn execute_direct_submit_skill<T: Transport + 'static>(
.map(str::trim)
.filter(|value| !value.is_empty())
.ok_or_else(|| PipeError::Protocol("direct submit skill is not configured".to_string()))?;
let (skill_name, tool_name) = parse_configured_tool_name(configured_tool)?;
let expected_domain = derive_expected_domain(task_context)?;
let period = derive_period(instruction)?;
let mut args = Map::new();
args.insert("expected_domain".to_string(), Value::String(expected_domain));
args.insert("period".to_string(), Value::String(period));
let output = execute_browser_script_skill_raw_output(
browser_tool,
configured_tool,
workspace_root,
settings,
args,
)?;
Ok(interpret_direct_submit_output(&output))
}
pub fn execute_browser_script_skill_raw_output<T: Transport + 'static>(
browser_tool: BrowserPipeTool<T>,
configured_tool: &str,
workspace_root: &Path,
settings: &SgClawSettings,
args: Map<String, Value>,
) -> Result<String, PipeError> {
let (skill_name, tool_name) = parse_configured_tool_name(configured_tool)?;
let skills_dir = resolve_skills_dir_from_sgclaw_settings(workspace_root, settings);
let skills = load_skills_from_directory(&skills_dir, true);
let skill = skills
@@ -53,13 +76,6 @@ pub fn execute_direct_submit_skill<T: Transport + 'static>(
))
})?;
if tool.kind != "browser_script" {
return Err(PipeError::Protocol(format!(
"direct submit tool {configured_tool} must be browser_script, got {}",
tool.kind
)));
}
let skill_root = skill
.location
.as_deref()
@@ -70,15 +86,31 @@ pub fn execute_direct_submit_skill<T: Transport + 'static>(
))
})?;
let mut args = Map::new();
args.insert("expected_domain".to_string(), Value::String(expected_domain));
args.insert("period".to_string(), Value::String(period));
execute_browser_script_tool_output(browser_tool, configured_tool, tool, skill_root, args)
}
fn execute_browser_script_tool_output<T: Transport + 'static>(
browser_tool: BrowserPipeTool<T>,
configured_tool: &str,
tool: &SkillTool,
skill_root: &Path,
args: Map<String, Value>,
) -> Result<String, PipeError> {
if tool.kind != "browser_script" {
return Err(PipeError::Protocol(format!(
"direct submit tool {configured_tool} must be browser_script, got {}",
tool.kind
)));
}
let mut tool = tool.clone();
tool.args.remove("expected_domain");
let runtime = tokio::runtime::Runtime::new()
.map_err(|err| PipeError::Protocol(format!("failed to create tokio runtime: {err}")))?;
let result = runtime
.block_on(execute_browser_script_tool(
tool,
&tool,
skill_root,
browser_tool,
Value::Object(args),
@@ -86,7 +118,7 @@ pub fn execute_direct_submit_skill<T: Transport + 'static>(
.map_err(|err| PipeError::Protocol(err.to_string()))?;
if result.success {
Ok(interpret_direct_submit_output(&result.output))
Ok(result.output)
} else {
Err(PipeError::Protocol(
result