feat: add Hermes WebUI provisioning and English Dragon HD Omni voices
Rebuild & Deploy / rebuild (push) Successful in 2m17s

This commit is contained in:
snowspeeder committed 2026-10-02 16:07:24 -04:00
1 parent 47cc9c88a0
commit 6b8d55fc92
59 files changed
+1175 -70

No files matched your search

+10
View File
@@ -0,0 +1,10 @@
<!doctype html><html lang="en"><head><meta charset="utf-8"><meta name="viewport" content="width=device-width,initial-scale=1,viewport-fit=cover"><title>Hope — Gather</title><style>
:root{--bg:#edf1ef;--ink:#183d34;--quiet:#52685f;--tint:#17614d;--wash:#e5eee9;--line:#d6e0da;--surface:#fff;--on:#fff}*{box-sizing:border-box}body{margin:0;background:var(--bg);color:var(--ink);font-family:-apple-system,BlinkMacSystemFont,"Segoe UI",sans-serif;-webkit-font-smoothing:antialiased}button,input,select{font:inherit}button{cursor:pointer;color:inherit;min-height:44px;border:0;background:none}button:focus-visible,a:focus-visible,input:focus-visible,select:focus-visible{outline:3px solid #b14d22;outline-offset:3px}a{color:inherit}h1,h2,p{margin:0}h1,h2{text-wrap:balance}[hidden]{display:none!important}.studio{max-width:1260px;margin:auto;min-height:100vh;display:grid;grid-template-columns:1fr 390px 200px;gap:50px;align-items:center;padding:44px}.intro{align-self:start;padding-top:70px}.back{font-size:14px;text-decoration:none;display:inline-flex;align-items:center;min-height:44px}.direction{display:block;margin:38px 0 18px;font-size:15px;font-weight:600}.intro h1{font-family:Georgia,serif;font-size:64px;font-weight:400;letter-spacing:-.035em;line-height:1.06}.lede{font-size:18px;line-height:1.6;margin-top:24px;max-width:33ch}.notes{margin-top:40px}.note{border-top:1px solid #c8d5cd;padding:18px 0;font-size:14px;line-height:1.55}.note strong{display:block;font-size:15px;margin-bottom:4px}.prototype-label{font-size:12px;margin:0 0 12px;text-align:center;color:var(--quiet)}.phone{width:390px;height:804px;background:var(--surface);border:8px solid #19352c;border-radius:48px;position:relative;overflow:hidden;display:flex;flex-direction:column}.statusbar{height:48px;flex-shrink:0;display:flex;align-items:center;justify-content:space-between;padding:10px 26px 0;font-size:14px;font-weight:650}.island{position:absolute;top:9px;left:50%;transform:translateX(-50%);width:110px;height:28px;background:#19352c;border-radius:20px}.topbar{display:flex;align-items:center;justify-content:space-between;padding:18px 20px 12px}.brand{font-size:28px;font-weight:650;letter-spacing:-.035em;display:flex;gap:9px;align-items:center}.brand svg{width:27px;height:27px;color:#db6137}.account{border:1px solid var(--line);border-radius:50%;width:44px;font-size:14px;font-weight:600}.view{flex:1;overflow:auto;padding:0 20px 18px;min-height:0}.welcome{padding:21px 0 23px}.welcome h2{font-family:Georgia,serif;font-size:34px;font-weight:400;line-height:1.16;letter-spacing:-.025em}.welcome p{color:var(--quiet);font-size:15px;line-height:1.5;margin-top:12px}.meta{display:flex;align-items:center;gap:7px;color:var(--quiet);font-size:12px;margin:0 0 18px}.dot{width:7px;height:7px;background:var(--tint);border-radius:50%}.topic{display:flex;justify-content:space-between;align-items:center;margin-bottom:18px;font-size:13px;color:var(--quiet)}.tag{background:var(--wash);padding:6px 10px;border-radius:6px;color:var(--ink)}.messages{display:flex;flex-direction:column;gap:22px}.message{font-size:16px;line-height:1.55}.who{font-size:12px;color:var(--quiet);font-weight:600;margin-bottom:7px}.message.user{margin-left:36px;background:var(--wash);padding:12px 15px;border-radius:12px}.message.assistant{padding-right:7px}.message p{white-space:pre-wrap;overflow-wrap:anywhere}.suggestion{display:flex;justify-content:space-between;width:100%;text-align:left;border-top:1px solid var(--line);border-bottom:1px solid var(--line);font-size:14px;margin-top:24px;padding:10px 0;color:var(--tint)}.dock{padding:14px 20px 15px;border-top:1px solid var(--line)}.voice-line{display:flex;align-items:center;justify-content:space-between;margin-bottom:10px}.voice-status{font-size:13px;font-weight:600}.voice-sub{font-size:12px;color:var(--quiet);margin-top:4px}.wave{height:24px;display:flex;align-items:center;gap:3px;color:var(--tint)}.wave i{width:3px;height:7px;background:currentColor;border-radius:3px}.wave i:nth-child(2n){height:17px}.wave i:nth-child(3n){height:24px}.controls{display:flex;gap:8px}.primary{background:var(--tint);color:var(--on);border-radius:12px;font-weight:600;flex:1;min-height:52px}.secondary{background:var(--wash);border-radius:12px;padding:0 14px;min-height:52px}.end{color:#9b352a;border:1px solid var(--line);border-radius:12px;padding:0 12px}.tabs{display:flex;justify-content:space-around;padding:7px 12px 17px;border-top:1px solid var(--line);flex-shrink:0}.tab{display:flex;flex-direction:column;gap:4px;align-items:center;color:var(--quiet);min-width:80px;font-size:11px;padding:4px}.tab svg{width:23px;height:23px}.tab[aria-selected=true]{color:var(--tint);font-weight:700}.home{position:absolute;bottom:6px;width:120px;height:4px;background:var(--ink);left:50%;transform:translateX(-50%);border-radius:3px}.app-icon{width:150px;height:150px;border-radius:34px;background:#db6137;display:grid;place-items:center}.app-icon svg{width:110px;height:110px;color:#fff}.icon-title{font-size:17px;font-weight:650;margin-top:20px}.icon-caption{font-size:14px;line-height:1.6;margin-top:10px;color:var(--quiet)}.small-icons{display:flex;gap:14px;align-items:end;margLine truncated
</style></head><body><svg width="0" height="0" style="position:absolute" aria-hidden="true"><defs><symbol id="mark" viewBox="0 0 100 100"><path fill="currentColor" d="M18 19h64v48H51L31 83V67H18z"/><path d="M36 34v19m14-24v29m14-24v19" stroke="#db6137" stroke-width="6" stroke-linecap="round"/></symbol><symbol id="talk" viewBox="0 0 24 24"><path d="M4 4h16v12H10l-5 4v-4H4z"/></symbol><symbol id="activity" viewBox="0 0 24 24"><path d="M9 5h11M9 12h11M9 19h11M3 5l1 1 2-3M3 12l1 1 2-3M3 19l1 1 2-3"/></symbol><symbol id="settings" viewBox="0 0 24 24"><path d="M3 7h18M3 17h18"/><circle cx="8" cy="7" r="3"/><circle cx="16" cy="17" r="3"/></symbol></defs></svg>
<main class="studio"><section class="intro"><a class="back" href="index.html">← All three directions</a><span class="direction">Gather / conversation first</span><h1>A place for<br>your thoughts.</h1><p class="lede">Less dashboard. More conversation. A readable thread that keeps your words—and Hope’s answers—at the center.</p><div class="notes"><div class="note"><strong>The transcript is the interface.</strong>No oversized visualizer. Pick up a conversation without hunting for its context.</div><div class="note"><strong>Voice stays within reach.</strong>One persistent dock for talking, muting, or switching to text.</div><div class="note"><strong>A warmer identity, without the glow.</strong>Forest-green controls. A terracotta speech mark that reads clearly on your home screen.</div></div></section>
<section class="demo" aria-label="Interactive Gather prototype"><p class="prototype-label">Interactive iOS concept · sample conversation</p><div class="phone" id="phone"><div class="statusbar"><span>9:41</span><div class="island"></div><span aria-hidden="true">▮▮▮ ▰</span></div><header class="topbar"><div class="brand">Hope <svg aria-hidden="true"><use href="#mark"/></svg></div><button class="account" id="account" aria-label="Open account settings">S</button></header><section class="view" id="talk-view" aria-label="Conversation"><div class="welcome"><h2>Let’s make room<br>for a good weekend.</h2><p>One conversation. Speak or type.</p></div><div class="meta"><span class="dot"></span>Your personal assistant · demo</div><div class="topic"><span class="tag">Weekend plans</span><span>Today, 9:38</span></div><div class="messages" id="messages" aria-live="polite"><article class="message user"><div class="who">You</div><p>I want a quiet weekend. Help me find a starting point?</p></article><article class="message assistant"><div class="who">Hope</div><p>Start with one thing you don’t want to rush. A morning walk, a good book, or cooking something new. What sounds good to you?</p></article></div><button class="suggestion" id="suggestion"><span>Let’s start with a morning walk</span><span aria-hidden="true">↗</span></button></section>
<section class="view" id="activity-view" aria-label="Assistant activity" hidden><h2 class="section-title">Activity</h2><p class="section-sub">See what Hope is working on, without leaving your conversation.</p><div class="row"><strong id="task-title">No task running</strong><p id="task-detail">Start the voice demo to see progress here.</p><small id="task-status">Ready</small></div><div class="row"><strong>Weekend conversation</strong><p>Your latest conversation is available in Talk.</p><small>Sample history · Today, 9:38</small></div></section><section class="view" id="settings-view" aria-label="Settings" hidden><h2 class="section-title">Settings</h2><p class="section-sub">Your voice, your preferences.</p><div class="group"><div class="setting"><span>Account</span><strong>Shane · demo</strong></div><label class="setting"><span>Hope’s voice</span><select id="voice"><option>Ava</option><option>Andrew</option><option>Emma</option></select></label><label class="setting"><span>Read replies aloud</span><input class="switch" type="checkbox" checked></label><label class="setting"><span>Dark appearance</span><input class="switch" id="dark-switch" type="checkbox"></label></div><p class="notice">Preferences are local to this demonstration. No server or account is connected.</p><button class="suggestion" id="signout">Sign out of demo <span aria-hidden="true">→</span></button><p class="notice" id="settings-note" role="status"></p></section>
<div class="dock" id="dock"><div class="voice-line"><div><div class="voice-status" id="voice-status" role="status">Ready when you are</div><div class="voice-sub" id="voice-sub">Microphone off · simulated audio</div></div><div class="wave" aria-hidden="true"><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i><i></i></div></div><div class="controls" id="voice-controls"><button class="primary" id="start">Talk to Hope</button><button class="secondary" id="text" aria-label="Switch to text">Aa</button><button class="end" id="end" hidden>End</button></div><form class="composer" id="composer" hidden><label class="sr-only" for="input">Message Hope</label><input id="input" placeholder="Message Hope…" maxlength="1000" autocomplete="off"><button aria-label="Send message" type="submit">↑</button></form><button class="mode-back" id="voice-back" hidden>Switch to voice</button></div>
<nav class="tabs" role="tablist" aria-label="Main sections"><button class="tab" role="tab" aria-selected="true" aria-controls="talk-view" data-view="talk"><svg fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><use href="#talk"/></svg>Talk</button><button class="tab" role="tab" aria-selected="false" aria-controls="activity-view" data-view="activity"><svg fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><use href="#activity"/></svg>Activity</button><button class="tab" role="tab" aria-selected="false" aria-controls="settings-view" data-view="settings"><svg fill="none" stroke="currentColor" stroke-width="1.7" aria-hidden="true"><use href="#settings"/></svg>Settings</button></nav><div class="home" aria-hidden="true"></div></div></section>
<aside class="icons"><div class="app-icon" aria-label="New Gather app icon"><svg aria-hidden="true"><use href="#mark"/></svg></div><h2 class="icon-title">The speech mark</h2><p class="icon-caption">A conversation bubble with three voice bars. Clear silhouette. No capsule, no halo.</p><div class="small-icons" aria-label="Icon at home-screen and small sizes"><div class="small-icon"><svg aria-hidden="true"><use href="#mark"/></svg></div><div class="small-icon tiny"><svg aria-hidden="true"><use href="#mark"/></svg></div></div><button class="theme" id="theme">Preview dark appearance</button><p class="demo-note">Try Talk to Hope, text input, Activity, and Settings. All replies and progress are simulated; this page never accesses your microphone.</p></aside></main>
<script>const $=id=>document.getElementById(id);let active=false,muted=false,timers=[],busy=false;function stopTimers(){timers.forEach(clearTimeout);timers=[];busy=false}function status(title,sub){$('voice-status').textContent=title;$('voice-sub').textContent=sub}function show(view){document.querySelectorAll('.view').forEach(el=>el.hidden=el.id!==view+'-view');document.querySelectorAll('.tab').forEach(el=>el.setAttribute('aria-selected',String(el.dataset.view===view)));$('dock').hidden=view==='settings'}document.querySelectorAll('.tab').forEach(btn=>btn.onclick=()=>show(btn.dataset.view));$('account').onclick=()=>show('settings');function add(role,text){let a=document.createElement('article');a.className='message '+role;let who=document.createElement('div');who.className='who';who.textContent=role==='user'?'You':'Hope';let p=document.createElement('p');p.textContent=text;a.append(who,p);$('messages').append(a);$('suggestion').hidden=true;$('talk-view').scrollTop=$('talk-view').scrollHeight}function reply(text){if(busy)return;busy=true;add('user',text);status('Finding a starting point…','Working · sample response');$('task-title').textContent='Putting together a suggestion';$('task-detail').textContent='Hope is preparing a response for your conversation.';$('task-status').textContent='In progress · simulated';timers.push(setTimeout(()=>{add('assistant','Keep it simple: choose a nearby route, leave your headphones at home, and give yourself thirty minutes with no schedule. Want to plan the rest of the day?');status(active&&!muted?'Listening':muted?'Microphone muted':'Ready when you are',active?'Demo session · no microphone access':'Microphone off · simulated audio');$('task-title').textContent='Suggestion ready';$('task-detail').textContent='Hope’s reply is in your conversation.';$('task-status').textContent='Completed · simulated';busy=false},1400))}function begin(){active=true;muted=false;$('start').textContent='Mute';$('start').setAttribute('aria-pressed','false');$('end').hidden=false;status('Listening','Demo session · no microphone access');timers.push(setTimeout(()=>{if(active&&!muted)reply('Let’s start with a morning walk.')},2000))}$('start').onclick=()=>{if(!active){begin();return}muted=!muted;$('start').textContent=muted?'Unmute':'Mute';$('start').setAttribute('aria-pressed',String(muted));status(muted?'Microphone muted':'Listening','Demo session · no microphone access')};$('end').onclick=()=>{stopTimers();active=false;muted=false;$('start').textContent='Talk to Hope';$('start').removeAttribute('aria-pressed');$('end').hidden=true;status('Conversation ended','Microphone off · sample transcript kept');$('task-status').textContent='Stopped'};function textMode(on){$('voice-controls').hidden=on;$('composer').hidden=!on;$('voice-back').hidden=!on;if(on){muted=active;status('Type to Hope','Voice input off');$('input').focus()}else status(active?'Microphone muted':'Ready when you are','Microphone off · simulated audio')}$('text').onclick=()=>textMode(true);$('voice-back').onclick=()=>{textMode(false);if(active)$('start').textContent='Unmute'};$('composer').onsubmit=e=>{e.preventDefault();const val=$('input').value.trim();if(val&&!busy){$('input').value='';reply(val)}};$('suggestion').onclick=()=>reply('Let’s start with a morning walk.');function dark(on){$('phone').classList.toggle('dark',on);$('dark-switch').checked=on;$('theme').textContent=on?'Preview light appearance':'Preview dark appearance'}$('theme').onclick=()=>dark(!$('phone').classList.contains('dark'));$('dark-switch').onchange=e=>dark(e.target.checked);$('voice').onchange=e=>$('settings-note').textContent='Demo voice set to '+e.target.value+'.';$('signout').onclick=()=>{$('end').click();$('settings-note').textContent='Demo signed out. No real account was changed. Reload to reset the sample.'};document.querySelector('.tabs').addEventListener('keydown',e=>{if(!['ArrowLeft','ArrowRight','Home','End'].includes(e.key))return;e.preventDefault();let tabs=[...document.querySelectorAll('.tab')],i=tabs.indexOf(document.activeElement);i=e.key==='Home'?0:e.key==='End'?tabs.length-1:(i+(e.key==='ArrowRight'?1:-1)+tabs.length)%tabs.length;tabs[i].focus();tabs[i].click()});</script></body></html>