From 539dd62085cd604faf2651a0cd6dd040e7c956f0 Mon Sep 17 00:00:00 2001 From: wsp Date: Mon, 12 Oct 2026 16:40:32 +0800 Subject: [PATCH] feat(agents): Disable project layout by default Remove project layout from built-in Agent context policies and custom Agent defaults to reduce automatic context injection. Keep explicit opt-in and the existing policy persistence rules. Generate remote layout previews only when requested, and report missing remote previews without falling back to the local filesystem. --- .../agents/definitions/hidden/code_review.rs | 1 - .../agents/definitions/hidden/deep_review.rs | 1 - .../agents/definitions/modes/cowork.rs | 1 - .../agents/definitions/modes/deep_research.rs | 1 - .../agents/definitions/modes/ultimate.rs | 1 - .../definitions/subagents/computer_use.rs | 4 +- .../definitions/subagents/general_purpose.rs | 1 - .../agents/definitions/subagents/swarm.rs | 2 - .../prompt_builder/prompt_builder_impl.rs | 37 +++++++++++++++---- .../src/agentic/execution/execution_engine.rs | 3 ++ .../core/src/agentic/memories/phase2_agent.rs | 2 - .../core/src/agentic/skill_agent_snapshot.rs | 1 + .../execution/agent-runtime/src/agents.rs | 1 - .../agent-runtime/src/custom_agent.rs | 3 +- .../agent_registry_contracts.rs | 2 +- .../agents/components/CreateAgentPage.tsx | 2 - 16 files changed, 36 insertions(+), 27 deletions(-) diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/hidden/code_review.rs b/src/crates/assembly/core/src/agentic/agents/definitions/hidden/code_review.rs index 25d9499336..df2a354e51 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/hidden/code_review.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/hidden/code_review.rs @@ -70,7 +70,6 @@ impl Agent for CodeReviewAgent { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/hidden/deep_review.rs b/src/crates/assembly/core/src/agentic/agents/definitions/hidden/deep_review.rs index d7c497cd63..8e81401919 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/hidden/deep_review.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/hidden/deep_review.rs @@ -67,7 +67,6 @@ impl Agent for DeepReviewAgent { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/modes/cowork.rs b/src/crates/assembly/core/src/agentic/agents/definitions/modes/cowork.rs index d7d7a0c996..882e3d13af 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/modes/cowork.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/modes/cowork.rs @@ -95,7 +95,6 @@ impl Agent for CoworkMode { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/modes/deep_research.rs b/src/crates/assembly/core/src/agentic/agents/definitions/modes/deep_research.rs index 04ee1dc164..19ac81a3eb 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/modes/deep_research.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/modes/deep_research.rs @@ -81,7 +81,6 @@ impl Agent for DeepResearchMode { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/modes/ultimate.rs b/src/crates/assembly/core/src/agentic/agents/definitions/modes/ultimate.rs index 1e7b368deb..4c0135bc64 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/modes/ultimate.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/modes/ultimate.rs @@ -65,7 +65,6 @@ impl Agent for UltimateHarness { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { false diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/computer_use.rs b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/computer_use.rs index 3a58205de4..acbae9a35f 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/computer_use.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/computer_use.rs @@ -62,9 +62,7 @@ impl Agent for ComputerUseMode { } fn user_context_policy(&self) -> UserContextPolicy { - UserContextPolicy::empty() - .with_workspace_instructions() - .with_project_layout() + UserContextPolicy::empty().with_workspace_instructions() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/general_purpose.rs b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/general_purpose.rs index f8dc93f946..4cafe747eb 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/general_purpose.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/general_purpose.rs @@ -63,7 +63,6 @@ impl Agent for GeneralPurposeAgent { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn is_readonly(&self) -> bool { diff --git a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/swarm.rs b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/swarm.rs index ee006fbbae..89a9923186 100644 --- a/src/crates/assembly/core/src/agentic/agents/definitions/subagents/swarm.rs +++ b/src/crates/assembly/core/src/agentic/agents/definitions/subagents/swarm.rs @@ -54,7 +54,6 @@ impl Agent for SwarmPlannerAgent { crate::agentic::agents::UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } } @@ -180,6 +179,5 @@ impl Agent for SwarmWorkerAgent { crate::agentic::agents::UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } } diff --git a/src/crates/assembly/core/src/agentic/agents/prompt_builder/prompt_builder_impl.rs b/src/crates/assembly/core/src/agentic/agents/prompt_builder/prompt_builder_impl.rs index f95cd077db..cb7e0456e7 100644 --- a/src/crates/assembly/core/src/agentic/agents/prompt_builder/prompt_builder_impl.rs +++ b/src/crates/assembly/core/src/agentic/agents/prompt_builder/prompt_builder_impl.rs @@ -150,6 +150,7 @@ impl PromptBuilderContext { } } +#[allow(clippy::too_many_arguments)] pub async fn build_prompt_context_for_workspace( workspace: &WorkspaceBinding, workspace_id: Option<&str>, @@ -158,6 +159,7 @@ pub async fn build_prompt_context_for_workspace( supports_image_understanding: Option, tool_listing_sections: ToolListingSections, runtime_context_needs: RuntimeContextNeeds, + user_context_policy: &UserContextPolicy, ) -> Option { let workspace_path = workspace.root_path_string(); @@ -203,6 +205,7 @@ pub async fn build_prompt_context_for_workspace( #[cfg(not(feature = "remote-workspace"))] { + let _ = user_context_policy; Some(base) } @@ -232,7 +235,6 @@ pub async fn build_prompt_context_for_workspace( }; let ssh_manager = manager.get_ssh_manager().await; - let file_service = manager.get_file_service().await; let (kernel_name, hostname) = if let Some(ref ssh) = ssh_manager { if let Some(info) = ssh.get_server_info(connection_id).await { (info.os_type, info.hostname) @@ -242,15 +244,24 @@ pub async fn build_prompt_context_for_workspace( } else { ("Linux".to_string(), "remote".to_string()) }; - let remote_layout = if let Some(ref fs) = file_service { - match build_remote_workspace_layout_preview(fs, connection_id, &workspace_path, 200) + let remote_layout = if user_context_policy.includes(UserContextSection::ProjectLayout) { + if let Some(fs) = manager.get_file_service().await { + match build_remote_workspace_layout_preview( + &fs, + connection_id, + &workspace_path, + 200, + ) .await - { - Ok((_, preview)) => Some(preview), - Err(e) => { - warn!("Remote workspace layout for prompt failed: {}", e); - None + { + Ok((_, preview)) => Some(preview), + Err(e) => { + warn!("Remote workspace layout for prompt failed: {}", e); + None + } } + } else { + None } } else { None @@ -334,6 +345,15 @@ impl PromptBuilder { }); } + if self.context.remote_execution.is_some() { + return render_project_layout(&ProjectLayoutFacts { + listing: "Remote workspace layout is unavailable.".to_string(), + reached_limit: false, + max_entries: self.file_tree_max_entries, + remote: true, + }); + } + let formatted_listing = get_formatted_directory_listing( &self.context.workspace_path, self.file_tree_max_entries, @@ -1097,6 +1117,7 @@ mod tests { None, ToolListingSections::default(), RuntimeContextNeeds::default(), + &UserContextPolicy::empty().with_workspace_context(), ) .await .expect("prompt context should build"); diff --git a/src/crates/assembly/core/src/agentic/execution/execution_engine.rs b/src/crates/assembly/core/src/agentic/execution/execution_engine.rs index 48a4ce658d..8c9dadd86c 100644 --- a/src/crates/assembly/core/src/agentic/execution/execution_engine.rs +++ b/src/crates/assembly/core/src/agentic/execution/execution_engine.rs @@ -1464,6 +1464,7 @@ impl ExecutionEngine { supports_image_understanding: bool, tool_listing_sections: ToolListingSections, runtime_context_needs: RuntimeContextNeeds, + user_context_policy: &UserContextPolicy, ) -> Option { let workspace = context.workspace.as_ref()?; let remote_file_delivery_channel = context @@ -1479,6 +1480,7 @@ impl ExecutionEngine { Some(supports_image_understanding), tool_listing_sections, runtime_context_needs, + user_context_policy, ) .await .map(|prompt_context| { @@ -1747,6 +1749,7 @@ impl ExecutionEngine { input.supports_image_understanding, input.tool_listing_sections, input.runtime_context_needs, + &input.current_agent.user_context_policy(), ) .await; let prepended_prompt_reminders = self diff --git a/src/crates/assembly/core/src/agentic/memories/phase2_agent.rs b/src/crates/assembly/core/src/agentic/memories/phase2_agent.rs index b16aa22b2d..7f09db7958 100644 --- a/src/crates/assembly/core/src/agentic/memories/phase2_agent.rs +++ b/src/crates/assembly/core/src/agentic/memories/phase2_agent.rs @@ -59,7 +59,6 @@ impl Agent for MemoryPhase2Agent { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() } fn tool_exposure_overrides(&self) -> &AgentToolPolicyOverrides { @@ -86,7 +85,6 @@ mod tests { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() ); assert!(agent.default_tools().contains(&"Read".to_string())); assert!(agent.default_tools().contains(&"Write".to_string())); diff --git a/src/crates/assembly/core/src/agentic/skill_agent_snapshot.rs b/src/crates/assembly/core/src/agentic/skill_agent_snapshot.rs index 76a13c5965..b9c6f929ab 100644 --- a/src/crates/assembly/core/src/agentic/skill_agent_snapshot.rs +++ b/src/crates/assembly/core/src/agentic/skill_agent_snapshot.rs @@ -245,6 +245,7 @@ pub async fn build_embedded_user_context_reminder( None, ToolListingSections::default(), Default::default(), + user_context_policy, ) .await?; PromptBuilder::new(context) diff --git a/src/crates/execution/agent-runtime/src/agents.rs b/src/crates/execution/agent-runtime/src/agents.rs index 0566507362..2661cb554b 100644 --- a/src/crates/execution/agent-runtime/src/agents.rs +++ b/src/crates/execution/agent-runtime/src/agents.rs @@ -53,7 +53,6 @@ pub fn standard_harness_user_context_policy() -> UserContextPolicy { UserContextPolicy::empty() .with_workspace_context() .with_workspace_instructions() - .with_project_layout() .with_memory_summary() } diff --git a/src/crates/execution/agent-runtime/src/custom_agent.rs b/src/crates/execution/agent-runtime/src/custom_agent.rs index 78b45852e6..99ab417f9f 100644 --- a/src/crates/execution/agent-runtime/src/custom_agent.rs +++ b/src/crates/execution/agent-runtime/src/custom_agent.rs @@ -332,8 +332,7 @@ pub fn custom_agent_tools_are_default(kind: CustomAgentKind, tools: &[String]) - pub fn default_custom_agent_user_context_policy(kind: CustomAgentKind) -> UserContextPolicy { let base = UserContextPolicy::empty() .with_workspace_context() - .with_workspace_instructions() - .with_project_layout(); + .with_workspace_instructions(); match kind { CustomAgentKind::Mode | CustomAgentKind::Subagent => base, } diff --git a/src/crates/execution/agent-runtime/tests/agent_definition_contracts/agent_registry_contracts.rs b/src/crates/execution/agent-runtime/tests/agent_definition_contracts/agent_registry_contracts.rs index e3aee2e127..1d4758e328 100644 --- a/src/crates/execution/agent-runtime/tests/agent_definition_contracts/agent_registry_contracts.rs +++ b/src/crates/execution/agent-runtime/tests/agent_definition_contracts/agent_registry_contracts.rs @@ -186,7 +186,7 @@ fn mode_presentation_and_shared_context_policy_match_existing_mode_contract() { assert_eq!( standard_harness_user_context_policy().cache_scope_key(), - "workspace_context|workspace_instructions|project_layout|memory_summary" + "workspace_context|workspace_instructions|memory_summary" ); } diff --git a/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.tsx b/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.tsx index 65eaf07704..04964ee85c 100644 --- a/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.tsx +++ b/src/web-ui/src/app/scenes/agents/components/CreateAgentPage.tsx @@ -31,12 +31,10 @@ const ID_REGEX = /^[a-zA-Z][a-zA-Z0-9_-]*$/; const DEFAULT_MODE_POLICY: UserContextSection[] = [ 'workspace_context', 'workspace_instructions', - 'project_layout', ]; const DEFAULT_SUBAGENT_POLICY: UserContextSection[] = [ 'workspace_context', 'workspace_instructions', - 'project_layout', ]; const DEFAULT_CUSTOM_MODE_TOOLS = [ 'Read',