Add voice state tags, SuperTTS configs, and demo WS log groups.

Parse leading <state> tags from LLM replies and emit response.state over the product websocket while stripping tags from TTS/text streams. Add FastGPT+Xfyun voice configs (including state-enabled preset), SuperTTS support, and context sync for interrupted turns. Refresh the voice demo with a state indicator and collapsible audio delta websocket log groups.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Xin Wang
2026-05-28 11:32:20 +08:00
parent b14ef64665
commit 9e2374f492
18 changed files with 1596 additions and 195 deletions

View File

@@ -405,6 +405,79 @@ body {
padding: 8px 4px;
}
.ws-log__group {
border-radius: 6px;
}
.ws-log__group-header {
display: grid;
grid-template-columns: 58px 42px 14px minmax(0, 1fr);
gap: 6px;
align-items: start;
width: 100%;
margin: 0;
padding: 5px 4px;
border: 0;
border-radius: 6px;
background: transparent;
color: inherit;
font: inherit;
text-align: left;
cursor: pointer;
white-space: pre-wrap;
word-break: break-word;
}
.ws-log__group-header:hover {
background: rgba(255, 255, 255, 0.03);
}
.ws-log__group-header:focus-visible {
outline: 2px solid var(--accent);
outline-offset: 1px;
}
.ws-log__group-chevron {
color: var(--text-dim);
font-size: 9px;
line-height: 1.6;
user-select: none;
}
.ws-log__group-summary {
min-width: 0;
overflow-wrap: anywhere;
color: var(--text);
}
.ws-log__group-children {
margin: 0 0 4px 18px;
padding-left: 8px;
border-left: 1px solid var(--border);
}
.ws-log__entry--child {
grid-template-columns: 58px 42px minmax(0, 1fr);
opacity: 0.85;
padding-left: 0;
}
.ws-log__group-omit {
padding: 4px 4px 4px 0;
font-size: 10px;
font-style: italic;
color: var(--text-dim);
opacity: 0.75;
}
.ws-log__group--send .ws-log__direction {
color: var(--success);
}
.ws-log__group--recv .ws-log__direction {
color: var(--accent-strong);
}
/* Controls -------------------------------------------------------------- */
.controls {
@@ -598,10 +671,26 @@ body {
animation: pulse 1s ease-in-out infinite;
}
.indicator.is-active .indicator__dot--state {
background: var(--warning);
border-color: var(--warning);
box-shadow: 0 0 0 4px rgba(255, 184, 77, 0.18);
}
.indicator.is-active .indicator__label {
color: var(--text);
}
.indicator--state {
max-width: 180px;
}
.indicator--state .indicator__label {
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.btn {
appearance: none;
border: 1px solid var(--border);
@@ -720,10 +809,15 @@ body {
align-items: stretch;
}
.ws-log__entry {
.ws-log__entry,
.ws-log__group-header {
grid-template-columns: 54px 38px minmax(0, 1fr);
}
.ws-log__group-header {
grid-template-columns: 54px 38px 12px minmax(0, 1fr);
}
.status {
justify-content: flex-end;
}