feat support ok-nte#250
Conversation
|
@codex review这个PR,回复请使用中文 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 10b2cab10b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
resolve了 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9abbe9c584
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
# Conflicts: # app/api/scripts.py # app/core/config.py # app/core/task_manager.py # app/models/config.py # app/models/schema.py # app/task/__init__.py # frontend/src/api/models/ScriptCreateIn.ts # frontend/src/api/models/ScriptCreateOut.ts # frontend/src/api/models/ScriptGetOut.ts # frontend/src/api/models/ScriptUpdateIn.ts # frontend/src/api/models/UserCreateOut.ts # frontend/src/api/models/UserGetOut.ts # frontend/src/api/models/UserUpdateIn.ts # frontend/src/components/ScriptTable.vue # frontend/src/composables/useScriptApi.ts # frontend/src/types/script.ts # frontend/src/views/Scripts.vue
| def _oknte_script_config(script_id: str) -> tuple[uuid.UUID, RuntimeOkNteConfig]: | ||
| script_uid = uuid.UUID(script_id) | ||
| script_config = Config.ScriptConfig[script_uid] | ||
| if not isinstance(script_config, RuntimeOkNteConfig): | ||
| raise ValueError("脚本配置类型错误, 不是 OK-NTE 类型") | ||
| return script_uid, script_config | ||
|
|
||
|
|
||
| def _oknte_legacy_mas_config_dir(script_id: str) -> Path: | ||
| script_uid, _ = _oknte_script_config(script_id) | ||
| return Path.cwd() / "data" / str(script_uid) / "Default" / "ConfigFile" | ||
|
|
||
|
|
||
| def _oknte_mas_config_dir(script_id: str, user_id: str) -> Path: | ||
| script_uid, _ = _oknte_script_config(script_id) | ||
| user_uid = uuid.UUID(user_id) | ||
| return Path.cwd() / "data" / str(script_uid) / str(user_uid) / "ConfigFile" | ||
|
|
||
|
|
||
| def _oknte_config_file_path(config_dir: Path, filename: str) -> Path: | ||
| file_path = Path(filename) | ||
| if ( | ||
| file_path.name != filename | ||
| or file_path.is_absolute() | ||
| or ".." in file_path.parts | ||
| ): | ||
| raise ValueError("配置文件名非法") | ||
| return config_dir / filename |
| @router.post( | ||
| "/oknte/configs/list", | ||
| tags=["OKNTE"], | ||
| summary="获取 OK-NTE 配置文件列表及 schema", | ||
| status_code=200, | ||
| ) | ||
| async def get_oknte_configs_list(script_id: str, user_id: str): | ||
| """ | ||
| 获取 OK-NTE 配置文件列表及 schema 定义。 | ||
| 读写用户配置目录(data/{script_id}/{user_id}/ConfigFile/), | ||
| 若为空则自动从 ok-nte configs 目录初始化默认配置。 | ||
|
|
||
| Args: | ||
| script_id: OK-NTE 脚本 ID | ||
| user_id: 用户 ID | ||
|
|
||
| Returns: | ||
| dict: 包含配置文件列表和 schema 的响应 | ||
| """ | ||
| try: | ||
| import json | ||
| import shutil | ||
| from app.task.OkNte.config_schema import ( | ||
| get_all_config_info, build_fields_for_config, load_oknte_option_labels, | ||
| ) | ||
|
|
||
| _, script_config = _oknte_script_config(script_id) | ||
|
|
||
| # 从 ok-nte 安装目录加载翻译 → option_labels | ||
| root_path = script_config.get("Info", "RootPath") | ||
| option_labels = load_oknte_option_labels(root_path) if root_path else {} | ||
|
|
||
| # 用户配置目录;旧版 Default 目录仅作为升级后的初始化来源。 | ||
| mas_config_dir = _oknte_mas_config_dir(script_id, user_id) | ||
|
|
||
| # ok-nte 源配置目录(用于自动初始化) | ||
| legacy_config_dir = _oknte_legacy_mas_config_dir(script_id) | ||
| oknte_configs_dir = ( | ||
| legacy_config_dir | ||
| if legacy_config_dir.is_dir() and any(legacy_config_dir.iterdir()) | ||
| else None | ||
| ) | ||
| if oknte_configs_dir is None: | ||
| raw_config_path = script_config.get("Script", "ConfigPath") | ||
| oknte_configs_dir = Path(raw_config_path) if raw_config_path else None | ||
| if not oknte_configs_dir or not oknte_configs_dir.exists(): | ||
| if root_path: | ||
| root = Path(root_path) | ||
| packaged_dir = root / "data" / "apps" / "ok-nte" / "working" / "configs" | ||
| source_dir = root / "configs" | ||
| oknte_configs_dir = packaged_dir if packaged_dir.is_dir() else source_dir | ||
|
|
||
| # 自动初始化:用户目录为空时从旧版共享目录或 ok-nte configs 复制默认配置 | ||
| need_init = not mas_config_dir.exists() or not any(mas_config_dir.iterdir()) | ||
| if need_init and oknte_configs_dir and oknte_configs_dir.is_dir(): | ||
| mas_config_dir.mkdir(parents=True, exist_ok=True) | ||
| shutil.copytree(oknte_configs_dir, mas_config_dir, dirs_exist_ok=True) | ||
|
|
||
| configs_info = get_all_config_info() | ||
|
|
||
| # 读取 per-user JSON 配置,通过 build_fields_for_config 构建字段列表 | ||
| result = [] | ||
| for info in configs_info: | ||
| filename = info["filename"] | ||
| filepath = _oknte_config_file_path(mas_config_dir, filename) | ||
| current_data: dict[str, Any] = {} | ||
| if filepath.exists(): | ||
| try: | ||
| current_data = json.loads(filepath.read_text(encoding="utf-8")) | ||
| except Exception: | ||
| pass | ||
|
|
||
| fields = build_fields_for_config(filename, current_data, option_labels) | ||
|
|
||
| result.append({ | ||
| **info, | ||
| "fields": fields, | ||
| "currentData": current_data, | ||
| }) | ||
|
|
||
| return { | ||
| "code": 200, | ||
| "status": "success", | ||
| "message": f"共 {len(result)} 个配置文件", | ||
| "data": result, | ||
| "optionLabels": option_labels, | ||
| "configPath": str(mas_config_dir) if mas_config_dir else None, | ||
| } | ||
| except Exception as e: | ||
| return { | ||
| "code": 500, | ||
| "status": "error", | ||
| "message": f"{type(e).__name__}: {str(e)}", | ||
| "data": [], | ||
| } | ||
|
|
||
|
|
||
| @router.post( | ||
| "/oknte/configs/update", | ||
| tags=["OKNTE"], | ||
| summary="更新 OK-NTE 配置文件", | ||
| status_code=200, | ||
| ) | ||
| async def update_oknte_config( | ||
| script_id: str = Body(...), | ||
| user_id: str = Body(...), | ||
| filename: str = Body(...), | ||
| data: dict = Body(...), | ||
| ): | ||
| """ | ||
| 更新 OK-NTE 配置文件 | ||
|
|
||
| Args: | ||
| script_id: OK-NTE 脚本 ID | ||
| user_id: 用户 ID | ||
| filename: 配置文件名(如 DailyTask.json) | ||
| data: 要更新的配置数据 | ||
|
|
||
| Returns: | ||
| dict: 操作结果 | ||
| """ | ||
| try: | ||
| import json | ||
|
|
||
| # 写入用户配置目录 | ||
| mas_config_dir = _oknte_mas_config_dir(script_id, user_id) | ||
| mas_config_dir.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| filepath = _oknte_config_file_path(mas_config_dir, filename) | ||
|
|
||
| existing_data = {} | ||
| if filepath.exists(): | ||
| with open(filepath, "r", encoding="utf-8") as f: | ||
| existing_data = json.load(f) | ||
|
|
||
| existing_data.update(data) | ||
|
|
||
| with open(filepath, "w", encoding="utf-8") as f: | ||
| json.dump(existing_data, f, ensure_ascii=False, indent=4) | ||
|
|
||
| return { | ||
| "code": 200, | ||
| "status": "success", | ||
| "message": f"配置文件 {filename} 已更新", | ||
| "data": existing_data, | ||
| } | ||
| except Exception as e: | ||
| return { | ||
| "code": 500, | ||
| "status": "error", | ||
| "message": f"{type(e).__name__}: {str(e)}", | ||
| } | ||
|
|
||
|
|
||
| @router.post( | ||
| "/oknte/configs/batch-update", | ||
| tags=["OKNTE"], | ||
| summary="批量更新 OK-NTE 配置文件", | ||
| status_code=200, | ||
| ) | ||
| async def batch_update_oknte_configs( | ||
| script_id: str = Body(...), | ||
| user_id: str = Body(...), | ||
| configs: dict = Body(...), | ||
| ): | ||
| """ | ||
| 批量更新 OK-NTE 配置文件 | ||
|
|
||
| Args: | ||
| script_id: OK-NTE 脚本 ID | ||
| user_id: 用户 ID | ||
| configs: { filename: data } 格式的配置数据 | ||
|
|
||
| Returns: | ||
| dict: 操作结果 | ||
| """ | ||
| try: | ||
| import json | ||
|
|
||
| # 写入用户配置目录 | ||
| mas_config_dir = _oknte_mas_config_dir(script_id, user_id) | ||
| mas_config_dir.mkdir(parents=True, exist_ok=True) | ||
|
|
||
| updated_files = [] | ||
| for filename, data in configs.items(): | ||
| filepath = _oknte_config_file_path(mas_config_dir, filename) | ||
| existing_data = {} | ||
| if filepath.exists(): | ||
| with open(filepath, "r", encoding="utf-8") as f: | ||
| existing_data = json.load(f) | ||
| existing_data.update(data) | ||
| with open(filepath, "w", encoding="utf-8") as f: | ||
| json.dump(existing_data, f, ensure_ascii=False, indent=4) | ||
| updated_files.append(filename) | ||
|
|
||
| return { | ||
| "code": 200, | ||
| "status": "success", | ||
| "message": f"已更新 {len(updated_files)} 个配置文件", | ||
| "data": updated_files, | ||
| } | ||
| except Exception as e: | ||
| return { | ||
| "code": 500, | ||
| "status": "error", | ||
| "message": f"{type(e).__name__}: {str(e)}", | ||
| } |
There was a problem hiding this comment.
这边也是,感觉和okww基本没啥区别,后续可以和@1w1w11w1和群主商量下要不要抽出来,具体实现看着没啥问题(
| self.Game_EmulatorId = ConfigItem( | ||
| "Game", | ||
| "EmulatorId", | ||
| "-", | ||
| MultipleUIDValidator("-", self.related_config, "EmulatorConfig"), | ||
| ) | ||
| self.Game_EmulatorIndex = ConfigItem("Game", "EmulatorIndex", "-") | ||
|
|
There was a problem hiding this comment.
有道理,刚把模拟器字段删了。我做fork分支的PR不好抽逻辑合轮子,动你们原本代码行数太多了,不然每次dev代码更新我都要重新merge解决冲突,现在是尽量并行的。如果要合并逻辑得把这个PR合进主干之后再新起一个单独PR来做。
There was a problem hiding this comment.
有道理,刚把模拟器字段删了。我做fork分支的PR不好抽逻辑合轮子,动你们原本代码行数太多了,不然每次dev代码更新我都要重新merge解决冲突,现在是尽量并行的。如果要合并逻辑得把这个PR合进主干之后再新起一个单独PR来做。
ok的,只是看到那部分代码之后感觉可以等合进去之后一起优化一下
| @@ -0,0 +1,401 @@ | |||
| # AUTO-MAS: A Multi-Script, Multi-Config Management and Automation Software | |||
There was a problem hiding this comment.
建议把这个文件和autoproxy内的通知模块都抽到tools里(当然只是建议
|
@sourcery-ai review |
审查者指南在后端任务执行、配置、API 模式以及前端 UI 中为 OK-NTE(ok-script)脚本类型提供一等公民支持,包括按用户的 OK-NTE 任务配置、游戏生命周期管理,以及带有多语言感知模式的 OK-NTE JSON 配置内置编辑器。 OK-NTE 按用户配置编辑流程的时序图sequenceDiagram
actor User
participant OkNteUserEdit as OkNteUserEditVue
participant OkNteConfigEditor as OkNteConfigEditorVue
participant OknteService
participant ScriptsAPI as FastAPI_scripts
participant Schema as OkNte_config_schema
participant FS as FileSystem
User->>OkNteUserEdit: open OkNte user edit page
OkNteUserEdit->>OkNteConfigEditor: mount with scriptId,userId
OkNteConfigEditor->>OknteService: getOknteConfigsListApiScriptsOknteConfigsListPost(scriptId,userId)
OknteService->>ScriptsAPI: POST /api/scripts/oknte/configs/list
ScriptsAPI->>ScriptsAPI: _oknte_mas_config_dir(script_id,user_id)
ScriptsAPI->>FS: init/copy configs if needed
ScriptsAPI->>Schema: get_all_config_info()
ScriptsAPI->>Schema: build_fields_for_config(filename,current_data,option_labels)
Schema-->>ScriptsAPI: config_infos with fields
ScriptsAPI-->>OknteService: config list + optionLabels
OknteService-->>OkNteConfigEditor: response
OkNteConfigEditor-->>User: render grouped config files & fields
User->>OkNteConfigEditor: modify multiple fields
OkNteConfigEditor->>OknteService: batchUpdateOknteConfigsApiScriptsOknteConfigsBatchUpdatePost(body)
OknteService->>ScriptsAPI: POST /api/scripts/oknte/configs/batch-update
ScriptsAPI->>FS: merge & write JSON files
ScriptsAPI-->>OknteService: updated_files
OknteService-->>OkNteConfigEditor: success
OkNteConfigEditor-->>User: show "配置已保存"
文件级改动
提示和命令与 Sourcery 交互
自定义你的使用体验访问你的 控制面板 来:
获取帮助Original review guide in EnglishReviewer's GuideAdd first-class support for the OK-NTE (ok-script) script type across backend task execution, configuration, API schema, and frontend UI, including per-user OK-NTE task configuration, game lifecycle management, and an in-app editor for OK-NTE JSON configs with translation-aware schema. Sequence diagram for OK-NTE per-user config editing flowsequenceDiagram
actor User
participant OkNteUserEdit as OkNteUserEditVue
participant OkNteConfigEditor as OkNteConfigEditorVue
participant OknteService
participant ScriptsAPI as FastAPI_scripts
participant Schema as OkNte_config_schema
participant FS as FileSystem
User->>OkNteUserEdit: open OkNte user edit page
OkNteUserEdit->>OkNteConfigEditor: mount with scriptId,userId
OkNteConfigEditor->>OknteService: getOknteConfigsListApiScriptsOknteConfigsListPost(scriptId,userId)
OknteService->>ScriptsAPI: POST /api/scripts/oknte/configs/list
ScriptsAPI->>ScriptsAPI: _oknte_mas_config_dir(script_id,user_id)
ScriptsAPI->>FS: init/copy configs if needed
ScriptsAPI->>Schema: get_all_config_info()
ScriptsAPI->>Schema: build_fields_for_config(filename,current_data,option_labels)
Schema-->>ScriptsAPI: config_infos with fields
ScriptsAPI-->>OknteService: config list + optionLabels
OknteService-->>OkNteConfigEditor: response
OkNteConfigEditor-->>User: render grouped config files & fields
User->>OkNteConfigEditor: modify multiple fields
OkNteConfigEditor->>OknteService: batchUpdateOknteConfigsApiScriptsOknteConfigsBatchUpdatePost(body)
OknteService->>ScriptsAPI: POST /api/scripts/oknte/configs/batch-update
ScriptsAPI->>FS: merge & write JSON files
ScriptsAPI-->>OknteService: updated_files
OknteService-->>OkNteConfigEditor: success
OkNteConfigEditor-->>User: show "配置已保存"
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - 我发现了 1 个安全问题、1 个其他问题,并留下了一些整体反馈:
安全问题:
- 原生 Python
xml库容易受到 XML 外部实体(XXE)攻击。这类攻击可能会泄露机密数据,而“XML 炸弹”则可能导致拒绝服务。请不要使用该库来解析不受信任的输入。Python 文档推荐使用defusedxml作为替代。(link)
总体评论:
- OK-NTE API 客户端方法同时定义在通用的 Service 类和新的 OknteService 中,这会引入冗余并带来潜在混淆;建议只在一个地方保留这些端点(最好是专门的 OknteService),并删除重复实现。
- 新的 /api/scripts/oknte/configs/list 端点声明为 POST,但只使用查询参数,并且行为上是只读的列表操作;如果能让 HTTP 动词和参数形式与语义保持一致(例如改为带 query 的 GET,或者带 body 的 POST),会让该 API 更清晰、更一致。
给 AI Agents 的提示
Please address the comments from this code review:
## Overall Comments
- The OK-NTE API client methods are defined both on the generic Service class and in the new OknteService, which introduces redundancy and potential confusion; consider keeping these endpoints in just one place (preferably the dedicated OknteService) and removing the duplicates.
- The new /api/scripts/oknte/configs/list endpoint is declared as POST but only uses query parameters and behaves like a read-only list operation; aligning the HTTP verb and parameter style with its semantics (e.g. GET with query or POST with body) would make the API clearer and more consistent.
## Individual Comments
### Comment 1
<location path="frontend/src/views/OkNteUserEdit/OkNteConfigEditor.vue" line_range="3-6" />
<code_context>
+<template>
+ <div class="oknte-config-editor">
+ <div class="editor-header">
+ <h3>OK-NTE 配置编辑</h3>
+ <a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
+ <a-tag v-else color="success">已保存</a-tag>
+ </div>
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** 编辑器会显示“有未保存的更改”的提示,但没有明确的保存操作,只依赖自动保存。
`hasChanges` 用来切换 `有未保存的更改` 这个标签,但 `saveAll` 只在 `onBeforeUnmount` 中被调用。当前用户无法通过 UI 主动触发保存,任何跳过卸载钩子(强制刷新、意外错误、部分路由守卫流程)的情况,都有可能导致编辑内容丢失。请添加一个明确的“保存配置”操作(例如一个调用 `saveAll(false)` 的按钮),并在 `hasChanges` 为 true 时考虑在导航时进行确认,以避免这些较重的 OK-NTE 配置数据丢失。
建议实现:
```
<div class="editor-header">
<h3>OK-NTE 配置编辑</h3>
<div class="editor-header-right">
<a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
<a-tag v-else color="success">已保存</a-tag>
<a-button
type="primary"
size="small"
:disabled="!hasChanges"
@click="saveAll(false)"
>
保存配置
</a-button>
</div>
</div>
```
要把这一套完全接好并覆盖导航安全性,可以考虑:
1. 确保在 `<script>` 中暴露 `saveAll`,以便在模板里调用(即在 `<script setup>` 中从 `setup()` 返回,或者在传统 Options API 中放进 `setup()`/`methods`)。
2. 如果你希望在导航时进行确认,可以添加:
- 在 `onMounted`/`onBeforeUnmount` 中添加 `window.beforeunload` 监听器,在 `hasChanges` 为 true 时设置 `event.returnValue` 为某个提示信息。
- 使用 `vue-router` 的 `onBeforeRouteLeave` 守卫,在 `hasChanges` 为 true 时弹出 Ant Design Vue 的确认对话框,在用户确认后再允许路由跳转。
3. 由于我看不到 `<script>` 部分,请按现有风格集成这些钩子(Composition API 或 Options API),并复用现有的 `hasChanges` ref/状态,而不是新增一套标志位。
</issue_to_address>
### Comment 2
<location path="app/task/OkNte/config_schema.py" line_range="105" />
<code_context>
root = ElementTree.parse(str(ts_path)).getroot()
</code_context>
<issue_to_address>
**security (python.lang.security.use-defused-xml-parse):** 原生 Python `xml` 库容易受到 XML 外部实体(XXE)攻击。这类攻击可能泄露机密数据,而“XML 炸弹”可能导致拒绝服务。请不要使用该库来解析不受信任的输入。Python 文档推荐使用 `defusedxml` 作为替代。
```suggestion
root = defusedxml.etree.ElementTree.parse(str(ts_path)).getroot()
```
*Source: opengrep*
</issue_to_address>帮我变得更有用!请在每条评论上点 👍 或 👎,我会根据你的反馈改进后续评审。
Original comment in English
Hey - I've found 1 security issue, 1 other issue, and left some high level feedback:
Security issues:
- The native Python
xmllibrary is vulnerable to XML External Entity (XXE) attacks. These attacks can leak confidential data and "XML bombs" can cause denial of service. Do not use this library to parse untrusted input. Instead the Python documentation recommends usingdefusedxml. (link)
General comments:
- The OK-NTE API client methods are defined both on the generic Service class and in the new OknteService, which introduces redundancy and potential confusion; consider keeping these endpoints in just one place (preferably the dedicated OknteService) and removing the duplicates.
- The new /api/scripts/oknte/configs/list endpoint is declared as POST but only uses query parameters and behaves like a read-only list operation; aligning the HTTP verb and parameter style with its semantics (e.g. GET with query or POST with body) would make the API clearer and more consistent.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- The OK-NTE API client methods are defined both on the generic Service class and in the new OknteService, which introduces redundancy and potential confusion; consider keeping these endpoints in just one place (preferably the dedicated OknteService) and removing the duplicates.
- The new /api/scripts/oknte/configs/list endpoint is declared as POST but only uses query parameters and behaves like a read-only list operation; aligning the HTTP verb and parameter style with its semantics (e.g. GET with query or POST with body) would make the API clearer and more consistent.
## Individual Comments
### Comment 1
<location path="frontend/src/views/OkNteUserEdit/OkNteConfigEditor.vue" line_range="3-6" />
<code_context>
+<template>
+ <div class="oknte-config-editor">
+ <div class="editor-header">
+ <h3>OK-NTE 配置编辑</h3>
+ <a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
+ <a-tag v-else color="success">已保存</a-tag>
+ </div>
+
</code_context>
<issue_to_address>
**suggestion (bug_risk):** The editor shows an unsaved-changes indicator but has no explicit save action, relying only on auto-save.
`hasChanges` toggles the `有未保存的更改` tag, but `saveAll` is only invoked in `onBeforeUnmount`. Users currently have no way to trigger a save from the UI, and any flow that skips the unmount hook (hard reload, unexpected error, some route-guard flows) risks losing edits. Please add an explicit “保存配置” action (e.g. a button calling `saveAll(false)`) and consider confirming navigation when `hasChanges` is true to avoid data loss for these heavier OK-NTE configs.
Suggested implementation:
```
<div class="editor-header">
<h3>OK-NTE 配置编辑</h3>
<div class="editor-header-right">
<a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
<a-tag v-else color="success">已保存</a-tag>
<a-button
type="primary"
size="small"
:disabled="!hasChanges"
@click="saveAll(false)"
>
保存配置
</a-button>
</div>
</div>
```
To fully wire this up and cover navigation safety:
1. Ensure `saveAll` is exposed in the `<script>` so it can be called from the template (i.e. returned from `setup()` in `<script setup>` or from `setup()`/`methods` in the options API).
2. If you want navigation confirmation, add:
- A `window.beforeunload` listener in `onMounted`/`onBeforeUnmount` that checks `hasChanges` and sets `event.returnValue` to a message when true.
- An `onBeforeRouteLeave` guard from `vue-router` that checks `hasChanges` and shows an Ant Design Vue confirmation modal before allowing route changes.
3. Since I can't see the `<script>` section, please integrate these hooks in the same style already used (Composition API vs Options API) and reuse the existing `hasChanges` ref/state instead of introducing new flags.
</issue_to_address>
### Comment 2
<location path="app/task/OkNte/config_schema.py" line_range="105" />
<code_context>
root = ElementTree.parse(str(ts_path)).getroot()
</code_context>
<issue_to_address>
**security (python.lang.security.use-defused-xml-parse):** The native Python `xml` library is vulnerable to XML External Entity (XXE) attacks. These attacks can leak confidential data and "XML bombs" can cause denial of service. Do not use this library to parse untrusted input. Instead the Python documentation recommends using `defusedxml`.
```suggestion
root = defusedxml.etree.ElementTree.parse(str(ts_path)).getroot()
```
*Source: opengrep*
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
| <div class="editor-header"> | ||
| <h3>OK-NTE 配置编辑</h3> | ||
| <a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag> | ||
| <a-tag v-else color="success">已保存</a-tag> |
There was a problem hiding this comment.
suggestion (bug_risk): 编辑器会显示“有未保存的更改”的提示,但没有明确的保存操作,只依赖自动保存。
hasChanges 用来切换 有未保存的更改 这个标签,但 saveAll 只在 onBeforeUnmount 中被调用。当前用户无法通过 UI 主动触发保存,任何跳过卸载钩子(强制刷新、意外错误、部分路由守卫流程)的情况,都有可能导致编辑内容丢失。请添加一个明确的“保存配置”操作(例如一个调用 saveAll(false) 的按钮),并在 hasChanges 为 true 时考虑在导航时进行确认,以避免这些较重的 OK-NTE 配置数据丢失。
建议实现:
<div class="editor-header">
<h3>OK-NTE 配置编辑</h3>
<div class="editor-header-right">
<a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
<a-tag v-else color="success">已保存</a-tag>
<a-button
type="primary"
size="small"
:disabled="!hasChanges"
@click="saveAll(false)"
>
保存配置
</a-button>
</div>
</div>
要把这一套完全接好并覆盖导航安全性,可以考虑:
- 确保在
<script>中暴露saveAll,以便在模板里调用(即在<script setup>中从setup()返回,或者在传统 Options API 中放进setup()/methods)。 - 如果你希望在导航时进行确认,可以添加:
- 在
onMounted/onBeforeUnmount中添加window.beforeunload监听器,在hasChanges为 true 时设置event.returnValue为某个提示信息。 - 使用
vue-router的onBeforeRouteLeave守卫,在hasChanges为 true 时弹出 Ant Design Vue 的确认对话框,在用户确认后再允许路由跳转。
- 在
- 由于我看不到
<script>部分,请按现有风格集成这些钩子(Composition API 或 Options API),并复用现有的hasChangesref/状态,而不是新增一套标志位。
Original comment in English
suggestion (bug_risk): The editor shows an unsaved-changes indicator but has no explicit save action, relying only on auto-save.
hasChanges toggles the 有未保存的更改 tag, but saveAll is only invoked in onBeforeUnmount. Users currently have no way to trigger a save from the UI, and any flow that skips the unmount hook (hard reload, unexpected error, some route-guard flows) risks losing edits. Please add an explicit “保存配置” action (e.g. a button calling saveAll(false)) and consider confirming navigation when hasChanges is true to avoid data loss for these heavier OK-NTE configs.
Suggested implementation:
<div class="editor-header">
<h3>OK-NTE 配置编辑</h3>
<div class="editor-header-right">
<a-tag v-if="hasChanges" color="warning">有未保存的更改</a-tag>
<a-tag v-else color="success">已保存</a-tag>
<a-button
type="primary"
size="small"
:disabled="!hasChanges"
@click="saveAll(false)"
>
保存配置
</a-button>
</div>
</div>
To fully wire this up and cover navigation safety:
- Ensure
saveAllis exposed in the<script>so it can be called from the template (i.e. returned fromsetup()in<script setup>or fromsetup()/methodsin the options API). - If you want navigation confirmation, add:
- A
window.beforeunloadlistener inonMounted/onBeforeUnmountthat checkshasChangesand setsevent.returnValueto a message when true. - An
onBeforeRouteLeaveguard fromvue-routerthat checkshasChangesand shows an Ant Design Vue confirmation modal before allowing route changes.
- A
- Since I can't see the
<script>section, please integrate these hooks in the same style already used (Composition API vs Options API) and reuse the existinghasChangesref/state instead of introducing new flags.
| """解析 Qt .ts 翻译文件(ok-script 框架级翻译)。""" | ||
| labels: dict[str, str] = {} | ||
| try: | ||
| root = ElementTree.parse(str(ts_path)).getroot() |
There was a problem hiding this comment.
security (python.lang.security.use-defused-xml-parse): 原生 Python xml 库容易受到 XML 外部实体(XXE)攻击。这类攻击可能泄露机密数据,而“XML 炸弹”可能导致拒绝服务。请不要使用该库来解析不受信任的输入。Python 文档推荐使用 defusedxml 作为替代。
| root = ElementTree.parse(str(ts_path)).getroot() | |
| root = defusedxml.etree.ElementTree.parse(str(ts_path)).getroot() |
Source: opengrep
Original comment in English
security (python.lang.security.use-defused-xml-parse): The native Python xml library is vulnerable to XML External Entity (XXE) attacks. These attacks can leak confidential data and "XML bombs" can cause denial of service. Do not use this library to parse untrusted input. Instead the Python documentation recommends using defusedxml.
| root = ElementTree.parse(str(ts_path)).getroot() | |
| root = defusedxml.etree.ElementTree.parse(str(ts_path)).getroot() |
Source: opengrep


这次推到了dev分支
Summary by Sourcery
在后端任务编排、配置模型、API 和前端 UI 中新增对 OK-NTE 脚本的一等公民级支持。
新特性:
OkNteConfig和OkNteUserConfig模型,并将其接入全局脚本/用户配置注册表。ok-nte.exe,并支持日志监控以及可选的游戏启动/关闭流程。增强改进:
Original summary in English
Summary by Sourcery
Add first-class OK-NTE script support across backend task orchestration, configuration models, APIs, and frontend UI.
New Features:
Enhancements: