-
Notifications
You must be signed in to change notification settings - Fork 17
feat: add --disable-subagents flag and CRABCODE_DISABLE_SUBAGENTS env #61
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -179,13 +179,20 @@ pub async fn register_dynamic_tools( | |
| )) | ||
| .await; | ||
|
|
||
| registry | ||
| .register(Arc::new( | ||
| TaskTool::new(registry.clone()) | ||
| .with_sender_opt(sender.clone()) | ||
| .with_runtime_options(permissions, agent_registry, cancel_token), | ||
| )) | ||
| .await; | ||
| // Omit (don't just deny) when disabled so `registry.get("task")` is | ||
| // None and the model never sees the tool. The flag path sets | ||
| // `CRABCODE_DISABLE_SUBAGENTS=1` early in `main`, so this single env | ||
| // check covers flag + env without threading a bool through every | ||
| // `register_dynamic_tools` call site (TUI, print, ACP, serve). | ||
| if !super::task::subagents_disabled() { | ||
| registry | ||
| .register(Arc::new( | ||
| TaskTool::new(registry.clone()) | ||
| .with_sender_opt(sender.clone()) | ||
| .with_runtime_options(permissions, agent_registry, cancel_token), | ||
| )) | ||
| .await; | ||
| } | ||
|
|
||
| // Keep terminal_session as a thin interactive alias for back-compat. | ||
| registry | ||
|
|
@@ -277,6 +284,9 @@ mod tests { | |
|
|
||
| #[tokio::test] | ||
| async fn dynamic_registry_contains_runtime_tools() { | ||
| let _lock = crate::tools::task::disable_subagents_env_lock(); | ||
| let prev = std::env::var(crate::tools::task::DISABLE_SUBAGENTS_ENV).ok(); | ||
| std::env::remove_var(crate::tools::task::DISABLE_SUBAGENTS_ENV); | ||
| let registry = initialize_tool_registry_with_dynamic( | ||
| None, | ||
| ToolPermissions::new("."), | ||
|
|
@@ -292,10 +302,40 @@ mod tests { | |
| assert!(registry.get("bash_output").await.is_some()); | ||
| assert!(registry.get("bash_kill").await.is_some()); | ||
| assert!(registry.get("bash_restart").await.is_some()); | ||
| match prev { | ||
| Some(value) => std::env::set_var(crate::tools::task::DISABLE_SUBAGENTS_ENV, value), | ||
| None => std::env::remove_var(crate::tools::task::DISABLE_SUBAGENTS_ENV), | ||
| } | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn disabled_env_omits_task_tool_from_dynamic_registry() { | ||
| let _lock = crate::tools::task::disable_subagents_env_lock(); | ||
| let prev = std::env::var(crate::tools::task::DISABLE_SUBAGENTS_ENV).ok(); | ||
| std::env::set_var(crate::tools::task::DISABLE_SUBAGENTS_ENV, "1"); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Under the default parallel Rust test runner, this process-wide environment mutation is serialized only against tests that explicitly acquire Useful? React with 👍 / 👎. |
||
| let registry = initialize_tool_registry_with_dynamic( | ||
| None, | ||
| ToolPermissions::new("."), | ||
| crate::agent::definition::AgentRegistry::default(), | ||
| CancellationToken::new(), | ||
| Arc::new(ProcessRegistry::new()), | ||
| ) | ||
| .await; | ||
|
|
||
| assert!(registry.get("task").await.is_none()); | ||
| // Interactive tools stay registered. | ||
| assert!(registry.get("question").await.is_some()); | ||
| match prev { | ||
| Some(value) => std::env::set_var(crate::tools::task::DISABLE_SUBAGENTS_ENV, value), | ||
| None => std::env::remove_var(crate::tools::task::DISABLE_SUBAGENTS_ENV), | ||
| } | ||
| } | ||
|
|
||
| #[tokio::test] | ||
| async fn scoped_plan_registry_hides_mutating_tools() { | ||
| let _lock = crate::tools::task::disable_subagents_env_lock(); | ||
| let prev = std::env::var(crate::tools::task::DISABLE_SUBAGENTS_ENV).ok(); | ||
| std::env::remove_var(crate::tools::task::DISABLE_SUBAGENTS_ENV); | ||
| let permissions = ToolPermissions::new("."); | ||
| let registry = initialize_tool_registry_with_dynamic( | ||
| None, | ||
|
|
@@ -317,6 +357,10 @@ mod tests { | |
| assert!(scoped.get("apply_patch").await.is_none()); | ||
| assert!(scoped.get("write").await.is_none()); | ||
| assert!(scoped.get("edit").await.is_none()); | ||
| match prev { | ||
| Some(value) => std::env::set_var(crate::tools::task::DISABLE_SUBAGENTS_ENV, value), | ||
| None => std::env::remove_var(crate::tools::task::DISABLE_SUBAGENTS_ENV), | ||
| } | ||
| } | ||
|
|
||
| #[tokio::test] | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When subagents are disabled and an image is sent to a text-only model with a configured
vlm-agent,llm/client.rs:726-728still setsshow_vlm_agent_hintto true. The converted user message therefore commands the model to calltask, while this branch omits that tool, and the normal unsupported-image warning is also suppressed. Include the disabled state when deciding whether to advertise the VLM fallback so these requests receive the warning instead of an impossible tool instruction.Useful? React with 👍 / 👎.