Skip to content

feat: expose conversation backend contract - #441

Open
meganetaaan wants to merge 2 commits into
developfrom
feat/issue-440-conversation-if
Open

feat: expose conversation backend contract#441
meganetaaan wants to merge 2 commits into
developfrom
feat/issue-440-conversation-if

Conversation

@meganetaaan

@meganetaaan meganetaaan commented May 14, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • Adds a shared ConversationBackend contract for Stack-chan conversation backends.
  • Keeps the existing ChatService behavior while making it implement the shared backend I/F.
  • Adds unit coverage for the contract, ChatAudioIO tool schema conversion, and backend-agnostic callbacks.
  • Adds a small Node test helper so unit tests can resolve the ChatAudioIO Moddable module specifier through the existing stub.

Review focus

This PR is intentionally small so we can review the I/F before adding the legacy STT -> Dialogue -> TTS backend.

Please focus on:

  • Whether ConversationBackend has the right shape for both ChatAudioIO and legacy STT/LLM/TTS pipelines.
  • Whether optional methods such as sendFunctionResult, setMicrophoneEnabled, and setVolume are the right boundary.
  • Whether ChatCallbacks is enough for UI / face / transcript integration to stay backend-independent.

Follow-up

After this I/F is agreed, the next slice will add a legacy pipeline backend that wraps:

robot.record() -> STT.transcribe() -> Dialogue.post() -> robot.say()

Closes #440

Release impact

none — internal TypeScript contract/test-only change; no user-visible firmware behavior change.

Test Plan

  • npm run test:unit
  • npx biome lint stackchan/services/chat.ts tests/unit/chat-service-contract.test.ts scripts/prepare-node-test-modules.js
  • npm run format -- stackchan/services/chat.ts tests/unit/chat-service-contract.test.ts scripts/prepare-node-test-modules.js package.json tsconfig.test.json

Note: full npm run lint -- ... currently scans the repo-wide script paths and reports pre-existing warnings in unrelated files; the targeted changed-file lint above is clean.

Summary by CodeRabbit

  • Tests

    • Added comprehensive unit tests covering chat service behavior, event routing, tool-to-function mapping, and backend-agnostic callback wiring.
  • Chores

    • Improved test infrastructure and scripts for more reliable test runs and module resolution.
  • Refactor

    • Internal backend abstraction introduced with no runtime behavior changes; compile-time contracts broadened for future flexibility.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 14, 2026

Copy link
Copy Markdown
Contributor

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 15f42827-e83f-4143-bc58-1c294b74d163

📥 Commits

Reviewing files that changed from the base of the PR and between b2f86fd and 7e9c242.

📒 Files selected for processing (1)
  • firmware/tests/unit/chat-service-contract.test.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • firmware/tests/unit/chat-service-contract.test.ts

📝 Walkthrough

Walkthrough

ChatService is abstracted to a minimal ChatAudioLike and implements an exported ConversationBackend type. Test infrastructure is added to stub ChatAudioIO for Node ESM resolution, and unit tests validate API forwarding, tool-schema conversion, and callback wiring.

Changes

ConversationBackend Interface and Contract Verification

Layer / File(s) Summary
ConversationBackend interface and ChatService implementation
firmware/stackchan/services/chat.ts
Adds ChatAudioLike and exported ConversationBackend; updates ChatServiceOptions.chatAudioIOCtor to construct ChatAudioLike; changes ChatService to hold #chat: ChatAudioLike and implement ConversationBackend; adjusts constructor cast.
Test infrastructure and module resolution
firmware/package.json, firmware/scripts/prepare-node-test-modules.js, firmware/tsconfig.test.json
Adds prepare-node-test-modules.js to write an ESM ChatAudioIO stub into dist-tests/node_modules/ChatAudioIO, updates test:unit script formatting, and adds tsconfig paths/includes so tests compile against the stub and chat.ts.
Contract verification tests
firmware/tests/unit/chat-service-contract.test.ts
Adds FakeChatAudioIO test double and three tests: (1) ConversationBackend API forwarding and final state/error assertions; (2) Dialogue-style tools → functions conversion with parameters from inputSchema; (3) callback wiring aggregation for levels, transcripts, function calls, and state events.

Sequence Diagram

sequenceDiagram
  participant Test
  participant ChatService
  participant FakeChatAudioIO
  Test->>ChatService: new ChatService(chatAudioIOCtor, options)
  Test->>ChatService: start()
  ChatService->>FakeChatAudioIO: connect()
  FakeChatAudioIO-->>ChatService: connected
  Test->>ChatService: sendText(text)
  ChatService->>FakeChatAudioIO: sendText(text)
  Test->>ChatService: setMicrophoneEnabled(flag)
  ChatService->>FakeChatAudioIO: setMicrophoneEnabled(flag)
  Test->>ChatService: stop()
  ChatService->>FakeChatAudioIO: disconnect()
  Test->>ChatService: close()
  ChatService->>FakeChatAudioIO: close()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • stack-chan/stack-chan#377: Also adjusts firmware test setup and test compilation inputs, related to the unit-test harness changes.

Poem

🐰 I stubbed a module, typed the chat,
A tiny interface keeps it flat.
Tests hop in, events align,
ConversationBackend looks just fine!
🥕

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title 'feat: expose conversation backend contract' accurately and concisely describes the main change: introducing and exposing the ConversationBackend interface to formalize the conversation backend contract.
Linked Issues check ✅ Passed The PR meets the coding requirements from issue #440 by defining the ConversationBackend interface, making ChatService implement it, testing contract compliance, and preserving ChatAudioIO behavior while establishing extension points for legacy pipelines.
Out of Scope Changes check ✅ Passed All changes are directly scoped to exposing the conversation backend contract as planned: interface definition, implementation, unit tests, and test infrastructure setup are all aligned with issue #440 objectives.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/issue-440-conversation-if

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 `@firmware/tests/unit/chat-service-contract.test.ts`:
- Around line 56-72: The test currently calls ChatService methods (start, stop,
sendText, sendFunctionResult, setMicrophoneEnabled, setVolume, close) but only
asserts final state; update the test to also assert that FakeChatAudioIO
recorded passthrough calls by checking FakeChatAudioIO.calls contains entries
for each invoked method (e.g., "start", "stop", "sendText:こんにちは",
"sendFunctionResult:call-1:set_emotion", "setMicrophoneEnabled:false",
"setVolume:0.4", "close"), so modify the assertions after exercising the API to
verify FakeChatAudioIO.calls includes those expected call strings in the same
order to catch noop/passthrough regressions in ChatService/ConversationBackend
integration.
🪄 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: 8e5eb34d-0608-414e-80bb-26b936806a4b

📥 Commits

Reviewing files that changed from the base of the PR and between 66a2003 and b2f86fd.

📒 Files selected for processing (5)
  • firmware/package.json
  • firmware/scripts/prepare-node-test-modules.js
  • firmware/stackchan/services/chat.ts
  • firmware/tests/unit/chat-service-contract.test.ts
  • firmware/tsconfig.test.json

Comment thread firmware/tests/unit/chat-service-contract.test.ts
onFunctionCall?: (call: string, name: string, params: Record<string, unknown>) => void
}

type ChatAudioLike = {

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

一段抽象化してパイプラインとChatAudioIOと従来のSTT/LLM/TTSを選んで差し込めるようにしたい

@meganetaaan
meganetaaan changed the base branch from dev/v1.0 to develop June 28, 2026 08:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

AI会話バックエンドを統一的に扱う共通I/Fを整理する

1 participant