feat: Created new .tool enable/disable and .mcp enable/disable aliases to make REPL usage more egonomic
This commit is contained in:
@@ -1031,6 +1031,273 @@ impl RequestContext {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn concrete_tool_names(&self) -> Vec<String> {
|
||||||
|
self.tool_scope
|
||||||
|
.functions
|
||||||
|
.declarations()
|
||||||
|
.iter()
|
||||||
|
.filter(|v| {
|
||||||
|
!v.name.starts_with("user__")
|
||||||
|
&& !v.name.starts_with("mcp_")
|
||||||
|
&& !v.name.starts_with("todo__")
|
||||||
|
&& !v.name.starts_with("agent__")
|
||||||
|
})
|
||||||
|
.map(|v| v.name.clone())
|
||||||
|
.collect()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tool_list_covers(&self, list: &[String], name: &str) -> bool {
|
||||||
|
for item in list {
|
||||||
|
let item = item.trim();
|
||||||
|
if item == name {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(values) = self.app.config.mapping_tools.get(item)
|
||||||
|
&& values.split(',').any(|v| v.trim() == name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn mcp_list_covers(&self, list: &[String], name: &str) -> bool {
|
||||||
|
for item in list {
|
||||||
|
let item = item.trim();
|
||||||
|
if item == name {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(values) = self.app.config.mapping_mcp_servers.get(item)
|
||||||
|
&& values.split(',').any(|v| v.trim() == name)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_layer_label(&self) -> &'static str {
|
||||||
|
if self.session.is_some() {
|
||||||
|
"session"
|
||||||
|
} else if self.agent.is_some() {
|
||||||
|
"agent"
|
||||||
|
} else if self.role.is_some() {
|
||||||
|
"role"
|
||||||
|
} else {
|
||||||
|
"global, in-memory"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn toggle_tool(&mut self, action: &str, name: &str) -> Result<()> {
|
||||||
|
let name = name.trim();
|
||||||
|
let enable = match action {
|
||||||
|
"enable" => true,
|
||||||
|
"disable" => false,
|
||||||
|
_ => bail!("Unknown action '{action}'. Usage: .tool <enable|disable> <name>"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.session.is_none() && self.agent.is_some() {
|
||||||
|
bail!(
|
||||||
|
"Cannot adjust tools for an agent outside a session; start a session first with `.session`"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let pool = self.concrete_tool_names();
|
||||||
|
let is_alias = self.app.config.mapping_tools.contains_key(name);
|
||||||
|
if !pool.iter().any(|v| v == name) && !is_alias {
|
||||||
|
bail!("Unknown tool '{name}'. Run `.list tools` to see what's available");
|
||||||
|
}
|
||||||
|
|
||||||
|
let current: Option<Vec<String>> = if let Some(session) = &self.session {
|
||||||
|
session.enabled_tools()
|
||||||
|
} else if let Some(role) = &self.role {
|
||||||
|
role.enabled_tools()
|
||||||
|
} else {
|
||||||
|
self.app.config.enabled_tools.clone()
|
||||||
|
};
|
||||||
|
let layer = self.write_layer_label();
|
||||||
|
|
||||||
|
let new_list: Vec<String> = if enable {
|
||||||
|
match current {
|
||||||
|
Some(list) if list.iter().any(|s| s.trim() == "all") => {
|
||||||
|
println!("Tool '{name}' is already enabled ('all' is set).");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if self.tool_list_covers(&list, name) => {
|
||||||
|
println!("Tool '{name}' is already enabled.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(mut list) => {
|
||||||
|
list.push(name.to_string());
|
||||||
|
list
|
||||||
|
}
|
||||||
|
None => vec![name.to_string()],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match current {
|
||||||
|
None => {
|
||||||
|
println!("No tools are enabled in this context; nothing to disable.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if list.is_empty() => {
|
||||||
|
println!("No tools are enabled in this context; nothing to disable.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if list.iter().any(|s| s.trim() == "all") => {
|
||||||
|
let mut materialized = pool;
|
||||||
|
materialized.retain(|v| v != name);
|
||||||
|
println!(
|
||||||
|
"Note: expanded 'all' into {} concrete tools.",
|
||||||
|
materialized.len()
|
||||||
|
);
|
||||||
|
materialized
|
||||||
|
}
|
||||||
|
Some(mut list) => {
|
||||||
|
if list.iter().any(|s| s.trim() == name) {
|
||||||
|
list.retain(|s| s.trim() != name);
|
||||||
|
list
|
||||||
|
} else if self.tool_list_covers(&list, name) {
|
||||||
|
bail!(
|
||||||
|
"Tool '{name}' is enabled via an alias in 'mapping_tools'. \
|
||||||
|
Disable the alias instead, or set the list explicitly with `.set enabled_tools`."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("Tool '{name}' is not enabled; nothing to do.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let new_list = Some(new_list);
|
||||||
|
|
||||||
|
if !self.set_enabled_tools_on_role_like(new_list.clone()) {
|
||||||
|
self.update_app_config(|app| app.enabled_tools = new_list.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
let verb = if enable { "Enabled" } else { "Disabled" };
|
||||||
|
println!("✓ {verb} tool '{name}' ({layer}).");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn toggle_mcp_server(
|
||||||
|
&mut self,
|
||||||
|
action: &str,
|
||||||
|
name: &str,
|
||||||
|
abort_signal: AbortSignal,
|
||||||
|
) -> Result<()> {
|
||||||
|
let name = name.trim();
|
||||||
|
let enable = match action {
|
||||||
|
"enable" => true,
|
||||||
|
"disable" => false,
|
||||||
|
_ => bail!("Unknown action '{action}'. Usage: .mcp <enable|disable> <server_name>"),
|
||||||
|
};
|
||||||
|
|
||||||
|
if self.agent.is_some() {
|
||||||
|
bail!(
|
||||||
|
"Agent MCP servers are defined by the agent's config ('mcp_servers'); \
|
||||||
|
edit the agent config with `.edit agent-config` instead."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let configured_keys: Vec<String> = match &self.app.mcp_config {
|
||||||
|
Some(mcp_config) if !mcp_config.mcp_servers.is_empty() => {
|
||||||
|
mcp_config.mcp_servers.keys().cloned().collect()
|
||||||
|
}
|
||||||
|
_ => bail!("No MCP servers are configured. Please configure MCP servers first."),
|
||||||
|
};
|
||||||
|
let is_alias = self.app.config.mapping_mcp_servers.contains_key(name);
|
||||||
|
if !configured_keys.iter().any(|v| v == name) && !is_alias {
|
||||||
|
bail!(
|
||||||
|
"MCP server '{name}' is not configured. Run `.list mcp-servers` to see what's available"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let current: Option<Vec<String>> = if let Some(session) = &self.session {
|
||||||
|
session.enabled_mcp_servers()
|
||||||
|
} else if let Some(role) = &self.role {
|
||||||
|
role.enabled_mcp_servers()
|
||||||
|
} else {
|
||||||
|
self.app.config.enabled_mcp_servers.clone()
|
||||||
|
};
|
||||||
|
let layer = self.write_layer_label();
|
||||||
|
|
||||||
|
let new_list: Vec<String> = if enable {
|
||||||
|
match current {
|
||||||
|
Some(list) if list.iter().any(|s| s.trim() == "all") => {
|
||||||
|
println!("MCP server '{name}' is already enabled ('all' is set).");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if self.mcp_list_covers(&list, name) => {
|
||||||
|
println!("MCP server '{name}' is already enabled.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(mut list) => {
|
||||||
|
list.push(name.to_string());
|
||||||
|
list
|
||||||
|
}
|
||||||
|
None => vec![name.to_string()],
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
match current {
|
||||||
|
None => {
|
||||||
|
println!("No MCP servers are enabled in this context; nothing to disable.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if list.is_empty() => {
|
||||||
|
println!("No MCP servers are enabled in this context; nothing to disable.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
Some(list) if list.iter().any(|s| s.trim() == "all") => {
|
||||||
|
let mut materialized = configured_keys;
|
||||||
|
materialized.retain(|v| v != name);
|
||||||
|
materialized
|
||||||
|
}
|
||||||
|
Some(mut list) => {
|
||||||
|
if list.iter().any(|s| s.trim() == name) {
|
||||||
|
list.retain(|s| s.trim() != name);
|
||||||
|
list
|
||||||
|
} else if self.mcp_list_covers(&list, name) {
|
||||||
|
bail!(
|
||||||
|
"MCP server '{name}' is enabled via an alias in 'mapping_mcp_servers'. \
|
||||||
|
Disable the alias instead, or set the list explicitly with `.set enabled_mcp_servers`."
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
println!("MCP server '{name}' is not enabled; nothing to do.");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
if !enable && self.skill_registry.loaded_mcp_servers().contains(name) {
|
||||||
|
println!(
|
||||||
|
"Note: '{name}' is granted by a loaded skill and will keep running until that skill is unloaded."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
let new_list = Some(new_list);
|
||||||
|
if !self.set_enabled_mcp_servers_on_role_like(new_list.clone()) {
|
||||||
|
self.update_app_config(|app| app.enabled_mcp_servers = new_list.clone());
|
||||||
|
}
|
||||||
|
|
||||||
|
if self.app.config.mcp_server_support {
|
||||||
|
let app = Arc::clone(&self.app.config);
|
||||||
|
self.bootstrap_tools(app.as_ref(), true, abort_signal)
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
let verb = if enable { "Enabled" } else { "Disabled" };
|
||||||
|
println!("✓ {verb} MCP server '{name}' ({layer}).");
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
pub fn set_save_session_on_session(&mut self, value: Option<bool>) -> bool {
|
pub fn set_save_session_on_session(&mut self, value: Option<bool>) -> bool {
|
||||||
match self.session.as_mut() {
|
match self.session.as_mut() {
|
||||||
Some(session) => {
|
Some(session) => {
|
||||||
@@ -2021,8 +2288,45 @@ impl RequestContext {
|
|||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
"tools" => {
|
||||||
|
let mut names: Vec<String> = self
|
||||||
|
.tool_scope
|
||||||
|
.functions
|
||||||
|
.declarations()
|
||||||
|
.iter()
|
||||||
|
.filter(|v| {
|
||||||
|
!v.name.starts_with("user__")
|
||||||
|
&& !v.name.starts_with("mcp_")
|
||||||
|
&& !v.name.starts_with("todo__")
|
||||||
|
&& !v.name.starts_with("agent__")
|
||||||
|
})
|
||||||
|
.map(|v| v.name.clone())
|
||||||
|
.collect();
|
||||||
|
names.extend(self.app.config.mapping_tools.keys().map(|v| v.to_string()));
|
||||||
|
names.sort_unstable();
|
||||||
|
names.dedup();
|
||||||
|
|
||||||
|
print_asset_names("tools", &names)
|
||||||
|
}
|
||||||
|
"mcp-servers" => {
|
||||||
|
let mut names: Vec<String> = vec![];
|
||||||
|
if let Some(mcp_config) = &self.app.mcp_config {
|
||||||
|
names.extend(mcp_config.mcp_servers.keys().map(|v| v.to_string()));
|
||||||
|
}
|
||||||
|
names.extend(
|
||||||
|
self.app
|
||||||
|
.config
|
||||||
|
.mapping_mcp_servers
|
||||||
|
.keys()
|
||||||
|
.map(|v| v.to_string()),
|
||||||
|
);
|
||||||
|
names.sort_unstable();
|
||||||
|
names.dedup();
|
||||||
|
|
||||||
|
print_asset_names("MCP servers", &names)
|
||||||
|
}
|
||||||
_ => bail!(
|
_ => bail!(
|
||||||
"Unknown kind '{kind}'. Valid kinds: roles, sessions, agents, rags, macros, skills"
|
"Unknown kind '{kind}'. Valid kinds: roles, sessions, agents, rags, macros, skills, tools, mcp-servers"
|
||||||
),
|
),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2517,7 +2821,14 @@ impl RequestContext {
|
|||||||
"agent-data",
|
"agent-data",
|
||||||
]),
|
]),
|
||||||
".list" => super::map_completion_values(vec![
|
".list" => super::map_completion_values(vec![
|
||||||
"roles", "sessions", "agents", "rags", "macros", "skills",
|
"roles",
|
||||||
|
"sessions",
|
||||||
|
"agents",
|
||||||
|
"rags",
|
||||||
|
"macros",
|
||||||
|
"skills",
|
||||||
|
"tools",
|
||||||
|
"mcp-servers",
|
||||||
]),
|
]),
|
||||||
".vault" => {
|
".vault" => {
|
||||||
let mut values = vec!["add", "get", "update", "delete", "list"];
|
let mut values = vec!["add", "get", "update", "delete", "list"];
|
||||||
@@ -2540,6 +2851,85 @@ impl RequestContext {
|
|||||||
.collect(),
|
.collect(),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if cmd == ".mcp"
|
||||||
|
&& (args.first() == Some(&"enable") || args.first() == Some(&"disable"))
|
||||||
|
&& args.len() == 2
|
||||||
|
{
|
||||||
|
let current = if let Some(session) = &self.session {
|
||||||
|
session.enabled_mcp_servers()
|
||||||
|
} else if let Some(role) = &self.role {
|
||||||
|
role.enabled_mcp_servers()
|
||||||
|
} else {
|
||||||
|
self.app.config.enabled_mcp_servers.clone()
|
||||||
|
}
|
||||||
|
.unwrap_or_default();
|
||||||
|
let has_all = current.iter().any(|s| s.trim() == "all");
|
||||||
|
|
||||||
|
let candidates: Vec<String> = if args.first() == Some(&"enable") {
|
||||||
|
if has_all {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
let mut candidates: Vec<String> = vec![];
|
||||||
|
if let Some(mcp_config) = &self.app.mcp_config {
|
||||||
|
candidates.extend(mcp_config.mcp_servers.keys().cloned());
|
||||||
|
}
|
||||||
|
candidates.extend(self.app.config.mapping_mcp_servers.keys().cloned());
|
||||||
|
candidates.sort_unstable();
|
||||||
|
candidates.dedup();
|
||||||
|
candidates.retain(|v| !self.mcp_list_covers(¤t, v));
|
||||||
|
|
||||||
|
candidates
|
||||||
|
}
|
||||||
|
} else if has_all {
|
||||||
|
self.app
|
||||||
|
.mcp_config
|
||||||
|
.as_ref()
|
||||||
|
.map(|c| c.mcp_servers.keys().cloned().collect())
|
||||||
|
.unwrap_or_default()
|
||||||
|
} else {
|
||||||
|
current
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.trim().to_string())
|
||||||
|
.filter(|s| s != "all" && !s.is_empty())
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
values = super::map_completion_values(candidates);
|
||||||
|
} else if cmd == ".tool"
|
||||||
|
&& (args.first() == Some(&"enable") || args.first() == Some(&"disable"))
|
||||||
|
&& args.len() == 2
|
||||||
|
{
|
||||||
|
let current = if let Some(session) = &self.session {
|
||||||
|
session.enabled_tools()
|
||||||
|
} else if let Some(role) = &self.role {
|
||||||
|
role.enabled_tools()
|
||||||
|
} else {
|
||||||
|
self.app.config.enabled_tools.clone()
|
||||||
|
}
|
||||||
|
.unwrap_or_default();
|
||||||
|
let has_all = current.iter().any(|s| s.trim() == "all");
|
||||||
|
|
||||||
|
let candidates: Vec<String> = if args.first() == Some(&"enable") {
|
||||||
|
if has_all {
|
||||||
|
vec![]
|
||||||
|
} else {
|
||||||
|
let mut candidates = self.concrete_tool_names();
|
||||||
|
candidates.extend(self.app.config.mapping_tools.keys().cloned());
|
||||||
|
candidates.sort_unstable();
|
||||||
|
candidates.dedup();
|
||||||
|
candidates.retain(|v| !self.tool_list_covers(¤t, v));
|
||||||
|
|
||||||
|
candidates
|
||||||
|
}
|
||||||
|
} else if has_all {
|
||||||
|
self.concrete_tool_names()
|
||||||
|
} else {
|
||||||
|
current
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.trim().to_string())
|
||||||
|
.filter(|s| s != "all" && !s.is_empty())
|
||||||
|
.collect()
|
||||||
|
};
|
||||||
|
values = super::map_completion_values(candidates);
|
||||||
} else if (cmd == ".edit" && args.first() == Some(&"skill") && args.len() == 2)
|
} else if (cmd == ".edit" && args.first() == Some(&"skill") && args.len() == 2)
|
||||||
|| (cmd == ".skill" && args.first() == Some(&"load") && args.len() == 2)
|
|| (cmd == ".skill" && args.first() == Some(&"load") && args.len() == 2)
|
||||||
{
|
{
|
||||||
|
|||||||
+63
-6
@@ -52,7 +52,7 @@ pub const DEFAULT_CONTINUATION_PROMPT: &str = indoc! {"
|
|||||||
4. Continue with the next pending item now. Call tools immediately."
|
4. Continue with the next pending item now. Call tools immediately."
|
||||||
};
|
};
|
||||||
|
|
||||||
static REPL_COMMANDS: LazyLock<[ReplCommand; 53]> = LazyLock::new(|| {
|
static REPL_COMMANDS: LazyLock<[ReplCommand; 57]> = LazyLock::new(|| {
|
||||||
[
|
[
|
||||||
ReplCommand::new(".help", "Show this help guide", AssertState::pass()),
|
ReplCommand::new(".help", "Show this help guide", AssertState::pass()),
|
||||||
ReplCommand::new(".info", "Show system info", AssertState::pass()),
|
ReplCommand::new(".info", "Show system info", AssertState::pass()),
|
||||||
@@ -71,6 +71,26 @@ static REPL_COMMANDS: LazyLock<[ReplCommand; 53]> = LazyLock::new(|| {
|
|||||||
"Authenticate with an MCP server via OAuth",
|
"Authenticate with an MCP server via OAuth",
|
||||||
AssertState::pass(),
|
AssertState::pass(),
|
||||||
),
|
),
|
||||||
|
ReplCommand::new(
|
||||||
|
".mcp enable",
|
||||||
|
"Enable a single MCP server in the current context",
|
||||||
|
AssertState::pass(),
|
||||||
|
),
|
||||||
|
ReplCommand::new(
|
||||||
|
".mcp disable",
|
||||||
|
"Disable a single MCP server in the current context",
|
||||||
|
AssertState::pass(),
|
||||||
|
),
|
||||||
|
ReplCommand::new(
|
||||||
|
".tool enable",
|
||||||
|
"Enable a single tool in the current context",
|
||||||
|
AssertState::True(StateFlags::FUNCTION_CALLING),
|
||||||
|
),
|
||||||
|
ReplCommand::new(
|
||||||
|
".tool disable",
|
||||||
|
"Disable a single tool in the current context",
|
||||||
|
AssertState::True(StateFlags::FUNCTION_CALLING),
|
||||||
|
),
|
||||||
ReplCommand::new(
|
ReplCommand::new(
|
||||||
".edit config",
|
".edit config",
|
||||||
"Modify configuration file",
|
"Modify configuration file",
|
||||||
@@ -271,7 +291,7 @@ static REPL_COMMANDS: LazyLock<[ReplCommand; 53]> = LazyLock::new(|| {
|
|||||||
),
|
),
|
||||||
ReplCommand::new(
|
ReplCommand::new(
|
||||||
".list",
|
".list",
|
||||||
"List roles, sessions, agents, RAGs, macros, or skills",
|
"List roles, sessions, agents, RAGs, macros, skills, tools, or MCP servers",
|
||||||
AssertState::pass(),
|
AssertState::pass(),
|
||||||
),
|
),
|
||||||
ReplCommand::new(
|
ReplCommand::new(
|
||||||
@@ -682,10 +702,45 @@ pub async fn run_repl_command(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
"enable" | "disable" => {
|
||||||
|
if rest.is_empty() {
|
||||||
|
println!("Usage: .mcp {sub} <server_name>");
|
||||||
|
} else {
|
||||||
|
ctx.toggle_mcp_server(sub, rest, abort_signal.clone())
|
||||||
|
.await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
_ => unknown_command()?,
|
_ => unknown_command()?,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
None => println!("Usage: .mcp auth <server_name>"),
|
None => println!(
|
||||||
|
r#"Usage:
|
||||||
|
.mcp auth <server_name> # Authenticate with an MCP server via OAuth
|
||||||
|
.mcp enable <server_name> # Enable a single MCP server in the current context
|
||||||
|
.mcp disable <server_name> # Disable a single MCP server in the current context"#
|
||||||
|
),
|
||||||
|
},
|
||||||
|
".tool" => match args {
|
||||||
|
Some(args) => {
|
||||||
|
let mut parts = args.splitn(2, char::is_whitespace);
|
||||||
|
let sub = parts.next().unwrap_or("").trim();
|
||||||
|
let rest = parts.next().map(str::trim).unwrap_or("");
|
||||||
|
match sub {
|
||||||
|
"enable" | "disable" => {
|
||||||
|
if rest.is_empty() {
|
||||||
|
println!("Usage: .tool {sub} <name>");
|
||||||
|
} else {
|
||||||
|
ctx.toggle_tool(sub, rest)?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
_ => unknown_command()?,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None => println!(
|
||||||
|
r#"Usage:
|
||||||
|
.tool enable <name> # Enable a single tool in the current context
|
||||||
|
.tool disable <name> # Disable a single tool in the current context"#
|
||||||
|
),
|
||||||
},
|
},
|
||||||
".prompt" => match args {
|
".prompt" => match args {
|
||||||
Some(text) => {
|
Some(text) => {
|
||||||
@@ -1102,7 +1157,9 @@ pub async fn run_repl_command(
|
|||||||
ctx.list_assets(args.trim())?;
|
ctx.list_assets(args.trim())?;
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
println!("Usage: .list <roles|sessions|agents|rags|macros|skills>")
|
println!(
|
||||||
|
"Usage: .list <roles|sessions|agents|rags|macros|skills|tools|mcp-servers>"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
".copy" => {
|
".copy" => {
|
||||||
@@ -1627,8 +1684,8 @@ mod tests {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn repl_commands_has_53_entries() {
|
fn repl_commands_has_57_entries() {
|
||||||
assert_eq!(REPL_COMMANDS.len(), 53);
|
assert_eq!(REPL_COMMANDS.len(), 57);
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
|
|||||||
Reference in New Issue
Block a user