refactor: Migrate file-based data storage to database
This commit is contained in:
@@ -8,17 +8,27 @@ def _empty_state():
|
||||
return {"active_threads": [], "immediate_handoff": "", "resolved_threads": [], "chapter": 0}
|
||||
|
||||
|
||||
def load_story_state(folder):
|
||||
"""Load structured story state from story_state.json, or return empty state."""
|
||||
def load_story_state(folder, project_id=None):
|
||||
"""Load structured story state from DB (if project_id given) or story_state.json fallback."""
|
||||
if project_id is not None:
|
||||
try:
|
||||
from web.db import StoryState
|
||||
record = StoryState.query.filter_by(project_id=project_id).first()
|
||||
if record and record.state_json:
|
||||
return json.loads(record.state_json) or _empty_state()
|
||||
except Exception:
|
||||
pass # Fall through to file-based load if DB unavailable (e.g. CLI context)
|
||||
|
||||
path = os.path.join(folder, "story_state.json")
|
||||
if os.path.exists(path):
|
||||
return utils.load_json(path) or _empty_state()
|
||||
return _empty_state()
|
||||
|
||||
|
||||
def update_story_state(chapter_text, chapter_num, current_state, folder):
|
||||
def update_story_state(chapter_text, chapter_num, current_state, folder, project_id=None):
|
||||
"""Use model_logic to extract structured story threads from the new chapter
|
||||
and save the updated state to story_state.json. Returns the new state."""
|
||||
and save the updated state to the StoryState DB table and/or story_state.json.
|
||||
Returns the new state."""
|
||||
utils.log("STATE", f"Updating story state after Ch {chapter_num}...")
|
||||
prompt = f"""
|
||||
ROLE: Story State Tracker
|
||||
@@ -54,9 +64,28 @@ def update_story_state(chapter_text, chapter_num, current_state, folder):
|
||||
utils.log_usage(folder, ai_models.model_logic.name, response.usage_metadata)
|
||||
new_state = json.loads(utils.clean_json(response.text))
|
||||
new_state['chapter'] = chapter_num
|
||||
|
||||
# Write to DB if project_id is available
|
||||
if project_id is not None:
|
||||
try:
|
||||
from web.db import db, StoryState
|
||||
from datetime import datetime
|
||||
record = StoryState.query.filter_by(project_id=project_id).first()
|
||||
if record:
|
||||
record.state_json = json.dumps(new_state)
|
||||
record.updated_at = datetime.utcnow()
|
||||
else:
|
||||
record = StoryState(project_id=project_id, state_json=json.dumps(new_state))
|
||||
db.session.add(record)
|
||||
db.session.commit()
|
||||
except Exception as db_err:
|
||||
utils.log("STATE", f" -> DB write failed: {db_err}. Falling back to file.")
|
||||
|
||||
# Always write to file for backward compat with CLI
|
||||
path = os.path.join(folder, "story_state.json")
|
||||
with open(path, 'w') as f:
|
||||
json.dump(new_state, f, indent=2)
|
||||
|
||||
utils.log("STATE", f" -> Story state saved. Active threads: {len(new_state.get('active_threads', []))}")
|
||||
return new_state
|
||||
except Exception as e:
|
||||
|
||||
@@ -157,10 +157,12 @@ def update_persona_sample(bp, folder):
|
||||
|
||||
author_name = meta.get('author', 'Unknown Author')
|
||||
|
||||
# Use a local file mirror for the engine context (runs outside Flask app context)
|
||||
_personas_file = os.path.join(config.PERSONAS_DIR, "personas.json")
|
||||
personas = {}
|
||||
if os.path.exists(config.PERSONAS_FILE):
|
||||
if os.path.exists(_personas_file):
|
||||
try:
|
||||
with open(config.PERSONAS_FILE, 'r') as f: personas = json.load(f)
|
||||
with open(_personas_file, 'r') as f: personas = json.load(f)
|
||||
except: pass
|
||||
|
||||
if author_name not in personas:
|
||||
@@ -189,4 +191,4 @@ def update_persona_sample(bp, folder):
|
||||
if filename not in personas[author_name]['sample_files']:
|
||||
personas[author_name]['sample_files'].append(filename)
|
||||
|
||||
with open(config.PERSONAS_FILE, 'w') as f: json.dump(personas, f, indent=2)
|
||||
with open(_personas_file, 'w') as f: json.dump(personas, f, indent=2)
|
||||
|
||||
Reference in New Issue
Block a user