diff --git a/AGENTS.md b/AGENTS.md index aab152d..db0b2b0 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -37,11 +37,12 @@ ## 工具使用规则 - `Read`:用于读取文件内容。 -- `Glob`:用于按模式查找文件。 +- 需要按文件名或路径模式查找时,优先使用 `Glob`。 +- 需要搜索文件内容时,优先使用 `Grep`。 - 修改已有文件内容时,优先使用 `Edit` 工具。 - 创建新文件时,优先使用 `Write` 工具。 - `Bash`:用于执行必须通过 shell 完成的最小命令。 -- 只有在确实需要 shell 特性时才使用 Bash。 +- 只有在确实需要复杂 shell 特性时才使用 Bash。 - 不要用 Bash 拼接文件内容。 - Windows 环境下优先使用兼容写法,不默认使用 `cat < list[Tool]: }, execute=lambda data: write_tool(workspace, data), ), + Tool( + name="Grep", + description="在文件或目录中搜索普通文本内容。", + input_schema={ + "type": "object", + "properties": { + "pattern": {"type": "string", "description": "要搜索的普通文本字符串"}, + "path": {"type": "string", "description": "可选,仅支持文件路径或目录路径,默认当前工作区"}, + }, + "required": ["pattern"], + "additionalProperties": False, + }, + execute=lambda data: grep_tool(workspace, data), + ), Tool( name="Bash", description="在工作区中执行一条 shell 命令。", @@ -138,6 +152,34 @@ def write_tool(workspace: Path, data: dict[str, Any]) -> str: return f"{action}文件: {path.relative_to(workspace)}" +def grep_tool(workspace: Path, data: dict[str, Any]) -> str: + pattern = str(data["pattern"]) + target = _safe_path(workspace, str(data.get("path") or ".")) + if not target.exists(): + return f"文件不存在: {target.relative_to(workspace)}" + + results: list[str] = [] + files = [target] if target.is_file() else [path for path in target.rglob("*") if path.is_file()] + if target.is_dir() and not files: + return f"目录为空: {target.relative_to(workspace)}" + + for file_path in files: + try: + text = file_path.read_text(encoding="utf-8", errors="replace") + except OSError: + continue + + for line_no, line in enumerate(text.splitlines(), start=1): + if pattern in line: + results.append(f"{file_path.relative_to(workspace)}:{line_no}: {line}") + if len(results) >= 20: + return "\n".join(results) + + if not results: + return "未找到匹配内容" + return "\n".join(results) + + def bash_tool(workspace: Path, data: dict[str, Any]) -> str: command = str(data["command"]) proc = subprocess.run(