diff --git a/llm_team_ui.py b/llm_team_ui.py index 316ce10..00cc776 100644 --- a/llm_team_ui.py +++ b/llm_team_ui.py @@ -6485,6 +6485,47 @@ def start_optimize(run_id): return jsonify({"ok": True, "job_id": job_id}) +@app.route("/api/optimize-history/") +@login_required +def optimize_history(run_id): + """Get optimization results for a specific parent run.""" + try: + with get_db() as conn: + with conn.cursor(cursor_factory=psycopg2.extras.RealDictCursor) as cur: + # Find all optimize pipeline runs for this parent + cur.execute(""" + SELECT id, result, duration_ms, completed_at + FROM pipeline_runs + WHERE pipeline = 'optimize' AND result->>'parent_run' = %s + ORDER BY completed_at DESC + """, (str(run_id),)) + results = [] + for r in cur.fetchall(): + res = r.get("result") or {} + results.append({ + "id": r["id"], + "best_score": res.get("best_score"), + "original_score": res.get("original_score"), + "improvement": res.get("improvement"), + "variations_tested": res.get("variations_tested"), + "calls_used": res.get("calls_used"), + "ranked": res.get("ranked", [])[:3], + "completed_at": str(r["completed_at"]) if r["completed_at"] else None, + "duration_ms": r["duration_ms"], + }) + # Also find child runs + cur.execute(""" + SELECT id, mode, quality_score, config->>'strategy' as strategy, config->>'variation' as variation + FROM team_runs + WHERE config->>'parent_run' = %s + ORDER BY quality_score DESC NULLS LAST + """, (str(run_id),)) + children = [dict(r) for r in cur.fetchall()] + return jsonify({"results": results, "children": children}) + except Exception as e: + return jsonify({"error": str(e), "results": [], "children": []}), 500 + + @app.route("/api/optimize//stream") @login_required def optimize_stream(job_id): @@ -6787,9 +6828,19 @@ function toast(msg, ok) { async function startOptimize(runId) { var r = await fetch('/api/runs/'+runId+'/optimize', {method:'POST'}); var data = await r.json(); + if (data.error && data.job_id) { + // Already running — reconnect to existing stream + toast('Reconnecting to active optimization...', true); + var jobId = data.job_id; + _showOptimizeStream(runId, jobId); + return; + } if (data.error) { toast(data.error, false); return; } var jobId = data.job_id; + _showOptimizeStream(runId, jobId); +} +function _showOptimizeStream(runId, jobId) { var panel = document.getElementById('detail-panel'); panel.textContent = ''; @@ -7036,13 +7087,48 @@ async function openDetail(id) { var delBtn = document.createElement('button'); delBtn.className = 'tool-btn red'; delBtn.textContent = 'Delete'; delBtn.onclick = function(){ if(confirm('Delete permanently?')){fetch('/api/runs/'+id,{method:'DELETE'}).then(function(){toast('Deleted',true);loadRuns();panel.className='detail-panel'})} }; actions.appendChild(delBtn); + var meta = run.score_metadata || {}; + var isOptimized = meta.optimized; var optBtn = document.createElement('button'); optBtn.className = 'tool-btn'; optBtn.style.cssText = 'color:var(--accent);border-color:var(--accent);margin-left:auto'; - optBtn.textContent = '\u26A1 Optimize'; + optBtn.textContent = isOptimized ? '\u26A1 Re-Optimize' : '\u26A1 Optimize'; optBtn.onclick = function(){ startOptimize(id); }; actions.appendChild(optBtn); panel.appendChild(actions); + // Optimization history + if (isOptimized) { + var optSection = document.createElement('div'); + optSection.style.cssText = 'background:var(--glow);border:1px solid var(--accent);border-radius:2px;padding:12px;margin-bottom:12px'; + var optTitle = document.createElement('div'); + optTitle.style.cssText = 'font-family:JetBrains Mono,monospace;font-size:9px;text-transform:uppercase;letter-spacing:1.5px;color:var(--accent);margin-bottom:6px;font-weight:700'; + optTitle.textContent = 'Optimization Results'; + optSection.appendChild(optTitle); + var optInfo = document.createElement('div'); + optInfo.style.cssText = 'font-size:12px;color:var(--text);line-height:1.6'; + var bestId = meta.best_variation_run; + var jobId = meta.optimize_job || ''; + optInfo.textContent = 'Best variation: Run #' + (bestId||'?') + ' | Job: ' + jobId; + optSection.appendChild(optInfo); + if (bestId) { + var viewBtn = document.createElement('button'); viewBtn.className = 'tool-btn'; + viewBtn.style.cssText = 'margin-top:8px;font-size:9px'; + viewBtn.textContent = 'View Best Variation (#' + bestId + ')'; + viewBtn.onclick = function(){ openDetail(bestId); }; + optSection.appendChild(viewBtn); + } + // Load pipeline results for more detail + fetch('/api/optimize-history/' + id).then(function(r){return r.json()}).then(function(d){ + if (d.results && d.results.length) { + var count = document.createElement('div'); + count.style.cssText = 'font-size:11px;color:var(--text2);margin-top:6px;font-family:JetBrains Mono,monospace'; + count.textContent = d.results.length + ' optimization(s) run | Best: ' + (d.results[0].best_score||'?') + '/10 | Original: ' + (d.results[0].original_score||'?') + '/10'; + optSection.appendChild(count); + } + }).catch(function(){}); + panel.appendChild(optSection); + } + // Responses var responses = run.responses || []; var respTitle = document.createElement('div');