step 3/6: chat UIホットパス最適化#365
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughRenamed ChatConfig identifier from Changes
Sequence Diagram(s)sequenceDiagram
autonumber
rect rgba(220,230,241,0.5)
participant Robot
end
rect rgba(200,240,220,0.5)
participant Startup
end
rect rgba(255,230,200,0.5)
participant ChatService
end
rect rgba(240,220,255,0.5)
participant ChatAudioIO
end
Robot->>Startup: onRobotCreated(robot)
Startup->>Startup: rawChatConfig = config.chat || {}
Startup->>Startup: chatConfig = { ...rawChatConfig, instructions: ... }
Startup->>Startup: validate typeof chatConfig.type === 'string' && chatConfig.type !== ''
alt valid type
Startup->>ChatService: construct(config.type, ...)
ChatService->>ChatAudioIO: ChatAudioIOCtor(specifier: config.type)
ChatAudioIO-->>ChatService: initialized events/state
ChatService-->>Startup: chat enabled
else invalid type
Startup-->>Robot: trace invalid config.chat.type (example)
Startup-->>Startup: exit early (chat disabled)
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~60 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: db759121f8
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
0efe339 to
e138186
Compare
4061491 to
b6843ad
Compare
|
別issueで修正する: #373 |
…k-dev-v1 # Conflicts: # firmware/stackchan/manifest_local.json # firmware/stackchan/renderers-piu/behaviors/face.ts
There was a problem hiding this comment.
Actionable comments posted: 4
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
firmware/chat.md (2)
118-130:⚠️ Potential issue | 🟡 MinorKeep
providerIDin the documented config surface.
ChatConfigstill exposesproviderID, but these sections now only describetype/modelID/voiceID/instructions. That leaves the public contract and the config test plan out of sync.Also applies to: 278-285, 390-395
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/chat.md` around lines 118 - 130, The documentation removed providerID from the `config.chat` surface but the code still exposes `ChatConfig.providerID`; update the docs and example to include `providerID` (e.g., in the example under `config.chat` and the descriptive text) and note that `ChatService` must forward `providerID` into the ChatAudioIO `specifier`; ensure references to `config.chat` (including the example block and the sections around lines ~278-285 and ~390-395) mention `providerID` alongside `type/modelID/voiceID/instructions` so the public contract and test plan match the `ChatConfig` shape.
121-130:⚠️ Potential issue | 🟡 MinorAdd a language to this fenced example.
This now trips markdownlint MD040.
📝 Suggested fix
-``` +```ts config: { chat: { type: "openAIRealtime", modelID: "gpt-realtime-mini", voiceID: "marin", instructions: "...", } } -``` +```🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/chat.md` around lines 121 - 130, The fenced code block example for the config object is missing a language tag, which triggers markdownlint MD040; update the opening triple-backtick fence that precedes the config example (the block showing config: { chat: { type: "openAIRealtime", modelID: "gpt-realtime-mini", voiceID: "marin", instructions: "..." } } ) to include a language identifier such as "ts" (i.e., change ``` to ```ts) so the block is properly typed and linter-compliant.
🧹 Nitpick comments (2)
firmware/stackchan/renderers-piu/effects/speech-balloon.ts (1)
91-117: The dynamic-height path is still quadratic.When
heightis not fixed,setText()re-runscountWrappedLines(), which concatenates and measures a growing prefix for every character. For streamed transcripts, that makes update cost grow with the whole accumulated string again. Consider caching wrap state or line widths instead of remeasuring every prefix on each update.Also applies to: 172-178
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts` around lines 91 - 117, countWrappedLines currently rebuilds and remeasures every growing prefix on each call (used by resolveHeight), producing quadratic cost for streaming/appended text; change to an incremental/cached wrap algorithm: maintain persistent wrap state (e.g., array of lineWidths or current lines) keyed to the existing text and update it when setText/appends occur rather than recomputing from scratch, and have countWrappedLines (or its replacement) use that cached state to compute the new line count in O(chars appeneded) time; locate and update the logic in countWrappedLines and resolveHeight and any other place calling the function (the streaming update path referenced around the second occurrence) to use the new cached structure and update it on each append instead of remeasuring all prefixes.firmware/stackchan/manifest_local.json (1)
4-8: Avoid checking a workstation-specific Voicevox endpoint into the shared local manifest.
192.168.7.136will be dead for almost everyone else pulling the branch. Prefer leavingtts.host/tts.porttomcconfigoverrides or an untracked local overlay.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/stackchan/manifest_local.json` around lines 4 - 8, The manifest_local.json currently hardcodes a workstation-specific Voicevox endpoint (tts.host = "192.168.7.136" and tts.port = 50021); remove these hardcoded values from the tracked manifest and make tts.host and tts.port configurable via the existing mcconfig override or an untracked local overlay instead (leave them null/empty or delete the keys in manifest_local.json), ensuring consumers can set values in their local mcconfig or overlay; reference the tts.host and tts.port fields and update any README or comments to instruct developers to set these in mcconfig/local overlay rather than committing workstation-specific endpoints.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@firmware/mods/chat_audioio/mod.js`:
- Around line 23-26: The guard should ensure config.chat.type is a string, not
just truthy: change the check around chatConfig (used where you call trace and
later derive the specifier) to verify typeof chatConfig?.type === 'string' and
treat any non-string (including objects, numbers, null) the same as missing by
logging via trace that config.chat.type must be a string and disabling chat;
update the trace message to mention the type requirement so downstream code that
constructs the specifier (from config.chat.type) never receives a non-string
value.
In `@firmware/stackchan/default-mods/on-robot-created.ts`:
- Around line 37-50: The code only emits 'onFaceMode' inside the toggle
callback, so listeners never get the initial 'simple' mode; after registering
the drawer button (the robot.application.addDrawerButton call) emit the same
event for the initial state by invoking the same distribute call with faceMode
(e.g. call robot.application.distribute?.('onFaceMode', faceMode) or, if you
must target the renderer like in the callback, grab the current renderer
application and call app?.distribute?.('onFaceMode', faceMode)); also ensure
robot.application.setDrawerButtonState('toggleFace', faceMode !== 'simple') is
set for the initial state so UI and listeners are synchronized.
In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts`:
- Around line 124-145: ensureParts currently recreates background/bodyText but
calls this.updatePalette(defaultFaceContext) which can leave new nodes
unskinned; store the last active face context in a field (e.g.,
this._activeFaceContext) when onFaceContext runs, and replace uses of
defaultFaceContext in ensureParts (and the other rebuild/repaint sites that call
updatePalette) with this._activeFaceContext so newly created background and
bodyText are re-skinned immediately; ensure onFaceContext sets
this._activeFaceContext and calls this.updatePalette(this._activeFaceContext),
and keep calling this.updateText(self, currentText) after reapplying the active
palette.
In `@firmware/stackchan/renderers-piu/face-view.ts`:
- Around line 27-30: The face behavior cache isn't updated when reapplying
state; add a behavior-level rehydrate hook (e.g., FaceBehavior.rehydrate or
FaceContainerBehavior.rehydrate) that accepts the container and new
FaceContext/palette and updates the cached context/palette inside FaceBehavior,
then call this hook from onFaceSkin() and applyFaceState() immediately after
pushing state into the subtree so the FaceBehavior cache is updated in lockstep
with descendants; ensure the FaceBehavior implementation updates its internal
cached context/palette in the new rehydrate method so onDisplaying()/resume()
won't use stale values.
---
Outside diff comments:
In `@firmware/chat.md`:
- Around line 118-130: The documentation removed providerID from the
`config.chat` surface but the code still exposes `ChatConfig.providerID`; update
the docs and example to include `providerID` (e.g., in the example under
`config.chat` and the descriptive text) and note that `ChatService` must forward
`providerID` into the ChatAudioIO `specifier`; ensure references to
`config.chat` (including the example block and the sections around lines
~278-285 and ~390-395) mention `providerID` alongside
`type/modelID/voiceID/instructions` so the public contract and test plan match
the `ChatConfig` shape.
- Around line 121-130: The fenced code block example for the config object is
missing a language tag, which triggers markdownlint MD040; update the opening
triple-backtick fence that precedes the config example (the block showing
config: { chat: { type: "openAIRealtime", modelID: "gpt-realtime-mini", voiceID:
"marin", instructions: "..." } } ) to include a language identifier such as "ts"
(i.e., change ``` to ```ts) so the block is properly typed and linter-compliant.
---
Nitpick comments:
In `@firmware/stackchan/manifest_local.json`:
- Around line 4-8: The manifest_local.json currently hardcodes a
workstation-specific Voicevox endpoint (tts.host = "192.168.7.136" and tts.port
= 50021); remove these hardcoded values from the tracked manifest and make
tts.host and tts.port configurable via the existing mcconfig override or an
untracked local overlay instead (leave them null/empty or delete the keys in
manifest_local.json), ensuring consumers can set values in their local mcconfig
or overlay; reference the tts.host and tts.port fields and update any README or
comments to instruct developers to set these in mcconfig/local overlay rather
than committing workstation-specific endpoints.
In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts`:
- Around line 91-117: countWrappedLines currently rebuilds and remeasures every
growing prefix on each call (used by resolveHeight), producing quadratic cost
for streaming/appended text; change to an incremental/cached wrap algorithm:
maintain persistent wrap state (e.g., array of lineWidths or current lines)
keyed to the existing text and update it when setText/appends occur rather than
recomputing from scratch, and have countWrappedLines (or its replacement) use
that cached state to compute the new line count in O(chars appeneded) time;
locate and update the logic in countWrappedLines and resolveHeight and any other
place calling the function (the streaming update path referenced around the
second occurrence) to use the new cached structure and update it on each append
instead of remeasuring all prefixes.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: c4b5bb24-187c-4a1e-9c84-e65fd8533860
📒 Files selected for processing (18)
firmware/chat.mdfirmware/mods/chat_audioio/mod.jsfirmware/stackchan/default-mods/on-robot-created.tsfirmware/stackchan/main.tsfirmware/stackchan/manifest.jsonfirmware/stackchan/manifest_local.jsonfirmware/stackchan/renderers-piu/behaviors/face.tsfirmware/stackchan/renderers-piu/common-view.tsfirmware/stackchan/renderers-piu/effects/speech-balloon.tsfirmware/stackchan/renderers-piu/face-view.tsfirmware/stackchan/renderers-piu/renderer-dog.tsfirmware/stackchan/renderers-piu/renderer-simple.tsfirmware/stackchan/renderers-piu/renderer-small.tsfirmware/stackchan/services/chat.tsfirmware/tests/chats/chat-service/main.tsfirmware/tests/renderers/piu-simple/main.tsfirmware/tests/renderers/piu-simple/manifest.jsonfirmware/tsconfig.json
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (1)
firmware/tests/renderers/default-mod-face/main.ts (1)
6-12: Exercise the registered drawer callback as well.The test validates initial sync, but it would still pass if the
toggleFacecallback stopped cyclingsimple → dog → image → simple. Capturingkind,initialState, and invoking the callback would cover the actual drawer interaction added infirmware/stackchan/default-mods/on-robot-created.ts:46-55.Suggested test expansion
+type DrawerButton = { + key?: string + kind?: string + initialState?: boolean + callback?: (target: { + renderer?: { + setFace?: (face: unknown) => void + application?: { distribute?: (event: string, payload: unknown) => void } + } + }) => void +} + -const buttons: { key?: string }[] = [] +const buttons: DrawerButton[] = [] const drawerStates: [string, boolean][] = [] const events: [string, unknown][] = [] const robot = { application: { - addDrawerButton: (button: { key?: string }) => { + addDrawerButton: (button: DrawerButton) => { buttons.push(button) }, setDrawerButtonState: (key: string, active: boolean) => { drawerStates.push([key, active]) @@ onRobotCreated(robot as never) equal(buttons[0]?.key, 'toggleFace', 'toggleFace button should be registered') +equal(buttons[0]?.kind, 'toggle', 'toggleFace should be registered as a toggle button') +equal(buttons[0]?.initialState, false, 'toggleFace initialState should be inactive') equal(drawerStates[0]?.[0], 'toggleFace', 'toggleFace state should be initialized') equal(drawerStates[0]?.[1], false, 'toggleFace should start inactive') equal(events[0]?.[0], 'onFaceMode', 'initial face mode should be distributed') equal(events[0]?.[1], 'simple', 'initial face mode should be simple') + +const faces: unknown[] = [] +const callbackTarget = { + renderer: { + ...robot.renderer, + setFace: (face: unknown) => { + faces.push(face) + }, + }, +} + +buttons[0]?.callback?.(callbackTarget) +equal(drawerStates[1]?.[0], 'toggleFace', 'toggleFace state should update after first toggle') +equal(drawerStates[1]?.[1], true, 'toggleFace should become active after switching to dog') +equal(events[1]?.[1], 'dog', 'first toggle should switch to dog face mode') + +buttons[0]?.callback?.(callbackTarget) +equal(drawerStates[2]?.[1], true, 'toggleFace should remain active after switching to image') +equal(events[2]?.[1], 'image', 'second toggle should switch to image face mode') + +buttons[0]?.callback?.(callbackTarget) +equal(drawerStates[3]?.[1], false, 'toggleFace should become inactive after returning to simple') +equal(events[3]?.[1], 'simple', 'third toggle should return to simple face mode') +equal(faces.length, 3, 'face should be replaced on each toggle')Also applies to: 42-48
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/tests/renderers/default-mod-face/main.ts` around lines 6 - 12, The test currently registers drawer callbacks via robot.application.addDrawerButton but never invokes them; extend the test to capture the registered button (from the buttons array) and its callback (the addDrawerButton handler stored when robot.application.addDrawerButton is called), extract the callback's parameters like kind and initialState, then invoke that callback repeatedly (or with the appropriate event payload) to assert the drawer state cycles through "simple" → "dog" → "image" → "simple" as implemented in on-robot-created.ts; update assertions on drawerStates and events after each invocation to verify the actual drawer interaction logic.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts`:
- Around line 2-8: The imports for Piu constructors are currently declared with
`import type`, so runtime constructors like Container, Content, Style, Text,
Texture (and missing Skin) will be undefined; change the imports to import the
actual runtime values (not type-only) so Container, Content, Style, Text,
Texture are available at runtime and add an import for Skin as well following
the same pattern used in the other renderer files (e.g., how
drawer.ts/face-view.ts import Piu constructors), or alternatively keep type-only
imports and add separate value imports or renamed value aliases so references to
Container, Content, Style, Text, Texture, and Skin used in the file resolve to
actual constructors at runtime.
In `@firmware/tests/chats/chat-audioio-config/main.ts`:
- Around line 11-20: The test stub defines addDrawerButton on robot.application
but the code under test (onRobotCreated) uses robot.renderer.application; update
the StubRobot so addDrawerButton (and its spy) is placed under
renderer.application.application (i.e.,
robot.renderer.application.addDrawerButton) and move/attach the spy accordingly
in the tests that assert drawer-button behavior (including the similar cases at
lines 33-40) so the assertions target the actual side-effect location used by
onRobotCreated.
---
Nitpick comments:
In `@firmware/tests/renderers/default-mod-face/main.ts`:
- Around line 6-12: The test currently registers drawer callbacks via
robot.application.addDrawerButton but never invokes them; extend the test to
capture the registered button (from the buttons array) and its callback (the
addDrawerButton handler stored when robot.application.addDrawerButton is
called), extract the callback's parameters like kind and initialState, then
invoke that callback repeatedly (or with the appropriate event payload) to
assert the drawer state cycles through "simple" → "dog" → "image" → "simple" as
implemented in on-robot-created.ts; update assertions on drawerStates and events
after each invocation to verify the actual drawer interaction logic.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: 157e6e44-e080-4542-89bd-9fa5b383f228
📒 Files selected for processing (13)
firmware/mods/chat_audioio/mod.jsfirmware/stackchan/default-mods/on-robot-created.tsfirmware/stackchan/renderers-piu/behaviors/face.tsfirmware/stackchan/renderers-piu/effects/speech-balloon.tsfirmware/stackchan/renderers-piu/face-view.tsfirmware/tests/chats/README.mdfirmware/tests/chats/chat-audioio-config/main.tsfirmware/tests/chats/chat-audioio-config/manifest.jsonfirmware/tests/chats/chat-balloon/main.tsfirmware/tests/renderers/default-mod-face/main.tsfirmware/tests/renderers/default-mod-face/manifest.jsonfirmware/tests/renderers/face-view-state/main.tsfirmware/tests/renderers/face-view-state/manifest.json
✅ Files skipped from review due to trivial changes (5)
- firmware/tests/chats/README.md
- firmware/mods/chat_audioio/mod.js
- firmware/tests/renderers/default-mod-face/manifest.json
- firmware/tests/renderers/face-view-state/manifest.json
- firmware/tests/chats/chat-audioio-config/manifest.json
🚧 Files skipped from review as they are similar to previous changes (2)
- firmware/stackchan/default-mods/on-robot-created.ts
- firmware/stackchan/renderers-piu/behaviors/face.ts
There was a problem hiding this comment.
🧹 Nitpick comments (2)
firmware/stackchan/renderers-piu/effects/speech-balloon.ts (1)
185-198: Minor: redundantupdateTextcall onsetText/onDisplaying.
ensurePartsalready invokesthis.updateText(self, currentText)(Line 147) after a rebuild, andupdatePalette(currentFace)(Line 146). So:
setText(Lines 185–189) callsupdateTexta second time whenever a rebuild occurred.onDisplaying(Lines 195–198) callsupdatePalette(currentFace)a second time afterensurePartsalready did.Harmless today (palette cache short-circuits,
updateTextjust reassigns the same string), but can be trimmed:♻️ Proposed tweak
setText(self: PiuContainer, text: string) { currentText = text ?? '' - this.ensureParts(self) - this.updateText(self, currentText) + // ensureParts will call updateText(currentText) if it rebuilds; + // otherwise we still need to push the new string through. + const rebuilt = !background || !bodyText || layoutWidth !== resolveWidth(self) + this.ensureParts(self) + if (!rebuilt) this.updateText(self, currentText) } @@ onDisplaying(content: PiuContainer) { this.ensureParts(content) - this.updatePalette(currentFace) }(Requires hoisting
resolveWidth/layoutWidth/background/bodyTextvisibility, which they already have in the closure.)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts` around lines 185 - 198, The setText and onDisplaying methods redundantly call updateText and updatePalette after ensureParts already performs those updates; remove the duplicate calls in setText (remove this.updateText(self, currentText)) and in onDisplaying (remove this.updatePalette(currentFace)) so ensureParts is the single place that updates text and palette during a rebuild, or alternatively wrap those calls with a cheap guard that skips if ensureParts already ran (use currentText/currentFace state checks); update references: setText, onDisplaying, ensureParts, updateText, updatePalette, currentText, currentFace.firmware/stackchan/renderers-piu/effects/emoticon.ts (1)
9-14: Optional: intersectingPiuContentwithPiuShapeforWithSkin.
WithSkinnow intersectsPiuContentwithOmit<PiuShape, 'fillOutline' | 'strokeOutline'>. Since all call sites construct shapes (not bare contents) viadefineShapeTemplate, typing this directly asOmit<PiuShape, ...> & { skin?: PiuSkin; fillOutline?: unknown; strokeOutline?: unknown }would be more accurate and drop the need to intersect withPiuContent. Not blocking — the current intersection typechecks.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@firmware/stackchan/renderers-piu/effects/emoticon.ts` around lines 9 - 14, The current WithSkin type unnecessarily intersects PiuContent with Omit<PiuShape, 'fillOutline' | 'strokeOutline'>; update WithSkin to be based directly on the shape type so it reflects actual call sites: replace the intersection with a single type defined as Omit<PiuShape, 'fillOutline' | 'strokeOutline'> & { skin?: PiuSkin; fillOutline?: unknown; strokeOutline?: unknown } (remove PiuContent from the union); ensure usages in defineShapeTemplate still type-check after this change.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Nitpick comments:
In `@firmware/stackchan/renderers-piu/effects/emoticon.ts`:
- Around line 9-14: The current WithSkin type unnecessarily intersects
PiuContent with Omit<PiuShape, 'fillOutline' | 'strokeOutline'>; update WithSkin
to be based directly on the shape type so it reflects actual call sites: replace
the intersection with a single type defined as Omit<PiuShape, 'fillOutline' |
'strokeOutline'> & { skin?: PiuSkin; fillOutline?: unknown; strokeOutline?:
unknown } (remove PiuContent from the union); ensure usages in
defineShapeTemplate still type-check after this change.
In `@firmware/stackchan/renderers-piu/effects/speech-balloon.ts`:
- Around line 185-198: The setText and onDisplaying methods redundantly call
updateText and updatePalette after ensureParts already performs those updates;
remove the duplicate calls in setText (remove this.updateText(self,
currentText)) and in onDisplaying (remove this.updatePalette(currentFace)) so
ensureParts is the single place that updates text and palette during a rebuild,
or alternatively wrap those calls with a cheap guard that skips if ensureParts
already ran (use currentText/currentFace state checks); update references:
setText, onDisplaying, ensureParts, updateText, updatePalette, currentText,
currentFace.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 69724d7a-bca9-4fd9-bc6a-21e448004de9
📒 Files selected for processing (11)
firmware/stackchan/renderers-piu/behaviors/face.tsfirmware/stackchan/renderers-piu/common-view.tsfirmware/stackchan/renderers-piu/effects/emoticon.tsfirmware/stackchan/renderers-piu/effects/multirow-balloon.tsfirmware/stackchan/renderers-piu/effects/speech-balloon.tsfirmware/stackchan/renderers-piu/face-view.tsfirmware/stackchan/renderers-piu/parts/dog/eyebrow.tsfirmware/stackchan/renderers-piu/parts/dog/mouth.tsfirmware/stackchan/renderers-piu/parts/dog/nose.tsfirmware/stackchan/renderers-piu/parts/eye.tsfirmware/stackchan/renderers-piu/template.ts
✅ Files skipped from review due to trivial changes (1)
- firmware/stackchan/renderers-piu/effects/multirow-balloon.ts
🚧 Files skipped from review as they are similar to previous changes (3)
- firmware/stackchan/renderers-piu/common-view.ts
- firmware/stackchan/renderers-piu/face-view.ts
- firmware/stackchan/renderers-piu/behaviors/face.ts
There was a problem hiding this comment.
Actionable comments posted: 1
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@firmware/tests/chats/chat-service/main.ts`:
- Around line 50-53: The test is silently falling back to numeric 3 when
ChatAudioIOAny.CONNECTED is missing; instead remove the nullish fallback and
fail fast: before calling instance.emitState, assert that
ChatAudioIOAny.CONNECTED is defined (throw or use expect) and then call
instance.emitState(ChatAudioIOAny.CONNECTED); reference
ChatAudioIOAny.CONNECTED, instance.emitState, and the ChatAudioIO instance to
locate and update the test so a missing mock constant causes the test to fail
rather than emit a hidden magic value.
🪄 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: defaults
Review profile: CHILL
Plan: Pro
Run ID: f3b6775e-3c68-4145-a1f3-ed20f607e9f7
📒 Files selected for processing (2)
firmware/tests/chats/chat-service/main.tsfirmware/tests/renderers/default-mod-face/main.ts
🚧 Files skipped from review as they are similar to previous changes (1)
- firmware/tests/renderers/default-mod-face/main.ts
Summary
Scope
dev/v1.0step-pr/03-chat-ui-hotpathNotes
Summary by CodeRabbit
New Features
Improvements
Documentation
Tests