feat: add /plan command in CLI to invoke reasoner with plan system prompt (#1616)
This commit is contained in:
@@ -63,6 +63,9 @@ pub trait Agent: Send + Sync {
|
||||
/// Returns the prompt text that would be used as user input
|
||||
async fn get_prompt(&self, name: &str, arguments: Value) -> Result<GetPromptResult>;
|
||||
|
||||
/// Get the plan prompt, which will be used with the planner (reasoner) model
|
||||
async fn get_plan_prompt(&self) -> anyhow::Result<String>;
|
||||
|
||||
/// Get a reference to the provider used by this agent
|
||||
async fn provider(&self) -> Arc<Box<dyn Provider>>;
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ use std::time::Duration;
|
||||
use tokio::sync::Mutex;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::extension::{ExtensionConfig, ExtensionError, ExtensionInfo, ExtensionResult};
|
||||
use super::extension::{ExtensionConfig, ExtensionError, ExtensionInfo, ExtensionResult, ToolInfo};
|
||||
use crate::config::Config;
|
||||
use crate::prompt_template;
|
||||
use crate::providers::base::Provider;
|
||||
@@ -83,6 +83,14 @@ fn normalize(input: String) -> String {
|
||||
result.to_lowercase()
|
||||
}
|
||||
|
||||
pub fn get_parameter_names(tool: &Tool) -> Vec<String> {
|
||||
tool.input_schema
|
||||
.get("properties")
|
||||
.and_then(|props| props.as_object())
|
||||
.map(|props| props.keys().cloned().collect())
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
impl Capabilities {
|
||||
/// Create a new Capabilities with the specified provider
|
||||
pub fn new(provider: Box<dyn Provider>) -> Self {
|
||||
@@ -296,6 +304,14 @@ impl Capabilities {
|
||||
Ok(result)
|
||||
}
|
||||
|
||||
/// Get the extension prompt including client instructions
|
||||
pub async fn get_planning_prompt(&self, tools_info: Vec<ToolInfo>) -> String {
|
||||
let mut context: HashMap<&str, Value> = HashMap::new();
|
||||
context.insert("tools", serde_json::to_value(tools_info).unwrap());
|
||||
|
||||
prompt_template::render_global_file("plan.md", &context).expect("Prompt should render")
|
||||
}
|
||||
|
||||
/// Get the extension prompt including client instructions
|
||||
pub async fn get_system_prompt(&self) -> String {
|
||||
let mut context: HashMap<&str, Value> = HashMap::new();
|
||||
|
||||
@@ -192,3 +192,21 @@ impl ExtensionInfo {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Information about the tool used for building prompts
|
||||
#[derive(Clone, Debug, Serialize)]
|
||||
pub struct ToolInfo {
|
||||
name: String,
|
||||
description: String,
|
||||
parameters: Vec<String>,
|
||||
}
|
||||
|
||||
impl ToolInfo {
|
||||
pub fn new(name: &str, description: &str, parameters: Vec<String>) -> Self {
|
||||
Self {
|
||||
name: name.to_string(),
|
||||
description: description.to_string(),
|
||||
parameters,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,8 @@ use tokio::sync::Mutex;
|
||||
use tracing::{debug, instrument};
|
||||
|
||||
use super::agent::SessionConfig;
|
||||
use super::capabilities::get_parameter_names;
|
||||
use super::extension::ToolInfo;
|
||||
use super::Agent;
|
||||
use crate::agents::capabilities::Capabilities;
|
||||
use crate::agents::extension::{ExtensionConfig, ExtensionResult};
|
||||
@@ -243,6 +245,19 @@ impl Agent for ReferenceAgent {
|
||||
Err(anyhow!("Prompt '{}' not found", name))
|
||||
}
|
||||
|
||||
async fn get_plan_prompt(&self) -> anyhow::Result<String> {
|
||||
let mut capabilities = self.capabilities.lock().await;
|
||||
let tools = capabilities.get_prefixed_tools().await?;
|
||||
let tools_info = tools
|
||||
.into_iter()
|
||||
.map(|tool| ToolInfo::new(&tool.name, &tool.description, get_parameter_names(&tool)))
|
||||
.collect();
|
||||
|
||||
let plan_prompt = capabilities.get_planning_prompt(tools_info).await;
|
||||
|
||||
Ok(plan_prompt)
|
||||
}
|
||||
|
||||
async fn provider(&self) -> Arc<Box<dyn Provider>> {
|
||||
let capabilities = self.capabilities.lock().await;
|
||||
capabilities.provider()
|
||||
|
||||
@@ -10,7 +10,9 @@ use tokio::sync::Mutex;
|
||||
use tracing::{debug, error, instrument, warn};
|
||||
|
||||
use super::agent::SessionConfig;
|
||||
use super::capabilities::get_parameter_names;
|
||||
use super::detect_read_only_tools;
|
||||
use super::extension::ToolInfo;
|
||||
use super::Agent;
|
||||
use crate::agents::capabilities::Capabilities;
|
||||
use crate::agents::extension::{ExtensionConfig, ExtensionResult};
|
||||
@@ -457,6 +459,19 @@ impl Agent for SummarizeAgent {
|
||||
Err(anyhow!("Prompt '{}' not found", name))
|
||||
}
|
||||
|
||||
async fn get_plan_prompt(&self) -> anyhow::Result<String> {
|
||||
let mut capabilities = self.capabilities.lock().await;
|
||||
let tools = capabilities.get_prefixed_tools().await?;
|
||||
let tools_info = tools
|
||||
.into_iter()
|
||||
.map(|tool| ToolInfo::new(&tool.name, &tool.description, get_parameter_names(&tool)))
|
||||
.collect();
|
||||
|
||||
let plan_prompt = capabilities.get_planning_prompt(tools_info).await;
|
||||
|
||||
Ok(plan_prompt)
|
||||
}
|
||||
|
||||
async fn provider(&self) -> Arc<Box<dyn Provider>> {
|
||||
let capabilities = self.capabilities.lock().await;
|
||||
capabilities.provider()
|
||||
|
||||
@@ -10,8 +10,9 @@ use tracing::{debug, error, instrument, warn};
|
||||
|
||||
use super::agent::SessionConfig;
|
||||
use super::detect_read_only_tools;
|
||||
use super::extension::ToolInfo;
|
||||
use super::Agent;
|
||||
use crate::agents::capabilities::Capabilities;
|
||||
use crate::agents::capabilities::{get_parameter_names, Capabilities};
|
||||
use crate::agents::extension::{ExtensionConfig, ExtensionResult};
|
||||
use crate::agents::ToolPermissionStore;
|
||||
use crate::config::Config;
|
||||
@@ -511,6 +512,19 @@ impl Agent for TruncateAgent {
|
||||
Err(anyhow!("Prompt '{}' not found", name))
|
||||
}
|
||||
|
||||
async fn get_plan_prompt(&self) -> anyhow::Result<String> {
|
||||
let mut capabilities = self.capabilities.lock().await;
|
||||
let tools = capabilities.get_prefixed_tools().await?;
|
||||
let tools_info = tools
|
||||
.into_iter()
|
||||
.map(|tool| ToolInfo::new(&tool.name, &tool.description, get_parameter_names(&tool)))
|
||||
.collect();
|
||||
|
||||
let plan_prompt = capabilities.get_planning_prompt(tools_info).await;
|
||||
|
||||
Ok(plan_prompt)
|
||||
}
|
||||
|
||||
async fn provider(&self) -> Arc<Box<dyn Provider>> {
|
||||
let capabilities = self.capabilities.lock().await;
|
||||
capabilities.provider()
|
||||
|
||||
Reference in New Issue
Block a user