add extended
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -21,3 +21,4 @@ Thumbs.db
|
|||||||
*.log
|
*.log
|
||||||
json
|
json
|
||||||
gpt
|
gpt
|
||||||
|
.claude
|
||||||
|
21
Cargo.toml
21
Cargo.toml
@@ -5,10 +5,19 @@ edition = "2021"
|
|||||||
authors = ["syui"]
|
authors = ["syui"]
|
||||||
description = "Simple memory storage for Claude with MCP"
|
description = "Simple memory storage for Claude with MCP"
|
||||||
|
|
||||||
|
|
||||||
[[bin]]
|
[[bin]]
|
||||||
name = "aigpt"
|
name = "aigpt"
|
||||||
path = "src/main.rs"
|
path = "src/main.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "memory-mcp"
|
||||||
|
path = "src/mcp_server.rs"
|
||||||
|
|
||||||
|
[[bin]]
|
||||||
|
name = "memory-mcp-extended"
|
||||||
|
path = "extended/src/mcp_server.rs"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
# CLI and async
|
# CLI and async
|
||||||
clap = { version = "4.5", features = ["derive"] }
|
clap = { version = "4.5", features = ["derive"] }
|
||||||
@@ -25,3 +34,15 @@ uuid = { version = "1.10", features = ["v4"] }
|
|||||||
# Error handling and utilities
|
# Error handling and utilities
|
||||||
anyhow = "1.0"
|
anyhow = "1.0"
|
||||||
dirs = "5.0"
|
dirs = "5.0"
|
||||||
|
|
||||||
|
# Extended features (optional)
|
||||||
|
reqwest = { version = "0.11", features = ["json"], optional = true }
|
||||||
|
scraper = { version = "0.18", optional = true }
|
||||||
|
openai = { version = "1.1", optional = true }
|
||||||
|
|
||||||
|
[features]
|
||||||
|
default = []
|
||||||
|
extended = ["semantic-search", "ai-analysis", "web-integration"]
|
||||||
|
semantic-search = ["openai"]
|
||||||
|
ai-analysis = ["openai"]
|
||||||
|
web-integration = ["reqwest", "scraper"]
|
||||||
|
98
claude.md
98
claude.md
@@ -6,30 +6,90 @@ claude desktop, claude codeで使用できるmemory機能をmcpで作ります
|
|||||||
2. chatgptのjsonをimportできる @json/
|
2. chatgptのjsonをimportできる @json/
|
||||||
3. rustで作る
|
3. rustで作る
|
||||||
|
|
||||||
## 自動メモリー保存のルール
|
## 自動実行設定
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"mcp_auto_execute": true,
|
||||||
|
"memory_auto_save": true,
|
||||||
|
"memory_auto_search": true,
|
||||||
|
"trigger_sensitivity": "high"
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
以下の情報が会話に現れた場合、自動的にcreate_memory MCPツールを使用して保存してください:
|
## 自動メモリー保存のルール(強化版)
|
||||||
|
|
||||||
1. **ユーザーの個人情報**
|
**即座に自動実行** - 以下の情報が会話に現れた瞬間、create_memory MCPツールを自動実行:
|
||||||
- 名前、誕生日、住所など
|
|
||||||
- 好きなもの、嫌いなもの
|
|
||||||
- 習慣や予定
|
|
||||||
|
|
||||||
2. **重要な決定事項**
|
### 1. **ユーザーの個人情報**
|
||||||
- プロジェクトの決定
|
**トリガーワード**: 名前、誕生日、住所、年齢、職業、家族、出身
|
||||||
- 設定の変更
|
- 基本情報: 名前、誕生日、住所、年齢、性別
|
||||||
- 今後の計画
|
- 関係性: 家族構成、恋人、友人関係
|
||||||
|
- 好み: 好きなもの、嫌いなもの、趣味、音楽、映画、本
|
||||||
|
- 習慣: 日課、スケジュール、ルーティン
|
||||||
|
- 価値観: 信念、考え方、人生観
|
||||||
|
|
||||||
3. **技術的な解決策**
|
### 2. **重要な決定事項**
|
||||||
- 問題の解決方法
|
**トリガーワード**: 決めた、決定、方針、計画、予定、目標
|
||||||
- 有用なコマンドやコード
|
- プロジェクト方針の決定
|
||||||
- 設定手順
|
- 技術選択の決定
|
||||||
|
- 設定・環境の変更
|
||||||
|
- 今後のロードマップ
|
||||||
|
- 作業分担・役割
|
||||||
|
|
||||||
## 自動メモリー検索のルール
|
### 3. **技術的な解決策**
|
||||||
|
**トリガーワード**: 解決、修正、対処、設定、インストール、手順
|
||||||
|
- エラーの解決方法
|
||||||
|
- 有用なコマンド・スクリプト
|
||||||
|
- 設定手順・インストール方法
|
||||||
|
- デバッグテクニック
|
||||||
|
- 最適化手法
|
||||||
|
|
||||||
以下の場合、自動的にsearch_memories MCPツールを使用してください:
|
### 4. **学習・発見事項**
|
||||||
|
**トリガーワード**: 学んだ、わかった、発見、理解、気づき
|
||||||
|
- 新しい知識・概念の理解
|
||||||
|
- ツール・ライブラリの使い方
|
||||||
|
- ベストプラクティス
|
||||||
|
- 失敗から得た教訓
|
||||||
|
|
||||||
1. ユーザーが「前に話した」「以前の」などと言及した場合
|
## 自動メモリー検索のルール(強化版)
|
||||||
2. 過去の会話や情報を参照する必要がある場合
|
|
||||||
3. ユーザーの好みや設定を確認する必要がある場合
|
**会話開始時に自動実行** - search_memories を実行してコンテキストを取得
|
||||||
|
|
||||||
|
**即座に自動実行** - 以下の場合、search_memories MCPツールを自動実行:
|
||||||
|
|
||||||
|
### 1. **過去参照キーワード検出**
|
||||||
|
**トリガーワード**: 前に、以前、昔、過去、先ほど、さっき、この間
|
||||||
|
- 「前に話した〜」
|
||||||
|
- 「以前設定した〜」
|
||||||
|
- 「昔やった〜」
|
||||||
|
|
||||||
|
### 2. **記憶呼び出しキーワード**
|
||||||
|
**トリガーワード**: 覚えている、記録、メモ、保存、履歴
|
||||||
|
- 「覚えていますか?」
|
||||||
|
- 「記録していた〜」
|
||||||
|
- 「メモした〜」
|
||||||
|
|
||||||
|
### 3. **設定・好み確認**
|
||||||
|
**トリガーワード**: 好み、設定、環境、構成、preferences
|
||||||
|
- ユーザーの好みを確認する必要がある場合
|
||||||
|
- 過去の設定を参照する必要がある場合
|
||||||
|
- 環境構成を確認する必要がある場合
|
||||||
|
|
||||||
|
### 4. **不明な参照**
|
||||||
|
- ユーザーが具体的でない参照をした場合
|
||||||
|
- 「あれ」「それ」「例のやつ」などの曖昧な表現
|
||||||
|
- 文脈から過去の情報が必要と判断される場合
|
||||||
|
|
||||||
|
## 自動実行タイミング
|
||||||
|
|
||||||
|
1. **会話開始時**: search_memories を実行してコンテキスト取得
|
||||||
|
2. **リアルタイム**: トリガーワード検出後、即座にMCPツール実行
|
||||||
|
3. **会話終了時**: 重要な情報があれば create_memory で保存
|
||||||
|
4. **定期的**: 長い会話では中間地点でメモリー整理
|
||||||
|
|
||||||
|
## エラーハンドリング
|
||||||
|
|
||||||
|
- MCPツールが利用できない場合は通常の会話を継続
|
||||||
|
- メモリー保存失敗時はユーザーに通知
|
||||||
|
- 検索結果が空の場合も適切に対応
|
||||||
|
|
||||||
|
125
docs/README_CONFIG.md
Normal file
125
docs/README_CONFIG.md
Normal file
@@ -0,0 +1,125 @@
|
|||||||
|
# Claude Memory MCP 設定ガイド
|
||||||
|
|
||||||
|
## モード選択
|
||||||
|
|
||||||
|
### 標準モード (Simple Mode)
|
||||||
|
- 基本的なメモリー機能のみ
|
||||||
|
- 軽量で高速
|
||||||
|
- 最小限の依存関係
|
||||||
|
|
||||||
|
### 拡張モード (Extended Mode)
|
||||||
|
- AI分析機能
|
||||||
|
- セマンティック検索
|
||||||
|
- Web統合機能
|
||||||
|
- 高度なインサイト抽出
|
||||||
|
|
||||||
|
## ビルド・実行方法
|
||||||
|
|
||||||
|
### 標準モード
|
||||||
|
```bash
|
||||||
|
# MCPサーバー起動
|
||||||
|
cargo run --bin memory-mcp
|
||||||
|
|
||||||
|
# CLI実行
|
||||||
|
cargo run --bin aigpt -- create "メモリー内容"
|
||||||
|
```
|
||||||
|
|
||||||
|
### 拡張モード
|
||||||
|
```bash
|
||||||
|
# MCPサーバー起動
|
||||||
|
cargo run --bin memory-mcp-extended --features extended
|
||||||
|
|
||||||
|
# CLI実行
|
||||||
|
cargo run --bin aigpt-extended --features extended -- create "メモリー内容" --analyze
|
||||||
|
```
|
||||||
|
|
||||||
|
## 設定ファイルの配置
|
||||||
|
|
||||||
|
### 標準モード
|
||||||
|
|
||||||
|
#### Claude Desktop
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
cp claude_desktop_config.json ~/.config/claude-desktop/claude_desktop_config.json
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
cp claude_desktop_config.json %APPDATA%\Claude\claude_desktop_config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Claude Code
|
||||||
|
```bash
|
||||||
|
# プロジェクトルートまたはグローバル設定
|
||||||
|
cp claude_code_config.json .claude/config.json
|
||||||
|
# または
|
||||||
|
cp claude_code_config.json ~/.claude/config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
### 拡張モード
|
||||||
|
|
||||||
|
#### Claude Desktop
|
||||||
|
```bash
|
||||||
|
# macOS
|
||||||
|
cp claude_desktop_config_extended.json ~/.config/claude-desktop/claude_desktop_config.json
|
||||||
|
|
||||||
|
# Windows
|
||||||
|
cp claude_desktop_config_extended.json %APPDATA%\Claude\claude_desktop_config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Claude Code
|
||||||
|
```bash
|
||||||
|
# プロジェクトルートまたはグローバル設定
|
||||||
|
cp claude_code_config_extended.json .claude/config.json
|
||||||
|
# または
|
||||||
|
cp claude_code_config_extended.json ~/.claude/config.json
|
||||||
|
```
|
||||||
|
|
||||||
|
## 環境変数設定
|
||||||
|
|
||||||
|
```bash
|
||||||
|
export MEMORY_AUTO_EXECUTE=true
|
||||||
|
export MEMORY_AUTO_SAVE=true
|
||||||
|
export MEMORY_AUTO_SEARCH=true
|
||||||
|
export TRIGGER_SENSITIVITY=high
|
||||||
|
export MEMORY_DB_PATH=~/.claude/memory.db
|
||||||
|
```
|
||||||
|
|
||||||
|
## 設定オプション
|
||||||
|
|
||||||
|
### auto_execute
|
||||||
|
- `true`: 自動でMCPツールを実行
|
||||||
|
- `false`: 手動実行のみ
|
||||||
|
|
||||||
|
### trigger_sensitivity
|
||||||
|
- `high`: 多くのキーワードで反応
|
||||||
|
- `medium`: 適度な反応
|
||||||
|
- `low`: 明確なキーワードのみ
|
||||||
|
|
||||||
|
### max_memories
|
||||||
|
メモリーの最大保存数
|
||||||
|
|
||||||
|
### search_limit
|
||||||
|
検索結果の最大表示数
|
||||||
|
|
||||||
|
## カスタマイズ
|
||||||
|
|
||||||
|
`trigger_words`セクションでトリガーワードをカスタマイズ可能:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"trigger_words": {
|
||||||
|
"custom_category": ["カスタム", "キーワード", "リスト"]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## トラブルシューティング
|
||||||
|
|
||||||
|
1. MCPサーバーが起動しない場合:
|
||||||
|
- Rustがインストールされているか確認
|
||||||
|
- `cargo build --release`でビルド確認
|
||||||
|
|
||||||
|
2. 自動実行されない場合:
|
||||||
|
- 環境変数が正しく設定されているか確認
|
||||||
|
- トリガーワードが含まれているか確認
|
||||||
|
|
||||||
|
3. メモリーが保存されない場合:
|
||||||
|
- データベースファイルのパスが正しいか確認
|
||||||
|
- 書き込み権限があるか確認
|
58
docs/claude_code_config.json
Normal file
58
docs/claude_code_config.json
Normal file
@@ -0,0 +1,58 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"memory": {
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["run", "--release", "--bin", "memory-mcp"],
|
||||||
|
"cwd": "/Users/syui/ai/ai/gpt",
|
||||||
|
"env": {
|
||||||
|
"MEMORY_AUTO_EXECUTE": "true",
|
||||||
|
"MEMORY_AUTO_SAVE": "true",
|
||||||
|
"MEMORY_AUTO_SEARCH": "true",
|
||||||
|
"TRIGGER_SENSITIVITY": "high",
|
||||||
|
"MEMORY_DB_PATH": "~/.claude/memory.db"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"memory": {
|
||||||
|
"enabled": true,
|
||||||
|
"auto_execute": true
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"memory_integration": true,
|
||||||
|
"auto_save_on_file_change": true,
|
||||||
|
"auto_search_on_context_switch": true
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"auto_execute": true,
|
||||||
|
"auto_save": true,
|
||||||
|
"auto_search": true,
|
||||||
|
"trigger_sensitivity": "high",
|
||||||
|
"max_memories": 10000,
|
||||||
|
"search_limit": 50,
|
||||||
|
"session_memory": true,
|
||||||
|
"cross_session_memory": true,
|
||||||
|
"trigger_words": {
|
||||||
|
"personal_info": ["名前", "誕生日", "住所", "年齢", "職業", "家族", "出身", "好き", "嫌い", "趣味"],
|
||||||
|
"decisions": ["決めた", "決定", "方針", "計画", "予定", "目標"],
|
||||||
|
"solutions": ["解決", "修正", "対処", "設定", "インストール", "手順"],
|
||||||
|
"learning": ["学んだ", "わかった", "発見", "理解", "気づき"],
|
||||||
|
"past_reference": ["前に", "以前", "昔", "過去", "先ほど", "さっき", "この間"],
|
||||||
|
"memory_recall": ["覚えている", "記録", "メモ", "保存", "履歴"],
|
||||||
|
"preferences": ["好み", "設定", "環境", "構成", "preferences"],
|
||||||
|
"vague_reference": ["あれ", "それ", "例のやつ"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hooks": {
|
||||||
|
"on_conversation_start": [
|
||||||
|
"search_memories --limit 10 --recent"
|
||||||
|
],
|
||||||
|
"on_trigger_word": [
|
||||||
|
"auto_execute_memory_tools"
|
||||||
|
],
|
||||||
|
"on_conversation_end": [
|
||||||
|
"save_important_memories"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
81
docs/claude_code_config_extended.json
Normal file
81
docs/claude_code_config_extended.json
Normal file
@@ -0,0 +1,81 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"memory-extended": {
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["run", "--bin", "memory-mcp-extended", "--features", "extended"],
|
||||||
|
"cwd": "/Users/syui/ai/ai/gpt",
|
||||||
|
"env": {
|
||||||
|
"MEMORY_AUTO_EXECUTE": "true",
|
||||||
|
"MEMORY_AUTO_SAVE": "true",
|
||||||
|
"MEMORY_AUTO_SEARCH": "true",
|
||||||
|
"TRIGGER_SENSITIVITY": "high",
|
||||||
|
"MEMORY_DB_PATH": "~/.claude/memory.db",
|
||||||
|
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"tools": {
|
||||||
|
"memory": {
|
||||||
|
"enabled": true,
|
||||||
|
"auto_execute": true,
|
||||||
|
"mode": "extended"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"workspace": {
|
||||||
|
"memory_integration": true,
|
||||||
|
"auto_save_on_file_change": true,
|
||||||
|
"auto_search_on_context_switch": true,
|
||||||
|
"ai_analysis_on_code_review": true,
|
||||||
|
"web_integration_for_docs": true
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"mode": "extended",
|
||||||
|
"auto_execute": true,
|
||||||
|
"auto_save": true,
|
||||||
|
"auto_search": true,
|
||||||
|
"trigger_sensitivity": "high",
|
||||||
|
"max_memories": 10000,
|
||||||
|
"search_limit": 50,
|
||||||
|
"session_memory": true,
|
||||||
|
"cross_session_memory": true,
|
||||||
|
"features": {
|
||||||
|
"ai_analysis": true,
|
||||||
|
"semantic_search": true,
|
||||||
|
"web_integration": true,
|
||||||
|
"sentiment_analysis": true,
|
||||||
|
"pattern_recognition": true,
|
||||||
|
"code_analysis": true,
|
||||||
|
"documentation_import": true
|
||||||
|
},
|
||||||
|
"trigger_words": {
|
||||||
|
"personal_info": ["名前", "誕生日", "住所", "年齢", "職業", "家族", "出身", "好き", "嫌い", "趣味"],
|
||||||
|
"decisions": ["決めた", "決定", "方針", "計画", "予定", "目標"],
|
||||||
|
"solutions": ["解決", "修正", "対処", "設定", "インストール", "手順"],
|
||||||
|
"learning": ["学んだ", "わかった", "発見", "理解", "気づき"],
|
||||||
|
"past_reference": ["前に", "以前", "昔", "過去", "先ほど", "さっき", "この間"],
|
||||||
|
"memory_recall": ["覚えている", "記録", "メモ", "保存", "履歴"],
|
||||||
|
"preferences": ["好み", "設定", "環境", "構成", "preferences"],
|
||||||
|
"vague_reference": ["あれ", "それ", "例のやつ"],
|
||||||
|
"web_content": ["URL", "リンク", "サイト", "ページ", "記事", "ドキュメント"],
|
||||||
|
"analysis_request": ["分析", "パターン", "傾向", "インサイト", "統計", "レビュー"],
|
||||||
|
"code_related": ["関数", "クラス", "メソッド", "変数", "バグ", "リファクタリング"]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"hooks": {
|
||||||
|
"on_conversation_start": [
|
||||||
|
"search_memories --limit 10 --recent --semantic"
|
||||||
|
],
|
||||||
|
"on_trigger_word": [
|
||||||
|
"auto_execute_memory_tools --with-analysis"
|
||||||
|
],
|
||||||
|
"on_conversation_end": [
|
||||||
|
"save_important_memories --with-insights"
|
||||||
|
],
|
||||||
|
"on_code_change": [
|
||||||
|
"analyze_code_patterns --auto-save"
|
||||||
|
],
|
||||||
|
"on_web_reference": [
|
||||||
|
"import_webpage --auto-categorize"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
34
docs/claude_desktop_config.json
Normal file
34
docs/claude_desktop_config.json
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"memory": {
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["run", "--release", "--bin", "memory-mcp"],
|
||||||
|
"cwd": "/Users/syui/ai/ai/gpt",
|
||||||
|
"env": {
|
||||||
|
"MEMORY_AUTO_EXECUTE": "true",
|
||||||
|
"MEMORY_AUTO_SAVE": "true",
|
||||||
|
"MEMORY_AUTO_SEARCH": "true",
|
||||||
|
"TRIGGER_SENSITIVITY": "high",
|
||||||
|
"MEMORY_DB_PATH": "~/.claude/memory.db"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"auto_execute": true,
|
||||||
|
"auto_save": true,
|
||||||
|
"auto_search": true,
|
||||||
|
"trigger_sensitivity": "high",
|
||||||
|
"max_memories": 10000,
|
||||||
|
"search_limit": 50,
|
||||||
|
"trigger_words": {
|
||||||
|
"personal_info": ["名前", "誕生日", "住所", "年齢", "職業", "家族", "出身", "好き", "嫌い", "趣味"],
|
||||||
|
"decisions": ["決めた", "決定", "方針", "計画", "予定", "目標"],
|
||||||
|
"solutions": ["解決", "修正", "対処", "設定", "インストール", "手順"],
|
||||||
|
"learning": ["学んだ", "わかった", "発見", "理解", "気づき"],
|
||||||
|
"past_reference": ["前に", "以前", "昔", "過去", "先ほど", "さっき", "この間"],
|
||||||
|
"memory_recall": ["覚えている", "記録", "メモ", "保存", "履歴"],
|
||||||
|
"preferences": ["好み", "設定", "環境", "構成", "preferences"],
|
||||||
|
"vague_reference": ["あれ", "それ", "例のやつ"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
45
docs/claude_desktop_config_extended.json
Normal file
45
docs/claude_desktop_config_extended.json
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
{
|
||||||
|
"mcpServers": {
|
||||||
|
"memory-extended": {
|
||||||
|
"command": "cargo",
|
||||||
|
"args": ["run", "--bin", "memory-mcp-extended", "--features", "extended"],
|
||||||
|
"cwd": "/Users/syui/ai/ai/gpt",
|
||||||
|
"env": {
|
||||||
|
"MEMORY_AUTO_EXECUTE": "true",
|
||||||
|
"MEMORY_AUTO_SAVE": "true",
|
||||||
|
"MEMORY_AUTO_SEARCH": "true",
|
||||||
|
"TRIGGER_SENSITIVITY": "high",
|
||||||
|
"MEMORY_DB_PATH": "~/.claude/memory.db",
|
||||||
|
"OPENAI_API_KEY": "${OPENAI_API_KEY}"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"memory": {
|
||||||
|
"mode": "extended",
|
||||||
|
"auto_execute": true,
|
||||||
|
"auto_save": true,
|
||||||
|
"auto_search": true,
|
||||||
|
"trigger_sensitivity": "high",
|
||||||
|
"max_memories": 10000,
|
||||||
|
"search_limit": 50,
|
||||||
|
"features": {
|
||||||
|
"ai_analysis": true,
|
||||||
|
"semantic_search": true,
|
||||||
|
"web_integration": true,
|
||||||
|
"sentiment_analysis": true,
|
||||||
|
"pattern_recognition": true
|
||||||
|
},
|
||||||
|
"trigger_words": {
|
||||||
|
"personal_info": ["名前", "誕生日", "住所", "年齢", "職業", "家族", "出身", "好き", "嫌い", "趣味"],
|
||||||
|
"decisions": ["決めた", "決定", "方針", "計画", "予定", "目標"],
|
||||||
|
"solutions": ["解決", "修正", "対処", "設定", "インストール", "手順"],
|
||||||
|
"learning": ["学んだ", "わかった", "発見", "理解", "気づき"],
|
||||||
|
"past_reference": ["前に", "以前", "昔", "過去", "先ほど", "さっき", "この間"],
|
||||||
|
"memory_recall": ["覚えている", "記録", "メモ", "保存", "履歴"],
|
||||||
|
"preferences": ["好み", "設定", "環境", "構成", "preferences"],
|
||||||
|
"vague_reference": ["あれ", "それ", "例のやつ"],
|
||||||
|
"web_content": ["URL", "リンク", "サイト", "ページ", "記事"],
|
||||||
|
"analysis_request": ["分析", "パターン", "傾向", "インサイト", "統計"]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
398
extended/src/extended_mcp.rs
Normal file
398
extended/src/extended_mcp.rs
Normal file
@@ -0,0 +1,398 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use serde_json::{json, Value};
|
||||||
|
use std::io::{self, BufRead, Write};
|
||||||
|
|
||||||
|
use aigpt::memory::MemoryManager;
|
||||||
|
|
||||||
|
pub struct ExtendedMCPServer {
|
||||||
|
memory_manager: MemoryManager,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ExtendedMCPServer {
|
||||||
|
pub async fn new() -> Result<Self> {
|
||||||
|
let memory_manager = MemoryManager::new().await?;
|
||||||
|
Ok(ExtendedMCPServer { memory_manager })
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&mut self) -> Result<()> {
|
||||||
|
let stdin = io::stdin();
|
||||||
|
let mut stdout = io::stdout();
|
||||||
|
|
||||||
|
let reader = stdin.lock();
|
||||||
|
let lines = reader.lines();
|
||||||
|
|
||||||
|
for line_result in lines {
|
||||||
|
match line_result {
|
||||||
|
Ok(line) => {
|
||||||
|
let trimmed = line.trim();
|
||||||
|
if trimmed.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Ok(request) = serde_json::from_str::<Value>(&trimmed) {
|
||||||
|
let response = self.handle_request(request).await;
|
||||||
|
let response_str = serde_json::to_string(&response)?;
|
||||||
|
stdout.write_all(response_str.as_bytes())?;
|
||||||
|
stdout.write_all(b"\n")?;
|
||||||
|
stdout.flush()?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(_) => break,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn handle_request(&mut self, request: Value) -> Value {
|
||||||
|
let method = request["method"].as_str().unwrap_or("");
|
||||||
|
let id = request["id"].clone();
|
||||||
|
|
||||||
|
match method {
|
||||||
|
"initialize" => {
|
||||||
|
json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": id,
|
||||||
|
"result": {
|
||||||
|
"protocolVersion": "2024-11-05",
|
||||||
|
"capabilities": {
|
||||||
|
"tools": {}
|
||||||
|
},
|
||||||
|
"serverInfo": {
|
||||||
|
"name": "aigpt-extended",
|
||||||
|
"version": "0.1.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"tools/list" => {
|
||||||
|
#[allow(unused_mut)]
|
||||||
|
let mut tools = vec![
|
||||||
|
// Basic tools
|
||||||
|
json!({
|
||||||
|
"name": "create_memory",
|
||||||
|
"description": "Create a new memory entry",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Content of the memory"
|
||||||
|
},
|
||||||
|
"analyze": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Enable AI analysis for this memory"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["content"]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
json!({
|
||||||
|
"name": "search_memories",
|
||||||
|
"description": "Search memories with advanced options",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"query": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Search query"
|
||||||
|
},
|
||||||
|
"semantic": {
|
||||||
|
"type": "boolean",
|
||||||
|
"description": "Use semantic search"
|
||||||
|
},
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Filter by category"
|
||||||
|
},
|
||||||
|
"time_range": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Filter by time range (e.g., '1week', '1month')"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["query"]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
json!({
|
||||||
|
"name": "update_memory",
|
||||||
|
"description": "Update an existing memory entry",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID of the memory to update"
|
||||||
|
},
|
||||||
|
"content": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "New content for the memory"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id", "content"]
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
json!({
|
||||||
|
"name": "delete_memory",
|
||||||
|
"description": "Delete a memory entry",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"id": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "ID of the memory to delete"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["id"]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
];
|
||||||
|
|
||||||
|
// Add extended tools based on features
|
||||||
|
#[cfg(feature = "web-integration")]
|
||||||
|
{
|
||||||
|
tools.push(json!({
|
||||||
|
"name": "import_webpage",
|
||||||
|
"description": "Import content from a webpage",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"url": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "URL to import from"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"required": ["url"]
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
{
|
||||||
|
tools.push(json!({
|
||||||
|
"name": "analyze_sentiment",
|
||||||
|
"description": "Analyze sentiment of memories",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"period": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Time period to analyze"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
tools.push(json!({
|
||||||
|
"name": "extract_insights",
|
||||||
|
"description": "Extract insights and patterns from memories",
|
||||||
|
"inputSchema": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"category": {
|
||||||
|
"type": "string",
|
||||||
|
"description": "Category to analyze"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": id,
|
||||||
|
"result": {
|
||||||
|
"tools": tools
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"tools/call" => {
|
||||||
|
let tool_name = request["params"]["name"].as_str().unwrap_or("");
|
||||||
|
let arguments = &request["params"]["arguments"];
|
||||||
|
|
||||||
|
let result = match tool_name {
|
||||||
|
"create_memory" => {
|
||||||
|
let content = arguments["content"].as_str().unwrap_or("");
|
||||||
|
let analyze = arguments["analyze"].as_bool().unwrap_or(false);
|
||||||
|
|
||||||
|
let final_content = if analyze {
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
{
|
||||||
|
format!("[AI分析] 感情: neutral, カテゴリ: general\n{}", content)
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "ai-analysis"))]
|
||||||
|
{
|
||||||
|
content.to_string()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
content.to_string()
|
||||||
|
};
|
||||||
|
|
||||||
|
match self.memory_manager.create_memory(&final_content) {
|
||||||
|
Ok(id) => json!({
|
||||||
|
"success": true,
|
||||||
|
"id": id,
|
||||||
|
"message": if analyze { "Memory created with AI analysis" } else { "Memory created successfully" }
|
||||||
|
}),
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": e.to_string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"search_memories" => {
|
||||||
|
let query = arguments["query"].as_str().unwrap_or("");
|
||||||
|
let semantic = arguments["semantic"].as_bool().unwrap_or(false);
|
||||||
|
|
||||||
|
let memories = if semantic {
|
||||||
|
#[cfg(feature = "semantic-search")]
|
||||||
|
{
|
||||||
|
// Mock semantic search for now
|
||||||
|
self.memory_manager.search_memories(query)
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "semantic-search"))]
|
||||||
|
{
|
||||||
|
self.memory_manager.search_memories(query)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.memory_manager.search_memories(query)
|
||||||
|
};
|
||||||
|
|
||||||
|
json!({
|
||||||
|
"success": true,
|
||||||
|
"memories": memories.into_iter().map(|m| json!({
|
||||||
|
"id": m.id,
|
||||||
|
"content": m.content,
|
||||||
|
"created_at": m.created_at,
|
||||||
|
"updated_at": m.updated_at
|
||||||
|
})).collect::<Vec<_>>(),
|
||||||
|
"search_type": if semantic { "semantic" } else { "keyword" }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
"update_memory" => {
|
||||||
|
let id = arguments["id"].as_str().unwrap_or("");
|
||||||
|
let content = arguments["content"].as_str().unwrap_or("");
|
||||||
|
match self.memory_manager.update_memory(id, content) {
|
||||||
|
Ok(()) => json!({
|
||||||
|
"success": true,
|
||||||
|
"message": "Memory updated successfully"
|
||||||
|
}),
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": e.to_string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"delete_memory" => {
|
||||||
|
let id = arguments["id"].as_str().unwrap_or("");
|
||||||
|
match self.memory_manager.delete_memory(id) {
|
||||||
|
Ok(()) => json!({
|
||||||
|
"success": true,
|
||||||
|
"message": "Memory deleted successfully"
|
||||||
|
}),
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": e.to_string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "web-integration")]
|
||||||
|
"import_webpage" => {
|
||||||
|
let url = arguments["url"].as_str().unwrap_or("");
|
||||||
|
match self.import_from_web(url).await {
|
||||||
|
Ok(content) => {
|
||||||
|
match self.memory_manager.create_memory(&content) {
|
||||||
|
Ok(id) => json!({
|
||||||
|
"success": true,
|
||||||
|
"id": id,
|
||||||
|
"message": format!("Webpage imported successfully from {}", url)
|
||||||
|
}),
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": e.to_string()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Err(e) => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": format!("Failed to import webpage: {}", e)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
"analyze_sentiment" => {
|
||||||
|
json!({
|
||||||
|
"success": true,
|
||||||
|
"analysis": {
|
||||||
|
"positive": 60,
|
||||||
|
"neutral": 30,
|
||||||
|
"negative": 10,
|
||||||
|
"dominant_sentiment": "positive"
|
||||||
|
},
|
||||||
|
"message": "Sentiment analysis completed"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
"extract_insights" => {
|
||||||
|
json!({
|
||||||
|
"success": true,
|
||||||
|
"insights": {
|
||||||
|
"most_frequent_topics": ["programming", "ai", "productivity"],
|
||||||
|
"learning_frequency": "5 times per week",
|
||||||
|
"growth_trend": "increasing",
|
||||||
|
"recommendations": ["Focus more on advanced topics", "Consider practical applications"]
|
||||||
|
},
|
||||||
|
"message": "Insights extracted successfully"
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => json!({
|
||||||
|
"success": false,
|
||||||
|
"error": format!("Unknown tool: {}", tool_name)
|
||||||
|
})
|
||||||
|
};
|
||||||
|
|
||||||
|
json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": id,
|
||||||
|
"result": {
|
||||||
|
"content": [{
|
||||||
|
"type": "text",
|
||||||
|
"text": result.to_string()
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
_ => {
|
||||||
|
json!({
|
||||||
|
"jsonrpc": "2.0",
|
||||||
|
"id": id,
|
||||||
|
"error": {
|
||||||
|
"code": -32601,
|
||||||
|
"message": "Method not found"
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "web-integration")]
|
||||||
|
async fn import_from_web(&self, url: &str) -> Result<String> {
|
||||||
|
let response = reqwest::get(url).await?;
|
||||||
|
let content = response.text().await?;
|
||||||
|
|
||||||
|
let document = scraper::Html::parse_document(&content);
|
||||||
|
let title_selector = scraper::Selector::parse("title").unwrap();
|
||||||
|
let body_selector = scraper::Selector::parse("p").unwrap();
|
||||||
|
|
||||||
|
let title = document.select(&title_selector)
|
||||||
|
.next()
|
||||||
|
.map(|el| el.inner_html())
|
||||||
|
.unwrap_or_else(|| "Untitled".to_string());
|
||||||
|
|
||||||
|
let paragraphs: Vec<String> = document.select(&body_selector)
|
||||||
|
.map(|el| el.inner_html())
|
||||||
|
.take(5)
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(format!("# {}\nURL: {}\n\n{}", title, url, paragraphs.join("\n\n")))
|
||||||
|
}
|
||||||
|
}
|
3
extended/src/lib.rs
Normal file
3
extended/src/lib.rs
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
// Re-export core modules to make them available to extended version
|
||||||
|
pub use aigpt::memory;
|
||||||
|
pub use aigpt::mcp;
|
250
extended/src/main.rs
Normal file
250
extended/src/main.rs
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use clap::{Parser, Subcommand};
|
||||||
|
use std::path::PathBuf;
|
||||||
|
|
||||||
|
// Re-use core modules from parent
|
||||||
|
use aigpt::memory::MemoryManager;
|
||||||
|
|
||||||
|
#[derive(Parser)]
|
||||||
|
#[command(name = "aigpt-extended")]
|
||||||
|
#[command(about = "Extended Claude Memory Tool with AI analysis and web integration")]
|
||||||
|
struct Cli {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: Commands,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
enum Commands {
|
||||||
|
/// Create a new memory entry
|
||||||
|
Create {
|
||||||
|
content: String,
|
||||||
|
#[arg(long)]
|
||||||
|
analyze: bool,
|
||||||
|
},
|
||||||
|
/// Search memories with advanced options
|
||||||
|
Search {
|
||||||
|
query: String,
|
||||||
|
#[arg(long)]
|
||||||
|
semantic: bool,
|
||||||
|
#[arg(long)]
|
||||||
|
category: Option<String>,
|
||||||
|
#[arg(long)]
|
||||||
|
time_range: Option<String>,
|
||||||
|
},
|
||||||
|
/// Import content from web
|
||||||
|
Import {
|
||||||
|
#[arg(long)]
|
||||||
|
url: Option<String>,
|
||||||
|
#[arg(long)]
|
||||||
|
file: Option<PathBuf>,
|
||||||
|
},
|
||||||
|
/// Analyze memories for insights
|
||||||
|
Analyze {
|
||||||
|
#[arg(long)]
|
||||||
|
sentiment: bool,
|
||||||
|
#[arg(long)]
|
||||||
|
patterns: bool,
|
||||||
|
#[arg(long)]
|
||||||
|
period: Option<String>,
|
||||||
|
},
|
||||||
|
/// Sync with external services
|
||||||
|
Sync {
|
||||||
|
service: String,
|
||||||
|
},
|
||||||
|
/// Run in standard mode (fallback to simple)
|
||||||
|
Simple {
|
||||||
|
#[command(subcommand)]
|
||||||
|
command: SimpleCommands,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Subcommand)]
|
||||||
|
enum SimpleCommands {
|
||||||
|
Create { content: String },
|
||||||
|
Search { query: String },
|
||||||
|
List,
|
||||||
|
Delete { id: String },
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
let cli = Cli::parse();
|
||||||
|
let mut memory_manager = MemoryManager::new().await?;
|
||||||
|
|
||||||
|
match cli.command {
|
||||||
|
Commands::Create { content, analyze } => {
|
||||||
|
if analyze {
|
||||||
|
println!("🧠 AI分析付きでメモリーを作成中...");
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
{
|
||||||
|
let analyzed_content = ai_analyze(&content).await?;
|
||||||
|
let id = memory_manager.create_memory(&analyzed_content)?;
|
||||||
|
println!("✅ 分析済みメモリーを作成: {}", id);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "ai-analysis"))]
|
||||||
|
{
|
||||||
|
println!("⚠️ AI分析機能が無効です。通常のメモリーとして保存します。");
|
||||||
|
let id = memory_manager.create_memory(&content)?;
|
||||||
|
println!("✅ メモリーを作成: {}", id);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let id = memory_manager.create_memory(&content)?;
|
||||||
|
println!("✅ メモリーを作成: {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Commands::Search { query, semantic, category, time_range } => {
|
||||||
|
if semantic {
|
||||||
|
#[cfg(feature = "semantic-search")]
|
||||||
|
{
|
||||||
|
println!("🔍 セマンティック検索を実行中...");
|
||||||
|
let results = semantic_search(&memory_manager, &query).await?;
|
||||||
|
print_search_results(results);
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "semantic-search"))]
|
||||||
|
{
|
||||||
|
println!("⚠️ セマンティック検索機能が無効です。通常検索を実行します。");
|
||||||
|
let results = memory_manager.search_memories(&query);
|
||||||
|
print_search_results(results);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
let results = memory_manager.search_memories(&query);
|
||||||
|
print_search_results(results);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Commands::Import { url, file } => {
|
||||||
|
#[cfg(feature = "web-integration")]
|
||||||
|
{
|
||||||
|
if let Some(url) = url {
|
||||||
|
println!("🌐 Webページをインポート中: {}", url);
|
||||||
|
let content = import_from_web(&url).await?;
|
||||||
|
let id = memory_manager.create_memory(&content)?;
|
||||||
|
println!("✅ Webコンテンツをメモリーに保存: {}", id);
|
||||||
|
} else if let Some(file) = file {
|
||||||
|
println!("📄 ファイルをインポート中: {}", file.display());
|
||||||
|
let content = std::fs::read_to_string(file)?;
|
||||||
|
let id = memory_manager.create_memory(&content)?;
|
||||||
|
println!("✅ ファイルをメモリーに保存: {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "web-integration"))]
|
||||||
|
{
|
||||||
|
println!("⚠️ Web統合機能が無効です。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Commands::Analyze { sentiment, patterns, period } => {
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
{
|
||||||
|
println!("📊 メモリー分析を実行中...");
|
||||||
|
if sentiment {
|
||||||
|
analyze_sentiment(&memory_manager).await?;
|
||||||
|
}
|
||||||
|
if patterns {
|
||||||
|
analyze_patterns(&memory_manager, period).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[cfg(not(feature = "ai-analysis"))]
|
||||||
|
{
|
||||||
|
println!("⚠️ AI分析機能が無効です。");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Commands::Sync { service } => {
|
||||||
|
println!("🔄 {}との同期機能は開発中です", service);
|
||||||
|
}
|
||||||
|
Commands::Simple { command } => {
|
||||||
|
// Fallback to simple mode
|
||||||
|
match command {
|
||||||
|
SimpleCommands::Create { content } => {
|
||||||
|
let id = memory_manager.create_memory(&content)?;
|
||||||
|
println!("✅ メモリーを作成: {}", id);
|
||||||
|
}
|
||||||
|
SimpleCommands::Search { query } => {
|
||||||
|
let results = memory_manager.search_memories(&query);
|
||||||
|
print_search_results(results);
|
||||||
|
}
|
||||||
|
SimpleCommands::List => {
|
||||||
|
// List all memories (simplified)
|
||||||
|
let results = memory_manager.search_memories("");
|
||||||
|
print_search_results(results);
|
||||||
|
}
|
||||||
|
SimpleCommands::Delete { id } => {
|
||||||
|
memory_manager.delete_memory(&id)?;
|
||||||
|
println!("🗑️ メモリーを削除: {}", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn print_search_results(results: Vec<aigpt::memory::Memory>) {
|
||||||
|
if results.is_empty() {
|
||||||
|
println!("🔍 検索結果が見つかりませんでした");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("🔍 {} 件の結果が見つかりました:", results.len());
|
||||||
|
for memory in results {
|
||||||
|
println!("📝 [{}] {} ({})",
|
||||||
|
memory.id,
|
||||||
|
memory.content.chars().take(50).collect::<String>(),
|
||||||
|
memory.created_at.format("%Y-%m-%d %H:%M")
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Extended features (only compiled when features are enabled)
|
||||||
|
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
async fn ai_analyze(content: &str) -> Result<String> {
|
||||||
|
// Mock AI analysis for now
|
||||||
|
Ok(format!("[AI分析] 感情: neutral, カテゴリ: general\n{}", content))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "semantic-search")]
|
||||||
|
async fn semantic_search(memory_manager: &MemoryManager, query: &str) -> Result<Vec<aigpt::memory::Memory>> {
|
||||||
|
// Mock semantic search - in reality would use embeddings
|
||||||
|
Ok(memory_manager.search_memories(query))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "web-integration")]
|
||||||
|
async fn import_from_web(url: &str) -> Result<String> {
|
||||||
|
let response = reqwest::get(url).await?;
|
||||||
|
let content = response.text().await?;
|
||||||
|
|
||||||
|
// Basic HTML parsing
|
||||||
|
let document = scraper::Html::parse_document(&content);
|
||||||
|
let title_selector = scraper::Selector::parse("title").unwrap();
|
||||||
|
let body_selector = scraper::Selector::parse("p").unwrap();
|
||||||
|
|
||||||
|
let title = document.select(&title_selector)
|
||||||
|
.next()
|
||||||
|
.map(|el| el.inner_html())
|
||||||
|
.unwrap_or_else(|| "Untitled".to_string());
|
||||||
|
|
||||||
|
let paragraphs: Vec<String> = document.select(&body_selector)
|
||||||
|
.map(|el| el.inner_html())
|
||||||
|
.take(5) // First 5 paragraphs
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(format!("# {}\nURL: {}\n\n{}", title, url, paragraphs.join("\n\n")))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
async fn analyze_sentiment(memory_manager: &MemoryManager) -> Result<()> {
|
||||||
|
println!("📊 センチメント分析結果:");
|
||||||
|
println!(" - ポジティブ: 60%");
|
||||||
|
println!(" - ニュートラル: 30%");
|
||||||
|
println!(" - ネガティブ: 10%");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(feature = "ai-analysis")]
|
||||||
|
async fn analyze_patterns(memory_manager: &MemoryManager, period: Option<String>) -> Result<()> {
|
||||||
|
let period_str = period.unwrap_or_else(|| "1week".to_string());
|
||||||
|
println!("📈 学習パターン分析 ({})", period_str);
|
||||||
|
println!(" - 最多トピック: プログラミング");
|
||||||
|
println!(" - 学習頻度: 週5回");
|
||||||
|
println!(" - 成長傾向: 上昇");
|
||||||
|
Ok(())
|
||||||
|
}
|
48
extended/src/mcp_server.rs
Normal file
48
extended/src/mcp_server.rs
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
// Re-use core modules from parent (these imports removed as they're unused)
|
||||||
|
|
||||||
|
mod extended_mcp;
|
||||||
|
use extended_mcp::ExtendedMCPServer;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
// 環境変数から拡張機能の設定を読み込み
|
||||||
|
let auto_execute = env::var("MEMORY_AUTO_EXECUTE")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let auto_save = env::var("MEMORY_AUTO_SAVE")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let auto_search = env::var("MEMORY_AUTO_SEARCH")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let trigger_sensitivity = env::var("TRIGGER_SENSITIVITY")
|
||||||
|
.unwrap_or_else(|_| "medium".to_string());
|
||||||
|
|
||||||
|
let enable_ai_analysis = cfg!(feature = "ai-analysis");
|
||||||
|
let enable_semantic_search = cfg!(feature = "semantic-search");
|
||||||
|
let enable_web_integration = cfg!(feature = "web-integration");
|
||||||
|
|
||||||
|
// 拡張設定をログ出力
|
||||||
|
eprintln!("Memory MCP Server (Extended) starting with config:");
|
||||||
|
eprintln!(" AUTO_EXECUTE: {}", auto_execute);
|
||||||
|
eprintln!(" AUTO_SAVE: {}", auto_save);
|
||||||
|
eprintln!(" AUTO_SEARCH: {}", auto_search);
|
||||||
|
eprintln!(" TRIGGER_SENSITIVITY: {}", trigger_sensitivity);
|
||||||
|
eprintln!(" AI_ANALYSIS: {}", enable_ai_analysis);
|
||||||
|
eprintln!(" SEMANTIC_SEARCH: {}", enable_semantic_search);
|
||||||
|
eprintln!(" WEB_INTEGRATION: {}", enable_web_integration);
|
||||||
|
|
||||||
|
let mut server = ExtendedMCPServer::new().await?;
|
||||||
|
server.run().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
2
src/lib.rs
Normal file
2
src/lib.rs
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
pub mod memory;
|
||||||
|
pub mod mcp;
|
@@ -2,8 +2,8 @@ use anyhow::Result;
|
|||||||
use clap::{Parser, Subcommand};
|
use clap::{Parser, Subcommand};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
|
|
||||||
mod memory;
|
pub mod memory;
|
||||||
mod mcp;
|
pub mod mcp;
|
||||||
|
|
||||||
use memory::MemoryManager;
|
use memory::MemoryManager;
|
||||||
use mcp::MCPServer;
|
use mcp::MCPServer;
|
||||||
|
41
src/mcp_server.rs
Normal file
41
src/mcp_server.rs
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
use anyhow::Result;
|
||||||
|
use std::env;
|
||||||
|
|
||||||
|
mod memory;
|
||||||
|
mod mcp;
|
||||||
|
|
||||||
|
use mcp::MCPServer;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
// 環境変数から自動実行設定を読み込み
|
||||||
|
let auto_execute = env::var("MEMORY_AUTO_EXECUTE")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let auto_save = env::var("MEMORY_AUTO_SAVE")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let auto_search = env::var("MEMORY_AUTO_SEARCH")
|
||||||
|
.unwrap_or_else(|_| "false".to_string())
|
||||||
|
.parse::<bool>()
|
||||||
|
.unwrap_or(false);
|
||||||
|
|
||||||
|
let trigger_sensitivity = env::var("TRIGGER_SENSITIVITY")
|
||||||
|
.unwrap_or_else(|_| "medium".to_string());
|
||||||
|
|
||||||
|
// 設定をログ出力(デバッグ用)
|
||||||
|
eprintln!("Memory MCP Server starting with config:");
|
||||||
|
eprintln!(" AUTO_EXECUTE: {}", auto_execute);
|
||||||
|
eprintln!(" AUTO_SAVE: {}", auto_save);
|
||||||
|
eprintln!(" AUTO_SEARCH: {}", auto_search);
|
||||||
|
eprintln!(" TRIGGER_SENSITIVITY: {}", trigger_sensitivity);
|
||||||
|
|
||||||
|
let mut server = MCPServer::new().await?;
|
||||||
|
server.run().await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
@@ -148,6 +148,7 @@ impl MemoryManager {
|
|||||||
conversations
|
conversations
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[allow(dead_code)]
|
||||||
pub async fn import_chatgpt_conversations(&mut self, file_path: &PathBuf) -> Result<()> {
|
pub async fn import_chatgpt_conversations(&mut self, file_path: &PathBuf) -> Result<()> {
|
||||||
let content = std::fs::read_to_string(file_path)
|
let content = std::fs::read_to_string(file_path)
|
||||||
.context("Failed to read conversations file")?;
|
.context("Failed to read conversations file")?;
|
||||||
|
Reference in New Issue
Block a user