j_cli/command/chat/
model.rs1use super::theme::ThemeName;
2use crate::config::YamlConfig;
3use crate::error;
4use serde::{Deserialize, Serialize};
5use std::fs;
6use std::path::PathBuf;
7
8#[derive(Debug, Clone, Serialize, Deserialize)]
12pub struct ModelProvider {
13 pub name: String,
15 pub api_base: String,
17 pub api_key: String,
19 pub model: String,
21}
22
23#[derive(Debug, Clone, Serialize, Deserialize, Default)]
25pub struct AgentConfig {
26 #[serde(default)]
28 pub providers: Vec<ModelProvider>,
29 #[serde(default)]
31 pub active_index: usize,
32 #[serde(default)]
34 pub system_prompt: Option<String>,
35 #[serde(default = "default_stream_mode")]
37 pub stream_mode: bool,
38 #[serde(default = "default_max_history_messages")]
40 pub max_history_messages: usize,
41 #[serde(default)]
43 pub theme: ThemeName,
44}
45
46fn default_max_history_messages() -> usize {
47 20
48}
49
50fn default_stream_mode() -> bool {
52 true
53}
54
55#[derive(Debug, Clone, Serialize, Deserialize)]
57pub struct ChatMessage {
58 pub role: String, pub content: String,
60}
61
62#[derive(Debug, Clone, Serialize, Deserialize, Default)]
64pub struct ChatSession {
65 pub messages: Vec<ChatMessage>,
66}
67
68pub fn agent_data_dir() -> PathBuf {
72 let dir = YamlConfig::data_dir().join("agent").join("data");
73 let _ = fs::create_dir_all(&dir);
74 dir
75}
76
77pub fn agent_config_path() -> PathBuf {
79 agent_data_dir().join("agent_config.json")
80}
81
82pub fn chat_history_path() -> PathBuf {
84 agent_data_dir().join("chat_history.json")
85}
86
87pub fn load_agent_config() -> AgentConfig {
91 let path = agent_config_path();
92 if !path.exists() {
93 return AgentConfig::default();
94 }
95 match fs::read_to_string(&path) {
96 Ok(content) => serde_json::from_str(&content).unwrap_or_else(|e| {
97 error!("❌ 解析 agent_config.json 失败: {}", e);
98 AgentConfig::default()
99 }),
100 Err(e) => {
101 error!("❌ 读取 agent_config.json 失败: {}", e);
102 AgentConfig::default()
103 }
104 }
105}
106
107pub fn save_agent_config(config: &AgentConfig) -> bool {
109 let path = agent_config_path();
110 if let Some(parent) = path.parent() {
111 let _ = fs::create_dir_all(parent);
112 }
113 match serde_json::to_string_pretty(config) {
114 Ok(json) => match fs::write(&path, json) {
115 Ok(_) => true,
116 Err(e) => {
117 error!("❌ 保存 agent_config.json 失败: {}", e);
118 false
119 }
120 },
121 Err(e) => {
122 error!("❌ 序列化 agent 配置失败: {}", e);
123 false
124 }
125 }
126}
127
128pub fn load_chat_session() -> ChatSession {
130 let path = chat_history_path();
131 if !path.exists() {
132 return ChatSession::default();
133 }
134 match fs::read_to_string(&path) {
135 Ok(content) => serde_json::from_str(&content).unwrap_or_else(|_| ChatSession::default()),
136 Err(_) => ChatSession::default(),
137 }
138}
139
140pub fn save_chat_session(session: &ChatSession) -> bool {
142 let path = chat_history_path();
143 if let Some(parent) = path.parent() {
144 let _ = fs::create_dir_all(parent);
145 }
146 match serde_json::to_string_pretty(session) {
147 Ok(json) => fs::write(&path, json).is_ok(),
148 Err(_) => false,
149 }
150}