Skip to main content

j_cli/command/chat/
mod.rs

1pub mod api;
2pub mod app;
3pub mod archive;
4pub mod handler;
5pub mod markdown;
6pub mod model;
7pub mod render;
8pub mod skill;
9pub mod theme;
10pub mod tools;
11pub mod ui;
12
13use crate::command::chat::theme::ThemeName;
14use crate::config::YamlConfig;
15use crate::{error, info};
16use api::call_openai_stream;
17use handler::run_chat_tui;
18use model::{
19    AgentConfig, ChatMessage, ModelProvider, agent_config_path, load_agent_config,
20    load_system_prompt, save_agent_config, save_system_prompt,
21};
22use std::io::{self, Write};
23
24pub fn handle_chat(content: &[String], _config: &YamlConfig) {
25    let mut agent_config = load_agent_config();
26    if let Some(file_prompt) = load_system_prompt() {
27        agent_config.system_prompt = Some(file_prompt);
28    } else if let Some(config_prompt) = agent_config.system_prompt.clone() {
29        let _ = save_system_prompt(&config_prompt);
30    }
31
32    if agent_config.providers.is_empty() {
33        info!("⚠️  尚未配置 LLM 模型提供方。");
34        info!("📁 请编辑配置文件: {}", agent_config_path().display());
35        info!("📝 配置示例:");
36        let example = AgentConfig {
37            providers: vec![ModelProvider {
38                name: "GPT-4o".to_string(),
39                api_base: "https://api.openai.com/v1".to_string(),
40                api_key: "sk-your-api-key".to_string(),
41                model: "gpt-4o".to_string(),
42            }],
43            active_index: 0,
44            system_prompt: None,
45            stream_mode: true,
46            max_history_messages: 20,
47            theme: ThemeName::default(),
48            tools_enabled: false,
49            max_tool_rounds: 10,
50            style: None,
51        };
52        if let Ok(json) = serde_json::to_string_pretty(&example) {
53            println!("{}", json);
54        }
55        let _ = save_system_prompt("你是一个有用的助手。");
56        // 自动创建示例配置文件
57        if !agent_config_path().exists() {
58            let _ = save_agent_config(&example);
59            info!(
60                "✅ 已自动创建示例配置文件: {}",
61                agent_config_path().display()
62            );
63            info!("📌 请修改其中的 api_key 和其他配置后重新运行 chat 命令");
64        }
65        return;
66    }
67
68    if content.is_empty() {
69        // 无参数:进入 TUI 对话界面
70        run_chat_tui();
71        return;
72    }
73
74    // 有参数:快速发送消息并打印回复
75    let message = content.join(" ");
76    let message = message.trim().to_string();
77    if message.is_empty() {
78        error!("⚠️ 消息内容为空");
79        return;
80    }
81
82    let idx = agent_config
83        .active_index
84        .min(agent_config.providers.len() - 1);
85    let provider = &agent_config.providers[idx];
86
87    info!("🤖 [{}] 思考中...", provider.name);
88
89    let mut messages = Vec::new();
90    messages.push(ChatMessage::text("user", message));
91
92    match call_openai_stream(
93        provider,
94        &messages,
95        agent_config.system_prompt.as_deref(),
96        &mut |chunk| {
97            print!("{}", chunk);
98            let _ = io::stdout().flush();
99        },
100    ) {
101        Ok(_) => {
102            println!(); // 换行
103        }
104        Err(e) => {
105            error!("\n❌ {}", e);
106        }
107    }
108}