Skip to content

feat(demo): 添加演示模式支持,禁用实时预览和控制功能#402

Merged
wess09 merged 1 commit into
masterfrom
dev
Jun 26, 2026
Merged

feat(demo): 添加演示模式支持,禁用实时预览和控制功能#402
wess09 merged 1 commit into
masterfrom
dev

Conversation

@wess09

@wess09 wess09 commented Jun 26, 2026

Copy link
Copy Markdown
Owner

Summary by Sourcery

添加一个演示模式,用于禁用资源密集型的实时预览/控制功能,并调整标识符和进程以支持安全的演示构建。

新功能:

  • 引入演示模式标志,通过环境变量 DEMO=1 控制,在演示构建中改变 Web UI 的行为。

改进:

  • 在演示模式下禁用实时截图和实时控制的 WebSocket 端点,并为用户展示说明此限制的错误消息。
  • 在演示模式运行时,在 UI 中显示特定于演示的设备标识字符串,而不显示真实设备 ID。
  • 在演示模式下跳过启动世界模拟器和 OCR 服务器进程,以避免初始化占用资源较多的设备服务。
  • 在演示模式下绕过受限设备检查,使演示可以在任意设备上运行。
  • 调整进程管理器以识别演示模式终止日志,并在状态报告中将其视为正常运行状态。
  • 在演示模式下启动进程时输出一段简短且确定性的演示日志序列,以展示日志输出效果。
Original summary in English

Summary by Sourcery

Add a demo mode that disables resource-intensive live preview/control features and adjusts identifiers and processes to support a safe demonstration build.

New Features:

  • Introduce a demo mode flag controlled via the DEMO=1 environment variable to alter web UI behavior for demonstration builds.

Enhancements:

  • Disable live screenshot and live control WebSocket endpoints in demo mode with user-facing error messages explaining the restriction.
  • Display a demo-specific device identifier string in the UI instead of the real device ID when running in demo mode.
  • Skip starting the world simulator and OCR server processes in demo mode to avoid initializing heavy device resources.
  • Bypass restricted-device checks in demo mode to allow the demo to run on any device.
  • Adjust the process manager to recognize demo-mode termination logs and treat them as a normal running state for status reporting.
  • Emit a short, deterministic demo log sequence when launching processes in demo mode to showcase logging output.

@chatgpt-codex-connector

Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@wess09 wess09 merged commit 044ad0d into master Jun 26, 2026
8 checks passed
@sourcery-ai

sourcery-ai Bot commented Jun 26, 2026

Copy link
Copy Markdown

审阅者指南

此 PR 引入了一个由环境变量 DEMO=1 控制的演示模式。在演示模式下,会禁用实时预览/控制,避免启动重量级服务(模拟器、OCR 服务、设备限制检查),并将真实设备 ID 和实际进程行为替换为适合演示的消息与流程。

Web UI 中演示模式行为开关的流程图

flowchart TD
    DEMO_env[DEMO=1 environment] --> is_demo_mode

    is_demo_mode -->|true| ws_live_screenshot
    is_demo_mode -->|true| ws_live_control
    is_demo_mode -->|true| simulator_start
    is_demo_mode -->|true| ocr_server_start
    is_demo_mode -->|true| demo_device_id
    is_demo_mode -->|true| demo_run_process

    ws_live_screenshot[[ws_live_screenshot]] --> disabled_preview[Send error and close websocket]
    ws_live_control[[ws_live_control]] --> disabled_control[Send error and close websocket]
    simulator_start[[WebUI._simulator_start]] --> skip_simulator[Skip simulator.start]
    ocr_server_start[[startup start_ocr_server_process]] --> skip_ocr[Do not start OCR server]
    demo_device_id[[get_device_id in UI]] --> use_demo_text[Use DEMO_DEVICE_ID_TEXT]
    demo_run_process[[run_process]] --> demo_logs[Log countdown and exit]

    is_demo_mode -->|false| normal_flow[Normal behavior for all components]
Loading

文件级变更

