docs: 为全部代码补充中文注释并加入 AGENTS 注释规范

This commit is contained in:
cat-shark
2026-08-13 22:09:55 +08:00
parent e974939df8
commit 6355579aa8
5 changed files with 41 additions and 1 deletions
+7
View File
@@ -24,3 +24,10 @@ uv run python -m wov_node_echo
- Python 环境统一使用 uv 管理。 - Python 环境统一使用 uv 管理。
- 测试必须达到 100% 行覆盖率,且只能通过调用真实代码路径覆盖。 - 测试必须达到 100% 行覆盖率,且只能通过调用真实代码路径覆盖。
## 代码注释规范
- 本仓库所有源码(Python、TOML 等支持注释的文件)必须配有详细中文注释,说明模块职责、核心函数的作用以及关键逻辑,确保后续维护人员可以快速理解代码工作原理。
- 新增或修改代码时,必须同步补充或更新对应注释;不得删除已有注释。
- 测试代码同样必须配有中文注释,说明每条测试验证的行为。
- JSON 数据文件(`node.manifest.json`)不支持注释,字段语义以 `wov-sdk``NodeManifest` 模型注释和本文档输入/输出说明为准。
+5
View File
@@ -1,3 +1,4 @@
# WOV Echo 节点配置:使用 uv 管理环境与依赖。
[project] [project]
name = "wov-node-echo" name = "wov-node-echo"
version = "0.1.0" version = "0.1.0"
@@ -5,16 +6,20 @@ description = "WOV example echo node"
requires-python = ">=3.11" requires-python = ">=3.11"
dependencies = ["wov-sdk"] dependencies = ["wov-sdk"]
# 本地路径依赖 wov-sdk,不发布到公共包索引。
[tool.uv.sources] [tool.uv.sources]
wov-sdk = { path = "../wov-sdk" } wov-sdk = { path = "../wov-sdk" }
# 开发依赖:pytest 与覆盖率工具。
[dependency-groups] [dependency-groups]
dev = ["pytest", "pytest-cov"] dev = ["pytest", "pytest-cov"]
# pytest 配置:强制 100% 行覆盖率,并允许直接 import 包源码。
[tool.pytest.ini_options] [tool.pytest.ini_options]
testpaths = ["tests"] testpaths = ["tests"]
pythonpath = ["."] pythonpath = ["."]
addopts = "--cov=wov_node_echo --cov-report=term-missing --cov-fail-under=100" addopts = "--cov=wov_node_echo --cov-report=term-missing --cov-fail-under=100"
# 仅打包节点包本身。
[tool.setuptools] [tool.setuptools]
packages = ["wov_node_echo"] packages = ["wov_node_echo"]
+10
View File
@@ -1,3 +1,8 @@
"""Echo 节点测试。
覆盖直接文本、绝对/相对文件 URI、默认文本和入口点启动等真实代码路径。
"""
import runpy import runpy
from pathlib import Path from pathlib import Path
@@ -6,6 +11,7 @@ from wov_sdk.models import InvokeRequest
def test_invoke_text(tmp_path) -> None: def test_invoke_text(tmp_path) -> None:
"""验证直接传入 text 时节点原样写出文本。"""
response = invoke( response = invoke(
InvokeRequest( InvokeRequest(
run_id="run_1", run_id="run_1",
@@ -20,6 +26,7 @@ def test_invoke_text(tmp_path) -> None:
def test_invoke_absolute_file(tmp_path) -> None: def test_invoke_absolute_file(tmp_path) -> None:
"""验证绝对路径 file_uri 的文件内容被读取为输入。"""
source = tmp_path / "input.txt" source = tmp_path / "input.txt"
source.write_text("from file", encoding="utf-8") source.write_text("from file", encoding="utf-8")
response = invoke( response = invoke(
@@ -35,6 +42,7 @@ def test_invoke_absolute_file(tmp_path) -> None:
def test_invoke_relative_file(tmp_path, monkeypatch) -> None: def test_invoke_relative_file(tmp_path, monkeypatch) -> None:
"""验证相对路径 file_uri 以节点仓库根目录为基准解析。"""
node_root = Path(__file__).resolve().parent.parent node_root = Path(__file__).resolve().parent.parent
source = node_root / "relative_input.txt" source = node_root / "relative_input.txt"
source.write_text("relative", encoding="utf-8") source.write_text("relative", encoding="utf-8")
@@ -55,6 +63,7 @@ def test_invoke_relative_file(tmp_path, monkeypatch) -> None:
def test_invoke_default_text(tmp_path) -> None: def test_invoke_default_text(tmp_path) -> None:
"""验证无任何输入时节点返回默认文本。"""
response = invoke( response = invoke(
InvokeRequest( InvokeRequest(
run_id="run_4", run_id="run_4",
@@ -68,6 +77,7 @@ def test_invoke_default_text(tmp_path) -> None:
def test_main_entrypoint(monkeypatch, tmp_path) -> None: def test_main_entrypoint(monkeypatch, tmp_path) -> None:
"""验证 python -m wov_node_echo 会加载 echo manifest 并启动服务。"""
module_path = Path(__file__).resolve().parent.parent / "wov_node_echo" / "__main__.py" module_path = Path(__file__).resolve().parent.parent / "wov_node_echo" / "__main__.py"
captured = {} captured = {}
+5 -1
View File
@@ -1 +1,5 @@
"""WOV example echo node.""" """WOV Echo 示例节点。
该节点用于验证节点协议、独立 Git 仓库管理和生命周期回收机制。它把输入文本
原样写入产物文件,作为最简的端到端链路验证。
"""
+14
View File
@@ -1,3 +1,9 @@
"""Echo 节点入口。
通过 wov_sdk.server.run_node 启动标准节点 HTTP 服务,并注册 invoke 处理器。
节点启动后打印 WOV_NODE_READY 行,等待 wov-api 的 NodeManager 调用。
"""
from __future__ import annotations from __future__ import annotations
import json import json
@@ -8,10 +14,13 @@ from wov_sdk.server import run_node
def _resolve_input_text(request: InvokeRequest, node_root: Path) -> str: def _resolve_input_text(request: InvokeRequest, node_root: Path) -> str:
"""按优先级解析输入文本:直接文本 > 文件 URI > 默认字符串。"""
# 优先使用请求中直接携带的 text 字段。
text = request.inputs.get("text") text = request.inputs.get("text")
if text is not None: if text is not None:
return str(text) return str(text)
# 其次读取 file_uri 指向的文件;相对路径以节点仓库根目录为基准。
file_uri = request.inputs.get("file_uri") file_uri = request.inputs.get("file_uri")
if file_uri: if file_uri:
path = Path(file_uri) path = Path(file_uri)
@@ -19,15 +28,19 @@ def _resolve_input_text(request: InvokeRequest, node_root: Path) -> str:
path = node_root / path path = node_root / path
return path.read_text(encoding="utf-8") return path.read_text(encoding="utf-8")
# 都没有时返回固定文本,保证节点总有可演示的输出。
return "echo" return "echo"
def invoke(request: InvokeRequest) -> InvokeResponse: def invoke(request: InvokeRequest) -> InvokeResponse:
"""处理节点调用:把解析出的文本写入产物并返回 URI。"""
# 节点仓库根目录用于解析相对文件路径。
node_root = Path(__file__).resolve().parent.parent node_root = Path(__file__).resolve().parent.parent
output_dir = Path(request.output_dir) output_dir = Path(request.output_dir)
output_dir.mkdir(parents=True, exist_ok=True) output_dir.mkdir(parents=True, exist_ok=True)
text = _resolve_input_text(request, node_root) text = _resolve_input_text(request, node_root)
# 产物必须落在请求给定的 output_dir,调度器按 run 与节点组织目录。
output_path = output_dir / "echo.txt" output_path = output_dir / "echo.txt"
output_path.write_text(text, encoding="utf-8") output_path.write_text(text, encoding="utf-8")
@@ -41,6 +54,7 @@ def invoke(request: InvokeRequest) -> InvokeResponse:
def main() -> None: def main() -> None:
"""加载节点清单并以本模块的 invoke 处理器启动服务。"""
manifest_path = Path(__file__).resolve().parent.parent / "node.manifest.json" manifest_path = Path(__file__).resolve().parent.parent / "node.manifest.json"
with open(manifest_path, "r", encoding="utf-8") as f: with open(manifest_path, "r", encoding="utf-8") as f:
manifest = NodeManifest.from_dict(json.load(f)) manifest = NodeManifest.from_dict(json.load(f))