feat(specialized): 提供可复制的专项适配基线模板 - #587
Conversation
审查者指南新增一套从 General 能力线抽取的专项适配基线模板,涵盖后端任务与配置、前端编辑界面、注册接入清单和最小回归测试;所有内容均为可复制的新增骨架,不直接改变现有运行行为。 文件级变更
提示和命令与 Sourcery 交互
自定义使用体验访问你的控制面板以:
获取帮助Original review guide in EnglishReviewer's Guide新增一套从 General 能力线抽取的专项适配基线模板,涵盖后端任务与配置、前端编辑界面、注册接入清单和最小回归测试;所有内容均为可复制的新增骨架,不直接改变现有运行行为。 File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
您好——我发现了 4 个问题
AI Agent 提示词
请处理以下代码审查中的评论:
## 具体评论
### 评论 1
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="434-436" />
<code_context>
+ await self.handle_pre_script_error("未找到日志文件")
+ continue
+ self.script_log_path = log_path
+ await self.general_log_monitor.start_monitor_file(
+ self.script_log_path, self.log_start_time
+ )
+ await self.wait_event.wait()
</code_context>
<issue_to_address>
**issue (bug_risk):** `LogMonitor.start_monitor_file` 接收的是一个 `Path` 对象,但该方法期望的是一个无参数的路径解析器,并且会立即调用它。每次 AutoProxy 运行进入日志监控阶段时,都会在监控器启动前抛出 `TypeError`。
**触发条件:** 脚本进程启动,并且 `_wait_for_log_file` 找到其日志文件时。
**建议修复:** 传入类似 `lambda: self.script_log_path` 的可调用对象,而不是 `Path` 对象。
```suggestion
await self.general_log_monitor.start_monitor_file(
lambda: self.script_log_path, self.log_start_time
)
```
</issue_to_address>
### 评论 2
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="154-156" />
<code_context>
+ async def check(self) -> str:
+ """检查用户状态和专项运行前置条件。"""
+
+ proxy_limit = self.script_config.get("Run", "ProxyTimesLimit")
+ if proxy_limit != 0 and self.cur_user_config.get("Data", "ProxyTimes") >= proxy_limit:
+ self.cur_user_item.status = "跳过"
+ return "今日代理次数已达上限, 跳过该用户"
+
</code_context>
<issue_to_address>
**issue (broader_impact):** 该专项模板将 `ProxyTimesLimit` 应用于所有任务,包括手动请求的一次性运行。与 General 实现不同,它没有将此检查限制在排队/自动任务上,因此达到每日上限的用户无法手动运行脚本。
**触发条件:** 用户已达到 `ProxyTimesLimit`,且任务是手动启动而非通过队列启动时。
**建议修复:** 在代理次数限制检查周围保留 General 实现中的 `task_info.is_queue_task` 判断,除非专项任务有意定义了不同的手动运行语义。
</issue_to_address>
### 评论 3
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="90" />
<code_context>
+ executable_paths.append(
+ (script_path / parts[0] if len(parts) > 1 else script_path).resolve()
+ )
+ arguments.append(shlex.split(parts[-1], posix=False))
+ return executable_paths, arguments
+
</code_context>
<issue_to_address>
**issue (bug_risk):** `_split_script_arguments` 使用了 `shlex.split(..., posix=False)`,这会保留参数中的引号。因此,包含带引号路径或空格的 Windows 参数会以字面引号的形式传递给子进程,其行为也与 General 任务的参数解析方式不一致。
**触发条件:** `Script.Arguments` 包含带引号的 Windows 路径,或包含空格的带引号参数时。
**建议修复:** 使用与 General 相同的 `shlex.split` 模式,或者在将参数传递给 `open_process` 前,显式规范化 Windows 命令行引号。
```suggestion
arguments.append(shlex.split(parts[-1]))
```
</issue_to_address>
### 评论 4
<location path="templates/specialized/tests/test_xxx_autoproxy.py" line_range="19-21" />
<code_context>
+ async def _start_game(self) -> None:
+ if self.game_manager is None:
+ return
+ try:
+ if isinstance(self.game_manager, ProcessManager):
+ if self.script_config.get("Game", "Type") == "URL":
</code_context>
<issue_to_address>
**issue (testing):** 测试模块在导入模板时捕获了所有 `ImportError`,然后跳过整个测试类。模板复制后出现的真实导入错误或缺失依赖会被静默转换为通过但跳过的测试,因此回归测试无法检测集成失败。
**触发条件:** 复制后的任务出现了除预期的注册前缺失之外的导入错误时。
**建议修复:** 只针对特定的预期注册前条件执行跳过,或者使用明确的环境/配置标记,而不是捕获所有 `ImportError` 异常。
```suggestion
except ModuleNotFoundError as exc:
if exc.name not in {"app.task.Xxx", "app.task.Xxx.AutoProxy"}:
raise
# 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。
AutoProxyTask = None
```
</issue_to_address>Sourcery 评估
需要人工审查。 请先处理 4 个发现的问题,并且本 PR 添加的是一个未集成的模板,因此合并它不会直接改变生产行为;不过,错误的副本可能会在未来的专项实现中传播不正确的进程、配置复制或恢复逻辑。回滚操作会移除源模板,但不会撤销已经基于该模板创建的适配版本,不过这些下游更改的影响仍然有限且可修复。
阻塞性发现:templates/specialized/backend/task/Xxx/AutoProxy.py:436、templates/specialized/backend/task/Xxx/AutoProxy.py:156、templates/specialized/backend/task/Xxx/AutoProxy.py:90、templates/specialized/tests/test_xxx_autoproxy.py:21
Original comment in English
Hey - I've found 4 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="434-436" />
<code_context>
+ await self.handle_pre_script_error("未找到日志文件")
+ continue
+ self.script_log_path = log_path
+ await self.general_log_monitor.start_monitor_file(
+ self.script_log_path, self.log_start_time
+ )
+ await self.wait_event.wait()
</code_context>
<issue_to_address>
**issue (bug_risk):** `LogMonitor.start_monitor_file` is passed a `Path` object, but the method expects a zero-argument path resolver and immediately calls it. Every AutoProxy run that reaches log monitoring raises `TypeError` before the monitor starts.
**Triggers:** When the script process starts and `_wait_for_log_file` finds its log file.
**Suggested fix:** Pass a callable such as `lambda: self.script_log_path` instead of the `Path` object.
```suggestion
await self.general_log_monitor.start_monitor_file(
lambda: self.script_log_path, self.log_start_time
)
```
</issue_to_address>
### Comment 2
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="154-156" />
<code_context>
+ async def check(self) -> str:
+ """检查用户状态和专项运行前置条件。"""
+
+ proxy_limit = self.script_config.get("Run", "ProxyTimesLimit")
+ if proxy_limit != 0 and self.cur_user_config.get("Data", "ProxyTimes") >= proxy_limit:
+ self.cur_user_item.status = "跳过"
+ return "今日代理次数已达上限, 跳过该用户"
+
</code_context>
<issue_to_address>
**issue (broader_impact):** The specialized template applies `ProxyTimesLimit` to every task, including manually requested one-off runs. Unlike the General implementation, it does not restrict this check to queued/automatic tasks, so a user who has reached the daily limit cannot manually run the script.
**Triggers:** When a user has reached `ProxyTimesLimit` and the task was started manually rather than through the queue.
**Suggested fix:** Preserve General's `task_info.is_queue_task` guard around the proxy-limit check, unless the specialized task intentionally defines different manual-run semantics.
</issue_to_address>
### Comment 3
<location path="templates/specialized/backend/task/Xxx/AutoProxy.py" line_range="90" />
<code_context>
+ executable_paths.append(
+ (script_path / parts[0] if len(parts) > 1 else script_path).resolve()
+ )
+ arguments.append(shlex.split(parts[-1], posix=False))
+ return executable_paths, arguments
+
</code_context>
<issue_to_address>
**issue (bug_risk):** `_split_script_arguments` uses `shlex.split(..., posix=False)`, which preserves quote characters in arguments. Windows arguments containing quoted paths or spaces are therefore passed to the child process with literal quotes and do not match the General task's argument parsing behavior.
**Triggers:** When `Script.Arguments` contains quoted Windows paths or quoted arguments with spaces.
**Suggested fix:** Use the same `shlex.split` mode as General, or explicitly normalize Windows command-line quoting before passing the arguments to `open_process`.
```suggestion
arguments.append(shlex.split(parts[-1]))
```
</issue_to_address>
### Comment 4
<location path="templates/specialized/tests/test_xxx_autoproxy.py" line_range="19-21" />
<code_context>
+ async def _start_game(self) -> None:
+ if self.game_manager is None:
+ return
+ try:
+ if isinstance(self.game_manager, ProcessManager):
+ if self.script_config.get("Game", "Type") == "URL":
</code_context>
<issue_to_address>
**issue (testing):** The test module catches every `ImportError` while importing the template and then skips the entire test class. A real broken import or missing dependency after the template is copied is silently converted into a passing skipped test, so the regression test does not detect integration failures.
**Triggers:** When the copied task has an import error other than the intentional pre-registration absence.
**Suggested fix:** Only skip for the specific expected pre-registration condition, or use an explicit environment/configuration marker rather than catching all `ImportError` exceptions.
```suggestion
except ModuleNotFoundError as exc:
if exc.name not in {"app.task.Xxx", "app.task.Xxx.AutoProxy"}:
raise
# 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。
AutoProxyTask = None
```
</issue_to_address>Sourcery assessment
Needs a human reviewer. 4 findings to address first, and this PR adds an unintegrated template, so merging it does not change production behavior directly; a faulty copy could nevertheless propagate incorrect process, configuration-copy, or restoration logic into a future specialization. Reverting removes the source template but would not undo adaptations already created from it, although those downstream changes remain bounded and repairable.
Blocking findings: templates/specialized/backend/task/Xxx/AutoProxy.py:436, templates/specialized/backend/task/Xxx/AutoProxy.py:156, templates/specialized/backend/task/Xxx/AutoProxy.py:90, templates/specialized/tests/test_xxx_autoproxy.py:21
| await self.general_log_monitor.start_monitor_file( | ||
| self.script_log_path, self.log_start_time | ||
| ) |
There was a problem hiding this comment.
issue (bug_risk): LogMonitor.start_monitor_file 接收的是一个 Path 对象,但该方法期望的是一个无参数的路径解析器,并且会立即调用它。每次 AutoProxy 运行进入日志监控阶段时,都会在监控器启动前抛出 TypeError。
触发条件: 脚本进程启动,并且 _wait_for_log_file 找到其日志文件时。
建议修复: 传入类似 lambda: self.script_log_path 的可调用对象,而不是 Path 对象。
| await self.general_log_monitor.start_monitor_file( | |
| self.script_log_path, self.log_start_time | |
| ) | |
| await self.general_log_monitor.start_monitor_file( | |
| lambda: self.script_log_path, self.log_start_time | |
| ) |
Original comment in English
issue (bug_risk): LogMonitor.start_monitor_file is passed a Path object, but the method expects a zero-argument path resolver and immediately calls it. Every AutoProxy run that reaches log monitoring raises TypeError before the monitor starts.
Triggers: When the script process starts and _wait_for_log_file finds its log file.
Suggested fix: Pass a callable such as lambda: self.script_log_path instead of the Path object.
| await self.general_log_monitor.start_monitor_file( | |
| self.script_log_path, self.log_start_time | |
| ) | |
| await self.general_log_monitor.start_monitor_file( | |
| lambda: self.script_log_path, self.log_start_time | |
| ) |
| proxy_limit = self.script_config.get("Run", "ProxyTimesLimit") | ||
| if proxy_limit != 0 and self.cur_user_config.get("Data", "ProxyTimes") >= proxy_limit: | ||
| self.cur_user_item.status = "跳过" |
There was a problem hiding this comment.
issue (broader_impact): 该专项模板将 ProxyTimesLimit 应用于所有任务,包括手动请求的一次性运行。与 General 实现不同,它没有将此检查限制在排队/自动任务上,因此达到每日上限的用户无法手动运行脚本。
触发条件: 用户已达到 ProxyTimesLimit,且任务是手动启动而非通过队列启动时。
建议修复: 在代理次数限制检查周围保留 General 实现中的 task_info.is_queue_task 判断,除非专项任务有意定义了不同的手动运行语义。
Original comment in English
issue (broader_impact): The specialized template applies ProxyTimesLimit to every task, including manually requested one-off runs. Unlike the General implementation, it does not restrict this check to queued/automatic tasks, so a user who has reached the daily limit cannot manually run the script.
Triggers: When a user has reached ProxyTimesLimit and the task was started manually rather than through the queue.
Suggested fix: Preserve General's task_info.is_queue_task guard around the proxy-limit check, unless the specialized task intentionally defines different manual-run semantics.
| executable_paths.append( | ||
| (script_path / parts[0] if len(parts) > 1 else script_path).resolve() | ||
| ) | ||
| arguments.append(shlex.split(parts[-1], posix=False)) |
There was a problem hiding this comment.
issue (bug_risk): _split_script_arguments 使用了 shlex.split(..., posix=False),这会保留参数中的引号。因此,包含带引号路径或空格的 Windows 参数会以字面引号的形式传递给子进程,其行为也与 General 任务的参数解析方式不一致。
触发条件: Script.Arguments 包含带引号的 Windows 路径,或包含空格的带引号参数时。
建议修复: 使用与 General 相同的 shlex.split 模式,或者在将参数传递给 open_process 前,显式规范化 Windows 命令行引号。
| arguments.append(shlex.split(parts[-1], posix=False)) | |
| arguments.append(shlex.split(parts[-1])) |
Original comment in English
issue (bug_risk): _split_script_arguments uses shlex.split(..., posix=False), which preserves quote characters in arguments. Windows arguments containing quoted paths or spaces are therefore passed to the child process with literal quotes and do not match the General task's argument parsing behavior.
Triggers: When Script.Arguments contains quoted Windows paths or quoted arguments with spaces.
Suggested fix: Use the same shlex.split mode as General, or explicitly normalize Windows command-line quoting before passing the arguments to open_process.
| arguments.append(shlex.split(parts[-1], posix=False)) | |
| arguments.append(shlex.split(parts[-1])) |
| except ImportError: | ||
| # 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。 | ||
| AutoProxyTask = None |
There was a problem hiding this comment.
issue (testing): 测试模块在导入模板时捕获了所有 ImportError,然后跳过整个测试类。模板复制后出现的真实导入错误或缺失依赖会被静默转换为通过但跳过的测试,因此回归测试无法检测集成失败。
触发条件: 复制后的任务出现了除预期的注册前缺失之外的导入错误时。
建议修复: 只针对特定的预期注册前条件执行跳过,或者使用明确的环境/配置标记,而不是捕获所有 ImportError 异常。
| except ImportError: | |
| # 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。 | |
| AutoProxyTask = None | |
| except ModuleNotFoundError as exc: | |
| if exc.name not in {"app.task.Xxx", "app.task.Xxx.AutoProxy"}: | |
| raise | |
| # 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。 | |
| AutoProxyTask = None |
Original comment in English
issue (testing): The test module catches every ImportError while importing the template and then skips the entire test class. A real broken import or missing dependency after the template is copied is silently converted into a passing skipped test, so the regression test does not detect integration failures.
Triggers: When the copied task has an import error other than the intentional pre-registration absence.
Suggested fix: Only skip for the specific expected pre-registration condition, or use an explicit environment/configuration marker rather than catching all ImportError exceptions.
| except ImportError: | |
| # 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。 | |
| AutoProxyTask = None | |
| except ModuleNotFoundError as exc: | |
| if exc.name not in {"app.task.Xxx", "app.task.Xxx.AutoProxy"}: | |
| raise | |
| # 模板尚未复制进 app/task 时允许仓库全量 pytest 收集并跳过本文件。 | |
| AutoProxyTask = None |
摘要
templates/specialized专项适配基线模板,覆盖后端任务/配置/Schema、前端编辑页、注册清单与最小回归测试Sourcery 总结
提供可复制的专项适配基线模板,帮助后续专项接入统一后端、前端、注册和验证流程。
新功能:
增强功能:
文档:
测试:
杂项:
Original summary in English
Summary by Sourcery
提供可复制的专项适配基线模板,帮助后续专项接入统一后端、前端、注册和验证流程。
New Features:
Enhancements:
Documentation:
Tests:
Chores: