输入:「帮我找出请求超时配置在哪里,只看 TypeScript」
用户给出语义目标与文件类型约束,没有要求 Agent 猜目录或直接运行任意 shell。
用户的一句话被收束成可审计的参数,深入文件树;原始命中再经过解析、安全过滤与分页,回到 Agent 成为可行动的答复。
输入:「帮我找出请求超时配置在哪里,只看 TypeScript」
用户给出语义目标与文件类型约束,没有要求 Agent 猜目录或直接运行任意 shell。
Agent 将“请求超时配置”收束为代码标识符 REQUEST_TIMEOUT_MS,并选择 search_files 的内容搜索模式。*.ts 明确落实“只看 TypeScript”。
{
"pattern": "REQUEST_TIMEOUT_MS",
"target": "content",
"path": "/tmp/hermes-search-pipeline-demo",
"file_glob": "*.ts",
"limit": 10,
"offset": 0,
"output_mode": "content",
"context": 1
}tools/file_tools.py:2550–2615
先规范化 offset/limit;连续相同搜索第 3 次提示、第 4 次阻断;解析任务路径并检查受保护路径;命中“不存在路径”缓存时避免重复 shell;随后调用 file_ops.search(...)。
tools/file_operations.py:3231–3278
set -o pipefail; rg --line-number --no-heading --with-filename -C 1 --glob '*.ts' 'REQUEST_TIMEOUT_MS' '/tmp/hermes-search-pipeline-demo' | head -n 210
210 = limit 10 + offset 0 + context 模式额外 200。参数经 shell 转义;Windows 原生路径另行处理;含正则换行时自动启用 multiline。
在已 git init 的演示仓库中,rg --files 实测仅枚举:
src/client.ts src/secrets.ts README.md
node_modules/fake-sdk/index.ts、ignored.log、.env 与 .git 未进入枚举。边界:ignore 行为依赖实际仓库与层级语境;仅放置孤立 .gitignore、尚未初始化 Git 时,本演示里的 node_modules 与 ignored.log 并未被排除。
/tmp/hermes-search-pipeline-demo/src/client.ts:1:export const REQUEST_TIMEOUT_MS = 8000;
/tmp/hermes-search-pipeline-demo/src/client.ts-2-
--
/tmp/hermes-search-pipeline-demo/src/client.ts-4- return fetch(`/api/users/${userId}`, {
/tmp/hermes-search-pipeline-demo/src/client.ts:5: signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),
/tmp/hermes-search-pipeline-demo/src/client.ts-6- });-- 是上下文组分隔符,不是搜索命中。
file_operations.py:3282–3373 先分离 rg diagnostics;兼容 Unix/Windows 路径;跳过 --;区分命中行与上下文行;每条 content 最多 500 字符;计算 total 后再按 offset/limit 切页。
file_tools.py:2616–2648 再过滤 credential/token/cache/secret-bearing env 文件,对每条内容调用 redact_sensitive_text(file_read=True),执行 to_dict(densify=True),并追加 omitted 与截断提示。
export const DEMO_API_KEY = "«redacted:sk-…»";实测 total_count=5,matches_format="path-grouped"。上下文行也作为记录进入结果,因此是行 1、2、4、5、6,而不是“2 个关键字命中”。
{
"total_count": 5,
"matches_format": "path-grouped",
"matches_text": "/tmp/hermes-search-pipeline-demo/src/client.ts:\n 1: export const REQUEST_TIMEOUT_MS = 8000;\n 2: \n 4: return fetch(`/api/users/${userId}`, {\n 5: signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS),\n 6: });"
}Agent 读取路径、行号与上下文:第 1 行是配置定义,值为 8000ms;第 5 行将它传给 AbortSignal.timeout。这一步把“搜索记录”提升为“可回答的定位结论”。
答复示例:请求超时配置位于 src/client.ts:1:REQUEST_TIMEOUT_MS = 8000(8 秒);它在 src/client.ts:5 传给 AbortSignal.timeout(...)。
切换观察 rg 的行协议如何变成 Hermes 的密集结构。
/tmp/hermes-search-pipeline-demo/src/client.ts:1:export const REQUEST_TIMEOUT_MS = 8000; /tmp/hermes-search-pipeline-demo/src/client.ts-2- /tmp/hermes-search-pipeline-demo/src/client.ts-4- return fetch(`/api/users/${userId}`, { /tmp/hermes-search-pipeline-demo/src/client.ts:5: signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), /tmp/hermes-search-pipeline-demo/src/client.ts-6- });
/tmp/hermes-search-pipeline-demo/src/client.ts: 1: export const REQUEST_TIMEOUT_MS = 8000; 2: 4: return fetch(`/api/users/${userId}`, { 5: signal: AbortSignal.timeout(REQUEST_TIMEOUT_MS), 6: });
rg 遍历候选文件、执行正则并吐出带路径/行号/上下文的文本。它负责快。
search_files 约束参数与路径,处理诊断、解析、敏感内容、分页和结果形态。它负责可控。
total_count=5 是解析后的 5 条记录,包含 3 条上下文;关键字实际出现在第 1、5 行。