feat: extract task tools builtin module
This commit is contained in:
parent
9721c81eb0
commit
f394f15ba5
|
|
@ -9,7 +9,7 @@ use session_store::Store;
|
|||
use tokio::sync::{broadcast, mpsc, oneshot};
|
||||
|
||||
use crate::discovery::{PodDiscovery, list_pods_tool, restore_pod_tool, send_to_peer_pod_tool};
|
||||
use crate::feature::{FeatureRegistryBuilder, builtin::task_feature};
|
||||
use crate::feature::{FeatureRegistryBuilder, builtin::task_tools_feature};
|
||||
use crate::ipc::alerter::Alerter;
|
||||
use crate::ipc::notify_buffer::NotifyBuffer;
|
||||
use crate::ipc::server::SocketServer;
|
||||
|
|
@ -522,7 +522,7 @@ where
|
|||
));
|
||||
|
||||
let mut feature_registry = FeatureRegistryBuilder::new();
|
||||
feature_registry.add_module(task_feature(task_store));
|
||||
feature_registry.add_module(task_tools_feature(task_store));
|
||||
let _feature_install_report = pod.install_features(feature_registry);
|
||||
|
||||
let worker = pod.worker_mut();
|
||||
|
|
|
|||
|
|
@ -1256,59 +1256,7 @@ pub enum FeatureInstallError {
|
|||
Install(String),
|
||||
}
|
||||
|
||||
/// Builtin task tools feature used to prove existing builtin tool registration
|
||||
/// through the feature registry without changing tool names, schemas, or
|
||||
/// permission behavior.
|
||||
pub mod builtin {
|
||||
use super::*;
|
||||
|
||||
pub fn task_feature(task_store: tools::TaskStore) -> impl FeatureModule {
|
||||
TaskFeature { task_store }
|
||||
}
|
||||
|
||||
struct TaskFeature {
|
||||
task_store: tools::TaskStore,
|
||||
}
|
||||
|
||||
impl FeatureModule for TaskFeature {
|
||||
fn descriptor(&self) -> FeatureDescriptor {
|
||||
FeatureDescriptor::builtin("task-tools", "Task tools")
|
||||
.with_description("Session-lifetime task tracking builtin tools")
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskCreate",
|
||||
"Create a session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskUpdate",
|
||||
"Update a session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskGet",
|
||||
"Get one session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskList",
|
||||
"List session-lifetime user-visible tasks",
|
||||
))
|
||||
}
|
||||
|
||||
fn install(
|
||||
&self,
|
||||
context: &mut FeatureInstallContext<'_>,
|
||||
) -> Result<(), FeatureInstallError> {
|
||||
let names = ["TaskCreate", "TaskList", "TaskGet", "TaskUpdate"];
|
||||
for (name, definition) in names
|
||||
.into_iter()
|
||||
.zip(tools::task_tools(self.task_store.clone()))
|
||||
{
|
||||
context
|
||||
.tools()
|
||||
.register(ToolContribution::new(name, definition))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
pub mod builtin;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
|
|
@ -1797,13 +1745,76 @@ mod tests {
|
|||
assert!(report.reports[0].skipped.is_empty());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_internal_task_feature_descriptor_has_exact_tools_and_no_authorities() {
|
||||
let descriptor = builtin::task_tools_feature(tools::TaskStore::new()).descriptor();
|
||||
let tool_names: Vec<_> = descriptor
|
||||
.tools
|
||||
.iter()
|
||||
.map(|tool| tool.name.as_str())
|
||||
.collect();
|
||||
|
||||
assert_eq!(descriptor.id.as_str(), "builtin:task-tools");
|
||||
assert_eq!(descriptor.runtime, FeatureRuntimeKind::Builtin);
|
||||
assert!(descriptor.requested_authorities.is_empty());
|
||||
assert!(descriptor.hooks.is_empty());
|
||||
assert!(descriptor.background_tasks.is_empty());
|
||||
assert!(descriptor.provides_services.is_empty());
|
||||
assert!(descriptor.requires_services.is_empty());
|
||||
assert_eq!(
|
||||
tool_names,
|
||||
vec!["TaskCreate", "TaskUpdate", "TaskGet", "TaskList"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_internal_task_feature_installs_declared_tools_without_host_authorities() {
|
||||
let task_store = tools::TaskStore::new();
|
||||
let mut hook_builder = HookRegistryBuilder::default();
|
||||
let mut pending_tools = Vec::new();
|
||||
let mut builder = FeatureRegistryBuilder::new();
|
||||
builder.add_module(builtin::task_tools_feature(task_store));
|
||||
let mut declared_names: Vec<_> = builder.descriptors()[0]
|
||||
.tools
|
||||
.iter()
|
||||
.map(|tool| tool.name.clone())
|
||||
.collect();
|
||||
let report = builder.install_into_pending(&mut pending_tools, &mut hook_builder);
|
||||
let pending_names: Vec<_> = pending_tools
|
||||
.iter()
|
||||
.map(|definition| definition().0.name)
|
||||
.collect();
|
||||
let installed_names = report.installed_tool_names();
|
||||
let mut sorted_installed_names = installed_names.clone();
|
||||
declared_names.sort();
|
||||
sorted_installed_names.sort();
|
||||
|
||||
assert_eq!(report.reports.len(), 1);
|
||||
assert!(report.reports[0].installed);
|
||||
assert_eq!(
|
||||
report.reports[0].granted_authorities,
|
||||
AuthorityGrantSet::empty()
|
||||
);
|
||||
assert!(report.reports[0].skipped.is_empty());
|
||||
assert!(report.reports[0].diagnostics.is_empty());
|
||||
assert_eq!(declared_names, sorted_installed_names);
|
||||
assert_eq!(
|
||||
installed_names,
|
||||
vec!["TaskCreate", "TaskList", "TaskGet", "TaskUpdate"]
|
||||
);
|
||||
assert_eq!(
|
||||
pending_names,
|
||||
vec!["TaskCreate", "TaskList", "TaskGet", "TaskUpdate"]
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn builtin_task_feature_installs_through_worker_tool_path() {
|
||||
let task_store = tools::TaskStore::new();
|
||||
let mut worker = Worker::new(DummyClient);
|
||||
let mut hook_builder = HookRegistryBuilder::default();
|
||||
let report = FeatureRegistryBuilder::new()
|
||||
.with_module(builtin::task_feature(task_store))
|
||||
.with_module(builtin::task_tools_feature(task_store))
|
||||
.install_into_worker(&mut worker, &mut hook_builder);
|
||||
|
||||
worker.tool_server_handle().flush_pending();
|
||||
|
|
|
|||
9
crates/pod/src/feature/builtin.rs
Normal file
9
crates/pod/src/feature/builtin.rs
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
//! Built-in internal feature modules.
|
||||
//!
|
||||
//! These modules are compiled into the Pod host and contribute through the
|
||||
//! same descriptor-approved registry path used by feature modules. They are not
|
||||
//! an external plugin-loading surface.
|
||||
|
||||
pub mod task;
|
||||
|
||||
pub use task::task_tools_feature;
|
||||
61
crates/pod/src/feature/builtin/task.rs
Normal file
61
crates/pod/src/feature/builtin/task.rs
Normal file
|
|
@ -0,0 +1,61 @@
|
|||
//! Task tools built-in feature module.
|
||||
//!
|
||||
//! This is the reference path for extracting an internal built-in module into
|
||||
//! the feature contribution boundary. The Pod host still owns the Pod-lifetime
|
||||
//! [`tools::TaskStore`] and passes the shared handle in at construction time;
|
||||
//! the module requests no sandbox/external-plugin host authorities.
|
||||
|
||||
use crate::feature::{
|
||||
FeatureDescriptor, FeatureInstallContext, FeatureInstallError, FeatureModule, ToolContribution,
|
||||
ToolDeclaration,
|
||||
};
|
||||
|
||||
/// Construct the built-in Task tool feature module.
|
||||
///
|
||||
/// The returned module contributes only `TaskCreate`, `TaskUpdate`, `TaskGet`,
|
||||
/// and `TaskList` through descriptor-approved tool registration. It does not
|
||||
/// request host authorities; normal ToolRegistry and PreToolCall permission
|
||||
/// policy still applies at call time.
|
||||
pub fn task_tools_feature(task_store: tools::TaskStore) -> impl FeatureModule {
|
||||
TaskToolsFeature { task_store }
|
||||
}
|
||||
|
||||
struct TaskToolsFeature {
|
||||
task_store: tools::TaskStore,
|
||||
}
|
||||
|
||||
impl FeatureModule for TaskToolsFeature {
|
||||
fn descriptor(&self) -> FeatureDescriptor {
|
||||
FeatureDescriptor::builtin("task-tools", "Task tools")
|
||||
.with_description("Session-lifetime task tracking builtin tools")
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskCreate",
|
||||
"Create a session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskUpdate",
|
||||
"Update a session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskGet",
|
||||
"Get one session-lifetime user-visible task",
|
||||
))
|
||||
.with_tool(ToolDeclaration::new(
|
||||
"TaskList",
|
||||
"List session-lifetime user-visible tasks",
|
||||
))
|
||||
}
|
||||
|
||||
fn install(&self, context: &mut FeatureInstallContext<'_>) -> Result<(), FeatureInstallError> {
|
||||
let names = ["TaskCreate", "TaskList", "TaskGet", "TaskUpdate"];
|
||||
for (name, definition) in names
|
||||
.into_iter()
|
||||
.zip(tools::task_tools(self.task_store.clone()))
|
||||
{
|
||||
context
|
||||
.tools()
|
||||
.register(ToolContribution::new(name, definition))?;
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user