aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/source/advanced_usage.md457
-rw-r--r--docs/source/index.rst8
-rw-r--r--docs/source/plugin_guide.md564
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)