File size: 6,842 Bytes
82d282f ee6161a 82d282f ee6161a 82d282f b9b34d4 82d282f ee6161a 82d282f ee6161a 82d282f ee6161a 82d282f ee6161a 82d282f b9b34d4 82d282f ee6161a 82d282f b9b34d4 82d282f ee6161a 82d282f ee6161a 82d282f 40f243c 82d282f b9b34d4 82d282f ee6161a 82d282f 036cb16 82d282f 036cb16 82d282f 036cb16 82d282f 036cb16 82d282f 036cb16 82d282f 036cb16 b9b34d4 036cb16 82d282f 036cb16 82d282f ee6161a dd86ab1 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 |
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>RMScript App</title>
<link rel="stylesheet" href="style.css" />
</head>
<body>
<div class="hero">
<div class="hero-content">
<div class="app-icon">ππ€</div>
<h1>Reachy Mini Script App</h1>
<p class="tagline">Web app for programming Reachy Mini movements</p>
</div>
</div>
<div class="container">
<div class="main-card">
<div class="app-preview">
<div class="preview-image">
<div class="camera-feed">π»</div>
<pre class="code-preview">"Wave hello"
look left
antenna both up
wait 1s
look right</pre>
</div>
</div>
<div class="app-details">
<h2>About RMScript</h2>
<div class="template-info">
<div class="info-box">
<h3>Kid-Friendly Language</h3>
<p>Write scripts using natural language commands like <code>look left</code>, <code>turn right</code>, and <code>antenna up</code>.</p>
</div>
<div class="info-box">
<h3>Real-Time Execution</h3>
<p>Execute scripts directly on your robot with proper timing and smooth movements.</p>
</div>
</div>
<div class="how-to-use">
<h3>Features</h3>
<div class="steps">
<div class="step">
<div class="step-number">1</div>
<div>
<h4>Syntax Highlighting</h4>
<p>Real-time verification and error detection as you type</p>
</div>
</div>
<div class="step">
<div class="step-number">2</div>
<div>
<h4>Live Compilation</h4>
<p>Instant compilation to robot commands with visual intermediate representation preview</p>
</div>
</div>
<div class="step">
<div class="step-number">3</div>
<div>
<h4>Movements & Sounds</h4>
<p>Support for head movements, antennas, waits, (sounds and pictures TBD !) </p>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="download-section">
<div class="download-card">
<h2>Install This App</h2>
<div class="dashboard-config">
<label for="dashboardUrl">Your Reachy Dashboard URL (when using the desktop Reachy Mini app):</label>
<input type="url" id="dashboardUrl" value="http://localhost:8042"
placeholder="http://your-reachy-ip:8000" />
</div>
<button id="installBtn" class="install-btn primary">
<span class="btn-icon">π₯</span>
Install Reachy Mini Script App to Reachy Mini
</button>
<div id="installStatus" class="install-status"></div>
</div>
</div>
<div class="footer">
<p>
π RMScript App β’
<a href="https://github.com/pollen-robotics" target="_blank">Pollen Robotics</a> β’
<a href="https://huggingface.co/spaces/pollen-robotics/Reachy_Mini_Apps" target="_blank">Browse More Apps</a>
</p>
</div>
<script>
function getCurrentSpaceUrl() {
const url = window.location.href;
// Match huggingface.co/spaces/user/repo format
const match = url.match(/https:\/\/huggingface\.co\/spaces\/([^\/]+\/[^\/]+)/);
if (match) {
return `https://huggingface.co/spaces/${match[1]}`;
}
// Match user-repo.hf.space format
if (url.includes('.hf.space')) {
const hostMatch = url.match(/https?:\/\/([^\.]+)\.hf\.space/);
if (hostMatch) {
const spaceName = hostMatch[1].replace(/-/g, '/');
return `https://huggingface.co/spaces/${spaceName}`;
}
}
return url;
}
async function parseTomlProjectName(tomlContent) {
const nameMatch = tomlContent.match(/^name\s*=\s*["']([^"']+)["']/m);
return nameMatch ? nameMatch[1] : null;
}
async function getAppNameFromCurrentSpace() {
try {
const spaceUrl = getCurrentSpaceUrl();
const tomlUrl = spaceUrl + '/raw/main/pyproject.toml';
const response = await fetch(tomlUrl);
if (response.ok) {
const tomlContent = await response.text();
return await parseTomlProjectName(tomlContent);
}
} catch (e) {
console.error('Error fetching app name:', e);
}
return 'rmscript-app';
}
function showStatus(type, message) {
const statusEl = document.getElementById('installStatus');
statusEl.className = `install-status ${type}`;
statusEl.textContent = message;
statusEl.style.display = 'block';
}
async function installToReachy() {
const btn = document.getElementById('installBtn');
const dashboardUrl = document.getElementById('dashboardUrl').value.replace(/\/$/, '');
btn.disabled = true;
showStatus('loading', 'Connecting to Reachy dashboard...');
try {
// Test connection using the correct endpoint
const testResponse = await fetch(`${dashboardUrl}/api/apps/list-available`, {
method: 'GET',
mode: 'cors',
});
if (!testResponse.ok) {
throw new Error('Cannot connect to dashboard');
}
showStatus('loading', 'Installing app...');
const spaceUrl = getCurrentSpaceUrl();
const appName = await getAppNameFromCurrentSpace();
// Use correct API format: AppInfo schema with name, source_kind, url
const installResponse = await fetch(`${dashboardUrl}/api/apps/install`, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
name: appName || 'rmscript-app',
source_kind: 'hf_space',
url: spaceUrl,
description: 'Web app for programming Reachy Mini with RMScript language',
}),
mode: 'cors',
});
if (installResponse.ok) {
const result = await installResponse.json();
if (result.job_id) {
showStatus('success', `Installation started! Job ID: ${result.job_id}. Check the dashboard for progress.`);
} else {
showStatus('success', `Successfully installed! Open the dashboard to run ${appName}.`);
}
} else {
const error = await installResponse.text();
throw new Error(error || 'Installation failed');
}
} catch (e) {
showStatus('error', `Error: ${e.message}. Make sure the Reachy daemon is running.`);
} finally {
btn.disabled = false;
}
}
document.getElementById('installBtn').addEventListener('click', installToReachy);
</script>
</body>
</html>
|