优化: prompt 策略(obscura 失败重试 + 精确不猜 + 工具职责 + get_app_config 引导)
obscura render 失败 2 次换方案 + 成功即收手;精确提取链接不臆造 URL;fetch_url/download_file /http_request 职责区分;get_app_config 引导(禁 run_command 查配置)。
This commit is contained in:
@@ -135,6 +135,17 @@ fn doc_exploration_strategy_section(lang: &str) -> &'static str {
|
|||||||
match lang {
|
match lang {
|
||||||
"en" => "\n\
|
"en" => "\n\
|
||||||
## Documentation Exploration Strategy\n\
|
## Documentation Exploration Strategy\n\
|
||||||
|
### Pick the right URL tool first (do NOT mix them up)\n\
|
||||||
|
Three URL tools exist — using the wrong one fails and wastes round-trips:\n\
|
||||||
|
- `fetch_url`: read a URL and convert to markdown (**HTML docs only**; refuses binary/images/files). For web pages, API docs, blog posts.\n\
|
||||||
|
- `download_file`: **download any file** (image / archive / binary / document) to local disk. Streaming, binary-safe, never goes into the prompt.\n\
|
||||||
|
- `http_request`: call an API (POST / auth / raw JSON response). For REST endpoints, webhooks, structured payloads.\n\
|
||||||
|
Hard rule by URL kind:\n\
|
||||||
|
1. **Image / archive / binary file URL** (e.g. `.png` `.jpg` `.zip` `.pdf` `.exe` `.tar.gz`) → use `download_file`. Never `fetch_url` (it rejects binary) and never `run_command` curl (fails on Windows alias/encoding).\n\
|
||||||
|
2. **Web page / doc URL** (HTML the browser would render) → use `fetch_url`.\n\
|
||||||
|
3. **API endpoint URL** (returns JSON / needs auth / POST body) → use `http_request`.\n\
|
||||||
|
If `fetch_url` ever returns an error mentioning binary content, switch to `download_file` immediately — do not retry `fetch_url` and do not fall back to `run_command` curl.\n\
|
||||||
|
\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\
|
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\
|
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\
|
2. **Identify intent**: is it an API doc (endpoints/auth), a product capability page, a config spec, or a code sample?\n\
|
||||||
@@ -143,6 +154,20 @@ fn doc_exploration_strategy_section(lang: &str) -> &'static str {
|
|||||||
5. **Apply**: configure the Provider / write code / transcribe into a file via `write_file`.\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\
|
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\
|
||||||
|
### Extract real links — NEVER fabricate URLs\n\
|
||||||
|
After a `fetch_url`/`http_request` returns content, do **not** invent URLs from memory or convention (no guessing `#hash` anchors, no speculating `/path` routes, no trying 'what the URL probably is'). Guessed URLs are ~99% dead (404/403) and waste round-trips. Extract the *real* links from the returned content, then fetch those verbatim:\n\
|
||||||
|
1. **Pull real links out of the response**: markdown `[text](url)`, HTML `<a href>` / `<script src>` / `<link href>`, JSON `url` / `endpoint` / `href` fields — these are the only URLs you may fire. A URL that does not appear in the returned content does not exist for you.\n\
|
||||||
|
2. **Fetch extracted URLs verbatim**: use the extracted URL exactly as-is — keep query params, do not strip the path, do not add a `#hash`, do not 'correct' the route. The link in the content is the link you fetch.\n\
|
||||||
|
3. **No explicit link → do not blind-fire**: never assemble a URL from hunches like 'it should be /api/xxx' or 'probably #download'. Instead, find an entry in the returned content (navigation / index page / official doc root), or ask the user for the exact link.\n\
|
||||||
|
4. **API endpoints are the same**: read base_url / path precisely from the doc or response fields (`base_url` / `endpoint` / `api_base`). Do not speculate routes like `/v1/chat/completions` — different vendors use different paths, and a guess is almost always wrong.\n\
|
||||||
|
Rule: send a request only when there is a sourced link; never fabricate a URL out of thin air.\n\
|
||||||
|
\n\
|
||||||
|
### render=true failure-retry rule (stop the AI hammering one URL)\n\
|
||||||
|
`fetch_url render=true` (JS render) failure signals: `html=0` (empty content), timeout, or an `obscura_failed` response. Observed: the AI repeatedly re-fires render=true at the same URL (each call times out at 30s; 8 retries = 4 minutes wasted, 8% success rate) — it **refuses to give up or switch tactics**. Mandatory rules:\n\
|
||||||
|
1. **Switch after 2 failures**: if `render=true` fails twice in a row (any failure signal) → **immediately stop retrying that URL**. Pick an alternative: (a) use `http_request` to hit the API endpoint directly; (b) ask the user to provide content/screenshots manually; (c) work with the data you already have and produce output now — don't wait for a perfect render.\n\
|
||||||
|
2. **Stop after the first success**: if the first `render=true` succeeds and returns markdown → **use the data you have immediately**; do NOT re-render the same URL to top up more content (what you got is what you use).\n\
|
||||||
|
3. **Never re-render the same URL**: once a URL's render result (success or failure) is known, never fire render=true at it again (history/cache is enough); for new content, switch URL or switch tactic.\n\
|
||||||
|
\n\
|
||||||
### JS-rendered docs & the obscura install hint\n\
|
### JS-rendered docs & the obscura install hint\n\
|
||||||
`fetch_url` defaults to a static fetch (no JS). For SPA / anti-scrape / JS-rendered docs, the user (or you) can pass `render=true`. When obscura (the JS-rendering backend, github.com/h4ckf0r0day/obscura) is **not installed**, the result silently falls back to static and the returned JSON carries `render_mode: \"static_fallback\"` plus a `hint` field pointing to the install page. Watch the **`hint` field** specifically (not just `render_mode`) — it is the install signal:\n\
|
`fetch_url` defaults to a static fetch (no JS). For SPA / anti-scrape / JS-rendered docs, the user (or you) can pass `render=true`. When obscura (the JS-rendering backend, github.com/h4ckf0r0day/obscura) is **not installed**, the result silently falls back to static and the returned JSON carries `render_mode: \"static_fallback\"` plus a `hint` field pointing to the install page. Watch the **`hint` field** specifically (not just `render_mode`) — it is the install signal:\n\
|
||||||
1. **Notice**: if the `fetch_url` result has `hint` set (or `render_mode` is `static_fallback`), obscura is missing and the page may be under-rendered.\n\
|
1. **Notice**: if the `fetch_url` result has `hint` set (or `render_mode` is `static_fallback`), obscura is missing and the page may be under-rendered.\n\
|
||||||
@@ -155,6 +180,17 @@ fn doc_exploration_strategy_section(lang: &str) -> &'static str {
|
|||||||
This is a pure conversational guide — there is no UI button for it; you detect the hint and drive the install through dialogue.\n",
|
This is a pure conversational guide — there is no UI button for it; you detect the hint and drive the install through dialogue.\n",
|
||||||
_ => "\n\
|
_ => "\n\
|
||||||
## 文档探索策略\n\
|
## 文档探索策略\n\
|
||||||
|
### 先选对 URL 工具(三者别混用)\n\
|
||||||
|
有三个 URL 工具——用错就失败、纯浪费往返:\n\
|
||||||
|
- `fetch_url`:读 URL 转 markdown(**仅 HTML 文档**;二进制/图片/文件一律拒)。用于网页、API 文档、博客。\n\
|
||||||
|
- `download_file`:**下载任意文件**(图片/压缩包/二进制/文档)到本地。流式写,二进制安全,内容不进 prompt。\n\
|
||||||
|
- `http_request`:调 API(POST/鉴权/原始 JSON 响应)。用于 REST 端点、webhook、结构化请求体。\n\
|
||||||
|
按 URL 类型选工具的铁律:\n\
|
||||||
|
1. **图片/压缩包/二进制文件 URL**(如 `.png` `.jpg` `.zip` `.pdf` `.exe` `.tar.gz`)→ 用 `download_file`。绝不用 `fetch_url`(它拒二进制),也不用 `run_command` curl(Windows 上 alias/编码会失败)。\n\
|
||||||
|
2. **网页/文档 URL**(浏览器会渲染的 HTML)→ 用 `fetch_url`。\n\
|
||||||
|
3. **API 端点 URL**(返回 JSON/需鉴权/POST body)→ 用 `http_request`。\n\
|
||||||
|
若 `fetch_url` 返回的错误信息提到二进制内容,立即改用 `download_file`——不要重试 `fetch_url`,也不要回退到 `run_command` curl。\n\
|
||||||
|
\n\
|
||||||
收到用户给的 URL(产品页/API 文档/SDK 说明)时,按以下流程走,不要盲目对原始 URL 发 http_request 瞎试:\n\
|
收到用户给的 URL(产品页/API 文档/SDK 说明)时,按以下流程走,不要盲目对原始 URL 发 http_request 瞎试:\n\
|
||||||
1. **嗅探**:先调 `fetch_url` 把 URL 转成干净的 markdown(剥离 HTML 噪声),读明白页面到底写了什么。\n\
|
1. **嗅探**:先调 `fetch_url` 把 URL 转成干净的 markdown(剥离 HTML 噪声),读明白页面到底写了什么。\n\
|
||||||
2. **识别意图**:是 API 文档(端点/鉴权)、产品能力页、配置规格,还是代码示例?\n\
|
2. **识别意图**:是 API 文档(端点/鉴权)、产品能力页、配置规格,还是代码示例?\n\
|
||||||
@@ -163,6 +199,20 @@ fn doc_exploration_strategy_section(lang: &str) -> &'static str {
|
|||||||
5. **应用**:配置 Provider / 编码 / 转写到文件(write_file)。\n\
|
5. **应用**:配置 Provider / 编码 / 转写到文件(write_file)。\n\
|
||||||
铁律:`fetch_url` 用于**读** URL(文档/网页/API 说明,输出 markdown);`http_request` 用于**调** API(POST/鉴权/原始响应)。严禁猜端点——先读文档提取,再验证。\n\
|
铁律:`fetch_url` 用于**读** URL(文档/网页/API 说明,输出 markdown);`http_request` 用于**调** API(POST/鉴权/原始响应)。严禁猜端点——先读文档提取,再验证。\n\
|
||||||
\n\
|
\n\
|
||||||
|
### 精确提取链接,严禁臆造 URL\n\
|
||||||
|
`fetch_url`/`http_request` 拿到返回内容后,**不要**凭印象/惯例臆造 URL(不猜 `#hash` 锚点、不推测 `/path` 路由、不试「这 URL 大概是啥」)。猜出来的 URL 99% 是死链(404/403),纯浪费往返。要从返回内容里提取**真实链接**,再原样 fetch:\n\
|
||||||
|
1. **从返回内容提取真实链接**:markdown `[文本](url)`、HTML `<a href>`/`<script src>`/`<link href>`、JSON 的 `url`/`endpoint`/`href` 字段——这些才是你能发的 URL。返回内容里没出现的 URL,对你而言不存在。\n\
|
||||||
|
2. **原样 fetch 提取到的 URL**:提取到的 URL 一字不改地用——保留查询参数,不删 path、不补 `#hash`、不「修正」路由。内容里的链接是啥,你就 fetch 啥。\n\
|
||||||
|
3. **没有明确链接 → 不盲试**:绝不凭「应该是 /api/xxx」「大概是 #download」拼 URL。回内容里找入口(导航/索引页/官方文档根),或直接问用户要准确链接。\n\
|
||||||
|
4. **API 端点同理**:base_url/path 从文档/响应字段精确读出(`base_url`/`endpoint`/`api_base`)。不推测 `/v1/chat/completions` 之类路由——不同厂商路径不同,猜必错。\n\
|
||||||
|
铁律:有据可查才发请求,无据绝不臆造 URL。\n\
|
||||||
|
\n\
|
||||||
|
### render=true 失败重试铁律(治 AI 死磕同一 URL)\n\
|
||||||
|
`fetch_url render=true`(JS 渲染)失败信号:`html=0`(空内容)、超时、或返回 `obscura_failed`。实测 AI 会反复对同一 URL 重发 render=true(单次 30s 超时,连发 8 次=浪费 4 分钟,成功率 8%),**不认输、不换方案**。强制规则:\n\
|
||||||
|
1. **失败 2 次必换方案**:`render=true` 连续 2 次失败(任意失败信号) → **立即停止重试同一 URL**,改走以下任一:(a) 改用 `http_request` 直接打 API 端点;(b) 提示用户手动提供内容/截图;(c) 用已拿到的数据先整理输出,别等完美渲染。\n\
|
||||||
|
2. **第 1 次成功即收手**:`render=true` 第 1 次成功拿到 markdown → **立即用已有数据整理输出**,不要重复 render 同 URL 去「补充」更多内容(已拿即用)。\n\
|
||||||
|
3. **同 URL 不重复 render=true**:同一 URL 的 render 结果(成功或失败)已知,后续不再对它重复发 render=true(缓存/历史即用);需要新内容请换 URL 或换方案。\n\
|
||||||
|
\n\
|
||||||
### JS 渲染文档与 obscura 安装引导\n\
|
### JS 渲染文档与 obscura 安装引导\n\
|
||||||
`fetch_url` 默认走静态抓取(不跑 JS)。遇到 SPA / 反爬 / JS 渲染的文档,用户(或你)可传 `render=true`。当 obscura(JS 渲染后端,github.com/h4ckf0r0day/obscura)**未安装**时,结果会静默回退静态,返回的 JSON 带 `render_mode: \"static_fallback\"` 和一个指向安装页的 `hint` 字段。请**重点看 `hint` 字段**(而非只看 `render_mode`)——它就是安装信号:\n\
|
`fetch_url` 默认走静态抓取(不跑 JS)。遇到 SPA / 反爬 / JS 渲染的文档,用户(或你)可传 `render=true`。当 obscura(JS 渲染后端,github.com/h4ckf0r0day/obscura)**未安装**时,结果会静默回退静态,返回的 JSON 带 `render_mode: \"static_fallback\"` 和一个指向安装页的 `hint` 字段。请**重点看 `hint` 字段**(而非只看 `render_mode`)——它就是安装信号:\n\
|
||||||
1. **察觉**:若 `fetch_url` 结果带 `hint`(或 `render_mode` 为 `static_fallback`),说明 obscura 缺失,页面可能没渲染完整。\n\
|
1. **察觉**:若 `fetch_url` 结果带 `hint`(或 `render_mode` 为 `static_fallback`),说明 obscura 缺失,页面可能没渲染完整。\n\
|
||||||
@@ -176,6 +226,27 @@ fn doc_exploration_strategy_section(lang: &str) -> &'static str {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// 查 DevFlow 自身配置引导段(中/英):教 AI 查 provider/model/agent 设置时用 get_app_config
|
||||||
|
/// 工具,不要 run_command 执行 PowerShell 内联 node/python 脚本查 db。
|
||||||
|
///
|
||||||
|
/// 治症状:实测 AI 想看「当前 provider/model/agent 配置」时,因没原生查配置工具,只能
|
||||||
|
/// run_command 执行 PowerShell 内联 node 脚本查 db,命令行引号三重嵌套(PowerShell 单引号
|
||||||
|
/// 包 node -e 内含 JS 模板字符串/双引号/db 路径)必失败,复盘实证反复踩坑。get_app_config
|
||||||
|
/// 工具一调即得(只读 + api_key 脱敏),根治绕行。
|
||||||
|
///
|
||||||
|
/// 与 doc_exploration_strategy_section 同款「机制治症状」风格:正向指令(用 X)+ 禁令
|
||||||
|
/// (不要 Y)+ 原因(引号嵌套易失败),而非空泛说教。
|
||||||
|
fn app_config_query_guidance_section(lang: &str) -> &'static str {
|
||||||
|
match lang {
|
||||||
|
"en" => "\n\
|
||||||
|
## Querying DevFlow's Own Configuration\n\
|
||||||
|
When you need to inspect DevFlow's own current configuration (which AI provider/model is active, agent iteration/retry limits, concurrency, approval timeout, whether the API key is set), use the `get_app_config` tool — it returns the live config as JSON in one call (read-only, api_key masked). Do **NOT** use `run_command` to run an inline PowerShell node/python script against the database: triple-nested quotes (PowerShell single-quote wrapping node `-e` containing JS template strings / double quotes / db paths) consistently fail. `get_app_config` is the correct path; `run_command` for config inspection is a known failure mode.\n",
|
||||||
|
_ => "\n\
|
||||||
|
## 查询 DevFlow 自身配置\n\
|
||||||
|
需要查看 DevFlow 自身当前配置(当前用哪个 AI provider/model、agent 迭代/重试上限、并发数、审批超时、api_key 是否配置)时,用 `get_app_config` 工具——一次调用即返当前生效配置 JSON(只读,api_key 已脱敏)。**严禁**用 `run_command` 执行 PowerShell 内联 node/python 脚本查数据库:命令行引号三重嵌套(PowerShell 单引号包 node `-e` 内含 JS 模板字符串/双引号/db 路径)必失败。`get_app_config` 是查配置的正解;`run_command` 查配置是已知的反复失败模式。\n",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// 构建系统提示词(环境信息 + 固定前缀 + 当前项目/任务**全局清单**)
|
/// 构建系统提示词(环境信息 + 固定前缀 + 当前项目/任务**全局清单**)
|
||||||
///
|
///
|
||||||
/// 本函数注入"全貌"清单:最近 20 项目 + 20 任务的 name/status/description(无 path),
|
/// 本函数注入"全貌"清单:最近 20 项目 + 20 任务的 name/status/description(无 path),
|
||||||
@@ -217,6 +288,8 @@ pub(crate) async fn build_system_prompt_with_excluded(
|
|||||||
prompt.push_str(prefix);
|
prompt.push_str(prefix);
|
||||||
// 文档探索策略段(URL→fetch_url 嗅探→识别→提取→验证→应用,治盲目 http_request 瞎试)
|
// 文档探索策略段(URL→fetch_url 嗅探→识别→提取→验证→应用,治盲目 http_request 瞎试)
|
||||||
prompt.push_str(doc_exploration_strategy_section(lang));
|
prompt.push_str(doc_exploration_strategy_section(lang));
|
||||||
|
// 查 DevFlow 自身配置引导(治 AI 查配置绕 run_command PowerShell 内联脚本引号嵌套失败)
|
||||||
|
prompt.push_str(app_config_query_guidance_section(lang));
|
||||||
|
|
||||||
// 附加当前数据上下文
|
// 附加当前数据上下文
|
||||||
if let Ok(projects) = state.projects.list_active().await {
|
if let Ok(projects) = state.projects.list_active().await {
|
||||||
@@ -426,6 +499,21 @@ mod tests {
|
|||||||
assert!(en.contains("Verify"));
|
assert!(en.contains("Verify"));
|
||||||
assert!(en.contains("Apply"));
|
assert!(en.contains("Apply"));
|
||||||
|
|
||||||
|
// 工具职责区分子段(中/英)——图片/二进制走 download_file 非 fetch_url(治会话 01f05167 卡死)
|
||||||
|
assert!(zh.contains("先选对 URL 工具"));
|
||||||
|
assert!(zh.contains("download_file"));
|
||||||
|
assert!(zh.contains("仅 HTML 文档"));
|
||||||
|
assert!(zh.contains("下载任意文件"));
|
||||||
|
assert!(zh.contains("图片/压缩包/二进制文件 URL"));
|
||||||
|
assert!(zh.contains("立即改用 `download_file`"));
|
||||||
|
|
||||||
|
assert!(en.contains("Pick the right URL tool first"));
|
||||||
|
assert!(en.contains("download_file"));
|
||||||
|
assert!(en.contains("HTML docs only"));
|
||||||
|
assert!(en.contains("download any file"));
|
||||||
|
assert!(en.contains("Image / archive / binary file URL"));
|
||||||
|
assert!(en.contains("switch to `download_file` immediately"));
|
||||||
|
|
||||||
// obscura 安装引导子段(中/英)——看 hint 字段自主提示 + 帮装 + 重试
|
// obscura 安装引导子段(中/英)——看 hint 字段自主提示 + 帮装 + 重试
|
||||||
// 核心:hint 字段是安装信号(非只看 render_mode),同意即用 run_command 装,装完重试 render=true。
|
// 核心:hint 字段是安装信号(非只看 render_mode),同意即用 run_command 装,装完重试 render=true。
|
||||||
assert!(zh.contains("obscura"));
|
assert!(zh.contains("obscura"));
|
||||||
@@ -445,6 +533,38 @@ mod tests {
|
|||||||
assert!(en.contains("cargo install obscura"));
|
assert!(en.contains("cargo install obscura"));
|
||||||
assert!(en.contains("github.com/h4ckf0r0day/obscura"));
|
assert!(en.contains("github.com/h4ckf0r0day/obscura"));
|
||||||
assert!(en.contains("render=true"));
|
assert!(en.contains("render=true"));
|
||||||
|
|
||||||
|
// render=true 失败重试铁律(中/英)——失败 2 次换方案 + 成功即收手 + 不重复 render
|
||||||
|
assert!(zh.contains("render=true 失败重试铁律"));
|
||||||
|
assert!(zh.contains("失败 2 次必换方案"));
|
||||||
|
assert!(zh.contains("第 1 次成功即收手"));
|
||||||
|
assert!(zh.contains("同 URL 不重复 render=true"));
|
||||||
|
assert!(zh.contains("html=0"));
|
||||||
|
assert!(zh.contains("obscura_failed"));
|
||||||
|
|
||||||
|
assert!(en.contains("render=true failure-retry rule"));
|
||||||
|
assert!(en.contains("Switch after 2 failures"));
|
||||||
|
assert!(en.contains("Stop after the first success"));
|
||||||
|
assert!(en.contains("Never re-render the same URL"));
|
||||||
|
assert!(en.contains("html=0"));
|
||||||
|
assert!(en.contains("obscura_failed"));
|
||||||
|
|
||||||
|
// 精确提取链接子段(中/英)——治 AI 凭印象臆造 URL(猜 #hash/推测路由)
|
||||||
|
// 核心:从返回内容提取真实链接原样 fetch,无据不臆造,有据才发请求。
|
||||||
|
assert!(zh.contains("精确提取链接,严禁臆造 URL"));
|
||||||
|
assert!(zh.contains("从返回内容提取真实链接"));
|
||||||
|
assert!(zh.contains("原样 fetch 提取到的 URL"));
|
||||||
|
assert!(zh.contains("没有明确链接 → 不盲试"));
|
||||||
|
assert!(zh.contains("API 端点同理"));
|
||||||
|
assert!(zh.contains("有据可查才发请求,无据绝不臆造 URL"));
|
||||||
|
|
||||||
|
assert!(en.contains("Extract real links"));
|
||||||
|
assert!(en.contains("NEVER fabricate URLs"));
|
||||||
|
assert!(en.contains("Pull real links out of the response"));
|
||||||
|
assert!(en.contains("Fetch extracted URLs verbatim"));
|
||||||
|
assert!(en.contains("No explicit link"));
|
||||||
|
assert!(en.contains("API endpoints are the same"));
|
||||||
|
assert!(en.contains("never fabricate a URL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@@ -481,6 +601,24 @@ mod tests {
|
|||||||
assert!(en.contains("breaks the context"));
|
assert!(en.contains("breaks the context"));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 查 DevFlow 自身配置引导段(中/英)存在且含关键引导
|
||||||
|
#[test]
|
||||||
|
fn app_config_query_guidance_section_present_zh_en() {
|
||||||
|
let zh = app_config_query_guidance_section("zh-CN");
|
||||||
|
assert!(zh.contains("查询 DevFlow 自身配置"));
|
||||||
|
assert!(zh.contains("get_app_config"));
|
||||||
|
assert!(zh.contains("run_command"));
|
||||||
|
assert!(zh.contains("引号三重嵌套"));
|
||||||
|
assert!(zh.contains("严禁"));
|
||||||
|
|
||||||
|
let en = app_config_query_guidance_section("en");
|
||||||
|
assert!(en.contains("Querying DevFlow's Own Configuration"));
|
||||||
|
assert!(en.contains("get_app_config"));
|
||||||
|
assert!(en.contains("run_command"));
|
||||||
|
assert!(en.contains("triple-nested quotes"));
|
||||||
|
assert!(en.contains("Do **NOT**"));
|
||||||
|
}
|
||||||
|
|
||||||
// 项目/任务清单注明语(中/英)存在
|
// 项目/任务清单注明语(中/英)存在
|
||||||
#[test]
|
#[test]
|
||||||
fn listed_notes_present_zh_en() {
|
fn listed_notes_present_zh_en() {
|
||||||
|
|||||||
Reference in New Issue
Block a user