diff options
| author | 2025-10-25 00:30:48 +0800 | |
|---|---|---|
| committer | 2025-10-25 00:30:48 +0800 | |
| commit | cbc653ffd0ea9abf4360623dc7a7651e1a49cc61 (patch) | |
| tree | ea3c396148158077bae3e77eaa9341f8c1990636 /docs | |
| parent | 08299b37dfda86e56e4f2b442f68ccd2da7a82e3 (diff) | |
| download | conventional_role_play-cbc653ffd0ea9abf4360623dc7a7651e1a49cc61.tar.gz conventional_role_play-cbc653ffd0ea9abf4360623dc7a7651e1a49cc61.zip | |
feat: Implement plugin system with combat tracker and dice analyzer
- Added `plugin_system_demo.py` to demonstrate basic plugin usage, processing, and analysis.
- Created `CombatTrackerPlugin` for tracking combat statistics including damage and healing.
- Developed `DiceAnalyzerPlugin` for analyzing dice rolls and calculating success rates.
- Introduced `renderer_demo.py` for rendering output in HTML, Markdown, and JSON formats.
- Implemented `rule_system_demo.py` to showcase rule engine capabilities with various examples.
- Established core rule engine functionality in `rules.py` with support for conditions and actions.
- Enhanced base plugin structure in `base.py` to support different plugin types (Processor, Renderer, Analyzer).
- Added custom exception handling in `exceptions.py` for better error management.
- Configured logging setup in `logging_config.py` for improved logging capabilities.
- Created unit tests in `test_rust_core.py` to validate core functionalities and performance.
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/source/advanced_usage.md | 457 | ||||
| -rw-r--r-- | docs/source/index.rst | 8 | ||||
| -rw-r--r-- | docs/source/plugin_guide.md | 564 |
3 files changed, 1029 insertions, 0 deletions
diff --git a/docs/source/advanced_usage.md b/docs/source/advanced_usage.md new file mode 100644 index 0000000..7c0ca14 --- /dev/null +++ b/docs/source/advanced_usage.md @@ -0,0 +1,457 @@ +# 高级使用指南 + +## 目录 + +1. [插件系统](#插件系统) +2. [规则引擎](#规则引擎) +3. [自定义渲染器](#自定义渲染器) +4. [性能优化](#性能优化) +5. [错误处理](#错误处理) + +--- + +## 插件系统 + +ConventionalRP 提供了强大的插件系统,允许您扩展和定制框架的功能。 + +### 插件类型 + +#### 1. 解析器插件 (ParserPlugin) + +用于扩展文本解析功能: + +```python +from conventionalrp.plugins import ParserPlugin + +class CustomParserPlugin(ParserPlugin): + def __init__(self): + super().__init__("CustomParser", "1.0.0") + self.priority = 60 # 优先级 + + def initialize(self, config=None): + self.config = config or {} + + def can_parse(self, text: str) -> bool: + # 判断是否可以解析 + return text.startswith("custom:") + + def parse(self, text: str) -> List[Dict[str, Any]]: + # 解析文本 + return [{"type": "custom", "content": text}] +``` + +#### 2. 处理器插件 (ProcessorPlugin) + +用于数据处理和转换: + +```python +from conventionalrp.plugins import ProcessorPlugin + +class CombatTrackerPlugin(ProcessorPlugin): + def __init__(self): + super().__init__("CombatTracker", "1.0.0") + self.total_damage = 0 + + def initialize(self, config=None): + self.config = config or {} + + def process_token(self, token: Dict[str, Any]) -> Dict[str, Any]: + # 处理单个 token + content = token.get("content", "") + + # 检测伤害 + import re + damage_match = re.search(r'(\d+)\s*点?伤害', content) + if damage_match: + damage = int(damage_match.group(1)) + self.total_damage += damage + token["combat_data"] = { + "type": "damage", + "amount": damage, + "total": self.total_damage + } + + return token +``` + +#### 3. 渲染器插件 (RendererPlugin) + +用于自定义输出格式: + +```python +from conventionalrp.plugins import RendererPlugin + +class PlainTextRenderer(RendererPlugin): + def __init__(self): + super().__init__("PlainText", "1.0.0") + + def initialize(self, config=None): + self.config = config or {} + + def render(self, data: Any) -> str: + # 渲染为纯文本 + lines = [] + for item in data: + speaker = item.get("speaker", "") + content = item.get("content", "") + if speaker: + lines.append(f"{speaker}: {content}") + else: + lines.append(content) + return "\n".join(lines) +``` + +#### 4. 分析器插件 (AnalyzerPlugin) + +用于数据分析和统计: + +```python +from conventionalrp.plugins import AnalyzerPlugin + +class SessionAnalyzerPlugin(AnalyzerPlugin): + def __init__(self): + super().__init__("SessionAnalyzer", "1.0.0") + + def initialize(self, config=None): + self.config = config or {} + + def analyze(self, data: Any) -> Dict[str, Any]: + # 分析游戏数据 + stats = { + "total_dialogues": 0, + "total_dice_rolls": 0, + "active_characters": set(), + } + + for token in data: + token_type = token.get("type", "") + if token_type == "dialogue": + stats["total_dialogues"] += 1 + elif token_type == "dice": + stats["total_dice_rolls"] += 1 + + speaker = token.get("speaker", "") + if speaker: + stats["active_characters"].add(speaker) + + stats["active_characters"] = list(stats["active_characters"]) + return stats +``` + +### 使用插件管理器 + +```python +from conventionalrp.plugins import PluginManager + +# 创建管理器 +manager = PluginManager(plugin_dirs=["./my_plugins"]) + +# 发现插件 +discovered = manager.discover_plugins() +print(f"发现 {len(discovered)} 个插件") + +# 注册插件 +my_plugin = MyCustomPlugin() +my_plugin.initialize() +manager.register_plugin(my_plugin) + +# 执行插件 +result = manager.execute_plugins(data, plugin_type=ProcessorPlugin) + +# 启用/禁用插件 +manager.disable_plugin("MyPlugin") +manager.enable_plugin("MyPlugin") + +# 获取统计信息 +stats = manager.get_statistics() +print(stats) +``` + +--- + +## 规则引擎 + +规则引擎允许您定义灵活的数据处理规则。 + +### 规则定义 + +```python +from conventionalrp.core.rules import Rule, RuleEngine + +# 创建规则 +rule = Rule( + name="detect_critical_hit", + conditions={ + "type": {"equals": "dice"}, + "content": {"matches": r"d20=20"} + }, + actions=[ + {"action": "add_tag", "tag": "critical_hit"}, + {"action": "set_field", "field": "is_critical", "value": True} + ], + priority=100 +) +``` + +### 条件运算符 + +- `equals`: 精确匹配 +- `not_equals`: 不等于 +- `contains`: 包含子字符串 +- `not_contains`: 不包含 +- `matches`: 正则表达式匹配 +- `in`: 值在列表中 +- `not_in`: 值不在列表中 +- `greater_than`: 大于 +- `less_than`: 小于 + +### 动作类型 + +- `set_field`: 设置字段值 +- `add_tag`: 添加标签 +- `remove_field`: 删除字段 +- `transform`: 自定义转换函数 + +### 使用规则引擎 + +```python +# 创建引擎 +engine = RuleEngine() + +# 添加规则 +engine.add_rule(rule) + +# 应用规则 +tokens = [ + {"type": "dice", "content": "d20=20"}, + {"type": "dialogue", "content": "我投了大成功!"} +] + +processed_tokens = engine.apply_rules(tokens) + +# 移除规则 +engine.remove_rule("detect_critical_hit") +``` + +### 高级示例:动态规则 + +```python +def create_damage_rule(min_damage: int): + """创建伤害检测规则""" + return Rule( + name=f"detect_damage_{min_damage}", + conditions={ + "content": {"matches": rf"(\d+)点伤害"}, + # 可以添加自定义验证 + }, + actions=[ + {"action": "set_field", "field": "damage_detected", "value": True}, + {"action": "transform", "function": lambda token: { + **token, + "damage_level": "high" if int(re.search(r'(\d+)', token["content"]).group(1)) > min_damage else "normal" + }} + ] + ) + +# 使用 +engine.add_rule(create_damage_rule(20)) +``` + +--- + +## 自定义渲染器 + +### 继承 BaseRenderer + +```python +from conventionalrp.renderers.base import BaseRenderer + +class LaTeXRenderer(BaseRenderer): + def __init__(self): + super().__init__() + + def render(self, data: List[Dict[str, Any]]) -> str: + latex = r"\documentclass{article}" + "\n" + latex += r"\begin{document}" + "\n" + + for item in data: + token_type = item.get("type", "") + content = item.get("content", "") + + if token_type == "dialogue": + speaker = item.get("speaker", "") + latex += rf"\textbf{{{speaker}:}} {content}\\" + "\n" + else: + latex += f"{content}\\\\\n" + + latex += r"\end{document}" + "\n" + return latex +``` + +### 使用主题系统 + +```python +from conventionalrp.renderers.html_renderer import HTMLRenderer + +# 使用内置主题 +renderer = HTMLRenderer(theme="dark") + +# 使用自定义 CSS +custom_css = """ +body { + background: linear-gradient(to bottom, #2c3e50, #3498db); +} +.token { + box-shadow: 0 4px 6px rgba(0,0,0,0.3); +} +""" + +renderer = HTMLRenderer(theme="light", custom_css=custom_css) +output = renderer.render(data) +``` + +--- + +## 性能优化 + +### 1. 使用 Rust 核心 + +编译 Rust 模块获得更好的性能: + +```bash +maturin develop --uv --release +``` + +### 2. 批量处理 + +```python +# 不推荐:逐个处理 +for token in tokens: + processor.process(token) + +# 推荐:批量处理 +processed_tokens = processor.process_batch(tokens) +``` + +### 3. 规则优化 + +```python +# 设置合适的优先级 +Rule(name="fast_rule", priority=100, ...) # 先执行 +Rule(name="slow_rule", priority=10, ...) # 后执行 + +# 预编译正则表达式 +import re +pattern = re.compile(r'd\d+') # 编译一次 +rule = Rule( + conditions={"content": {"matches": pattern}}, + ... +) +``` + +### 4. 缓存结果 + +```python +from functools import lru_cache + +@lru_cache(maxsize=128) +def expensive_operation(data: str) -> str: + # 昂贵的计算 + return result +``` + +### 性能基准测试 + +```bash +# 运行基准测试 +python benchmarks/benchmark_parser.py +python benchmarks/benchmark_rules.py +``` + +--- + +## 错误处理 + +### 自定义异常 + +```python +from conventionalrp.utils.exceptions import ( + ParsingError, + RuleError, + PluginError +) + +try: + parser.parse_log("invalid.txt") +except ParsingError as e: + print(f"解析错误: {e}") +except FileNotFoundError as e: + print(f"文件未找到: {e}") +``` + +### 日志配置 + +```python +from conventionalrp.utils.logging_config import setup_logging +import logging + +# 设置日志级别 +setup_logging(level=logging.DEBUG) + +# 在您的代码中使用 +logger = logging.getLogger(__name__) +logger.debug("调试信息") +logger.info("普通信息") +logger.warning("警告") +logger.error("错误") +``` + +### 最佳实践 + +1. **始终验证输入** + ```python + def process_token(token: Dict[str, Any]) -> Dict[str, Any]: + if not isinstance(token, dict): + raise TypeError("Token must be a dictionary") + + if "type" not in token: + raise ValueError("Token must have a 'type' field") + + return processed_token + ``` + +2. **使用类型提示** + ```python + from typing import List, Dict, Any, Optional + + def parse_data(text: str) -> List[Dict[str, Any]]: + ... + ``` + +3. **提供清晰的错误消息** + ```python + if not file_path.exists(): + raise FileNotFoundError( + f"Log file not found: {file_path}\n" + f"Please check the file path and try again." + ) + ``` + +--- + +## 完整示例 + +查看 `examples/` 目录获取更多示例: + +- `basic_usage.py` - 基本使用 +- `rule_system_demo.py` - 规则系统演示 +- `plugin_system_demo.py` - 插件系统演示 +- `renderer_demo.py` - 渲染器演示 + +--- + +## 下一步 + +- 阅读 [API 文档](api.md) +- 查看 [插件开发指南](plugin_guide.md) +- 参与 [GitHub 讨论](https://github.com/HydroRoll-Team/conventional_role_play/discussions) diff --git a/docs/source/index.rst b/docs/source/index.rst index e69de29..e3b529f 100644 --- a/docs/source/index.rst +++ b/docs/source/index.rst @@ -0,0 +1,8 @@ +.. toctree:: + :maxdepth: 2 + :caption: 内容目录 + + usage <usage.md> + advanced_usage <advanced_usage.md> + plugin_guide <plugin_guide.md> + api <api.md>
\ No newline at end of file diff --git a/docs/source/plugin_guide.md b/docs/source/plugin_guide.md new file mode 100644 index 0000000..7c146fe --- /dev/null +++ b/docs/source/plugin_guide.md @@ -0,0 +1,564 @@ +# 插件开发指南 + +本指南将帮助您创建自己的 ConventionalRP 插件。 + +## 目录 + +1. [插件基础](#插件基础) +2. [插件类型](#插件类型) +3. [开发流程](#开发流程) +4. [最佳实践](#最佳实践) +5. [发布插件](#发布插件) + +--- + +## 插件基础 + +### 什么是插件? + +插件是扩展 ConventionalRP 功能的独立模块。每个插件继承自基础 `Plugin` 类,并实现特定的接口。 + +### 插件生命周期 + +1. **发现** - PluginManager 扫描插件目录 +2. **加载** - 导入插件模块 +3. **初始化** - 调用 `initialize()` 方法 +4. **启用** - 调用 `on_enable()` 钩子 +5. **执行** - 调用 `process()` 方法处理数据 +6. **禁用** - 调用 `on_disable()` 钩子 + +### 基本结构 + +```python +from conventionalrp.plugins import Plugin +from typing import Any, Dict, Optional + +class MyPlugin(Plugin): + def __init__(self): + super().__init__(name="MyPlugin", version="1.0.0") + # 初始化插件状态 + self.data = {} + + def initialize(self, config: Optional[Dict[str, Any]] = None): + """初始化插件,加载配置""" + self.config = config or {} + self.logger.info(f"{self.name} initialized with config: {self.config}") + + def process(self, data: Any) -> Any: + """处理数据""" + self.logger.debug(f"Processing data: {data}") + # 实现您的处理逻辑 + return data + + def on_enable(self): + """插件启用时调用""" + super().on_enable() + # 执行启用逻辑(如打开文件、建立连接等) + + def on_disable(self): + """插件禁用时调用""" + # 执行清理逻辑(如关闭文件、断开连接等) + super().on_disable() +``` + +--- + +## 插件类型 + +### 1. 解析器插件 (ParserPlugin) + +解析器插件用于识别和解析特定格式的文本。 + +#### 接口 + +```python +from conventionalrp.plugins import ParserPlugin + +class MyParserPlugin(ParserPlugin): + def can_parse(self, text: str) -> bool: + """判断是否可以解析给定文本""" + raise NotImplementedError + + def parse(self, text: str) -> List[Dict[str, Any]]: + """解析文本并返回结果""" + raise NotImplementedError +``` + +#### 示例:CoC 规则解析器 + +```python +import re +from conventionalrp.plugins import ParserPlugin + +class CoCParserPlugin(ParserPlugin): + """Call of Cthulhu 规则解析器""" + + def __init__(self): + super().__init__("CoCParser", "1.0.0") + self.priority = 60 + + # CoC 特有的模式 + self.skill_check_pattern = re.compile( + r'\.(?:rc|san|sc)\s+(.+)', + re.IGNORECASE + ) + self.sanity_pattern = re.compile( + r'(\d+)/(\d+d\d+)', + re.IGNORECASE + ) + + def initialize(self, config=None): + self.config = config or {} + + def can_parse(self, text: str) -> bool: + """检查是否是 CoC 指令""" + return bool(self.skill_check_pattern.match(text)) + + def parse(self, text: str) -> List[Dict[str, Any]]: + """解析 CoC 指令""" + results = [] + + match = self.skill_check_pattern.match(text) + if match: + command_text = match.group(1) + + # 解析 SAN 检定 + san_match = self.sanity_pattern.search(command_text) + if san_match: + results.append({ + "type": "sanity_check", + "success_loss": san_match.group(1), + "failure_loss": san_match.group(2), + "content": text, + }) + else: + # 普通技能检定 + results.append({ + "type": "skill_check", + "skill": command_text.strip(), + "content": text, + }) + + return results +``` + +### 2. 处理器插件 (ProcessorPlugin) + +处理器插件用于转换和增强数据。 + +#### 示例:经验值追踪器 + +```python +from conventionalrp.plugins import ProcessorPlugin +import re + +class ExperienceTrackerPlugin(ProcessorPlugin): + """经验值追踪插件""" + + def __init__(self): + super().__init__("ExperienceTracker", "1.0.0") + self.character_exp = {} + self.exp_pattern = re.compile(r'获得\s*(\d+)\s*点?经验', re.IGNORECASE) + + def initialize(self, config=None): + self.config = config or {} + # 加载初始经验值 + if "initial_exp" in self.config: + self.character_exp = self.config["initial_exp"].copy() + + def process_token(self, token: Dict[str, Any]) -> Dict[str, Any]: + """处理 token 并追踪经验值""" + content = token.get("content", "") + speaker = token.get("speaker", "") + + # 检测经验值获取 + match = self.exp_pattern.search(content) + if match and speaker: + exp_gained = int(match.group(1)) + + if speaker not in self.character_exp: + self.character_exp[speaker] = 0 + + self.character_exp[speaker] += exp_gained + + # 添加经验值信息到 token + token["exp_data"] = { + "gained": exp_gained, + "total": self.character_exp[speaker], + "character": speaker, + } + + self.logger.info(f"{speaker} 获得 {exp_gained} 经验,总计 {self.character_exp[speaker]}") + + return token + + def get_leaderboard(self) -> List[Dict[str, Any]]: + """获取经验值排行榜""" + sorted_chars = sorted( + self.character_exp.items(), + key=lambda x: x[1], + reverse=True + ) + return [ + {"character": char, "exp": exp} + for char, exp in sorted_chars + ] +``` + +### 3. 渲染器插件 (RendererPlugin) + +渲染器插件用于生成特定格式的输出。 + +#### 示例:Discord Markdown 渲染器 + +```python +from conventionalrp.plugins import RendererPlugin + +class DiscordRenderer(RendererPlugin): + """Discord Markdown 渲染器""" + + def __init__(self): + super().__init__("DiscordRenderer", "1.0.0") + + def initialize(self, config=None): + self.config = config or {} + self.use_embeds = self.config.get("use_embeds", False) + + def render(self, data: Any) -> str: + """渲染为 Discord 格式""" + output = [] + + for token in data: + token_type = token.get("type", "unknown") + speaker = token.get("speaker", "") + content = token.get("content", "") + + if token_type == "dialogue": + # 使用 Discord 的粗体和引用 + output.append(f"**{speaker}:** {content}") + + elif token_type == "dice": + # 使用代码块高亮骰子结果 + result = token.get("result", "?") + output.append(f"`{content}` → **{result}**") + + elif token_type == "narration": + # 使用斜体表示旁白 + output.append(f"*{content}*") + + elif token_type == "system": + # 使用代码块表示系统消息 + output.append(f"```\n{content}\n```") + + else: + output.append(content) + + return "\n\n".join(output) +``` + +### 4. 分析器插件 (AnalyzerPlugin) + +分析器插件用于统计和分析数据。 + +#### 示例:对话分析器 + +```python +from conventionalrp.plugins import AnalyzerPlugin +from collections import Counter + +class DialogueAnalyzerPlugin(AnalyzerPlugin): + """对话分析插件""" + + def __init__(self): + super().__init__("DialogueAnalyzer", "1.0.0") + + def initialize(self, config=None): + self.config = config or {} + + def analyze(self, data: Any) -> Dict[str, Any]: + """分析对话数据""" + dialogue_count = Counter() + word_count = Counter() + total_words = 0 + + for token in data: + if token.get("type") == "dialogue": + speaker = token.get("speaker", "Unknown") + content = token.get("content", "") + + # 统计对话次数 + dialogue_count[speaker] += 1 + + # 统计词数 + words = len(content.split()) + word_count[speaker] += words + total_words += words + + # 计算参与度 + most_active = dialogue_count.most_common(1) + most_talkative = word_count.most_common(1) + + return { + "total_dialogues": sum(dialogue_count.values()), + "total_words": total_words, + "dialogue_count": dict(dialogue_count), + "word_count": dict(word_count), + "most_active_character": most_active[0][0] if most_active else None, + "most_talkative_character": most_talkative[0][0] if most_talkative else None, + "average_words_per_dialogue": total_words / sum(dialogue_count.values()) if dialogue_count else 0, + } +``` + +--- + +## 开发流程 + +### 1. 创建插件项目 + +```bash +mkdir my_plugin +cd my_plugin +touch my_plugin.py +touch config.json +touch README.md +``` + +### 2. 实现插件 + +```python +# my_plugin.py +from conventionalrp.plugins import ProcessorPlugin + +class MyPlugin(ProcessorPlugin): + # ... 实现代码 + pass +``` + +### 3. 添加配置 + +```json +{ + "name": "MyPlugin", + "version": "1.0.0", + "description": "My custom plugin", + "author": "Your Name", + "settings": { + "enable_feature_x": true, + "threshold": 10 + } +} +``` + +### 4. 测试插件 + +```python +# test_my_plugin.py +import unittest +from my_plugin import MyPlugin + +class TestMyPlugin(unittest.TestCase): + def setUp(self): + self.plugin = MyPlugin() + self.plugin.initialize() + + def test_process(self): + test_data = [{"type": "test", "content": "test"}] + result = self.plugin.process(test_data) + self.assertIsNotNone(result) + + def test_enable_disable(self): + self.assertTrue(self.plugin.enabled) + self.plugin.on_disable() + self.assertFalse(self.plugin.enabled) + +if __name__ == "__main__": + unittest.main() +``` + +### 5. 集成测试 + +```python +# integration_test.py +from conventionalrp.plugins import PluginManager +from my_plugin import MyPlugin + +manager = PluginManager() +plugin = MyPlugin() +plugin.initialize({"test": True}) +manager.register_plugin(plugin) + +# 测试数据 +test_data = [...] + +# 执行插件 +result = manager.execute_plugins(test_data) +print(result) +``` + +--- + +## 最佳实践 + +### 1. 命名约定 + +- 插件类名使用 PascalCase,如 `MyCustomPlugin` +- 文件名使用 snake_case,如 `my_custom_plugin.py` +- 配置键使用 snake_case + +### 2. 日志记录 + +```python +def process_token(self, token): + self.logger.debug(f"Processing token: {token['type']}") + + try: + result = self._do_processing(token) + self.logger.info("Processing successful") + return result + except Exception as e: + self.logger.error(f"Processing failed: {e}") + raise +``` + +### 3. 错误处理 + +```python +from conventionalrp.utils.exceptions import PluginError + +def initialize(self, config=None): + try: + self.config = config or {} + # 验证必需的配置 + if "required_key" not in self.config: + raise PluginError( + f"{self.name}: Missing required configuration 'required_key'" + ) + except Exception as e: + self.logger.error(f"Initialization failed: {e}") + raise +``` + +### 4. 性能优化 + +```python +# 使用缓存 +from functools import lru_cache + +@lru_cache(maxsize=128) +def expensive_operation(self, key: str) -> Any: + # 昂贵的计算 + return result + +# 批量处理 +def process(self, data: List[Dict]) -> List[Dict]: + # 一次性处理所有数据,而不是逐个处理 + return [self.process_token(token) for token in data] +``` + +### 5. 文档注释 + +```python +class MyPlugin(Plugin): + """ + 我的自定义插件 + + 这个插件用于... + + Attributes: + setting_x: 设置 X 的说明 + setting_y: 设置 Y 的说明 + + Example: + >>> plugin = MyPlugin() + >>> plugin.initialize({"setting_x": True}) + >>> result = plugin.process(data) + """ + + def process_token(self, token: Dict[str, Any]) -> Dict[str, Any]: + """ + 处理单个 token + + Args: + token: 输入 token + + Returns: + 处理后的 token + + Raises: + PluginError: 如果处理失败 + """ + pass +``` + +--- + +## 发布插件 + +### 1. 准备文件 + +创建以下文件: +- `README.md` - 插件说明 +- `LICENSE` - 开源许可证 +- `requirements.txt` - 依赖列表 +- `setup.py` 或 `pyproject.toml` - 打包配置 + +### 2. 打包 + +```bash +# 使用 setuptools +python setup.py sdist bdist_wheel + +# 或使用 poetry +poetry build +``` + +### 3. 发布 + +```bash +# 发布到 PyPI +twine upload dist/* + +# 或发布到 GitHub +git tag v1.0.0 +git push origin v1.0.0 +``` + +### 4. 文档 + +在 README.md 中包含: +- 插件描述 +- 安装方法 +- 使用示例 +- 配置选项 +- API 文档 +- 许可证信息 + +--- + +## 示例项目结构 + +``` +my_plugin/ +├── README.md +├── LICENSE +├── requirements.txt +├── setup.py +├── my_plugin/ +│ ├── __init__.py +│ ├── plugin.py +│ └── utils.py +├── tests/ +│ ├── test_plugin.py +│ └── test_utils.py +└── examples/ + └── example_usage.py +``` + +--- + +## 相关资源 + +- [插件系统演示](../../examples/plugin_system_demo.py) +- [示例插件](../../examples/plugins/) +- [API 文档](api.md) +- [高级使用指南](advanced_usage.md) |
