This commit is contained in:
2025-06-09 02:32:45 +09:00
parent 6dadc41da7
commit 5564db014a
68 changed files with 265 additions and 11470 deletions

View File

@ -1,54 +0,0 @@
use aigpt::config::Config;
use anyhow::Result;
fn main() -> Result<()> {
println!("Testing configuration loading...");
// Debug: check which JSON files exist
let possible_paths = vec![
"../config.json",
"config.json",
"gpt/config.json",
"/Users/syui/ai/ai/gpt/config.json",
];
println!("Checking for config.json files:");
for path in &possible_paths {
let path_buf = std::path::PathBuf::from(path);
if path_buf.exists() {
println!(" ✓ Found: {}", path);
} else {
println!(" ✗ Not found: {}", path);
}
}
// Load configuration
let config = Config::new(None)?;
println!("Configuration loaded successfully!");
println!("Default provider: {}", config.default_provider);
println!("Available providers:");
for (name, provider) in &config.providers {
println!(" - {}: model={}, host={:?}",
name,
provider.default_model,
provider.host);
}
if let Some(mcp) = &config.mcp {
println!("\nMCP Configuration:");
println!(" Enabled: {}", mcp.enabled);
println!(" Auto-detect: {}", mcp.auto_detect);
println!(" Servers: {}", mcp.servers.len());
}
if let Some(atproto) = &config.atproto {
println!("\nATProto Configuration:");
println!(" Host: {}", atproto.host);
println!(" Handle: {:?}", atproto.handle);
}
println!("\nConfig file path: {}", config.data_dir.join("config.json").display());
Ok(())
}

View File

