Added revised book feature.
This commit is contained in:
@@ -887,6 +887,34 @@ def restart_run(id):
|
|||||||
flash(f"Started new Run #{new_run.id}" + (" with modifications." if feedback else "."))
|
flash(f"Started new Run #{new_run.id}" + (" with modifications." if feedback else "."))
|
||||||
return redirect(url_for('view_project', id=run.project_id))
|
return redirect(url_for('view_project', id=run.project_id))
|
||||||
|
|
||||||
|
@app.route('/project/<int:run_id>/revise_book/<string:book_folder>', methods=['POST'])
|
||||||
|
@login_required
|
||||||
|
def revise_book(run_id, book_folder):
|
||||||
|
run = db.session.get(Run, run_id) or Run.query.get_or_404(run_id)
|
||||||
|
if run.project.user_id != current_user.id: return "Unauthorized", 403
|
||||||
|
|
||||||
|
instruction = request.form.get('instruction')
|
||||||
|
|
||||||
|
# Create new run
|
||||||
|
new_run = Run(project_id=run.project_id, status="queued")
|
||||||
|
db.session.add(new_run)
|
||||||
|
db.session.commit()
|
||||||
|
|
||||||
|
# Task: Apply feedback to Bible, Copy all books EXCEPT this one, then Generate
|
||||||
|
task = generate_book_task(
|
||||||
|
new_run.id,
|
||||||
|
run.project.folder_path,
|
||||||
|
os.path.join(run.project.folder_path, "bible.json"),
|
||||||
|
allow_copy=True,
|
||||||
|
feedback=instruction,
|
||||||
|
source_run_id=run.id,
|
||||||
|
keep_cover=True,
|
||||||
|
exclude_folders=[book_folder]
|
||||||
|
)
|
||||||
|
|
||||||
|
flash(f"Started Revision Run #{new_run.id}. Book '{book_folder}' will be regenerated.")
|
||||||
|
return redirect(url_for('view_project', id=run.project_id))
|
||||||
|
|
||||||
@app.route('/run/<int:id>')
|
@app.route('/run/<int:id>')
|
||||||
@login_required
|
@login_required
|
||||||
def view_run(id):
|
def view_run(id):
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ def db_progress_callback(db_path, run_id, percent):
|
|||||||
except: break
|
except: break
|
||||||
|
|
||||||
@huey.task()
|
@huey.task()
|
||||||
def generate_book_task(run_id, project_path, bible_path, allow_copy=True, feedback=None, source_run_id=None, keep_cover=False):
|
def generate_book_task(run_id, project_path, bible_path, allow_copy=True, feedback=None, source_run_id=None, keep_cover=False, exclude_folders=None):
|
||||||
"""
|
"""
|
||||||
Background task to run the book generation.
|
Background task to run the book generation.
|
||||||
"""
|
"""
|
||||||
@@ -147,6 +147,10 @@ def generate_book_task(run_id, project_path, bible_path, allow_copy=True, feedba
|
|||||||
for item in os.listdir(latest_run_dir):
|
for item in os.listdir(latest_run_dir):
|
||||||
# Copy only folders that look like books and have a manuscript
|
# Copy only folders that look like books and have a manuscript
|
||||||
if item.startswith("Book_") and os.path.isdir(os.path.join(latest_run_dir, item)):
|
if item.startswith("Book_") and os.path.isdir(os.path.join(latest_run_dir, item)):
|
||||||
|
if exclude_folders and item in exclude_folders:
|
||||||
|
utils.log("SYSTEM", f" -> Skipping copy of {item} (Target for revision).")
|
||||||
|
continue
|
||||||
|
|
||||||
if os.path.exists(os.path.join(latest_run_dir, item, "manuscript.json")):
|
if os.path.exists(os.path.join(latest_run_dir, item, "manuscript.json")):
|
||||||
src = os.path.join(latest_run_dir, item)
|
src = os.path.join(latest_run_dir, item)
|
||||||
dst = os.path.join(current_run_dir, item)
|
dst = os.path.join(current_run_dir, item)
|
||||||
|
|||||||
@@ -170,12 +170,38 @@
|
|||||||
<a href="{{ url_for('check_consistency', run_id=run.id, book_folder=book.folder) }}" class="btn btn-outline-warning ms-2">
|
<a href="{{ url_for('check_consistency', run_id=run.id, book_folder=book.folder) }}" class="btn btn-outline-warning ms-2">
|
||||||
<i class="fas fa-search me-2"></i>Check Consistency
|
<i class="fas fa-search me-2"></i>Check Consistency
|
||||||
</a>
|
</a>
|
||||||
|
<button class="btn btn-warning ms-2" data-bs-toggle="modal" data-bs-target="#reviseBookModal{{ loop.index }}" title="Regenerate this book with changes, keeping others.">
|
||||||
|
<i class="fas fa-pencil-alt me-2"></i>Revise
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<!-- Revise Book Modal -->
|
||||||
|
<div class="modal fade" id="reviseBookModal{{ loop.index }}" tabindex="-1">
|
||||||
|
<div class="modal-dialog">
|
||||||
|
<form class="modal-content" action="{{ url_for('revise_book', run_id=run.id, book_folder=book.folder) }}" method="POST">
|
||||||
|
<div class="modal-header">
|
||||||
|
<h5 class="modal-title">Revise Book</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body">
|
||||||
|
<p class="text-muted small">This will start a <strong>new run</strong>. All other books will be copied over, but this book will be regenerated based on your instructions.</p>
|
||||||
|
<div class="mb-3">
|
||||||
|
<label class="form-label">Instructions</label>
|
||||||
|
<textarea name="instruction" class="form-control" rows="4" placeholder="e.g. 'Change the ending', 'Make the pacing faster', 'Add a scene about X'." required></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer">
|
||||||
|
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
|
||||||
|
<button type="submit" class="btn btn-warning">Start Revision</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
|
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
|
|||||||
Reference in New Issue
Block a user