232 lines
8.6 KiB
Python
232 lines
8.6 KiB
Python
#!/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() |