Change Details Files
引入一个共享的演示模式标志,并将其应用到 WebSocket 端点上,以在演示模式下禁用实时截图和控制。
  • 在 api 模块中基于 DEMO 环境变量新增 is_demo_mode 辅助函数
  • 在演示模式下对 ws_live_screenshot 进行短路处理:发送错误消息后关闭 WebSocket
  • 在演示模式下对 ws_live_control 进行短路处理:发送错误消息后关闭 WebSocket
module/webui/api.py
调整 Web UI 在演示模式下的行为:掩盖设备 ID、跳过模拟器/OCR 启动,并放宽设备限制检查。
  • 定义 DEMO_DEVICE_ID_TEXT,用于显示演示专用的设备标识文本
  • 在演示模式下,在 DropRecord 分组中使用 DEMO_DEVICE_ID_TEXT 来替代真实设备 ID
  • 移除之前对 alas 和模拟器的定时自动停止/中断逻辑,改为在演示模式下完全跳过模拟器启动,并记录日志
  • 在演示模式下,将 DEMO_DEVICE_ID_TEXT 用于日志容器的 CSS 变量
  • 即使在配置中启用了 OCR,也要在演示模式下阻止 OCR 服务启动
  • 在演示模式下,完全绕过受限设备阻断逻辑
module/webui/app.py
修改进程管理器在演示模式下的行为,以模拟日志并短路真实任务执行,同时将演示完成消息识别为正常的结束状态。
  • 在状态检测逻辑中,把包含演示消息('此版本为演示用途')的日志行视作正常运行/完成状态
  • DEMO=1 时,输出一段倒计时日志序列和最终的演示消息,而不是运行真实的 AzurLane 进程,然后提前返回
module/webui/process_manager.py

技巧和命令

与 Sourcery 交互

  • 触发新审阅: 在 Pull Request 中评论 @sourcery-ai review
  • 继续讨论: 直接回复 Sourcery 的审阅评论。
  • 从审阅评论生成 GitHub Issue: 在某条审阅评论下回复,请求 Sourcery 从该评论创建一个 Issue。你也可以在该评论下回复 @sourcery-ai issue 来创建 Issue。
  • 生成 Pull Request 标题: 在 Pull Request 标题的任意位置写上 @sourcery-ai 即可随时生成标题。你也可以在 Pull Request 中评论 @sourcery-ai title 来(重新)生成标题。
  • 生成 Pull Request 摘要: 在 Pull Request 正文的任意位置写上 @sourcery-ai summary,即可在相应位置生成 PR 摘要。你也可以在 Pull Request 中评论 @sourcery-ai summary 来(重新)生成摘要。
  • 生成审阅者指南: 在 Pull Request 中评论 @sourcery-ai guide,即可随时(重新)生成审阅者指南。
  • 解决所有 Sourcery 评论: 在 Pull Request 中评论 @sourcery-ai resolve 来解决所有 Sourcery 评论。如果你已经处理了所有评论且不想再看到它们,这会很有用。
  • 撤销所有 Sourcery 审阅: 在 Pull Request 中评论 @sourcery-ai dismiss 来撤销所有现有的 Sourcery 审阅。如果你想从头开始进行一次新的审阅,这尤其有用——别忘了再评论 @sourcery-ai review 来触发新的审阅!

自定义你的使用体验

访问你的 控制面板 以:

  • 启用或禁用审阅功能,例如 Sourcery 生成的 Pull Request 摘要、审阅者指南等。
  • 更改审阅语言。
  • 添加、移除或编辑自定义审阅说明。
  • 调整其他审阅设置。

获取帮助

Original review guide in English

Reviewer's Guide

This PR introduces a demo mode controlled by the DEMO=1 environment variable that disables live preview/control, avoids starting heavy services (simulator, OCR server, device restriction checks), and replaces real device IDs and process behavior with demo-safe messages and flow.

Flow diagram for demo mode behavior gating in web UI

