Repository navigation
feat: TUI 提示色按终端亮/暗主题适配 - #5
Conversation
旧实现除 --smoke-test 外静默忽略一切参数,新用户照惯例敲 --help 直接进交互菜单(实测复现),只能 Ctrl+C 退出重来。现在 -h/--help 在初始化依赖之前打印用法并退出(--help 必须瞬时返回)。 回归测试红/绿验证(旧行为进菜单、新行为打印用法)。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
主菜单/聊天提示符的 <skyblue>(xterm 116 #87d7af)与 questionary pointer 的固定 fg:yellow 在白底上对比度仅 1.7-2.3:1(WCAG AA 正文 要求 4.5:1,实测计算),亮色终端下几乎不可读;rich 语义色本就按 终端类型自动选择亮/暗变体,问题集中在 prompt_toolkit/questionary 的固定色。 - 新增 src/ui/terminal_theme.py:检测策略为 PYRAG_LIGHT/PYRAG_DARK 显式覆盖 > COLORFGBG 背景分量 ≥8 判亮 > 兜底暗色(终端用户主流 且误判代价不对称)。不做 OSC 11 轮询(编辑器线程并发下有竞争风险)。 - 暗色沿用原浅色(黑底 ~12:1);亮色换深变体 #0e7490(白底 5.4:1) 与 #a16207(白底 4.9:1),双向对比度均过 WCAG AA。 - HTML tag <skyblue> 改 <prompt> class,颜色完全交给主题样式工厂 (原 tag 内联 fg 优先于 class 样式,无法覆盖)。 - pty 实测:暗色 38;5;115 / 亮色 38;5;30,主菜单与聊天提示符一致。 - 测试替身 PromptSession 构造接受 style= kwargs;display_utils 豁免 表随行号漂移重基线(原文逐条核对);green38 夹具 249→250、 473→474(语义核对通过) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
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 |
评审者指南本 PR 引入基于环境变量和 COLORFGBG 的终端亮暗主题检测,为 prompt_toolkit 与 questionary 的三类 TUI 提示统一提供高对比度样式,并接入主菜单、聊天和配置菜单;同时补充 -h/--help 的早期 CLI 处理、测试替身兼容性及相关回归测试。 文件级变更
提示与命令与 Sourcery 互动
自定义使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's Guide本 PR 引入基于环境变量和 COLORFGBG 的终端亮暗主题检测,为 prompt_toolkit 与 questionary 的三类 TUI 提示统一提供高对比度样式,并接入主菜单、聊天和配置菜单;同时补充 -h/--help 的早期 CLI 处理、测试替身兼容性及相关回归测试。 File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
嘿——我发现了 5 个问题
面向 AI Agent 的提示
请处理这次代码审查中的评论:
## 各条评论
### 评论 1
<location path="src/ui/terminal_theme.py" line_range="59-61" />
<code_context>
+ # "0;15"(暗 fg / 亮 bg,亮色终端)、"0;15;x"(Konsole 三段式)。
+ # 取**最后一个**数值段作背景(两段式里它是 bg;三段式里 mode 不可能
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**浅色背景被错误分类**
当浅色背景终端提供的 `COLORFGBG` 为 `0;15;0` 时,`detect_light_background` 会读取末尾的 mode,而不是背景字段,并返回 `False`,因此样式工厂会使用对比度较低的暗色主题颜色。该格式的测试也预期返回 `False`,所以存在此缺陷时测试会通过,修正检测逻辑后反而会失败。
对于文档所述的三段格式,请读取背景字段,并更新测试,使其对 `0;15;0` 预期返回 `True`。
另请查看 `tests/ui/test_terminal_theme.py:27`。
</issue_to_address>
### 评论 2
<location path="src/chat/core.py" line_range="391" />
<code_context>
bot = Chatbot(console)
try:
- session = PromptSession()
+ session = PromptSession(style=prompt_style_for_theme())
if bot.llm_model:
</code_context>
<issue_to_address>
**检索提示仍然对比度过低**
当用户在浅色背景终端中运行检索测试时,`run_retrieval_test_async` 会创建一个未设置样式的 `PromptSession`,并使用固定的 `<deepskyblue>` 提示文本,因此不会应用主题样式,查询提示的对比度仍然很低。
请在 `run_retrieval_test_async` 中应用适配主题的提示样式和提示颜色。
另请查看 `src/ui/terminal_theme.py:3-8`、`src/ui/terminal_theme.py:69`。
</issue_to_address>
### 评论 3
<location path="src/ui/terminal_theme.py" line_range="59-61" />
<code_context>
+ # "0;15"(暗 fg / 亮 bg,亮色终端)、"0;15;x"(Konsole 三段式)。
+ # 取**最后一个**数值段作背景(两段式里它是 bg;三段式里 mode 不可能
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**格式错误的主题提示会导致提示界面崩溃**
当 `COLORFGBG` 在另一个仅含数字的字段后包含 `²` 之类的字段时,`str.isdigit()` 会接受一些 `int()` 无法解析的字符串(例如 `²`),导致 `detect_light_background` 抛出 `ValueError`,而不是回退到暗色主题;结果是提示界面创建失败,菜单无法显示。
请仅解析 ASCII 十进制字段,或捕获转换错误并采用文档所述的暗色回退方案。
</issue_to_address>
### 评论 4
<location path="src/ui/terminal_theme.py" line_range="61" />
<code_context>
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**ANSI 白色背景被误判为暗色**
当 `COLORFGBG` 为 `0;7`,且终端将背景索引 `7` 映射为白色或浅灰色时,`detect_light_background` 会将背景索引 `7` 判定为暗色,因为它要求索引至少为 `8`。因此,在索引 `7` 实际为白色或浅灰色的终端上,会选择浅淡的暗色主题颜色。
请识别已知的浅色 ANSI 背景索引(例如 `7`),或者根据所报告背景的实际亮度来判断,而不是使用索引阈值。
</issue_to_address>
### 评论 5
<location path="src/ui/config_menu.py" line_range="184" />
<code_context>
questionary.Choice("返回主菜单", value="back"),
],
- style=questionary.Style([("pointer", "bold fg:yellow")]),
+ style=questionary_style_for_theme(),
).ask()
</code_context>
<issue_to_address>
**嵌套选择提示中的指针样式未适配主题**
当用户打开嵌套的检索或模型选择提示时,`edit_retrieval_params` 和 `edit_model_params` 中嵌套的 `questionary.select` 调用没有传入 `questionary_style_for_theme()`,因此这些选择提示使用 questionary 内置的、未适配主题的样式,而不是新的主题专属指针颜色。
请也在嵌套的 `questionary.select` 调用中传入 `questionary_style_for_theme()`。
另请查看 `src/ui/config_menu.py:457`、`src/ui/config_menu.py:555`。
</issue_to_address>Sourcery 评估
等待批准。 请先处理 5 个发现的问题。
阻塞项:src/ui/terminal_theme.py:61、src/chat/core.py:391、src/ui/terminal_theme.py:61、src/ui/terminal_theme.py:61、src/ui/config_menu.py:184
Original comment in English
Hey - I've found 5 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="src/ui/terminal_theme.py" line_range="59-61" />
<code_context>
+ # "0;15"(暗 fg / 亮 bg,亮色终端)、"0;15;x"(Konsole 三段式)。
+ # 取**最后一个**数值段作背景(两段式里它是 bg;三段式里 mode 不可能
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**Light backgrounds are misclassified**
When a light-background terminal supplies `COLORFGBG` as `0;15;0`, `detect_light_background` reads the trailing mode instead of the background field and returns `False`, so the style factories use low-contrast dark-theme colors. The test for this format also expects `False`, so it passes with the defect and fails once detection is corrected.
Read the background field in the documented three-part format and update the test to expect `True` for `0;15;0`.
Also at `tests/ui/test_terminal_theme.py:27`.
</issue_to_address>
### Comment 2
<location path="src/chat/core.py" line_range="391" />
<code_context>
bot = Chatbot(console)
try:
- session = PromptSession()
+ session = PromptSession(style=prompt_style_for_theme())
if bot.llm_model:
</code_context>
<issue_to_address>
**Retrieval prompt stays low contrast**
When a user runs retrieval testing in a light-background terminal, `run_retrieval_test_async` creates an unstyled `PromptSession` and uses fixed `<deepskyblue>` prompt text, so it does not use the theme style and the query prompt remains low-contrast.
Apply the theme-aware prompt style and prompt color in `run_retrieval_test_async`.
Also at `src/ui/terminal_theme.py:3-8`, `src/ui/terminal_theme.py:69`.
</issue_to_address>
### Comment 3
<location path="src/ui/terminal_theme.py" line_range="59-61" />
<code_context>
+ # "0;15"(暗 fg / 亮 bg,亮色终端)、"0;15;x"(Konsole 三段式)。
+ # 取**最后一个**数值段作背景(两段式里它是 bg;三段式里 mode 不可能
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**Malformed theme hint aborts prompts**
When `COLORFGBG` contains a segment such as `²` after another digit-only segment, `str.isdigit()` accepts some strings that `int()` cannot parse (for example, `²`), so `detect_light_background` raises `ValueError` instead of falling back to dark; prompt construction then fails rather than displaying the menu.
Parse only ASCII decimal segments or catch conversion errors and use the documented dark fallback.
</issue_to_address>
### Comment 4
<location path="src/ui/terminal_theme.py" line_range="61" />
<code_context>
+ # 出现在 bg 之前)。
+ parts = [segment for segment in colorfgbg.split(";") if segment.strip().isdigit()]
+ if len(parts) >= 2:
+ return int(parts[-1]) >= 8
+ return False
+
</code_context>
<issue_to_address>
**ANSI 白色背景误判为暗色**
When `COLORFGBG` is `0;7` and the terminal maps background index `7` to white or light gray, `detect_light_background` treats background index `7` as dark because it requires an index of at least `8`, so it selects pale dark-theme colors on a terminal whose index `7` is white or light gray.
Recognize known light ANSI background indices such as `7`, or determine the reported background’s actual brightness instead of using the index threshold.
</issue_to_address>
### Comment 5
<location path="src/ui/config_menu.py" line_range="184" />
<code_context>
questionary.Choice("返回主菜单", value="back"),
],
- style=questionary.Style([("pointer", "bold fg:yellow")]),
+ style=questionary_style_for_theme(),
).ask()
</code_context>
<issue_to_address>
**Nested choice pointers stay unadapted**
When a user opens a nested retrieval or model choice prompt, the nested `questionary.select` calls in `edit_retrieval_params` and `edit_model_params` do not pass `questionary_style_for_theme()`, so those choice prompts use questionary’s built-in, non-theme-aware styles instead of the new theme-specific pointer colors.
Pass `questionary_style_for_theme()` to the nested `questionary.select` calls as well.
Also at `src/ui/config_menu.py:457`, `src/ui/config_menu.py:555`.
</issue_to_address>Sourcery assessment
Approval pending. 5 findings to address first.
Blocking findings: src/ui/terminal_theme.py:61, src/chat/core.py:391, src/ui/terminal_theme.py:61, src/ui/terminal_theme.py:61, src/ui/config_menu.py:184
PR #4/#5 bot 复核的 9 条发现逐条探针核实,8 条属实修复、1 条记录不修: --help(PR #4): - 注销 atexit 退出清理钩子——import src.utils.cleanup 的模块级注册 在分支之前生效,不注销则 --help 退出把上次会话的缓存目录整个 rmtree(实测复现);--help 是只读查询,不应有副作用 - 坏配置下 --help 不再裸 traceback:log_manager.get_module_logger 在 import 期调 get_settings(),配置语法错误让 --help 连用法都 打不出(实测复现);日志级别降级为默认值,主流程仍按原契约报错 - 用法行按 sys.frozen 区分:打包产物是 PyRAG-Kit 可执行文件, python main.py 指引在冻结态不可用 - 回归测试补断言:help 分支不初始化依赖、注销退出清理 主题适配(PR #5): - COLORFGBG 三段式取第二段作 bg——取末段把 mode=0 的亮色终端 误判成暗色(实测 0;15;0 判 False);测试原断言与缺陷同向, 已随修正翻转 - 判据放弃 str.isdigit(接受 '²' 而 int() 崩,实测 ValueError 穿透到菜单构建),只认 ASCII 数字 - 召回测试提示符纳入主题:run_retrieval_test_async 的独立 PromptSession 与固定 <deepskyblue> 未适配(实测 38;5;39 白底 低对比),改主题样式 + <prompt> class - 4 处嵌套 questionary.select(method/fusion/LLM/Rerank)补 主题样式——只有 3 处外层菜单适配了,子菜单 pointer 仍用 questionary 内置样式 - 记录不修:COLORFGBG bg=7(ANSI 浅灰)在个别终端映射为白—— rxvt 惯例本就把 0-7 归暗色系,为罕见映射改判据会误伤主流 测试替身随新增 style= 参数适配;display_utils 豁免表与 green38 夹具随行号漂移重基线(原文逐条核对)。全量 4547 passed, 8 项质量门全绿。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
|
Sourcery 的 5 条发现逐条核实,4 条属实已修复(65f86e0)、1 条记录不修:
|
目的
TUI 的三处提示色写死浅色系:主菜单/聊天提示符
<skyblue>(xterm 116,#87d7af)与 questionary pointer 的fg:yellow在白底上对比度仅 1.7-2.3:1(WCAG AA 正文要求 4.5:1,实测计算),亮色终端下几乎不可读。rich 的语义色(边框/文字的 green/yellow/red)不受影响——Console按终端类型自动选亮/暗变体;问题集中在 prompt_toolkit / questionary 的固定色。实现方案
src/ui/terminal_theme.py,检测策略(按优先级):PYRAG_LIGHT=1/PYRAG_DARK=1显式覆盖(用户逃生通道)COLORFGBG背景分量 ≥8 判亮(xterm/rxvt/Konsole 会设)#0e7490(白底 5.4:1)与#a16207(白底 4.9:1),双向对比度均过 WCAG AA。<skyblue>改<prompt>class:原 tag 直接携带fg:#87ceeb内联色,优先于 class 样式无法覆盖。/config编辑器线程并发下有竞争风险。影响范围与验证
main.py、src/chat/core.py、src/ui/config_menu.py(3 处样式点)PromptSession构造签名补**kwargs(新增style=参数)38;5;115/ 亮色38;5;30,主菜单与聊天提示符两处一致tests/ui/test_terminal_theme.py(14 条);全量 4545 passed;8 项质量门全绿配置影响
无新配置项。环境变量
PYRAG_LIGHT/PYRAG_DARK为可选覆盖,默认自动检测。🤖 Generated with Claude Code
Sourcery 摘要
提升 TUI 在不同终端主题下的可读性,并提供标准的命令行帮助输出。
新功能:
-h/--help用法输出,并在初始化交互界面前退出。增强功能:
PYRAG_LIGHT、PYRAG_DARK或COLORFGBG自动或显式选择终端主题;如果缺少检测信号,则默认使用暗色方案。测试:
Original summary in English
Sourcery 摘要
提升交互式终端在不同主题下的可读性,并为命令行入口提供无副作用的帮助输出。
新功能:
-h/--help用法输出,并在初始化交互环境前安全退出。错误修复:
改进:
PYRAG_LIGHT、PYRAG_DARK和COLORFGBG自动或显式选择终端主题;未检测到相关信号时,默认使用暗色方案。文档:
测试:
Original summary in English
Summary by Sourcery
提升交互式终端在不同主题下的可读性,并为命令行入口提供无副作用的帮助输出。
New Features:
-h/--help用法输出,并在初始化交互环境前安全退出。Bug Fixes:
Enhancements:
PYRAG_LIGHT、PYRAG_DARK和COLORFGBG自动或显式选择终端主题,未检测到信号时默认使用暗色方案。Documentation:
Tests: