skilllite_core/protocol.rs
1//! Standard Node I/O types for protocol handlers and P2P routing.
2//!
3//! These types are the shared "currency" across stdio_rpc, agent_chat, MCP,
4//! and the future P2P layer. They intentionally carry only what a remote peer
5//! (or routing layer) needs — not full agent internals.
6
7use serde::{Deserialize, Serialize};
8
9// ─── Input types (NodeTask, NodeContext) ─────────────────────────────────────
10
11/// Execution context attached to every [`NodeTask`].
12///
13/// Provides the agent with workspace identity, session continuity, and the
14/// capability tags the caller intends to use. Remote P2P peers use
15/// `required_capabilities` to decide whether to accept the task.
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct NodeContext {
18 /// Workspace path (local execution) or originating node ID (P2P).
19 pub workspace: String,
20 /// Session key for memory/transcript continuity (matches `ChatSession` key).
21 pub session_key: String,
22 /// Capability tags the caller expects to exercise (e.g. `["python", "web"]`).
23 #[serde(default)]
24 pub required_capabilities: Vec<String>,
25}
26
27/// Standard task unit — the universal input for local execution and P2P routing.
28#[derive(Debug, Clone, Serialize, Deserialize)]
29pub struct NodeTask {
30 /// Unique task identifier (UUIDv4 or monotonic counter string).
31 pub id: String,
32 /// Natural-language description of what the agent should accomplish.
33 pub description: String,
34 /// Execution context (workspace, session, capabilities).
35 pub context: NodeContext,
36 /// Optional hint for which skill or tool to prefer.
37 #[serde(skip_serializing_if = "Option::is_none")]
38 pub tool_hint: Option<String>,
39}
40
41// ─── Output types (NodeResult, NewSkill) ─────────────────────────────────────
42
43/// An evolved skill produced during task execution.
44///
45/// Emitted in [`NodeResult::new_skill`] when the Evolution Engine synthesises
46/// or refines a skill as a side-effect of completing a task.
47#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct NewSkill {
49 /// Skill name — matches the `name` field in `SKILL.md`.
50 pub name: String,
51 /// Human-readable description of what the skill does.
52 pub description: String,
53 /// Local filesystem path where the skill was installed.
54 pub path: String,
55 /// Evolution transaction ID — used for rollback via `skilllite evolution reset`.
56 pub txn_id: String,
57}
58
59/// Standard result unit — the universal output for local execution and P2P routing.
60///
61/// Maps from `AgentResult` internally; fields are intentionally minimal so
62/// that routing layers and remote peers can parse results without knowing agent internals.
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct NodeResult {
65 /// Echoed task ID (matches caller's task id when available; otherwise a generated UUID).
66 pub task_id: String,
67 /// Agent's final response text.
68 pub response: String,
69 /// Whether the agent marked the task as completed.
70 pub task_completed: bool,
71 /// Total tool calls made during execution.
72 pub tool_calls: usize,
73 /// Newly synthesised skill, if the Evolution Engine produced one.
74 #[serde(skip_serializing_if = "Option::is_none")]
75 pub new_skill: Option<NewSkill>,
76}