Skip to content

Commit 62aaf95

Browse files
committed
feat(demo): route live scenario through same-origin gateway
1 parent e6add48 commit 62aaf95

1 file changed

Lines changed: 92 additions & 0 deletions

File tree

demo/outcome-engine/live-proxy.js

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
2+
(() => {
3+
const style=document.createElement('style');
4+
style.textContent=`
5+
.privacy.demo::before{background:#c88418;box-shadow:0 0 0 5px rgba(200,132,24,.12)}
6+
.backend-proof{display:none;margin:12px 0;border:1px solid rgba(23,107,87,.2);background:#edf8f3;border-radius:16px;padding:13px;font-size:12px;color:#315c50;line-height:1.5}
7+
.backend-proof.visible{display:block}.backend-proof strong{color:var(--accent)}
8+
.trace-tools{display:flex;flex-wrap:wrap;gap:5px;margin-top:8px}.trace-tool{background:white;border:1px solid rgba(23,107,87,.14);border-radius:999px;padding:4px 7px;font-size:10px;font-weight:800}
9+
.error-box{display:none;margin:12px 0;border:1px solid rgba(161,60,60,.25);background:#fff1f1;color:#7c2929;border-radius:16px;padding:13px;font-size:13px;line-height:1.45}.error-box.visible{display:block}
10+
`;
11+
document.head.appendChild(style);
12+
13+
const privacy=document.querySelector('.privacy');
14+
const appStatus=document.querySelector('.app-head .status');
15+
privacy.id='privacyStatus'; appStatus.id='appStatus';
16+
const warning=document.getElementById('warning');
17+
const backendProof=document.createElement('div'); backendProof.id='backendProof'; backendProof.className='backend-proof';
18+
const errorBox=document.createElement('div'); errorBox.id='errorBox'; errorBox.className='error-box';
19+
warning.after(backendProof,errorBox);
20+
els.backendProof=backendProof; els.errorBox=errorBox; els.privacyStatus=privacy; els.appStatus=appStatus;
21+
22+
const originalSelectScenario=selectScenario;
23+
const originalResetResults=resetResults;
24+
const originalShowResults=showResults;
25+
const originalDecision=decision;
26+
27+
function updateMode(){
28+
const live=currentKey==='legal';
29+
privacy.textContent=live?'Live GitLaw API · ausschließlich Demo-Daten':'Interaktiver Browser-Prototyp · keine Übertragung';
30+
privacy.classList.toggle('demo',!live);
31+
appStatus.innerHTML=live?'Kanzlei: <strong>Live GitLaw API</strong> · kein automatischer Versand':'Produktprototyp · <strong>lokale Auswertung</strong> · keine Übertragung';
32+
els.runBtn.textContent=live?'Live mit GitLaw analysieren →':'Outcome Engine starten →';
33+
}
34+
35+
selectScenario=function(key){ originalSelectScenario(key); updateMode(); };
36+
resetResults=function(){
37+
originalResetResults();
38+
backendProof.classList.remove('visible'); backendProof.innerHTML='';
39+
errorBox.classList.remove('visible'); errorBox.textContent='';
40+
document.querySelector('.result-top').style.display='';
41+
document.querySelector('.cards').style.display='';
42+
document.querySelector('.review').style.display='';
43+
els.runBtn.textContent=currentKey==='legal'?'Live mit GitLaw analysieren →':'Outcome Engine starten →';
44+
};
45+
46+
function isoToGerman(iso){const m=String(iso||'').match(/^(\d{4})-(\d{2})-(\d{2})$/);return m?`${m[3]}.${m[2]}.${m[1]}`:iso;}
47+
async function runLive(text){
48+
const started=performance.now();
49+
const r=await fetch('/api/analyze',{
50+
method:'POST',
51+
headers:{'Content-Type':'application/json'},
52+
body:JSON.stringify({letter_text:text})
53+
});
54+
const p=await r.json().catch(()=>({}));
55+
if(!r.ok)throw new Error(p.upstream_error||p.detail||p.error||`Live gateway failed (${r.status})`);
56+
const a=p.artefacts||{},c=a.classification||{},f=a.frist||{},meta=a.meta||{};
57+
const docs=(a.required_documents||[]).map(d=>d.name_de||d.name||String(d)).filter(Boolean);
58+
const draft=a.mandant_notification?.body||a.anwalt_response?.body||'Kein Entwurf erzeugt — manuell prüfen.';
59+
const relative=!f.deadline_iso&&Boolean(f.raw_text),missing=!f.deadline_iso&&!f.raw_text,matched=Boolean(a.matched_case);
60+
const tasks=[matched?`Akte ${a.matched_case.aktenzeichen||'zugeordnet'} öffnen`:'Akte manuell zuordnen'];
61+
if(f.deadline_iso||f.raw_text)tasks.push('Frist nach Originalprüfung vormerken');
62+
if(docs.length)tasks.push(`${docs.length} angeforderte Unterlage${docs.length===1?'':'n'} anfordern`);
63+
if(a.mandant_notification||a.anwalt_response)tasks.push('Entwurf anwaltlich prüfen');
64+
const blockers=[];if(!matched)blockers.push('keine eindeutige Aktenzuordnung');if(relative)blockers.push('relative Frist benötigt Zugangsdatum');if(missing)blockers.push('keine eindeutige Frist erkannt');
65+
const trace=(p.tool_trace||[]).map(t=>t.tool).filter(Boolean);
66+
return {type:(c.letter_type?c.letter_type.replaceAll('_',' '):(meta.betreff||'Behördenkorrespondenz')),summary:p.final_message||c.reasoning_de||'GitLaw hat den Brief strukturiert verarbeitet.',deadline:{date:f.deadline_iso?isoToGerman(f.deadline_iso):(f.raw_text||'Nicht eindeutig erkannt'),relative,missing},docs:docs.length?docs:['Keine ausdrücklich geforderten Unterlagen erkannt'],tasks,draft,urgency:c.urgency?c.urgency[0].toUpperCase()+c.urgency.slice(1):'Manuell prüfen',blocker:blockers.length>0,warning:blockers.length?`Sicher gestoppt: ${blockers.join(' · ')}.`:'Live-Ergebnis: Vor Freigabe gegen das Originaldokument prüfen.',live:true,backend:{runId:p.agent_run_id||'—',status:p.status||'completed',latencyMs:p.gateway?.elapsed_ms||Math.round(performance.now()-started),costUsd:Number(p.total_cost_usd||0),iterations:p.iterations||trace.length,trace}};
67+
}
68+
69+
showResults=function(r){
70+
originalShowResults(r);
71+
els.confidence.textContent=r.live?'GitLaw live':'Demo-Auswertung';
72+
if(r.backend){const b=r.backend;backendProof.innerHTML=`<strong>Live backend execution</strong><br>Run ${escapeHtml(b.runId)} · ${escapeHtml(b.status)} · ${(b.latencyMs/1000).toFixed(1)} s · $${b.costUsd.toFixed(4)} · ${b.iterations} iterations<div class="trace-tools">${b.trace.map(t=>`<span class="trace-tool">${escapeHtml(t)}</span>`).join('')}</div>`;backendProof.classList.add('visible');}
73+
errorBox.classList.remove('visible');
74+
};
75+
76+
runWorkflow=async function(){
77+
const text=els.documentText.value.trim();if(text.length<50){alert('Bitte füge einen aussagekräftigen Dokumenttext ein.');return;}
78+
resetResults();els.runBtn.disabled=true;els.runBtn.textContent=currentKey==='legal'?'GitLaw verarbeitet live …':'Workflow läuft …';
79+
try{
80+
steps[0].classList.add('active');await new Promise(r=>setTimeout(r,180));steps[0].classList.remove('active');steps[0].classList.add('done');
81+
steps[1].classList.add('active');currentResult=currentKey==='legal'?await runLive(text):makeResult(text);steps[1].classList.remove('active');steps[1].classList.add('done');
82+
for(let i=2;i<5;i++){steps[i].classList.add('active');await new Promise(r=>setTimeout(r,140));steps[i].classList.remove('active');steps[i].classList.add('done');}
83+
steps[5].classList.add('active');showResults(currentResult);
84+
}catch(e){
85+
steps.forEach(s=>s.classList.remove('active'));els.resultEmpty.style.display='none';els.results.classList.add('visible');document.querySelector('.result-top').style.display='none';document.querySelector('.cards').style.display='none';document.querySelector('.review').style.display='none';errorBox.textContent=`Live-Verbindung fehlgeschlagen: ${e.message}. Es wurde kein lokales Ergebnis als echt ausgegeben.`;errorBox.classList.add('visible');currentResult=null;
86+
}finally{els.runBtn.disabled=false;els.runBtn.textContent=currentKey==='legal'?'Live erneut analysieren':'Erneut analysieren';}
87+
};
88+
decision=function(kind){originalDecision(kind);steps[5].classList.remove('active');steps[5].classList.add('done');};
89+
els.runBtn.onclick=runWorkflow;els.approveBtn.onclick=()=>decision('approve');els.reviseBtn.onclick=()=>decision('revise');els.rejectBtn.onclick=()=>decision('reject');
90+
const fine=document.querySelector('.fineprint');fine.textContent='Der Kanzlei-Fall ruft GitLaw Pro live auf und zeigt Agent-Run, Tool-Trace, Laufzeit und Kosten. Andere Rollen bleiben interaktive Produktprototypen. Keine Nachricht wird automatisch versendet.';
91+
updateMode();
92+
})();

0 commit comments

Comments
 (0)