diff --git a/src/agents.rs b/src/agents.rs index 07c5d60..5936e34 100644 --- a/src/agents.rs +++ b/src/agents.rs @@ -1,7 +1,7 @@ use serde::{Deserialize, Serialize}; /* ExploreAgent is intentionally limited to read-only tools so it can be - dispatched without approval for safe, unrestricted codebase exploration. */ +dispatched without approval for safe, unrestricted codebase exploration. */ #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] #[serde(rename_all = "snake_case")] pub enum AgentType { @@ -101,17 +101,17 @@ impl AgentPolicy { max_depth: 3, require_preview: false, timeout_seconds: 300, - max_tokens: 16384, + max_tokens: 131072, allowed_tools: vec![], forbidden_mutations: vec!["Cargo.toml".into(), "package.json".into()], }, AgentType::Planner => Self { agent_type: agent_type.clone(), auto_approve: false, - max_depth: 3, + max_depth: 5, require_preview: true, timeout_seconds: 120, - max_tokens: 16384, + max_tokens: 131072, allowed_tools: vec![], forbidden_mutations: vec![], }, @@ -126,7 +126,7 @@ impl AgentPolicy { forbidden_mutations: vec![], }, /* ExploreAgent: auto-approved, read-only tools only, short timeout. - Forbidden mutations set to wildcard to block all writes. */ + Forbidden mutations set to wildcard to block all writes. */ AgentType::ExploreAgent => Self { agent_type: agent_type.clone(), auto_approve: true, @@ -149,8 +149,8 @@ impl AgentPolicy { } /* Per-agent prompt configuration. Stored in the DB and resolved on task - dispatch. Resolution order: task instructions > DB override > this config - > compiled-in default > tool protocol. */ +dispatch. Resolution order: task instructions > DB override > this config +> compiled-in default > tool protocol. */ #[derive(Debug, Clone, Serialize, Deserialize)] pub struct AgentPromptConfig { pub agent_type: AgentType, @@ -208,7 +208,12 @@ mod tests { for agent_type in &types { let s = agent_type.as_str(); let parsed = AgentType::from_str(s); - assert_eq!(parsed.as_ref(), Some(agent_type), "roundtrip failed for {:?}", agent_type); + assert_eq!( + parsed.as_ref(), + Some(agent_type), + "roundtrip failed for {:?}", + agent_type + ); } } diff --git a/src/lib.rs b/src/lib.rs index 39e809d..8c295c9 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -18,7 +18,9 @@ pub mod task; pub mod todo; pub mod tools; -pub use agents::{AgentPolicy, AgentPromptConfig, AgentType, ApprovalMode, PlannedAction, SimulationResult}; +pub use agents::{ + AgentPolicy, AgentPromptConfig, AgentType, ApprovalMode, PlannedAction, SimulationResult, +}; pub use ai_response::{Conversation, Message}; pub use conclusion::{ Artifact, ArtifactType, ConclusionCard, ConclusionMetrics, ConclusionTrigger, @@ -32,11 +34,11 @@ pub use project::{Project, ProjectFile, ProjectId, ProjectSettings}; pub use task::{Task, TaskResult}; pub use todo::{Dependency, ToDo}; pub use tools::{ - format_tool_error, format_tools_json, format_tool_result, parse_tool_call_blocks, - parse_tool_call_stream, tool_definitions, tool_ids_for_agent_type, ApprovalRequirement, - CompositionStep, ContextVisibility, ExecutionContext, MarketplaceSearchResults, ParsedToolCall, - REEF_PROXY_TOOLS, GLOBAL_TOOLS, is_reef_proxy_tool, is_global_tool, - TestAction, ToolComposition, ToolDefinition, ToolDependency, ToolDocumentation, ToolExample, - ToolListing, ToolParser, ToolPlugin, ToolExecutor, ToolRegistry, ToolTest, ToolTestResult, ToolTestSuite, - ToolTestSuiteResult, ToolVersion, + format_tool_error, format_tool_result, format_tools_json, is_global_tool, is_reef_proxy_tool, + parse_tool_call_blocks, parse_tool_call_stream, tool_definitions, tool_ids_for_agent_type, + ApprovalRequirement, CompositionStep, ContextVisibility, ExecutionContext, + MarketplaceSearchResults, ParsedToolCall, TestAction, ToolComposition, ToolDefinition, + ToolDependency, ToolDocumentation, ToolExample, ToolExecutor, ToolListing, ToolParser, + ToolPlugin, ToolRegistry, ToolTest, ToolTestResult, ToolTestSuite, ToolTestSuiteResult, + ToolVersion, GLOBAL_TOOLS, REEF_PROXY_TOOLS, }; diff --git a/src/sandbox.rs b/src/sandbox.rs index 459e951..e0ac923 100644 --- a/src/sandbox.rs +++ b/src/sandbox.rs @@ -1,4 +1,4 @@ -use std::path::{Path, PathBuf, Component}; +use std::path::{Component, Path, PathBuf}; /* Maximum allowed path depth as a safety measure */ const MAX_PATH_DEPTH: usize = 64; @@ -54,15 +54,15 @@ pub fn resolve_sandboxed_path(validated: &Path, sandbox_root: &Path) -> Result

