Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions src/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,85 @@ members = [
"llm-coding-tools-bubblewrap",
]

[workspace.dependencies]
# Serialization
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde_yaml = "0.9"
bitcode = "0.6.9"
bitflags = "2.11.0"

# Error handling
thiserror = "2.0"

# Async/Runtime
tokio = { version = "1.51", features = ["fs", "io-util", "process", "time"] }
maybe-async = "0.2"
async-trait = "0.1"
futures = "0.3"

# HTTP/Network
reqwest = { version = "0.13", default-features = false, features = ["rustls", "rustls-native-certs"] }
html-to-markdown-rs = "3.1"

# Filesystem/Path
shellexpand = "3.1.2"
soft-canonicalize = "0.5.5"
dirs = "6"
tempfile = "3.27"
ignore = "0.4.25"

# Data structures
hashbrown = "0.17"
indexmap = { version = "2", features = ["serde"] }
tinyvec = { version = "1.11", features = ["alloc"] }
lite-strtab = "0.2"
ahash = { version = "0.8", features = ["serde"] }
parking_lot = "0.12"

# Bit operations
bitfields = "1.0.3"

# Grep/Glob tools
globset = "0.4.18"
grep-regex = "0.1.14"
grep-searcher = "0.1.16"
memchr = "2.8.0"

# Process management
process-wrap = { version = "9.1", default-features = false }

# String formatting
const_format = "0.2.35"
crlf-to-lf-inplace = "0.2"

# Schema/Validation
schemars = "1.2"

# Compression/Encoding
zstd = "0.13.3"
endian-writer = "2.2.0"
endian-writer-derive = "0.1.0"

# serdes-ai ecosystem
serdes-ai = { version = "0.2.6", default-features = false }
serdes-ai-models = { version = "0.2.6", default-features = false }
serdes-ai-streaming = "0.2"

# Internal crates
llm-coding-tools-core = { version = "0.2.0", path = "llm-coding-tools-core", default-features = false }
llm-coding-tools-bubblewrap = { version = "0.1.0", path = "llm-coding-tools-bubblewrap" }
llm-coding-tools-agents = { version = "0.1.0", path = "llm-coding-tools-agents" }
llm-coding-tools-models-dev = { version = "0.1.0", path = "llm-coding-tools-models-dev" }

# Dev dependencies
criterion = "0.8"
rstest = "0.26"
serial_test = "3"
wiremock = "0.6"
indoc = "2"
temp-env = "0.3.6"

# Profile Build
[profile.profile]
inherits = "release"
Expand Down
29 changes: 14 additions & 15 deletions src/llm-coding-tools-agents/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -10,37 +10,36 @@ readme = "README.md"

[dependencies]
# YAML parsing for frontmatter
serde = { version = "1.0", features = ["derive"] }
serde_yaml = "0.9"
serde_json = "1.0"
serde = { workspace = true }
serde_yaml = { workspace = true }
serde_json = { workspace = true }

# Preserve insertion order for permission maps
indexmap = { version = "2", features = ["serde"] }
indexmap = { workspace = true }

# Error handling
thiserror = "2.0"
thiserror = { workspace = true }

# Fast CRLF to LF conversion
crlf-to-lf-inplace = "0.2"

crlf-to-lf-inplace = { workspace = true }

# Directory scanning with gitignore support
ignore = "0.4.25"
ignore = { workspace = true }

# High-performance hashing (sync version with core crate)
ahash = { version = "0.8", features = ["serde"] }
ahash = { workspace = true }

# Core library for permissions and tool types
llm-coding-tools-core = { path = "../llm-coding-tools-core", version = "0.2.0" }
llm-coding-tools-core = { workspace = true, features = ["tokio"] }

# Canonicalizes paths, resolving symlinks without requiring the full path to exist
soft-canonicalize = "0.5"
soft-canonicalize = { workspace = true }

[dev-dependencies]
tempfile = "3.27"
criterion = "0.8"
indoc = "2"
rstest = "0.26"
tempfile = { workspace = true }
criterion = { workspace = true }
indoc = { workspace = true }
rstest = { workspace = true }