flowchart TD
    DEMO_env[DEMO=1 environment] --> is_demo_mode

    is_demo_mode -->|true| ws_live_screenshot
    is_demo_mode -->|true| ws_live_control
    is_demo_mode -->|true| simulator_start
    is_demo_mode -->|true| ocr_server_start
    is_demo_mode -->|true| demo_device_id
    is_demo_mode -->|true| demo_run_process

    ws_live_screenshot[[ws_live_screenshot]] --> disabled_preview[Send error and close websocket]
    ws_live_control[[ws_live_control]] --> disabled_control[Send error and close websocket]
    simulator_start[[WebUI._simulator_start]] --> skip_simulator[Skip simulator.start]
    ocr_server_start[[startup start_ocr_server_process]] --> skip_ocr[Do not start OCR server]
    demo_device_id[[get_device_id in UI]] --> use_demo_text[Use DEMO_DEVICE_ID_TEXT]
    demo_run_process[[run_process]] --> demo_logs[Log countdown and exit]

    is_demo_mode -->|false| normal_flow[Normal behavior for all components]
Loading

File-Level Changes

Change Details Files
Introduce a shared demo-mode flag and apply it to WebSocket endpoints to disable live screenshot and control in demo mode.
  • Add is_demo_mode helper in api module based on DEMO environment variable
  • Short-circuit ws_live_screenshot when in demo mode, sending an error message then closing the WebSocket
  • Short-circuit ws_live_control when in demo mode, sending an error message then closing the WebSocket
module/webui/api.py
Adjust web UI behavior in demo mode by masking device IDs, skipping simulator/OCR startup, and relaxing device restriction checks.
  • Define DEMO_DEVICE_ID_TEXT for displaying a demo-specific device identifier text
  • Use DEMO_DEVICE_ID_TEXT instead of the real device ID in DropRecord group when in demo mode
  • Remove the previous timed auto-stop/interrupt for alas and simulator and instead skip simulator startup entirely in demo mode with a log message
  • Use DEMO_DEVICE_ID_TEXT in the log container CSS variable when in demo mode
  • Prevent OCR server startup when in demo mode even if enabled in config
  • Bypass restricted device blocking logic entirely when in demo mode
module/webui/app.py
Modify process manager behavior in demo mode to simulate logs and short-circuit real task execution while recognizing the demo completion message as a normal finish state.
  • Treat a log line containing the demo message ('此版本为演示用途') as a normal running/finished state in state detection logic
  • When DEMO=1, emit a countdown log sequence and a final demo message instead of running the real AzurLane process, then return early
module/webui/process_manager.py

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@gemini-code-assist gemini-code-assist 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.

Code Review

This pull request introduces a demo mode (DEMO=1) to restrict features like live screenshots, live controls, simulator startup, and OCR server processes, while displaying a placeholder device ID. The review feedback highlights a potential race condition in ProcessManager where the log queue handler thread might terminate before processing the final demo log message, and suggests deduplicating the is_demo_mode() helper function by centralizing it in a shared utility module.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

if update_tail_hit:
return 4
return 2
elif "此版本为演示用途" in s:

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.

high

这里存在一个潜在的竞争条件(Race Condition)。在 ProcessManager 中,_thread_log_queue_handler 线程是通过 while self.alive 循环来读取日志队列的。\n\n当子进程在 run_process 中执行完 logger.info("此版本为演示用途") 并执行 return 退出后,self.alive 会立即变为 False。这可能导致 _thread_log_queue_handler 线程在还没来得及从队列中读取最后这条日志时就终止了循环,从而导致 "此版本为演示用途" 无法被追加到 self.renderables 中。\n\n如果发生这种情况,state 将无法匹配到该关键字,进而错误地返回状态 3(异常/警告)而不是 2(未运行)。\n\n建议:\n在 _thread_log_queue_handler 退出 while self.alive 循环后,增加一个清空队列中剩余日志的逻辑。例如:\npython\n# 在 while self.alive 循环结束后\nwhile not self._renderable_queue.empty():\n try:\n log = self._renderable_queue.get_nowait()\n self.renderables.append(log)\n except queue.Empty:\n break\n\n由于 _thread_log_queue_handler 的定义不在当前 diff 中,请在对应位置手动进行修复。

