soothe-plugins 0.2.6__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- soothe_plugins-0.2.6/.github/workflows/ci.yml +70 -0
- soothe_plugins-0.2.6/.github/workflows/release.yml +74 -0
- soothe_plugins-0.2.6/.gitignore +34 -0
- soothe_plugins-0.2.6/CONTRIBUTING.md +328 -0
- soothe_plugins-0.2.6/MANIFEST.md +154 -0
- soothe_plugins-0.2.6/Makefile +646 -0
- soothe_plugins-0.2.6/PKG-INFO +156 -0
- soothe_plugins-0.2.6/README.md +120 -0
- soothe_plugins-0.2.6/docs/RFC-601-community-agents.md +349 -0
- soothe_plugins-0.2.6/pyproject.toml +89 -0
- soothe_plugins-0.2.6/skills/create_subagent/SKILL.md +301 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/PLUGIN_TEMPLATE.md +40 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/README.md.template +152 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/__init__.py.template +174 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/events.py.template +34 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/implementation.py.template +112 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/models.py.template +39 -0
- soothe_plugins-0.2.6/src/soothe_plugins/.plugin_template/state.py.template +48 -0
- soothe_plugins-0.2.6/src/soothe_plugins/README.md +150 -0
- soothe_plugins-0.2.6/src/soothe_plugins/__init__.py +20 -0
- soothe_plugins-0.2.6/src/soothe_plugins/_paths.py +17 -0
- soothe_plugins-0.2.6/src/soothe_plugins/sample_echo/__init__.py +44 -0
- soothe_plugins-0.2.6/src/soothe_plugins/sample_echo/implementation.py +47 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/__init__.py +288 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/events.py +148 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/indexer.py +312 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/models.py +36 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/retriever.py +165 -0
- soothe_plugins-0.2.6/src/soothe_plugins/skillify/warehouse.py +96 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/__init__.py +507 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/analyzer.py +81 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/composer.py +322 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/events.py +223 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/generator.py +177 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/models.py +136 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/registry.py +214 -0
- soothe_plugins-0.2.6/src/soothe_plugins/weaver/reuse.py +151 -0
- soothe_plugins-0.2.6/tests/conftest.py +13 -0
- soothe_plugins-0.2.6/tests/integration/test_plugin_loading.py +145 -0
- soothe_plugins-0.2.6/tests/test_sample_echo/test_sample_echo_plugin.py +30 -0
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@v5
|
|
18
|
+
|
|
19
|
+
- name: Install uv
|
|
20
|
+
uses: astral-sh/setup-uv@v4
|
|
21
|
+
with:
|
|
22
|
+
version: "latest"
|
|
23
|
+
|
|
24
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
25
|
+
run: uv python install ${{ matrix.python-version }}
|
|
26
|
+
|
|
27
|
+
- name: Install dependencies
|
|
28
|
+
run: uv sync --all-extras
|
|
29
|
+
|
|
30
|
+
- name: Run linting
|
|
31
|
+
run: |
|
|
32
|
+
uv run ruff check src/ tests/ --output-format=github
|
|
33
|
+
uv run ruff format --check src/ tests/
|
|
34
|
+
|
|
35
|
+
- name: Run tests
|
|
36
|
+
run: uv run pytest tests/ -v --tb=short
|
|
37
|
+
|
|
38
|
+
- name: Run tests with coverage
|
|
39
|
+
if: matrix.python-version == '3.12'
|
|
40
|
+
run: uv run pytest tests/ --cov=src/soothe_plugins --cov-report=xml --cov-report=term-missing
|
|
41
|
+
|
|
42
|
+
- name: Upload coverage report
|
|
43
|
+
if: matrix.python-version == '3.12'
|
|
44
|
+
uses: actions/upload-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: coverage-report
|
|
47
|
+
path: coverage.xml
|
|
48
|
+
|
|
49
|
+
build:
|
|
50
|
+
runs-on: ubuntu-latest
|
|
51
|
+
needs: test
|
|
52
|
+
|
|
53
|
+
steps:
|
|
54
|
+
- uses: actions/checkout@v5
|
|
55
|
+
|
|
56
|
+
- name: Install uv
|
|
57
|
+
uses: astral-sh/setup-uv@v4
|
|
58
|
+
with:
|
|
59
|
+
version: "latest"
|
|
60
|
+
|
|
61
|
+
- name: Set up Python
|
|
62
|
+
run: uv python install 3.12
|
|
63
|
+
|
|
64
|
+
- name: Build package
|
|
65
|
+
run: uv build
|
|
66
|
+
|
|
67
|
+
- name: Verify package
|
|
68
|
+
run: |
|
|
69
|
+
uv run twine check dist/*
|
|
70
|
+
echo "✅ Package built and verified"
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
name: Release soothe-plugins
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
id-token: write # IMPORTANT: this permission is mandatory for trusted publishing
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
deploy:
|
|
13
|
+
runs-on: ubuntu-latest
|
|
14
|
+
environment:
|
|
15
|
+
name: pypi
|
|
16
|
+
url: https://pypi.org/p/soothe-plugins
|
|
17
|
+
|
|
18
|
+
steps:
|
|
19
|
+
- uses: actions/checkout@v5
|
|
20
|
+
|
|
21
|
+
- name: Install uv
|
|
22
|
+
uses: astral-sh/setup-uv@v4
|
|
23
|
+
with:
|
|
24
|
+
version: "latest"
|
|
25
|
+
|
|
26
|
+
- name: Set up Python
|
|
27
|
+
run: uv python install 3.12
|
|
28
|
+
|
|
29
|
+
- name: Install dependencies
|
|
30
|
+
run: uv sync --all-extras
|
|
31
|
+
|
|
32
|
+
- name: Get version
|
|
33
|
+
id: version
|
|
34
|
+
run: |
|
|
35
|
+
VERSION=$(grep '^version = "' pyproject.toml | sed 's/version = "\(.*\)"/\1/')
|
|
36
|
+
echo "version=$VERSION" >> $GITHUB_OUTPUT
|
|
37
|
+
|
|
38
|
+
- name: Check if version exists on PyPI
|
|
39
|
+
id: check
|
|
40
|
+
run: |
|
|
41
|
+
VERSION="${{ steps.version.outputs.version }}"
|
|
42
|
+
echo "Checking if soothe-plugins $VERSION exists on PyPI..."
|
|
43
|
+
if pip index versions soothe-plugins 2>/dev/null | grep -q "$VERSION"; then
|
|
44
|
+
echo "exists=true" >> $GITHUB_OUTPUT
|
|
45
|
+
echo "⚠️ Version $VERSION already exists on PyPI, skipping publish"
|
|
46
|
+
else
|
|
47
|
+
echo "exists=false" >> $GITHUB_OUTPUT
|
|
48
|
+
echo "✓ Version $VERSION not found on PyPI, will publish"
|
|
49
|
+
fi
|
|
50
|
+
|
|
51
|
+
- name: Build package
|
|
52
|
+
if: steps.check.outputs.exists == 'false'
|
|
53
|
+
run: uv build
|
|
54
|
+
|
|
55
|
+
- name: Verify dist directory
|
|
56
|
+
if: steps.check.outputs.exists == 'false'
|
|
57
|
+
run: |
|
|
58
|
+
if [ ! -d "dist" ]; then
|
|
59
|
+
echo "❌ Error: dist directory not found"
|
|
60
|
+
exit 1
|
|
61
|
+
fi
|
|
62
|
+
if [ -z "$(ls -A dist)" ]; then
|
|
63
|
+
echo "❌ Error: dist directory is empty"
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
echo "✓ dist directory exists and contains packages"
|
|
67
|
+
ls -la dist/
|
|
68
|
+
|
|
69
|
+
- name: Publish to PyPI
|
|
70
|
+
if: steps.check.outputs.exists == 'false'
|
|
71
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
72
|
+
with:
|
|
73
|
+
verbose: true
|
|
74
|
+
print-hash: true
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
*$py.class
|
|
4
|
+
*.so
|
|
5
|
+
.Python
|
|
6
|
+
build/
|
|
7
|
+
develop-eggs/
|
|
8
|
+
dist/
|
|
9
|
+
downloads/
|
|
10
|
+
eggs/
|
|
11
|
+
.eggs/
|
|
12
|
+
lib/
|
|
13
|
+
lib64/
|
|
14
|
+
parts/
|
|
15
|
+
sdist/
|
|
16
|
+
var/
|
|
17
|
+
wheels/
|
|
18
|
+
*.egg-info/
|
|
19
|
+
.installed.cfg
|
|
20
|
+
*.egg
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
htmlcov/
|
|
24
|
+
.ruff_cache/
|
|
25
|
+
.mypy_cache/
|
|
26
|
+
.vscode/
|
|
27
|
+
.idea/
|
|
28
|
+
*.swp
|
|
29
|
+
*.swo
|
|
30
|
+
.env
|
|
31
|
+
.venv
|
|
32
|
+
venv/
|
|
33
|
+
ENV/
|
|
34
|
+
env/
|
|
@@ -0,0 +1,328 @@
|
|
|
1
|
+
# Contributing to Soothe Community Plugins
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to soothe-plugins! This guide will help you add new plugins, tools, and subagents.
|
|
4
|
+
|
|
5
|
+
## Table of Contents
|
|
6
|
+
|
|
7
|
+
- [Adding a New Plugin](#adding-a-new-plugin)
|
|
8
|
+
- [Plugin Structure](#plugin-structure)
|
|
9
|
+
- [Development Workflow](#development-workflow)
|
|
10
|
+
- [Testing Guidelines](#testing-guidelines)
|
|
11
|
+
- [Code Standards](#code-standards)
|
|
12
|
+
|
|
13
|
+
## Adding a New Plugin
|
|
14
|
+
|
|
15
|
+
### 1. Create Plugin Package
|
|
16
|
+
|
|
17
|
+
Create a new package in `src/soothe_plugins/your_plugin/`:
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
src/soothe_plugins/
|
|
21
|
+
├── __init__.py
|
|
22
|
+
├── paperscout/
|
|
23
|
+
│ └── ...
|
|
24
|
+
└── your_plugin/
|
|
25
|
+
├── __init__.py # Plugin class with @plugin decorator
|
|
26
|
+
├── events.py # Custom events (optional)
|
|
27
|
+
├── models.py # Data models
|
|
28
|
+
├── state.py # State definitions (if subagent)
|
|
29
|
+
├── implementation.py # Core logic
|
|
30
|
+
└── README.md # Plugin documentation
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
### 2. Define Plugin Class
|
|
34
|
+
|
|
35
|
+
Create your plugin class in `__init__.py`:
|
|
36
|
+
|
|
37
|
+
```python
|
|
38
|
+
from soothe_sdk.plugin import plugin, subagent, tool
|
|
39
|
+
|
|
40
|
+
@plugin(
|
|
41
|
+
name="your_plugin",
|
|
42
|
+
version="1.0.0",
|
|
43
|
+
description="Brief description of your plugin",
|
|
44
|
+
dependencies=[
|
|
45
|
+
"required-package>=1.0.0",
|
|
46
|
+
],
|
|
47
|
+
trust_level="standard", # or "trusted" for privileged plugins
|
|
48
|
+
)
|
|
49
|
+
class YourPlugin:
|
|
50
|
+
"""Your plugin implementation."""
|
|
51
|
+
|
|
52
|
+
async def on_load(self, context):
|
|
53
|
+
"""Called when plugin is loaded.
|
|
54
|
+
|
|
55
|
+
Args:
|
|
56
|
+
context: Plugin context with config, logger, and utilities.
|
|
57
|
+
"""
|
|
58
|
+
# Validate dependencies
|
|
59
|
+
# Initialize resources
|
|
60
|
+
context.logger.info("Your plugin loaded")
|
|
61
|
+
|
|
62
|
+
@subagent(
|
|
63
|
+
name="your_agent",
|
|
64
|
+
description="What your agent does",
|
|
65
|
+
model="openai:gpt-4o-mini",
|
|
66
|
+
)
|
|
67
|
+
async def create_subagent(self, model, config, context, **kwargs):
|
|
68
|
+
"""Create your subagent.
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Subagent dict with name, description, and runnable.
|
|
72
|
+
"""
|
|
73
|
+
from .implementation import create_your_subagent
|
|
74
|
+
|
|
75
|
+
return create_your_subagent(config=config, **kwargs)
|
|
76
|
+
|
|
77
|
+
@tool(
|
|
78
|
+
name="your_tool",
|
|
79
|
+
description="What your tool does",
|
|
80
|
+
)
|
|
81
|
+
def your_tool(self, arg: str) -> str:
|
|
82
|
+
"""Your tool implementation."""
|
|
83
|
+
return f"Result: {arg}"
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### 3. Register Plugin
|
|
87
|
+
|
|
88
|
+
Add entry point to `pyproject.toml`:
|
|
89
|
+
|
|
90
|
+
```toml
|
|
91
|
+
[project.entry-points."soothe.plugins"]
|
|
92
|
+
your_plugin = "soothe_plugins.your_plugin:YourPlugin"
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### 4. Add Dependencies
|
|
96
|
+
|
|
97
|
+
Add required packages to `dependencies` in `pyproject.toml`:
|
|
98
|
+
|
|
99
|
+
```toml
|
|
100
|
+
dependencies = [
|
|
101
|
+
# ... existing dependencies ...
|
|
102
|
+
"your-required-package>=1.0.0",
|
|
103
|
+
]
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
### 5. Create Tests
|
|
107
|
+
|
|
108
|
+
Create test suite in `tests/test_your_plugin/`:
|
|
109
|
+
|
|
110
|
+
```
|
|
111
|
+
tests/
|
|
112
|
+
├── conftest.py
|
|
113
|
+
├── test_paperscout/
|
|
114
|
+
│ └── ...
|
|
115
|
+
└── test_your_plugin/
|
|
116
|
+
├── conftest.py # Plugin-specific fixtures
|
|
117
|
+
├── test_events.py # Event tests
|
|
118
|
+
├── test_models.py # Model tests
|
|
119
|
+
├── test_plugin.py # Plugin lifecycle tests
|
|
120
|
+
└── test_implementation.py # Core logic tests
|
|
121
|
+
```
|
|
122
|
+
|
|
123
|
+
## Plugin Structure
|
|
124
|
+
|
|
125
|
+
### Subagent Plugins
|
|
126
|
+
|
|
127
|
+
For agent-based plugins:
|
|
128
|
+
|
|
129
|
+
```python
|
|
130
|
+
from langgraph.graph import StateGraph
|
|
131
|
+
from deepagents import CompiledSubAgent
|
|
132
|
+
|
|
133
|
+
def create_your_subagent(config, **kwargs) -> dict:
|
|
134
|
+
"""Create and return a compiled subagent.
|
|
135
|
+
|
|
136
|
+
Returns:
|
|
137
|
+
Dict with 'name', 'description', and 'runnable' (CompiledSubAgent).
|
|
138
|
+
"""
|
|
139
|
+
# Define state
|
|
140
|
+
# Create graph
|
|
141
|
+
# Add nodes and edges
|
|
142
|
+
# Compile subagent
|
|
143
|
+
return {
|
|
144
|
+
"name": "your_agent",
|
|
145
|
+
"description": "What it does",
|
|
146
|
+
"runnable": compiled_graph,
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### Tool Plugins
|
|
151
|
+
|
|
152
|
+
For simple tool-based plugins:
|
|
153
|
+
|
|
154
|
+
```python
|
|
155
|
+
from langchain_core.tools import tool
|
|
156
|
+
|
|
157
|
+
@tool
|
|
158
|
+
def your_tool(arg: str) -> str:
|
|
159
|
+
"""Tool description.
|
|
160
|
+
|
|
161
|
+
Args:
|
|
162
|
+
arg: Argument description.
|
|
163
|
+
|
|
164
|
+
Returns:
|
|
165
|
+
Result description.
|
|
166
|
+
"""
|
|
167
|
+
# Tool implementation
|
|
168
|
+
return result
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## Development Workflow
|
|
172
|
+
|
|
173
|
+
### 1. Setup Development Environment
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
# Clone repository
|
|
177
|
+
git clone <soothe-plugins-repo>
|
|
178
|
+
cd soothe-plugins
|
|
179
|
+
|
|
180
|
+
# Create virtual environment
|
|
181
|
+
python -m venv .venv
|
|
182
|
+
source .venv/bin/activate # or `source .venv/bin/activate.fish`
|
|
183
|
+
|
|
184
|
+
# Install in development mode
|
|
185
|
+
pip install -e ".[dev]"
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### 2. Develop Your Plugin
|
|
189
|
+
|
|
190
|
+
```bash
|
|
191
|
+
# Create plugin package
|
|
192
|
+
mkdir -p src/soothe_plugins/your_plugin
|
|
193
|
+
|
|
194
|
+
# Implement plugin
|
|
195
|
+
# Add tests
|
|
196
|
+
|
|
197
|
+
# Run tests
|
|
198
|
+
pytest tests/test_your_plugin/
|
|
199
|
+
|
|
200
|
+
# Format code
|
|
201
|
+
ruff format src/soothe_plugins/your_plugin/
|
|
202
|
+
|
|
203
|
+
# Lint code
|
|
204
|
+
ruff check --fix src/soothe_plugins/your_plugin/
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### 3. Test Integration
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
# Test with Soothe
|
|
211
|
+
pip install -e /path/to/soothe
|
|
212
|
+
soothe checkhealth
|
|
213
|
+
|
|
214
|
+
# Run your plugin
|
|
215
|
+
soothe "test query" --subagent your_agent
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Testing Guidelines
|
|
219
|
+
|
|
220
|
+
### Test Structure
|
|
221
|
+
|
|
222
|
+
```python
|
|
223
|
+
# tests/test_your_plugin/test_plugin.py
|
|
224
|
+
|
|
225
|
+
import pytest
|
|
226
|
+
from soothe_plugins.your_plugin import YourPlugin
|
|
227
|
+
|
|
228
|
+
@pytest.fixture
|
|
229
|
+
def plugin():
|
|
230
|
+
"""Create plugin instance."""
|
|
231
|
+
return YourPlugin()
|
|
232
|
+
|
|
233
|
+
@pytest.mark.asyncio
|
|
234
|
+
async def test_plugin_load(plugin, mock_soothe_config):
|
|
235
|
+
"""Test plugin can load."""
|
|
236
|
+
context = MagicMock()
|
|
237
|
+
context.logger = MagicMock()
|
|
238
|
+
|
|
239
|
+
await plugin.on_load(context)
|
|
240
|
+
|
|
241
|
+
# Verify initialization
|
|
242
|
+
|
|
243
|
+
def test_plugin_metadata(plugin):
|
|
244
|
+
"""Test plugin metadata."""
|
|
245
|
+
assert plugin.name == "your_plugin"
|
|
246
|
+
assert plugin.version == "1.0.0"
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Test Coverage
|
|
250
|
+
|
|
251
|
+
- **Unit tests**: Test individual functions and classes
|
|
252
|
+
- **Integration tests**: Test plugin with Soothe framework
|
|
253
|
+
- **Event tests**: Test custom event emission
|
|
254
|
+
- **Error handling**: Test error cases
|
|
255
|
+
|
|
256
|
+
## Code Standards
|
|
257
|
+
|
|
258
|
+
### Python Style
|
|
259
|
+
|
|
260
|
+
- **Python >=3.11**
|
|
261
|
+
- **Type hints** on all public functions
|
|
262
|
+
- **Google-style docstrings**
|
|
263
|
+
- **Ruff** for formatting and linting
|
|
264
|
+
- **Line length**: 120 characters
|
|
265
|
+
|
|
266
|
+
### Docstring Format
|
|
267
|
+
|
|
268
|
+
```python
|
|
269
|
+
def your_function(arg: str, optional: int = 0) -> dict:
|
|
270
|
+
"""Brief description.
|
|
271
|
+
|
|
272
|
+
Args:
|
|
273
|
+
arg: Description of arg.
|
|
274
|
+
optional: Description of optional parameter.
|
|
275
|
+
|
|
276
|
+
Returns:
|
|
277
|
+
Description of return value.
|
|
278
|
+
|
|
279
|
+
Raises:
|
|
280
|
+
ValueError: When arg is invalid.
|
|
281
|
+
"""
|
|
282
|
+
pass
|
|
283
|
+
```
|
|
284
|
+
|
|
285
|
+
### Event Registration
|
|
286
|
+
|
|
287
|
+
Register custom events in `events.py`:
|
|
288
|
+
|
|
289
|
+
```python
|
|
290
|
+
from soothe.core.event_catalog import register_event
|
|
291
|
+
from soothe.core.base_events import SootheEvent
|
|
292
|
+
|
|
293
|
+
class YourCustomEvent(SootheEvent):
|
|
294
|
+
type: str = "soothe.community.your_plugin.custom"
|
|
295
|
+
data: str
|
|
296
|
+
|
|
297
|
+
# Register at module load time
|
|
298
|
+
register_event(
|
|
299
|
+
YourCustomEvent,
|
|
300
|
+
summary_template="Custom event: {data}",
|
|
301
|
+
)
|
|
302
|
+
```
|
|
303
|
+
|
|
304
|
+
## Submitting Changes
|
|
305
|
+
|
|
306
|
+
1. **Fork** the repository
|
|
307
|
+
2. **Create** a feature branch (`git checkout -b feature/your-plugin`)
|
|
308
|
+
3. **Commit** changes (`git commit -m "Add your_plugin"`)
|
|
309
|
+
4. **Push** to branch (`git push origin feature/your-plugin`)
|
|
310
|
+
5. **Open** a Pull Request
|
|
311
|
+
|
|
312
|
+
### PR Checklist
|
|
313
|
+
|
|
314
|
+
- [ ] Code follows style guidelines
|
|
315
|
+
- [ ] Tests added and passing
|
|
316
|
+
- [ ] Documentation updated
|
|
317
|
+
- [ ] Entry points registered
|
|
318
|
+
- [ ] Dependencies added to `pyproject.toml`
|
|
319
|
+
|
|
320
|
+
## Getting Help
|
|
321
|
+
|
|
322
|
+
- **Issues**: Open an issue on GitHub
|
|
323
|
+
- **Documentation**: See Soothe RFCs and implementation guides
|
|
324
|
+
- **Examples**: Check `sample_echo/` for minimal reference implementation
|
|
325
|
+
|
|
326
|
+
## License
|
|
327
|
+
|
|
328
|
+
By contributing, you agree that your contributions will be licensed under the MIT License.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
# Soothe Community Package Structure
|
|
2
|
+
|
|
3
|
+
This document describes the final polished structure of the soothe-plugins package.
|
|
4
|
+
|
|
5
|
+
## Package Layout
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
soothe-plugins-pkg/
|
|
9
|
+
├── .gitignore # Git ignore patterns
|
|
10
|
+
├── CONTRIBUTING.md # Guide for contributors
|
|
11
|
+
├── MIGRATION.md # Migration guide for standalone repo
|
|
12
|
+
├── README.md # Package overview
|
|
13
|
+
├── pyproject.toml # Package configuration
|
|
14
|
+
├── src/
|
|
15
|
+
│ └── soothe_plugins/
|
|
16
|
+
│ ├── __init__.py # Package initialization
|
|
17
|
+
│ ├── paperscout/ # PaperScout plugin
|
|
18
|
+
│ │ ├── __init__.py # Plugin class
|
|
19
|
+
│ │ ├── email.py # Email functionality
|
|
20
|
+
│ │ ├── events.py # Custom events
|
|
21
|
+
│ │ ├── gap_scanner.py # Gap scanning
|
|
22
|
+
│ │ ├── implementation.py # Subagent creation
|
|
23
|
+
│ │ ├── models.py # Data models
|
|
24
|
+
│ │ ├── nodes.py # Graph nodes
|
|
25
|
+
│ │ ├── reranker.py # Reranking logic
|
|
26
|
+
│ │ └── state.py # State definitions
|
|
27
|
+
│ ├── .plugin_template/ # Template for new plugins
|
|
28
|
+
│ │ ├── PLUGIN_TEMPLATE.md
|
|
29
|
+
│ │ ├── __init__.py.template
|
|
30
|
+
│ │ ├── events.py.template
|
|
31
|
+
│ │ ├── models.py.template
|
|
32
|
+
│ │ ├── state.py.template
|
|
33
|
+
│ │ ├── implementation.py.template
|
|
34
|
+
│ │ └── README.md.template
|
|
35
|
+
│ └── README.md # Package-level README
|
|
36
|
+
└── tests/
|
|
37
|
+
├── conftest.py # Shared test fixtures
|
|
38
|
+
└── test_paperscout/ # PaperScout tests
|
|
39
|
+
├── conftest.py
|
|
40
|
+
├── test_email.py
|
|
41
|
+
├── test_events.py
|
|
42
|
+
├── test_models.py
|
|
43
|
+
├── test_plugin.py
|
|
44
|
+
└── test_reranker.py
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Key Features
|
|
48
|
+
|
|
49
|
+
### 1. Clean Package Structure
|
|
50
|
+
- No nested directories
|
|
51
|
+
- Proper `src/` layout following Python packaging best practices
|
|
52
|
+
- Tests colocated with package
|
|
53
|
+
|
|
54
|
+
### 2. Extensibility
|
|
55
|
+
- Plugin template directory with all necessary files
|
|
56
|
+
- Clear documentation for adding new plugins
|
|
57
|
+
- CONTRIBUTING.md with detailed guidelines
|
|
58
|
+
|
|
59
|
+
### 3. Testing
|
|
60
|
+
- All tests moved from main Soothe project
|
|
61
|
+
- Shared fixtures in `tests/conftest.py`
|
|
62
|
+
- Plugin-specific fixtures in each test directory
|
|
63
|
+
|
|
64
|
+
### 4. Documentation
|
|
65
|
+
- **README.md**: Quick start and overview
|
|
66
|
+
- **CONTRIBUTING.md**: How to contribute and add plugins
|
|
67
|
+
- **MIGRATION.md**: Standalone repository migration guide
|
|
68
|
+
- **Plugin READMEs**: Each plugin has its own documentation
|
|
69
|
+
|
|
70
|
+
### 5. Build Configuration
|
|
71
|
+
- Proper `pyproject.toml` with all metadata
|
|
72
|
+
- Entry points for plugin discovery
|
|
73
|
+
- Development dependencies
|
|
74
|
+
- Ruff configuration for code quality
|
|
75
|
+
|
|
76
|
+
## Usage
|
|
77
|
+
|
|
78
|
+
### Installation
|
|
79
|
+
|
|
80
|
+
```bash
|
|
81
|
+
pip install soothe-plugins
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
### Development Installation
|
|
85
|
+
|
|
86
|
+
```bash
|
|
87
|
+
pip install -e ".[dev]"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
### Running Tests
|
|
91
|
+
|
|
92
|
+
```bash
|
|
93
|
+
pytest tests/
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Adding a New Plugin
|
|
97
|
+
|
|
98
|
+
1. Copy the template:
|
|
99
|
+
```bash
|
|
100
|
+
cp -r src/soothe_plugins/.plugin_template src/soothe_plugins/your_plugin
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
2. Rename and update template files
|
|
104
|
+
|
|
105
|
+
3. Register in `pyproject.toml`:
|
|
106
|
+
```toml
|
|
107
|
+
[project.entry-points."soothe.plugins"]
|
|
108
|
+
your_plugin = "soothe_plugins.your_plugin:YourPlugin"
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
4. Add tests in `tests/test_your_plugin/`
|
|
112
|
+
|
|
113
|
+
5. Update README with plugin documentation
|
|
114
|
+
|
|
115
|
+
## Extensibility Points
|
|
116
|
+
|
|
117
|
+
The package is designed to support:
|
|
118
|
+
|
|
119
|
+
1. **Multiple Plugins**: Add new plugins without modifying existing code
|
|
120
|
+
2. **Plugin Types**: Support subagents, tools, or hybrid plugins
|
|
121
|
+
3. **Custom Events**: Each plugin can define its own events
|
|
122
|
+
4. **Independent Testing**: Each plugin has isolated tests
|
|
123
|
+
5. **Documentation**: Each plugin has its own README
|
|
124
|
+
|
|
125
|
+
## Next Steps
|
|
126
|
+
|
|
127
|
+
This package is ready for:
|
|
128
|
+
|
|
129
|
+
1. **Testing**: Verify all tests pass
|
|
130
|
+
2. **Distribution**: Publish to PyPI
|
|
131
|
+
3. **Migration**: Move to standalone repository if desired
|
|
132
|
+
4. **Extension**: Add new community plugins
|
|
133
|
+
|
|
134
|
+
## Verification Checklist
|
|
135
|
+
|
|
136
|
+
- [x] Clean directory structure (no nested soothe-plugins-pkg/)
|
|
137
|
+
- [x] Source files in `src/soothe_plugins/`
|
|
138
|
+
- [x] Tests moved from main Soothe project
|
|
139
|
+
- [x] Plugin template created
|
|
140
|
+
- [x] CONTRIBUTING.md with detailed guidelines
|
|
141
|
+
- [x] Updated README with extensibility information
|
|
142
|
+
- [x] Proper pyproject.toml configuration
|
|
143
|
+
- [x] All template files created
|
|
144
|
+
- [ ] Tests passing (requires pytest installation)
|
|
145
|
+
- [ ] Package installable with `pip install -e .`
|
|
146
|
+
|
|
147
|
+
## Success Metrics
|
|
148
|
+
|
|
149
|
+
The package structure is complete and ready for:
|
|
150
|
+
|
|
151
|
+
1. Independent development and testing
|
|
152
|
+
2. Addition of new community plugins
|
|
153
|
+
3. Distribution as a standalone package
|
|
154
|
+
4. Migration to separate repository if desired
|