#!/usr/bin/env python3 # -*- coding: utf-8 -*- """ 会话管理 API 作者:小白 🐶 """ import os import json import glob from datetime import datetime from flask import jsonify, request from . import api SESSIONS_DIR = '/root/.openclaw/agents/main/sessions' @api.route('/sessions') def get_sessions(): """获取会话列表""" try: sessions = [] for filepath in glob.glob(os.path.join(SESSIONS_DIR, '*.jsonl')): if '.reset.' in filepath or filepath.endswith('.lock'): continue session_id = os.path.basename(filepath).replace('.jsonl', '') stat = os.stat(filepath) updated_at = stat.st_mtime size = stat.st_size messages_count = 0 try: with open(filepath, 'r') as f: messages_count = len([l for l in f.readlines() if l.strip()]) except: pass is_active = (datetime.now().timestamp() - updated_at) < 300 sessions.append({ 'id': session_id, 'key': f'agent:main:session:{session_id}', 'updatedAt': int(updated_at * 1000), 'updatedTime': datetime.fromtimestamp(updated_at).strftime('%Y-%m-%d %H:%M:%S'), 'size': size, 'messagesCount': messages_count, 'status': 'active' if is_active else 'inactive' }) sessions.sort(key=lambda x: x['updatedAt'], reverse=True) return jsonify({ 'success': True, 'data': { 'count': len(sessions), 'sessions': sessions } }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @api.route('/sessions/') def get_session_detail(session_id): """获取会话详情""" try: filepath = os.path.join(SESSIONS_DIR, f'{session_id}.jsonl') if not os.path.exists(filepath): return jsonify({'success': False, 'error': '会话不存在'}) messages = [] with open(filepath, 'r') as f: for line in f: line = line.strip() if not line: continue try: record = json.loads(line) # 只处理 message 类型的记录 if record.get('type') == 'message': msg = record.get('message', {}) role = msg.get('role', 'unknown') content_parts = msg.get('content', []) # 提取文本内容 text_content = '' for part in content_parts: if isinstance(part, dict): if part.get('type') == 'text': text_content += part.get('text', '') elif part.get('type') == 'thinking': text_content += '[思考中...] ' elif isinstance(part, str): text_content += part if text_content.strip(): messages.append({ 'role': role, 'content': text_content[:500], 'timestamp': record.get('timestamp', '') }) except: continue # 只保留最近 30 条消息 messages = messages[-30:] return jsonify({ 'success': True, 'data': { 'id': session_id, 'messagesCount': len(messages), 'messages': messages } }) except Exception as e: return jsonify({'success': False, 'error': str(e)}) @api.route('/sessions//kill', methods=['POST']) def kill_session(session_id): """终止会话""" try: filepath = os.path.join(SESSIONS_DIR, f'{session_id}.jsonl') if not os.path.exists(filepath): return jsonify({'success': False, 'error': '会话不存在'}) backup_path = filepath + f'.reset.{datetime.now().isoformat()}' os.rename(filepath, backup_path) return jsonify({'success': True, 'message': '会话已终止'}) except Exception as e: return jsonify({'success': False, 'error': str(e)})