Comment thread module/webui/api.py
Comment on lines 27 to +32
from module.config.utils import DEFAULT_CONFIG_NAME


def is_demo_mode():
return os.environ.get("DEMO") == "1"

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.

medium

module/webui/api.pymodule/webui/app.py 中都重复定义了 is_demo_mode() 函数。此外,在 process_manager.pyapp.py(如第 5095 行)以及 config.py 中仍然直接使用了 os.environ.get("DEMO") == "1"。\n\n为了提高代码的可维护性和一致性,建议将 is_demo_mode() 统一移动到公共工具模块(例如 module/config/utils.py,该模块已被这些文件广泛导入),并在所有相关地方统一调用。

Suggested change
from module.config.utils import DEFAULT_CONFIG_NAME
def is_demo_mode():
return os.environ.get("DEMO") == "1"
from module.config.utils import DEFAULT_CONFIG_NAME, is_demo_mode

@sourcery-ai sourcery-ai 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.

Hey - 我发现了两个问题,并提供了一些整体反馈:

  • 当前在多个位置(webui/api.pywebui/app.pyprocess_manager.py)都实现了演示模式检查,而且使用的模式略有不同;建议将 is_demo_mode()(以及 DEMO 环境变量相关逻辑)集中到一个共享的工具函数中,以避免行为偏差,并让后续修改更安全。
  • DEMO_DEVICE_ID_TEXT 和用于结束演示的日志字符串使用了不同的硬编码文案来表示演示模式;建议为演示识别相关的字符串定义一个统一的常量(或常量集合),以保持 UI 与进程管理器中的检查逻辑一致。
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- 当前在多个位置(`webui/api.py``webui/app.py``process_manager.py`)都实现了演示模式检查,而且使用的模式略有不同;建议将 `is_demo_mode()`(以及 `DEMO` 环境变量相关逻辑)集中到一个共享的工具函数中,以避免行为偏差,并让后续修改更安全。
- `DEMO_DEVICE_ID_TEXT` 和用于结束演示的日志字符串使用了不同的硬编码文案来表示演示模式;建议为演示识别相关的字符串定义一个统一的常量(或常量集合),以保持 UI 与进程管理器中的检查逻辑一致。

## Individual Comments

### Comment 1
<location path="module/webui/process_manager.py" line_range="183-182" />
<code_context>
                 if update_tail_hit:
                     return 4
                 return 2
+            elif "此版本为演示用途" in s:
+                return 2
             elif update_tail_hit:
                 return 4
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 与特定日志消息字符串的紧密耦合可能会比较脆弱。

这个条件依赖日志中的字面子串 "此版本为演示用途",将行为绑定到一个面向用户的本地化文案上,而这些文案可能会发生变化(文案修改、国际化、重写等)。相较于匹配具体的消息文本,更推荐使用结构化且稳定的信号(例如专门的非本地化标签/前缀或日志中的机器可读标记)。

建议实现方式:

```python
            elif DEMO_LOG_MARKER in s:
                return 2

```

```python
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":

```

