Upload app.py
Browse files
app.py
CHANGED
|
@@ -3008,8 +3008,8 @@ FRONTEND_HTML = r"""
|
|
| 3008 |
</div>
|
| 3009 |
<div class="settings-actions">
|
| 3010 |
<button id="saveReachySettings" type="button">Save settings</button>
|
| 3011 |
-
<button id="
|
| 3012 |
-
<button id="
|
| 3013 |
<span class="status-line" id="reachyStatus">Reachy bridge not configured.</span>
|
| 3014 |
<span class="status-line" id="metricsSyncStatus"></span>
|
| 3015 |
</div>
|
|
@@ -3473,21 +3473,6 @@ FRONTEND_HTML = r"""
|
|
| 3473 |
return normalizeForCorrectionCompare(original) === normalizeForCorrectionCompare(corrected);
|
| 3474 |
}
|
| 3475 |
|
| 3476 |
-
function reachyToneBridgeUrl(baseUrl, payload) {
|
| 3477 |
-
const json = JSON.stringify({
|
| 3478 |
-
text: payload.text || "",
|
| 3479 |
-
emotion: payload.emotion || "happy",
|
| 3480 |
-
lang: payload.lang || "en",
|
| 3481 |
-
robotVoice: payload.robotVoice !== false,
|
| 3482 |
-
audioUrl: payload.audioUrl || "",
|
| 3483 |
-
autoRun: true
|
| 3484 |
-
});
|
| 3485 |
-
const config = btoa(unescape(encodeURIComponent(json)));
|
| 3486 |
-
const url = new URL(baseUrl);
|
| 3487 |
-
url.searchParams.set("config", config);
|
| 3488 |
-
return url.toString();
|
| 3489 |
-
}
|
| 3490 |
-
|
| 3491 |
function reachyAudioUrl(comment, chinese) {
|
| 3492 |
const url = new URL("/reachy_audio.mp3", window.location.origin);
|
| 3493 |
url.searchParams.set("comment", comment || "Here is the correction.");
|
|
@@ -3496,6 +3481,11 @@ FRONTEND_HTML = r"""
|
|
| 3496 |
return url.toString();
|
| 3497 |
}
|
| 3498 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3499 |
function buildReachyCorrectionPayload(payload, renderedText) {
|
| 3500 |
const original = payload.original_sentence || currentOriginalSentence || field("#sentence").value.trim();
|
| 3501 |
const corrected = payload.corrected_sentence || currentCorrectedSentence || extractCorrectedSentence(renderedText) || original;
|
|
@@ -3524,7 +3514,7 @@ FRONTEND_HTML = r"""
|
|
| 3524 |
};
|
| 3525 |
}
|
| 3526 |
|
| 3527 |
-
function sendReachyPayload(payload, options = {}) {
|
| 3528 |
const settings = currentReachySettings();
|
| 3529 |
if (!options.force && !settings.enabled) return false;
|
| 3530 |
const baseUrl = normalizedReachyBridgeBase(settings);
|
|
@@ -3534,49 +3524,49 @@ FRONTEND_HTML = r"""
|
|
| 3534 |
return false;
|
| 3535 |
}
|
| 3536 |
const audioUrl = reachyAudioUrl(payload.comment, payload.chinese_text);
|
| 3537 |
-
const
|
| 3538 |
text: payload.text,
|
| 3539 |
emotion: payload.emotion,
|
| 3540 |
lang: payload.lang || "en",
|
| 3541 |
robotVoice: settings.robotVoice,
|
| 3542 |
-
audioUrl
|
| 3543 |
-
|
| 3544 |
-
|
|
|
|
| 3545 |
if (openReachyLast) {
|
| 3546 |
openReachyLast.hidden = false;
|
| 3547 |
openReachyLast.disabled = false;
|
| 3548 |
}
|
| 3549 |
|
| 3550 |
-
|
| 3551 |
-
|
| 3552 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3553 |
updateSettingsHeader(settings);
|
| 3554 |
return true;
|
| 3555 |
-
}
|
| 3556 |
-
|
| 3557 |
-
let opened = null;
|
| 3558 |
-
try {
|
| 3559 |
-
opened = window.open(bridgeUrl, "tonebridgeReachyBridge", "noopener,noreferrer");
|
| 3560 |
} catch (error) {
|
| 3561 |
-
|
| 3562 |
-
|
| 3563 |
-
if (!opened) {
|
| 3564 |
-
setStatusLine(reachyStatus, "Reachy bridge ready. Click Open Reachy.", "error");
|
| 3565 |
updateSettingsHeader(settings);
|
| 3566 |
return false;
|
| 3567 |
}
|
| 3568 |
-
|
| 3569 |
-
const label = payload.status === "correct" ? "Reachy bridge opened with encouragement." : "Reachy bridge opened with correction.";
|
| 3570 |
-
setStatusLine(reachyStatus, label, "ok");
|
| 3571 |
-
updateSettingsHeader(settings);
|
| 3572 |
-
return true;
|
| 3573 |
}
|
| 3574 |
|
| 3575 |
function testReachyConnection() {
|
| 3576 |
const settings = currentReachySettings();
|
| 3577 |
saveReachySettingsValue(settings);
|
| 3578 |
updateSettingsHeader(settings);
|
| 3579 |
-
sendReachyPayload({
|
| 3580 |
source: "ToneBridge",
|
| 3581 |
event: "test",
|
| 3582 |
status: "test",
|
|
@@ -3610,6 +3600,7 @@ FRONTEND_HTML = r"""
|
|
| 3610 |
function initializeReachySettings() {
|
| 3611 |
const settings = loadReachySettings();
|
| 3612 |
applyReachySettings(settings);
|
|
|
|
| 3613 |
setStatusLine(
|
| 3614 |
reachyStatus,
|
| 3615 |
settings.bridgeUrl ? "Reachy bridge configured." : "Reachy bridge not configured.",
|
|
@@ -4124,7 +4115,7 @@ FRONTEND_HTML = r"""
|
|
| 4124 |
currentOriginalSentence = payload.original_sentence || sentence;
|
| 4125 |
currentRequestId = payload.request_id || "";
|
| 4126 |
if (currentRequestId) showFeedbackPanel();
|
| 4127 |
-
sendReachyPayload(buildReachyCorrectionPayload(payload, data));
|
| 4128 |
if (copyCorrected) copyCorrected.disabled = !corrected;
|
| 4129 |
if (corrected) {
|
| 4130 |
readingPanel.style.display = "block";
|
|
@@ -4189,6 +4180,7 @@ FRONTEND_HTML = r"""
|
|
| 4189 |
const settings = currentReachySettings();
|
| 4190 |
saveReachySettingsValue(settings);
|
| 4191 |
updateSettingsHeader(settings);
|
|
|
|
| 4192 |
setStatusLine(reachyStatus, settings.bridgeUrl ? "Reachy bridge settings saved." : "Reachy bridge URL missing.", settings.bridgeUrl ? "ok" : "error");
|
| 4193 |
});
|
| 4194 |
testReachy?.addEventListener("click", () => testReachyConnection());
|
|
|
|
| 3008 |
</div>
|
| 3009 |
<div class="settings-actions">
|
| 3010 |
<button id="saveReachySettings" type="button">Save settings</button>
|
| 3011 |
+
<button id="openReachyLast" type="button">Open Reachy bridge</button>
|
| 3012 |
+
<button id="testReachy" type="button">Send test command</button>
|
| 3013 |
<span class="status-line" id="reachyStatus">Reachy bridge not configured.</span>
|
| 3014 |
<span class="status-line" id="metricsSyncStatus"></span>
|
| 3015 |
</div>
|
|
|
|
| 3473 |
return normalizeForCorrectionCompare(original) === normalizeForCorrectionCompare(corrected);
|
| 3474 |
}
|
| 3475 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3476 |
function reachyAudioUrl(comment, chinese) {
|
| 3477 |
const url = new URL("/reachy_audio.mp3", window.location.origin);
|
| 3478 |
url.searchParams.set("comment", comment || "Here is the correction.");
|
|
|
|
| 3481 |
return url.toString();
|
| 3482 |
}
|
| 3483 |
|
| 3484 |
+
function reachyCommandUrl(baseUrl) {
|
| 3485 |
+
const url = new URL("/api/commands", baseUrl);
|
| 3486 |
+
return url.toString();
|
| 3487 |
+
}
|
| 3488 |
+
|
| 3489 |
function buildReachyCorrectionPayload(payload, renderedText) {
|
| 3490 |
const original = payload.original_sentence || currentOriginalSentence || field("#sentence").value.trim();
|
| 3491 |
const corrected = payload.corrected_sentence || currentCorrectedSentence || extractCorrectedSentence(renderedText) || original;
|
|
|
|
| 3514 |
};
|
| 3515 |
}
|
| 3516 |
|
| 3517 |
+
async function sendReachyPayload(payload, options = {}) {
|
| 3518 |
const settings = currentReachySettings();
|
| 3519 |
if (!options.force && !settings.enabled) return false;
|
| 3520 |
const baseUrl = normalizedReachyBridgeBase(settings);
|
|
|
|
| 3524 |
return false;
|
| 3525 |
}
|
| 3526 |
const audioUrl = reachyAudioUrl(payload.comment, payload.chinese_text);
|
| 3527 |
+
const command = {
|
| 3528 |
text: payload.text,
|
| 3529 |
emotion: payload.emotion,
|
| 3530 |
lang: payload.lang || "en",
|
| 3531 |
robotVoice: settings.robotVoice,
|
| 3532 |
+
audioUrl,
|
| 3533 |
+
autoRun: true
|
| 3534 |
+
};
|
| 3535 |
+
lastReachyBridgeUrl = baseUrl;
|
| 3536 |
if (openReachyLast) {
|
| 3537 |
openReachyLast.hidden = false;
|
| 3538 |
openReachyLast.disabled = false;
|
| 3539 |
}
|
| 3540 |
|
| 3541 |
+
setStatusLine(reachyStatus, "Sending command to Reachy bridge...", "");
|
| 3542 |
+
try {
|
| 3543 |
+
const response = await fetch(reachyCommandUrl(baseUrl), {
|
| 3544 |
+
method: "POST",
|
| 3545 |
+
headers: {
|
| 3546 |
+
"Content-Type": "application/json"
|
| 3547 |
+
},
|
| 3548 |
+
body: JSON.stringify(command)
|
| 3549 |
+
});
|
| 3550 |
+
const result = await response.json().catch(() => ({}));
|
| 3551 |
+
if (!response.ok || result?.ok === false) {
|
| 3552 |
+
throw new Error(result?.error || `HTTP ${response.status}`);
|
| 3553 |
+
}
|
| 3554 |
+
setStatusLine(reachyStatus, "Reachy command queued. Keep the bridge open.", "ok");
|
| 3555 |
updateSettingsHeader(settings);
|
| 3556 |
return true;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3557 |
} catch (error) {
|
| 3558 |
+
console.warn("Reachy command failed.", error);
|
| 3559 |
+
setStatusLine(reachyStatus, `Reachy command failed: ${error?.message || error}`, "error");
|
|
|
|
|
|
|
| 3560 |
updateSettingsHeader(settings);
|
| 3561 |
return false;
|
| 3562 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3563 |
}
|
| 3564 |
|
| 3565 |
function testReachyConnection() {
|
| 3566 |
const settings = currentReachySettings();
|
| 3567 |
saveReachySettingsValue(settings);
|
| 3568 |
updateSettingsHeader(settings);
|
| 3569 |
+
void sendReachyPayload({
|
| 3570 |
source: "ToneBridge",
|
| 3571 |
event: "test",
|
| 3572 |
status: "test",
|
|
|
|
| 3600 |
function initializeReachySettings() {
|
| 3601 |
const settings = loadReachySettings();
|
| 3602 |
applyReachySettings(settings);
|
| 3603 |
+
lastReachyBridgeUrl = normalizedReachyBridgeBase(settings);
|
| 3604 |
setStatusLine(
|
| 3605 |
reachyStatus,
|
| 3606 |
settings.bridgeUrl ? "Reachy bridge configured." : "Reachy bridge not configured.",
|
|
|
|
| 4115 |
currentOriginalSentence = payload.original_sentence || sentence;
|
| 4116 |
currentRequestId = payload.request_id || "";
|
| 4117 |
if (currentRequestId) showFeedbackPanel();
|
| 4118 |
+
void sendReachyPayload(buildReachyCorrectionPayload(payload, data));
|
| 4119 |
if (copyCorrected) copyCorrected.disabled = !corrected;
|
| 4120 |
if (corrected) {
|
| 4121 |
readingPanel.style.display = "block";
|
|
|
|
| 4180 |
const settings = currentReachySettings();
|
| 4181 |
saveReachySettingsValue(settings);
|
| 4182 |
updateSettingsHeader(settings);
|
| 4183 |
+
lastReachyBridgeUrl = normalizedReachyBridgeBase(settings);
|
| 4184 |
setStatusLine(reachyStatus, settings.bridgeUrl ? "Reachy bridge settings saved." : "Reachy bridge URL missing.", settings.bridgeUrl ? "ok" : "error");
|
| 4185 |
});
|
| 4186 |
testReachy?.addEventListener("click", () => testReachyConnection());
|