[[bench]]
name = "parser"
Expand Down
4 changes: 2 additions & 2 deletions src/llm-coding-tools-agents/src/loader.rs
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ impl AgentLoader {
///
/// # Errors
/// - Returns [`AgentLoadError::Io`] when the path exists but is not a directory.
/// Walk errors (permissions, etc.) may be silently skipped by [`load_directory_with`]
/// Walk errors (permissions, etc.) may be silently skipped by `load_directory_with`
/// and are not guaranteed to surface as [`AgentLoadError::Io`].
pub fn add_directory(
&self,
Expand All @@ -105,7 +105,7 @@ impl AgentLoader {
///
/// # Errors
/// - Returns [`AgentLoadError::Io`] when the path exists but is not a directory.
/// Walk errors (permissions, etc.) may be silently skipped by [`load_directory_with`]
/// Walk errors (permissions, etc.) may be silently skipped by `load_directory_with`
/// and are not guaranteed to surface as [`AgentLoadError::Io`].
/// - Individual file parse/validation failures are reported via `on_error` and do not fail the operation.
pub fn add_directory_with_errors(
Expand Down
15 changes: 7 additions & 8 deletions src/llm-coding-tools-bubblewrap/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,12 @@ default = ["tokio"]
tokio = ["dep:process-wrap", "process-wrap/tokio1", "process-wrap/process-group"]
blocking = ["dep:process-wrap", "process-wrap/std", "process-wrap/process-group"]
[dependencies]
parking_lot = "0.12"
thiserror = "2.0"
process-wrap = { version = "9", default-features = false, optional = true }
tempfile = "3.27"
parking_lot = { workspace = true }
thiserror = { workspace = true }
process-wrap = { workspace = true, optional = true }
tempfile = { workspace = true }

[dev-dependencies]
rstest = "0.26"
serial_test = "3"
tempfile = "3.27"
tokio = { version = "1.51", features = ["rt", "macros"] }
rstest = { workspace = true }
serial_test = { workspace = true }
tokio = { workspace = true, features = ["rt", "macros"] }
73 changes: 35 additions & 38 deletions src/llm-coding-tools-core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -38,84 +38,81 @@ linux-bubblewrap = ["dep:llm-coding-tools-bubblewrap"]

[dependencies]
# Tool outputs (BashOutput, GrepOutput, etc.) serialize to JSON for LLM consumption
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
serde = { workspace = true }
serde_json = { workspace = true }

# Zero overhead compile time bitflag generation
bitflags = "2.11.0"
bitflags = { workspace = true }

# Shell-like expansion for home directory paths (~/ and $HOME/)
shellexpand = "3.1.2"
shellexpand = { workspace = true }

# Cross-platform canonicalization for non-existent paths
soft-canonicalize = "0.5.5"
soft-canonicalize = { workspace = true }

# Fast binary serialization for catalog cache types
bitcode = "0.6.9"
bitcode = { workspace = true }

# Compile-time generated packed bitfield structs for model metadata
bitfields = "1.0.3"
bitfields = { workspace = true }

# High-performance hashing for permission keys
ahash = "0.8"
ahash = { workspace = true }

# Explicit low-level hash table for model catalog lookup
hashbrown = "0.17"
hashbrown = { workspace = true }

# Inline vector storage for ProviderEnvVars
tinyvec = { version = "1.11", features = ["alloc"] }
tinyvec = { workspace = true }

# Efficient immutable string table for provider URLs and env vars
lite-strtab = "0.2"
lite-strtab = { workspace = true }

# ToolError type uses thiserror for ergonomic error definitions
thiserror = "2.0"
thiserror = { workspace = true }

# Todo types derive JsonSchema for LLM tool parameter validation
schemars = "1.2"
schemars = { workspace = true }

# Sync RwLock for TodoState (no tokio dependency)
parking_lot = "0.12"
parking_lot = { workspace = true }

# Glob and grep tool implementations (aligned with ripgrep)
globset = "0.4.18" # Glob matching with ripgrep-optimized engine
grep-regex = "0.1.14" # Regex matcher for grep_search
grep-searcher = "0.1.16" # File content searching for grep_search
ignore = "0.4.25" # Respects .gitignore when walking directories
memchr = "2.8.0" # Fast newline detection in read_file
globset = { workspace = true } # Glob matching with ripgrep-optimized engine
grep-regex = { workspace = true } # Regex matcher for grep_search
grep-searcher = { workspace = true } # File content searching for grep_search
ignore = { workspace = true } # Respects .gitignore when walking directories
memchr = { workspace = true } # Fast newline detection in read_file

# Webfetch tool converts HTML to markdown for LLM-friendly output
html-to-markdown-rs = "3.1"
reqwest = { version = "0.13", default-features = false, features = [
"rustls",
"rustls-native-certs",
], optional = true }
html-to-markdown-rs = { workspace = true }
reqwest = { workspace = true, optional = true }

# Unifies async/sync code via procedural macros
maybe-async = "0.2"
maybe-async = { workspace = true }

# Async file I/O, process execution, and timeouts
tokio = { version = "1.51", features = ["fs", "io-util", "process", "time"], optional = true }
tokio = { workspace = true, optional = true }

# Cross-platform process tree management (Job Objects on Windows, process groups on Unix)
process-wrap = { version = "9.1", default-features = false }
process-wrap = { workspace = true }
# Compile-time string formatting for prompt text and parameter descriptions
const_format = "0.2.35"
const_format = { workspace = true }

# Linux sandbox types and runtime
llm-coding-tools-bubblewrap = { version = "0.1.0", path = "../llm-coding-tools-bubblewrap", optional = true }
llm-coding-tools-bubblewrap = { workspace = true, optional = true }

[dev-dependencies]
serial_test = "3"
tempfile = "3.27"
dirs = "6"
serial_test = { workspace = true }
tempfile = { workspace = true }
dirs = { workspace = true }
# For tests (async and blocking with wiremock)
tokio = { version = "1.51", features = ["rt-multi-thread", "macros"] }
wiremock = "0.6"
indoc = "2"
criterion = "0.8"
temp-env = "0.3.6"
rstest = "0.26"
tokio = { workspace = true, features = ["rt-multi-thread", "macros"] }
wiremock = { workspace = true }
indoc = { workspace = true }
criterion = { workspace = true }
temp-env = { workspace = true }
rstest = { workspace = true }

[[bench]]
name = "model_catalog_builder"
Expand Down
8 changes: 8 additions & 0 deletions src/llm-coding-tools-core/src/fs/blocking_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::path::Path;
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be read (e.g., file does not exist,
/// permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub fn read_to_string(path: impl AsRef<Path>) -> ToolResult<String> {
Ok(std::fs::read_to_string(path)?)
}
Expand All @@ -17,6 +19,8 @@ pub fn read_to_string(path: impl AsRef<Path>) -> ToolResult<String> {
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be written (e.g., parent directory
/// does not exist, permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> ToolResult<()> {
Ok(std::fs::write(path, contents)?)
}
Expand All @@ -26,6 +30,8 @@ pub fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> ToolResult<(
/// # Errors
/// - Returns [`ToolError::Io`] when the directory cannot be created (e.g., permission
/// denied or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub fn create_dir_all(path: impl AsRef<Path>) -> ToolResult<()> {
Ok(std::fs::create_dir_all(path)?)
}
Expand All @@ -35,6 +41,8 @@ pub fn create_dir_all(path: impl AsRef<Path>) -> ToolResult<()> {
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be opened (e.g., file does not exist,
/// permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub fn open_buffered(
path: impl AsRef<Path>,
capacity: usize,
Expand Down
8 changes: 8 additions & 0 deletions src/llm-coding-tools-core/src/fs/tokio_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ use std::path::Path;
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be read (e.g., file does not exist,
/// permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub async fn read_to_string(path: impl AsRef<Path>) -> ToolResult<String> {
Ok(tokio::fs::read_to_string(path).await?)
}
Expand All @@ -17,6 +19,8 @@ pub async fn read_to_string(path: impl AsRef<Path>) -> ToolResult<String> {
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be written (e.g., parent directory
/// does not exist, permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> ToolResult<()> {
Ok(tokio::fs::write(path, contents).await?)
}
Expand All @@ -26,6 +30,8 @@ pub async fn write(path: impl AsRef<Path>, contents: impl AsRef<[u8]>) -> ToolRe
/// # Errors
/// - Returns [`ToolError::Io`] when the directory cannot be created (e.g., permission
/// denied or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub async fn create_dir_all(path: impl AsRef<Path>) -> ToolResult<()> {
Ok(tokio::fs::create_dir_all(path).await?)
}
Expand All @@ -35,6 +41,8 @@ pub async fn create_dir_all(path: impl AsRef<Path>) -> ToolResult<()> {
/// # Errors
/// - Returns [`ToolError::Io`] when the file cannot be opened (e.g., file does not exist,
/// permission denied, or other I/O error).
///
/// [`ToolError::Io`]: crate::error::ToolError::Io
pub async fn open_buffered(
path: impl AsRef<Path>,
capacity: usize,
Expand Down
Loading