`) 要求所有产生与演示相关日志的代码都包含这个标记。

以下是具体修改:

<file_operations>
<file_operation operation="edit" file_path="module/webui/process_manager.py">
<<<<<<< SEARCH
            elif "此版本为演示用途" in s:
                return 2
=======
            elif DEMO_LOG_MARKER in s:
                return 2
>>>>>>> REPLACE

<<<<<<< SEARCH
        set_func_logger(func=q.put)

        if os.environ.get("DEMO") == "1":
=======
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>
1. 在产生该日志行的地方(原来包含 `"此版本为演示用途"` 的那一行),以一种稳定的方式在日志信息中前置或插入 `DEMO_LOG_MARKER` 字符串 `"[DEMO_MODE]"`(例如:`" [DEMO_MODE] 此版本为演示用途..."`)。
2. 如果存在多条与演示相关的日志消息,建议统一使用同一个标记,以简化消费端逻辑。
3. 如果你更偏好通过配置而不是硬编码标记,后续可以将 `DEMO_LOG_MARKER` 重构为模块级常量或配置项,但仍需保持其非本地化且稳定。
</issue_to_address>

### Comment 2
<location path="module/webui/process_manager.py" line_range="235-242" />
<code_context>

     def _alas_start(self):
         self.alas.start(None, updater.event)
-        if os.environ.get("DEMO") == "1":
-            threading.Timer(5, self.alas.stop).start()

</code_context>
<issue_to_address>
**suggestion:** 演示模式检测是临时实现的,而不是通过共享的辅助函数来完成。

其他模块使用 `is_demo_mode()` 辅助函数,而这个文件则直接读取 `os.environ.get("DEMO") == "1"`。为了在将来修改演示模式逻辑时(例如添加额外条件或配置)避免行为出现偏差,请在这里复用共享辅助函数,或者引入一个小的本地辅助函数并委托给它。

建议实现方式:

```python
        set_func_logger(func=q.put)


        if is_demo_mode():
            logger.info("Log3")
            time.sleep(1)
            logger.info("Log2")
            time.sleep(1)
            logger.info("Log1")
            time.sleep(1)
            logger.info("此版本为演示用途")
            return

```

1. 确保在 `module/webui/process_manager.py` 顶部从其他模块使用的相同位置导入 `is_demo_mode`(例如 `from module.webui.utils import is_demo_mode` 或等价路径)。
2. 如果该文件中还有其他地方直接读取 `os.environ.get("DEMO")`,也请更新为使用 `is_demo_mode()` 以保持行为一致。
</issue_to_address>

Sourcery 对开源项目免费——如果你觉得我们的代码审查有帮助,请考虑分享它 ✨
帮我变得更有用!请在每条评论上点击 👍 或 👎,我会根据你的反馈改进后续的代码审查。
Original comment in English

Hey - I've found 2 issues, and left some high level feedback:

  • The demo-mode check is implemented in multiple places (webui/api.py, webui/app.py, process_manager.py) with slightly different patterns; consider centralizing is_demo_mode() (and the DEMO env logic) in a shared utility to avoid drift and make future changes safer.
  • DEMO_DEVICE_ID_TEXT and the demo termination log string use different hardcoded messages to indicate demo mode; consider defining a single shared constant (or constants) for demo-identification strings to keep UI and process-manager checks aligned.
Prompt for AI Agents
Please address the comments from this code review:

## Overall Comments
- The demo-mode check is implemented in multiple places (`webui/api.py`, `webui/app.py`, `process_manager.py`) with slightly different patterns; consider centralizing `is_demo_mode()` (and the `DEMO` env logic) in a shared utility to avoid drift and make future changes safer.
- `DEMO_DEVICE_ID_TEXT` and the demo termination log string use different hardcoded messages to indicate demo mode; consider defining a single shared constant (or constants) for demo-identification strings to keep UI and process-manager checks aligned.

## Individual Comments

### Comment 1
<location path="module/webui/process_manager.py" line_range="183-182" />
<code_context>
                 if update_tail_hit:
                     return 4
                 return 2
+            elif "此版本为演示用途" in s:
+                return 2
             elif update_tail_hit:
                 return 4
</code_context>
<issue_to_address>
**suggestion (bug_risk):** Tight coupling to a specific log message string may be brittle.

This condition depends on the literal substring "此版本为演示用途" in the log, tying behavior to a localized, human-facing message that may change (copy edits, i18n, rewording). Prefer a structured, stable signal (e.g., a dedicated non-localized tag/prefix or machine-readable marker in the log) instead of matching the exact message text.

Suggested implementation:

```python
            elif DEMO_LOG_MARKER in s:
                return 2

```

```python
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":

```

`) that any demo-related log producers include this marker.

Here are the concrete edits:

<file_operations>
<file_operation operation="edit" file_path="module/webui/process_manager.py">
<<<<<<< SEARCH
            elif "此版本为演示用途" in s:
                return 2
=======
            elif DEMO_LOG_MARKER in s:
                return 2
>>>>>>> REPLACE

<<<<<<< SEARCH
        set_func_logger(func=q.put)

        if os.environ.get("DEMO") == "1":
