refactor: support both CSV and list formats for enabled_tools
This commit is contained in:
+8
-1
@@ -82,7 +82,14 @@ vault_password_file: null # Path to a file containing the password for th
|
||||
function_calling_support: true # Enables or disables function calling (Globally).
|
||||
mapping_tools: # Alias for a tool or toolset
|
||||
fs: 'fs_cat,fs_ls,fs_mkdir,fs_rm,fs_write,fs_read,fs_glob,fs_grep'
|
||||
enabled_tools: null # Which tools to enable by default. (e.g. 'fs,web_search_coyote')
|
||||
enabled_tools: null # Which tools to enable by default.
|
||||
# Accepts either a YAML list or a comma-separated string. Use 'all' to enable everything.
|
||||
# Example (list form):
|
||||
# enabled_tools:
|
||||
# - fs
|
||||
# - web_search_coyote
|
||||
# Example (comma-separated form):
|
||||
# enabled_tools: fs,web_search_coyote
|
||||
visible_tools: # Which tools are visible to be compiled (and are thus able to be defined in 'enabled_tools')
|
||||
# - demo_py.py
|
||||
# - demo_sh.sh
|
||||
|
||||
@@ -8,7 +8,9 @@ name: <role-name> # The name of the role
|
||||
model: openai:gpt-4o # The model to use for this role
|
||||
temperature: 0.2 # The temperature to use for this role when querying the model
|
||||
top_p: 0 # The top_p to use for this role when querying the model
|
||||
enabled_tools: fs_ls,fs_cat # A comma-separated list of tools to enable for this role
|
||||
enabled_tools: # Tools to enable for this role. Accepts a YAML list (preferred)
|
||||
- fs_ls # or a comma-separated string (e.g. `enabled_tools: fs_ls,fs_cat`).
|
||||
- fs_cat # Use `all` to enable every visible tool.
|
||||
enabled_mcp_servers: # MCP servers to enable for this role. Accepts a YAML list (preferred)
|
||||
- github # or a comma-separated string (e.g. `enabled_mcp_servers: github,gitmcp`).
|
||||
- gitmcp # Use `all` to enable every configured MCP server.
|
||||
|
||||
+4
-5
@@ -548,7 +548,7 @@ impl RoleLike for Agent {
|
||||
self.config.top_p
|
||||
}
|
||||
|
||||
fn enabled_tools(&self) -> Option<String> {
|
||||
fn enabled_tools(&self) -> Option<Vec<String>> {
|
||||
None
|
||||
}
|
||||
|
||||
@@ -569,15 +569,14 @@ impl RoleLike for Agent {
|
||||
self.config.top_p = value;
|
||||
}
|
||||
|
||||
fn set_enabled_tools(&mut self, value: Option<String>) {
|
||||
fn set_enabled_tools(&mut self, value: Option<Vec<String>>) {
|
||||
match value {
|
||||
Some(tools) => {
|
||||
let tools = tools
|
||||
.split(',')
|
||||
self.config.global_tools = tools
|
||||
.into_iter()
|
||||
.map(|v| v.trim().to_string())
|
||||
.filter(|v| !v.is_empty())
|
||||
.collect::<Vec<_>>();
|
||||
self.config.global_tools = tools;
|
||||
}
|
||||
None => {
|
||||
self.config.global_tools.clear();
|
||||
|
||||
@@ -34,7 +34,8 @@ pub struct AppConfig {
|
||||
|
||||
pub function_calling_support: bool,
|
||||
pub mapping_tools: IndexMap<String, String>,
|
||||
pub enabled_tools: Option<String>,
|
||||
#[serde(default, deserialize_with = "super::deserialize_csv_or_vec")]
|
||||
pub enabled_tools: Option<Vec<String>>,
|
||||
pub visible_tools: Option<Vec<String>>,
|
||||
|
||||
pub skills_enabled: bool,
|
||||
@@ -394,7 +395,7 @@ impl AppConfig {
|
||||
self.mapping_tools = v;
|
||||
}
|
||||
if let Some(v) = super::read_env_value::<String>(&get_env_name("enabled_tools")) {
|
||||
self.enabled_tools = v;
|
||||
self.enabled_tools = v.map(|raw| super::csv_to_vec(&raw));
|
||||
}
|
||||
|
||||
if let Some(Some(v)) = super::read_env_bool(&get_env_name("skills_enabled")) {
|
||||
@@ -516,7 +517,7 @@ impl AppConfig {
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn set_enabled_tools_default(&mut self, value: Option<String>) {
|
||||
pub fn set_enabled_tools_default(&mut self, value: Option<Vec<String>>) {
|
||||
self.enabled_tools = value;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,7 +33,7 @@ pub async fn macro_execute(
|
||||
let mut app_config = (*ctx.app.config).clone();
|
||||
app_config.temperature = role.temperature();
|
||||
app_config.top_p = role.top_p();
|
||||
app_config.enabled_tools = role.enabled_tools().clone();
|
||||
app_config.enabled_tools = role.enabled_tools();
|
||||
app_config.enabled_mcp_servers = role.enabled_mcp_servers();
|
||||
|
||||
let mut app_state = (*ctx.app).clone();
|
||||
|
||||
+2
-1
@@ -196,7 +196,8 @@ pub struct Config {
|
||||
|
||||
pub function_calling_support: bool,
|
||||
pub mapping_tools: IndexMap<String, String>,
|
||||
pub enabled_tools: Option<String>,
|
||||
#[serde(default, deserialize_with = "deserialize_csv_or_vec")]
|
||||
pub enabled_tools: Option<Vec<String>>,
|
||||
pub visible_tools: Option<Vec<String>>,
|
||||
|
||||
pub skills_enabled: bool,
|
||||
|
||||
@@ -700,7 +700,7 @@ impl RequestContext {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn set_enabled_tools_on_role_like(&mut self, value: Option<String>) -> bool {
|
||||
pub fn set_enabled_tools_on_role_like(&mut self, value: Option<Vec<String>>) -> bool {
|
||||
match self.role_like_mut() {
|
||||
Some(role_like) => {
|
||||
role_like.set_enabled_tools(value);
|
||||
@@ -854,7 +854,7 @@ impl RequestContext {
|
||||
("top_p", super::format_option_value(&role.top_p())),
|
||||
(
|
||||
"enabled_tools",
|
||||
super::format_option_value(&role.enabled_tools()),
|
||||
super::format_option_value(&role.enabled_tools().map(|v| v.join(","))),
|
||||
),
|
||||
(
|
||||
"enabled_mcp_servers",
|
||||
@@ -1148,10 +1148,10 @@ impl RequestContext {
|
||||
}
|
||||
|
||||
let mut tool_names: HashSet<String> = Default::default();
|
||||
if enabled_tools == "all" {
|
||||
if enabled_tools.iter().any(|s| s.trim() == "all") {
|
||||
tool_names.extend(declaration_names);
|
||||
} else {
|
||||
for item in enabled_tools.split(',') {
|
||||
for item in enabled_tools.iter() {
|
||||
let item = item.trim();
|
||||
if item.is_empty() {
|
||||
continue;
|
||||
@@ -1714,9 +1714,10 @@ impl RequestContext {
|
||||
}
|
||||
}
|
||||
"enabled_tools" => {
|
||||
let value = super::parse_value(value)?;
|
||||
if !self.set_enabled_tools_on_role_like(value.clone()) {
|
||||
self.update_app_config(|app| app.enabled_tools = value);
|
||||
let raw: Option<String> = super::parse_value(value)?;
|
||||
let parsed: Option<Vec<String>> = raw.map(|s| super::csv_to_vec(&s));
|
||||
if !self.set_enabled_tools_on_role_like(parsed.clone()) {
|
||||
self.update_app_config(|app| app.enabled_tools = parsed.clone());
|
||||
}
|
||||
}
|
||||
"enabled_skills" => {
|
||||
@@ -3366,7 +3367,7 @@ mod tests {
|
||||
};
|
||||
let ctx = RequestContext::new(app_state, WorkingMode::Cmd);
|
||||
let mut role = Role::new("r", "p");
|
||||
role.set_enabled_tools(Some("all".to_string()));
|
||||
role.set_enabled_tools(Some(vec!["all".to_string()]));
|
||||
assert!(ctx.select_functions(&role).is_none());
|
||||
}
|
||||
|
||||
@@ -3377,7 +3378,7 @@ mod tests {
|
||||
ctx.tool_scope.functions.append_user_interaction_functions();
|
||||
|
||||
let mut role = Role::new("r", "p");
|
||||
role.set_enabled_tools(Some("all".to_string()));
|
||||
role.set_enabled_tools(Some(vec!["all".to_string()]));
|
||||
|
||||
let fns = ctx.select_functions(&role).unwrap();
|
||||
let names: Vec<&str> = fns.iter().map(|f| f.name.as_str()).collect();
|
||||
@@ -3391,7 +3392,7 @@ mod tests {
|
||||
ctx.tool_scope.functions.append_todo_functions();
|
||||
|
||||
let mut role = Role::new("r", "p");
|
||||
role.set_enabled_tools(Some("todo__init, todo__add".to_string()));
|
||||
role.set_enabled_tools(Some(vec!["todo__init".to_string(), "todo__add".to_string()]));
|
||||
|
||||
let fns = ctx.select_functions(&role).unwrap();
|
||||
let names: Vec<&str> = fns.iter().map(|f| f.name.as_str()).collect();
|
||||
|
||||
+20
-11
@@ -28,12 +28,12 @@ pub trait RoleLike {
|
||||
fn model(&self) -> &Model;
|
||||
fn temperature(&self) -> Option<f64>;
|
||||
fn top_p(&self) -> Option<f64>;
|
||||
fn enabled_tools(&self) -> Option<String>;
|
||||
fn enabled_tools(&self) -> Option<Vec<String>>;
|
||||
fn enabled_mcp_servers(&self) -> Option<Vec<String>>;
|
||||
fn set_model(&mut self, model: Model);
|
||||
fn set_temperature(&mut self, value: Option<f64>);
|
||||
fn set_top_p(&mut self, value: Option<f64>);
|
||||
fn set_enabled_tools(&mut self, value: Option<String>);
|
||||
fn set_enabled_tools(&mut self, value: Option<Vec<String>>);
|
||||
fn set_enabled_mcp_servers(&mut self, value: Option<Vec<String>>);
|
||||
}
|
||||
|
||||
@@ -51,8 +51,12 @@ pub struct Role {
|
||||
temperature: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
top_p: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
enabled_tools: Option<String>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "super::deserialize_csv_or_vec"
|
||||
)]
|
||||
enabled_tools: Option<Vec<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
@@ -106,7 +110,7 @@ impl Role {
|
||||
"model" => role.model_id = value.as_str().map(|v| v.to_string()),
|
||||
"temperature" => role.temperature = value.as_f64(),
|
||||
"top_p" => role.top_p = value.as_f64(),
|
||||
"enabled_tools" => role.enabled_tools = value.as_str().map(|v| v.to_string()),
|
||||
"enabled_tools" => role.enabled_tools = parse_string_or_array(value),
|
||||
"enabled_mcp_servers" => {
|
||||
role.enabled_mcp_servers = parse_string_or_array(value)
|
||||
}
|
||||
@@ -155,8 +159,10 @@ impl Role {
|
||||
if let Some(top_p) = self.top_p() {
|
||||
metadata.push(format!("top_p: {top_p}"));
|
||||
}
|
||||
if let Some(enabled_tools) = self.enabled_tools() {
|
||||
metadata.push(format!("enabled_tools: {enabled_tools}"));
|
||||
if let Some(enabled_tools) = &self.enabled_tools {
|
||||
let inline =
|
||||
serde_json::to_string(enabled_tools).unwrap_or_else(|_| "[]".to_string());
|
||||
metadata.push(format!("enabled_tools: {inline}"));
|
||||
}
|
||||
if let Some(enabled_mcp_servers) = &self.enabled_mcp_servers {
|
||||
let inline =
|
||||
@@ -236,7 +242,7 @@ impl Role {
|
||||
model: &Model,
|
||||
temperature: Option<f64>,
|
||||
top_p: Option<f64>,
|
||||
enabled_tools: Option<String>,
|
||||
enabled_tools: Option<Vec<String>>,
|
||||
enabled_mcp_servers: Option<Vec<String>>,
|
||||
) {
|
||||
self.set_model(model.clone());
|
||||
@@ -371,7 +377,7 @@ impl RoleLike for Role {
|
||||
self.top_p
|
||||
}
|
||||
|
||||
fn enabled_tools(&self) -> Option<String> {
|
||||
fn enabled_tools(&self) -> Option<Vec<String>> {
|
||||
self.enabled_tools.clone()
|
||||
}
|
||||
|
||||
@@ -394,7 +400,7 @@ impl RoleLike for Role {
|
||||
self.top_p = value;
|
||||
}
|
||||
|
||||
fn set_enabled_tools(&mut self, value: Option<String>) {
|
||||
fn set_enabled_tools(&mut self, value: Option<Vec<String>>) {
|
||||
self.enabled_tools = value;
|
||||
}
|
||||
|
||||
@@ -499,7 +505,10 @@ mod tests {
|
||||
fn role_new_parses_enabled_tools() {
|
||||
let content = "---\nenabled_tools: tool1,tool2\n---\nPrompt";
|
||||
let role = Role::new("test", content);
|
||||
assert_eq!(role.enabled_tools(), Some("tool1,tool2".to_string()));
|
||||
assert_eq!(
|
||||
role.enabled_tools(),
|
||||
Some(vec!["tool1".to_string(), "tool2".to_string()])
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+10
-6
@@ -24,8 +24,12 @@ pub struct Session {
|
||||
temperature: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
top_p: Option<f64>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
enabled_tools: Option<String>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
deserialize_with = "super::deserialize_csv_or_vec"
|
||||
)]
|
||||
enabled_tools: Option<Vec<String>>,
|
||||
#[serde(
|
||||
default,
|
||||
skip_serializing_if = "Option::is_none",
|
||||
@@ -197,7 +201,7 @@ impl Session {
|
||||
data["top_p"] = top_p.into();
|
||||
}
|
||||
if let Some(enabled_tools) = self.enabled_tools() {
|
||||
data["enabled_tools"] = enabled_tools.into();
|
||||
data["enabled_tools"] = json!(enabled_tools);
|
||||
}
|
||||
if let Some(enabled_mcp_servers) = self.enabled_mcp_servers() {
|
||||
data["enabled_mcp_servers"] = json!(enabled_mcp_servers);
|
||||
@@ -263,7 +267,7 @@ impl Session {
|
||||
}
|
||||
|
||||
if let Some(enabled_tools) = self.enabled_tools() {
|
||||
items.push(("enabled_tools", enabled_tools));
|
||||
items.push(("enabled_tools", enabled_tools.join(",")));
|
||||
}
|
||||
|
||||
if let Some(enabled_mcp_servers) = self.enabled_mcp_servers() {
|
||||
@@ -711,7 +715,7 @@ impl RoleLike for Session {
|
||||
self.top_p
|
||||
}
|
||||
|
||||
fn enabled_tools(&self) -> Option<String> {
|
||||
fn enabled_tools(&self) -> Option<Vec<String>> {
|
||||
self.enabled_tools.clone()
|
||||
}
|
||||
|
||||
@@ -742,7 +746,7 @@ impl RoleLike for Session {
|
||||
}
|
||||
}
|
||||
|
||||
fn set_enabled_tools(&mut self, value: Option<String>) {
|
||||
fn set_enabled_tools(&mut self, value: Option<Vec<String>>) {
|
||||
if self.enabled_tools != value {
|
||||
self.enabled_tools = value;
|
||||
self.dirty = true;
|
||||
|
||||
+7
-4
@@ -33,7 +33,7 @@ pub struct Skill {
|
||||
#[serde(default)]
|
||||
body: String,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
enabled_tools: Option<String>,
|
||||
enabled_tools: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
enabled_mcp_servers: Option<Vec<String>>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
@@ -69,7 +69,7 @@ impl Skill {
|
||||
}
|
||||
}
|
||||
"enabled_tools" => {
|
||||
skill.enabled_tools = value.as_str().map(|v| v.to_string());
|
||||
skill.enabled_tools = parse_skill_string_or_array(value);
|
||||
}
|
||||
"enabled_mcp_servers" => {
|
||||
skill.enabled_mcp_servers = parse_skill_string_or_array(value);
|
||||
@@ -134,7 +134,7 @@ impl Skill {
|
||||
&self.body
|
||||
}
|
||||
|
||||
pub fn enabled_tools(&self) -> Option<&str> {
|
||||
pub fn enabled_tools(&self) -> Option<&[String]> {
|
||||
self.enabled_tools.as_deref()
|
||||
}
|
||||
|
||||
@@ -207,7 +207,10 @@ mod tests {
|
||||
|
||||
assert_eq!(skill.name(), "git-master");
|
||||
assert_eq!(skill.description(), "Atomic commits, rebase surgery");
|
||||
assert_eq!(skill.enabled_tools(), Some("shell,fs"));
|
||||
assert_eq!(
|
||||
skill.enabled_tools(),
|
||||
Some(["shell".to_string(), "fs".to_string()].as_slice())
|
||||
);
|
||||
assert_eq!(
|
||||
skill.enabled_mcp_servers(),
|
||||
Some(["github".to_string()].as_slice())
|
||||
|
||||
@@ -69,14 +69,19 @@ impl SkillRegistry {
|
||||
let base_tools_set = effective.enabled_tools().is_some();
|
||||
let base_mcps_set = effective.enabled_mcp_servers().is_some();
|
||||
|
||||
let mut tools = parse_csv(effective.enabled_tools().as_deref());
|
||||
let mut tools: BTreeSet<String> = effective
|
||||
.enabled_tools()
|
||||
.map(|v| v.into_iter().collect())
|
||||
.unwrap_or_default();
|
||||
let mut mcps: BTreeSet<String> = effective
|
||||
.enabled_mcp_servers()
|
||||
.map(|v| v.into_iter().collect())
|
||||
.unwrap_or_default();
|
||||
|
||||
for (_, skill) in &self.loaded {
|
||||
tools.extend(parse_csv(skill.enabled_tools()));
|
||||
if let Some(skill_tools) = skill.enabled_tools() {
|
||||
tools.extend(skill_tools.iter().cloned());
|
||||
}
|
||||
if let Some(servers) = skill.enabled_mcp_servers() {
|
||||
mcps.extend(servers.iter().cloned());
|
||||
}
|
||||
@@ -92,7 +97,7 @@ impl SkillRegistry {
|
||||
}
|
||||
|
||||
if base_tools_set || !tools.is_empty() {
|
||||
effective.set_enabled_tools(Some(join_csv(&tools)));
|
||||
effective.set_enabled_tools(Some(tools.into_iter().collect()));
|
||||
}
|
||||
|
||||
if base_mcps_set || !mcps.is_empty() {
|
||||
@@ -103,23 +108,6 @@ impl SkillRegistry {
|
||||
}
|
||||
}
|
||||
|
||||
fn parse_csv(s: Option<&str>) -> BTreeSet<String> {
|
||||
let mut set = BTreeSet::new();
|
||||
if let Some(raw) = s {
|
||||
for token in raw.split(',') {
|
||||
let trimmed = token.trim();
|
||||
if !trimmed.is_empty() {
|
||||
set.insert(trimmed.to_string());
|
||||
}
|
||||
}
|
||||
}
|
||||
set
|
||||
}
|
||||
|
||||
fn join_csv(set: &BTreeSet<String>) -> String {
|
||||
set.iter().cloned().collect::<Vec<_>>().join(",")
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
impl SkillRegistry {
|
||||
fn insert_for_test(&mut self, skill: Skill) {
|
||||
@@ -199,7 +187,7 @@ mod tests {
|
||||
|
||||
assert_eq!(effective.prompt(), "Process: __INPUT__");
|
||||
let tools = effective.enabled_tools().expect("tools set by skill");
|
||||
assert!(tools.contains("shell"));
|
||||
assert!(tools.iter().any(|s| s == "shell"));
|
||||
}
|
||||
|
||||
#[test]
|
||||
@@ -228,12 +216,12 @@ mod tests {
|
||||
));
|
||||
|
||||
let mut base = Role::new("test", "body");
|
||||
base.set_enabled_tools(Some("web_search".to_string()));
|
||||
base.set_enabled_tools(Some(vec!["web_search".to_string()]));
|
||||
|
||||
let effective = registry.effective_role(&base);
|
||||
|
||||
let tools_str = effective.enabled_tools().unwrap();
|
||||
let tools: BTreeSet<&str> = tools_str.split(',').collect();
|
||||
let tools_vec = effective.enabled_tools().unwrap();
|
||||
let tools: BTreeSet<&str> = tools_vec.iter().map(|s| s.as_str()).collect();
|
||||
assert_eq!(tools, BTreeSet::from(["fs", "git", "shell", "web_search"]));
|
||||
|
||||
let mcps_vec = effective.enabled_mcp_servers().unwrap();
|
||||
@@ -259,10 +247,13 @@ mod tests {
|
||||
registry.insert_for_test(make_skill("knowledge", "", "Pure knowledge"));
|
||||
|
||||
let mut base = Role::new("test", "Base");
|
||||
base.set_enabled_tools(Some(String::new()));
|
||||
base.set_enabled_tools(Some(Vec::new()));
|
||||
let effective = registry.effective_role(&base);
|
||||
|
||||
assert_eq!(effective.enabled_tools().as_deref(), Some(""));
|
||||
assert_eq!(
|
||||
effective.enabled_tools().as_deref(),
|
||||
Some([].as_slice())
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
+2
-25
@@ -127,7 +127,7 @@ fn handle_list(ctx: &RequestContext, policy: &SkillPolicy) -> Result<Value> {
|
||||
entries.push(json!({
|
||||
"name": skill.name(),
|
||||
"description": skill.description(),
|
||||
"grants_tools": csv_to_vec(skill.enabled_tools()),
|
||||
"grants_tools": skill.enabled_tools().unwrap_or_default(),
|
||||
"grants_mcp_servers": skill.enabled_mcp_servers().unwrap_or_default(),
|
||||
"loaded": ctx.skill_registry.is_loaded(skill.name()),
|
||||
}));
|
||||
@@ -166,7 +166,7 @@ async fn handle_load(
|
||||
|
||||
let tools_declared = skill
|
||||
.enabled_tools()
|
||||
.map(|s| !s.trim().is_empty())
|
||||
.map(|v| !v.is_empty())
|
||||
.unwrap_or(false);
|
||||
let mcps_declared = skill
|
||||
.enabled_mcp_servers()
|
||||
@@ -226,16 +226,6 @@ async fn handle_unload(ctx: &mut RequestContext, args: &Value) -> Result<Value>
|
||||
}))
|
||||
}
|
||||
|
||||
fn csv_to_vec(csv: Option<&str>) -> Vec<String> {
|
||||
csv.map(|raw| {
|
||||
raw.split(',')
|
||||
.map(|t| t.trim().to_string())
|
||||
.filter(|t| !t.is_empty())
|
||||
.collect()
|
||||
})
|
||||
.unwrap_or_default()
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
@@ -294,17 +284,4 @@ mod tests {
|
||||
assert!(required, "skill__list should have no required parameters");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn csv_to_vec_empty_input() {
|
||||
assert!(csv_to_vec(None).is_empty());
|
||||
assert!(csv_to_vec(Some("")).is_empty());
|
||||
assert!(csv_to_vec(Some(" ")).is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn csv_to_vec_parses_and_trims() {
|
||||
let v = csv_to_vec(Some("a, b ,c,, d"));
|
||||
|
||||
assert_eq!(v, vec!["a", "b", "c", "d"]);
|
||||
}
|
||||
}
|
||||
|
||||
+3
-3
@@ -256,13 +256,13 @@ fn build_inline_role(
|
||||
}
|
||||
|
||||
if node.tools.as_deref().unwrap_or_default().is_empty() {
|
||||
role.set_enabled_tools(Some(String::new()));
|
||||
role.set_enabled_tools(Some(Vec::new()));
|
||||
role.set_enabled_mcp_servers(Some(Vec::new()));
|
||||
} else {
|
||||
if !regular_tools.is_empty() {
|
||||
role.set_enabled_tools(Some(regular_tools.join(",")));
|
||||
role.set_enabled_tools(Some(regular_tools.to_vec()));
|
||||
} else {
|
||||
role.set_enabled_tools(Some(String::new()));
|
||||
role.set_enabled_tools(Some(Vec::new()));
|
||||
}
|
||||
if !mcp_servers.is_empty() {
|
||||
role.set_enabled_mcp_servers(Some(mcp_servers.to_vec()));
|
||||
|
||||
@@ -55,7 +55,7 @@ async fn extract_via_extractor(
|
||||
|
||||
fn build_extractor_role() -> Result<Role> {
|
||||
let mut role = Role::new(EXTRACTOR_ROLE_NAME, EXTRACTOR_ROLE_PROMPT);
|
||||
role.set_enabled_tools(Some(String::new()));
|
||||
role.set_enabled_tools(Some(Vec::new()));
|
||||
role.set_enabled_mcp_servers(Some(Vec::new()));
|
||||
Ok(role)
|
||||
}
|
||||
@@ -183,7 +183,10 @@ mod tests {
|
||||
fn build_extractor_role_disables_tools_and_mcp() {
|
||||
let role = build_extractor_role().expect("builtin role must exist");
|
||||
|
||||
assert_eq!(role.enabled_tools().as_deref(), Some(""));
|
||||
assert_eq!(
|
||||
role.enabled_tools().as_deref(),
|
||||
Some([].as_slice())
|
||||
);
|
||||
assert_eq!(
|
||||
role.enabled_mcp_servers().as_deref(),
|
||||
Some([].as_slice())
|
||||
|
||||
Reference in New Issue
Block a user