docs: 为全部代码补充中文注释并加入 AGENTS 注释规范
This commit is contained in:
@@ -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` 模型注释和本文档输入/输出说明为准。
|
||||||
|
|||||||
@@ -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"]
|
||||||
|
|||||||
@@ -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 = {}
|
||||||
|
|
||||||
|
|||||||
@@ -1 +1,5 @@
|
|||||||
"""WOV example echo node."""
|
"""WOV Echo 示例节点。
|
||||||
|
|
||||||
|
该节点用于验证节点协议、独立 Git 仓库管理和生命周期回收机制。它把输入文本
|
||||||
|
原样写入产物文件,作为最简的端到端链路验证。
|
||||||
|
"""
|
||||||
|
|||||||
@@ -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))
|
||||||
|
|||||||
Reference in New Issue
Block a user