Files
hive/scripts/hermes_search_files.md
T
2026-04-30 15:43:15 -07:00

2.8 KiB

def search_tool(pattern: str, target: str = "content", path: str = ".", file_glob: str = None, limit: int = 50, offset: int = 0, output_mode: str = "content", context: int = 0, task_id: str = "default") -> str: """Search for content or files.""" try: # Track searches to detect consecutive repeated search loops. # Include pagination args so users can page through truncated # results without tripping the repeated-search guard. search_key = ( "search", pattern, target, str(path), file_glob or "", limit, offset, ) with _read_tracker_lock: task_data = _read_tracker.setdefault(task_id, { "last_key": None, "consecutive": 0, "read_history": set(), }) if task_data["last_key"] == search_key: task_data["consecutive"] += 1 else: task_data["last_key"] = search_key task_data["consecutive"] = 1 count = task_data["consecutive"]

    if count >= 4:
        return json.dumps({
            "error": (
                f"BLOCKED: You have run this exact search {count} times in a row. "
                "The results have NOT changed. You already have this information. "
                "STOP re-searching and proceed with your task."
            ),
            "pattern": pattern,
            "already_searched": count,
        }, ensure_ascii=False)

    file_ops = _get_file_ops(task_id)
    result = file_ops.search(
        pattern=pattern, path=path, target=target, file_glob=file_glob,
        limit=limit, offset=offset, output_mode=output_mode, context=context
    )
    if hasattr(result, 'matches'):
        for m in result.matches:
            if hasattr(m, 'content') and m.content:
                m.content = redact_sensitive_text(m.content)
    result_dict = result.to_dict()

    if count >= 3:
        result_dict["_warning"] = (
            f"You have run this exact search {count} times consecutively. "
            "The results have not changed. Use the information you already have."
        )

    result_json = json.dumps(result_dict, ensure_ascii=False)
    # Hint when results were truncated — explicit next offset is clearer
    # than relying on the model to infer it from total_count vs match count.
    if result_dict.get("truncated"):
        next_offset = offset + limit
        result_json += f"\n\n[Hint: Results truncated. Use offset={next_offset} to see more, or narrow with a more specific pattern or file_glob.]"
    return result_json
except Exception as e:
    return tool_error(str(e))