feat: auto-select STT engine (Azure → Google Cloud → Whisper) and show provider in results
Removes user-facing engine/model/key/beam controls. The server now picks the best available engine automatically: 1. Microsoft Azure Speech — short clips (≤1MB, no diarization, audio/*) 2. Google Cloud Speech v2 — long audio, diarization, all languages 3. OpenAI Whisper GPU — local fallback Results display which provider was used (e.g. "Transcribed with Google Cloud Speech") via transcript-engine-badge and traceMeta. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,101 @@
|
||||
/* global React, ReactDOM,
|
||||
Topbar, Manifesto, Disclaimer, ToolRail, ReasoningPanel, FootStrip, TRACE_WAITING,
|
||||
AskView, SearchView, AdvocateView, RedactView, TimelineView, CasebookView, VoicesView,
|
||||
TweaksPanel, useTweaks, TweakSection, TweakSlider, TweakRadio, TweakToggle, TweakSelect
|
||||
*/
|
||||
const { useState, useEffect, useMemo } = React;
|
||||
|
||||
const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{
|
||||
"distress": 0.6,
|
||||
"headline": "twelve",
|
||||
"surface": "light"
|
||||
}/*EDITMODE-END*/;
|
||||
|
||||
const TOOL_INSTRUMENT = {
|
||||
ask: "ECHR Art. 8 · Barneloven §43",
|
||||
search: "Lovdata + Strasbourg + UNCRC",
|
||||
advocate: "ECHR Art. 8 (partisan)",
|
||||
redact: "GDPR · Personopplysningsloven",
|
||||
timeline: "Pedersen v. Norway pattern",
|
||||
cases: "ECHR Art. 8 · 23 judgments",
|
||||
voices: "Verified testimony · court documents on file",
|
||||
};
|
||||
|
||||
function App() {
|
||||
const [tool, setTool] = useState("ask");
|
||||
const [trace, setTrace] = useState(TRACE_WAITING);
|
||||
const [t, setT] = useTweaks(TWEAK_DEFAULTS);
|
||||
|
||||
// Apply visual layer to <html>
|
||||
useEffect(() => {
|
||||
const root = document.documentElement;
|
||||
root.style.setProperty("--distress", String(t.distress));
|
||||
root.classList.toggle("surface-dark", t.surface === "dark");
|
||||
}, [t.distress, t.surface]);
|
||||
|
||||
const headline = window.DBN_DATA.headlines[t.headline] || window.DBN_DATA.headlines.twelve;
|
||||
const stats = window.DBN_DATA.stats;
|
||||
|
||||
// Reset trace when tool changes
|
||||
useEffect(() => { setTrace(TRACE_WAITING); }, [tool]);
|
||||
|
||||
const view = useMemo(() => {
|
||||
switch (tool) {
|
||||
case "ask": return <AskView onTrace={setTrace}/>;
|
||||
case "search": return <SearchView onTrace={setTrace}/>;
|
||||
case "advocate": return <AdvocateView onTrace={setTrace}/>;
|
||||
case "redact": return <RedactView onTrace={setTrace}/>;
|
||||
case "timeline": return <TimelineView onTrace={setTrace}/>;
|
||||
case "cases": return <CasebookView onTrace={setTrace}/>;
|
||||
case "voices": return <VoicesView onTrace={setTrace}/>;
|
||||
default: return <AskView onTrace={setTrace}/>;
|
||||
}
|
||||
}, [tool]);
|
||||
|
||||
return (
|
||||
<main className="app-shell" data-screen-label="00 Tools Workspace">
|
||||
<Topbar caseNo="case ELENA-K-2024 · session #a1c8" status="Live · 23 violations indexed"/>
|
||||
<Disclaimer />
|
||||
<Manifesto headline={headline} stats={stats} intensity={t.distress}/>
|
||||
|
||||
<section className="workspace" aria-label="Tools workspace">
|
||||
<ToolRail active={tool} onSelect={setTool}/>
|
||||
<section className="tool-panel" aria-labelledby="toolTitle">
|
||||
<div className="corner-fold" aria-hidden="true"></div>
|
||||
{view}
|
||||
</section>
|
||||
<ReasoningPanel steps={trace} caseNo="ELENA-K-2024" instrument={TOOL_INSTRUMENT[tool]}/>
|
||||
</section>
|
||||
|
||||
<FootStrip />
|
||||
|
||||
<TweaksPanel title="Tweaks · Case workbench">
|
||||
<TweakSection title="Distress treatment">
|
||||
<TweakSlider tweak="distress" label="Intensity" min={0} max={1} step={0.05}
|
||||
value={t.distress} onChange={(v)=>setT("distress", v)}
|
||||
help="0 = somber & restrained · 1 = defiant editorial layout (bigger headline, deeper bleed, larger fold)."/>
|
||||
</TweakSection>
|
||||
|
||||
<TweakSection title="Headline variant">
|
||||
<TweakSelect tweak="headline" label="Manifesto" value={t.headline} onChange={(v)=>setT("headline", v)}
|
||||
options={[
|
||||
{ value: "twelve", label: "Twelve minutes" },
|
||||
{ value: "twentythree", label: "Twenty-three violations" },
|
||||
{ value: "members", label: "Numbers · 9,482 / 20,000" },
|
||||
{ value: "compliance", label: "Compliance is love" },
|
||||
]}/>
|
||||
</TweakSection>
|
||||
|
||||
<TweakSection title="Surface">
|
||||
<TweakRadio tweak="surface" label="Mode" value={t.surface} onChange={(v)=>setT("surface", v)}
|
||||
options={[
|
||||
{ value: "light", label: "Light" },
|
||||
{ value: "dark", label: "Dark" },
|
||||
]}/>
|
||||
</TweakSection>
|
||||
</TweaksPanel>
|
||||
</main>
|
||||
);
|
||||
}
|
||||
|
||||
ReactDOM.createRoot(document.getElementById("root")).render(<App/>);
|
||||
Reference in New Issue
Block a user