| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
feat: add Discussion TTS with per-agent voice assignment (#211) * feat(tts): add resolveVoice() and getServerVoiceList() utilities Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tts): add AudioIndicator equalizer bars component Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tts): add onSegmentSealed callback to StreamBuffer Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tts): add voiceOverrides field to AgentConfig and AgentTemplate Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tts): add useDiscussionTTS hook with audio queue and cleanup Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): add audio state indicator to Roundtable bubble Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(tts): wire onSegmentSealed callback through chat sessions Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): add per-agent voice dropdown to AgentBar Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): integrate useDiscussionTTS in Stage and pass state to Roundtable Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(tts): refine voice dropdown to pill-style selector Replace native select styling with a compact rounded-full pill that blends into the agent row. Remove border, use muted bg, smaller text, and a custom chevron icon. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(tts): use shadcn Select for voice dropdown, link with TTS toggle - Replace native <select> with shadcn Select component for consistent UI - Hide voice dropdown when TTS is muted (ttsMuted) - Compact pill-style trigger with rounded-full, no border, muted bg Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(tts): add voice label prefix and always show dropdown Show "音色: Alloy" instead of plain "Alloy" in the voice pill. Always show dropdown regardless of mute state (voice config is independent of playback). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(tts): add volume icon hint in collapsed AgentBar Show a small Volume2 icon in the collapsed pill when voice config is available, hinting that voice settings are inside. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): fix voice dropdown layout and click handling - Move voice pill below agent name (second line) to prevent horizontal overflow in English - Wrap Select in div with onPointerDown stopPropagation to fix Radix click-through to parent row - Add line-clamp-1 to descriptions for consistent row height - Use items-start instead of items-center for better multi-line alignment Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(tts): redesign AgentBar voice layout for compactness - Single-line layout: checkbox · avatar · name · role · voice pill - Remove descriptions from agent rows (saves vertical space) - Extract AgentVoicePill component to isolate Select event handling - Smaller avatars (size-7), tighter row padding (py-1.5) - Voice pill uses Volume2 icon + voice name (no prefix text) - Works in both Chinese and English without overflow Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): cross-provider voice selection per agent - Change voiceConfig from per-provider lookup to explicit { providerId, voiceId } per agent - Each agent can use a different TTS provider's voice - Voice picker dropdown groups voices by provider - useDiscussionTTS routes TTS requests per agent's provider - resolveAgentVoice falls back to global provider if no config Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): align role badge and voice pill across agent rows Give role badge fixed width (w-14 text-right) so role text and voice pills align vertically across all rows regardless of agent name length. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): fix role badge and voice pill alignment Wrap role badge + voice pill in a fixed-width container (w-[9.5rem] justify-end) so both align vertically across all agent rows regardless of name or role text length. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * style(tts): align role badge and voice pill across agent rows Add min-w-[52px] text-right to role badge so it starts at a consistent position regardless of agent name length. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): use fixed w-[60px] for role badge alignment * fix(tts): use fixed w-[88px] for voice pill alignment * fix(tts): prevent click-outside from closing AgentBar when Select portal is open * fix(tts): comprehensive voice picker rewrite - Replace Radix Select with Popover + button list (fixes click issue) - Fix getAvailableProvidersWithVoices to always include global provider - Widen panel from w-80 to w-96 (prevents name truncation) - Voice pill uses primary color instead of gray (more visible) - Extract renderAgentRow helper to reduce duplication - Popover shows voices grouped by provider with active state - Add findVoiceDisplayName utility Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): align voice provider availability with toolbar logic * fix(tts): fallback to first available provider when global provider has no voices * refactor(tts): remove global provider fallback from voice resolution Voice resolution now only depends on available providers (those with API keys or server-configured). No more globalProviderId parameter. Fallback is first available provider, then browser-native-tts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): add browser native TTS voices to agent voice picker Load speechSynthesis.getVoices() in AgentBar and include as a "Browser Native" provider group in the voice popover. No API key needed - always available if browser supports it. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): simplify toolbar TTS to on/off toggle, add disabled state Toolbar: - Replace volume slider with simple TTS on/off toggle button - Remove ttsMuted/ttsVolume/onVolumeChange props from CanvasToolbar - Toggle now controls ttsEnabled (not ttsMuted) AgentBar: - Collapsed: show VolumeX icon when TTS disabled - Voice pills show disabled state (gray, cursor-not-allowed, no popover) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(tts): simplify Settings TTS tab to toggle + provider config Remove voice selection, speed slider, preview/test, Azure locale filter from Settings TTS tab. Voice is now per-agent in AgentBar. Keep: on/off toggle, provider selector, API key + base URL config. Add hint text pointing to AgentBar for voice configuration. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(tts): simplify media popover TTS tab to toggle only * fix(tts): add voice config hint to media popover TTS tab * feat(tts): add per-voice preview button in voice picker Each voice row in the popover has a small speaker icon button. Click to preview the voice with "欢迎来到AI课堂" / "Welcome to AI Classroom" (follows i18n). Browser native uses Web Speech API, server TTS calls /api/generate/tts. Click again or close popover to stop. Shows spinner while generating. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): preview text follows course language instead of UI language * refactor(tts): redesign AgentBar expanded panel layout - Teacher always at top with voice pill (works in both modes) - Mode tabs moved below teacher - Auto mode: single compact row with shuffle icon + description - Max turns: compact inline row with smaller input - Preset mode: only student agents listed (teacher already above) - Remove large shuffle animation from auto mode Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(tts): merge max turns into teacher row * refactor(tts): separate teacher row and max turns, use stepper UI - Teacher row: avatar + name + voice pill only - Max turns: bottom row with MessageSquare icon + compact stepper (minus/number/plus in a rounded pill) - Remove Input component dependency Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): increase voice pill contrast in dark mode * fix(tts): make max turns input editable, tighten panel padding * fix(tts): restore shuffle animation in auto mode (compact version) * fix(tts): adjust auto mode text spacing and add voice auto-assign hint * fix(tts): auto-close voice popover after selecting a voice * fix(tts): increase auto mode vertical padding for better balance * fix(tts): push auto mode text toward bottom with flex spacer * fix(tts): reduce auto mode bottom padding * feat(tts): wait for TTS audio to finish before next agent turn Add waitForDrain() to useDiscussionTTS that returns a promise resolving when the audio queue is empty. The agent loop in useChatSessions now awaits this after buffer drain, so the next agent's turn doesn't start until the current agent's TTS audio finishes playing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): keep bubble visible while TTS audio is still playing When buffer drains (text=null) but audio indicator is still active, don't clear liveSpeech. Clear it only when audio state goes idle. This keeps the speech bubble visible until TTS finishes. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): hold discussion bubble until TTS audio finishes When StreamBuffer fires the done signal (onLiveSpeech null), Stage now checks if TTS is still playing. If so, it defers clearing the bubble state. The bubble stays visible until onAllAudioEnd fires from the TTS hook (queue empty + nothing playing), then clears. This prevents the jarring UX where the bubble disappears while the agent's voice is still audible. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): fix bubble hold - guard onStopSession instead of onLiveSpeech Root cause: bubble disappears because doSessionCleanup fires via onStopSession when the agent loop ends naturally, NOT because of onLiveSpeech(null, null). Fix: when onStopSession fires and TTS is still playing, defer doSessionCleanup to onAllAudioEnd callback. Manual stop (user presses button) still cleans up immediately via handleStopDiscussion. Use doSessionCleanupRef to avoid circular dependency between discussionTTS hook and doSessionCleanup useCallback. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): guard BOTH onLiveSpeech and onStopSession for bubble hold Two paths clear the bubble: 1. onLiveSpeech(null, null) from StreamBuffer done → clears liveSpeech 2. onStopSession → doSessionCleanup → clears all state Both fire when agent loop ends. Path 1 fires first (tick loop), path 2 fires after (waitUntilDrained resolves). Both must be guarded when TTS is still playing. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): hold bubble during TTS playback and respect playback speed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat(tts): LLM picks voice matching agent persona during generation - Client sends available voices (providerId + voiceId + name) to /api/generate/agent-profiles - LLM prompt asks to pick a voice matching each agent's personality - Parse "providerId::voiceId" from response, save as voiceConfig - Fallback to index-based assignment if LLM doesn't pick - Browser native voices hidden when server providers are available - saveGeneratedAgents accepts and persists voiceConfig Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): restore volume slider in classroom toolbar Revert the toolbar simplification from 36e3997 that replaced the volume slider with a TTS on/off toggle. The volume control with hover slider is a core classroom UX. TTS on/off is controlled via Settings and Media popover instead. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): teacher uses global lecture voice in discussion when no voiceConfig override * fix(tts): teacher always uses global lecture voice, no overrides * fix(tts): sync playback speed to currently playing audio in real-time * fix(tts): address code review issues - Issue 2: enabled flag now checks ttsEnabled && !ttsMuted in stage.tsx - Issue 4: remove unused browserAvailableVoices from useDiscussionTTS - Issue 5: remove dead code in audio-settings.tsx (Slider, Loader2, handleTTSVoiceChange, handleTTSSpeedChange, handleTestTTS, testingTTS, ttsTestStatus, ttsTestMessage, testText, ttsSpeed, setTTSSpeed, and unused browser-tts-preview imports) - Issue 6: shouldHold now checks queue length in addition to isPlayingRef - Issue 8: hide AgentVoicePill for teacher row in agent-bar.tsx (teacher voice is controlled in Settings) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(tts): address PR review — abort preview fetch, defer error recovery 1. Add AbortController to voice preview server TTS fetch, abort on stopPreview to prevent stale responses on rapid switching 2. Use queueMicrotask for processQueue calls in error/ended handlers to prevent synchronous recursion if multiple items fail consecutively 3. Add ordering invariant comment on sealLastText's onSegmentSealed Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(tts): restore teacher voice pill, respect voiceConfig override * fix(tts): sync volume and mute to discussion TTS audio in real-time * fix(tts): allow browser-native TTS alongside server providers * fix(tts): remove top padding from voice popover content * fix(tts): make selectedAgents reactive to voiceConfig changes * fix(tts): use agents record instead of listAgents() to avoid infinite loop * fix(tts): single source of truth for teacher voice Teacher voice pill now reads/writes global ttsProviderId + ttsVoice (same settings used by lecture TTS). This ensures lecture and discussion always use the same teacher voice. Student agents still use per-agent voiceConfig. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * feat: add avatar descriptions for smarter LLM avatar selection Each avatar now has a one-line description (appearance, vibe) sent to the agent-profiles generation API. LLM picks avatars matching agent personality instead of guessing from file paths. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> Co-authored-by: 杨慎 <117187635+cosarah@users.noreply.github.com> | 5 个月前 | |
feat: refine presentation mode speech bubbles, input flow, and accessibility (#195) * feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 .git/COMMIT_EDITMSG [unix] (14:47 22/03/2026) 1,1 Top feat: add presentation mode with fullscreen, idle-hide, and keyboard navigation - Fullscreen via toolbar button or F11; exit via ESC/F11/button - Header auto-hides, sidebars collapse, slide fills viewport - Idle auto-hide (3s): toolbar/avatars fade out, speech bubble stays visible - Smart suspension: idle-hide pauses during typing/recording/voice input - Keyboard navigation: Arrow keys (prev/next), Space (play/pause), ESC (exit) - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 .git/COMMIT_EDITMSG [unix] (14:47 22/03/2026) 1,1 Top - F11 intercepted to use Fullscreen API (ESC-friendly) instead of browser native - Whiteboard hints reposition from bottom to top corners in fullscreen - i18n: fullscreen/exitFullscreen keys (zh-CN + en-US) Closes #102 * feat: refine presentation mode speech bubbles, input flow, and accessibility - User messages now display as right-side speech bubbles for send confirmation - 'Your turn' cue is a clickable glass button respecting ASR preference - Cue properly excludes bubbleRole/thinkingState to avoid UI overlap - Right-side dock + bubble uses flexbox for dynamic stacking - Voice-to-text switch now stops recording to prevent mic leaks - Backdrop no longer blocks toolbar (bottom-14 cutoff) - User message clears immediately when agent starts responding - Dock buttons and avatar have proper aria-labels and button semantics - Voice panel mic trigger converted from div to button with aria-label - Added 5 i18n keys (zh-CN + en-US) for new accessible labels - matchesSide typed as boolean, removed unused userAvatar from left overlay - Avatar alt text localized via i18n Refs #102 * fix: address code review audit cancel ghost sends, consolidate getAgentConfig, fix a11y * fix: guard concurrent voice recording and suppress cancel error toast * style: vertically center placeholder text in presentation input bar * style: full light-mode adaptation for presentation UI, toolbar dividers, bubble opacity 60% * chore: address #129 follow-up remove orphan i18n keys, clarify waitUntilDrained pause behavior * fix: resolve spacebar conflict and address review feedback - Stage: skip Space during active QA/discussion (let Roundtable own buffer-level pause); deterministic, no listener-order dependency - Stage: wrap handlePlayPause in useCallback([playbackCompleted, currentScene]) to avoid keyboard listener re-registration - Stage: clear presentationIdleTimerRef on unmount - PresentationBubbleCard: add aria-live='polite' for screen readers - Extract shared avatar constants to roundtable/constants.ts * style: format with prettier * fix: render ProactiveCard inside fullscreen container via portalContainer prop * feat: show requesting agent avatar in dock on discussion request --------- Co-authored-by: YizukiAme <yizukiame@github.com> | 5 个月前 | |
feat(chat): add single PPT element references to Pi (#1224) * feat(chat): add PPT element references to Pi * fix(chat): include chart values in reference routing * fix(chat): harden slide element reference evidence * fix(playback): clear element reference on scene navigation * fix(pi): preserve element grounding across child retries --------- Co-authored-by: wyuc <wang-yc24@mails.tsinghua.edu.cn> | 18 天前 | |
fix(roundtable): use inline style for breathing bar background color (#307) Tailwind 4 purges dynamically constructed class names passed through cn(). The breathing bars in presentation speech bubbles were invisible because `bg-blue-500` / `bg-purple-500` were tree-shaken from the CSS. Switch to inline `backgroundColor` style which is not subject to purging. | 5 个月前 |
| 文件 | 最后提交记录 | 最后更新时间 |
|---|---|---|
| 5 个月前 | ||
| 5 个月前 | ||
| 18 天前 | ||
| 5 个月前 |