@ -575,16 +575,16 @@ impl DocsManager {
std::fs::write(&title_path, &home_content)?;
println!(" ✓ Updated: {}", "title.md".green());
// auto/ディレクトリの更新
let auto_dir = ai_wiki_path.join("auto");
std::fs::create_dir_all(&auto_dir)?;
// プロジェクト個別ディレクトリの更新
let projects = self.discover_projects()?;
for project in projects {
let auto_content = self.generate_auto_project_content(&project).await?;
let auto_file = auto_dir.join(format!("{}.md", project));
std::fs::write(&auto_file, auto_content)?;
println!(" ✓ Updated: {}", format!("auto/{}.md", project).green());
let project_dir = ai_wiki_path.join(&project);
std::fs::create_dir_all(&project_dir)?;
let project_content = self.generate_auto_project_content(&project).await?;
let project_file = project_dir.join(format!("{}.md", project));
std::fs::write(&project_file, project_content)?;
println!(" ✓ Updated: {}", format!("{}/{}.md", project, project).green());
}
println!("{}", "✅ ai.wiki updated successfully".green().bold());
@ -630,7 +630,7 @@ impl DocsManager {
if let Some(projects_in_category) = project_sections.get(category) {
for (project, info) in projects_in_category {
content.push_str(&format!("#### [{}](auto/{}.md)\n", project, project));
content.push_str(&format!("#### [{}]({}.md)\n", project, project));
if !info.description.is_empty() {
content.push_str(&format!("- **名前**: ai.{} - **パッケージ**: ai{} - **タイプ**: {} - **役割**: {}\n\n",
@ -638,14 +638,15 @@ impl DocsManager {
}
content.push_str(&format!("**Status**: {} \n", info.status));
content.push_str(&format!("**Links**: [Repo](https://git.syui.ai/ai/{}) | [Docs](https://git.syui.ai/ai/{}/src/branch/main/claude.md)\n\n", project, project));
let branch = self.get_project_branch(project);
content.push_str(&format!("**Links**: [Repo](https://git.syui.ai/ai/{}) | [Docs](https://git.syui.ai/ai/{}/src/branch/{}/claude.md)\n\n", project, project, branch));
}
}
}
content.push_str("---\n\n");
content.push_str("## ディレクトリ構成\n\n");
content.push_str("- `auto/` - 自動生成されたプロジェクト概要\n");
content.push_str("- `{project}/` - プロジェクト個別ドキュメント\n");
content.push_str("- `claude/` - Claude Code作業記録\n");
content.push_str("- `manual/` - 手動作成ドキュメント\n\n");
content.push_str("---\n\n");
@ -655,7 +656,7 @@ impl DocsManager {
Ok(content)
}
/// auto/プロジェクトファイルのコンテンツ生成
/// プロジェクト個別ファイルのコンテンツ生成
async fn generate_auto_project_content(&self, project: &str) -> Result<String> {
let info = self.load_project_info(project).unwrap_or_default();
let mut content = String::new();
@ -669,7 +670,8 @@ impl DocsManager {
content.push_str(&format!("- **タイプ**: {}\n", info.project_type));
content.push_str(&format!("- **説明**: {}\n", info.description));
content.push_str(&format!("- **ステータス**: {}\n", info.status));
content.push_str("- **ブランチ**: main\n");
let branch = self.get_project_branch(project);
content.push_str(&format!("- **ブランチ**: {}\n", branch));
content.push_str("- **最終更新**: Unknown\n\n");
// プロジェクト固有の機能情報を追加
@ -684,7 +686,8 @@ impl DocsManager {
content.push_str("## リンク\n");
content.push_str(&format!("- **Repository**: https://git.syui.ai/ai/{}\n", project));
content.push_str(&format!("- **Project Documentation**: [claude/projects/{}.md](https://git.syui.ai/ai/ai/src/branch/main/claude/projects/{}.md)\n", project, project));
content.push_str(&format!("- **Generated Documentation**: [{}/claude.md](https://git.syui.ai/ai/{}/src/branch/main/claude.md)\n\n", project, project));
let branch = self.get_project_branch(project);
content.push_str(&format!("- **Generated Documentation**: [{}/claude.md](https://git.syui.ai/ai/{}/src/branch/{}/claude.md)\n\n", project, project, branch));
content.push_str("---\n");
content.push_str(&format!("*このページは claude/projects/{}.md から自動生成されました*\n", project));
@ -761,4 +764,26 @@ impl DocsManager {
Ok(())
}
/// メインai.jsonからプロジェクトのブランチ情報を取得
fn get_project_branch(&self, project: &str) -> String {
let main_ai_json_path = self.ai_root.join("ai.json");
if main_ai_json_path.exists() {
if let Ok(content) = std::fs::read_to_string(&main_ai_json_path) {
if let Ok(json_data) = serde_json::from_str::<serde_json::Value>(&content) {
if let Some(ai_section) = json_data.get("ai") {
if let Some(project_data) = ai_section.get(project) {
if let Some(branch) = project_data.get("branch").and_then(|v| v.as_str()) {
return branch.to_string();
}
}
}
}
}
}
// デフォルトはmain
"main".to_string()
}
}

View File

@ -1,21 +1,110 @@
use anyhow::{anyhow, Result};
use reqwest::Client;
use serde_json::Value;
use serde::{Serialize, Deserialize};
use std::time::Duration;
use std::collections::HashMap;
/// Service configuration for unified service management
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ServiceConfig {
pub base_url: String,
pub timeout: Duration,
pub health_endpoint: String,
}
impl Default for ServiceConfig {
fn default() -> Self {
Self {
base_url: "http://localhost:8000".to_string(),
timeout: Duration::from_secs(30),
health_endpoint: "/health".to_string(),
}
}
}
/// HTTP client for inter-service communication
pub struct ServiceClient {
client: Client,
service_registry: HashMap<String, ServiceConfig>,
}
impl ServiceClient {
pub fn new() -> Self {
Self::with_default_services()
}
/// Create ServiceClient with default ai ecosystem services
pub fn with_default_services() -> Self {
let client = Client::builder()
.timeout(Duration::from_secs(30))
.build()
.expect("Failed to create HTTP client");
Self { client }
let mut service_registry = HashMap::new();
// Register default ai ecosystem services
service_registry.insert("ai.card".to_string(), ServiceConfig {
base_url: "http://localhost:8000".to_string(),
timeout: Duration::from_secs(30),
health_endpoint: "/health".to_string(),
});
service_registry.insert("ai.log".to_string(), ServiceConfig {
base_url: "http://localhost:8002".to_string(),
timeout: Duration::from_secs(30),
health_endpoint: "/health".to_string(),
});
service_registry.insert("ai.bot".to_string(), ServiceConfig {
base_url: "http://localhost:8003".to_string(),
timeout: Duration::from_secs(30),
health_endpoint: "/health".to_string(),
});
Self { client, service_registry }
}
/// Create ServiceClient with custom service registry
pub fn with_services(service_registry: HashMap<String, ServiceConfig>) -> Self {
let client = Client::builder()
.timeout(Duration::from_secs(30))
.build()
.expect("Failed to create HTTP client");
Self { client, service_registry }
}
/// Register a new service configuration
pub fn register_service(&mut self, name: String, config: ServiceConfig) {
self.service_registry.insert(name, config);
}
/// Get service configuration by name
pub fn get_service_config(&self, service: &str) -> Result<&ServiceConfig> {
self.service_registry.get(service)
.ok_or_else(|| anyhow!("Unknown service: {}", service))
}
/// Universal service method call
pub async fn call_service_method<T: Serialize>(
&self,
service: &str,
method: &str,
params: &T
) -> Result<Value> {
let config = self.get_service_config(service)?;
let url = format!("{}/{}", config.base_url.trim_end_matches('/'), method.trim_start_matches('/'));
self.post_request(&url, &serde_json::to_value(params)?).await
}
/// Universal service GET call
pub async fn call_service_get(&self, service: &str, endpoint: &str) -> Result<Value> {
let config = self.get_service_config(service)?;
let url = format!("{}/{}", config.base_url.trim_end_matches('/'), endpoint.trim_start_matches('/'));
self.get_request(&url).await
}
/// Check if a service is available
@ -68,18 +157,50 @@ impl ServiceClient {
/// Get user's card collection from ai.card service
pub async fn get_user_cards(&self, user_did: &str) -> Result<Value> {
let url = format!("http://localhost:8000/api/v1/cards/user/{}", user_did);
self.get_request(&url).await
let endpoint = format!("api/v1/cards/user/{}", user_did);
self.call_service_get("ai.card", &endpoint).await
}
/// Draw a card for user from ai.card service
pub async fn draw_card(&self, user_did: &str, is_paid: bool) -> Result<Value> {
let payload = serde_json::json!({
let params = serde_json::json!({
"user_did": user_did,
"is_paid": is_paid
});
self.post_request("http://localhost:8000/api/v1/cards/draw", &payload).await
self.call_service_method("ai.card", "api/v1/cards/draw", &params).await
}
/// Get card statistics from ai.card service
pub async fn get_card_stats(&self) -> Result<Value> {
self.call_service_get("ai.card", "api/v1/cards/gacha-stats").await
}
// MARK: - ai.log service methods
/// Create a new blog post
pub async fn create_blog_post<T: Serialize>(&self, params: &T) -> Result<Value> {
self.call_service_method("ai.log", "api/v1/posts", params).await
}
/// Get list of blog posts
pub async fn get_blog_posts(&self) -> Result<Value> {
self.call_service_get("ai.log", "api/v1/posts").await
}
/// Build the blog
pub async fn build_blog(&self) -> Result<Value> {
self.call_service_method("ai.log", "api/v1/build", &serde_json::json!({})).await
}
/// Translate document using ai.log service
pub async fn translate_document<T: Serialize>(&self, params: &T) -> Result<Value> {
self.call_service_method("ai.log", "api/v1/translate", params).await
}
/// Generate documentation using ai.log service
pub async fn generate_docs<T: Serialize>(&self, params: &T) -> Result<Value> {
self.call_service_method("ai.log", "api/v1/docs", params).await
}
}

View File

@ -1860,38 +1860,63 @@ async fn execute_command_handler(
}
}
// AI Card proxy handlers (TODO: Fix ServiceClient method visibility)
// AI Card proxy handlers
async fn get_user_cards_handler(
State(_state): State<AppState>,
State(state): State<AppState>,
AxumPath(user_id): AxumPath<String>,
) -> Json<MCPHttpResponse> {
// TODO: Implement proper ai.card service integration
Json(MCPHttpResponse {
success: false,
result: None,
error: Some(format!("AI Card service integration not yet implemented for user: {}", user_id)),
})
let server = state.lock().await;
match server.service_client.get_user_cards(&user_id).await {
Ok(cards) => Json(MCPHttpResponse {
success: true,
result: Some(cards),
error: None,
}),
Err(e) => Json(MCPHttpResponse {
success: false,
result: None,
error: Some(format!("Failed to get user cards: {}", e)),
}),
}
}
async fn draw_card_handler(
State(_state): State<AppState>,
Json(_request): Json<MCPHttpRequest>,
State(state): State<AppState>,
Json(request): Json<MCPHttpRequest>,
) -> Json<MCPHttpResponse> {
// TODO: Implement proper ai.card service integration
Json(MCPHttpResponse {
success: false,
result: None,
error: Some("AI Card draw service integration not yet implemented".to_string()),
})
// Extract user_did from user_id field, default is_paid to false for now
let user_did = request.user_id.as_deref().unwrap_or("unknown");
let is_paid = false; // TODO: Add is_paid field to MCPHttpRequest if needed
let server = state.lock().await;
match server.service_client.draw_card(user_did, is_paid).await {
Ok(card) => Json(MCPHttpResponse {
success: true,
result: Some(card),
error: None,
}),
Err(e) => Json(MCPHttpResponse {
success: false,
result: None,
error: Some(format!("Failed to draw card: {}", e)),
}),
}
}
async fn get_card_stats_handler(State(_state): State<AppState>) -> Json<MCPHttpResponse> {
// TODO: Implement proper ai.card service integration
Json(MCPHttpResponse {
success: false,
result: None,
error: Some("AI Card stats service integration not yet implemented".to_string()),
})
async fn get_card_stats_handler(State(state): State<AppState>) -> Json<MCPHttpResponse> {
let server = state.lock().await;
match server.service_client.get_card_stats().await {
Ok(stats) => Json(MCPHttpResponse {
success: true,
result: Some(stats),
error: None,
}),
Err(e) => Json(MCPHttpResponse {
success: false,
result: None,
error: Some(format!("Failed to get card stats: {}", e)),
}),
}
}
// AI Log proxy handlers (placeholder - these would need to be implemented)