From 6fdc5733581abd18496debe9972e44e52fbb6350 Mon Sep 17 00:00:00 2001 From: syui Date: Wed, 21 May 2025 22:33:11 +0900 Subject: [PATCH] add git-repo --- README.md | 8 +++++++ src/chat.rs | 6 ++--- src/commands/git_repo.rs | 17 ++++++++++++++ src/commands/mcp.rs | 50 ++++++++++++++++++++++++++++++++++++++-- src/commands/mod.rs | 1 + 5 files changed, 77 insertions(+), 5 deletions(-) create mode 100644 src/commands/git_repo.rs diff --git a/README.md b/README.md index a1d4faa..2db50e4 100644 --- a/README.md +++ b/README.md @@ -35,5 +35,13 @@ $ ./aigpt mcp chat "hello world!" --host http://localhost:11434 --model syui/ai # openai api $ ./aigpt mcp set-api -api sk-abc123 $ ./aigpt mcp chat "こんにちは" -p openai -m gpt-4o-mini + +--- +# git管理されているファイルをAIに読ませる +./aigpt mcp chat --host http://localhost:11434 --repo git@git.syui.ai:ai/gpt +**改善案と次のステップ:** +1. **README.md の大幅な改善:** +**次のステップ:** +1. **README.md の作成:** 1. の指示に従って、README.md ファイルを作成します。 ``` diff --git a/src/chat.rs b/src/chat.rs index 12b4e9c..24b276f 100644 --- a/src/chat.rs +++ b/src/chat.rs @@ -43,7 +43,7 @@ fn load_openai_api_key() -> Option { Some(parsed.token) } -pub fn ask_chat(c: &Context, question: &str) { +pub fn ask_chat(c: &Context, question: &str) -> String { let config = ConfigPaths::new(); let base_dir = config.base_dir.join("mcp"); let script_path = base_dir.join("scripts/ask.py"); @@ -83,18 +83,18 @@ pub fn ask_chat(c: &Context, question: &str) { command.env("OPENAI_API_KEY", api_key); } - // 🔁 実行 let output = command .output() .expect("❌ MCPチャットスクリプトの実行に失敗しました"); if output.status.success() { - println!("💬 {}", String::from_utf8_lossy(&output.stdout)); + String::from_utf8_lossy(&output.stdout).to_string() } else { eprintln!( "❌ 実行エラー: {}\n{}", String::from_utf8_lossy(&output.stderr), String::from_utf8_lossy(&output.stdout), ); + String::from("エラーが発生しました。") } } diff --git a/src/commands/git_repo.rs b/src/commands/git_repo.rs new file mode 100644 index 0000000..c59ee94 --- /dev/null +++ b/src/commands/git_repo.rs @@ -0,0 +1,17 @@ +// src/commands/git_repo.rs +use std::fs; + +// Gitリポジトリ内の全てのファイルを取得し、内容を読み取る +pub fn read_all_git_files(repo_path: &str) -> String { + let mut content = String::new(); + for entry in fs::read_dir(repo_path).expect("ディレクトリ読み込み失敗") { + let entry = entry.expect("エントリ読み込み失敗"); + let path = entry.path(); + if path.is_file() { + if let Ok(file_content) = fs::read_to_string(&path) { + content.push_str(&format!("\n\n# File: {}\n{}", path.display(), file_content)); + } + } + } + content +} diff --git a/src/commands/mcp.rs b/src/commands/mcp.rs index c18b987..8b68064 100644 --- a/src/commands/mcp.rs +++ b/src/commands/mcp.rs @@ -5,10 +5,10 @@ use std::path::{PathBuf}; use std::process::Command as OtherCommand; use serde_json::json; use seahorse::{Command, Context, Flag, FlagType}; - use crate::chat::ask_chat; use crate::git::{git_init, git_status}; use crate::config::ConfigPaths; +use crate::commands::git_repo::read_all_git_files; pub fn mcp_setup() { let config = ConfigPaths::new(); @@ -153,13 +153,54 @@ fn chat_cmd() -> Command { .description("OpenAI APIキー") .alias("k"), ) + .flag( + Flag::new("repo", FlagType::String) + .description("Gitリポジトリのパスを指定 (すべてのコードを読み込む)") + .alias("r"), + ) .action(|c: &Context| { if let Some(question) = c.args.get(0) { - ask_chat(c, question); + let response = ask_chat(c, question); + println!("💬 応答:\n{}", response); } else { eprintln!("❗ 質問が必要です: mcp chat 'こんにちは'"); } }) + .action(|c: &Context| { + let config = ConfigPaths::new(); + if let Ok(repo_url) = c.string_flag("repo") { + let repo_base = config.base_dir.join("repos"); + let repo_dir = repo_base.join(sanitize_repo_name(&repo_url)); + + if !repo_dir.exists() { + println!("📥 Gitリポジトリをクローン中: {}", repo_url); + let status = OtherCommand::new("git") + .args(&["clone", &repo_url, repo_dir.to_str().unwrap()]) + .status() + .expect("❌ Gitのクローンに失敗しました"); + assert!(status.success(), "Git clone エラー"); + } else { + println!("✔ リポジトリはすでに存在します: {}", repo_dir.display()); + } + + //let files = read_all_git_files(&repo_dir); + let files = read_all_git_files(repo_dir.to_str().unwrap()); + let prompt = format!( + "以下のコードベースを読み込んで、改善案や次のステップを提案してください:\n{}", + files + ); + + let response = ask_chat(c, &prompt); + println!("💡 提案:\n{}", response); + } else { + if let Some(question) = c.args.get(0) { + let response = ask_chat(c, question); + println!("💬 {}", response); + } else { + eprintln!("❗ 質問が必要です: mcp chat 'こんにちは'"); + } + } + }) } fn init_cmd() -> Command { @@ -200,3 +241,8 @@ pub fn mcp_cmd() -> Command { .command(setup_cmd()) .command(set_api_key_cmd()) } + +// ファイル名として安全な形に変換 +fn sanitize_repo_name(repo_url: &str) -> String { + repo_url.replace("://", "_").replace("/", "_").replace("@", "_") +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs index c7db2bc..5fe1951 100644 --- a/src/commands/mod.rs +++ b/src/commands/mod.rs @@ -1,3 +1,4 @@ pub mod db; pub mod scheduler; pub mod mcp; +pub mod git_repo;