#!/usr/bin/env python3 """ inkos 终极修复方案 直接修复数据库中的数据错误 """ import json import os import shutil import sqlite3 import subprocess import time def stop_inkos(): """停止inkos所有进程""" print("1. 停止inkos所有进程...") subprocess.run(["pkill", "-9", "-f", "node.*inkos"], capture_output=True) subprocess.run(["pkill", "-9", "-f", "inkos"], capture_output=True) time.sleep(3) print(" ✅ inkos已停止") def backup_data(): """备份所有数据""" print("2. 备份数据...") backup_dir = f"/root/.openclaw/workspace/backups/inkos_ultimate_fix_{time.strftime('%Y%m%d_%H%M%S')}" os.makedirs(backup_dir, exist_ok=True) # 备份重要文件和目录 backup_items = [ "/root/.openclaw/workspace/tomato-novel/inkos.json", "/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资", "/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资" ] for item in backup_items: if os.path.exists(item): if os.path.isfile(item): shutil.copy2(item, backup_dir) else: shutil.copytree(item, os.path.join(backup_dir, os.path.basename(item)), dirs_exist_ok=True) print(f" 已备份: {os.path.basename(item)}") print(f" 备份位置: {backup_dir}") return backup_dir def fix_database(): """修复数据库文件""" print("3. 修复数据库文件...") # 找到并修复所有数据库文件 db_files = [ "/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/memory.db", "/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/memory.db" ] for db_file in db_files: if os.path.exists(db_file): print(f" 检查数据库: {db_file}") try: # 备份数据库 shutil.copy2(db_file, f"{db_file}.backup") # 尝试连接到数据库 conn = sqlite3.connect(db_file) cursor = conn.cursor() # 获取所有表名 cursor.execute("SELECT name FROM sqlite_master WHERE type='table';") tables = cursor.fetchall() print(f" 数据库表: {[t[0] for t in tables]}") # 查找可能包含章节数据的表 for table in tables: table_name = table[0] if 'chapter' in table_name.lower() or 'row' in table_name.lower(): print(f" 检查表: {table_name}") # 获取表结构 cursor.execute(f"PRAGMA table_info({table_name});") columns = cursor.fetchall() print(f" 列: {[col[1] for col in columns]}") # 查找title列 title_col = None for col in columns: if 'title' in col[1].lower(): title_col = col[1] break if title_col: # 查找空标题的行 cursor.execute(f"SELECT rowid, {title_col} FROM {table_name} WHERE {title_col} IS NULL OR {title_col} = '' OR LENGTH(TRIM({title_col})) = 0;") empty_titles = cursor.fetchall() if empty_titles: print(f" 找到 {len(empty_titles)} 个空标题") for rowid, title in empty_titles: # 修复空标题 new_title = f"第{rowid}章" cursor.execute(f"UPDATE {table_name} SET {title_col} = ? WHERE rowid = ?", (new_title, rowid)) print(f" 修复行 {rowid}: '{new_title}'") conn.commit() conn.close() print(f" ✅ 数据库修复完成: {os.path.basename(db_file)}") except Exception as e: print(f" ❌ 修复数据库时出错: {e}") # 如果数据库损坏严重,删除它让inkos重新创建 print(f" 删除损坏的数据库: {db_file}") os.remove(db_file) print(f" ✅ 已删除,inkos将重新创建数据库") def clean_state_files(): """清理状态文件,让inkos重新开始""" print("4. 清理状态文件...") # 删除可能损坏的状态文件 state_dirs = [ "/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/state", "/root/.openclaw/workspace/tomato-novel/tomato-novel/books/末日重生-开局囤货十亿物资/story/runtime", "/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/state", "/root/.openclaw/workspace/tomato-novel/books/末日重生-开局囤货十亿物资/story/runtime" ] for state_dir in state_dirs: if os.path.exists(state_dir): # 只删除特定文件,保留章节文件 for file in os.listdir(state_dir): if file.endswith('.json') or file.endswith('.db'): file_path = os.path.join(state_dir, file) try: os.remove(file_path) print(f" 删除: {file}") except: pass print(" ✅ 状态文件已清理") def create_simple_config(): """创建最简单的配置""" print("5. 创建简单配置...") config = { "name": "tomato-novel-fixed", "version": "0.1.0", "language": "zh", "llm": { "provider": "custom", "baseUrl": "https://ark.cn-beijing.volces.com/api/coding/v3", "model": "deepseek-v3.2" }, "daemon": { "schedule": { "writeCron": "0 */2 * * *" # 每2小时一次 }, "maxConcurrentBooks": 1 }, "quality": { "enforcement": "none" # 完全关闭质量检查 } } config_path = "/root/.openclaw/workspace/tomato-novel/inkos.json" with open(config_path, 'w', encoding='utf-8') as f: json.dump(config, f, ensure_ascii=False, indent=2) print(" ✅ 简单配置已创建") def start_inkos(): """启动inkos""" print("6. 启动inkos...") os.chdir("/root/.openclaw/workspace/tomato-novel") # 启动inkos with open("/tmp/inkos_ultimate_start.log", "w") as log_file: process = subprocess.Popen( ["nohup", "inkos", "up"], stdout=log_file, stderr=subprocess.STDOUT, start_new_session=True ) time.sleep(10) # 检查是否启动成功 result = subprocess.run(["ps", "aux"], capture_output=True, text=True) if "inkos up" in result.stdout: pid_line = [line for line in result.stdout.split('\n') if "inkos up" in line][0] pid = pid_line.split()[1] print(f" ✅ inkos 已启动 (PID: {pid})") return True else: print(" ❌ inkos 启动失败") return False def main(): """主函数""" print("=" * 60) print("inkos 终极修复方案") print("=" * 60) stop_inkos() backup_dir = backup_data() fix_database() clean_state_files() create_simple_config() if start_inkos(): print("\n" + "=" * 60) print("✅ 修复完成!") print(f"备份位置: {backup_dir}") print("=" * 60) print("\ninkos 已重新启动,配置为:") print("- 质量检查: 关闭") print("- 创作频率: 每2小时") print("- 日志文件: /tmp/inkos_ultimate_start.log") print("\n等待5-10分钟后,使用以下命令测试:") print(" inkos status") print(" inkos draft 末日重生-开局囤货十亿物资") else: print("\n" + "=" * 60) print("❌ 修复失败!") print("=" * 60) print("\n请检查:") print("1. inkos 是否安装: which inkos") print("2. 日志文件: tail -100 /tmp/inkos_ultimate_start.log") print("3. 可能需要重新安装 inkos") if __name__ == "__main__": main()