Skip to content

fix(speak): keep help-offer dialogue coherent across worker and client - #21

Merged
moyunzero merged 2 commits into
mainfrom
moyunzero/fix/npc-speak-dialogue-coherence
Jul 20, 2026
Merged

fix(speak): keep help-offer dialogue coherent across worker and client#21
moyunzero merged 2 commits into
mainfrom
moyunzero/fix/npc-speak-dialogue-coherence

Conversation

@moyunzero

@moyunzero moyunzero commented Jul 20, 2026

Copy link
Copy Markdown
Owner

Distinguish player help offers from help requests, gate casual/social fast lanes when session history exists, inject recent_turns into social LLM prompts, and align shared preview routing with worker parity including extended offer phrases and per-NPC dialogue history on web.

Summary by CodeRabbit

  • New Features

    • NPC dialogue previews and responses now use recent conversation context for more coherent multi-turn interactions.
    • NPC conversations now maintain more accurate per-NPC dialogue history.
    • Help offers are distinguished from help requests, enabling more natural responses.
  • Bug Fixes

    • Reduced repetitive, incorrect, or inverted help-related replies.
    • Short follow-up messages are less likely to be misclassified when conversation history exists.
  • Tests

    • Added coverage for dialogue context, NPC-specific history, help offers, and response quality.

Distinguish player help offers from help requests, gate casual/social fast
lanes when session history exists, inject recent_turns into social LLM
prompts, and align shared preview routing with worker parity including
extended offer phrases and per-NPC dialogue history on web.

Co-authored-by: Cursor <cursoragent@cursor.com>
@coderabbitai

coderabbitai Bot commented Jul 20, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@moyunzero, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 29 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: ee5a1756-c85a-40f1-b8a9-6bf4f506a33c

📥 Commits

Reviewing files that changed from the base of the PR and between cf7a71e and 5b46132.

📒 Files selected for processing (4)
  • apps/web/src/hooks/npcChat/dialogueTurns.test.ts
  • apps/web/src/hooks/npcChat/dialogueTurns.ts
  • workers/agent-worker/src/graph/nodes/llm_social_turn.py
  • workers/agent-worker/tests/test_help_reply_by_npc.py
📝 Walkthrough

Walkthrough

The change adds recent-dialogue context to NPC speak previews and social-turn prompts, distinguishes help offers from help requests, blocks deterministic fast lanes when history is present, and adds web, worker, unit, and Playwright validation.

Changes

History-aware speak handling

Layer / File(s) Summary
Shared intent and preview contracts
packages/shared/src/speakIntent.ts, packages/shared/src/casualSpeakStub.ts, packages/shared/src/index.ts, packages/shared/src/*.test.ts
Adds DialogueTurn, refines help-offer/request detection, classifies short contextual messages as narrative, and blocks casual previews when recent turns exist.
NPC chat history and server preview wiring
apps/web/src/hooks/npcChat/*, apps/web/src/hooks/useNpcChat.ts, apps/game-server/src/colyseus/GameRoom.ts, apps/game-server/src/routes/chat.ts
Derives NPC-specific completed turns, preserves player npcId metadata, and supplies recent turns to client and server preview generation.
Social-turn routing and prompt context
workers/agent-worker/src/collective/*, workers/agent-worker/src/graph/*, workers/agent-worker/tests/*
Separates help offers from requests, gates deterministic social and casual paths, injects player/NPC history into prompts, and includes NPC turns in recall context.
Help-offer UAT and issue records
scripts/uat-speak-help-offer-playwright.mjs, package.json, docs/ISSUE-LOG.md
Adds a Playwright scenario and command for validating multi-turn help-offer replies and documents the associated guardrails and resolved issue.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant Player
  participant useNpcChat
  participant GameRoom
  participant llm_social_turn
  participant append_recent_dialogue_messages
  Player->>useNpcChat: Submit speak message
  useNpcChat->>GameRoom: Send message with NPC context
  GameRoom->>llm_social_turn: Process speak with recent turns
  llm_social_turn->>append_recent_dialogue_messages: Append player and NPC history
  append_recent_dialogue_messages-->>llm_social_turn: Return contextual messages
  llm_social_turn-->>Player: Generate contextual NPC reply
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 23.08% 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 title clearly summarizes the main change: making help-offer dialogue coherent across worker and client.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch moyunzero/fix/npc-speak-dialogue-coherence

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.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: cf7a71ecf5

ℹ️ 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".

return None
inferred = infer_social_from_message(msg)
if inferred is not None:
if (recent_turns or player_offers_help(msg)) and inferred.kind in ("rude", "help"):

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Skip deterministic casual replies when history exists

In the worker interactive path, this guard only disables deterministic rude/help replies. With existing recent_turns, a follow-up such as 你好,用一句话简短回复一下你的计划安排吧 (20 chars, contains 一句话) is still classified as CASUAL; process_job skips the B1 fast lane, but llm_social_turn() calls _deterministic_social_turn() and falls through to the CASUAL branch below, emitting a canned reply before append_recent_dialogue_messages() can run. That reintroduces history-ignoring stub replies for longer continuation/meta-brief messages.

Useful? React with 👍 / 👎.

Comment on lines +24 to +25
if (m.npcId !== npcId) {
pendingPlayers = [];

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2 Badge Preserve pending turns across other NPC replies

When chats with different NPCs overlap, this clears the pending player line for the target NPC as soon as any other NPC reply is seen. Since sendMessage only blocks the same npcId, a user can send to npc-5, switch to npc-1, receive npc-1's reply, then receive npc-5's reply; the npc-5 turn is omitted from recentDialogueTurnsForNpc, so the client may show a casual preview for the next npc-5 follow-up while the server/worker correctly see history. Keep pending turns per NPC or ignore unrelated NPC messages instead of clearing them.

Useful? React with 👍 / 👎.

… NPCs

Block deterministic CASUAL/meta replies in llm_social_turn when recent_turns
exist (interactive path parity with fast-lane gate). Skip unrelated NPC
messages in dialogueTurns without clearing pending player lines.

Co-authored-by: Cursor <cursoragent@cursor.com>
@moyunzero
moyunzero merged commit 857dc96 into main Jul 20, 2026
2 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Jul 30, 2026
7 tasks
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.

1 participant