Stop loading deprecated agent rules (#57844) (cherry-pick to preview) (#57851)

Cherry-pick of #57844 to preview

----
Summary:

- Stop loading persisted default Zed Rules into native agent project
context.
- Remove legacy user-rules rendering from agent system prompt templates.
- Keep Skills and project rules file support unchanged.

Tests:

- cargo test -p agent
test_system_prompt_does_not_render_legacy_zed_rules_section --lib
- cargo test -p prompt_store test_empty_skills_sets_has_skills_false
- cargo test -p prompt_store
test_project_context_does_not_filter_by_budget

Closes AI-325
Release Notes:

- Fixed deprecated Rules being automatically included in new agent
requests.

Co-authored-by: MartinYe1234 <52641447+MartinYe1234@users.noreply.github.com>
This commit is contained in:
zed-zippy[bot] 2026-05-27 16:34:01 +00:00 committed by GitHub
parent e0ecfa8225
commit 3965f7133f
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 78 additions and 186 deletions

View file

@ -49,10 +49,7 @@ use language_model::{IconOrSvg, LanguageModel, LanguageModelProvider, LanguageMo
use project::{
AgentId, Project, ProjectItem, ProjectPath, Worktree, trusted_worktrees::TrustedWorktrees,
};
use prompt_store::{
ProjectContext, PromptStore, RULES_FILE_NAMES, RulesFileContext, UserRulesContext,
WorktreeContext,
};
use prompt_store::{ProjectContext, RULES_FILE_NAMES, RulesFileContext, WorktreeContext};
use serde::{Deserialize, Serialize};
use settings::{LanguageModelSelection, Settings as _, update_settings_file};
use std::any::Any;
@ -306,7 +303,6 @@ pub struct NativeAgent {
templates: Arc<Templates>,
/// Cached model information
models: LanguageModels,
prompt_store: Option<Entity<PromptStore>>,
fs: Arc<dyn Fs>,
_subscriptions: Vec<Subscription>,
/// Tracks the lifecycle of global skills directory observation. We
@ -353,20 +349,16 @@ impl NativeAgent {
pub fn new(
thread_store: Entity<ThreadStore>,
templates: Arc<Templates>,
prompt_store: Option<Entity<PromptStore>>,
fs: Arc<dyn Fs>,
cx: &mut App,
) -> Entity<NativeAgent> {
log::debug!("Creating new NativeAgent");
cx.new(|cx| {
let mut subscriptions = vec![cx.subscribe(
let subscriptions = vec![cx.subscribe(
&LanguageModelRegistry::global(cx),
Self::handle_models_updated_event,
)];
if let Some(prompt_store) = prompt_store.as_ref() {
subscriptions.push(cx.subscribe(prompt_store, Self::handle_prompts_updated_event))
}
if !cx.has_global::<SkillIndex>() {
cx.set_global(SkillIndex::default());
@ -379,7 +371,6 @@ impl NativeAgent {
projects: HashMap::default(),
templates,
models: LanguageModels::new(cx),
prompt_store,
fs,
_subscriptions: subscriptions,
skills_state: SkillsState::default(),
@ -638,7 +629,7 @@ impl NativeAgent {
return project_id;
}
let project_context = cx.new(|_| ProjectContext::new(vec![], vec![]));
let project_context = cx.new(|_| ProjectContext::new(vec![]));
self.register_project_with_initial_context(project.clone(), project_context, cx);
if let Some(state) = self.projects.get_mut(&project_id) {
state.project_context_needs_refresh.send(()).ok();
@ -731,7 +722,6 @@ impl NativeAgent {
.context("project state not found")?;
anyhow::Ok(Self::build_project_context(
&state.project,
this.prompt_store.as_ref(),
this.fs.clone(),
cx,
))
@ -803,7 +793,6 @@ impl NativeAgent {
fn build_project_context(
project: &Entity<Project>,
prompt_store: Option<&Entity<PromptStore>>,
fs: Arc<dyn Fs>,
cx: &mut App,
) -> Task<(ProjectContext, Vec<Skill>, Vec<SkillLoadError>)> {
@ -885,22 +874,8 @@ impl NativeAgent {
.collect();
cx.background_spawn(async move { future::join_all(project_skills_futures).await })
};
let default_user_rules_task = if let Some(prompt_store) = prompt_store.as_ref() {
prompt_store.read_with(cx, |prompt_store, cx| {
let prompts = prompt_store.default_prompt_metadata();
let load_tasks = prompts.into_iter().map(|prompt_metadata| {
let contents = prompt_store.load(prompt_metadata.id, cx);
async move { (contents.await, prompt_metadata) }
});
cx.background_spawn(future::join_all(load_tasks))
})
} else {
Task::ready(vec![])
};
cx.spawn(async move |_cx| {
let (worktrees, default_user_rules) =
future::join(future::join_all(worktree_tasks), default_user_rules_task).await;
let worktrees = future::join_all(worktree_tasks).await;
let worktrees = worktrees
.into_iter()
@ -913,27 +888,6 @@ impl NativeAgent {
})
.collect::<Vec<_>>();
let default_user_rules = default_user_rules
.into_iter()
.flat_map(|(contents, prompt_metadata)| match contents {
Ok(contents) => Some(UserRulesContext {
uuid: prompt_metadata.id.as_user()?,
title: prompt_metadata.title.map(|title| title.to_string()),
contents,
}),
Err(_err) => {
// TODO: show error message
// this.update(cx, |_, cx| {
// cx.emit(RulesLoadingError {
// message: format!("{err:?}").into(),
// });
// })
// .ok();
None
}
})
.collect::<Vec<_>>();
// Load and combine skills. `combine_skills` deliberately
// does NOT deduplicate — the autocomplete popup needs to
// see every entry so users can disambiguate same-named
@ -957,8 +911,7 @@ impl NativeAgent {
let (catalog_skills, budget_errors) = select_catalog_skills(&overridden);
skill_errors.extend(budget_errors);
let project_context =
ProjectContext::new(worktrees, default_user_rules).with_skills(catalog_skills);
let project_context = ProjectContext::new(worktrees).with_skills(catalog_skills);
(project_context, skills, skill_errors)
})
}
@ -1119,17 +1072,6 @@ impl NativeAgent {
}
}
fn handle_prompts_updated_event(
&mut self,
_prompt_store: Entity<PromptStore>,
_event: &prompt_store::PromptsUpdatedEvent,
_cx: &mut Context<Self>,
) {
for state in self.projects.values_mut() {
state.project_context_needs_refresh.send(()).ok();
}
}
fn handle_models_updated_event(
&mut self,
_registry: Entity<LanguageModelRegistry>,
@ -3499,7 +3441,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
// Creating a session registers the project and triggers context building.
let connection = NativeAgentConnection(agent.clone());
@ -3590,7 +3532,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
// Simulate the user-interaction trigger that the agent panel
// fires (input focus, slash autocomplete, or submit). In tests
@ -3653,7 +3595,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
// First scan trigger: nothing on disk yet, state stays idle.
cx.update(|cx| {
@ -3730,7 +3672,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
// First scan trigger: nothing on disk yet.
cx.update(|cx| {
@ -3876,7 +3818,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
// Open a parent session through the connection, the same way
// production does. This triggers project-context refresh which
@ -3989,7 +3931,7 @@ mod internal_tests {
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
let connection = NativeAgentConnection(agent.clone());
let acp_thread = cx
@ -4094,7 +4036,7 @@ mod internal_tests {
Project::test_with_worktree_trust(fs.clone(), [Path::new("/project")], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
let connection = NativeAgentConnection(agent.clone());
let acp_thread = cx
@ -4175,10 +4117,9 @@ mod internal_tests {
fs.insert_tree("/", json!({ "a": {} })).await;
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let connection =
NativeAgentConnection(cx.update(|cx| {
NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx)
}));
let connection = NativeAgentConnection(
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx)),
);
// Create a thread/session
let acp_thread = cx
@ -4252,7 +4193,7 @@ mod internal_tests {
// Create the agent and connection
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
let connection = NativeAgentConnection(agent.clone());
// Create a thread/session
@ -4349,7 +4290,7 @@ mod internal_tests {
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
let connection = NativeAgentConnection(agent.clone());
let acp_thread = cx
@ -4440,7 +4381,7 @@ mod internal_tests {
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), None, fs.clone(), cx));
cx.update(|cx| NativeAgent::new(thread_store, Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -4491,9 +4432,8 @@ mod internal_tests {
fs.insert_tree("/", json!({ "a": {} })).await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
// Register a thinking model.
@ -4594,9 +4534,8 @@ mod internal_tests {
fs.insert_tree("/", json!({ "a": {} })).await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
// Register a model where id() != name(), like real Anthropic models
@ -4710,9 +4649,8 @@ mod internal_tests {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -4892,9 +4830,8 @@ mod internal_tests {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -4973,9 +4910,8 @@ mod internal_tests {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5057,9 +4993,8 @@ mod internal_tests {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5202,9 +5137,8 @@ mod internal_tests {
fs.insert_tree("/", json!({ "a": {} })).await;
let project = Project::test(fs.clone(), [], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent = cx
.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx

View file

@ -9,9 +9,7 @@ use fs::Fs;
use gpui::{App, Entity, Task};
use language_model::{LanguageModelId, LanguageModelProviderId, LanguageModelRegistry};
use project::{AgentId, Project};
use prompt_store::PromptStore;
use settings::{LanguageModelSelection, Settings as _, update_settings_file};
use util::ResultExt as _;
use crate::{NativeAgent, NativeAgentConnection, ThreadStore, templates::Templates};
@ -45,15 +43,12 @@ impl AgentServer for NativeAgentServer {
log::debug!("NativeAgentServer::connect");
let fs = self.fs.clone();
let thread_store = self.thread_store.clone();
let prompt_store = PromptStore::global(cx);
cx.spawn(async move |cx| {
log::debug!("Creating templates for native agent");
let templates = Templates::new();
let prompt_store = prompt_store.await.log_err();
log::debug!("Creating native agent entity");
let agent =
cx.update(|cx| NativeAgent::new(thread_store, templates, prompt_store, fs, cx));
let agent = cx.update(|cx| NativeAgent::new(thread_store, templates, fs, cx));
// Create the connection wrapper
let connection = NativeAgentConnection(agent);

View file

@ -111,7 +111,7 @@ mod tests {
project_entry_id: 1,
}),
}];
let project = ProjectContext::new(worktrees, Vec::new());
let project = ProjectContext::new(worktrees);
let template = SystemPromptTemplate {
project: &project,
available_tools: vec!["echo".into()],
@ -149,4 +149,21 @@ mod tests {
let rendered = template.render(&templates).unwrap();
assert!(!rendered.contains("### Personal `AGENTS.md`"));
}
#[test]
fn test_system_prompt_does_not_render_legacy_zed_rules_section() {
let project = prompt_store::ProjectContext::default();
let template = SystemPromptTemplate {
project: &project,
available_tools: vec!["echo".into()],
model_name: Some("test-model".to_string()),
date: "2026-01-01".to_string(),
user_agents_md: None,
};
let templates = Templates::new();
let rendered = template.render(&templates).unwrap();
assert!(!rendered.contains("The user has specified the following rules"));
assert!(!rendered.contains("Rules title:"));
}
}

View file

@ -162,12 +162,11 @@ The current project contains the following root directories:
You are powered by the model named {{model_name}}.
{{/if}}
{{#if (or has_rules has_user_rules)}}
{{#if has_rules}}
## User's Custom Instructions
The following additional instructions are provided by the user and should be followed to the best of your ability{{#if (gt (len available_tools) 0)}} without interfering with the tool use guidelines{{/if}}.
{{#if has_rules}}
There are project rules that apply to these root directories:
{{#each worktrees}}
{{#if rules_file}}
@ -178,17 +177,3 @@ There are project rules that apply to these root directories:
{{/if}}
{{/each}}
{{/if}}
{{#if has_user_rules}}
The user has specified the following rules that should be applied:
{{#each user_rules}}
{{#if title}}
Rules title: {{title}}
{{/if}}
``````
{{contents}}
``````
{{/each}}
{{/if}}
{{/if}}

View file

@ -212,7 +212,7 @@ To use a Skill:
4. If the Skill references additional files, use `read_file` to access them. Paths inside a Skill resolve relative to that Skill's directory (the parent of its `SKILL.md`).
{{/if}}
{{#if (or user_agents_md has_rules has_user_rules)}}
{{#if (or user_agents_md has_rules)}}
## User's Custom Instructions
The following additional instructions are provided by the user and should be followed to the best of your ability{{#if (gt (len available_tools) 0)}} without interfering with the tool use guidelines{{/if}}.
@ -243,16 +243,4 @@ There are project rules that apply to these root directories:
{{/each}}
{{/if}}
{{#if has_user_rules}}
The user has specified the following rules that should be applied:
{{#each user_rules}}
{{#if title}}
Rules title: {{title}}
{{/if}}
``````
{{contents}}
``````
{{/each}}
{{/if}}
{{/if}}

View file

@ -3520,8 +3520,8 @@ async fn test_agent_connection(cx: &mut TestAppContext) {
let thread_store = cx.new(|cx| ThreadStore::new(cx));
// Create agent and connection
let agent = cx
.update(|cx| NativeAgent::new(thread_store, templates.clone(), None, fake_fs.clone(), cx));
let agent =
cx.update(|cx| NativeAgent::new(thread_store, templates.clone(), fake_fs.clone(), cx));
let connection = NativeAgentConnection(agent.clone());
// Create a thread using new_thread
@ -4941,9 +4941,8 @@ async fn test_subagent_tool_call_end_to_end(cx: &mut TestAppContext) {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5076,9 +5075,8 @@ async fn test_subagent_tool_output_does_not_include_thinking(cx: &mut TestAppCon
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5224,9 +5222,8 @@ async fn test_subagent_tool_call_cancellation_during_task_prompt(cx: &mut TestAp
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5354,9 +5351,8 @@ async fn test_subagent_tool_resume_session(cx: &mut TestAppContext) {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -5887,9 +5883,8 @@ async fn test_subagent_context_window_warning(cx: &mut TestAppContext) {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -6013,9 +6008,8 @@ async fn test_subagent_no_context_window_warning_when_already_at_warning(cx: &mu
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx
@ -6187,9 +6181,8 @@ async fn test_subagent_error_propagation(cx: &mut TestAppContext) {
.await;
let project = Project::test(fs.clone(), [path!("/a").as_ref()], cx).await;
let thread_store = cx.new(|cx| ThreadStore::new(cx));
let agent = cx.update(|cx| {
NativeAgent::new(thread_store.clone(), Templates::new(), None, fs.clone(), cx)
});
let agent =
cx.update(|cx| NativeAgent::new(thread_store.clone(), Templates::new(), fs.clone(), cx));
let connection = Rc::new(NativeAgentConnection(agent.clone()));
let acp_thread = cx

View file

@ -361,7 +361,7 @@ impl EditToolTest {
abs_path: Path::new("/path/to/root").into(),
rules_file: None,
}];
let project_context = ProjectContext::new(worktrees, Vec::default());
let project_context = ProjectContext::new(worktrees);
let tool_names = tools
.iter()
.map(|tool| tool.name.clone().into())

View file

@ -220,7 +220,7 @@ impl TerminalToolTest {
abs_path: Path::new("/path/to/root").into(),
rules_file: None,
}];
let project_context = ProjectContext::new(worktrees, Vec::default());
let project_context = ProjectContext::new(worktrees);
let tool_names = tools
.iter()
.map(|tool| tool.name.clone().into())

View file

@ -191,7 +191,7 @@ impl WriteToolTest {
abs_path: Path::new("/path/to/root").into(),
rules_file: None,
}];
let project_context = ProjectContext::new(worktrees, Vec::default());
let project_context = ProjectContext::new(worktrees);
let tool_names = tools
.iter()
.map(|tool| tool.name.clone().into())

View file

@ -560,13 +560,7 @@ async fn run_agent(
let agent = cx.update(|cx| {
let thread_store = cx.new(|cx| ThreadStore::new(cx));
NativeAgent::new(
thread_store,
Templates::new(),
None,
app_state.fs.clone(),
cx,
)
NativeAgent::new(thread_store, Templates::new(), app_state.fs.clone(), cx)
});
let connection = Rc::new(NativeAgentConnection(agent.clone()));

View file

@ -19,8 +19,6 @@ use util::{
ResultExt, get_default_system_shell_preferring_bash, rel_path::RelPath, shell::ShellKind,
};
use crate::UserPromptId;
pub const RULES_FILE_NAMES: &[&str] = &[
".rules",
".cursorrules",
@ -38,14 +36,11 @@ pub struct ProjectContext {
pub worktrees: Vec<WorktreeContext>,
/// Whether any worktree has a rules_file. Provided as a field because handlebars can't do this.
pub has_rules: bool,
pub user_rules: Vec<UserRulesContext>,
/// `!user_rules.is_empty()` - provided as a field because handlebars can't do this.
pub has_user_rules: bool,
pub os: String,
pub arch: String,
pub shell: String,
// Similarly to `has_rules` / `has_user_rules`, `has_skills` is a
// derived flag exposed to the handlebars template (which can't do
// Similarly to `has_rules`, `has_skills` is a derived flag exposed
// to the handlebars template (which can't do
// `!skills.is_empty()`). These are `pub(crate)` so the only way to
// set them from outside is via `with_skills`, which keeps the two
// fields in sync.
@ -54,15 +49,13 @@ pub struct ProjectContext {
}
impl ProjectContext {
pub fn new(worktrees: Vec<WorktreeContext>, default_user_rules: Vec<UserRulesContext>) -> Self {
pub fn new(worktrees: Vec<WorktreeContext>) -> Self {
let has_rules = worktrees
.iter()
.any(|worktree| worktree.rules_file.is_some());
Self {
worktrees,
has_rules,
has_user_rules: !default_user_rules.is_empty(),
user_rules: default_user_rules,
os: std::env::consts::OS.to_string(),
arch: std::env::consts::ARCH.to_string(),
shell: ShellKind::new(&get_default_system_shell_preferring_bash(), cfg!(windows))
@ -91,13 +84,6 @@ impl ProjectContext {
}
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub struct UserRulesContext {
pub uuid: UserPromptId,
pub title: Option<String>,
pub contents: String,
}
#[derive(Debug, Clone, Eq, PartialEq, Serialize)]
pub struct WorktreeContext {
pub root_name: String,
@ -167,14 +153,14 @@ mod tests {
};
let summary = SkillSummary::from(&skill);
let context = ProjectContext::new(vec![], vec![]).with_skills(vec![summary]);
let context = ProjectContext::new(vec![]).with_skills(vec![summary]);
assert_eq!(context.skills.len(), 1);
assert_eq!(context.skills[0].description, huge_description);
}
#[test]
fn test_empty_skills_sets_has_skills_false() {
let context = ProjectContext::new(vec![], vec![]);
let context = ProjectContext::new(vec![]);
assert!(!context.has_skills);
assert!(context.skills.is_empty());
}