=======
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":
>>>>>>> REPLACE
</file_operation>
</file_operations>

<additional_changes>
1. Wherever this log line is produced (the one that previously contained `"此版本为演示用途"`), prepend or inject the `DEMO_LOG_MARKER` string `"[DEMO_MODE]"` into the log message in a stable way (e.g. `" [DEMO_MODE] 此版本为演示用途..."`).
2. If there are multiple demo-related messages, standardize on using this same marker for all of them to keep the consumer logic simple.
3. If you prefer configuration over a hardcoded marker, you can later refactor `DEMO_LOG_MARKER` into a module-level constant or configuration setting, but keep it non-localized and stable.
</issue_to_address>

### Comment 2
<location path="module/webui/process_manager.py" line_range="235-242" />
<code_context>

     def _alas_start(self):
         self.alas.start(None, updater.event)
-        if os.environ.get("DEMO") == "1":
-            threading.Timer(5, self.alas.stop).start()

</code_context>
<issue_to_address>
**suggestion:** Demo-mode detection is implemented ad hoc instead of using a shared helper.

Other modules use an `is_demo_mode()` helper, while this file reads `os.environ.get("DEMO") == "1"` directly. To avoid future behavior drift if demo-mode logic changes (e.g., extra conditions or config), please reuse the shared helper here or introduce a small local helper that delegates to it.

Suggested implementation:

```python
        set_func_logger(func=q.put)


        if is_demo_mode():
            logger.info("Log3")
            time.sleep(1)
            logger.info("Log2")
            time.sleep(1)
            logger.info("Log1")
            time.sleep(1)
            logger.info("此版本为演示用途")
            return

```

1. Ensure `is_demo_mode` is imported at the top of `module/webui/process_manager.py` from the same place other modules use (e.g., `from module.webui.utils import is_demo_mode` or equivalent).
2. If there are other direct reads of `os.environ.get("DEMO")` in this file, update them to use `is_demo_mode()` as well to keep behavior consistent.
</issue_to_address>

Sourcery is free for open source - if you like our reviews please consider sharing them ✨
Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.

@@ -180,6 +180,8 @@ def state(self) -> int:
if update_tail_hit:
return 4
return 2

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion (bug_risk): 与特定日志消息字符串的紧密耦合可能会比较脆弱。

这个条件依赖日志中的字面子串 "此版本为演示用途",将行为绑定到一个面向用户的本地化文案上,而这些文案可能会发生变化(文案修改、国际化、重写等)。相较于匹配具体的消息文本,更推荐使用结构化且稳定的信号(例如专门的非本地化标签/前缀或日志中的机器可读标记)。

建议实现方式:

            elif DEMO_LOG_MARKER in s:
                return 2
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":

`) 要求所有产生与演示相关日志的代码都包含这个标记。

以下是具体修改:

<file_operations>
<file_operation operation="edit" file_path="module/webui/process_manager.py">
<<<<<<< SEARCH
elif "此版本为演示用途" in s:
return 2

        elif DEMO_LOG_MARKER in s:
            return 2

REPLACE

<<<<<<< SEARCH
set_func_logger(func=q.put)

    if os.environ.get("DEMO") == "1":

=======
set_func_logger(func=q.put)

    DEMO_LOG_MARKER = "[DEMO_MODE]"

    if os.environ.get("DEMO") == "1":

REPLACE
</file_operation>
</file_operations>

<additional_changes>

  1. 在产生该日志行的地方(原来包含 "此版本为演示用途" 的那一行),以一种稳定的方式在日志信息中前置或插入 DEMO_LOG_MARKER 字符串 "[DEMO_MODE]"(例如:" [DEMO_MODE] 此版本为演示用途...")。
  2. 如果存在多条与演示相关的日志消息,建议统一使用同一个标记,以简化消费端逻辑。
  3. 如果你更偏好通过配置而不是硬编码标记,后续可以将 DEMO_LOG_MARKER 重构为模块级常量或配置项,但仍需保持其非本地化且稳定。
Original comment in English

suggestion (bug_risk): Tight coupling to a specific log message string may be brittle.

This condition depends on the literal substring "此版本为演示用途" in the log, tying behavior to a localized, human-facing message that may change (copy edits, i18n, rewording). Prefer a structured, stable signal (e.g., a dedicated non-localized tag/prefix or machine-readable marker in the log) instead of matching the exact message text.

Suggested implementation:

            elif DEMO_LOG_MARKER in s:
                return 2
        set_func_logger(func=q.put)

        DEMO_LOG_MARKER = "[DEMO_MODE]"

        if os.environ.get("DEMO") == "1":

`) that any demo-related log producers include this marker.

