优化: run_command 实时流式 + 审批浮窗修复 + 文档探索闭环(fetch_url+obscura引导+model_fetch兼容+prompt策略+厂商预设)

This commit is contained in:
lxy
2026-08-01 17:58:47 +08:00
parent 0e0c6862ba
commit d664bdc309
25 changed files with 1693 additions and 44 deletions
+58
View File
@@ -116,6 +116,40 @@ fn system_prompt_parts(lang: &str) -> (&'static str, &'static str, &'static str)
}
}
/// 文档探索策略段(中/英):引导 AI 收到 URL 时走「嗅探→识别→提取→验证→应用」,
/// 而非盲目对 URL 发 http_request 瞎试。
///
/// 机制治症状:实测 AI 收到产品/文档 URL 时,会直接 http_request 打原始 URL(HTML 噪声爆 token、
/// 也调不出真正 API 端点),应先用 fetch_url 转成可读 markdown 理解文档,提取 base_url/鉴权/
/// 端点路径后,再用 http_request 打正确端点验证。
///
/// - fetch_url = 读文档(URL→markdown,去 HTML 噪声);http_request = 调 API(POST/鉴权/原始响应)
/// - 不瞎试 URL:先读文档提取端点,再验证;杜绝未读文档即对原始 URL 盲发请求
///
/// 仅段加在 prefix 末尾(聚焦段后),不破坏现有结构。
fn doc_exploration_strategy_section(lang: &str) -> &'static str {
match lang {
"en" => "\n\
## Documentation Exploration Strategy\n\
When the user gives you a URL (product page / API docs / SDK guide), follow this flow instead of blindly firing http_request at the raw URL:\n\
1. **Sniff**: call `fetch_url` to turn the URL into clean markdown (strips HTML noise) and read what the page actually says.\n\
2. **Identify intent**: is it an API doc (endpoints/auth), a product capability page, a config spec, or a code sample?\n\
3. **Extract keys**: pull out base_url, provider_type, auth scheme, model list, endpoint paths — write them down explicitly before calling anything.\n\
4. **Verify**: only now use `http_request` against the correct endpoint you extracted (e.g. `GET {base_url}/v1/models` with the auth header) to confirm it works.\n\
5. **Apply**: configure the Provider / write code / transcribe into a file via `write_file`.\n\
Rule: `fetch_url` is for *reading* a URL (docs/web/API description, markdown output); `http_request` is for *calling* an API (POST/auth/raw response). Never guess an endpoint — read the doc first, extract, then verify.\n",
_ => "\n\
## 文档探索策略\n\
收到用户给的 URL(产品页/API 文档/SDK 说明)时,按以下流程走,不要盲目对原始 URL 发 http_request 瞎试:\n\
1. **嗅探**:先调 `fetch_url` 把 URL 转成干净的 markdown(剥离 HTML 噪声),读明白页面到底写了什么。\n\
2. **识别意图**:是 API 文档(端点/鉴权)、产品能力页、配置规格,还是代码示例?\n\
3. **提取关键**:把 base_url、provider_type、鉴权方式、模型清单、端点路径显式列出来,再决定调什么。\n\
4. **验证**:此时才用 `http_request` 打你提取出的正确端点(如带鉴权头 `GET {base_url}/v1/models`)确认可用。\n\
5. **应用**:配置 Provider / 编码 / 转写到文件(write_file)。\n\
铁律:`fetch_url` 用于**读** URL(文档/网页/API 说明,输出 markdown);`http_request` 用于**调** API(POST/鉴权/原始响应)。严禁猜端点——先读文档提取,再验证。\n",
}
}
/// 构建系统提示词(环境信息 + 固定前缀 + 当前项目/任务**全局清单**)
///
/// 本函数注入"全貌"清单:最近 20 项目 + 20 任务的 name/status/description(无 path),
@@ -155,6 +189,8 @@ pub(crate) async fn build_system_prompt_with_excluded(
let (prefix, proj_label, task_label) = system_prompt_parts(lang);
let mut prompt = env_profile_line();
prompt.push_str(prefix);
// 文档探索策略段(URL→fetch_url 嗅探→识别→提取→验证→应用,治盲目 http_request 瞎试)
prompt.push_str(doc_exploration_strategy_section(lang));
// 附加当前数据上下文
if let Ok(projects) = state.projects.list_active().await {
@@ -343,6 +379,28 @@ mod tests {
assert!(prefix.contains("聚焦准则"));
}
// 文档探索策略段(中/英)存在且含关键引导
#[test]
fn doc_exploration_strategy_section_present_zh_en() {
let zh = doc_exploration_strategy_section("zh-CN");
assert!(zh.contains("## 文档探索策略"));
assert!(zh.contains("fetch_url"));
assert!(zh.contains("http_request"));
assert!(zh.contains("嗅探"));
assert!(zh.contains("识别意图"));
assert!(zh.contains("提取关键"));
assert!(zh.contains("验证"));
assert!(zh.contains("应用"));
let en = doc_exploration_strategy_section("en");
assert!(en.contains("## Documentation Exploration Strategy"));
assert!(en.contains("Sniff"));
assert!(en.contains("Identify intent"));
assert!(en.contains("Extract keys"));
assert!(en.contains("Verify"));
assert!(en.contains("Apply"));
}
#[test]
fn compress_prompt_unaffected_by_focus_addition() {
// 压缩 prompt 是独立函数,聚焦段改动不应波及