j_cli/command/chat/
model.rs1use crate::config::YamlConfig;
2use crate::error;
3use serde::{Deserialize, Serialize};
4use std::fs;
5use std::path::PathBuf;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
11pub struct ModelProvider {
12 pub name: String,
14 pub api_base: String,
16 pub api_key: String,
18 pub model: String,
20}
21
22#[derive(Debug, Clone, Serialize, Deserialize, Default)]
24pub struct AgentConfig {
25 #[serde(default)]
27 pub providers: Vec<ModelProvider>,
28 #[serde(default)]
30 pub active_index: usize,
31 #[serde(default)]
33 pub system_prompt: Option<String>,
34 #[serde(default = "default_stream_mode")]
36 pub stream_mode: bool,
37 #[serde(default = "default_max_history_messages")]
39 pub max_history_messages: usize,
40}
41
42fn default_max_history_messages() -> usize {
43 20
44}
45
46fn default_stream_mode() -> bool {
48 true
49}
50
51#[derive(Debug, Clone, Serialize, Deserialize)]
53pub struct ChatMessage {
54 pub role: String, pub content: String,
56}
57
58#[derive(Debug, Clone, Serialize, Deserialize, Default)]
60pub struct ChatSession {
61 pub messages: Vec<ChatMessage>,
62}
63
64pub fn agent_data_dir() -> PathBuf {
68 let dir = YamlConfig::data_dir().join("agent").join("data");
69 let _ = fs::create_dir_all(&dir);
70 dir
71}
72
73pub fn agent_config_path() -> PathBuf {
75 agent_data_dir().join("agent_config.json")
76}
77
78pub fn chat_history_path() -> PathBuf {
80 agent_data_dir().join("chat_history.json")
81}
82
83pub fn load_agent_config() -> AgentConfig {
87 let path = agent_config_path();
88 if !path.exists() {
89 return AgentConfig::default();
90 }
91 match fs::read_to_string(&path) {
92 Ok(content) => serde_json::from_str(&content).unwrap_or_else(|e| {
93 error!("❌ 解析 agent_config.json 失败: {}", e);
94 AgentConfig::default()
95 }),
96 Err(e) => {
97 error!("❌ 读取 agent_config.json 失败: {}", e);
98 AgentConfig::default()
99 }
100 }
101}
102
103pub fn save_agent_config(config: &AgentConfig) -> bool {
105 let path = agent_config_path();
106 if let Some(parent) = path.parent() {
107 let _ = fs::create_dir_all(parent);
108 }
109 match serde_json::to_string_pretty(config) {
110 Ok(json) => match fs::write(&path, json) {
111 Ok(_) => true,
112 Err(e) => {
113 error!("❌ 保存 agent_config.json 失败: {}", e);
114 false
115 }
116 },
117 Err(e) => {
118 error!("❌ 序列化 agent 配置失败: {}", e);
119 false
120 }
121 }
122}
123
124pub fn load_chat_session() -> ChatSession {
126 let path = chat_history_path();
127 if !path.exists() {
128 return ChatSession::default();
129 }
130 match fs::read_to_string(&path) {
131 Ok(content) => serde_json::from_str(&content).unwrap_or_else(|_| ChatSession::default()),
132 Err(_) => ChatSession::default(),
133 }
134}
135
136pub fn save_chat_session(session: &ChatSession) -> bool {
138 let path = chat_history_path();
139 if let Some(parent) = path.parent() {
140 let _ = fs::create_dir_all(parent);
141 }
142 match serde_json::to_string_pretty(session) {
143 Ok(json) => fs::write(&path, json).is_ok(),
144 Err(_) => false,
145 }
146}