feat(mascot): react to conversation cues#2423
Conversation
📝 WalkthroughWalkthroughThe mascot now selects a post-turn acknowledgement face (happy, confused, or concerned) per chat result using a new pickConversationAckFace classifier (reaction_emoji or full_response cues), and threads that face through chat_done non-TTS holds and TTS playback flows; tests and docs updated. ChangesMascot Acknowledgement Face Selection
Sequence Diagram(s)sequenceDiagram
participant ChatDoneEvent
participant useHumanMascot
participant startTtsPlayback
ChatDoneEvent->>useHumanMascot: chat_done(event)
useHumanMascot->>useHumanMascot: pickConversationAckFace(event)
alt TTS enabled
useHumanMascot->>startTtsPlayback: startTtsPlayback(ackFace)
startTtsPlayback->>useHumanMascot: finally -> hold ackFace
else TTS disabled
useHumanMascot->>useHumanMascot: holdThenIdle(ackFace)
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Suggested labels
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src/features/human/useHumanMascot.ts`:
- Around line 106-107: Guard against event.full_response being null/undefined
before calling .trim() in useHumanMascot: check event.full_response (or coalesce
it to an empty string) so you don't call .trim() on an absent value, then
proceed to trim and test text; update the logic around the text variable and the
early return so that event.full_response is validated before trimming to avoid
the runtime crash.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: 33ea4020-100b-4b56-b93a-f823dc6f7e10
📒 Files selected for processing (3)
app/src/features/human/useHumanMascot.test.tsapp/src/features/human/useHumanMascot.tsgitbooks/features/mascot/README.md
|
placeholder |
1 similar comment
|
placeholder |
110d56b to
ebca27d
Compare
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@app/src/features/human/useHumanMascot.ts`:
- Around line 263-266: The startTtsPlayback function currently only sets
degraded when synthesizeSpeech throws, so downstream playback/decoding errors
still call holdThenIdle(ackFace) showing normal faces; wrap the
playback/decoding steps in their own try/catch and set degraded = true on any
exception (or re-use the existing degraded flag) before calling holdThenIdle,
ensuring that holdThenIdle is invoked with the concerned face when degraded is
true; reference the startTtsPlayback function, the degraded flag, and the
holdThenIdle call to locate where to add the additional error handling.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro
Run ID: ab506eb2-7d3a-422e-b90d-16e0d5974f74
📒 Files selected for processing (3)
app/src/features/human/useHumanMascot.test.tsapp/src/features/human/useHumanMascot.tsgitbooks/features/mascot/README.md
✅ Files skipped from review due to trivial changes (1)
- gitbooks/features/mascot/README.md
ebca27d to
f10684a
Compare
| const CONCERNED_REACTION_EMOJIS = new Set(['⚠️', '⚠', '🚨', '❌', '😕', '😟']); | ||
|
|
||
| const CONCERNED_TEXT_RE = | ||
| /\b(sorry|apolog(?:y|ize|ise)|failed|failure|error|cannot|can't|unable|blocked|problem)\b/i; |
There was a problem hiding this comment.
[minor] HAPPY_TEXT_RE — common words like done, ready, and nice can false-positive on neutral or negative messages. For example "I'm done explaining — the system is broken" matches done → happy. The concerned > confused > happy priority order already mitigates the worst cases, but consider tightening these to phrase-level anchors (e.g. all set, it's done, that's fixed) in a follow-up if you see odd expressions in practice.
| type ConversationAckFace = Extract<MascotFace, 'happy' | 'confused' | 'concerned'>; | ||
| type ConversationAckEvent = { full_response?: string | null; reaction_emoji?: string | null }; | ||
|
|
||
| const HAPPY_REACTION_EMOJIS = new Set(['✅', '🎉', '🙌', '😊', '😄', '👍', '💪']); |
There was a problem hiding this comment.
[minor] HAPPY_REACTION_EMOJIS contains 👍 but won't match skin-tone variants like 👍🏽 (they're distinct Unicode sequences). Same for other emoji sets. Probably fine if the backend sends base codepoints, but worth a note if you later see mismatches.
Summary
chat_done.reaction_emojiand clear response text cues intohappy,confused, orconcernedbeats while preserving existing runtime states for thinking/speaking/listening.concernedrecovery path instead of showing a normal acknowledgement.Problem
#1144 asks for the mascot to react to message/conversation meaning instead of only transport phases. The hook already reacts to runtime events; this PR adds the first bounded message-aware layer without introducing animation noise.
Solution
pickConversationAckFaceto classify explicit reaction emoji first, then deterministic response text cues.concernedso recovery states still take priority.Submission Checklist
useHumanMascot.test.tscovers emoji, text-cue, neutral fallback, TTS success, synth failure, and playback failure transitions.Validation
pnpm install --offline --frozen-lockfilepnpm --dir app test -- src/features/human/useHumanMascot.test.ts- 1 file, 34 tests.pnpm --dir app compilepnpm --dir app exec prettier --check src/features/human/useHumanMascot.ts src/features/human/useHumanMascot.test.tsgit diff --checkRelated
AI Authored PR Metadata (required for Codex/Linear PRs)
Linear Issue
Commit & Branch
codex/1144-mascot-reactions5a4aca728432b2e5327dc84a3b090c7eb714bfdeValidation Run
Validation Blocked
Behavior Changes
happy,confused, orconcernedmascot acknowledgement based on conversation cues.Parity Contract
concerned; unknown reaction cues fall back to prior behavior.Duplicate / Superseded PR Handling
Summary by CodeRabbit
New Features
Tests
Documentation