Skip to main content

wm_tools/expansion/
tasks.rs

1//! Task tools — distribute, status.
2
3#![forbid(unsafe_code)]
4
5use async_trait::async_trait;
6
7use serde_json::{Value, json};
8use std::sync::Arc;
9use wm_core::{Context, EffectRow, Galaxy, Gana, Resource, Tool, ToolStats};
10use wm_memory::{Memory, MemoryStore};
11
12pub struct TaskDistributeTool {
13    store: Arc<MemoryStore>,
14    stats: ToolStats,
15    effects: EffectRow,
16}
17
18impl TaskDistributeTool {
19    pub fn new(store: Arc<MemoryStore>) -> Self {
20        Self {
21            store,
22            stats: ToolStats::default(),
23            effects: EffectRow {
24                writes: vec![Resource::Galaxy("substrate".into())],
25                ..Default::default()
26            },
27        }
28    }
29}
30
31#[async_trait]
32impl Tool for TaskDistributeTool {
33    fn name(&self) -> &str {
34        "task.distribute"
35    }
36    fn gana(&self) -> Gana {
37        Gana::TurtleBeak
38    }
39    fn effects(&self) -> &EffectRow {
40        &self.effects
41    }
42    fn description(&self) -> &str {
43        "Distribute a task to registered agents"
44    }
45    async fn call(&self, _ctx: &mut Context, args: Value) -> wm_core::Result<Value> {
46        let task = args.get("task").and_then(|v| v.as_str()).unwrap_or("");
47        let agent_id = args
48            .get("agent_id")
49            .and_then(|v| v.as_str())
50            .unwrap_or("any");
51        let mut mem = Memory::new(
52            Galaxy::Substrate,
53            json!({
54                "type": "task",
55                "task": task,
56                "agent_id": agent_id,
57                "status": "distributed",
58            })
59            .to_string(),
60        );
61        mem.metadata.tags = vec!["task".into(), "distributed".into()];
62        mem.metadata.importance = 0.7;
63        self.store.put(Galaxy::Substrate, &mem)?;
64        Ok(json!({
65            "status": "success",
66            "task_id": mem.metadata.id,
67            "task": task,
68            "agent_id": agent_id,
69        }))
70    }
71    fn stats(&self) -> &ToolStats {
72        &self.stats
73    }
74}
75
76/// `task.status` — check task status.
77pub struct TaskStatusTool {
78    store: Arc<MemoryStore>,
79    stats: ToolStats,
80    effects: EffectRow,
81}
82
83impl TaskStatusTool {
84    pub fn new(store: Arc<MemoryStore>) -> Self {
85        Self {
86            store,
87            stats: ToolStats::default(),
88            effects: EffectRow::read_only(vec![Resource::Galaxy("substrate".into())]),
89        }
90    }
91}
92
93#[async_trait]
94impl Tool for TaskStatusTool {
95    fn name(&self) -> &str {
96        "task.status"
97    }
98    fn gana(&self) -> Gana {
99        Gana::TurtleBeak
100    }
101    fn effects(&self) -> &EffectRow {
102        &self.effects
103    }
104    fn description(&self) -> &str {
105        "Check status of distributed tasks"
106    }
107    async fn call(&self, _ctx: &mut Context, args: Value) -> wm_core::Result<Value> {
108        let task_id = args.get("task_id").and_then(|v| v.as_str()).unwrap_or("");
109        let memories = self.store.scan(Galaxy::Substrate, 500)?;
110        let tasks: Vec<Value> = memories
111            .iter()
112            .filter(|m| m.metadata.tags.contains(&"task".to_string()))
113            .filter(|m| task_id.is_empty() || m.metadata.id.to_string().contains(task_id))
114            .map(|m| {
115                json!({
116                    "id": m.metadata.id,
117                    "content": m.content,
118                    "tags": m.metadata.tags,
119                })
120            })
121            .collect();
122        Ok(json!({
123            "status": "success",
124            "count": tasks.len(),
125            "tasks": tasks,
126        }))
127    }
128    fn stats(&self) -> &ToolStats {
129        &self.stats
130    }
131}