agents-tools 0.1.0

Shared Rust implementations of agent tools
Documentation
//! Shared, reusable implementations of agent editing tools.
//!
//! The crate exposes two layers:
//!
//! - [`apply_diff_to_text`] applies a complete update body to an in-memory
//!   string. It supports multiple anchored sections and is always available.
//! - `apply_diff` parses a complete multi-file patch and applies it beneath a
//!   filesystem root. It is available with the default `filesystem` feature.
//!
//! # Patch format
//!
//! Filesystem patches use a single envelope containing one or more file
//! operations:
//!
//! ```text
//! *** Begin Patch
//! *** Add File: src/new.rs
//! +pub fn new() {}
//! *** Update File: src/lib.rs
//! @@ pub fn old() {
//! -    before();
//! +    after();
//! *** Update File: src/name.rs
//! *** Move to: src/renamed.rs
//! *** Delete File: src/unused.rs
//! *** End Patch
//! ```
//!
//! Update bodies may contain multiple `@@` sections. Lines beginning with a
//! space are context, `-` removes a line, and `+` inserts a line. Add blocks
//! require every content line to begin with `+`.
//!
//! # Failure and concurrency model
//!
//! Patch syntax and unsafe paths are validated before filesystem work begins.
//! Each connected logical file is then planned fully in memory and committed
//! independently. A failed file remains unchanged while unrelated files in the
//! same patch can still succeed; inspect `ApplyDiffReport::failed` for those
//! failures.
//!
//! File replacements are written completely, synchronized, and atomically
//! installed, so readers do not observe partially written contents. Overlapping
//! paths are serialized within the process, and the on-disk snapshot is checked
//! again immediately before each commit to detect observed external changes.
//!
//! # Feature flags
//!
//! The `filesystem` feature is enabled by default and provides the filesystem
//! API and serializable reports. Text-only users can disable default features:
//!
//! ```toml
//! agents-tools = { version = "0.1", default-features = false }
//! ```
//!
//! # In-memory example
//!
//! ```
//! use agents_tools::apply_diff_to_text;
//!
//! let updated = apply_diff_to_text(
//!     "fn run() {\n    before();\n}\n",
//!     "@@ fn run() {\n-    before();\n+    after();",
//! )?;
//!
//! assert_eq!(updated, "fn run() {\n    after();\n}\n");
//! # Ok::<(), agents_tools::ApplyDiffError>(())
//! ```

#![forbid(unsafe_code)]

mod apply_diff;
#[cfg(feature = "filesystem")]
mod filesystem;

pub use apply_diff::{
    ApplyDiffError, ApplyDiffMode, apply_diff_to_text, apply_diff_to_text_with_mode,
};
#[cfg(feature = "filesystem")]
pub use filesystem::{AppliedFile, ApplyDiffReport, FailedFile, FileChangeKind, apply_diff};