feat(project): sync engineering standards and finalize markdown-normalizer v1.2.7
- Update .github/copilot-instructions.md with latest i18n and naming standards - Add docs/development/issue-reply-guide.md for professional community engagement - Sync all documentation (MKDocs, READMEs, Docs) to v1.2.7 - Include CI/CD and Agent instruction templates for better automation
This commit is contained in:
54
.github/instructions/code-review.instructions.md
vendored
Normal file
54
.github/instructions/code-review.instructions.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: Plugin Code Review
|
||||
description: Comprehensive OpenWebUI plugin review checklist covering i18n, context helpers, antigravity safety, and streaming compatibility
|
||||
applyTo: "plugins/**/*.py"
|
||||
---
|
||||
# Code Review Instructions — OpenWebUI Plugins
|
||||
|
||||
You are an expert Senior Software Engineer reviewing OpenWebUI plugins for the `openwebui-extensions` repository.
|
||||
When reviewing plugin code, you MUST verify each point below to ensure the code meets the strict repository standards.
|
||||
|
||||
## 1. Single-file i18n Pattern (CRITICAL)
|
||||
- **One File Rule**: One `.py` file per plugin. No `_cn.py` or language-split files.
|
||||
- **Translations**: All user-visible strings (status, notification, UI text) MUST go through a `TRANSLATIONS` dictionary and a `FALLBACK_MAP`.
|
||||
- **Safety**: `format(**kwargs)` calls on translated strings MUST be wrapped in `try/except KeyError` to prevent crashes if a translation is missing a placeholder.
|
||||
|
||||
## 2. Context Helpers (CRITICAL)
|
||||
- **User Context**: MUST use `_get_user_context(__user__)` instead of direct `__user__["name"]` access. `__user__` can be a list, dict, or None.
|
||||
- **Chat Context**: MUST use `_get_chat_context(body, __metadata__)` instead of ad-hoc `body.get("chat_id")` calls.
|
||||
|
||||
## 3. Event & Logging
|
||||
- **No Print**: No bare `print()` in production code. Use `logging.getLogger(__name__)`.
|
||||
- **Emitter Safety**: Every `await emitter(...)` call MUST be guarded by `if emitter:` (or equivalent).
|
||||
- **Status Lifecycle**:
|
||||
- `_emit_status(done=False)` at task start.
|
||||
- `_emit_status(done=True)` on completion.
|
||||
- `_emit_notification("error")` on failure.
|
||||
|
||||
## 4. Antigravity Safety (CRITICAL)
|
||||
- **Timeout Guards**: All `__event_call__` JS executions MUST be wrapped with `asyncio.wait_for(..., timeout=2.0)`. Failure to do this can hang the entire backend.
|
||||
- **JS Fallbacks**: JS code executed via `__event_call__` MUST have an internal `try { ... } catch (e) { return fallback; }` block.
|
||||
- **Path Sandboxing**: File path operations MUST be validated against the workspace root (no directory traversal vulnerabilities).
|
||||
- **Upload Fallbacks**: Upload paths MUST have a dual-channel fallback (API → local/DB).
|
||||
|
||||
## 5. Filter Singleton Safety
|
||||
- **No Mutable State**: Filter plugins are singletons. There MUST be NO request-scoped mutable state stored on `self` (e.g., `self.current_user = ...`).
|
||||
- **Statelessness**: Per-request values MUST be computed from `body` and context helpers on each call.
|
||||
|
||||
## 6. Copilot SDK Tools
|
||||
- **Pydantic Models**: Tool parameters MUST be defined as a `pydantic.BaseModel` subclass.
|
||||
- **Explicit Params**: `define_tool(...)` MUST include `params_type=MyParams`.
|
||||
- **Naming**: Tool names MUST match `^[a-zA-Z0-9_-]+$` (ASCII only).
|
||||
|
||||
## 7. Streaming Compatibility (OpenWebUI 0.8.x)
|
||||
- **Thinking Tags**: The `</think>` tag MUST be closed before any normal content or tool cards are emitted.
|
||||
- **Attribute Escaping**: Tool card `arguments` and `result` attributes MUST escape `"` as `"`.
|
||||
- **Newline Requirement**: The `<details type="tool_calls" ...>` block MUST be followed by a newline immediately after `>`.
|
||||
|
||||
## 8. Performance & Memory
|
||||
- **Streaming**: Large files or responses MUST be streamed, not loaded entirely into memory.
|
||||
- **Database Connections**: Plugins MUST reuse the OpenWebUI internal database connection (`owui_engine`, `owui_Session`) rather than creating new ones.
|
||||
|
||||
## 9. HTML Injection (Action Plugins)
|
||||
- **Wrapper Template**: HTML output MUST use the standard `<!-- OPENWEBUI_PLUGIN_OUTPUT -->` wrapper.
|
||||
- **Idempotency**: The plugin MUST implement `_remove_existing_html` to ensure multiple runs do not duplicate the HTML output.
|
||||
90
.github/instructions/commit-message.instructions.md
vendored
Normal file
90
.github/instructions/commit-message.instructions.md
vendored
Normal file
@@ -0,0 +1,90 @@
|
||||
---
|
||||
name: Commit Message
|
||||
description: Comprehensive Conventional Commits guidelines for openwebui-extensions
|
||||
---
|
||||
# Commit Message Instructions
|
||||
|
||||
You are an expert developer generating commit messages for the `openwebui-extensions` repository.
|
||||
Always adhere to the following strict guidelines based on the Conventional Commits specification.
|
||||
|
||||
## 1. General Rules
|
||||
- **Language**: **English ONLY**. Never use Chinese or other languages in the commit title or body.
|
||||
- **Structure**:
|
||||
```text
|
||||
<type>(<scope>): <subject>
|
||||
<BLANK LINE>
|
||||
<body>
|
||||
<BLANK LINE>
|
||||
<footer>
|
||||
```
|
||||
|
||||
## 2. Type (`<type>`)
|
||||
Must be one of the following:
|
||||
- `feat`: A new feature or a new plugin.
|
||||
- `fix`: A bug fix.
|
||||
- `docs`: Documentation only changes (e.g., README, MkDocs).
|
||||
- `refactor`: A code change that neither fixes a bug nor adds a feature.
|
||||
- `perf`: A code change that improves performance.
|
||||
- `test`: Adding missing tests or correcting existing tests.
|
||||
- `chore`: Changes to the build process, CI/CD, or auxiliary tools/scripts.
|
||||
- `style`: Changes that do not affect the meaning of the code (white-space, formatting, etc.).
|
||||
|
||||
## 3. Scope (`<scope>`)
|
||||
The scope should indicate the affected component or plugin.
|
||||
- **For Plugins**: Use the plugin's folder name or category (e.g., `actions`, `filters`, `pipes`, `export-to-docx`, `github-copilot-sdk`).
|
||||
- **For Docs**: Use `docs` or the specific doc section (e.g., `guide`, `readme`).
|
||||
- **For Infra**: Use `ci`, `scripts`, `deps`.
|
||||
- *Note*: Omit the scope if the change is global or spans too many components.
|
||||
|
||||
## 4. Subject Line (`<subject>`)
|
||||
- **Length**: Keep it under 50-72 characters.
|
||||
- **Mood**: Use the imperative, present tense: "change" not "changed" nor "changes" (e.g., "add feature" instead of "added feature").
|
||||
- **Formatting**: Do not capitalize the first letter. Do not place a period `.` at the end.
|
||||
- **Clarity**: State exactly *what* changed. Avoid vague terms like "update code" or "fix bug".
|
||||
|
||||
## 5. Body (`<body>`)
|
||||
- **When to use**: Highly recommended for `feat`, `fix`, and `refactor`.
|
||||
- **Content**: Explain *what* and *why* (motivation), not just *how* (the code diff shows the how).
|
||||
- **Format**: Use a bulleted list (1-3 points) for readability.
|
||||
- **Repo Specifics**: If the commit involves a plugin version bump, explicitly mention that the READMEs and docs were synced.
|
||||
|
||||
## 6. Footer / Breaking Changes (`<footer>`)
|
||||
- If the commit introduces a breaking change (e.g., changing a Valve configuration key, altering a plugin's output format), append `!` after the scope/type: `feat(pipes)!: ...`
|
||||
- Add a `BREAKING CHANGE:` block in the footer explaining the migration path.
|
||||
|
||||
## 7. Examples
|
||||
|
||||
**Example 1: Feature with Body**
|
||||
```text
|
||||
feat(github-copilot-sdk): add antigravity timeout guards
|
||||
|
||||
- Wrap all __event_call__ JS executions with asyncio.wait_for(timeout=2.0)
|
||||
- Add dual-channel upload fallback (API → local/DB)
|
||||
- Emit staged status events for tasks > 3 seconds
|
||||
```
|
||||
|
||||
**Example 2: Bug Fix**
|
||||
```text
|
||||
fix(export-to-docx): resolve missing title fallback
|
||||
|
||||
- Fallback to user_name + date when chat_title is empty
|
||||
- Prevent crash when metadata variables are missing
|
||||
```
|
||||
|
||||
**Example 3: Documentation Sync**
|
||||
```text
|
||||
docs(plugins): sync bilingual READMEs for v1.2.0 release
|
||||
|
||||
- Update What's New section for folder-memory plugin
|
||||
- Sync docs/plugins/filters/folder-memory.md
|
||||
```
|
||||
|
||||
**Example 4: Breaking Change**
|
||||
```text
|
||||
refactor(core)!: rename global configuration valves
|
||||
|
||||
- Standardize all valve keys to UPPER_SNAKE_CASE
|
||||
- Remove deprecated legacy_api_key field
|
||||
|
||||
BREAKING CHANGE: Users must reconfigure their API keys in the UI as the old `api_key` field is no longer read.
|
||||
```
|
||||
54
.github/instructions/test-generation.instructions.md
vendored
Normal file
54
.github/instructions/test-generation.instructions.md
vendored
Normal file
@@ -0,0 +1,54 @@
|
||||
---
|
||||
name: Test Generation
|
||||
description: Comprehensive Pytest conventions, mocking strategies, and model usage rules for OpenWebUI plugins
|
||||
applyTo: "plugins/debug/**,tests/**"
|
||||
---
|
||||
# Test Generation Instructions
|
||||
|
||||
You are an expert SDET (Software Development Engineer in Test) writing tests for the `openwebui-extensions` repository.
|
||||
Follow these comprehensive guidelines to ensure robust, reliable, and cost-effective testing.
|
||||
|
||||
## 1. Test Structure & Placement
|
||||
- **Unit Tests**: Place in the `tests/` directory at the root of the repository. Name files `test_<module>.py`.
|
||||
- **Integration/Debug Scripts**: Place in `plugins/debug/<plugin_name>/`. Name files `debug_<feature>.py` or `inspect_<feature>.py`.
|
||||
- **Fixtures**: Use `conftest.py` for shared fixtures (e.g., mock users, mock emitters, mock database sessions).
|
||||
|
||||
## 2. Model Usage & Cost Control (CRITICAL)
|
||||
When writing tests or debug scripts that actually invoke an LLM:
|
||||
- **Allowed Models**: You MUST use low-cost models: `gpt-5-mini` (Preferred) or `gpt-4.1`.
|
||||
- **Forbidden**: NEVER use expensive models (like `gpt-4-turbo`, `claude-3-opus`) in automated tests unless explicitly requested by the user.
|
||||
- **API Keys**: Never hardcode API keys. Always read from environment variables (`os.getenv("OPENAI_API_KEY")`) or a `.env` file.
|
||||
|
||||
## 3. Mocking OpenWebUI Internals
|
||||
OpenWebUI plugins rely heavily on injected runtime variables. Your tests must mock these accurately:
|
||||
- **`__user__`**: Mock as a dictionary. Always test both with a full user object and an empty/None object to ensure fallback logic works.
|
||||
```python
|
||||
mock_user_en = {"id": "u1", "name": "Alice", "language": "en-US"}
|
||||
mock_user_zh = {"id": "u2", "name": "Bob", "language": "zh-CN"}
|
||||
mock_user_none = None
|
||||
```
|
||||
- **`__event_emitter__`**: Mock as an async callable that records emitted events for assertion.
|
||||
```python
|
||||
async def mock_emitter(event: dict):
|
||||
emitted_events.append(event)
|
||||
```
|
||||
- **`__event_call__`**: Mock as an async callable. To test Antigravity timeout guards, you must occasionally mock this to sleep longer than the timeout (e.g., `await asyncio.sleep(3.0)`) to ensure `asyncio.wait_for` catches it.
|
||||
|
||||
## 4. Testing Async Code
|
||||
- All OpenWebUI plugin entry points (`action`, `inlet`, `outlet`) are asynchronous.
|
||||
- Use `@pytest.mark.asyncio` for all test functions.
|
||||
- Ensure you `await` all plugin method calls.
|
||||
|
||||
## 5. i18n (Internationalization) Testing
|
||||
Since all plugins must be single-file i18n:
|
||||
- **Mandatory**: Write parameterized tests to verify output in both English (`en-US`) and Chinese (`zh-CN`).
|
||||
- Verify that if an unsupported language is passed (e.g., `fr-FR`), the system correctly falls back to the default (usually `en-US`).
|
||||
|
||||
## 6. Antigravity & Safety Testing
|
||||
- **Timeout Guards**: Explicitly test that frontend JS executions (`__event_call__`) do not hang the backend. Assert that a `TimeoutError` is caught and handled gracefully.
|
||||
- **State Leakage**: For `Filter` plugins (which are singletons), write tests that simulate concurrent requests from different users to ensure no state leaks across `self`.
|
||||
|
||||
## 7. Assertions & Best Practices
|
||||
- Assert on **behavior and output**, not internal implementation details.
|
||||
- For HTML/Markdown generation plugins, use Regex or BeautifulSoup to assert the presence of required tags (e.g., `<!-- OPENWEBUI_PLUGIN_OUTPUT -->`) rather than exact string matching.
|
||||
- Keep tests isolated. Do not rely on the execution order of tests.
|
||||
Reference in New Issue
Block a user