Result

bool { - path.components().any(|comp| matches!(comp, Component::ParentDir)) + path.components() + .any(|comp| matches!(comp, Component::ParentDir)) } fn contains_null_bytes(path: &Path) -> bool { @@ -90,10 +91,11 @@ fn contains_null_bytes(path: &Path) -> bool { fn contains_shell_metacharacters(path: &Path) -> bool { const SHELL_METACHARACTERS: &[char] = &[ - '|', ';', '&', '$', '`', '>', '<', '(', ')', '{', '}', - '!', '#', '*', '?', '[', ']', '~', '\n', '\r', + '|', ';', '&', '$', '`', '>', '<', '(', ')', '{', '}', '!', '#', '*', '?', '[', ']', '~', + '\n', '\r', ]; - path.to_str().map_or(true, |s| s.contains(SHELL_METACHARACTERS)) + path.to_str() + .map_or(true, |s| s.contains(SHELL_METACHARACTERS)) } #[cfg(test)] @@ -152,7 +154,12 @@ mod tests { #[test] fn test_rejects_path_with_shell_metacharacters() { let attacks = vec![ - "file|echo", "file;rm", "file$(id)", "file`id`", "file>out", "fileout", + "file>) -> Result<(), ValidationError> { + pub fn validate( + &self, + deps: &std::collections::HashMap>, + ) -> Result<(), ValidationError> { if self.title.is_empty() { return Err(ValidationError::EmptyTitle); } @@ -127,8 +130,10 @@ impl ToDo { } /* DFS cycle detection over a full dependency graph. Returns the first - todo_id found in a cycle, or None when the graph is acyclic. */ - pub fn detect_cycle_in_graph(deps: &std::collections::HashMap>) -> Option { + todo_id found in a cycle, or None when the graph is acyclic. */ + pub fn detect_cycle_in_graph( + deps: &std::collections::HashMap>, + ) -> Option { let mut visited: HashSet = HashSet::new(); let mut in_stack: HashSet = HashSet::new(); @@ -210,10 +215,7 @@ impl ToDo { } /// Walk the parent_todo_id chain and return the depth (1 = root, 2 = child, etc.) - pub fn calculate_depth( - todo_id: Uuid, - get_parent: impl Fn(Uuid) -> Option, - ) -> usize { + pub fn calculate_depth(todo_id: Uuid, get_parent: impl Fn(Uuid) -> Option) -> usize { let mut depth = 1usize; let mut current_id = get_parent(todo_id); let mut visited = HashSet::new(); @@ -264,7 +266,6 @@ impl ToDo { } } - #[cfg(test)] mod tests { use super::*; @@ -287,7 +288,10 @@ mod tests { fn test_todo_validate_empty_title() { let todo = ToDo::default(); let deps = std::collections::HashMap::new(); - assert!(matches!(todo.validate(&deps), Err(ValidationError::EmptyTitle))); + assert!(matches!( + todo.validate(&deps), + Err(ValidationError::EmptyTitle) + )); } #[test] diff --git a/src/tools.rs b/src/tools.rs index 5eb59d9..838ef0f 100644 --- a/src/tools.rs +++ b/src/tools.rs @@ -1867,6 +1867,8 @@ pub fn tool_ids_for_agent_type(agent_type: &crate::agents::AgentType) -> Option< "get_documentation_context", "documentation_tree", "store_file_doc", + "kanban_create_todo", + "kanban_update_todo", ]), crate::agents::AgentType::TestJudge => curated(&[ "read_file",