Skip to content

预埋羽毛球小游戏后端路由与提示词#3

Closed
MomiJiSan wants to merge 1 commit into
mainfrom
codex/badminton-backend-route-prompts
Closed

预埋羽毛球小游戏后端路由与提示词#3
MomiJiSan wants to merge 1 commit into
mainfrom
codex/badminton-backend-route-prompts

Conversation

@MomiJiSan

Copy link
Copy Markdown
Owner

改动概述

本 PR 先预埋羽毛球小游戏的后端能力:把原篮球小游戏后端 route、pregame、quick-lines、memory policy、duel 控制提示词迁移到 badminton 语义,并保留 basketball game_type 作为兼容别名,避免前端入口尚未切换时旧页面直接失效。

这是堆叠 PR 的第一层;用户可见页面、资源、i18n 和测试迁移在后续 PR 中完成。

回归报告 / Regression Report

改动内容:main_routers/game_router.py 的小游戏后端路由、会话状态、赛前上下文、quick-lines、memory policy、排行榜/分数会话和对战控制逻辑从 basketball 语义迁移到 badminton 语义;config/prompts/prompts_game.py 同步替换系统提示词、duel 提示词、quick-lines 和 pregame prompt。

理由/必要性:羽毛球小游戏需要先具备后端 route 生命周期和 LLM 提示词能力,后续前端页面才能切换到 /api/game/badminton/* 并复用现有游戏 route 基础设施。

前后表现:变更后后端可识别 badminton game_type,并通过兼容别名继续接收 basketball game_type;PR1 单独合入时不会开放新页面入口,主要作为后端预埋层。

潜在回归点:game_route_startgame_quick_lines、game memory policy、postgame archive、leaderboard score session 的 game_type 分发。GitNexus 标记本层为 high risk,review 时请重点看 route 生命周期和 quick-lines 分发。

风险与边界

本 PR 不切换用户入口、不提交前端模板资源、不迁移 locale 和测试合同;这些放在第二层 stacked PR。当前保留 basketball 兼容别名是为了降低堆叠期间的中间态风险。

@MomiJiSan

Copy link
Copy Markdown
Owner Author

开错仓库位置了,已改为上游 stacked draft PR:Project-N-E-K-O#1888

@MomiJiSan MomiJiSan closed this Jun 18, 2026
@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: daddc526-3c85-439a-9a15-87dcbc55b4e0

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/badminton-backend-route-prompts

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.

MomiJiSan pushed a commit that referenced this pull request Jun 19, 2026
…-up 3/4/6) (Project-N-E-K-O#1895)

* feat(focus): 凝神指示灯 + 流式 <think> 剥离 + i18n(PR Project-N-E-K-O#1815 follow-up 3/4/6)

凝神 v1(PR Project-N-E-K-O#1815,默认 FOCUS_MODE_ENABLED=False、inert)的三项剩余 follow-up,
后端骨架此前已落,这次补打开开关前的安全闸 + 前端可见化:

- 3① 流式 <think> 剥离(安全前置):新增 ThinkingStreamStripper(utils/llm_client),
  仅对会在 content 里漏 CoT 的 provider(qwen3.5/3.6/3.7 hybrid,dangling </think>)
  + thinking_on 时挂上,缓冲到首个 </think> 丢弃 CoT 再放行正文,跨 chunk 安全。
  干净 provider(reasoning_content 路径)经 config.providers.leaks_thinking_in_content
  排除,流式不受影响、零回归。接入点在 OmniOfflineClient.stream_text 流式咽喉。

- 4 前端凝神指示灯:SM 订阅 FOCUS_ENTER/EXIT → LLMSessionManager._on_focus_transition
  推 focus_state ws → app-websocket.js 转 neko-focus-state 事件 → react-neko-chat 渲
  极隐"呼吸微光" badge(chat-window inset box-shadow,compact/full/手机三上下文共用,
  prefers-reduced-motion 退化为静态微光)。FOCUS_MODE_ENABLED 默认关 = 不显示。

- 6 i18n:chat.focusIndicator 八语言(仅 aria-label/tooltip,极隐微光无可见文字)。

范围说明:3② provider extras 保留此前已落;评分器 LLM 化(1)在另一分支推进中;
memory FOCUS_EXIT 联动(5)/ True-Name v2(8)不在本 PR。

测试:ThinkingStreamStripper 流式/跨 chunk 分割/dangling/classifier(test_thinking_stream_stripper)
+ focus_state 桥 on/off(test_focus_indicator_bridge);既有 test_focus_mode 43 + 前端
221 vitest 全过。inert by default。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(focus): emit ThinkingStreamStripper residual even when prefix checking is off (Greptile P2)

post-loop flush gated on `not prefix_checked`; with _prefix_buffer_size==0
prefix_checked starts True, so a held residual (leak-prone model under
thinking_on that never emitted </think>) was appended to prefix_buffer then
silently dropped. Clear prefix_checked when residual is non-empty so the unified
fence/length-guard/emit path runs. Safe: a non-empty residual means the stripper
held the whole stream, so prefix_buffer was never filled by the live path.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(focus): address Codex review — history/proactive/tool-boundary/indicator coverage

Four P2s from Codex review (all real, verified):

- #1 history raw CoT: streamed_text_buffer (assistant tool-call turn) was
  persisted RAW — a leak-prone Focus turn carried <think> into next-turn
  context. Now strip_thinking_segments() at both inner-generator history writes
  (openai + genai, symmetric); no-op on clean replies.
- #3 proactive coverage: text-mode proactive Phase-2 streams thinking-on via its
  own loop in system_router (not stream_text), so it was unprotected. Mounted
  the same ThinkingStreamStripper there (feed in-loop, flush held answer into the
  tag-parse buffer), gated on leak-prone model + thinking-on — symmetric with
  the inline path.
- #4 tool-boundary drop: tool_round reset discarded held pre-tool text when no
  </think> arrived. Flush + emit to TTS/UI before reset (history already has it
  via #1).
- #2 stuck badge: subscribing only to FOCUS_ENTER/EXIT missed silent clears
  (clear_focus history-wipe, master-switch self-clear). Added an idempotent
  _push_focus_indicator + per-turn _reconcile_focus_indicator (inline + idle) so
  the badge can't get stuck on. getattr-guards bypass-__init__ managers.

Also: sr-only indicator uses clip-path: inset(50%) (CodeRabbit; clip deprecated).

Tests: indicator idempotency + reconcile-clears-after-silent-drop added;
67 focus/stripper backend + 221 vitest pass; clip-path hidden + glow verified.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(focus): gate stripper on effective thinking + same-turn badge clear (Codex round 2)

- Gate ThinkingStreamStripper on `thinking_on and not _focus_images_seen`,
  matching _focus_stream_overrides' effective-thinking condition: a vision Focus
  turn runs thinking-OFF, so no </think> arrives and the stripper would needlessly
  hold the stream.
- Reconcile the badge again right after the master-switch self-clear (inline +
  idle, symmetric): that clear emits no FOCUS_EXIT, so clear the badge this turn
  instead of next.

(Declined Codex's third P2 — routing the rare tool-boundary residual through the
full fence/length emit machinery — as edge-of-edge churn on a hot path; the
residual is already history-clean and emitted to TTS/UI.)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
@MomiJiSan MomiJiSan deleted the codex/badminton-backend-route-prompts branch June 19, 2026 10:21
MomiJiSan pushed a commit that referenced this pull request Jun 24, 2026
* feat(proactive): 主动搭话以屏幕为素材时暂存截图,用户回复前注入对话上下文

原本:主动搭话用 vision 模型看屏幕生成台词后,finish_proactive_delivery 只把
纯文本 AIMessage 写进历史,那张截图当场丢弃——用户回复时对话模型完全不知道
刚才评论的屏幕长什么样。

改动:
- OmniOfflineClient 新增独立单槽 _proactive_image_to_inject + set_proactive_screenshot(),
  与用户自己的 _pending_images 严格隔离(共用会偷走用户下一帧,Codex P2)。
- stream_text 把暂存截图作为「前导」image_url 折叠进用户下一条 text 回复
  (排在用户自己的帧之前,时间序),一次性消费后清空。
- finish_proactive_delivery 新增 vision_screenshot_b64 参数,仅在 commit 成功
  (sid 未被用户抢占)时落槽;传 None 清掉旧截图。
- 路由 gate:phase2_use_vision 且 primary_channel in ('chat','vision') 才暂存
  (vision-only 轮无 tag 兜底成 CHAT→primary 是 'chat' 而非 'vision';落到
  music/web/meme 时屏幕只是顺带喂进去、并非话题,不暂存)。

语音回复不处理:voice session 是独立 realtime 连接,不继承 text session 历史,
属架构隔离,截图槽随旧 OmniOfflineClient close() 自然丢弃。

测试:tests/unit/test_proactive_vision_screenshot_staging.py(9 例,覆盖单槽隔离/
注入顺序/一次性消费/commit 才暂存/None 清旧/sid 抢占不暂存)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* refactor(proactive): 放宽截图缓存条件为「拿到截图+有vision模型」并加 2 分钟 TTL

按需求收敛:
- gate 放宽:不再要求 primary_channel in ('chat','vision'),只要本轮后端拿到
  截图且有可用 vision 模型(phase2_use_vision)就缓存最后一张主动搭话截图;
  落到 music/web/meme 时屏幕仍是这轮看过的画面,留着供用户追问。
- 新一轮主动搭话产生即覆盖/清旧缓存(没拿到截图的轮次 commit 时传 None 清)。
- 新增 2 分钟 TTL:set_proactive_screenshot 记 monotonic 时间戳,stream_text
  注入前惰性判定,过期则丢弃不注入并清槽。
- 修 review:删未使用的 SimpleNamespace import;test 文件 docstring 改英文过
  DOCSTRING_CJK 守卫(中文留在行内注释)。

测试:新增 TTL 过期/未过期两例,11 例全绿;相关 proactive 套件 136 例全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(proactive): 截图缓存钉死在「最后一条 AI 轮」,避免被后续 ephemeral 轮带陈旧屏

Codex P2:screen-based proactive_chat 暂存截图后,若用户回复前又来了一条经
prompt_ephemeral 投递的 AI 轮(greeting / agent 回调,不过 finish_proactive_delivery
也不 set_proactive_screenshot(None)),旧截图会被注给「回复那条不相关的后续轮」。

修法(path-agnostic):暂存时记录历史长度 _proactive_image_history_len,注入前
若历史已变长(说明中途有别的 AI 轮 append)则判定 superseded、丢弃不注入。与
2 分钟 TTL 并列两道失效门。新增 superseded 用例,12 例全绿。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(proactive): ephemeral 可见回复(头像 quip 等)也清掉暂存截图

Codex P2 #2:history-len marker 只能发现「append 进历史」的 AI 轮,但头像交互走
prompt_ephemeral(persist_response=False) —— 有可见回复却不进历史、长度不变,marker
看不到。若屏幕轮暂存截图后用户先戳了头像再打字,旧屏会被注给「回复头像那条」。

修法:在 prompt_ephemeral 的 finally、确认吐出可见文本(content_committed)时清掉
暂存槽。这是所有 greeting / agent 回调 / 头像 quip 的统一 choke point,覆盖
persist=True/False 两种。只在真有可见文本时清,半途 abort 不丢有效暂存屏。
history-len marker 保留作 path-agnostic 兜底(catch 任何"进历史"的轮次)。

测试:+2 例(可见 ephemeral 回复清槽 / 无文本尝试保留槽),14 例全绿;
相关 proactive+ephemeral 套件 234 例无回归。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* fix(proactive): magic-command 绕过路径也清掉暂存截图

Codex P2 #3:OpenClaw/Qwenpaw magic command 走 _clear_text_pending_images 后
早 return、不经 stream_text,从不消费暂存槽。屏幕轮后用户用 magic command 回应,
旧截图残留、之后被注进不相关消息。

修法:在 _clear_text_pending_images(清 _pending_images 的同一 choke point)一并
set_proactive_screenshot(None)——两者同为"用户做了别的动作→失效待发视觉上下文"。
+1 测试。pre-existing 的 2 个 openclaw 测试红是 base 既有(_FakeState 缺 mode),
与本改无关(set_proactive_screenshot 不在其报错路径)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

* test(proactive): 锁定注入截图走正常 keep_turns=2 图片轮淘汰

确认需求:proactive 注入的图片是普通 list-content 图片轮,占用 history 图片槽位,
由同一个 _evict_old_images(keep_turns=2) 淘汰——source-agnostic,与用户帧无差别、
正常更替,不特殊豁免。补一例钉死该契约。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
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