use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq, Eq)]
#[serde(rename_all = "lowercase")]
pub enum GrainType {
Fact,
Event,
State,
Workflow,
Tool,
Observation,
Goal,
Reasoning,
Consensus,
Consent,
Skill,
}
impl std::fmt::Display for GrainType {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let s = match self {
Self::Fact => "fact",
Self::Event => "event",
Self::State => "state",
Self::Workflow => "workflow",
Self::Tool => "tool",
Self::Observation => "observation",
Self::Goal => "goal",
Self::Reasoning => "reasoning",
Self::Consensus => "consensus",
Self::Consent => "consent",
Self::Skill => "skill",
};
f.write_str(s)
}
}
#[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 blob_hash: String,
pub grain_type: String,
pub score: f64,
#[serde(default)]
pub subject: Option<String>,
#[serde(default)]
pub relation: Option<String>,
#[serde(default)]
pub object: Option<String>,
#[serde(default)]
pub confidence: Option<f64>,
#[serde(default)]
pub namespace: Option<String>,
#[serde(default)]
pub tags: Vec<String>,
#[serde(default)]
pub temporal_type: Option<String>,
#[serde(default)]
pub created_at: Option<String>,
#[serde(default)]
pub fields: serde_json::Value,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub score_breakdown: Option<serde_json::Value>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub explanation: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub relative_time: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub conflict_status: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub supersession_status: Option<String>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub recall_source: Option<String>,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RecallResponse {
pub results: Vec<SearchHit>,
pub count: u32,
#[serde(default)]
pub total: u32,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub offset: Option<u32>,
#[serde(default)]
pub has_more: bool,
#[serde(default)]
pub sources: Vec<SearchHit>,
#[serde(default, skip_serializing_if = "Option::is_none")]
pub total_candidates: Option<u32>,
}
#[derive(Debug, Clone, Default, 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, 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 tool_hashes: Vec<String>,
}
fn default_status_completed() -> HarnessChatStatus {
HarnessChatStatus::Completed
}