feat: add internal ZCLAW kernel crates to git tracking
This commit is contained in:
15
crates/zclaw-types/Cargo.toml
Normal file
15
crates/zclaw-types/Cargo.toml
Normal file
@@ -0,0 +1,15 @@
|
||||
[package]
|
||||
name = "zclaw-types"
|
||||
version.workspace = true
|
||||
edition.workspace = true
|
||||
license.workspace = true
|
||||
repository.workspace = true
|
||||
rust-version.workspace = true
|
||||
description = "ZCLAW core type definitions"
|
||||
|
||||
[dependencies]
|
||||
serde = { workspace = true }
|
||||
serde_json = { workspace = true }
|
||||
thiserror = { workspace = true }
|
||||
uuid = { workspace = true }
|
||||
chrono = { workspace = true }
|
||||
165
crates/zclaw-types/src/agent.rs
Normal file
165
crates/zclaw-types/src/agent.rs
Normal file
@@ -0,0 +1,165 @@
|
||||
//! Agent configuration and state types
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::{AgentId, Capability, ModelConfig};
|
||||
|
||||
/// Agent configuration
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AgentConfig {
|
||||
/// Unique identifier
|
||||
pub id: AgentId,
|
||||
/// Human-readable name
|
||||
pub name: String,
|
||||
/// Agent description
|
||||
#[serde(default)]
|
||||
pub description: Option<String>,
|
||||
/// Model configuration
|
||||
#[serde(default)]
|
||||
pub model: ModelConfig,
|
||||
/// System prompt
|
||||
#[serde(default)]
|
||||
pub system_prompt: Option<String>,
|
||||
/// Capabilities granted to this agent
|
||||
#[serde(default)]
|
||||
pub capabilities: Vec<Capability>,
|
||||
/// Tools available to this agent
|
||||
#[serde(default)]
|
||||
pub tools: Vec<String>,
|
||||
/// Maximum tokens per response
|
||||
#[serde(default)]
|
||||
pub max_tokens: Option<u32>,
|
||||
/// Temperature (0.0 - 1.0)
|
||||
#[serde(default)]
|
||||
pub temperature: Option<f32>,
|
||||
/// Whether the agent is active
|
||||
#[serde(default = "default_enabled")]
|
||||
pub enabled: bool,
|
||||
}
|
||||
|
||||
fn default_enabled() -> bool {
|
||||
true
|
||||
}
|
||||
|
||||
impl Default for AgentConfig {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
id: AgentId::new(),
|
||||
name: String::new(),
|
||||
description: None,
|
||||
model: ModelConfig::default(),
|
||||
system_prompt: None,
|
||||
capabilities: Vec::new(),
|
||||
tools: Vec::new(),
|
||||
max_tokens: None,
|
||||
temperature: None,
|
||||
enabled: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AgentConfig {
|
||||
pub fn new(name: impl Into<String>) -> Self {
|
||||
Self {
|
||||
id: AgentId::new(),
|
||||
name: name.into(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
|
||||
pub fn with_id(mut self, id: AgentId) -> Self {
|
||||
self.id = id;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_description(mut self, description: impl Into<String>) -> Self {
|
||||
self.description = Some(description.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_system_prompt(mut self, prompt: impl Into<String>) -> Self {
|
||||
self.system_prompt = Some(prompt.into());
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_model(mut self, model: ModelConfig) -> Self {
|
||||
self.model = model;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_capabilities(mut self, capabilities: Vec<Capability>) -> Self {
|
||||
self.capabilities = capabilities;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_tools(mut self, tools: Vec<String>) -> Self {
|
||||
self.tools = tools;
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_max_tokens(mut self, max_tokens: u32) -> Self {
|
||||
self.max_tokens = Some(max_tokens);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_temperature(mut self, temperature: f32) -> Self {
|
||||
self.temperature = Some(temperature);
|
||||
self
|
||||
}
|
||||
}
|
||||
|
||||
/// Agent runtime state
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub enum AgentState {
|
||||
/// Agent is running and can receive messages
|
||||
Running,
|
||||
/// Agent is paused
|
||||
Suspended,
|
||||
/// Agent has been terminated
|
||||
Terminated,
|
||||
}
|
||||
|
||||
impl Default for AgentState {
|
||||
fn default() -> Self {
|
||||
Self::Running
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AgentState {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
AgentState::Running => write!(f, "running"),
|
||||
AgentState::Suspended => write!(f, "suspended"),
|
||||
AgentState::Terminated => write!(f, "terminated"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Agent information for display
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct AgentInfo {
|
||||
pub id: AgentId,
|
||||
pub name: String,
|
||||
pub description: Option<String>,
|
||||
pub model: String,
|
||||
pub provider: String,
|
||||
pub state: AgentState,
|
||||
pub message_count: usize,
|
||||
pub created_at: chrono::DateTime<chrono::Utc>,
|
||||
pub updated_at: chrono::DateTime<chrono::Utc>,
|
||||
}
|
||||
|
||||
impl From<AgentConfig> for AgentInfo {
|
||||
fn from(config: AgentConfig) -> Self {
|
||||
Self {
|
||||
id: config.id,
|
||||
name: config.name,
|
||||
description: config.description,
|
||||
model: config.model.model,
|
||||
provider: config.model.provider,
|
||||
state: AgentState::Running,
|
||||
message_count: 0,
|
||||
created_at: chrono::Utc::now(),
|
||||
updated_at: chrono::Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
158
crates/zclaw-types/src/capability.rs
Normal file
158
crates/zclaw-types/src/capability.rs
Normal file
@@ -0,0 +1,158 @@
|
||||
//! Capability-based security model
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
/// A capability grants permission for a specific operation
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum Capability {
|
||||
/// Invoke a specific tool
|
||||
ToolInvoke { name: String },
|
||||
/// Access to all tools
|
||||
ToolAll,
|
||||
/// Read from memory scope
|
||||
MemoryRead { scope: String },
|
||||
/// Write to memory scope
|
||||
MemoryWrite { scope: String },
|
||||
/// Connect to network host
|
||||
NetConnect { host: String },
|
||||
/// Execute shell commands matching pattern
|
||||
ShellExec { pattern: String },
|
||||
/// Spawn new agents
|
||||
AgentSpawn,
|
||||
/// Send messages to agents matching pattern
|
||||
AgentMessage { pattern: String },
|
||||
/// Kill agents matching pattern
|
||||
AgentKill { pattern: String },
|
||||
/// Discover remote peers via OFP
|
||||
OfpDiscover,
|
||||
/// Connect to specific OFP peers
|
||||
OfpConnect { peer: String },
|
||||
/// Advertise to OFP peers
|
||||
OfpAdvertise,
|
||||
}
|
||||
|
||||
impl Capability {
|
||||
/// Create a tool invocation capability
|
||||
pub fn tool(name: impl Into<String>) -> Self {
|
||||
Self::ToolInvoke { name: name.into() }
|
||||
}
|
||||
|
||||
/// Create a memory read capability
|
||||
pub fn memory_read(scope: impl Into<String>) -> Self {
|
||||
Self::MemoryRead { scope: scope.into() }
|
||||
}
|
||||
|
||||
/// Create a memory write capability
|
||||
pub fn memory_write(scope: impl Into<String>) -> Self {
|
||||
Self::MemoryWrite { scope: scope.into() }
|
||||
}
|
||||
|
||||
/// Create a network connect capability
|
||||
pub fn net_connect(host: impl Into<String>) -> Self {
|
||||
Self::NetConnect { host: host.into() }
|
||||
}
|
||||
|
||||
/// Check if this capability grants access to a tool
|
||||
pub fn allows_tool(&self, tool_name: &str) -> bool {
|
||||
match self {
|
||||
Capability::ToolAll => true,
|
||||
Capability::ToolInvoke { name } => name == tool_name,
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this capability grants read access to a scope
|
||||
pub fn allows_memory_read(&self, scope: &str) -> bool {
|
||||
match self {
|
||||
Capability::MemoryRead { scope: s } => {
|
||||
s == "*" || s == scope || scope.starts_with(&format!("{}.", s))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this capability grants write access to a scope
|
||||
pub fn allows_memory_write(&self, scope: &str) -> bool {
|
||||
match self {
|
||||
Capability::MemoryWrite { scope: s } => {
|
||||
s == "*" || s == scope || scope.starts_with(&format!("{}.", s))
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Capability set for an agent
|
||||
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
|
||||
pub struct CapabilitySet {
|
||||
pub capabilities: Vec<Capability>,
|
||||
}
|
||||
|
||||
impl CapabilitySet {
|
||||
pub fn new() -> Self {
|
||||
Self { capabilities: Vec::new() }
|
||||
}
|
||||
|
||||
pub fn with(mut self, capability: Capability) -> Self {
|
||||
self.capabilities.push(capability);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_all_tools(mut self) -> Self {
|
||||
self.capabilities.push(Capability::ToolAll);
|
||||
self
|
||||
}
|
||||
|
||||
pub fn with_tool(mut self, name: impl Into<String>) -> Self {
|
||||
self.capabilities.push(Capability::tool(name));
|
||||
self
|
||||
}
|
||||
|
||||
/// Check if any capability grants access to a tool
|
||||
pub fn can_invoke_tool(&self, tool_name: &str) -> bool {
|
||||
self.capabilities.iter().any(|c| c.allows_tool(tool_name))
|
||||
}
|
||||
|
||||
/// Check if any capability grants read access to a scope
|
||||
pub fn can_read_memory(&self, scope: &str) -> bool {
|
||||
self.capabilities.iter().any(|c| c.allows_memory_read(scope))
|
||||
}
|
||||
|
||||
/// Check if any capability grants write access to a scope
|
||||
pub fn can_write_memory(&self, scope: &str) -> bool {
|
||||
self.capabilities.iter().any(|c| c.allows_memory_write(scope))
|
||||
}
|
||||
|
||||
/// Validate that a child's capabilities don't exceed parent's
|
||||
pub fn validate_inheritance(&self, child: &CapabilitySet) -> bool {
|
||||
// Child can only have capabilities that parent has
|
||||
child.capabilities.iter().all(|child_cap| {
|
||||
self.capabilities.iter().any(|parent_cap| {
|
||||
child_cap == parent_cap || parent_cap.grants(child_cap)
|
||||
})
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
impl Capability {
|
||||
/// Check if this capability grants another capability
|
||||
fn grants(&self, other: &Capability) -> bool {
|
||||
match (self, other) {
|
||||
// ToolAll grants any ToolInvoke
|
||||
(Capability::ToolAll, Capability::ToolInvoke { .. }) => true,
|
||||
// Wildcard scopes grant specific scopes
|
||||
(Capability::MemoryRead { scope: a }, Capability::MemoryRead { scope: b }) => {
|
||||
a == "*" || a == b || b.starts_with(&format!("{}.", a))
|
||||
}
|
||||
(Capability::MemoryWrite { scope: a }, Capability::MemoryWrite { scope: b }) => {
|
||||
a == "*" || a == b || b.starts_with(&format!("{}.", a))
|
||||
}
|
||||
// NetConnect with "*" grants any host
|
||||
(Capability::NetConnect { host: a }, Capability::NetConnect { host: b }) => {
|
||||
a == "*" || a == b
|
||||
}
|
||||
_ => false,
|
||||
}
|
||||
}
|
||||
}
|
||||
52
crates/zclaw-types/src/error.rs
Normal file
52
crates/zclaw-types/src/error.rs
Normal file
@@ -0,0 +1,52 @@
|
||||
//! Error types for ZCLAW
|
||||
|
||||
use thiserror::Error;
|
||||
|
||||
/// ZCLAW unified error type
|
||||
#[derive(Debug, Error)]
|
||||
pub enum ZclawError {
|
||||
#[error("Not found: {0}")]
|
||||
NotFound(String),
|
||||
|
||||
#[error("Permission denied: {0}")]
|
||||
PermissionDenied(String),
|
||||
|
||||
#[error("LLM error: {0}")]
|
||||
LlmError(String),
|
||||
|
||||
#[error("Tool error: {0}")]
|
||||
ToolError(String),
|
||||
|
||||
#[error("Storage error: {0}")]
|
||||
StorageError(String),
|
||||
|
||||
#[error("Configuration error: {0}")]
|
||||
ConfigError(String),
|
||||
|
||||
#[error("Serialization error: {0}")]
|
||||
SerializationError(#[from] serde_json::Error),
|
||||
|
||||
#[error("IO error: {0}")]
|
||||
IoError(#[from] std::io::Error),
|
||||
|
||||
#[error("HTTP error: {0}")]
|
||||
HttpError(String),
|
||||
|
||||
#[error("Timeout: {0}")]
|
||||
Timeout(String),
|
||||
|
||||
#[error("Invalid input: {0}")]
|
||||
InvalidInput(String),
|
||||
|
||||
#[error("Agent loop detected: {0}")]
|
||||
LoopDetected(String),
|
||||
|
||||
#[error("Rate limited: {0}")]
|
||||
RateLimited(String),
|
||||
|
||||
#[error("Internal error: {0}")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
/// Result type alias for ZCLAW operations
|
||||
pub type Result<T> = std::result::Result<T, ZclawError>;
|
||||
136
crates/zclaw-types/src/event.rs
Normal file
136
crates/zclaw-types/src/event.rs
Normal file
@@ -0,0 +1,136 @@
|
||||
//! Event types for ZCLAW event bus
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use crate::{AgentId, SessionId, RunId};
|
||||
|
||||
/// An event in the ZCLAW system
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum Event {
|
||||
/// Kernel started
|
||||
KernelStarted,
|
||||
|
||||
/// Kernel shutting down
|
||||
KernelShutdown,
|
||||
|
||||
/// Agent spawned
|
||||
AgentSpawned {
|
||||
agent_id: AgentId,
|
||||
name: String,
|
||||
},
|
||||
|
||||
/// Agent terminated
|
||||
AgentTerminated {
|
||||
agent_id: AgentId,
|
||||
reason: String,
|
||||
},
|
||||
|
||||
/// Agent state changed
|
||||
AgentStateChanged {
|
||||
agent_id: AgentId,
|
||||
old_state: String,
|
||||
new_state: String,
|
||||
},
|
||||
|
||||
/// Session created
|
||||
SessionCreated {
|
||||
session_id: SessionId,
|
||||
agent_id: AgentId,
|
||||
},
|
||||
|
||||
/// Message received
|
||||
MessageReceived {
|
||||
agent_id: AgentId,
|
||||
session_id: SessionId,
|
||||
role: String,
|
||||
},
|
||||
|
||||
/// Message sent
|
||||
MessageSent {
|
||||
agent_id: AgentId,
|
||||
session_id: SessionId,
|
||||
role: String,
|
||||
},
|
||||
|
||||
/// Tool invoked
|
||||
ToolInvoked {
|
||||
agent_id: AgentId,
|
||||
tool_name: String,
|
||||
},
|
||||
|
||||
/// Tool completed
|
||||
ToolCompleted {
|
||||
agent_id: AgentId,
|
||||
tool_name: String,
|
||||
success: bool,
|
||||
duration_ms: u64,
|
||||
},
|
||||
|
||||
/// Workflow started
|
||||
WorkflowStarted {
|
||||
workflow_id: String,
|
||||
run_id: RunId,
|
||||
},
|
||||
|
||||
/// Workflow completed
|
||||
WorkflowCompleted {
|
||||
workflow_id: String,
|
||||
run_id: RunId,
|
||||
success: bool,
|
||||
},
|
||||
|
||||
/// Trigger fired
|
||||
TriggerFired {
|
||||
trigger_id: String,
|
||||
trigger_type: String,
|
||||
},
|
||||
|
||||
/// Skill loaded
|
||||
SkillLoaded {
|
||||
skill_id: String,
|
||||
version: String,
|
||||
},
|
||||
|
||||
/// Hand triggered
|
||||
HandTriggered {
|
||||
hand_name: String,
|
||||
agent_id: Option<AgentId>,
|
||||
},
|
||||
|
||||
/// Health check failed
|
||||
HealthCheckFailed {
|
||||
agent_id: AgentId,
|
||||
reason: String,
|
||||
},
|
||||
|
||||
/// Error occurred
|
||||
Error {
|
||||
source: String,
|
||||
message: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl Event {
|
||||
/// Get the event type name
|
||||
pub fn event_type(&self) -> &'static str {
|
||||
match self {
|
||||
Event::KernelStarted { .. } => "kernel_started",
|
||||
Event::KernelShutdown { .. } => "kernel_shutdown",
|
||||
Event::AgentSpawned { .. } => "agent_spawned",
|
||||
Event::AgentTerminated { .. } => "agent_terminated",
|
||||
Event::AgentStateChanged { .. } => "agent_state_changed",
|
||||
Event::SessionCreated { .. } => "session_created",
|
||||
Event::MessageReceived { .. } => "message_received",
|
||||
Event::MessageSent { .. } => "message_sent",
|
||||
Event::ToolInvoked { .. } => "tool_invoked",
|
||||
Event::ToolCompleted { .. } => "tool_completed",
|
||||
Event::WorkflowStarted { .. } => "workflow_started",
|
||||
Event::WorkflowCompleted { .. } => "workflow_completed",
|
||||
Event::TriggerFired { .. } => "trigger_fired",
|
||||
Event::SkillLoaded { .. } => "skill_loaded",
|
||||
Event::HandTriggered { .. } => "hand_triggered",
|
||||
Event::HealthCheckFailed { .. } => "health_check_failed",
|
||||
Event::Error { .. } => "error",
|
||||
}
|
||||
}
|
||||
}
|
||||
147
crates/zclaw-types/src/id.rs
Normal file
147
crates/zclaw-types/src/id.rs
Normal file
@@ -0,0 +1,147 @@
|
||||
//! ID types for ZCLAW entities
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::str::FromStr;
|
||||
use uuid::Uuid;
|
||||
|
||||
/// Unique identifier for an Agent
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct AgentId(pub Uuid);
|
||||
|
||||
impl AgentId {
|
||||
pub fn new() -> Self {
|
||||
Self(Uuid::new_v4())
|
||||
}
|
||||
|
||||
pub fn from_uuid(uuid: Uuid) -> Self {
|
||||
Self(uuid)
|
||||
}
|
||||
|
||||
pub fn as_uuid(&self) -> &Uuid {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for AgentId {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for AgentId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for AgentId {
|
||||
type Err = uuid::Error;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
Uuid::parse_str(s).map(AgentId)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique identifier for a conversation session
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct SessionId(pub Uuid);
|
||||
|
||||
impl SessionId {
|
||||
pub fn new() -> Self {
|
||||
Self(Uuid::new_v4())
|
||||
}
|
||||
|
||||
pub fn from_uuid(uuid: Uuid) -> Self {
|
||||
Self(uuid)
|
||||
}
|
||||
|
||||
pub fn as_uuid(&self) -> &Uuid {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for SessionId {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SessionId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique identifier for a tool
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct ToolId(pub String);
|
||||
|
||||
impl ToolId {
|
||||
pub fn new(name: impl Into<String>) -> Self {
|
||||
Self(name.into())
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for ToolId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&str> for ToolId {
|
||||
fn from(s: &str) -> Self {
|
||||
Self(s.to_string())
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for ToolId {
|
||||
fn from(s: String) -> Self {
|
||||
Self(s)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique identifier for a skill
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct SkillId(pub String);
|
||||
|
||||
impl SkillId {
|
||||
pub fn new(name: impl Into<String>) -> Self {
|
||||
Self(name.into())
|
||||
}
|
||||
|
||||
pub fn as_str(&self) -> &str {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for SkillId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
|
||||
/// Unique identifier for a workflow run
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize)]
|
||||
pub struct RunId(pub Uuid);
|
||||
|
||||
impl RunId {
|
||||
pub fn new() -> Self {
|
||||
Self(Uuid::new_v4())
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for RunId {
|
||||
fn default() -> Self {
|
||||
Self::new()
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for RunId {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(f, "{}", self.0)
|
||||
}
|
||||
}
|
||||
24
crates/zclaw-types/src/lib.rs
Normal file
24
crates/zclaw-types/src/lib.rs
Normal file
@@ -0,0 +1,24 @@
|
||||
//! ZCLAW Core Types
|
||||
//!
|
||||
//! This crate defines the fundamental types used across all ZCLAW crates.
|
||||
|
||||
pub mod id;
|
||||
pub mod message;
|
||||
pub mod agent;
|
||||
pub mod capability;
|
||||
pub mod error;
|
||||
pub mod event;
|
||||
pub mod tool;
|
||||
pub mod config;
|
||||
|
||||
pub use id::*;
|
||||
pub use message::*;
|
||||
pub use agent::*;
|
||||
pub use capability::*;
|
||||
pub use error::*;
|
||||
pub use event::*;
|
||||
pub use tool::*;
|
||||
pub use config::*;
|
||||
|
||||
// Re-export commonly used external types
|
||||
pub use serde_json::Value as JsonValue;
|
||||
163
crates/zclaw-types/src/message.rs
Normal file
163
crates/zclaw-types/src/message.rs
Normal file
@@ -0,0 +1,163 @@
|
||||
//! Message types for Agent communication
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::Value;
|
||||
use crate::ToolId;
|
||||
|
||||
/// A message in a conversation
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "role", rename_all = "lowercase")]
|
||||
pub enum Message {
|
||||
/// User message
|
||||
User {
|
||||
content: String,
|
||||
},
|
||||
/// Assistant message
|
||||
Assistant {
|
||||
content: String,
|
||||
/// Optional thinking/reasoning content
|
||||
thinking: Option<String>,
|
||||
},
|
||||
/// Tool use request from the assistant
|
||||
ToolUse {
|
||||
id: String,
|
||||
tool: ToolId,
|
||||
input: Value,
|
||||
},
|
||||
/// Tool execution result
|
||||
ToolResult {
|
||||
tool_call_id: String,
|
||||
tool: ToolId,
|
||||
output: Value,
|
||||
/// Whether the tool execution failed
|
||||
is_error: bool,
|
||||
},
|
||||
/// System message (injected into context)
|
||||
System {
|
||||
content: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl Message {
|
||||
pub fn user(content: impl Into<String>) -> Self {
|
||||
Self::User {
|
||||
content: content.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assistant(content: impl Into<String>) -> Self {
|
||||
Self::Assistant {
|
||||
content: content.into(),
|
||||
thinking: None,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assistant_with_thinking(content: impl Into<String>, thinking: impl Into<String>) -> Self {
|
||||
Self::Assistant {
|
||||
content: content.into(),
|
||||
thinking: Some(thinking.into()),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tool_use(id: impl Into<String>, tool: ToolId, input: Value) -> Self {
|
||||
Self::ToolUse {
|
||||
id: id.into(),
|
||||
tool,
|
||||
input,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tool_result(tool_call_id: impl Into<String>, tool: ToolId, output: Value, is_error: bool) -> Self {
|
||||
Self::ToolResult {
|
||||
tool_call_id: tool_call_id.into(),
|
||||
tool,
|
||||
output,
|
||||
is_error,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn system(content: impl Into<String>) -> Self {
|
||||
Self::System {
|
||||
content: content.into(),
|
||||
}
|
||||
}
|
||||
|
||||
/// Get the role name as a string
|
||||
pub fn role(&self) -> &'static str {
|
||||
match self {
|
||||
Message::User { .. } => "user",
|
||||
Message::Assistant { .. } => "assistant",
|
||||
Message::ToolUse { .. } => "tool_use",
|
||||
Message::ToolResult { .. } => "tool_result",
|
||||
Message::System { .. } => "system",
|
||||
}
|
||||
}
|
||||
|
||||
/// Check if this is a user message
|
||||
pub fn is_user(&self) -> bool {
|
||||
matches!(self, Message::User { .. })
|
||||
}
|
||||
|
||||
/// Check if this is an assistant message
|
||||
pub fn is_assistant(&self) -> bool {
|
||||
matches!(self, Message::Assistant { .. })
|
||||
}
|
||||
|
||||
/// Check if this is a tool use
|
||||
pub fn is_tool_use(&self) -> bool {
|
||||
matches!(self, Message::ToolUse { .. })
|
||||
}
|
||||
|
||||
/// Check if this is a tool result
|
||||
pub fn is_tool_result(&self) -> bool {
|
||||
matches!(self, Message::ToolResult { .. })
|
||||
}
|
||||
}
|
||||
|
||||
/// Content block for structured responses
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
#[serde(tag = "type", rename_all = "snake_case")]
|
||||
pub enum ContentBlock {
|
||||
Text { text: String },
|
||||
Thinking { thinking: String },
|
||||
ToolUse {
|
||||
id: String,
|
||||
name: String,
|
||||
input: Value,
|
||||
},
|
||||
ToolResult {
|
||||
tool_use_id: String,
|
||||
content: String,
|
||||
is_error: bool,
|
||||
},
|
||||
Image {
|
||||
source: ImageSource,
|
||||
},
|
||||
}
|
||||
|
||||
/// Image source for multimodal messages
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub struct ImageSource {
|
||||
#[serde(rename = "type")]
|
||||
pub source_type: String, // "base64", "url"
|
||||
pub media_type: String,
|
||||
pub data: String,
|
||||
}
|
||||
|
||||
impl ImageSource {
|
||||
pub fn base64(media_type: impl Into<String>, data: impl Into<String>) -> Self {
|
||||
Self {
|
||||
source_type: "base64".to_string(),
|
||||
media_type: media_type.into(),
|
||||
data: data.into(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn url(url: impl Into<String>) -> Self {
|
||||
Self {
|
||||
source_type: "url".to_string(),
|
||||
media_type: "image/*".to_string(),
|
||||
data: url.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user