pub mod client;
mod convert;
mod dns;
mod error;
pub mod fetchers;
pub mod file_saver;
mod tool;
mod types;
pub use client::{fetch, fetch_with_options, FetchOptions};
pub use convert::{html_to_markdown, html_to_text};
pub use dns::DnsPolicy;
pub use error::FetchError;
pub use fetchers::{DefaultFetcher, Fetcher, FetcherRegistry, GitHubRepoFetcher};
pub use file_saver::{FileSaveError, FileSaver, LocalFileSaver, SaveResult};
pub use tool::{Tool, ToolBuilder, ToolStatus};
pub use types::{FetchRequest, FetchResponse, HttpMethod};
pub const DEFAULT_USER_AGENT: &str = "Everruns FetchKit/1.0";
pub(crate) const TOOL_DESCRIPTION_BASE: &str = "\
Fetches content from a URL and optionally converts HTML to markdown or text.
- Supports GET and HEAD methods
- Converts HTML to markdown or plain text
- Returns metadata for binary content
- Strict timeouts for reliability";
pub(crate) const TOOL_DESCRIPTION_SAVE: &str = "\n- File download (save_to_file)";
pub(crate) const TOOL_LLMTXT_HEADER: &str = "\
# FetchKit Tool
Fetches content from a URL and optionally converts HTML to markdown or text.
## Capabilities
- HTTP GET and HEAD requests
- HTML to Markdown conversion
- HTML to plain text conversion
- Binary content detection (returns metadata only)
- Automatic timeout handling
## Input Parameters
- `url` (required): The URL to fetch (must be http:// or https://)
- `method` (optional): GET or HEAD (default: GET)
- `as_markdown` (optional): Convert HTML to markdown
- `as_text` (optional): Convert HTML to plain text";
pub(crate) const TOOL_LLMTXT_SAVE_INPUT: &str = "\
\n- `save_to_file` (optional): Save response body to this path instead of returning inline content. \
Accepts binary content (images, PDFs, archives). Requires file saving to be enabled.";
pub(crate) const TOOL_LLMTXT_OUTPUT_BASE: &str = "
## Output Fields
- `url`: The fetched URL
- `status_code`: HTTP status code
- `content_type`: Content-Type header value
- `size`: Content size in bytes
- `last_modified`: Last-Modified header value
- `filename`: Extracted filename
- `format`: \"markdown\", \"text\", or \"raw\"
- `content`: The fetched/converted content
- `truncated`: True if content was truncated due to timeout
- `method`: \"HEAD\" for HEAD requests
- `error`: Error message for binary content";
pub(crate) const TOOL_LLMTXT_SAVE_OUTPUT: &str = "\
\n- `saved_path`: Path where file was saved (when save_to_file was used)
- `bytes_written`: Bytes written to file (when save_to_file was used)";
pub(crate) const TOOL_LLMTXT_EXAMPLES_BASE: &str = "
## Examples
### Fetch a webpage as markdown
```json
{\"url\": \"https://example.com\", \"as_markdown\": true}
```
### Check if a URL exists (HEAD request)
```json
{\"url\": \"https://example.com/file.pdf\", \"method\": \"HEAD\"}
```
### Fetch raw content
```json
{\"url\": \"https://api.example.com/data.json\"}
```";
pub(crate) const TOOL_LLMTXT_SAVE_EXAMPLE: &str = "
### Download a file
```json
{\"url\": \"https://example.com/image.png\", \"save_to_file\": \"image.png\"}
```";
pub(crate) const TOOL_LLMTXT_ERRORS_BASE: &str = "
## Error Handling
- Invalid URLs return an error
- Binary content returns metadata with error message
- Timeouts return partial content with truncated flag";
pub(crate) const TOOL_LLMTXT_SAVE_ERRORS: &str = "\
\n- Binary content is accepted when using save_to_file\n\
- File saving errors include path validation and IO failures";
pub const TOOL_DESCRIPTION: &str = "\
Fetches content from a URL and optionally converts HTML to markdown or text.\n\
\n\
- Supports GET and HEAD methods\n\
- Converts HTML to markdown or plain text\n\
- Returns metadata for binary content\n\
- Strict timeouts for reliability\n\
- File download (save_to_file)";
pub static TOOL_LLMTXT: std::sync::LazyLock<String> =
std::sync::LazyLock::new(|| build_llmtxt(true));
pub(crate) fn build_llmtxt(include_save: bool) -> String {
let mut s = String::with_capacity(2048);
s.push_str(TOOL_LLMTXT_HEADER);
if include_save {
s.push_str(TOOL_LLMTXT_SAVE_INPUT);
}
s.push_str(TOOL_LLMTXT_OUTPUT_BASE);
if include_save {
s.push_str(TOOL_LLMTXT_SAVE_OUTPUT);
}
s.push_str(TOOL_LLMTXT_EXAMPLES_BASE);
if include_save {
s.push_str(TOOL_LLMTXT_SAVE_EXAMPLE);
}
s.push_str(TOOL_LLMTXT_ERRORS_BASE);
if include_save {
s.push_str(TOOL_LLMTXT_SAVE_ERRORS);
}
s.push('\n');
s
}