mirror of
https://github.com/zed-industries/zed.git
synced 2026-06-01 03:14:56 +07:00
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:
parent
e0ecfa8225
commit
3965f7133f
11 changed files with 78 additions and 186 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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:"));
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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}}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
|
|
|
|||
|
|
@ -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()));
|
||||
|
|
|
|||
|
|
@ -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());
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue