From 6824266a191165b1aa00fb4d87b69eabf9f508d6 Mon Sep 17 00:00:00 2001 From: syui Date: Tue, 20 May 2025 23:06:24 +0900 Subject: [PATCH] add db --- .gitignore | 2 ++ Cargo.toml | 1 + config/config.json | 2 +- src/cli.rs | 28 +++++++++++++--------------- src/commands/db.rs | 32 ++++++++++++++++++++++++++++++++ src/commands/mod.rs | 1 + src/main.rs | 2 ++ src/model.rs | 35 +++++++++++++++++++++++++++++++++-- src/utils.rs | 13 +++++++++++++ 9 files changed, 98 insertions(+), 18 deletions(-) create mode 100644 src/commands/db.rs create mode 100644 src/commands/mod.rs create mode 100644 src/utils.rs diff --git a/.gitignore b/.gitignore index 0cdcca2..d088031 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,4 @@ **target **.lock +output.json +config/*.db diff --git a/Cargo.toml b/Cargo.toml index 825acdb..21198f1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,3 +8,4 @@ serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = "0.4" seahorse = "*" +rusqlite = { version = "0.29", features = ["serde_json"] } diff --git a/config/config.json b/config/config.json index 0e485f0..6df5aef 100644 --- a/config/config.json +++ b/config/config.json @@ -4,7 +4,7 @@ "strength": 0.8 }, "relationship": { - "trust": 0.9, + "trust": 0.2, "intimacy": 0.6, "curiosity": 0.5, "threshold": 1.5 diff --git a/src/cli.rs b/src/cli.rs index 7736728..37cd8c5 100644 --- a/src/cli.rs +++ b/src/cli.rs @@ -1,23 +1,15 @@ //src/cli.rs use seahorse::{App, Command, Context}; -use crate::model::{AiSystem}; -use std::fs; +use crate::utils::{load_config, save_config}; +use crate::commands::db::{save_cmd, export_cmd}; use crate::agent::AIState; use chrono::{Duration, Local}; - -fn load_config(path: &str) -> AiSystem { - let data = fs::read_to_string(path).expect("JSON読み込み失敗"); - serde_json::from_str(&data).expect("JSONパース失敗") -} - -fn save_config(path: &str, ai: &AiSystem) { - let json = serde_json::to_string_pretty(&ai).expect("JSONシリアライズ失敗"); - fs::write(path, json).expect("JSON保存失敗"); -} +use rusqlite::Connection; pub fn cli_app() -> App { + let set_cmd = Command::new("set") .usage("set [trust|intimacy|curiosity] [value]") .action(|c: &Context| { @@ -32,8 +24,9 @@ pub fn cli_app() -> App { std::process::exit(1); }); - let path = "config/config.json"; - let mut ai = load_config(path); + let json_path = "config/config.json"; + let db_path = "config/ai_state.db"; + let mut ai = load_config(json_path); match field.as_str() { "trust" => ai.relationship.trust = value, @@ -44,8 +37,11 @@ pub fn cli_app() -> App { std::process::exit(1); } } + save_config(json_path, &ai); + + let conn = Connection::open(db_path).expect("DB接続失敗"); + ai.save_to_db(&conn).expect("DB保存失敗"); - save_config(path, &ai); println!("✅ {field} を {value} に更新しました"); }); @@ -87,4 +83,6 @@ pub fn cli_app() -> App { .command(set_cmd) .command(show_cmd) .command(talk_cmd) + .command(save_cmd()) + .command(export_cmd()) } diff --git a/src/commands/db.rs b/src/commands/db.rs new file mode 100644 index 0000000..1e3c342 --- /dev/null +++ b/src/commands/db.rs @@ -0,0 +1,32 @@ +// src/commands/db.rs +use seahorse::{Command, Context}; +use crate::utils::load_config; +use crate::model::AiSystem; +use rusqlite::Connection; +use std::fs; + +pub fn save_cmd() -> Command { + Command::new("save") + .usage("save") + .action(|_c: &Context| { + let ai = load_config("config/config.json"); + let conn = Connection::open("config/ai_state.db").expect("DB接続失敗"); + ai.save_to_db(&conn).expect("DB保存失敗"); + println!("💾 DBに保存完了"); + }) +} + +pub fn export_cmd() -> Command { + Command::new("export") + .usage("export [output.json]") + .action(|c: &Context| { + let path = c.args.get(0).map(|s| s.as_str()).unwrap_or("output.json"); + let conn = Connection::open("config/ai_state.db").expect("DB接続失敗"); + let ai = AiSystem::load_from_db(&conn).expect("DB読み込み失敗"); + + let json = serde_json::to_string_pretty(&ai).expect("JSON変換失敗"); + fs::write(path, json).expect("ファイル書き込み失敗"); + + println!("📤 JSONにエクスポート完了: {path}"); + }) +} diff --git a/src/commands/mod.rs b/src/commands/mod.rs new file mode 100644 index 0000000..dec1023 --- /dev/null +++ b/src/commands/mod.rs @@ -0,0 +1 @@ +pub mod db; diff --git a/src/main.rs b/src/main.rs index a62032b..9f8642d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -3,6 +3,8 @@ mod model; mod logic; mod agent; mod cli; +mod utils; +mod commands; use cli::cli_app; use seahorse::App; diff --git a/src/model.rs b/src/model.rs index edf406a..1aa3b10 100644 --- a/src/model.rs +++ b/src/model.rs @@ -1,4 +1,5 @@ //src/model.rs +use rusqlite::{params, Connection, Result as SqlResult}; use serde::{Deserialize, Serialize}; #[derive(Debug, Serialize, Deserialize)] @@ -9,6 +10,38 @@ pub struct AiSystem { pub messaging: Messaging, } +impl AiSystem { + pub fn save_to_db(&self, conn: &Connection) -> SqlResult<()> { + conn.execute( + "CREATE TABLE IF NOT EXISTS ai_state (id INTEGER PRIMARY KEY, json TEXT)", + [], + )?; + + let json_data = serde_json::to_string(self).map_err(|e| { + rusqlite::Error::ToSqlConversionFailure(Box::new(e)) + })?; + + conn.execute( + "INSERT OR REPLACE INTO ai_state (id, json) VALUES (?1, ?2)", + params![1, json_data], + )?; + + Ok(()) + } + + pub fn load_from_db(conn: &Connection) -> SqlResult { + let mut stmt = conn.prepare("SELECT json FROM ai_state WHERE id = ?1")?; + let json: String = stmt.query_row(params![1], |row| row.get(0))?; + + // ここも serde_json のエラーを map_err で変換 + let system: AiSystem = serde_json::from_str(&json).map_err(|e| { + rusqlite::Error::FromSqlConversionFailure(0, rusqlite::types::Type::Text, Box::new(e)) + })?; + + Ok(system) + } +} + #[derive(Debug, Serialize, Deserialize)] pub struct Personality { pub kind: String, // e.g., "positive", "negative", "neutral" @@ -37,5 +70,3 @@ pub struct Messaging { pub decay_rate: f32, // how quickly emotion fades (0.0 - 1.0) pub templates: Vec, // message template variations } - - diff --git a/src/utils.rs b/src/utils.rs new file mode 100644 index 0000000..3fd757a --- /dev/null +++ b/src/utils.rs @@ -0,0 +1,13 @@ +// src/utils.rs +use std::fs; +use crate::model::AiSystem; + +pub fn load_config(path: &str) -> AiSystem { + let data = fs::read_to_string(path).expect("JSON読み込み失敗"); + serde_json::from_str(&data).expect("JSONパース失敗") +} + +pub fn save_config(path: &str, ai: &AiSystem) { + let json = serde_json::to_string_pretty(&ai).expect("JSONシリアライズ失敗"); + fs::write(path, json).expect("JSON保存失敗"); +}