surface: per-agent TTS voice + turn clock + reply-handler fix
Speech resolves voice per active agent (agents[].voice_id from the list), with the system voice as fallback — two agents on a host need not match. Souveraine.qml carries voice_id into the agents map and adds a turn clock (turnStartedAt/turnElapsedMs) + a 60s agent-inventory refresh. Ai.qml declares pendingFilePath and imports qs.modules.common.functions so StringUtils.ttsClean no longer aborts the stream-finished handler.
This commit is contained in:
parent
e9bf33e64a
commit
0ef239515f
4 changed files with 137 additions and 16 deletions
|
|
@ -20,6 +20,25 @@ Item {
|
|||
property var suggestionQuery: ""
|
||||
property var suggestionList: []
|
||||
|
||||
// Turn clock formatting. A local 9B can take minutes on a cold prompt, so
|
||||
// the readout has to stay legible from milliseconds to tens of minutes.
|
||||
function formatTurnDuration(ms) {
|
||||
if (ms < 1000)
|
||||
return `${ms}ms`;
|
||||
const seconds = ms / 1000;
|
||||
if (seconds < 60)
|
||||
return `${seconds.toFixed(1)}s`;
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const rest = Math.floor(seconds % 60);
|
||||
return `${minutes}m ${rest < 10 ? "0" : ""}${rest}s`;
|
||||
}
|
||||
|
||||
function formatClockTime(msEpoch) {
|
||||
if (!msEpoch)
|
||||
return "—";
|
||||
return new Date(msEpoch).toLocaleTimeString(Qt.locale(), "HH:mm:ss");
|
||||
}
|
||||
|
||||
onFocusChanged: focus => {
|
||||
if (focus) {
|
||||
root.inputField.forceActiveFocus();
|
||||
|
|
@ -369,7 +388,18 @@ Inline w/ backslash and round brackets \\(e^{i\\pi} + 1 = 0\\)
|
|||
visible: Ai.tokenCount.total > 0
|
||||
icon: "token"
|
||||
statusText: Ai.tokenCount.total
|
||||
description: Translation.tr("Total token count\nInput: %1\nOutput: %2").arg(Ai.tokenCount.input).arg(Ai.tokenCount.output)
|
||||
description: Translation.tr("Context estimate: %1 tokens\n(Local count of the conversation — not the provider's usage numbers)").arg(Ai.tokenCount.total)
|
||||
}
|
||||
StatusSeparator {
|
||||
visible: Souveraine.turnStartedAt > 0
|
||||
}
|
||||
StatusItem {
|
||||
visible: Souveraine.turnStartedAt > 0
|
||||
icon: Souveraine.turnActive ? "hourglass_top" : "timer"
|
||||
statusText: root.formatTurnDuration(Souveraine.turnElapsedMs)
|
||||
description: Souveraine.turnActive
|
||||
? Translation.tr("Waiting on the agent\nSent at %1").arg(root.formatClockTime(Souveraine.turnStartedAt))
|
||||
: Translation.tr("Last turn took %1\nSent at %2").arg(root.formatTurnDuration(Souveraine.turnElapsedMs)).arg(root.formatClockTime(Souveraine.turnStartedAt))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue