use anyhow::Result;
use kube::Client;
use kube::api::Api;
use polyc_controller::Conversation;
use crate::components::tools::{ToolSource, ToolView};
pub(crate) const LOCAL_TOOLS: &[&str] = &[
"shell_exec",
"file_read",
"file_write",
"file_edit",
"glob",
"grep",
"web_fetch",
"paid_fetch",
];
#[must_use]
pub(crate) fn classify_source(name: &str) -> ToolSource {
if LOCAL_TOOLS.contains(&name) {
ToolSource::Local
} else {
ToolSource::Dynamic
}
}
pub(crate) async fn load_tools(
client: &Client,
namespace: &str,
conversation_id: &str,
) -> Result<Vec<ToolView>> {
let api: Api<Conversation> = Api::namespaced(client.clone(), namespace);
let conv = api.get(conversation_id).await?;
Ok(views_from_spec(&conv))
}
#[must_use]
pub(crate) fn views_from_spec(conv: &Conversation) -> Vec<ToolView> {
conv.spec
.tools_enabled
.iter()
.map(|name| ToolView {
name: name.clone(),
source: classify_source(name),
enabled: true,
description: None,
requires_approval: false,
})
.collect()
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn local_tools_classify_as_local() {
for name in LOCAL_TOOLS {
assert_eq!(classify_source(name), ToolSource::Local, "{name}");
}
assert_eq!(classify_source("shell_exec"), ToolSource::Local);
assert_eq!(classify_source("web_fetch"), ToolSource::Local);
}
#[test]
fn unknown_tools_classify_as_dynamic() {
assert_eq!(classify_source("slacksearch"), ToolSource::Dynamic);
assert_eq!(classify_source("websearch"), ToolSource::Dynamic);
assert_eq!(classify_source(""), ToolSource::Dynamic);
}
}