File size: 11,079 Bytes
14015fd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
"""
会話履歴自動記録システム
=======================

GitHub Copilotとの会話を自動的にSQLiteに保存するためのフックシステム

使用方法:
1. このモジュールをインポート
2. log_conversation()を呼び出すだけで自動保存
3. セッション管理も自動化
"""

import uuid
import datetime
import json
import os
import traceback
import sqlite3
from typing import Optional, Dict, List
from controllers.conversation_history import ConversationManager

class ConversationLogger:
    def __init__(self):
        """会話ログシステムの初期化"""
        self.conversation_manager = ConversationManager()
        self.current_session_id = self.generate_session_id()
        self.session_start_time = datetime.datetime.now()
        
        print(f"🎯 会話ログシステム開始 - セッションID: {self.current_session_id[:8]}")
    
    def generate_session_id(self) -> str:
        """新しいセッションIDを生成"""
        return str(uuid.uuid4())
    
    def start_new_session(self, session_name: str = None) -> str:
        """新しいセッションを開始"""
        self.current_session_id = self.generate_session_id()
        self.session_start_time = datetime.datetime.now()
        
        if session_name:
            # セッション名を更新
            try:
                conn = sqlite3.connect(self.conversation_manager.db_path)
                cursor = conn.cursor()
                cursor.execute('''
                    UPDATE sessions 
                    SET session_name = ?
                    WHERE session_id = ?
                ''', (session_name, self.current_session_id))
                conn.commit()
                conn.close()
            except Exception as e:
                print(f"⚠️ セッション名更新エラー: {e}")
        
        print(f"🆕 新しいセッション開始: {self.current_session_id[:8]}")
        return self.current_session_id
    
    def log_conversation(self,
                        user_message: str,
                        assistant_response: str,
                        context_info: str = "",
                        files_involved: List[str] = None,
                        tools_used: List[str] = None,
                        tags: List[str] = None,
                        project_name: str = "ContBK統合システム") -> Optional[int]:
        """
        会話を自動記録
        
        Args:
            user_message: ユーザーからのメッセージ
            assistant_response: アシスタントの応答
            context_info: コンテキスト情報
            files_involved: 関連ファイルのリスト
            tools_used: 使用ツールのリスト
            tags: タグのリスト
            project_name: プロジェクト名
        
        Returns:
            会話ID (保存に成功した場合)
        """
        try:
            # リストを文字列に変換
            files_str = ", ".join(files_involved) if files_involved else ""
            tools_str = ", ".join(tools_used) if tools_used else ""
            tags_str = ", ".join(tags) if tags else ""
            
            # 会話を保存
            conversation_id = self.conversation_manager.save_conversation(
                session_id=self.current_session_id,
                user_message=user_message,
                assistant_response=assistant_response,
                context_info=context_info,
                files_involved=files_str,
                tools_used=tools_str,
                tags=tags_str
            )
            
            print(f"✅ 会話を記録しました (ID: {conversation_id})")
            return conversation_id
            
        except Exception as e:
            print(f"❌ 会話記録エラー: {e}")
            print(traceback.format_exc())
            return None
    
    def log_tool_usage(self, tool_name: str, parameters: Dict, result: str):
        """ツール使用ログを記録"""
        tool_info = {
            "tool": tool_name,
            "parameters": parameters,
            "result": result[:500],  # 結果は500文字まで
            "timestamp": datetime.datetime.now().isoformat()
        }
        
        # 直前の会話にツール情報を追加
        try:
            conn = sqlite3.connect(self.conversation_manager.db_path)
            cursor = conn.cursor()
            
            # 最新の会話を取得
            cursor.execute('''
                SELECT id, tools_used FROM conversations 
                WHERE session_id = ?
                ORDER BY timestamp DESC 
                LIMIT 1
            ''', (self.current_session_id,))
            
            row = cursor.fetchone()
            if row:
                conversation_id, existing_tools = row
                
                # 既存のツール情報に追加
                updated_tools = existing_tools + f", {tool_name}" if existing_tools else tool_name
                
                cursor.execute('''
                    UPDATE conversations 
                    SET tools_used = ?, updated_at = CURRENT_TIMESTAMP
                    WHERE id = ?
                ''', (updated_tools, conversation_id))
                
                conn.commit()
            
            conn.close()
            print(f"🔧 ツール使用を記録: {tool_name}")
            
        except Exception as e:
            print(f"⚠️ ツール使用記録エラー: {e}")
    
    def get_session_summary(self) -> Dict:
        """現在のセッションの要約を取得"""
        try:
            conversations = self.conversation_manager.get_conversations(
                session_id=self.current_session_id
            )
            
            return {
                "session_id": self.current_session_id,
                "start_time": self.session_start_time.isoformat(),
                "conversation_count": len(conversations),
                "duration_minutes": (datetime.datetime.now() - self.session_start_time).total_seconds() / 60,
                "latest_conversation": conversations[0] if conversations else None
            }
        except Exception as e:
            print(f"⚠️ セッション要約取得エラー: {e}")
            return {}
    
    def export_session(self, session_id: str = None) -> str:
        """セッションをJSON形式でエクスポート"""
        target_session = session_id or self.current_session_id
        
        try:
            conversations = self.conversation_manager.get_conversations(
                session_id=target_session
            )
            
            export_data = {
                "session_id": target_session,
                "export_time": datetime.datetime.now().isoformat(),
                "conversation_count": len(conversations),
                "conversations": conversations
            }
            
            filename = f"session_export_{target_session[:8]}_{datetime.datetime.now().strftime('%Y%m%d_%H%M%S')}.json"
            
            with open(filename, 'w', encoding='utf-8') as f:
                json.dump(export_data, f, ensure_ascii=False, indent=2)
            
            print(f"📥 セッションエクスポート完了: {filename}")
            return filename
            
        except Exception as e:
            print(f"❌ セッションエクスポートエラー: {e}")
            return ""

