codetether_agent/tool/readonly.rs
1//! Read-only tool allowlist for parallel dispatch.
2//!
3//! When a provider emits multiple tool calls in a single assistant turn
4//! (e.g. OpenAI parallel_tool_calls, Claude parallel tools), independent
5//! read-only calls can be executed concurrently instead of sequentially.
6//! This module maintains the hardcoded allowlist of tool IDs known to be
7//! side-effect-free.
8//!
9//! # Examples
10//!
11//! ```rust
12//! use codetether_agent::tool::readonly::is_read_only;
13//!
14//! assert!(is_read_only("read"));
15//! assert!(is_read_only("grep"));
16//! assert!(!is_read_only("bash"));
17//! assert!(!is_read_only("write"));
18//! ```
19
20/// Tool IDs whose `execute()` is guaranteed not to mutate the filesystem,
21/// network-visible resources, or internal agent state.
22const READ_ONLY_TOOL_IDS: &[&str] = &[
23 "read",
24 "list",
25 "glob",
26 "tree",
27 "fileinfo",
28 "headtail",
29 "diff",
30 "grep",
31 "codesearch",
32 "lsp",
33 "webfetch",
34 "websearch",
35];
36
37/// Returns `true` if `tool_id` identifies a known read-only tool that is
38/// safe to dispatch concurrently with other read-only tool calls.
39///
40/// Unknown or side-effecting tools return `false` and must be executed
41/// sequentially to preserve ordering semantics.
42pub fn is_read_only(tool_id: &str) -> bool {
43 READ_ONLY_TOOL_IDS.contains(&tool_id)
44}