use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum GrainType {
Belief,
Event,
State,
Workflow,
Action,
Observation,
Goal,
Reasoning,
Consensus,
Consent,
}
impl std::fmt::Display for GrainType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Belief => "belief",
Self::Event => "event",
Self::State => "state",
Self::Workflow => "workflow",
Self::Action => "action",
Self::Observation => "observation",
Self::Goal => "goal",
Self::Reasoning => "reasoning",
Self::Consensus => "consensus",
Self::Consent => "consent",
};
f.write_str(s)
}
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct AddOptions {
#[serde(skip_serializing_if = "Option::is_none")]
pub extract_event_date: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub auto_relate: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extract_memories: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub sync: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddRequest {
pub grain_type: GrainType,
pub fields: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub options: Option<AddOptions>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct AddResponse {
pub hash: String,
}
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct RecallRequest {
#[serde(skip_serializing_if = "Option::is_none")]
pub query: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub subject: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub object: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub grain_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub limit: Option<u32>,
#[serde(skip_serializing_if = "Option::is_none")]
pub temporal_expr: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub deduplicate: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub rerank: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub query_expansion: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub explanation: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub min_score: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub diversity: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub recency_weight: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub entity: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub multi_hop: Option<u32>,
#[serde(flatten)]
pub extra: serde_json::Map<String, serde_json::Value>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SearchHit {
pub hash: String,
pub grain_type: String,
pub score: f64,
pub fields: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub explanation: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub relative_time: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecallResponse {
pub count: u32,
pub results: Vec<SearchHit>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ForgetRequest {
pub hash: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SupersedeRequest {
pub old_hash: String,
pub grain_type: GrainType,
pub fields: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct SupersedeResponse {
pub new_hash: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RememberRequest {
pub text: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub sync: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub keep_source: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub namespace: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub user_id: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tags: Option<Vec<String>>,
#[serde(skip_serializing_if = "Option::is_none")]
pub source_type: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub created_at: Option<i64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub confidence: Option<f64>,
#[serde(skip_serializing_if = "Option::is_none")]
pub extract_event_date: Option<bool>,
#[serde(skip_serializing_if = "Option::is_none")]
pub auto_relate: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RememberResponse {
pub source_hash: String,
pub mode: String,
pub extracted_count: u32,
pub source_forgotten: bool,
#[serde(default)]
pub extracted_hashes: Vec<String>,
#[serde(default)]
pub warnings: Vec<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub marker_status: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct GetResponse {
pub hash: String,
pub grain_type: String,
pub fields: serde_json::Value,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HealthResponse {
pub status: String,
pub version: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct StatsResponse {
pub total_grains: u64,
pub disk_space_bytes: u64,
pub store_size: String,
#[serde(default)]
pub type_counts: std::collections::HashMap<String, u64>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
pub enum HarnessChatStatus {
Completed,
RequiresAction,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HarnessChatRequest {
pub conversation_id: String,
pub user_message: String,
#[serde(skip_serializing_if = "Option::is_none")]
pub model: Option<String>,
#[serde(skip_serializing_if = "Option::is_none")]
pub provider: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct PendingToolCall {
pub tool_call_id: String,
pub tool_name: String,
pub arguments: String,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatToolOutput {
pub tool_call_id: String,
pub output: serde_json::Value,
#[serde(skip_serializing_if = "Option::is_none")]
pub is_error: Option<bool>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct InlineToolResult {
pub tool_call_id: String,
pub tool_name: String,
pub content: String,
pub is_error: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ChatResumeRequest {
pub session_id: String,
pub tool_outputs: Vec<ChatToolOutput>,
#[serde(skip_serializing_if = "Option::is_none")]
pub tenant_timestamp_ms: Option<i64>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ToolCallTrace {
pub iteration: u32,
pub tool_id: String,
pub arguments: String,
pub result: String,
pub is_error: bool,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct HarnessChatResponse {
#[serde(default = "default_status_completed")]
pub status: HarnessChatStatus,
pub text: String,
pub harness_slug: String,
pub conversation_id: String,
pub system_prompt: String,
pub tool_names: Vec<String>,
pub blocked_tools: Vec<String>,
pub tool_calls: Vec<ToolCallTrace>,
pub iterations: u32,
pub assemble_params: std::collections::HashMap<String, String>,
pub input_tokens: u32,
pub output_tokens: u32,
pub provider: String,
pub model: String,
pub retrieval_ms: u64,
pub llm_ms: u64,
pub tools_ms: u64,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub session_id: Option<String>,
#[serde(default)]
pub pending_tool_calls: Vec<PendingToolCall>,
#[serde(default)]
pub inline_tool_results: Vec<InlineToolResult>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub user_event_hash: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub assistant_event_hash: Option<String>,
#[serde(default)]
pub action_hashes: Vec<String>,
}
fn default_status_completed() -> HarnessChatStatus {
HarnessChatStatus::Completed
}