# グローバルログインスタンス
conversation_logger = ConversationLogger()

def log_this_conversation(user_msg: str, assistant_msg: str, 
                         context: str = "", files: List[str] = None, 
                         tools: List[str] = None, tags: List[str] = None):
    """
    簡単な会話ログ記録関数
    
    使用例:
    log_this_conversation(
        user_msg="ContBK統合システムについて教えて",
        assistant_msg="ContBK統合システムは...",
        files=["controllers/contbk_example.py"],
        tools=["create_file", "insert_edit_into_file"],
        tags=["contbk", "gradio"]
    )
    """
    return conversation_logger.log_conversation(
        user_message=user_msg,
        assistant_response=assistant_msg,
        context_info=context,
        files_involved=files,
        tools_used=tools,
        tags=tags
    )

def start_new_conversation_session(session_name: str = None):
    """新しい会話セッションを開始"""
    return conversation_logger.start_new_session(session_name)

def get_current_session_info():
    """現在のセッション情報を取得"""
    return conversation_logger.get_session_summary()

# 自動ログ記録のデコレーター
def auto_log_conversation(tags: List[str] = None):
    """
    関数の実行を自動的にログに記録するデコレーター
    
    使用例:
    @auto_log_conversation(tags=["gradio", "interface"])
    def create_interface():
        # 関数の処理
        pass
    """
    def decorator(func):
        def wrapper(*args, **kwargs):
            start_time = datetime.datetime.now()
            
            try:
                result = func(*args, **kwargs)
                
                # 成功した場合のログ
                conversation_logger.log_conversation(
                    user_message=f"関数実行: {func.__name__}",
                    assistant_response=f"関数 {func.__name__} が正常に実行されました",
                    context_info=f"実行時間: {(datetime.datetime.now() - start_time).total_seconds():.2f}秒",
                    tools_used=[func.__name__],
                    tags=tags or ["自動実行"]
                )
                
                return result
                
            except Exception as e:
                # エラーの場合のログ
                conversation_logger.log_conversation(
                    user_message=f"関数実行エラー: {func.__name__}",
                    assistant_response=f"エラーが発生しました: {str(e)}",
                    context_info=f"実行時間: {(datetime.datetime.now() - start_time).total_seconds():.2f}秒",
                    tools_used=[func.__name__],
                    tags=(tags or []) + ["エラー"]
                )
                raise
                
        return wrapper
    return decorator

if __name__ == "__main__":
    # テスト実行
    print("🧪 会話ログシステムテスト")
    
    # サンプル会話を記録
    log_this_conversation(
        user_msg="会話履歴システムのテストです",
        assistant_msg="会話履歴システムが正常に動作しています!",
        context="テスト実行",
        files=["controllers/conversation_logger.py"],
        tools=["create_file"],
        tags=["テスト", "会話履歴"]
    )
    
    # セッション情報表示
    session_info = get_current_session_info()
    print(f"📊 セッション情報: {session_info}")
    
    print("✅ テスト完了")