cduss's picture
Upload folder using huggingface_hub
3389a05 verified
Raw
History Blame Contribute Delete
11.5 kB
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
<title>Minimal Conversation</title>
<link rel="icon" href="/icon.svg" type="image/svg+xml" />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700;800&display=swap"
rel="stylesheet"
/>
<!--
Cross-mode boot guard.
The body ships pre-rendered with the embed-mode DOM scaffolding
(the conversation orb, settings dialog, etc.) so the embed entry
can wire to it without an extra paint. In *host* mode that
scaffolding is irrelevant - `mountHost()` calls
`document.body.replaceChildren()` and injects `#root` - but the
host bundle is loaded asynchronously, so without this guard the
conversation UI flashes for ~1 frame before the wipe. The
embed-mode CSS that normally hides `.hidden` lives in
`style.css` and is itself only loaded by `embed.ts`, hence the
duplication here.
`body.booting` is removed by both entries (host: in `mountHost`
after the wipe, embed: at the end of `boot()`) once the
respective content is ready to be shown.
-->
<style>
body.booting #app,
body.booting #settings-modal {
display: none !important;
}
</style>
<!--
Theme bootstrap: paints the right palette BEFORE the CSS is
applied so there is no flash of the wrong palette. Priority:
1. `?theme=dark|light` query param (set by the host),
2. `prefers-color-scheme` (standalone).
-->
<script>
(function () {
try {
var params = new URLSearchParams(window.location.search);
var raw = params.get("theme");
var mode;
if (raw === "dark" || raw === "light") {
mode = raw;
} else if (window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches === false) {
mode = "light";
} else {
mode = "dark";
}
document.documentElement.setAttribute("data-theme", mode);
} catch (_) {
document.documentElement.setAttribute("data-theme", "dark");
}
})();
</script>
<!--
HF Spaces helper variables.
On a `sdk: static` Space, HF injects
`window.huggingface = { variables: { OAUTH_CLIENT_ID, OAUTH_SCOPES,
OPENID_PROVIDER_URL, ... } }` into the <head> automatically when
`hf_oauth: true` is set in README.md — so no build-time or
entrypoint substitution is needed (the Docker variant patched
placeholders here; the static variant gets it for free).
For local dev (`npm run dev`) `window.huggingface` is absent and
the host shell falls back to the clientId from `?clientId=` or the
Settings dialog (see the SDK APP_AUTHOR_GUIDE).
-->
<!--
The ReachyMini SDK is no longer loaded from a CDN script tag:
`src/dispatch.ts` statically imports `@pollen-robotics/reachy-mini-sdk`
from npm and exposes the constructor on `window.ReachyMini` before
the host shell or the embed entry runs (both wait for the global).
The bundled SDK is version-pinned via `package.json`, removing
the jsdelivr branch / cache-purge friction we used to live with.
-->
<script type="module" crossorigin src="/assets/index-COur_VG-.js"></script>
</head>
<!--
`booting` disables transitions + animations until the first paint is
committed. The dispatcher strips the class after one rAF.
-->
<body class="booting">
<!--
The DOM scaffolding below is intentionally hidden by default
(`display:none`) and revealed only when the embed entry mounts
it (so the host's iframe doesn't briefly flash through a broken
layout during the host:init handshake). The dispatcher swaps in
the standalone host shell when `?embedded=1` is absent, replacing
the body content.
-->
<div id="app" class="hidden">
<main class="stage">
<div class="orb-wrap">
<button id="mic-btn" class="side-btn" type="button" aria-label="Mute" title="Mute" aria-hidden="true">
<svg class="mic-on" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="2" width="6" height="12" rx="3"/><path d="M5 10a7 7 0 0 0 14 0"/><line x1="12" y1="19" x2="12" y2="22"/></svg>
<svg class="mic-off" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"><line x1="2" y1="2" x2="22" y2="22"/><path d="M9 5a3 3 0 0 1 6 0v4"/><path d="M9 10v1a3 3 0 0 0 5.1 2.1"/><path d="M19 10a7 7 0 0 1-1.24 3.97"/><path d="M5 10a7 7 0 0 0 11 5.67"/><line x1="12" y1="19" x2="12" y2="22"/></svg>
</button>
<button
id="main-circle"
class="circle state-starting"
type="button"
aria-label="Voice conversation"
>
<span class="circle-glow" aria-hidden="true"></span>
<span class="circle-ring" aria-hidden="true"></span>
<span class="circle-ring-outer" aria-hidden="true"></span>
<span class="circle-core">
<span class="circle-indicator" aria-hidden="true">
<svg class="ind ind-mic" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.6" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<rect x="9" y="2" width="6" height="12" rx="3" fill="currentColor" stroke="none"/>
<path d="M5 10a7 7 0 0 0 14 0"/>
<line x1="12" y1="19" x2="12" y2="22"/>
<line x1="8" y1="22" x2="16" y2="22"/>
</svg>
<svg class="ind ind-error" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="9"/><line x1="12" y1="8" x2="12" y2="13"/><line x1="12" y1="16" x2="12" y2="16"/></svg>
<span class="ind ind-spinner"></span>
<span class="ind ind-thinking">
<span class="dot"></span>
<span class="dot"></span>
<span class="dot"></span>
</span>
<span class="ind ind-bars">
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
<span class="bar"></span>
</span>
<svg class="ind ind-voice" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<path d="M3 10v4a1 1 0 0 0 1 1h3l5 4V5L7 9H4a1 1 0 0 0-1 1z" fill="currentColor" stroke="none"/>
<path class="wave wave-1" d="M16 8a5 5 0 0 1 0 8"/>
<path class="wave wave-2" d="M19 5a9 9 0 0 1 0 14"/>
</svg>
</span>
</span>
</button>
<button id="stop-btn" class="side-btn" type="button" aria-label="End" title="End" aria-hidden="true">
<svg viewBox="0 0 24 24" fill="currentColor"><rect x="6" y="6" width="12" height="12" rx="2"/></svg>
</button>
</div>
<p id="circle-caption" class="circle-caption" role="status">Starting</p>
<div id="tool-toast" class="tool-toast" role="status" aria-live="polite" aria-hidden="true">
<svg class="tool-toast-icon" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round" aria-hidden="true">
<circle cx="12" cy="12" r="3"/>
<path d="M12 2v3M12 19v3M2 12h3M19 12h3M4.9 4.9l2.1 2.1M17 17l2.1 2.1M4.9 19.1l2.1-2.1M17 7l2.1-2.1"/>
</svg>
<span class="tool-toast-text"></span>
</div>
<button id="settings-btn" class="settings-fab" type="button" title="Settings" aria-label="Settings">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 1 1-2.83 2.83l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 1 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 1 1-2.83-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 1 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 1 1 2.83-2.83l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 1 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 1 1 2.83 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9c0 .66.39 1.25 1 1.51H21a2 2 0 1 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></svg>
</button>
</main>
</div>
<dialog id="settings-modal" class="modal">
<form method="dialog" class="modal-content">
<header class="modal-header">
<h2>Settings</h2>
<button class="icon-btn" value="close" aria-label="Close">
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
</button>
</header>
<!--
The only remaining user-editable setting is the system
prompt. The OpenAI key is no longer asked: the app mints a
short-lived Realtime ephemeral key from the visitor's HF
OAuth token (see `src/ephemeral-key.ts`). Model + voice are
locked to the server-side defaults that the ephemeral mint
provisions, so exposing pickers here would just invite
mismatches with the SDP handshake's session config.
-->
<div class="settings-body">
<label class="field">
<span>Instructions</span>
<textarea id="openai-instructions" rows="6" placeholder="You are Reachy Mini, a friendly robot assistant..."></textarea>
<small>System prompt sent to the model. Applied on next conversation start.</small>
</label>
<!--
Only does something while a session is live - embed.ts enables
the button whenever the conversation engine is live, and hides
the hint otherwise.
-->
<div class="field">
<button id="restart-conversation" type="button" class="btn primary wide" disabled>
Restart conversation with these instructions
</button>
<small id="restart-hint">Connect first, then come back here to apply live changes.</small>
</div>
</div>
<footer class="modal-footer">
<button id="settings-save" type="submit" class="btn primary" value="save">Save</button>
</footer>
</form>
</dialog>
<!--
Single dispatcher. Picks the host shell (standalone visit) or
the embedded app (host's iframe) based on `?embedded=1`.
-->
</body>
</html>