Merge commit e95582a: PR #20 proactive chat, topic chips, low-info turn plan

- Merge staging workflow parent and resolve conflicts with English/i18n and WS pool
- Re-greeting: language-aware fallbacks and prompts; router passes user_language
- RealtimeSession: topic suggestion callbacks + TTS sync path preserved

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Kevin
2026-05-12 11:02:58 +08:00
21 changed files with 1047 additions and 97 deletions

View File

@@ -181,13 +181,66 @@ def test_plan_clarify_first_when_very_short():
p = plan_interview_turn(
current_stage="childhood",
empty_slots=["place"],
normalized_user_message="还好吧",
normalized_user_message="有点说不清",
memory_evidence_text="",
stage_switched_this_turn=False,
)
assert p.mode == "clarify_first"
def test_plan_low_information_reply_pushes_next_topic_when_slots_remain():
p = plan_interview_turn(
current_stage="childhood",
empty_slots=["place", "people"],
normalized_user_message="嗯。",
memory_evidence_text="",
stage_switched_this_turn=False,
)
assert p.mode == "memoir_push"
assert p.anchor_slot_key == "place"
assert p.reply_shape == "ack_then_question"
assert p.low_information_reply is True
def test_low_information_directive_asks_for_proactive_topic_not_clarification():
p = plan_interview_turn(
current_stage="childhood",
empty_slots=["place"],
normalized_user_message="",
memory_evidence_text="",
stage_switched_this_turn=False,
)
block = format_interview_turn_directive_block(p)
assert "低信息短回复处理" in block
assert "不要把这个短答本身当成需要澄清的内容" in block
assert "恰好一个" in block
assert "主动" in block
def test_plan_low_information_reply_uses_follow_when_no_slots_remain():
p = plan_interview_turn(
current_stage="childhood",
empty_slots=[],
normalized_user_message="是的",
memory_evidence_text="",
stage_switched_this_turn=False,
)
assert p.mode == "follow_user_only"
assert p.reply_shape == "ack_then_question"
assert p.low_information_reply is True
def test_short_substantive_reply_is_not_treated_as_low_information():
p = plan_interview_turn(
current_stage="childhood",
empty_slots=["place", "people"],
normalized_user_message="上海",
memory_evidence_text="",
stage_switched_this_turn=False,
)
assert p.low_information_reply is False
def test_plan_memoir_push():
p = plan_interview_turn(
current_stage="childhood",
@@ -232,3 +285,4 @@ def test_plan_follow_when_no_empty_slots():
stage_switched_this_turn=False,
)
assert p.mode == "follow_user_only"
assert p.low_information_reply is True