refactor(resource): 统一资源管理、下载队列与多源回退 - #2638
Conversation
📝 Walkthrough新增(Added)
变更(Changed)
移除(Removed)
WalkthroughChanges统一资源下载与更新体系
Estimated code review effort: 5 (Critical) | ~120 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 2📝 Generate docstrings 💡
⚔️ Resolve merge conflicts 💡
🧪 Generate unit tests (beta)
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 |
There was a problem hiding this comment.
Actionable comments posted: 15
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.py (1)
21-37: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win为新增参数补充文档说明。
__init__新增了必填参数model_download_url,但文档字符串(Line 31-37)没有对应的:param说明。补充说明,保持文档与函数签名一致。📝 建议的修改
""" 崩铁用的YOLO模型 参考自 https://github.com/ibaiGorordo/ONNX-YOLOv8-Object-Detection :param model_name: 模型名称 在根目录下会有一个以模型名称创建的子文件夹 :param backup_model_name: 放置所有模型的根目录 + :param model_download_url: 模型下载根地址 :param gpu: 是否启用GPU运算 :param keep_result_seconds: 保留多长时间的识别结果 """As per path instructions, "注释应使用Google风格,函数职责较重时必须有注释".
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.py` around lines 21 - 37, 在 __init__ 的文档字符串中补充 model_download_url 参数的说明,明确其用途,并保持现有参数文档风格与函数签名一致。Source: Path instructions
src/one_dragon_qt/windows/main_app_window_base.py (1)
63-99: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win为新增成员变量补充类型注解。
self.download_queue(Line 64)和self.download_queue_dialog(Line 75)缺少类型注解。同一个__init__方法里,self._download_queue_tip(Line 76)和self.resource_update_coordinator(Line 77-85)都带有类型注解。为这两个变量补充类型注解,保持风格一致。🔧 建议的修改
- self.download_queue = DownloadQueueService(ctx) + self.download_queue: DownloadQueueService = DownloadQueueService(ctx)- self.download_queue_dialog = DownloadQueueDialog(self.download_queue, self) + self.download_queue_dialog: DownloadQueueDialog = DownloadQueueDialog(self.download_queue, self)As per coding guidelines, "
src/**/*.py: 项目使用 Python 3.11;所有函数签名和类成员变量都必须有类型注解".🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/windows/main_app_window_base.py` around lines 63 - 99, 为 __init__ 方法中的 self.download_queue 和 self.download_queue_dialog 补充类型注解,分别使用 DownloadQueueService 和 DownloadQueueDialog,与现有 self._download_queue_tip 及 self.resource_update_coordinator 的成员变量注解风格保持一致。Source: Coding guidelines
🧹 Nitpick comments (9)
src/one_dragon_qt/view/resource_management_interface.py (2)
444-470: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议为启动器类型提供公开访问方式。
第 446 行读取
self.launcher_opt._launcher_type,跨类访问私有属性。LauncherDownloadCard内部若重命名该属性,此处会静默失效。建议在LauncherDownloadCard上增加只读属性launcher_type,此处改用公开属性。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/view/resource_management_interface.py` around lines 444 - 470, 在 LauncherDownloadCard 中增加只读公开属性 launcher_type,用于返回内部的启动器类型;更新 _build_launcher_spec,改为读取 self.launcher_opt.launcher_type,避免直接访问私有属性 _launcher_type。
61-83: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win避免用
finished命名自定义线程信号。
FetchTotalRunner和FetchPageRunner覆盖QThread.finished后,PySide6 会把该名称解析为子类自定义信号,导致线程生命周期结束的QThread.finished无法被外部直接连接。如果当前连接都服务于结果回调,将信号改为result_ready,并更新两处finished.connect()调用;如果后续需要监听线程结束事件,避免覆盖同名信号或直接连接父类信号。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/view/resource_management_interface.py` around lines 61 - 83, Rename the custom finished signals in FetchTotalRunner and FetchPageRunner to result_ready, update their emit calls and both corresponding finished.connect() usages, and preserve QThread.finished for thread lifecycle notifications.src/one_dragon_qt/widgets/setting_card/common_download_card.py (2)
88-91: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议消除隐式
Optional注解。
extra_btn_list: list[QAbstractButton] = None使用了 PEP 484 禁止的隐式Optional。Ruff 报出 RUF013。项目规范要求使用X | Y现代联合语法。♻️ 建议修改
- extra_btn_list: list[QAbstractButton] = None, + extra_btn_list: list[QAbstractButton] | None = None,依据编码规范:“所有函数签名和类成员变量都必须有类型注解,并优先使用
list[str]、X | Y等现代语法。”Also applies to: 388-391
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py` around lines 88 - 91, Update the extra_btn_list annotations in the affected function signatures to explicitly allow None using modern union syntax, such as list[QAbstractButton] | None, while preserving the existing defaults and behavior.Sources: Coding guidelines, Linters/SAST tools
152-155: 🩺 Stability & Availability | 🔵 Trivial | ⚡ Quick win建议为 lambda 连接指定接收者,避免卡片销毁后的悬垂调用。
第 154 行连接的是 lambda。Qt 只在接收者是
QObject的绑定方法时自动断开连接。lambda 没有关联接收者,卡片销毁后服务信号仍会调用它,可能触发RuntimeError: Internal C++ object already deleted。建议改为绑定方法或传入self作为连接上下文。♻️ 建议方案
- service.task_removed.connect(lambda _task_key: self.check_and_update_display()) + service.task_removed.connect(self._on_queue_task_removed)并新增方法:
def _on_queue_task_removed(self, _task_key: str) -> None: """队列任务被移除时刷新卡片。""" self.check_and_update_display()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py` around lines 152 - 155, Replace the lambda connected to service.task_removed with a bound method on the card, adding _on_queue_task_removed(self, _task_key: str) to call check_and_update_display(). Keep the existing task-added and task-updated connections unchanged so the signal is associated with the card QObject and is disconnected safely on destruction.src/one_dragon_qt/widgets/download_card/launcher_download_card.py (1)
94-98: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议与父类保持参数名一致。
父类方法签名为
_get_downloader_param(self, index: int | None = None),此处覆写为_idx。如果后续有调用方使用index=关键字参数,覆写方法会抛TypeError。建议改名为index。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py` around lines 94 - 98, 将 LauncherDownloadCard 的 _get_downloader_param 方法参数从 _idx 重命名为 index,使覆写签名与父类一致并支持使用 index= 关键字调用;保持现有参数传递和返回逻辑不变。src/one_dragon_qt/view/source_config_interface.py (1)
20-22: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value两个视图文件都从弹窗模块导入
build_resource_source_options,形成视图对弹窗的依赖。 共同根因是这个纯配置转换函数被放在了widgets/resource_download_dialog.py中。建议把它移动到one_dragon/envs/repo_config.py或独立工具模块。
src/one_dragon_qt/view/source_config_interface.py#L20-L22:改为从新位置导入。src/one_dragon_qt/view/resource_management_interface.py#L44-L46:改为从新位置导入。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/view/source_config_interface.py` around lines 20 - 22, 将纯配置转换函数 build_resource_source_options 从弹窗模块移动到 one_dragon/envs/repo_config.py 或独立工具模块,并更新 src/one_dragon_qt/view/source_config_interface.py 的导入;同时更新 src/one_dragon_qt/view/resource_management_interface.py 的对应导入,使两个视图不再依赖 resource_download_dialog.py。src/zzz_od/yolo/flash_classifier.py (1)
19-24: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value两个 YOLO 封装类新增了必填参数
model_download_url,但 docstring 未同步。 共同根因是模型下载地址来源改为由调用方注入后,构造函数文档没有随之更新。
src/zzz_od/yolo/flash_classifier.py#L19-L24:补充:param model_download_url:说明。src/zzz_od/yolo/hollow_event_detector.py#L17-L23:补充:param model_download_url:说明,并删除已不存在的model_parent_dir_path参数说明。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/zzz_od/yolo/flash_classifier.py` around lines 19 - 24, Update the constructor docstrings for the YOLO wrapper classes: in src/zzz_od/yolo/flash_classifier.py lines 19-24, document the required model_download_url parameter; in src/zzz_od/yolo/hollow_event_detector.py lines 17-23, document model_download_url and remove the obsolete model_parent_dir_path entry.src/one_dragon_qt/widgets/resource_download_dialog.py (1)
76-76: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value改用
checkStateChanged以兼容当前 PySide6 签名规范。
PySide6依赖锁定在6.8.0.2,Qt 6.8 已将QCheckBox.stateChanged标记为弃用;同项目其他复选框已使用checkStateChanged。将此处连接改为checkStateChanged,并让_update_confirm_enabled接收PySide6.QtCore.Qt.CheckState值。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/resource_download_dialog.py` at line 76, 在资源下载对话框的复选框连接处,将 check.stateChanged 改为 check.checkStateChanged,以符合 PySide6 6.8 的签名规范;同时更新 _update_confirm_enabled,使其接收并正确处理 PySide6.QtCore.Qt.CheckState 值,保持确认按钮启用状态逻辑不变。src/one_dragon_qt/windows/window.py (1)
223-232: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value移除未使用的
downloadQueueButton动态属性。
downloadQueueButton的样式在title_bar.qss中仅通过对象名、状态和homeMode选择器定义,没有hasError相关选择器;failed > 0的颜色变化已由setStyleSheet直接控制。setProperty("hasError", ...)不会影响当前样式效果,可以移除。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/windows/window.py` around lines 223 - 232, Remove the unused setProperty("hasError", ...) call from set_download_queue_counts; retain the existing text updates and direct setStyleSheet color handling based on failed.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/one_dragon_qt/services/download_queue_service.py`:
- Around line 324-345: Update the progress-signal wiring in the worker-start
flow and _on_progress_changed so each callback carries and updates the task that
emitted it, rather than reading self._current_task at delivery time. Bind the
task object when connecting DownloadTaskWorker.progress_changed, preserve the
existing progress/state transitions, and emit task_updated for that bound task
even if _current_task has already advanced.
In `@src/one_dragon_qt/services/resource_update_coordinator.py`:
- Around line 325-336: Update the OCR request flow around `_on_task_updated` to
also listen for `queue.task_removed`, so removal of the matching task completes
the request immediately instead of waiting for the timeout. Reuse the existing
task-key matching, callback disconnection, and `_respond_ocr_request` logic,
returning a failure response for removed tasks while preserving terminal-state
success handling.
In `@src/one_dragon_qt/view/setting/setting_env_interface.py`:
- Around line 188-192: 在设置界面的初始化逻辑及相关可见性更新逻辑中,移除对 developer_mode_opt 自身的
setVisible 绑定,确保关闭开发者模式后该开关仍保持可见;保留 developer_mode 对
debug_opt、_on_developer_mode_changed() 和标题栏状态的刷新行为。
In `@src/one_dragon_qt/view/setting/setting_instance_interface.py`:
- Around line 231-236: 在 `_refresh_content_widget` 重建内容控件后立即调用
`_update_developer_visibility`,确保新建的 `custom_win_title_opt` 遵循当前开发者模式。移除
`_update_developer_visibility` 中多余的 `hasattr` 判断,直接更新已在 `get_content_widget`
阶段创建的控件可见性。
In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py`:
- Around line 35-39: Update the run method to catch exceptions from
update_service.get_launcher_version_info, log the failure using the imported
one_dragon.utils.log_utils.log, and emit check_finished with safe fallback
version values in the exception path so the UI exits its checking state and
remains usable.
In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py`:
- Around line 173-176: Update the ResourceDownloadTaskState.WAITING branch in
the download card state handling to display “等待中” instead of “下载中”, matching
DownloadQueueDialog while preserving the existing enabled-button behavior and
return value.
- Around line 157-166: 缓存由 download_spec_factory 生成的 task_key,避免 _get_queue_task
在高频 _on_queue_task_changed 刷新中重复构造规格;在 __init__ 初始化 _cached_task_key,并在
on_index_changed 及下载类型切换时将其重置为 None,确保选项变化后重新生成规格,其他情况下复用缓存键查询队列任务。
In `@src/one_dragon/base/config/basic_model_config.py`:
- Around line 62-76: 更新
BasicModelConfig.get_model_download_base_url,移除默认固定为“github”的行为;当调用方未提供
source_id 时,按 EnvConfig.get_resource_source_order() 的候选顺序解析并返回第一个可用下载地址,同时保留显式
source_id 的现有查询与未配置时的 ValueError 行为。
In `@src/one_dragon/base/matcher/ocr/ocr_matcher.py`:
- Around line 31-39: Update the base OcrMatcher.init_model signature to accept
on_source_failure and fallback_on_slow, matching the keyword arguments passed by
one_dragon_context.init_ocr. Keep the existing parameter types and defaults
consistent with the concrete OnnxOcrMatcher implementation so injected
OcrMatcher subclasses conform to the shared interface.
In `@src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py`:
- Around line 22-40: 更新 get_ocr_download_urls,优先通过
RepoConfig.get_resource_asset_urls 获取 env 仓库对应模型压缩包的下载地址,使用与
update_service.get_launcher_download_param 一致的配置优先策略;仅在 RepoConfig 缺少相关配置时回退到
OCR_DOWNLOAD_URLS,保留现有返回结构并避免新增硬编码源列表。
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Around line 508-512: Update OnnxOcrMatcher.ocr() to lazily call init_model()
before accessing or using self._model, ensuring recognition remains safe when
init_ocr() skips model initialization after download cancellation. Preserve
existing behavior for already-loaded models and cover every public recognition
path through ocr().
- Around line 518-525: 同步 OcrMatcher.init_model 的接口与调用参数:在基类 init_model 签名中补充
on_source_failure 和 fallback_on_slow,并确保其他实现(包括 OnnxOcrMatcher)兼容并正确处理这两个参数,避免
self.ocr.init_model 调用触发 TypeError。
In `@src/one_dragon/envs/update_service.py`:
- Around line 176-185: Update _swap_launcher_backup so exceptions are re-raised
when backup=True, while retaining log-only handling for rollback operations;
ensure prepare_launcher_update propagates backup failures and
apply_staged_launcher_update does not replace the launcher unless backups
complete successfully.
In `@src/one_dragon/utils/http_utils.py`:
- Around line 143-144: 调整 http 下载流程中 opener.open 的 timeout 配置,避免 5
秒读超时使弱网或最后候选源在短暂无数据时失败;将读超时放宽至 15–30 秒,并继续由 min_bytes_per_second
负责低速下载淘汰,同时保持连接超时控制。
In `@src/zzz_od/gui/app.py`:
- Around line 256-260: 为 closeEvent 方法的 event 参数添加 QCloseEvent 类型注解,并将返回类型标注为
None;确认从 PySide6.QtGui 导入 QCloseEvent,保持现有关闭事件处理逻辑不变。
---
Outside diff comments:
In `@src/one_dragon_qt/windows/main_app_window_base.py`:
- Around line 63-99: 为 __init__ 方法中的 self.download_queue 和
self.download_queue_dialog 补充类型注解,分别使用 DownloadQueueService 和
DownloadQueueDialog,与现有 self._download_queue_tip 及
self.resource_update_coordinator 的成员变量注解风格保持一致。
In `@src/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.py`:
- Around line 21-37: 在 __init__ 的文档字符串中补充 model_download_url
参数的说明,明确其用途,并保持现有参数文档风格与函数签名一致。
---
Nitpick comments:
In `@src/one_dragon_qt/view/resource_management_interface.py`:
- Around line 444-470: 在 LauncherDownloadCard 中增加只读公开属性
launcher_type,用于返回内部的启动器类型;更新 _build_launcher_spec,改为读取
self.launcher_opt.launcher_type,避免直接访问私有属性 _launcher_type。
- Around line 61-83: Rename the custom finished signals in FetchTotalRunner and
FetchPageRunner to result_ready, update their emit calls and both corresponding
finished.connect() usages, and preserve QThread.finished for thread lifecycle
notifications.
In `@src/one_dragon_qt/view/source_config_interface.py`:
- Around line 20-22: 将纯配置转换函数 build_resource_source_options 从弹窗模块移动到
one_dragon/envs/repo_config.py 或独立工具模块,并更新
src/one_dragon_qt/view/source_config_interface.py 的导入;同时更新
src/one_dragon_qt/view/resource_management_interface.py 的对应导入,使两个视图不再依赖
resource_download_dialog.py。
In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py`:
- Around line 94-98: 将 LauncherDownloadCard 的 _get_downloader_param 方法参数从 _idx
重命名为 index,使覆写签名与父类一致并支持使用 index= 关键字调用;保持现有参数传递和返回逻辑不变。
In `@src/one_dragon_qt/widgets/resource_download_dialog.py`:
- Line 76: 在资源下载对话框的复选框连接处,将 check.stateChanged 改为 check.checkStateChanged,以符合
PySide6 6.8 的签名规范;同时更新 _update_confirm_enabled,使其接收并正确处理
PySide6.QtCore.Qt.CheckState 值,保持确认按钮启用状态逻辑不变。
In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py`:
- Around line 88-91: Update the extra_btn_list annotations in the affected
function signatures to explicitly allow None using modern union syntax, such as
list[QAbstractButton] | None, while preserving the existing defaults and
behavior.
- Around line 152-155: Replace the lambda connected to service.task_removed with
a bound method on the card, adding _on_queue_task_removed(self, _task_key: str)
to call check_and_update_display(). Keep the existing task-added and
task-updated connections unchanged so the signal is associated with the card
QObject and is disconnected safely on destruction.
In `@src/one_dragon_qt/windows/window.py`:
- Around line 223-232: Remove the unused setProperty("hasError", ...) call from
set_download_queue_counts; retain the existing text updates and direct
setStyleSheet color handling based on failed.
In `@src/zzz_od/yolo/flash_classifier.py`:
- Around line 19-24: Update the constructor docstrings for the YOLO wrapper
classes: in src/zzz_od/yolo/flash_classifier.py lines 19-24, document the
required model_download_url parameter; in
src/zzz_od/yolo/hollow_event_detector.py lines 17-23, document
model_download_url and remove the obsolete model_parent_dir_path entry.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 1321c745-2f93-4baf-bc6b-9e31957afe7d
📒 Files selected for processing (49)
config/repository.ymldeploy/module_manifest.pydocs/develop/README.mddocs/develop/one_dragon/modules/resource_download.mdsrc/one_dragon/base/config/basic_model_config.pysrc/one_dragon/base/matcher/ocr/ocr_matcher.pysrc/one_dragon/base/matcher/ocr/onnx_ocr_matcher.pysrc/one_dragon/base/operation/context_download_request_event.pysrc/one_dragon/base/operation/context_event_bus.pysrc/one_dragon/base/operation/one_dragon_context.pysrc/one_dragon/base/operation/one_dragon_env_context.pysrc/one_dragon/base/web/common_downloader.pysrc/one_dragon/base/web/zip_downloader.pysrc/one_dragon/envs/env_config.pysrc/one_dragon/envs/repo_config.pysrc/one_dragon/envs/update_service.pysrc/one_dragon/utils/http_utils.pysrc/one_dragon/yolo/yolo_utils.pysrc/one_dragon_qt/_rc/qss/dark/title_bar.qsssrc/one_dragon_qt/_rc/qss/light/title_bar.qsssrc/one_dragon_qt/_rc/resource.pysrc/one_dragon_qt/services/download_queue_service.pysrc/one_dragon_qt/services/resource_update_coordinator.pysrc/one_dragon_qt/view/code_interface.pysrc/one_dragon_qt/view/resource_management_interface.pysrc/one_dragon_qt/view/setting/resource_download_interface.pysrc/one_dragon_qt/view/setting/setting_env_interface.pysrc/one_dragon_qt/view/setting/setting_instance_interface.pysrc/one_dragon_qt/view/source_config_interface.pysrc/one_dragon_qt/widgets/download_card/launcher_download_card.pysrc/one_dragon_qt/widgets/download_queue_dialog.pysrc/one_dragon_qt/widgets/install_card/launcher_install_card.pysrc/one_dragon_qt/widgets/resource_download_dialog.pysrc/one_dragon_qt/widgets/setting_card/common_download_card.pysrc/one_dragon_qt/widgets/teaching_tip.pysrc/one_dragon_qt/windows/main_app_window_base.pysrc/one_dragon_qt/windows/window.pysrc/zzz_od/application/hollow_zero/lost_void/context/lost_void_context.pysrc/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.pysrc/zzz_od/auto_battle/auto_battle_dodge_context.pysrc/zzz_od/config/model_config.pysrc/zzz_od/context/zzz_context.pysrc/zzz_od/gui/app.pysrc/zzz_od/gui/view/home/home_interface.pysrc/zzz_od/gui/view/setting/app_setting_interface.pysrc/zzz_od/gui/view/setting/zzz_resource_download_interface.pysrc/zzz_od/hollow_zero/hollow_map/hollow_zero_map_service.pysrc/zzz_od/yolo/flash_classifier.pysrc/zzz_od/yolo/hollow_event_detector.py
💤 Files with no reviewable changes (6)
- src/one_dragon/yolo/yolo_utils.py
- src/one_dragon_qt/view/setting/resource_download_interface.py
- src/one_dragon_qt/view/code_interface.py
- src/zzz_od/gui/view/setting/app_setting_interface.py
- src/zzz_od/gui/view/setting/zzz_resource_download_interface.py
- src/zzz_od/config/model_config.py
| worker = DownloadTaskWorker(self.ctx, task) | ||
| worker.progress_changed.connect(self._on_progress_changed) | ||
| worker.task_finished.connect(self._store_worker_result) | ||
| worker.finished.connect(self._on_worker_finished) | ||
| worker.finished.connect(worker.deleteLater) | ||
| self._worker = worker | ||
| self._worker_result = None | ||
| worker.start() | ||
|
|
||
| def _on_progress_changed(self, progress: ResourceDownloadProgress) -> None: | ||
| """保存当前任务进度。""" | ||
| task = self._current_task | ||
| if task is None: | ||
| return | ||
| task.progress = progress | ||
| if progress.phase == 'extracting': | ||
| task.state = ResourceDownloadTaskState.EXTRACTING | ||
| elif progress.phase == 'applying': | ||
| task.state = ResourceDownloadTaskState.APPLYING | ||
| elif task.state != ResourceDownloadTaskState.CANCELLING: | ||
| task.state = ResourceDownloadTaskState.DOWNLOADING | ||
| self.task_updated.emit(task) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
进度回调应绑定发出该进度的任务。
_on_progress_changed 使用 self._current_task,不使用信号来源任务。_on_worker_finished 在第 384 行立即调用 _start_next(),把 _current_task 切换为下一个任务。如果上一个 worker 仍有排队中的 progress_changed 事件,处理时会写入新任务的 progress,并把新任务状态改为 DOWNLOADING。下载器在多源回退时可能从其他线程调用 status_callback,此时事件顺序不受保证。
建议在连接时绑定任务对象。
🛠️ 建议修改
worker = DownloadTaskWorker(self.ctx, task)
- worker.progress_changed.connect(self._on_progress_changed)
+ worker.progress_changed.connect(
+ lambda progress, bound_task=task: self._on_progress_changed(bound_task, progress)
+ )
worker.task_finished.connect(self._store_worker_result)- def _on_progress_changed(self, progress: ResourceDownloadProgress) -> None:
- """保存当前任务进度。"""
- task = self._current_task
- if task is None:
+ def _on_progress_changed(
+ self,
+ task: ResourceDownloadTask,
+ progress: ResourceDownloadProgress,
+ ) -> None:
+ """保存指定任务的进度。"""
+ if task is not self._current_task:
return📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| worker = DownloadTaskWorker(self.ctx, task) | |
| worker.progress_changed.connect(self._on_progress_changed) | |
| worker.task_finished.connect(self._store_worker_result) | |
| worker.finished.connect(self._on_worker_finished) | |
| worker.finished.connect(worker.deleteLater) | |
| self._worker = worker | |
| self._worker_result = None | |
| worker.start() | |
| def _on_progress_changed(self, progress: ResourceDownloadProgress) -> None: | |
| """保存当前任务进度。""" | |
| task = self._current_task | |
| if task is None: | |
| return | |
| task.progress = progress | |
| if progress.phase == 'extracting': | |
| task.state = ResourceDownloadTaskState.EXTRACTING | |
| elif progress.phase == 'applying': | |
| task.state = ResourceDownloadTaskState.APPLYING | |
| elif task.state != ResourceDownloadTaskState.CANCELLING: | |
| task.state = ResourceDownloadTaskState.DOWNLOADING | |
| self.task_updated.emit(task) | |
| worker = DownloadTaskWorker(self.ctx, task) | |
| worker.progress_changed.connect( | |
| lambda progress, bound_task=task: self._on_progress_changed(bound_task, progress) | |
| ) | |
| worker.task_finished.connect(self._store_worker_result) | |
| worker.finished.connect(self._on_worker_finished) | |
| worker.finished.connect(worker.deleteLater) | |
| self._worker = worker | |
| self._worker_result = None | |
| worker.start() | |
| def _on_progress_changed( | |
| self, | |
| task: ResourceDownloadTask, | |
| progress: ResourceDownloadProgress, | |
| ) -> None: | |
| """保存指定任务的进度。""" | |
| if task is not self._current_task: | |
| return | |
| task.progress = progress | |
| if progress.phase == 'extracting': | |
| task.state = ResourceDownloadTaskState.EXTRACTING | |
| elif progress.phase == 'applying': | |
| task.state = ResourceDownloadTaskState.APPLYING | |
| elif task.state != ResourceDownloadTaskState.CANCELLING: | |
| task.state = ResourceDownloadTaskState.DOWNLOADING | |
| self.task_updated.emit(task) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon_qt/services/download_queue_service.py` around lines 324 - 345,
Update the progress-signal wiring in the worker-start flow and
_on_progress_changed so each callback carries and updates the task that emitted
it, rather than reading self._current_task at delivery time. Bind the task
object when connecting DownloadTaskWorker.progress_changed, preserve the
existing progress/state transitions, and emit task_updated for that bound task
even if _current_task has already advanced.
| def _on_task_updated(updated: ResourceDownloadTask) -> None: | ||
| if updated.task_key != task.task_key or updated.state not in terminal_states: | ||
| return | ||
| with contextlib.suppress(RuntimeError): | ||
| self.queue.task_updated.disconnect(_on_task_updated) | ||
| self._respond_ocr_request( | ||
| request, | ||
| updated.state == ResourceDownloadTaskState.SUCCEEDED, | ||
| remember, | ||
| ) | ||
|
|
||
| self.queue.task_updated.connect(_on_task_updated) |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
任务被移出队列时 OCR 请求不会得到应答。
_on_task_updated 只监听 task_updated。DownloadQueueService.remove 移除处于 WAITING 状态的任务时只发出 task_removed,不发出 task_updated。此时该闭包保持连接,后端线程必须等到 300 秒超时才继续。建议同时监听 task_removed。
🛠️ 建议修改
def _on_task_updated(updated: ResourceDownloadTask) -> None:
if updated.task_key != task.task_key or updated.state not in terminal_states:
return
+ _disconnect()
+ self._respond_ocr_request(
+ request,
+ updated.state == ResourceDownloadTaskState.SUCCEEDED,
+ remember,
+ )
+
+ def _on_task_removed(removed_key: str) -> None:
+ if removed_key != task.task_key:
+ return
+ _disconnect()
+ self._respond_ocr_request(request, False, remember)
+
+ def _disconnect() -> None:
with contextlib.suppress(RuntimeError):
self.queue.task_updated.disconnect(_on_task_updated)
- self._respond_ocr_request(
- request,
- updated.state == ResourceDownloadTaskState.SUCCEEDED,
- remember,
- )
+ with contextlib.suppress(RuntimeError):
+ self.queue.task_removed.disconnect(_on_task_removed)
self.queue.task_updated.connect(_on_task_updated)
+ self.queue.task_removed.connect(_on_task_removed)📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| def _on_task_updated(updated: ResourceDownloadTask) -> None: | |
| if updated.task_key != task.task_key or updated.state not in terminal_states: | |
| return | |
| with contextlib.suppress(RuntimeError): | |
| self.queue.task_updated.disconnect(_on_task_updated) | |
| self._respond_ocr_request( | |
| request, | |
| updated.state == ResourceDownloadTaskState.SUCCEEDED, | |
| remember, | |
| ) | |
| self.queue.task_updated.connect(_on_task_updated) | |
| def _on_task_updated(updated: ResourceDownloadTask) -> None: | |
| if updated.task_key != task.task_key or updated.state not in terminal_states: | |
| return | |
| _disconnect() | |
| self._respond_ocr_request( | |
| request, | |
| updated.state == ResourceDownloadTaskState.SUCCEEDED, | |
| remember, | |
| ) | |
| def _on_task_removed(removed_key: str) -> None: | |
| if removed_key != task.task_key: | |
| return | |
| _disconnect() | |
| self._respond_ocr_request(request, False, remember) | |
| def _disconnect() -> None: | |
| with contextlib.suppress(RuntimeError): | |
| self.queue.task_updated.disconnect(_on_task_updated) | |
| with contextlib.suppress(RuntimeError): | |
| self.queue.task_removed.disconnect(_on_task_removed) | |
| self.queue.task_updated.connect(_on_task_updated) | |
| self.queue.task_removed.connect(_on_task_removed) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon_qt/services/resource_update_coordinator.py` around lines 325 -
336, Update the OCR request flow around `_on_task_updated` to also listen for
`queue.task_removed`, so removal of the matching task completes the request
immediately instead of waiting for the timeout. Reuse the existing task-key
matching, callback disconnection, and `_respond_ocr_request` logic, returning a
failure response for removed tasks while preserving terminal-state success
handling.
| try: | ||
| self.prepare_launcher_update(launcher_type) | ||
| staged_exe.replace(work_dir / staged_exe.name) | ||
| if launcher_type == 'runtime': | ||
| staged_runtime.rename(work_dir / RUNTIME_DIR) | ||
| self.finish_launcher_update(launcher_type, True) | ||
| shutil.rmtree(staging_dir, ignore_errors=True) | ||
| except Exception: | ||
| self.finish_launcher_update(launcher_type, False) | ||
| raise |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift
备份失败时仍会继续替换启动器。
_swap_launcher_backup 在第 227-228 行和第 244-245 行捕获异常后只写日志,不向上抛出。因此 prepare_launcher_update 在备份 exe 或 .runtime 目录失败时也会正常返回。随后 apply_staged_launcher_update 继续执行替换。如果后续步骤失败,finish_launcher_update(launcher_type, False) 找不到可用备份,用户会同时失去旧版本和新版本。
建议让备份阶段的失败可被感知:_swap_launcher_backup 在 backup=True 时抛出异常,回滚路径继续保持只记录日志。
🛠️ 参考修改方向
def _swap_launcher_backup(self, launcher_type: LauncherType, backup: bool) -> None:
- """备份或回滚启动器文件。"""
+ """备份或回滚启动器文件。备份失败时抛出异常,回滚失败时仅记录日志。"""
work_dir = Path(os_utils.get_work_dir())
action = '备份' if backup else '回滚'
@@
except Exception as e:
log.error(f'{action}文件失败 {source_path.name}: {e}')
+ if backup:
+ raise🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon/envs/update_service.py` around lines 176 - 185, Update
_swap_launcher_backup so exceptions are re-raised when backup=True, while
retaining log-only handling for rollback operations; ensure
prepare_launcher_update propagates backup failures and
apply_staged_launcher_update does not replace the launcher unless backups
complete successfully.
| # 读超时保持较短,避免网络停滞时取消请求长时间无响应。 | ||
| with opener.open(request, timeout=5) as response: |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win
请确认 5 秒读超时不会让慢速网络用户无法完成下载。
opener.open(request, timeout=5) 同时作为连接超时和 socket 读超时。设计文档 docs/develop/one_dragon/modules/resource_download.md 第 67 行说明“最后一个候选源不限速,避免慢网络完全无法下载”。但 5 秒读超时不受 min_bytes_per_second 控制,对最后一个候选源同样生效。若某次 response.read() 在 5 秒内没有返回任何字节,下载会直接失败,即使整体速率尚可接受。
请确认该取值在弱网环境下经过验证,或考虑把读超时放宽到 15–30 秒,仅依赖 min_bytes_per_second 做低速淘汰。
🧰 Tools
🪛 Ruff (0.16.0)
[warning] 143-143: Comment contains ambiguous , (FULLWIDTH COMMA). Did you mean , (COMMA)?
(RUF003)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon/utils/http_utils.py` around lines 143 - 144, 调整 http 下载流程中
opener.open 的 timeout 配置,避免 5 秒读超时使弱网或最后候选源在短暂无数据时失败;将读超时放宽至 15–30 秒,并继续由
min_bytes_per_second 负责低速下载淘汰,同时保持连接超时控制。
028807c to
44ccef6
Compare
There was a problem hiding this comment.
Actionable comments posted: 5
♻️ Duplicate comments (4)
src/one_dragon/base/operation/one_dragon_context.py (2)
518-525: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
OcrMatcher.init_model基类签名缺少两个参数。此处传入
on_source_failure和fallback_on_slow。基类src/one_dragon/base/matcher/ocr/ocr_matcher.py的init_model只声明到on_source_success。其他实现类会抛出TypeError。请把这两个参数补进基类签名。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon/base/operation/one_dragon_context.py` around lines 518 - 525, Update the base OcrMatcher.init_model signature to accept on_source_failure and fallback_on_slow, matching the arguments passed by OneDragonContext and existing implementations; preserve the current behavior and parameter ordering for the other arguments.
508-512: 🩺 Stability & Availability | 🔴 Critical | ⚡ Quick win取消下载后 OCR 识别入口缺少懒加载保护。
init_ocr()在用户取消时直接返回,不调用init_model()。OnnxOcrMatcher.ocr()直接访问self._model,此时self._model为None,识别会抛出AttributeError。请在OnnxOcrMatcher.ocr()中按需调用init_model()。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon/base/operation/one_dragon_context.py` around lines 508 - 512, Update OnnxOcrMatcher.ocr() to lazily call init_model() before accessing self._model, so OCR remains safe when init_ocr() returns after a cancelled download. Preserve the existing recognition flow once the model is initialized.src/one_dragon_qt/services/resource_update_coordinator.py (1)
325-336: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win任务被移出队列时 OCR 请求得不到应答。
_on_task_updated只监听task_updated。DownloadQueueService.remove移除WAITING状态任务时只发出task_removed。此时闭包保持连接,后端线程必须等到 300 秒超时才继续。请同时监听task_removed。🛠️ 建议修改
def _on_task_updated(updated: ResourceDownloadTask) -> None: if updated.task_key != task.task_key or updated.state not in terminal_states: return - with contextlib.suppress(RuntimeError): - self.queue.task_updated.disconnect(_on_task_updated) + _disconnect() self._respond_ocr_request( request, updated.state == ResourceDownloadTaskState.SUCCEEDED, remember, ) + def _on_task_removed(removed_key: str) -> None: + if removed_key != task.task_key: + return + _disconnect() + self._respond_ocr_request(request, False, remember) + + def _disconnect() -> None: + with contextlib.suppress(RuntimeError): + self.queue.task_updated.disconnect(_on_task_updated) + with contextlib.suppress(RuntimeError): + self.queue.task_removed.disconnect(_on_task_removed) + self.queue.task_updated.connect(_on_task_updated) + self.queue.task_removed.connect(_on_task_removed)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/services/resource_update_coordinator.py` around lines 325 - 336, Update the OCR request callback around _on_task_updated to also handle the queue’s task_removed signal, so removal of the matching task completes the request instead of waiting for timeout. Reuse the existing task-key matching, disconnection, and _respond_ocr_request flow, and connect the removal signal alongside task_updated while preserving terminal-state handling for updates.src/one_dragon_qt/services/download_queue_service.py (1)
324-345: 🎯 Functional Correctness | 🟠 Major | ⚡ Quick win进度回调需要绑定发出进度的任务。
_on_progress_changed读取self._current_task,不使用信号来源任务。_on_worker_finished在第 384 行立即调用_start_next()并切换_current_task。旧 worker 尚未派发的progress_changed事件随后会写入新任务的progress,并把新任务状态改回DOWNLOADING。请在连接时绑定任务对象。🛠️ 建议修改
worker = DownloadTaskWorker(self.ctx, task) - worker.progress_changed.connect(self._on_progress_changed) + worker.progress_changed.connect( + lambda progress, bound_task=task: self._on_progress_changed(bound_task, progress) + )- def _on_progress_changed(self, progress: ResourceDownloadProgress) -> None: - """保存当前任务进度。""" - task = self._current_task - if task is None: + def _on_progress_changed( + self, + task: ResourceDownloadTask, + progress: ResourceDownloadProgress, + ) -> None: + """保存指定任务的进度。""" + if task is not self._current_task: return🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/services/download_queue_service.py` around lines 324 - 345, Update the progress signal connection in the worker-start flow to bind the worker’s task object when connecting to _on_progress_changed, and change _on_progress_changed to accept and update that bound task instead of reading self._current_task. Preserve the existing phase and cancellation state transitions while ensuring late progress events from a finished worker cannot modify the next task.
🧹 Nitpick comments (7)
src/one_dragon_qt/services/download_queue_service.py (1)
55-69: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议给任务数据类关闭
__eq__生成。
ResourceDownloadTask是 dataclass,默认生成按字段值比较的__eq__。self._current_task in self.tasks与self.tasks.index(self._current_task)因此按值匹配,而不是按身份匹配。当前queued_at时间戳使不同实例几乎总是不相等,所以尚未出现故障。加上eq=False可以让这些查找严格按身份进行。♻️ 建议修改
-@dataclass(slots=True) +@dataclass(slots=True, eq=False) class ResourceDownloadTask: """下载队列中的任务及运行状态。"""Also applies to: 174-176, 239-243
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/services/download_queue_service.py` around lines 55 - 69, Update the ResourceDownloadTask dataclass declaration with eq=False so it uses identity-based equality. Preserve the existing task_key and field definitions, ensuring self._current_task membership and index lookups in the task queue match only the same task instance.src/one_dragon/base/operation/context_download_request_event.py (1)
21-23: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议把内部状态字段标记为
init=False。
_response_event、_confirmed、_remember目前进入__init__参数列表,调用方可以直接传入内部状态。这三个字段只由respond()维护。加上init=False可以收窄构造接口。♻️ 建议修改
- _response_event: threading.Event = field(default_factory=threading.Event) - _confirmed: bool = False - _remember: bool = False + _response_event: threading.Event = field(default_factory=threading.Event, init=False) + _confirmed: bool = field(default=False, init=False) + _remember: bool = field(default=False, init=False)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon/base/operation/context_download_request_event.py` around lines 21 - 23, 将 ContextDownloadRequestEvent 中的内部状态字段 _response_event、_confirmed 和 _remember 的 dataclass field 配置为 init=False,使它们不再出现在构造函数参数中;保留现有默认值,并继续由 respond() 负责维护这些状态。src/one_dragon_qt/windows/main_app_window_base.py (1)
170-180: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoff建议改用公共钩子,替代反射调用私有方法。
这里用
getattr查找子界面的_update_developer_visibility。跨类访问私有名会在界面重命名该方法时静默失效,没有任何报错。建议在BaseInterface上定义一个空实现的公共方法(例如update_developer_visibility()),各界面按需覆盖,这里直接调用。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/windows/main_app_window_base.py` around lines 170 - 180, 在 BaseInterface 中新增空实现的公共钩子 update_developer_visibility(),并让需要更新开发者可见性的界面覆盖它;同时修改 _apply_developer_mode_visibility,移除 getattr 和 callable 反射逻辑,直接对每个 stackedWidget 子界面调用该公共方法。src/one_dragon_qt/services/resource_update_coordinator.py (1)
297-299: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value建议按
resource_type判断 OCR 项,而不是按 key 前缀。
key.startswith('ocr:')依赖task_key的字符串格式。若某个模型的config_key命名改动,这个判断容易失效。这里已经可以直接遍历specs判断resource_type。♻️ 建议修改
- if not any(key.startswith('ocr:') for key in selected_keys): + if not any(spec.resource_type == 'ocr' for spec in specs):🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/services/resource_update_coordinator.py` around lines 297 - 299, 将 OCR 请求完成判断从 selected_keys 中检查 “ocr:” 前缀改为遍历已有的 specs,并依据对应项的 resource_type 判断是否包含 OCR 资源;仅当没有任何 OCR 类型资源时调用 _respond_ocr_request(ocr_request, False, False),避免依赖 task_key/config_key 的命名格式。src/one_dragon_qt/view/resource_management_interface.py (1)
446-446: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win避免跨类访问
_launcher_type私有属性。第 446 行读取
LauncherDownloadCard._launcher_type。该名称以下划线开头,属于内部状态。若卡片内部重命名,此处会静默失效。建议在
LauncherDownloadCard上暴露公开只读属性(例如launcher_type),并在此处使用它。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/view/resource_management_interface.py` at line 446, Update LauncherDownloadCard to expose a public read-only launcher_type property backed by its internal _launcher_type value, then change the caller at the launcher_type assignment to use self.launcher_opt.launcher_type instead of accessing the private attribute directly.src/one_dragon/envs/update_service.py (1)
153-160: 🔒 Security & Privacy | 🔵 Trivial | 💤 Low value建议对
target_version做更严格的路径净化。第 159 行只替换了
/和\。如果标签包含..,safe_version仍可以让目录跳出launcher_update。target_version来自远程仓库标签,属于外部输入。建议追加过滤,只保留安全字符。
🛡️ 建议修改
- safe_version = target_version.replace('/', '_').replace('\\', '_') + safe_version = re.sub(r'[^A-Za-z0-9._-]', '_', target_version).strip('.') or 'latest'需要在文件顶部导入
re。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon/envs/update_service.py` around lines 153 - 160, Update get_launcher_staging_dir to sanitize the externally supplied target_version by retaining only an explicitly safe character set, preventing values such as “..” from escaping the launcher_update directory; add the required re import and use the sanitized version when constructing the Path.src/one_dragon_qt/widgets/setting_card/common_download_card.py (1)
91-91: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win修正
extra_btn_list的隐式 Optional 注解。 两处构造函数都写成list[QAbstractButton] = None。PEP 484 不允许隐式 Optional,Ruff 也报 RUF013。本次改动已经把其他参数改为现代联合类型,这两处应保持一致。
src/one_dragon_qt/widgets/setting_card/common_download_card.py#L91-L91:把CommonDownloaderSettingCard.__init__的extra_btn_list: list[QAbstractButton] = None改为extra_btn_list: list[QAbstractButton] | None = None。src/one_dragon_qt/widgets/setting_card/common_download_card.py#L391-L391:把ZipDownloaderSettingCard.__init__的同名参数做相同修改。♻️ 建议修改
- extra_btn_list: list[QAbstractButton] = None, + extra_btn_list: list[QAbstractButton] | None = None,As per coding guidelines:“所有函数签名和类成员变量都必须有类型注解,并优先使用
list[str]、X | Y等现代语法。”🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py` at line 91, 更新 src/one_dragon_qt/widgets/setting_card/common_download_card.py 第91行的 CommonDownloaderSettingCard.__init__ 以及第391行的 ZipDownloaderSettingCard.__init__,将 extra_btn_list 的类型注解改为显式可空的 list[QAbstractButton] | None,并保留默认值 None。Sources: Coding guidelines, Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@src/one_dragon_qt/view/resource_management_interface.py`:
- Around line 498-513: Update _on_ocr_gpu_changed so ctx.init_ocr() runs
asynchronously in a background worker instead of blocking the GUI thread, while
preserving the immediate model_config.ocr_use_gpu update. Keep any
configuration-control state changes and user notifications on the main thread,
using the existing worker/signaling mechanism and ensuring completion or failure
restores the appropriate UI state.
In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py`:
- Around line 77-92: Update _on_type_changed so replacing the version checker
does not release the previous checker while its QThread is still running. Prefer
reusing the existing version_checker and updating its launcher type when the
thread is not running; otherwise retain the old checker until its worker thread
finishes before allowing it to be destroyed, while preserving signal handling
and triggering the refreshed version check.
In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py`:
- Around line 330-333: Update the download action around download_queue.enqueue
so completed tasks, including SUCCEEDED tasks, are removed from the queue before
being re-enqueued; retain the existing retry behavior for CANCELLED tasks.
Ensure the subsequent enqueue creates a fresh task that can download again
rather than silently reusing the completed task.
In `@src/one_dragon_qt/windows/main_app_window_base.py`:
- Around line 228-243: Update closeEvent to distinguish the user’s response:
when No is selected, ignore the event and return; when Yes is selected, record a
pending-close intent, call download_queue.cancel_all(), and wait for
queue_updated to report no active tasks before closing. Initialize the intent in
__init__ and connect the existing queue_updated signal to the handler that
completes the deferred close.
In `@src/one_dragon/base/web/common_downloader.py`:
- Around line 116-117: 在处理 GITHUB_SOURCE_ID 的 ghproxy_url 拼接逻辑中,先移除 ghproxy_url
末尾的斜杠,再使用现有的单斜杠拼接 download_url,确保用户输入带或不带尾部斜杠时都不会生成双斜杠地址。
---
Duplicate comments:
In `@src/one_dragon_qt/services/download_queue_service.py`:
- Around line 324-345: Update the progress signal connection in the worker-start
flow to bind the worker’s task object when connecting to _on_progress_changed,
and change _on_progress_changed to accept and update that bound task instead of
reading self._current_task. Preserve the existing phase and cancellation state
transitions while ensuring late progress events from a finished worker cannot
modify the next task.
In `@src/one_dragon_qt/services/resource_update_coordinator.py`:
- Around line 325-336: Update the OCR request callback around _on_task_updated
to also handle the queue’s task_removed signal, so removal of the matching task
completes the request instead of waiting for timeout. Reuse the existing
task-key matching, disconnection, and _respond_ocr_request flow, and connect the
removal signal alongside task_updated while preserving terminal-state handling
for updates.
In `@src/one_dragon/base/operation/one_dragon_context.py`:
- Around line 518-525: Update the base OcrMatcher.init_model signature to accept
on_source_failure and fallback_on_slow, matching the arguments passed by
OneDragonContext and existing implementations; preserve the current behavior and
parameter ordering for the other arguments.
- Around line 508-512: Update OnnxOcrMatcher.ocr() to lazily call init_model()
before accessing self._model, so OCR remains safe when init_ocr() returns after
a cancelled download. Preserve the existing recognition flow once the model is
initialized.
---
Nitpick comments:
In `@src/one_dragon_qt/services/download_queue_service.py`:
- Around line 55-69: Update the ResourceDownloadTask dataclass declaration with
eq=False so it uses identity-based equality. Preserve the existing task_key and
field definitions, ensuring self._current_task membership and index lookups in
the task queue match only the same task instance.
In `@src/one_dragon_qt/services/resource_update_coordinator.py`:
- Around line 297-299: 将 OCR 请求完成判断从 selected_keys 中检查 “ocr:” 前缀改为遍历已有的
specs,并依据对应项的 resource_type 判断是否包含 OCR 资源;仅当没有任何 OCR 类型资源时调用
_respond_ocr_request(ocr_request, False, False),避免依赖 task_key/config_key 的命名格式。
In `@src/one_dragon_qt/view/resource_management_interface.py`:
- Line 446: Update LauncherDownloadCard to expose a public read-only
launcher_type property backed by its internal _launcher_type value, then change
the caller at the launcher_type assignment to use
self.launcher_opt.launcher_type instead of accessing the private attribute
directly.
In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py`:
- Line 91: 更新 src/one_dragon_qt/widgets/setting_card/common_download_card.py
第91行的 CommonDownloaderSettingCard.__init__ 以及第391行的
ZipDownloaderSettingCard.__init__,将 extra_btn_list 的类型注解改为显式可空的
list[QAbstractButton] | None,并保留默认值 None。
In `@src/one_dragon_qt/windows/main_app_window_base.py`:
- Around line 170-180: 在 BaseInterface 中新增空实现的公共钩子
update_developer_visibility(),并让需要更新开发者可见性的界面覆盖它;同时修改
_apply_developer_mode_visibility,移除 getattr 和 callable 反射逻辑,直接对每个 stackedWidget
子界面调用该公共方法。
In `@src/one_dragon/base/operation/context_download_request_event.py`:
- Around line 21-23: 将 ContextDownloadRequestEvent 中的内部状态字段
_response_event、_confirmed 和 _remember 的 dataclass field 配置为
init=False,使它们不再出现在构造函数参数中;保留现有默认值,并继续由 respond() 负责维护这些状态。
In `@src/one_dragon/envs/update_service.py`:
- Around line 153-160: Update get_launcher_staging_dir to sanitize the
externally supplied target_version by retaining only an explicitly safe
character set, preventing values such as “..” from escaping the launcher_update
directory; add the required re import and use the sanitized version when
constructing the Path.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: cc7c18e7-f6e4-490c-a63d-f15d3947548c
📒 Files selected for processing (49)
config/repository.ymldeploy/module_manifest.pydocs/develop/README.mddocs/develop/one_dragon/modules/resource_download.mdsrc/one_dragon/base/config/basic_model_config.pysrc/one_dragon/base/matcher/ocr/ocr_matcher.pysrc/one_dragon/base/matcher/ocr/onnx_ocr_matcher.pysrc/one_dragon/base/operation/context_download_request_event.pysrc/one_dragon/base/operation/context_event_bus.pysrc/one_dragon/base/operation/one_dragon_context.pysrc/one_dragon/base/operation/one_dragon_env_context.pysrc/one_dragon/base/web/common_downloader.pysrc/one_dragon/base/web/zip_downloader.pysrc/one_dragon/envs/env_config.pysrc/one_dragon/envs/repo_config.pysrc/one_dragon/envs/update_service.pysrc/one_dragon/utils/http_utils.pysrc/one_dragon/yolo/yolo_utils.pysrc/one_dragon_qt/_rc/qss/dark/title_bar.qsssrc/one_dragon_qt/_rc/qss/light/title_bar.qsssrc/one_dragon_qt/_rc/resource.pysrc/one_dragon_qt/services/download_queue_service.pysrc/one_dragon_qt/services/resource_update_coordinator.pysrc/one_dragon_qt/view/code_interface.pysrc/one_dragon_qt/view/resource_management_interface.pysrc/one_dragon_qt/view/setting/resource_download_interface.pysrc/one_dragon_qt/view/setting/setting_env_interface.pysrc/one_dragon_qt/view/setting/setting_instance_interface.pysrc/one_dragon_qt/view/source_config_interface.pysrc/one_dragon_qt/widgets/download_card/launcher_download_card.pysrc/one_dragon_qt/widgets/download_queue_dialog.pysrc/one_dragon_qt/widgets/install_card/launcher_install_card.pysrc/one_dragon_qt/widgets/resource_download_dialog.pysrc/one_dragon_qt/widgets/setting_card/common_download_card.pysrc/one_dragon_qt/widgets/teaching_tip.pysrc/one_dragon_qt/windows/main_app_window_base.pysrc/one_dragon_qt/windows/window.pysrc/zzz_od/application/hollow_zero/lost_void/context/lost_void_context.pysrc/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.pysrc/zzz_od/auto_battle/auto_battle_dodge_context.pysrc/zzz_od/config/model_config.pysrc/zzz_od/context/zzz_context.pysrc/zzz_od/gui/app.pysrc/zzz_od/gui/view/home/home_interface.pysrc/zzz_od/gui/view/setting/app_setting_interface.pysrc/zzz_od/gui/view/setting/zzz_resource_download_interface.pysrc/zzz_od/hollow_zero/hollow_map/hollow_zero_map_service.pysrc/zzz_od/yolo/flash_classifier.pysrc/zzz_od/yolo/hollow_event_detector.py
💤 Files with no reviewable changes (6)
- src/one_dragon/yolo/yolo_utils.py
- src/one_dragon_qt/view/code_interface.py
- src/one_dragon_qt/view/setting/resource_download_interface.py
- src/zzz_od/gui/view/setting/zzz_resource_download_interface.py
- src/zzz_od/gui/view/setting/app_setting_interface.py
- src/zzz_od/config/model_config.py
🚧 Files skipped from review as they are similar to previous changes (27)
- src/one_dragon/base/operation/context_event_bus.py
- deploy/module_manifest.py
- src/zzz_od/auto_battle/auto_battle_dodge_context.py
- src/one_dragon_qt/widgets/teaching_tip.py
- src/one_dragon_qt/_rc/qss/light/title_bar.qss
- src/one_dragon_qt/view/source_config_interface.py
- src/one_dragon_qt/_rc/resource.py
- src/one_dragon_qt/view/setting/setting_instance_interface.py
- src/one_dragon_qt/_rc/qss/dark/title_bar.qss
- src/zzz_od/context/zzz_context.py
- src/zzz_od/application/hollow_zero/lost_void/context/lost_void_context.py
- src/zzz_od/yolo/hollow_event_detector.py
- src/one_dragon/base/matcher/ocr/ocr_matcher.py
- src/one_dragon/envs/env_config.py
- src/zzz_od/yolo/flash_classifier.py
- src/one_dragon/base/operation/one_dragon_env_context.py
- src/zzz_od/hollow_zero/hollow_map/hollow_zero_map_service.py
- src/zzz_od/gui/view/home/home_interface.py
- src/zzz_od/application/hollow_zero/lost_void/context/lost_void_detector.py
- src/one_dragon_qt/widgets/install_card/launcher_install_card.py
- src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
- src/one_dragon_qt/widgets/download_queue_dialog.py
- config/repository.yml
- src/zzz_od/gui/app.py
- src/one_dragon_qt/windows/window.py
- src/one_dragon/base/web/zip_downloader.py
- src/one_dragon/base/config/basic_model_config.py
| def _after_model_download( | ||
| self, | ||
| success: bool, | ||
| config_key: str, | ||
| target: str, | ||
| ) -> None: | ||
| """模型下载成功后切换配置。""" | ||
| if success: | ||
| self.ctx.model_config.update(config_key, target) | ||
| if config_key == 'ocr': | ||
| self.ctx.init_ocr() | ||
|
|
||
| def _on_ocr_gpu_changed(self, value: bool) -> None: | ||
| """更新 OCR GPU 配置。""" | ||
| self.ctx.model_config.ocr_use_gpu = value | ||
| self.ctx.init_ocr() |
There was a problem hiding this comment.
🩺 Stability & Availability | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
# 确认 init_ocr 的实现与线程假设
ast-grep run --pattern $'def init_ocr(self) -> None {
$$$
}' --lang python src/one_dragon/base/operation/one_dragon_context.py
rg -n -C 5 'def init_ocr|def _confirm_resource_download|def dispatch_event' src/one_dragon/base/operation/Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 3160
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate relevant files =="
fd -a 'one_dragon_context.py|context_event_bus.py|resource_management_interface.py|worker.*|download.*' . | sed 's#^\./##' | head -100
echo
echo "== init_ocr outline and implementation =="
wc -l src/one_dragon/base/operation/one_dragon_context.py
sed -n '470,540p' src/one_dragon/base/operation/one_dragon_context.py
echo
echo "== context_event_bus implementation =="
wc -l src/one_dragon/base/operation/context_event_bus.py
cat -n src/one_dragon/base/operation/context_event_bus.py
echo
echo "== resource_management relevant sections =="
sed -n '450,525p' src/one_dragon_qt/view/resource_management_interface.py
echo
echo "== search init_ocr call sites =="
rg -n -C 4 'init_ocr\(' src/one_dragon src/one_dragon_qtRepository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 13050
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== DownloadWorker implementation and after_download callbacks =="
rg -n -C 8 'class DownloadWorker|after_download|after_download=' src/one_dragon_qt services/view -g '*.py' 2>/dev/null || rg -n -C 8 'class DownloadWorker|after_download|after_download=' . -g '*.py' | head -200
echo
echo "== _on_ocr_gpu_changed call sites / GUI wiring =="
rg -n -C 6 'ocr_use_gpu|is_gpu|GPU|ocr' src/one_dragon_qt/view/resource_management_interface.py src/one_dragon_qt -g '*.py' | head -240
echo
echo "== OnnxOcrMatcher implementation =="
rg -n -C 8 'class OnnxOcrMatcher|class OnnxOcrParam|def init_model|def is_file_existed|cleanup' src -g '*.py' | head -320
echo
echo "== event dispatch callback implementations for ContextNotifyEvent =="
rg -n -C 5 'ContextNotifyEvent\.EVENT_ID|def .*notify|notify_config|ContextNotifyEvent' src/one_dragon src/one_dragon_qt -g '*.py' | head -320Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 50400
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== exact OnnxOcrMatcher declaration and methods =="
rg -n 'class OnnxOcrMatcher|class OnnxOcrParam|def init_model|def is_file_existed|def cleanup|__init__' src -g '*.py' | sed -n '1,220p'
echo
echo "== init_ocr source with line numbers =="
sed -n '486,538p' src/one_dragon/base/operation/one_dragon_context.py
echo
echo "== context notify event ID and listeners =="
rg -n 'ContextNotifyEvent\.EVENT_ID|listen_event\(".*ContextNotifyEvent|listen_event\(.*ContextNotifyEvent|def .*context.*notify|_notify' src/one_dragon src/one_dragon_qt -g '*.py' | sed -n '1,220p'
echo
echo "== thread safety indicators in OCR model code =="
sed -n '1,220p' src/one_dragon_qt/widgets/onnx_ocr_matcher.pyRepository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 37365
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== exact OnnxOcrMatcher file =="
fd -a 'onnx.*ocr.*matcher|ocr.*matcher|matcher|paddleocr|onnx_paddleocr' src onnxocr 2>/dev/null | sed 's#^\./##' | head -120
echo
echo "== OnnxOcrMatcher declarations =="
rg -n --glob '*.py' 'class OnnxOcrMatcher|class OnnxOcrParam|def init_model\b|def is_file_existed\b|def cleanup\b|__init__\(' src onnxocr | sed -n '1,180p'
echo
echo "== init_model implementations (focused) =="
rg -n --glob '*.py' -C 3 'def init_model\b|OnnxOcrMatcher\b|class OnnxOcrMatcher' src onnxocr | sed -n '1,320p'Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 18668
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== OCR matcher implementation =="
wc -l src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
sed -n '1,240p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
echo
echo "== ModelResourceDefinition GPU config reference =="
rg -n -C 8 'class ModelResourceDefinition|gpu_config_key|onnxocr|OnnxOcrParam|OnnxOcrMatcher' src/one_dragon_qt src/one_dragon -g '*.py' | sed -n '1,320p'
echo
echo "== main_app_window context notify queue implementation =="
sed -n '1,170p' src/one_dragon_qt/windows/main_app_window_base.pyRepository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 41503
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== full OnnxOcrMatcher cleanup and relevant methods =="
sed -n '208,380p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
sed -n '520,580p' src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
echo
echo "== main app signal definitions =="
rg -n -C 4 'context_notify_signal\s*=|context_download_request_signal\s*=|init_ocr\(' src/one_dragon_qt/windows src -g '*.py' | sed -n '1,220p'Repository: OneDragon-Anything/ZenlessZoneZero-OneDragon
Length of output: 25008
将 init_ocr() 后台执行,避免 GUI 线程被 OCR 模型加载阻塞。
_on_ocr_gpu_changed 在主线程同步切换到 ctx.init_ocr(),而该方法会执行 OCR 下载和 ONNXPaddleOcr 加载;init_model() 内部有 _init_lock,但当前调用仍在 GUI 线程等待完成,可能导致界面卡住。建议将 OCR 模型重载放入后台线程,只在主线程更新配置按钮状态和显示通知。
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon_qt/view/resource_management_interface.py` around lines 498 -
513, Update _on_ocr_gpu_changed so ctx.init_ocr() runs asynchronously in a
background worker instead of blocking the GUI thread, while preserving the
immediate model_config.ocr_use_gpu update. Keep any configuration-control state
changes and user notifications on the main thread, using the existing
worker/signaling mechanism and ensuring completion or failure restores the
appropriate UI state.
| if task is not None and task.state == ResourceDownloadTaskState.CANCELLED: | ||
| self.download_queue.retry(task.task_key) | ||
| else: | ||
| self.download_queue.enqueue(spec) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
已成功的同版本任务重新入队后不会重新下载。
DownloadQueueService.enqueue 先按 task_key 查找已有任务,命中则直接返回,不重置状态。第 333 行对 SUCCEEDED 状态的任务调用 enqueue,因此不会触发新的下载。之后第 336 行仍显示“已加入队列”提示,用户会误判任务已开始。
正常情况下 is_downloaded 为 True 会禁用按钮,掩盖该路径。但如果资源文件被手动删除,按钮重新可用,点击后就会静默无动作。
建议对已结束的任务先移除再入队。
🐛 建议修复
if task is not None and task.state == ResourceDownloadTaskState.CANCELLED:
self.download_queue.retry(task.task_key)
else:
+ if task is not None:
+ self.download_queue.remove(task.task_key)
self.download_queue.enqueue(spec)🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon_qt/widgets/setting_card/common_download_card.py` around lines
330 - 333, Update the download action around download_queue.enqueue so completed
tasks, including SUCCEEDED tasks, are removed from the queue before being
re-enqueued; retain the existing retry behavior for CANCELLED tasks. Ensure the
subsequent enqueue creates a fresh task that can download again rather than
silently reusing the completed task.
| if source_id == GITHUB_SOURCE_ID and ghproxy_url is not None: | ||
| download_url = f'{ghproxy_url}/{download_url}' |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
请确认 ghproxy_url 尾部斜杠不会产生双斜杠地址。
第 117 行固定拼接 /。界面对免费代理地址的占位符是 https://ghproxy.link/,用户很可能输入带尾部斜杠的地址。此时结果为 https://ghproxy.link//https://github.com/...。部分代理会拒绝该形式。
建议先去掉尾部斜杠再拼接。
🛠️ 建议修改
- if source_id == GITHUB_SOURCE_ID and ghproxy_url is not None:
- download_url = f'{ghproxy_url}/{download_url}'
+ if source_id == GITHUB_SOURCE_ID and ghproxy_url is not None:
+ download_url = f'{ghproxy_url.rstrip("/")}/{download_url}'📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if source_id == GITHUB_SOURCE_ID and ghproxy_url is not None: | |
| download_url = f'{ghproxy_url}/{download_url}' | |
| if source_id == GITHUB_SOURCE_ID and ghproxy_url is not None: | |
| download_url = f'{ghproxy_url.rstrip("/")}/{download_url}' |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@src/one_dragon/base/web/common_downloader.py` around lines 116 - 117, 在处理
GITHUB_SOURCE_ID 的 ghproxy_url 拼接逻辑中,先移除 ghproxy_url 末尾的斜杠,再使用现有的单斜杠拼接
download_url,确保用户输入带或不带尾部斜杠时都不会生成双斜杠地址。
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (2)
src/one_dragon_qt/widgets/download_card/launcher_download_card.py (1)
186-190: 🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win将启动器类型和更新事务状态绑定到队列任务。
队列下单时
_on_download_click直接调用基类回调并跳过prepare_launcher_update(a)。如果队列支持多并发任务,任务完成时会读取当前卡片的_launcher_type调用finish_launcher_update,会把当前选择的启动器类型当作实际任务类型结算。把任务当时的下载配置/准备状态保存在该任务上下文中,不要用卡片状态覆盖。🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py` around lines 186 - 190, 修复 _on_download_click 与队列任务完成回调之间的状态传递:下单时不要跳过 prepare_launcher_update(a),应将该任务实际的启动器类型及下载配置/准备状态保存到任务上下文;任务完成时使用上下文中的快照调用 finish_launcher_update,禁止读取当前卡片的 _launcher_type 覆盖并发任务的实际类型。src/one_dragon_qt/windows/main_app_window_base.py (1)
233-253: 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win在
cancel_all()后重新检查队列状态。用户确认时后台任务可能已完成。用户选择
Yes后,cancel_all()不会进入可取消状态并触发更新;_closing_after_cancel会在后续无更新时无法触发自动关闭,导致需要再次手动关闭。请在
cancel_all()后立即调用self.download_queue.has_active_tasks()。如果队列已清空,直接完成当前QCloseEvent;只有仍有活动任务时,才设置_closing_after_cancel并忽略事件。补充覆盖该时序的回归测试。建议修改
- self._closing_after_cancel = True self.download_queue.cancel_all() + if not self.download_queue.has_active_tasks(): + super().closeEvent(event) + return + self._closing_after_cancel = True self.show_download_queue() event.ignore()🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/windows/main_app_window_base.py` around lines 233 - 253, 在 closeEvent 的用户确认分支中,先调用 download_queue.cancel_all() 后立即重新检查 has_active_tasks();若队列已无活动任务,直接完成当前关闭事件并返回,避免依赖后续更新。仅当仍有活动任务时设置 _closing_after_cancel、显示下载队列并忽略事件;同时补充覆盖该竞态时序的回归测试。Source: Coding guidelines
🧹 Nitpick comments (1)
src/one_dragon_qt/windows/main_app_window_base.py (1)
63-64: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win为新增实例成员补充显式类型注解。
self.download_queue和self.download_queue_dialog当前没有类型注解。请分别声明为DownloadQueueService和DownloadQueueDialog。建议修改
- self.download_queue = DownloadQueueService(ctx) + self.download_queue: DownloadQueueService = DownloadQueueService(ctx) - self.download_queue_dialog = DownloadQueueDialog(self.download_queue, self) + self.download_queue_dialog: DownloadQueueDialog = DownloadQueueDialog( + self.download_queue, + self, + )As per coding guidelines,Python 源码中的类成员变量必须有类型注解。
Also applies to: 74-75
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/one_dragon_qt/windows/main_app_window_base.py` around lines 63 - 64, 为实例成员补充显式类型注解:在初始化 self.download_queue 的位置声明其类型为 DownloadQueueService,并在对应的 self.download_queue_dialog 初始化位置声明其类型为 DownloadQueueDialog;保持现有初始化逻辑不变。Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@src/one_dragon_qt/widgets/download_card/launcher_download_card.py`:
- Around line 186-190: 修复 _on_download_click 与队列任务完成回调之间的状态传递:下单时不要跳过
prepare_launcher_update(a),应将该任务实际的启动器类型及下载配置/准备状态保存到任务上下文;任务完成时使用上下文中的快照调用
finish_launcher_update,禁止读取当前卡片的 _launcher_type 覆盖并发任务的实际类型。
In `@src/one_dragon_qt/windows/main_app_window_base.py`:
- Around line 233-253: 在 closeEvent 的用户确认分支中,先调用 download_queue.cancel_all()
后立即重新检查 has_active_tasks();若队列已无活动任务,直接完成当前关闭事件并返回,避免依赖后续更新。仅当仍有活动任务时设置
_closing_after_cancel、显示下载队列并忽略事件;同时补充覆盖该竞态时序的回归测试。
---
Nitpick comments:
In `@src/one_dragon_qt/windows/main_app_window_base.py`:
- Around line 63-64: 为实例成员补充显式类型注解:在初始化 self.download_queue 的位置声明其类型为
DownloadQueueService,并在对应的 self.download_queue_dialog 初始化位置声明其类型为
DownloadQueueDialog;保持现有初始化逻辑不变。
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro Plus
Run ID: 55db96d6-d30e-4dfe-8f8d-c1abdd283345
📒 Files selected for processing (6)
src/one_dragon/base/matcher/ocr/ocr_matcher.pysrc/one_dragon/base/matcher/ocr/onnx_ocr_matcher.pysrc/one_dragon_qt/view/setting/setting_env_interface.pysrc/one_dragon_qt/view/setting/setting_instance_interface.pysrc/one_dragon_qt/widgets/download_card/launcher_download_card.pysrc/one_dragon_qt/windows/main_app_window_base.py
💤 Files with no reviewable changes (1)
- src/one_dragon_qt/view/setting/setting_env_interface.py
🚧 Files skipped from review as they are similar to previous changes (2)
- src/one_dragon_qt/view/setting/setting_instance_interface.py
- src/one_dragon/base/matcher/ocr/onnx_ocr_matcher.py
Uh oh!
There was an error while loading. Please reload this page.