vv-agent 0.6.2

VectorVein agent runtime, SDK, CLI, tools, and workspace backends
Documentation
use serde_json::{json, Value};

const SEARCH_FILES_DESCRIPTION: &str = r#"Search workspace file contents with regex or literal text.

When to use:
- Find symbols, text, config keys, error strings, TODOs, or call sites before deciding which files to read or edit.
- Prefer this tool over ad-hoc shell grep for direct content search.
- Narrow broad searches with `path`, `glob`, or `type` so results stay useful and fast.

OUTPUT MODES:
- `files_with_matches` (default): show only matching file paths.
- `content`: show matching lines with optional context and line numbers.
- `count`: show per-file match counts.

FILTERS:
- `path` + `glob`: scope the search root and file pattern.
- A single file path searches that file directly, even if it is hidden or under an ignored root.
- `type`: language/file-type shortcut (py/js/ts/md/json/...).
- default matching uses smart-case: all-lowercase patterns search case-insensitively and patterns containing uppercase stay case-sensitive.
- `case_sensitive`: explicitly override smart-case behavior.
- `multiline`: let `.` match newlines and allow multi-line patterns.
- `literal`: search for exact text instead of regex.
- `include_hidden`: include hidden files/directories.
- `include_ignored`: include common dependency/cache roots at workspace root.
- `include_sensitive`: include paths that look like secrets or credentials. Default false.

CONTENT OPTIONS (only for `content` mode):
- `b`: lines before each match.
- `a`: lines after each match.
- `c`: lines before+after and overrides b/a.
- `n`: include line numbers.

LIMITING:
- `offset`: skip the first N result rows/entries.
- `head_limit`: return only first N output rows/entries. Default 250; 0 means unlimited subject to hard caps.

Returns:
- Matching content rows, file paths, or counts according to `output_mode`.
- Truncation metadata such as `content_truncated`, `structured_truncated`, `structured_item_limit`, and `structured_char_limit` when output is capped."#;

pub(in crate::tools::schemas) fn search_files_schema() -> Value {
    json!({
        "type": "function",
        "function": {
            "name": "search_files",
            "description": SEARCH_FILES_DESCRIPTION,
            "parameters": {
                "type": "object",
                "properties": {
                    "pattern": {"type": "string", "description": "Regex pattern to search for, or exact text when `literal=true`. Escape regex metacharacters when `literal=false` and searching for literal dots, brackets, or file extensions."},
                    "path": {"type": "string", "description": "Optional search root or single file path. Use workspace-relative path by default; absolute path is allowed when outside-workspace access is enabled. Default '.'. A single file path searches that file directly, even if it is hidden or under an ignored root."},
                    "glob": {"type": "string", "description": "Optional file glob filter such as `**/*.rs` or `docs/**/*.md`. Use it to narrow by filename, path segment, or extension before running broad regex searches. Default **/*."},
                    "include_hidden": {"type": "boolean", "description": "Whether hidden files and dotfiles are included. Default false; set true only when explicitly searching hidden project files such as .env.example, .github, or dot-directories."},
                    "include_ignored": {"type": "boolean", "description": "When searching workspace root, include files under common dependency/cache directories. Default false; set true only when explicitly inspecting generated, dependency, cache, or build-output paths."},
                    "include_sensitive": {"type": "boolean", "description": "Include files whose paths look like secrets, credentials, keys, tokens, or private config. Default false."},
                    "output_mode": {"type": "string", "enum": ["files_with_matches", "content", "count"], "description": "Search output mode. `files_with_matches` returns matching paths for a follow-up read/search, `content` returns matching lines for inspection, and `count` returns per-file match counts. Default is 'files_with_matches'."},
                    "literal": {"type": "boolean", "description": "Search for the exact pattern text instead of interpreting it as a regex. Default false."},
                    "b": {"type": "integer", "description": "Lines before each match. Only used in content mode. Use when each match needs leading context, such as a function signature, heading, import block, or preceding error line."},
                    "a": {"type": "integer", "description": "Lines after each match. Only used in content mode. Use when each match needs following context, such as a function body, config value, stack trace continuation, or adjacent TODO detail."},
                    "c": {"type": "integer", "description": "Context lines before and after each match. Overrides b/a. Use this instead of separate b/a values when symmetric context is enough to decide the next read or edit."},
                    "n": {"type": "boolean", "description": "Whether to include line numbers in content output. Default true."},
                    "type": {"type": "string", "description": "File type shortcut (e.g. py/js/ts/md/json). Unsupported or unknown shortcuts return a structured error listing supported values."},
                    "offset": {"type": "integer", "minimum": 0, "description": "Number of result rows or entries to skip before returning results. Default 0."},
                    "head_limit": {"type": "integer", "minimum": 0, "description": "Cap output to the first N rows or entries. Default 250. Use 0 for unlimited output subject to hard caps. Use this for broad searches, then run a narrower follow-up query if matches are truncated."},
                    "multiline": {"type": "boolean", "description": "Enable multiline regex mode. Use for patterns that intentionally span line breaks, such as adjacent JSON fields, multi-line imports, or repeated prompt blocks."},
                    "case_sensitive": {"type": "boolean", "description": "Explicitly override smart-case behavior. Set true when literal casing matters, false when you need forced case-insensitive matching."}
                },
                "required": ["pattern"]
            }
        }
    })
}