213 lines
6.4 KiB
Rust
213 lines
6.4 KiB
Rust
pub mod ws_adapter;
|
||
|
||
use serde::{Deserialize, Serialize};
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct SessionSummary {
|
||
pub session_id: String,
|
||
pub title: String,
|
||
pub channel_name: String,
|
||
pub chat_id: String,
|
||
pub message_count: i64,
|
||
pub last_active_at: i64,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub archived_at: Option<i64>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct Channel {
|
||
pub id: String,
|
||
pub name: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub description: Option<String>,
|
||
#[serde(rename = "isWritable")]
|
||
pub is_writable: bool,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct TopicSummary {
|
||
pub topic_id: String,
|
||
pub session_id: String,
|
||
pub title: String,
|
||
pub message_count: i64,
|
||
pub created_at: i64,
|
||
pub last_active_at: i64,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub description: Option<String>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct MediaSummary {
|
||
pub path: String,
|
||
pub media_type: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub mime_type: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub content_base64: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub file_name: Option<String>,
|
||
}
|
||
|
||
/// 定时任务会话查找键(用于前端加载执行对话)
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct SchedulerJobSessionLookup {
|
||
pub channel: String,
|
||
pub chat_id: String,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
pub struct SchedulerJobSummary {
|
||
pub id: String,
|
||
pub kind: String,
|
||
pub schedule: serde_json::Value,
|
||
pub enabled: bool,
|
||
pub state: String,
|
||
pub last_status: Option<String>,
|
||
pub last_error: Option<String>,
|
||
pub run_count: i64,
|
||
pub max_runs: Option<i64>,
|
||
pub last_fired_at: Option<i64>,
|
||
pub next_fire_at: Option<i64>,
|
||
pub created_at: i64,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
pub session_lookup: Option<SchedulerJobSessionLookup>,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
#[serde(tag = "type")]
|
||
pub enum WsInbound {
|
||
/// 普通用户消息
|
||
#[serde(rename = "message")]
|
||
Message {
|
||
content: String,
|
||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||
attachments: Vec<MediaSummary>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
channel: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
chat_id: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
sender_id: Option<String>,
|
||
},
|
||
/// 命令(JSON 格式)
|
||
#[serde(rename = "command")]
|
||
Command { payload: String },
|
||
#[serde(rename = "ping")]
|
||
Ping,
|
||
}
|
||
|
||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||
#[serde(tag = "type")]
|
||
pub enum WsOutbound {
|
||
#[serde(rename = "assistant_response")]
|
||
AssistantResponse {
|
||
id: String,
|
||
content: String,
|
||
role: String,
|
||
#[serde(default, skip_serializing_if = "Vec::is_empty")]
|
||
attachments: Vec<MediaSummary>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
subagent_task_id: Option<String>,
|
||
},
|
||
#[serde(rename = "tool_call")]
|
||
ToolCall {
|
||
id: String,
|
||
tool_call_id: String,
|
||
tool_name: String,
|
||
arguments: serde_json::Value,
|
||
content: String,
|
||
role: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
subagent_task_id: Option<String>,
|
||
},
|
||
#[serde(rename = "tool_result")]
|
||
ToolResult {
|
||
id: String,
|
||
tool_call_id: String,
|
||
tool_name: String,
|
||
content: String,
|
||
role: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
subagent_task_id: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
duration_ms: Option<u64>,
|
||
},
|
||
#[serde(rename = "tool_pending")]
|
||
ToolPending {
|
||
id: String,
|
||
tool_call_id: String,
|
||
tool_name: String,
|
||
content: String,
|
||
role: String,
|
||
resume_hint: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
subagent_task_id: Option<String>,
|
||
},
|
||
#[serde(rename = "error")]
|
||
Error { code: String, message: String },
|
||
#[serde(rename = "task_started")]
|
||
TaskStarted {
|
||
task_id: String,
|
||
description: String,
|
||
subagent_type: String,
|
||
},
|
||
#[serde(rename = "session_established")]
|
||
SessionEstablished { session_id: String },
|
||
#[serde(rename = "session_created")]
|
||
SessionCreated { session_id: String, title: String },
|
||
#[serde(rename = "session_list")]
|
||
SessionList {
|
||
sessions: Vec<SessionSummary>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
current_session_id: Option<String>,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
channel_name: Option<String>,
|
||
},
|
||
#[serde(rename = "channel_list")]
|
||
ChannelList {
|
||
channels: Vec<Channel>,
|
||
},
|
||
#[serde(rename = "topic_list")]
|
||
TopicList {
|
||
topics: Vec<TopicSummary>,
|
||
session_id: String,
|
||
},
|
||
#[serde(rename = "session_loaded")]
|
||
SessionLoaded {
|
||
session_id: String,
|
||
title: String,
|
||
message_count: i64,
|
||
},
|
||
#[serde(rename = "session_saved")]
|
||
SessionSaved { session_id: String, filepath: String },
|
||
#[serde(rename = "task_messages_loaded")]
|
||
TaskMessagesLoaded {
|
||
task_id: String,
|
||
description: String,
|
||
subagent_type: String,
|
||
status: String,
|
||
#[serde(default, skip_serializing_if = "Option::is_none")]
|
||
summary: Option<String>,
|
||
},
|
||
#[serde(rename = "scheduler_job_list")]
|
||
SchedulerJobList {
|
||
jobs: Vec<SchedulerJobSummary>,
|
||
},
|
||
#[serde(rename = "execution_cancelled")]
|
||
ExecutionCancelled { message: String },
|
||
#[serde(rename = "pong")]
|
||
Pong,
|
||
}
|
||
|
||
pub fn parse_inbound(raw: &str) -> Result<WsInbound, serde_json::Error> {
|
||
serde_json::from_str(raw)
|
||
}
|
||
|
||
pub fn serialize_inbound(msg: &WsInbound) -> Result<String, serde_json::Error> {
|
||
serde_json::to_string(msg)
|
||
}
|
||
|
||
pub fn serialize_outbound(msg: &WsOutbound) -> Result<String, serde_json::Error> {
|
||
serde_json::to_string(msg)
|
||
}
|