use crate::command::chat::tools::tool_names;
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
pub enum ContextTier {
System = 0,
User = 1,
KeyTool = 2,
Assistant = 3,
RegularTool = 4,
}
impl ContextTier {
pub fn priority(self) -> u8 {
self as u8
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RetentionPolicy {
AlwaysPreserve,
Placeholder,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct ToolContextPolicy {
pub tier: ContextTier,
pub retention: RetentionPolicy,
}
impl ToolContextPolicy {
const fn key_preserve() -> Self {
Self {
tier: ContextTier::KeyTool,
retention: RetentionPolicy::AlwaysPreserve,
}
}
const fn regular_placeholder() -> Self {
Self {
tier: ContextTier::RegularTool,
retention: RetentionPolicy::Placeholder,
}
}
}
pub const KEY_TOOL_NAMES: &[&str] = &[
tool_names::ENTER_PLAN_MODE,
tool_names::EXIT_PLAN_MODE,
tool_names::ENTER_WORKTREE,
tool_names::EXIT_WORKTREE,
tool_names::ASK,
tool_names::LOAD_SKILL,
tool_names::TODO_WRITE,
tool_names::TODO_READ,
tool_names::TASK,
tool_names::AGENT,
tool_names::AGENT_TEAM,
tool_names::SEND_MESSAGE,
tool_names::CREATE_TEAMMATE,
];
pub fn policy_for(tool_name: &str) -> ToolContextPolicy {
match tool_name {
tool_names::ENTER_PLAN_MODE
| tool_names::EXIT_PLAN_MODE
| tool_names::ENTER_WORKTREE
| tool_names::EXIT_WORKTREE
| tool_names::ASK
| tool_names::LOAD_SKILL
| tool_names::TODO_WRITE
| tool_names::TODO_READ
| tool_names::TASK
| tool_names::AGENT
| tool_names::AGENT_TEAM
| tool_names::SEND_MESSAGE
| tool_names::CREATE_TEAMMATE => ToolContextPolicy::key_preserve(),
_ => ToolContextPolicy::regular_placeholder(),
}
}
pub fn is_key_tool(tool_name: &str) -> bool {
policy_for(tool_name).retention == RetentionPolicy::AlwaysPreserve
}
pub fn tier_for(tool_name: &str) -> ContextTier {
policy_for(tool_name).tier
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn key_tool_list_matches_policy() {
for name in KEY_TOOL_NAMES {
assert!(
is_key_tool(name),
"KEY_TOOL_NAMES 中的 {} 应返回 AlwaysPreserve",
name
);
}
}
#[test]
fn regular_tools_are_placeholder() {
for name in [
tool_names::BASH,
tool_names::READ,
tool_names::WRITE,
tool_names::EDIT,
tool_names::GLOB,
tool_names::GREP,
tool_names::WEB_FETCH,
] {
let p = policy_for(name);
assert_eq!(
p.tier,
ContextTier::RegularTool,
"{} 应为 RegularTool",
name
);
assert_eq!(
p.retention,
RetentionPolicy::Placeholder,
"{} 应为 Placeholder",
name
);
}
}
#[test]
fn unknown_tool_fallback_regular() {
let p = policy_for("SomeNewFutureTool");
assert_eq!(p.tier, ContextTier::RegularTool);
assert_eq!(p.retention, RetentionPolicy::Placeholder);
}
#[test]
fn tier_priority_ordering() {
assert!(ContextTier::System.priority() < ContextTier::User.priority());
assert!(ContextTier::User.priority() < ContextTier::KeyTool.priority());
assert!(ContextTier::KeyTool.priority() < ContextTier::Assistant.priority());
assert!(ContextTier::Assistant.priority() < ContextTier::RegularTool.priority());
}
#[test]
fn user_mentioned_key_tools_are_preserved() {
for name in [
tool_names::ENTER_PLAN_MODE,
tool_names::ENTER_WORKTREE,
tool_names::ASK,
tool_names::LOAD_SKILL,
] {
assert!(is_key_tool(name), "{} 必须是 KeyTool", name);
}
}
}