Here are the concrete edits:

<file_operations>
<file_operation operation="edit" file_path="module/webui/process_manager.py">
<<<<<<< SEARCH
elif "此版本为演示用途" in s:
return 2

        elif DEMO_LOG_MARKER in s:
            return 2

REPLACE

<<<<<<< SEARCH
set_func_logger(func=q.put)

    if os.environ.get("DEMO") == "1":

=======
set_func_logger(func=q.put)

    DEMO_LOG_MARKER = "[DEMO_MODE]"

    if os.environ.get("DEMO") == "1":

REPLACE
</file_operation>
</file_operations>

<additional_changes>

  1. Wherever this log line is produced (the one that previously contained "此版本为演示用途"), prepend or inject the DEMO_LOG_MARKER string "[DEMO_MODE]" into the log message in a stable way (e.g. " [DEMO_MODE] 此版本为演示用途...").
  2. If there are multiple demo-related messages, standardize on using this same marker for all of them to keep the consumer logic simple.
  3. If you prefer configuration over a hardcoded marker, you can later refactor DEMO_LOG_MARKER into a module-level constant or configuration setting, but keep it non-localized and stable.

Comment on lines +235 to +242
if os.environ.get("DEMO") == "1":
logger.info("Log3")
time.sleep(1)
logger.info("Log2")
time.sleep(1)
logger.info("Log1")
time.sleep(1)
logger.info("此版本为演示用途")

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

suggestion: 演示模式检测是临时实现的,而不是通过共享的辅助函数来完成。

其他模块使用 is_demo_mode() 辅助函数,而这个文件则直接读取 os.environ.get("DEMO") == "1"。为了在将来修改演示模式逻辑时(例如添加额外条件或配置)避免行为出现偏差,请在这里复用共享辅助函数,或者引入一个小的本地辅助函数并委托给它。

建议实现方式:

        set_func_logger(func=q.put)


        if is_demo_mode():
            logger.info("Log3")
            time.sleep(1)
            logger.info("Log2")
            time.sleep(1)
            logger.info("Log1")
            time.sleep(1)
            logger.info("此版本为演示用途")
            return
  1. 确保在 module/webui/process_manager.py 顶部从其他模块使用的相同位置导入 is_demo_mode(例如 from module.webui.utils import is_demo_mode 或等价路径)。
  2. 如果该文件中还有其他地方直接读取 os.environ.get("DEMO"),也请更新为使用 is_demo_mode() 以保持行为一致。
Original comment in English

suggestion: Demo-mode detection is implemented ad hoc instead of using a shared helper.

Other modules use an is_demo_mode() helper, while this file reads os.environ.get("DEMO") == "1" directly. To avoid future behavior drift if demo-mode logic changes (e.g., extra conditions or config), please reuse the shared helper here or introduce a small local helper that delegates to it.

Suggested implementation:

        set_func_logger(func=q.put)


        if is_demo_mode():
            logger.info("Log3")
            time.sleep(1)
            logger.info("Log2")
            time.sleep(1)
            logger.info("Log1")
            time.sleep(1)
            logger.info("此版本为演示用途")
            return
  1. Ensure is_demo_mode is imported at the top of module/webui/process_manager.py from the same place other modules use (e.g., from module.webui.utils import is_demo_mode or equivalent).
  2. If there are other direct reads of os.environ.get("DEMO") in this file, update them to use is_demo_mode() as well to keep behavior consistent.

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