Compare commits

..

534 Commits

Author SHA1 Message Date
fujie
f5a983fb4a feat(github-copilot-sdk): release v0.10.0 with native prompt restoration and live todo widget
- Restore native Copilot CLI prompts for authentic Plan Mode behavior
- Add SQLite-backed session management for state persistence via system prompt
- Implement Adaptive Autonomy (Agent chooses planning vs direct execution)
- Fix OpenWebUI custom tool context injection for v0.8.x compatibility
- Add compact Live TODO widget synchronized with session.db
- Upgrade SDK to github-copilot-sdk==0.1.30
- Remove legacy mode switch RPC calls (moved to prompt-driven orchestration)
- Fix intent status localization and widget whitespace optimization
- Sync bilingual READMEs and all documentation mirrors to v0.10.0
2026-03-07 04:30:15 +08:00
github-actions[bot]
35dec491de chore: update community stats - new plugin added (26 -> 27) 2026-03-06 20:12:54 +00:00
fujie
67de7f1cfc refactor(github-copilot-sdk): expand _get_chat_context to handle session_id and message_id 2026-03-05 18:44:34 +08:00
fujie
b954fbca1d refactor(github-copilot-sdk): synchronize tool extra_params with OpenWebUI 0.8.x standards 2026-03-05 18:44:34 +08:00
fujie
c1411e731d fix(github-copilot-sdk): inject __messages__, __metadata__ and __event_emitter__ into tools 2026-03-05 18:44:34 +08:00
github-actions[bot]
df78f0454b chore: update community stats - new plugin added (25 -> 26) 2026-03-04 17:19:26 +00:00
fujie
d5931fbc5e docs(smart-mind-map-tool): restore fancy note format in READMEs 2026-03-04 23:53:48 +08:00
fujie
af59959ade docs(smart-mind-map-tool): clean up README note format for community posting 2026-03-04 23:42:36 +08:00
fujie
56a6ddd422 feat(smart-mind-map-tool): initial release v1.0.0 with adaptive Rich UI 2026-03-04 23:18:21 +08:00
fujie
eda495e55f refactor(feature-request): simplify template and add plugin dropdown
- Convert Plugin Name from text input to dropdown with all plugins
- Add Tool type option to match bug report template
- Merge Alternatives Considered into Additional Information section
- Combine Motivation fields into single Motivation & Use Case field
- Reduce from 7 to 5 key fields for better UX
- Keep all critical information for feature evaluation
- Consistent structure with bug report template
2026-03-04 05:03:54 +08:00
fujie
3642058292 refactor(bug-report): simplify template for better UX
- Reduce from 17 to 9 key fields
- Merge Expected/Actual Behavior into single Description field
- Combine environment and browser into Operating System & Container field
- Move screenshots to Additional Information section
- Keep core fields essential for bug reproduction (plugin, version, OS, steps)
- Add collapsible debug information guide with frontend/server log instructions
- Improve user experience by reducing form fatigue
- Maintain all critical debugging information
2026-03-04 05:02:04 +08:00
fujie
5b0464dcdd feat(bug-report): add plugin dropdown selector
- Convert Plugin Name from text input to dropdown menu
- Include all current plugins (Actions, Filters, Pipelines, Pipes, Tools)
- Add 'Other / Not Listed' option with fallback text field
- Reduces typos and improves issue categorization accuracy
- Easier plugin-specific issue tracking and statistics
2026-03-04 04:58:12 +08:00
fujie
2aff7f1bf4 fix(bug-report): correct plugin types and environment info
- Change 'Tool (Copilot SDK)' to 'Tool' (Copilot SDK is a Pipe plugin)
- Rename Environment Details field
- Include OS and container/deployment info (Docker, Docker Compose, native, etc)
- Update checklist to reflect container/deployment requirements
- Keep OpenWebUI version as required field
- Ensures proper environment context for issue reproduction
2026-03-04 04:57:24 +08:00
fujie
ba0d63930e refactor(bug-report): simplify to OS info only
- Change Environment Information to Operating System field
- Keep only OS details (Windows/macOS/Linux versions)
- Simplify checklist requirement from full environment to OS info
- Maintains essential debugging information without overhead
2026-03-04 04:55:18 +08:00
fujie
a1568de67b enhance(bug-report): improve issue template with tool type and better logging guidance
- Add Tool (Copilot SDK) as plugin type option
- Add Environment Information field (OS, hardware, deployment)
  - Platform, device type, GPU/hardware, Python version, Docker, deployment method
- Add detailed Debug Logs & Troubleshooting guide with:
  - Frontend console logs (with steps to enable Plugin Debug Output)
  - Server-side logs (docker logs or local terminal)
- Separate Frontend Console Logs field with debug output instructions
- Add Server-Side Logs field for backend error tracking
- Add Screenshots field with guidance on what to capture
- Enhanced Checklist with environment and logs requirements
- Improves issue triage and faster bug resolution
2026-03-04 04:54:53 +08:00
fujie
f4a38a7906 feat: add issue templates for bug reports and feature requests
- Add bug_report.yml template with plugin-specific fields
- Add feature_request.yml template for enhancement suggestions
- Add config.yml to customize issue creation experience
- Templates help standardize issue reporting and improve triage
2026-03-04 04:51:40 +08:00
fujie
2e6c61737f fix(workflow): only trigger release on actual version changes
- Remove doc-only change trigger to prevent unnecessary releases
- Release should only be created when plugin versions actually change
- Keeps manual workflow_dispatch and tag-based releases intact
2026-03-04 04:45:32 +08:00
fujie
c1e9aca5dc feat(pipes/github-copilot-sdk): add strict file link validation rules
- Add Strict Link Validity Rule (CRITICAL) forbidding fabricated URLs
- Implement Failure Handling for non-successful publish operations
- Establish Allowed Link Formats (Whitelist) with exact patterns
- Define Invalid Link Examples (Forbidden) including /c/... and relative paths
- Add Auto-Correction Rule requiring discard of non-whitelisted links
- Enhance URL Format guidance to emphasize verbatim copying without modification
- Add Workspace Visibility Hint (#10) for workspace file inspection context
2026-03-04 04:14:48 +08:00
Fu-Jie
6f700fe610 Fix capitalization in README description
Corrected capitalization of 'OpenWebUI' to 'open-webui'.
2026-03-04 04:11:16 +08:00
fujie
3927e384cc docs(skill): add open-terminal project to source-code-analyzer 2026-03-04 02:20:24 +08:00
fujie
e1dac2219e fix(stats): stabilize Top6 version badges and fix Excel version display [skip release]
- replace rank-based p{idx}_version usage with per-post static version badge generation

- set Export to Excel version badge to v0.3.7 in home README and README_CN
2026-03-04 01:59:31 +08:00
fujie
9436364b9a docs(readme): restore version badge for Copilot SDK; ci: add skip-release support and README link injection [skip release]
- add static v0.9.1 badge to Copilot SDK Star Features heading

- inject plugin README link before each embedded v*.md in release body

- skip release workflow when commit message contains [skip release]
2026-03-04 01:34:24 +08:00
fujie
e7b1ff4c54 docs(readme): clean up Star Features badges and fix Copilot SDK stats badge keys
- remove all Market badges from Star Features headings

- replace invalid p0_dl/p0_vw placeholders with correct per-post MD5-keyed Gist badges

- remove GitHub Copilot SDK row from Top 6 table (not in ranked stats yet)
2026-03-04 01:20:35 +08:00
fujie
c4ff4fea7e ci(release): reorder release body and improve commits format
- move v*.md release notes to top of release body

- commits now show subject (bold) + body lines per Conventional Commits best practice
2026-03-04 01:19:34 +08:00
fujie
32afc3286e ci(release): fix release notes format
- remove file path header (### plugins/...) from embedded release note content

- exclude _CN.md files to avoid Chinese/English mixed output

- remove Documentation Changes file list and Additional Documentation Files section
2026-03-04 01:06:54 +08:00
fujie
3e8b15af46 ci(release): include documentation content in release body
- embed changed v*.md release note content into generated GitHub release notes

- keep additional doc changes visible as file list in release output

- refine v0.9.1 EN/CN release notes to include only actual updated/fixed items
2026-03-04 00:57:18 +08:00
fujie
658f37baa6 ci(release): optimize plugin release workflow
- detect both version changes and plugin/docs release-note updates

- broaden push path filters and include documentation change summary in release notes

- harden worktree temp handling, remove duplicate extraction, and skip tag creation on tag-triggered runs
2026-03-04 00:52:07 +08:00
fujie
c65ba57553 chore(release): finalize github-copilot-sdk v0.9.1 prep
- sync bilingual plugin READMEs, docs mirrors, and root highlight sections for v0.9.1

- add comprehensive EN/CN release notes covering features, fixes, docs, and i18n updates

- enforce full-coverage release-note rule in release-prep skill for future releases
2026-03-04 00:47:48 +08:00
fujie
7c17dbbe23 style(pipes): unify entity name to 'Agent' across all languages
- Replaced 'Assistant' and its translations with 'Agent' in all translation dictionaries (EN, ZH, JA, KO, FR, DE, IT, ES, RU, VI, ID)
- Consistent with the previous change in Chinese locales.
2026-03-04 00:17:19 +08:00
fujie
c6279240b9 fix(pipes): fix mcp tool filtering and force-enable autonomous web search
- Fix issue where mcp tool filtering logic (function_name_filter_list) in admin backend caused all tools to be hidden due to ID prefix mismatch
- Force enable web_search tool for Copilot Agent regardless of UI toggles, providing full autonomy for search-related intents
- Updated README and version to v0.9.1
2026-03-04 00:11:28 +08:00
fujie
a8a324500a Refactor code structure for improved readability and maintainability 2026-03-03 19:36:53 +08:00
fujie
369e8c900c fix(stats): restore dynamic badges and update community statistics
- Recover dynamic Shields.io badges in README by restoring missing Gist ID 'db3d95687075a880af6f1fba76d679c6'.
- Add 'tool' to DOWNLOADABLE_TYPES and implement TYPE_ALIASES for normalization (mapping 'tools' to 'tool').
- Update community statistics and Ranking list (Top 6) based on latest marketplace data.
- Refactor openwebui_stats.py with 100% English comments and enhanced user ID auto-resolution.
- Verify Smart Mind Map (#1) and other top plugins maintain correct sorting.
2026-03-03 19:29:34 +08:00
fujie
83e317a335 docs(skills): align doc-mirror-sync docs-only guidance
- Add docs-only sync mode rules (no version bump, no release actions).

- Add EN-only and EN+ZH sync command examples.

- Keep .github and .gemini skill instructions in sync.
2026-02-28 23:24:26 +08:00
fujie
c28c3c837b docs(openwebui-skills-manager): prioritize official marketplace install
- Update bilingual plugin README to use official marketplace as default install path.

- Keep manual paste installation as fallback and sync docs mirrors.

- Keep version unchanged at 0.2.1.
2026-02-28 23:20:30 +08:00
fujie
701ea0b18f fix(openwebui-skills-manager): replace broken install example URLs
- Replace non-existent anthropics skills paths with valid xlsx/docx examples.

- Keep English and Chinese README examples synchronized.
2026-02-28 23:13:16 +08:00
fujie
eb79bc9633 fix(tools): release openwebui-skills-manager v0.2.1
- Add GitHub skills-directory auto-discovery for install_skill batch install from tree root URLs.

- Harden language detection with frontend-first fallback (__event_call__ + timeout), then headers/profile.

- Bump plugin/docs versions to 0.2.1 and sync bilingual README/docs/index entries.
2026-02-28 23:06:08 +08:00
fujie
0c7d427b93 chore: cleanup debug files and update plugin configuration 2026-02-28 16:39:41 +08:00
fujie
07bc5f027e feat(skills-manager): add openwebui_id and fix tool type sync bug 2026-02-28 16:14:38 +08:00
fujie
701fc3e906 docs(skills-manager): add skill installation examples for single and batch URLs 2026-02-28 15:53:04 +08:00
fujie
d392af66c9 chore: rename update_pipe.py to deploy_pipe.py to reflect its creation capabilities and update skills reference 2026-02-28 15:29:46 +08:00
fujie
67cf86fb26 fix(pipes): yield artifacts string directly to stream flow avoiding emitter replacement 2026-02-28 15:21:28 +08:00
fujie
fe98b0e007 fix(pipes): fallback artifacts mode to using direct view_url iframe to bypass openwebui srcdoc sandbox cdn crash 2026-02-28 14:58:56 +08:00
fujie
3236d19e28 fix(pipes): restore corrupted isinstance check + add frontend console debug tracing 2026-02-28 14:35:53 +08:00
fujie
354c1eee6b chore(pipes): add debug tracing for pending_embeds lifecycle 2026-02-28 14:30:38 +08:00
fujie
6b3eb8064b fix(pipes): align artifacts internal array type tracking with stream loops 2026-02-28 14:17:05 +08:00
fujie
f32e90e182 feat(pipes): automate artifacts html generation via emitter message append 2026-02-28 13:48:53 +08:00
fujie
8001ab18ee feat(pipes): update richui mode to send raw HTML content instead of an iframe tag 2026-02-28 13:11:03 +08:00
fujie
dcfde9c0dc fix(pipes): revert artifacts iframe to barebone structure to avoid OpenWebUI markdown parsing issues 2026-02-28 13:06:10 +08:00
fujie
dbcf7421ea feat(pipes): simplify richui iframe tag to give full styling control to openwebui emitter 2026-02-28 13:04:10 +08:00
fujie
1705baf976 feat(pipes): unrestrict richui iframe height and apply generous sandbox policies 2026-02-28 13:01:38 +08:00
fujie
8e8d478ece fix(pipes): inject explicit sandbox policies to artifacts iframe to mitigate client-side block 2026-02-28 12:57:22 +08:00
fujie
acc9cd7ff2 fix(pipes): clarify ANTI-INLINE rule to allow iframe output and hardcode iframe shadow 2026-02-28 12:37:49 +08:00
fujie
e4582c3197 feat(pipes): optimize richui vs artifacts selection and enforce fullscreen button 2026-02-28 12:23:10 +08:00
fujie
d0eb72467d feat(pipes): enforce ANTI-INLINE HTML generation rule 2026-02-28 12:16:19 +08:00
fujie
6b6e62398a docs: add skill demo GIF asset 2026-02-28 06:12:13 +08:00
fujie
fd22ed8fa0 docs: use .gif instead of .mov for Skill demo in README 2026-02-28 05:51:02 +08:00
fujie
4fccd1893e docs: use absolute raw GitHub URL for video embedding 2026-02-28 05:44:21 +08:00
fujie
a74e03fff8 docs: use HTML video tag for README video embedding compatibility 2026-02-28 05:41:38 +08:00
fujie
850838226d docs: add skill visual agent demo video to home README 2026-02-28 05:37:04 +08:00
fujie
a52ac34d59 refactor(pipes): add video (MOV/MP4) embedding support to instructions 2026-02-28 05:12:50 +08:00
fujie
3263ab9db6 docs: enhance GitHub Copilot SDK Pipe description in home READMEs
- highlight autonomous agent capabilities
- add v0.9.0 key leaps: Skills Revolution, Secure Isolation, Interactive Delivery
2026-02-28 05:10:39 +08:00
fujie
7c7daef30b refactor(pipes): optimize gif embedding and detection
- update BASE_GUIDELINES to explicitly allow direct GIF embedding
- update publish_file_from_workspace to support common image formats
2026-02-28 04:56:28 +08:00
fujie
64754ba26b refactor(pipes): optimize artifacts prompt for HTML embeds
- Explicitly instruct AI to wrap iframe in html code blocks in artifacts mode
- Clarify guidelines to distinguish between artifacts and richui delivery
2026-02-28 04:16:55 +08:00
github-actions[bot]
4188410d61 chore: update community stats - new plugin added (24 -> 25) 2026-02-27 20:12:34 +00:00
Fu-Jie
0c7201902c feat(github-copilot-sdk): add workspace skills support (v0.9.0) (#51)
* feat(github-copilot-sdk): add workspace skills support

- Introduce ENABLE_WORKSPACE_SKILLS valve to enable/disable workspace custom tools discovery
- Modify _build_session_config() to auto-load tools from .copilot-skills/ directory
- Add workspace_skills_example.py template with 3 working example tools
- Update README.md and README_CN.md with Workspace Skills guide and usage examples
- Create v0.9.0.md and v0.9.0_CN.md release notes
- Sync version to all docs files (index.md, index.zh.md, and main docs)
- Bump version from 0.8.0 to 0.9.0 across all 7+ locations

* docs: establish temp files handling policy (project-based, not /tmp)

- Add TEMP_FILES_POLICY.md guideline for all skills and workflows
- Update pr-submitter skill to use .temp/ directory instead of /tmp
- Update release-prep skill documentation with temp file convention
- Add .temp/ and .build/ entries to .gitignore
- Create internal policy memo in /memories/repo/

This policy ensures:
- All temporary files stay within project workspace (not system /tmp)
- Alignment with OpenWebUI workspace isolation principles
- Multi-user safety and cleanup traceability
- Consistent handling across all skills and development workflows

* fix(terminology): rename 'workspace skills' to 'workspace custom tools' for accuracy

The term 'Skills' in Anthropic context refers to instruction-based frameworks
(SKILL.md files with YAML frontmatter + markdown), not custom tool functions.

Our implementation uses @define_tool decorator to define custom tools that the
SDK auto-discovers from .copilot-skills/ directory. These are Tools, not Skills.

Changes:
- Rename ENABLE_WORKSPACE_SKILLS valve -> ENABLE_WORKSPACE_TOOLS
- Update all documentation (README, README_CN, docs, release notes)
- Fix section headings and descriptions throughout
- Ensure consistent terminology across all files

This is a terminology-only change; functionality remains identical.

* feat(pipes): release v0.9.0 of GitHub Copilot SDK Pipe

- Integrated OpenWebUI Skills Bridge and manage_skills tool
- Reinforced status bar stability with session_finalized logic
- Added persistent SDK config directory support

* docs(pipes): add comprehensive guides and v0.9.0 notes for Copilot SDK

- Added skill manager and best practices guides
- Added publishing tool documentation
- Included v0.9.0 release notes and deployment script
- Updated usage guides
2026-02-28 03:50:56 +08:00
Fu-Jie
f47c3f6354 Fix formatting for Open WebUI Prompt Plus entry
Updated README.md to improve formatting of the Open WebUI Prompt Plus section.
2026-02-26 13:15:49 +08:00
Copilot
272245d911 docs: add OOpenWebUI official newsletter featured recognition to Smart Mind Map, Markdown Normalizer, and Prompt Plus (#52)
* Initial plan

* docs: add OpenWebUI official newsletter featured recognition

- Add newsletter featured callout to Smart Mind Map README.md, README_CN.md, and docs
- Add newsletter featured callout to Markdown Normalizer README.md, README_CN.md, and docs
- Add newsletter featured badge to Prompt Plus in root README.md and README_CN.md
- Reference both newsletters: Jan 28, 2026 and Feb 3, 2026

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>

* docs: fix newsletter links to match actual featured issue per plugin

- Smart Mind Map: link only to Feb 3, 2026 (second newsletter)
- Markdown Normalizer: link only to Jan 28, 2026 (first newsletter)
- Prompt Plus (root READMEs): already correct, no change needed

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-26 13:12:13 +08:00
fujie
ce93464f47 chore(skills): sync all github copilot skills to gemini 2026-02-26 01:42:13 +08:00
fujie
c658e379c0 docs(skills): clarify community-publisher is for new posts only 2026-02-26 01:41:25 +08:00
fujie
ab28465dd5 feat(skills): add openwebui-community-publisher skill 2026-02-26 01:33:49 +08:00
github-actions[bot]
d22ba88f33 chore: update community stats - new plugin added (23 -> 24) 2026-02-25 17:28:32 +00:00
Fu-Jie
db33f44cbc feat(plugins): release Copilot SDK Pipe v0.8.0 and Files Filter v0.1.3 (#50)
* feat(plugins): release copilot sdk pipe v0.8.0 and files filter v0.1.3

- Add P1~P4 conditional tool filtering and admin/server gating behavior

- Fix artifact publishing reliability, strict /api file URLs, and HTML preview/download delivery

- Update bilingual README/docs, release notes, and filter matching/debug improvements

* fix(docs): remove duplicate code block in tool-filtering zh doc

- Remove incorrectly placed duplicate 'if not is_enabled: continue' block
  outside code fence on line 161-163 of copilot-sdk-tool-filtering.zh.md
- Addresses review comment from gemini-code-assist (#50)
2026-02-26 01:05:31 +08:00
fujie
5b6dddd517 docs(agent): sync source-code-analyzer skill to .github/skills 2026-02-24 23:08:18 +08:00
fujie
c8ba7c99af feat(agent): inject source-code-analyzer skill and update repo rules
- Add source-code-analyzer skill with global/plugin-specific paths\n- Update GEMINI.md with External Auth and Source Sensing rules\n- Explicitly authorize Antigravity to read core component source code
2026-02-24 23:07:44 +08:00
fujie
81279845e2 chore(skills): sync .gemini and .github skills and fix i18n validator 2026-02-24 22:19:48 +08:00
fujie
6b39531fbc feat(skills): add 6 generalized AI-driven development skills
- version-bumper: automated multi-file version synchronization
- plugin-scaffolder: standardized 12-language i18n template generation
- doc-mirror-sync: automated README to docs mirroring
- i18n-validator: dictionary key alignment analysis via AST
- gh-issue-replier: professional English reply with star-check logic
- gh-issue-scheduler: unanswered issue audit and action planning
2026-02-24 16:02:01 +08:00
fujie
377534e6c9 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
2026-02-24 15:13:52 +08:00
fujie
2da934dd92 feat(filters): upgrade markdown-normalizer to v1.2.7
- Fix Issue #49: resolve greedy regex matching in consecutive emphasis
- Add LaTeX formula protection to prevent corruption of \times, \nu, etc.
- Expand i18n support to 12 languages with strict alignment
- Fix NameError in Request import during testing
2026-02-24 15:05:25 +08:00
fujie
18ada2a177 docs: fix table header alignment and column count in READMEs 2026-02-23 14:43:28 +08:00
fujie
a5fbc8bed9 docs: add Actively Developed Projects section with GitHub Copilot SDK Pipe 2026-02-23 14:42:14 +08:00
github-actions[bot]
904eeb0ad0 chore: update community stats - new plugin added (22 -> 23) 2026-02-22 19:12:33 +00:00
fujie
9c70110e1d docs: refine wording in English v0.7.0.md (use UI instead of interface) 2026-02-23 02:42:58 +08:00
fujie
9af6a8c9bd docs: refine wording in v0.7.0_CN.md (UI instead of interface) 2026-02-23 02:42:10 +08:00
fujie
ac948023e3 docs: add Chinese version of v0.7.0 post 2026-02-23 02:41:19 +08:00
fujie
512b606827 docs: add emoji and subtitle to v0.7.0.md 2026-02-23 02:40:24 +08:00
fujie
fc9f1ccb43 feat(pipes): v0.7.0 final release with native tool UI and CLI integration
- Core: Adapt to OpenWebUI native tool call UI and thinking process visualization
- Infra: Bundle Copilot CLI via pip package (no more background curl installation)
- Fix: Resolve "Error getting file content" on OpenWebUI v0.8.0+ via absolute paths
- i18n: Add native localization for status messages in 11 languages
- UX: Optimize reasoning status display logic and cleanup legacy code
2026-02-23 02:33:59 +08:00
fujie
272b959a44 fix(actions): fix white background bleed in dark mode when viewport is narrow 2026-02-22 00:24:37 +08:00
fujie
0bde066088 fix: correct Top 6 plugin name-data mapping to match Gist badge order 2026-02-22 00:10:04 +08:00
fujie
6334660e8d docs: add root README update date sync rule to consistency maintenance 2026-02-22 00:06:43 +08:00
fujie
c29d84f97a docs: update Smart Mind Map release date in root readmes to 2026-02-22 2026-02-22 00:02:51 +08:00
fujie
aac2e89022 chore: update smart mind map plugin image. 2026-02-22 00:00:19 +08:00
fujie
fea812d4f4 ci: remove redundant release title from github release body 2026-02-21 23:49:36 +08:00
fujie
b570cbfcde docs(filters): fix broken link to workflow guide in mkdocs strict build 2026-02-21 23:47:48 +08:00
fujie
adc5e0a1f4 feat(filters): release v1.3.0 for async context compression
- Add native i18n support across 9 languages
- Implement non-blocking frontend log emission for zero TTFB delay
- Add token_usage_status_threshold to intelligently control status notifications
- Automatically detect and skip compression for copilot_sdk models
- Set debug_mode default to false for a quieter production environment
- Update documentation and remove legacy bilingual code
2026-02-21 23:44:12 +08:00
fujie
04b8108890 chore: ignore and stop tracking .git-worktrees 2026-02-21 21:50:35 +08:00
fujie
f1ba03e3bd Merge remote-tracking branch 'origin/main' into copilot/sub-pr-42
# Conflicts:
#	plugins/actions/smart-mind-map/README.md
#	plugins/actions/smart-mind-map/README_CN.md
#	plugins/actions/smart-mind-map/smart_mind_map.py
#	plugins/actions/smart-mind-map/smart_mind_map_cn.py
2026-02-21 18:04:48 +08:00
fujie
cdd9950973 docs: update pr submission guidelines to require gh tool 2026-02-21 17:54:09 +08:00
fujie
473012fa6f feat(actions): release Smart Mind Map v1.0.0 - a milestone with Native i18n & Direct Embed 2026-02-21 17:50:44 +08:00
fujie
1bbddb2222 feat(pipe): show Copilot CLI install progress during first run 2026-02-15 00:18:27 +08:00
copilot-swe-agent[bot]
dc66610cb2 docs: Align with copilot-instructions.md standards and update all repo references
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-13 03:36:30 +00:00
copilot-swe-agent[bot]
655b5311cf chore: Update repository references from awesome-openwebui to openwebui-extensions
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-13 03:31:06 +00:00
copilot-swe-agent[bot]
4390ee2085 Initial plan 2026-02-13 03:29:45 +00:00
fujie
6bf3656d30 docs: rename Awesome OpenWebUI and OpenWebUI Extras to OpenWebUI Extensions 2026-02-13 11:10:48 +08:00
google-labs-jules[bot]
bfb2039095 feat: Add full i18n support, security fixes, and zh-TW to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (including explicit zh-TW support).
- Implemented robust language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added base language fallback (e.g., fr-BE -> fr-FR) and variant mapping.
- Fixed critical security vulnerabilities:
    - Prevented JS injection by safely escaping IDs with `json.dumps`.
    - Prevented XSS by sanitizing user input and language codes.
    - Prevented DoS crashes from curly braces in LLM output by replacing `.format()` with safe string replacement.
- Fixed regex regression by using standard strings with escaped backslashes.
- Restored clickable "Markmap" link in the footer.
- Verified all changes with comprehensive unit and security tests.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 21:05:45 +00:00
google-labs-jules[bot]
86091f77cf feat: Security and i18n improvements for Smart Mind Map plugin
- Fixed high-severity XSS and JS injection vulnerabilities by safely escaping IDs and user input using `json.dumps` and HTML entity encoding.
- Prevented potential DoS crashes caused by curly braces in LLM output by replacing `.format()` with safe string replacement.
- Refactored language resolution into a `_resolve_language` helper method, implementing base language fallback (e.g., `fr-BE` -> `fr-FR`).
- Refactored date formatting to use a cleaner, dictionary-based approach.
- Consolidated i18n logic into a single file with robust fallback handling.
- Verified all changes with comprehensive unit and security tests.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:41:52 +00:00
google-labs-jules[bot]
eb223e3e75 feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings by properly escaping backslashes in standard strings.
- Implemented robust UI translation loading to prevent crashes on missing keys.
- Verified frontend rendering with Playwright and backend logic with unit tests.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:15:50 +00:00
google-labs-jules[bot]
d1bbbd9071 feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN, zh-TW).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added explicit support for zh-TW (Traditional Chinese) with correct translations.
- Updated HTML/JS templates to use injected translations.
- Restored clickable "Markmap" link in the footer for all languages.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 17:06:28 +00:00
google-labs-jules[bot]
840c77ea2f feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 18 languages (including explicit zh-TW support).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added fallback mapping for regional variants (e.g., es-AR -> es-ES).
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright and backend logic with unit tests.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:54:48 +00:00
google-labs-jules[bot]
91ba7df086 feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Added fallback mapping for regional variants (e.g. zh-TW -> zh-HK, es-AR -> es-ES).
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:46:27 +00:00
google-labs-jules[bot]
fa636c7bc5 feat: Add full i18n support to Smart Mind Map plugin
- Consolidated smart_mind_map.py and smart_mind_map_cn.py into a single file.
- Added TRANSLATIONS dictionary supporting 17 languages (en-US, ko-KR, fr-FR, es-AR, en-CA, fr-CA, ja-JP, de-DE, zh-HK, it-IT, zh-CN, en-GB, es-MX, id-ID, es-ES, de-AT, en-AU, vi-VN).
- Implemented automatic language detection with fallback to browser/local storage.
- Added localized date formatting for various locales.
- Updated HTML/JS templates to use injected translations.
- Fixed SyntaxWarning in regex strings.
- Verified frontend rendering with Playwright.

Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-02-12 16:33:04 +00:00
fujie
a5ad295d38 ci: clean up unused variables in stats workflow 2026-02-11 14:19:28 +08:00
fujie
e1f70d52a5 ci: remove push trigger for merged feature branch 2026-02-11 14:15:58 +08:00
fujie
015c22063a ci: remove fetch-depth 0, history data already persisted in Gist 2026-02-11 14:14:55 +08:00
fujie
0ea95ceefa feat: 自动化统计系统重构 - 动态徽章 + Gist SVG 图表 + 历史数据恢复 2026-02-11 14:11:26 +08:00
fujie
1192c71453 fix: merge Gist+local history and rebuild from community-stats.json 2026-02-11 14:04:03 +08:00
fujie
0b5663636f chore: hydrate stats history with recovered data (38 days record) 2026-02-11 14:00:17 +08:00
fujie
1736a1bfbf feat: auto-rebuild stats history from git logs if local/gist data is missing 2026-02-11 13:53:55 +08:00
fujie
d7c25aa973 fix: relax history requirements for chart generation 2026-02-11 13:50:42 +08:00
fujie
d71b4a7351 chore: add logging to upload_chart_svg to debug silent failure 2026-02-11 13:49:08 +08:00
fujie
a05697df70 fix: correct vl_spec syntax and use POST for Kroki 2026-02-11 13:47:23 +08:00
fujie
b355c3f0c1 feat: implement SVG generation and Gist upload logic in stats script 2026-02-11 13:42:27 +08:00
fujie
30f2aed68a feat: switch to static Gist SVG for activity chart (no more daily README commits) 2026-02-11 13:41:41 +08:00
fujie
50c549b260 chore: apply dynamic version badges to README 2026-02-11 13:36:28 +08:00
fujie
2a75580831 style: apply colored badges to post type statistics in docs 2026-02-11 13:36:05 +08:00
fujie
4032746243 style: enhance stats docs with colored badges for post types 2026-02-11 13:34:14 +08:00
fujie
871e76b1df chore: manual stats update (latest history & chart) 2026-02-11 13:32:27 +08:00
fujie
954ebad8b2 feat: sync docs chart with README chart (Vega-Lite) 2026-02-11 13:31:14 +08:00
fujie
fa5d962152 feat: use dynamic badges for plugin versions, remove version changes as commit trigger 2026-02-11 13:28:19 +08:00
fujie
2ac8d4b14f ci: remove points and followers as commit triggers since they are now dynamic badges 2026-02-11 13:26:00 +08:00
fujie
c86b27a0c1 ci: add dedicated daily workflow for chart updates at 01:10 Beijing time 2026-02-11 13:24:17 +08:00
fujie
2381c5080e fix: revert chart to embedded data - Kroki server-side rendering cannot fetch external URLs 2026-02-11 13:23:05 +08:00
fujie
0394be7d16 chore: update READMEs and docs with stable Gist-based chart URL 2026-02-11 13:18:51 +08:00
fujie
7c9bf4082a feat: sync activity chart in docs with README configuration 2026-02-11 13:16:02 +08:00
fujie
8621d178ae feat: restore external Gist data source for stable chart URL 2026-02-11 13:11:54 +08:00
fujie
20a7d57b5b fix: revert to embedded activity chart data to resolve loading failures 2026-02-11 13:09:23 +08:00
fujie
8f72e25671 perf: use external Gist data source for trend chart to keep URL static 2026-02-11 13:04:36 +08:00
fujie
b7e62e63e0 docs: restore missing language switcher in README 2026-02-11 12:59:08 +08:00
fujie
bbccffa95b style: move activity chart to end of stats section and add updated badge to top6 table 2026-02-11 12:56:30 +08:00
fujie
b9104702ac fix: use dynamic badges for auto-updated timestamp to ensure real-time accuracy 2026-02-11 12:54:45 +08:00
fujie
015b0d98ec style: embed full-history activity chart into stats section and refine top 6 table 2026-02-11 12:52:14 +08:00
fujie
fc56ea7faa style: move activity chart to bottom and use vega-lite for better visuals 2026-02-11 12:46:24 +08:00
fujie
e1c2261537 fix: implement safe badge keys and add dynamic upvote/save badges 2026-02-11 12:41:16 +08:00
fujie
93e8e3bee2 fix: remove duplicate saves entry and restore comments entry formatting 2026-02-11 12:37:51 +08:00
fujie
1fb2cccd58 fix: resolve type error in gist sync and implement full English localization for charts 2026-02-11 12:35:45 +08:00
fujie
b34ce0b075 docs: finalize Zero-Commit dynamic reports with Kroki charts and dynamic badges 2026-02-11 12:29:39 +08:00
fujie
49efcb7e4d feat: implement Zero-Commit dynamic Mermaid charts via Kroki server-side rendering 2026-02-11 12:26:09 +08:00
fujie
8d334a48b9 feat: transition stats hosting to Gist-first model to minimize repository commits 2026-02-11 12:23:10 +08:00
fujie
16882bf9e5 data: finalize community stats with full historical data and dynamic badges 2026-02-11 12:21:56 +08:00
fujie
dc0366aab2 feat: enable live stats for community reports via Gist dynamic badges 2026-02-11 12:19:16 +08:00
fujie
6d080d3a28 data: reconstruct full stats history from git logs and update reports 2026-02-11 12:15:22 +08:00
fujie
e50a55ee11 feat: enhance Mermaid visualizations with multi-series trends, distribution pie, and impact analysis 2026-02-11 12:13:29 +08:00
fujie
edbd75e5dc fix: URL encode Gist raw endpoints for reliable Shields.io badge rendering 2026-02-11 12:12:37 +08:00
fujie
387ca8788b feat: use dynamic badges for Top 6 plugin statistics in README 2026-02-11 12:10:46 +08:00
fujie
cfb15808ef docs: finalize dynamic stats badges in READMEs 2026-02-11 12:09:11 +08:00
fujie
0424521380 feat: complete no-commit update system with dynamic badges and history sync 2026-02-11 12:08:05 +08:00
fujie
c2ea3b2479 feat: migrate stats display to dynamic Shields.io badges via Gist 2026-02-11 12:05:52 +08:00
fujie
a96a588141 style: reformat README stats section for better clarity and premium look 2026-02-11 12:01:54 +08:00
fujie
f34da0b263 feat: include per-post download stats in historical snapshots 2026-02-11 11:59:56 +08:00
fujie
80dce6e1de fix: compatibility with Python < 3.12 for f-strings with backslashes 2026-02-11 11:58:44 +08:00
fujie
080534d03b feat: implement Gist-based history tracking and enhanced stats categorization 2026-02-11 11:57:07 +08:00
fujie
a63d3e89ff feat: implement stats history, growth tracking, and mermaid trend charts 2026-02-11 11:41:12 +08:00
github-actions[bot]
0b9c242c0f chore: update community stats - points increased (270 -> 271) 2026-02-11 03:11:02 +00:00
github-actions[bot]
6f7ae4a304 chore: update community stats - points increased (269 -> 270) 2026-02-10 23:19:32 +00:00
github-actions[bot]
571adf33c5 chore: update community stats - points increased (268 -> 269), followers increased (219 -> 220) 2026-02-10 21:20:45 +00:00
github-actions[bot]
813e2b8320 chore: update community stats - followers increased (218 -> 219) 2026-02-10 20:19:43 +00:00
github-actions[bot]
21ec586c68 chore: update community stats - points increased (266 -> 268), followers increased (217 -> 218) 2026-02-10 15:32:07 +00:00
fujie
e95a786420 docs: add core practical examples (Star Prediction & Video Processing) to README 2026-02-10 23:07:44 +08:00
github-actions[bot]
7773723b18 chore: update community stats - new plugin added (21 -> 22), plugin version updated, points increased (262 -> 266) 2026-02-10 14:35:09 +00:00
fujie
c547c1cee5 docs: fix broken relative links in example cases to resolve mkdocs build warnings 2026-02-10 21:41:15 +08:00
fujie
b04112a261 docs: add GitHub Copilot SDK pipe masterclass cases and documentation updates 2026-02-10 21:38:54 +08:00
github-actions[bot]
df977a7ccc chore: update community stats - followers increased (216 -> 217) 2026-02-10 10:26:05 +00:00
fujie
3986eb854f docs: modernize file delivery protocol and update tutorials 2026-02-10 17:01:18 +08:00
fujie
fe170bedb9 chore: remove sample_sales_data.csv (accidentally committed) 2026-02-10 16:23:20 +08:00
fujie
3504313f15 docs(workflow): optimize release format to English-only changelog 2026-02-10 16:20:47 +08:00
github-actions[bot]
e5e0f4cbcc chore: update community stats - plugin version updated 2026-02-10 07:30:30 +00:00
fujie
a7b244602f feat(pipe): release v0.6.2 - full-lifecycle file agent support 2026-02-10 14:55:16 +08:00
github-actions[bot]
3343e73848 chore: update community stats - followers increased (215 -> 216) 2026-02-10 04:51:12 +00:00
github-actions[bot]
7ab3e51d6f chore: update community stats - followers increased (214 -> 215) 2026-02-10 03:11:20 +00:00
github-actions[bot]
303d21c73d chore: update community stats - followers increased (213 -> 214) 2026-02-09 21:18:32 +00:00
github-actions[bot]
054af87e6e chore: update community stats - points increased (261 -> 262), followers increased (212 -> 213) 2026-02-09 19:34:12 +00:00
github-actions[bot]
991570d025 chore: update community stats - plugin version updated 2026-02-09 17:24:09 +00:00
fujie
5a5261d184 chore(release): bump github-copilot-sdk to 0.6.1 and update READMEs/CHANGELOG 2026-02-10 01:04:13 +08:00
fujie
8cdc7723d2 docs(pipes): update github-copilot-sdk README version to 0.6.1 2026-02-10 01:04:02 +08:00
github-actions[bot]
a167f51026 chore: update community stats - followers increased (211 -> 212) 2026-02-09 15:25:46 +00:00
fujie
03ff69f9e0 docs: synchronize README_CN.md with the latest premium layout and market links 2026-02-09 22:12:21 +08:00
fujie
62c69a9a41 fix: restore <b> tags in summary for proper rendering on GitHub 2026-02-09 22:09:14 +08:00
fujie
9bf2a5d2a2 docs: link Star Features titles to OpenWebUI Community market 2026-02-09 22:07:56 +08:00
fujie
13aed46c05 docs: shorten community market badges to Get-Market for better visual balance 2026-02-09 22:06:37 +08:00
fujie
02a1668979 docs: add direct Community Market download badges to Star Features 2026-02-09 22:04:46 +08:00
fujie
9760ccb243 style: silence MD033 lint errors by wrapping with markdownlint-disable comments 2026-02-09 22:00:45 +08:00
fujie
e2c705fe15 style: reduce HTML elements in README.md collapsible sections and fix summary bold 2026-02-09 21:59:43 +08:00
fujie
37c7bf73c0 style: fix table formatting lint errors in README.md 2026-02-09 21:58:55 +08:00
fujie
447e791ab6 style: fix lint global errors and synchronize stats generator 2026-02-09 21:58:27 +08:00
fujie
cde685a364 docs: synchronize project contents with disk and add missing filters 2026-02-09 21:55:54 +08:00
fujie
b00206b063 docs: implement collapsible project content layout in home README 2026-02-09 21:53:47 +08:00
fujie
e0a838e512 docs: finalize home README with 5 star features and BYOK highlight (pure English) 2026-02-09 21:51:36 +08:00
fujie
b9f4f5f1d6 chore: update project README with star feature highlight (English only) 2026-02-09 21:47:54 +08:00
github-actions[bot]
c1afd1fa23 chore: update community stats - points increased (259 -> 261), followers increased (210 -> 211) 2026-02-09 13:37:24 +00:00
Jeff
eaeaadaf12 Merge pull request #39 from Fu-Jie/add-abaroni-contributor
chore: add @abaroni as contributor
2026-02-09 20:27:07 +08:00
fujie
ee70c6629e chore: add @abaroni as contributor (ideas) 2026-02-09 20:26:27 +08:00
github-actions[bot]
692971c93c chore: update community stats - new plugin added (20 -> 21), plugin version updated 2026-02-09 12:25:10 +00:00
fujie
e17818bf6c chore: re-trigger release for v0.6.0 2026-02-09 19:54:49 +08:00
fujie
c5c9fd9d57 fix(ci): fix shell script error when commit messages contain backticks 2026-02-09 19:53:23 +08:00
fujie
5c9875d390 feat: add openwebui_id to the GitHub Copilot SDK files filter plugin metadata. 2026-02-09 19:48:41 +08:00
fujie
9185f88d40 feat: release github-copilot-sdk v0.6.0 and files-filter v0.1.2 2026-02-09 19:45:23 +08:00
github-actions[bot]
1fcad993ea chore: update community stats - followers increased (208 -> 210) 2026-02-09 03:10:29 +00:00
github-actions[bot]
1594ea3a20 chore: update community stats - followers increased (207 -> 208) 2026-02-09 00:44:14 +00:00
github-actions[bot]
ee681ddad9 chore: update community stats - followers increased (206 -> 207) 2026-02-08 21:11:27 +00:00
github-actions[bot]
881597fd51 chore: update community stats - followers increased (205 -> 206) 2026-02-08 07:21:06 +00:00
github-actions[bot]
5772b1c65f chore: update community stats - plugin version updated, points increased (258 -> 259) 2026-02-08 00:53:22 +00:00
fujie
3d4b4b96e8 fix(docs): Repair broken valves table in README 2026-02-08 08:33:02 +08:00
fujie
409d2f663f feat(copilot): Release v0.5.1 - Smarter BYOK, Tool Caching & Refined Docs 2026-02-08 08:21:32 +08:00
github-actions[bot]
de9948a5b0 chore: update community stats - followers increased (204 -> 205) 2026-02-07 23:12:20 +00:00
github-actions[bot]
0a51b4cfca chore: update community stats - points increased (257 -> 258) 2026-02-07 18:13:00 +00:00
github-actions[bot]
f8eb096300 chore: update community stats - plugin version updated 2026-02-07 11:08:46 +00:00
fujie
f6369a1591 feat: release export-to-docx v0.4.4 w/ formatting & font fixes 2026-02-07 18:14:11 +08:00
github-actions[bot]
81634f57fa chore: update community stats - points increased (254 -> 257) 2026-02-07 09:12:46 +00:00
github-actions[bot]
70dc62aaab chore: update community stats - points increased (246 -> 254), followers increased (203 -> 204) 2026-02-07 06:19:35 +00:00
fujie
8762c05e04 docs: add explicit Copilot subscription requirement to README 2026-02-07 13:41:23 +08:00
github-actions[bot]
db52ac1041 chore: update community stats - plugin version updated 2026-02-07 05:23:23 +00:00
fujie
795ac34cd9 chore: archive development research artifacts and debug scripts 2026-02-07 12:49:42 +08:00
fujie
89a12a4fe8 docs: enforce English-only for commit messages and release notes 2026-02-07 12:38:46 +08:00
fujie
f882997337 feat(github-copilot-sdk): v0.3.0 - unified tool bridge & dynamic MCP discovery
Major enhancements:
- Zero-config OpenWebUI Tool Bridge: automatically converts WebUI Functions to Copilot-compatible tools
- Dynamic MCP Discovery: seamlessly reads MCP servers from Admin Settings -> Connections
- High-performance async engine with optimized event-driven streaming
- Robust interoperability via dynamic Pydantic model generation
- Simplified token acquisition (web-based PAT only, removed CLI method)
- Updated configuration valves (renamed, removed legacy parameters)
- Comprehensive bilingual documentation sync
2026-02-07 12:36:46 +08:00
github-actions[bot]
8e2c1b467e chore: update community stats - followers increased (202 -> 203) 2026-02-07 01:38:50 +00:00
github-actions[bot]
db2433afa1 chore: update community stats - points increased (245 -> 246) 2026-02-06 21:12:47 +00:00
github-actions[bot]
fd125c9dea chore: update community stats - followers increased (201 -> 202) 2026-02-06 17:20:41 +00:00
github-actions[bot]
0a726aacb6 chore: update community stats - followers increased (200 -> 201) 2026-02-06 14:21:48 +00:00
github-actions[bot]
bf82e093d4 chore: update community stats - points increased (244 -> 245), followers increased (199 -> 200) 2026-02-06 10:19:17 +00:00
github-actions[bot]
53ae7ef003 chore: update community stats - followers increased (197 -> 199) 2026-02-06 04:39:50 +00:00
github-actions[bot]
c2c7e3b2d3 chore: update community stats - followers increased (196 -> 197) 2026-02-06 01:39:25 +00:00
github-actions[bot]
26df5f5144 chore: update community stats - followers increased (195 -> 196) 2026-02-05 20:13:20 +00:00
github-actions[bot]
aebeb3677c chore: update community stats - followers increased (194 -> 195) 2026-02-05 17:22:50 +00:00
github-actions[bot]
076c1d62c6 chore: update community stats - points increased (243 -> 244) 2026-02-05 12:20:12 +00:00
github-actions[bot]
21cf6ecc1d chore: update community stats - followers increased (193 -> 194) 2026-02-05 11:18:53 +00:00
github-actions[bot]
e6bdab54c9 chore: update community stats - followers increased (192 -> 193) 2026-02-05 10:20:57 +00:00
github-actions[bot]
2232e5adb3 chore: update community stats - followers increased (191 -> 192) 2026-02-05 09:22:17 +00:00
github-actions[bot]
d17089972a chore: update community stats - followers increased (190 -> 191) 2026-02-05 07:27:09 +00:00
github-actions[bot]
a7991147be chore: update community stats - followers increased (189 -> 190) 2026-02-05 04:39:47 +00:00
github-actions[bot]
be6eb35567 chore: update community stats - followers increased (188 -> 189) 2026-02-05 00:43:05 +00:00
github-actions[bot]
90bc295871 chore: update community stats - followers increased (187 -> 188) 2026-02-04 18:22:31 +00:00
github-actions[bot]
310ad5d1d3 chore: update community stats - points increased (223 -> 243), followers increased (186 -> 187) 2026-02-04 07:23:53 +00:00
github-actions[bot]
00ce724430 chore: update community stats - points increased (204 -> 223), followers increased (184 -> 186) 2026-02-04 05:25:30 +00:00
github-actions[bot]
43b68b3ff0 chore: update community stats - points increased (202 -> 204), followers increased (183 -> 184) 2026-02-04 00:39:22 +00:00
github-actions[bot]
b6c1335335 chore: update community stats - points increased (200 -> 202) 2026-02-03 16:23:48 +00:00
github-actions[bot]
8b0b33015f chore: update community stats - followers increased (182 -> 183) 2026-02-03 10:19:31 +00:00
github-actions[bot]
11ee9086b2 chore: update community stats - followers increased (181 -> 182) 2026-02-03 08:17:37 +00:00
github-actions[bot]
3578ffc543 chore: update community stats - points increased (198 -> 200) 2026-02-02 23:11:34 +00:00
github-actions[bot]
b8531f1979 chore: update community stats - followers increased (180 -> 181) 2026-02-02 14:21:14 +00:00
github-actions[bot]
8607afd4c3 chore: update community stats - points increased (197 -> 198), followers increased (179 -> 180) 2026-02-02 12:19:30 +00:00
github-actions[bot]
41d9963d35 chore: update community stats - followers increased (178 -> 179) 2026-02-02 09:24:12 +00:00
github-actions[bot]
bd5f3d3f7c chore: update community stats - followers increased (177 -> 178) 2026-02-02 04:46:56 +00:00
github-actions[bot]
dda8262bc0 chore: update community stats - followers increased (176 -> 177) 2026-02-01 10:09:57 +00:00
github-actions[bot]
0271013ec2 chore: update community stats - points increased (196 -> 197) 2026-01-31 21:07:54 +00:00
github-actions[bot]
e1f210d600 chore: update community stats - followers increased (175 -> 176) 2026-01-31 10:08:48 +00:00
github-actions[bot]
eac8f6f355 chore: update community stats - points increased (195 -> 196) 2026-01-31 09:11:17 +00:00
github-actions[bot]
3998b93034 chore: update community stats - points increased (194 -> 195) 2026-01-31 04:36:15 +00:00
github-actions[bot]
ae04e95e13 chore: update community stats - points increased (193 -> 194) 2026-01-30 22:09:21 +00:00
github-actions[bot]
12d638e134 chore: update community stats - followers increased (173 -> 175) 2026-01-30 21:11:14 +00:00
github-actions[bot]
4a9eb8ed3d chore: update community stats - points increased (190 -> 193), followers increased (172 -> 173) 2026-01-30 19:16:44 +00:00
github-actions[bot]
af127bbfd5 chore: update community stats - points increased (189 -> 190) 2026-01-30 18:17:05 +00:00
github-actions[bot]
db7bb6250a chore: update community stats - points increased (188 -> 189) 2026-01-30 17:17:25 +00:00
github-actions[bot]
24b029e617 chore: update community stats - points increased (187 -> 188) 2026-01-30 15:15:33 +00:00
github-actions[bot]
ff63ab3118 chore: update community stats - points increased (186 -> 187) 2026-01-30 03:03:29 +00:00
github-actions[bot]
07e7e74fe1 chore: update community stats - followers increased (171 -> 172) 2026-01-30 00:41:11 +00:00
github-actions[bot]
55456775c1 chore: update community stats - points increased (185 -> 186), followers increased (170 -> 171) 2026-01-29 22:11:07 +00:00
github-actions[bot]
05bb2e4644 chore: update community stats - points increased (184 -> 185) 2026-01-29 21:11:30 +00:00
github-actions[bot]
83fa20ed08 chore: update community stats - points increased (183 -> 184) 2026-01-29 20:11:59 +00:00
fujie
ec69524357 feat: add Open WebUI Prompt Plus to extensions list and documentation 2026-01-30 02:16:38 +08:00
github-actions[bot]
829361da63 chore: update community stats - points increased (182 -> 183), followers increased (169 -> 170) 2026-01-29 17:17:44 +00:00
github-actions[bot]
af05ecec6a chore: update community stats - points increased (180 -> 182) 2026-01-29 16:18:22 +00:00
github-actions[bot]
1e08ae7d10 chore: update community stats - points increased (179 -> 180) 2026-01-29 14:20:30 +00:00
github-actions[bot]
b24233ee07 chore: update community stats - followers increased (168 -> 169) 2026-01-29 11:15:47 +00:00
github-actions[bot]
e5d1550986 chore: update community stats - points increased (170 -> 179), followers increased (167 -> 168) 2026-01-29 09:19:59 +00:00
fujie
7f5deb603e feat: 添加支持暂存插件源码更新的功能 2026-01-29 13:21:18 +08:00
fujie
55b2a28f79 fix: 移除标题中的图标,简化信息图插件的标题 2026-01-29 11:12:32 +08:00
fujie
db9bcb2c31 feat: 添加 README 文件同步工具到 OpenWebUI 社区 2026-01-29 10:58:40 +08:00
fujie
ad2773e8f1 Update plugin documentation for various filters and actions
- Updated README.md and README_CN.md for the infographic plugin to reflect new features and bug fixes in version 1.5.0, including context-aware generation and language synchronization.
- Revised README.md and README_CN.md for the smart mind map plugin to include support for user feedback and a changelog.
- Enhanced README.md and README_CN.md for the async context compression filter with critical fixes and improved compatibility details.
- Introduced initial release notes for the folder memory filter, detailing its core features and installation instructions.
- Updated markdown normalizer documentation to synchronize version numbers and improve clarity on configuration options.
- Revised GitHub Copilot SDK documentation to enhance installation instructions and troubleshooting sections, including a new changelog.
2026-01-29 03:22:21 +08:00
github-actions[bot]
7d4da3be8a chore: update community stats - followers increased (166 -> 167) 2026-01-28 18:14:59 +00:00
github-actions[bot]
28166728a4 chore: update community stats - points increased (169 -> 170) 2026-01-28 15:14:05 +00:00
github-actions[bot]
4dfca903c4 chore: update community stats - points increased (168 -> 169) 2026-01-28 10:11:40 +00:00
github-actions[bot]
b619d3f402 chore: update community stats - points increased (167 -> 168), followers increased (165 -> 166) 2026-01-28 06:14:04 +00:00
github-actions[bot]
1e68f985fb chore: update community stats - new plugin added (19 -> 20), plugin version updated 2026-01-28 05:13:56 +00:00
github-actions[bot]
596b571887 chore: update community stats - plugin version updated 2026-01-28 03:38:17 +00:00
fujie
c4d36c32a0 docs(pipes): fix copilot sdk tools link
Point tools usage link to GitHub source
2026-01-28 11:15:23 +08:00
fujie
6adbcd8d42 fix(scripts): resolve plugin scan NameError
Define metadata per file before use
2026-01-28 11:11:38 +08:00
fujie
89c039fe33 fix(actions): bump smart mind map to 0.9.2
Align mind map language rule with input text

Update plugin docs and README versions
2026-01-28 11:09:18 +08:00
github-actions[bot]
3a73ccfaa7 chore: update community stats - points increased (166 -> 167) 2026-01-28 01:37:45 +00:00
github-actions[bot]
7eff265e1c chore: update community stats - points increased (161 -> 166) 2026-01-27 21:07:14 +00:00
github-actions[bot]
989b45fc16 chore: update community stats - points increased (157 -> 161) 2026-01-27 20:09:28 +00:00
fujie
163d8ce8bd fix(scripts): exclude debug directory from release scanning 2026-01-28 02:30:38 +08:00
fujie
4e32e1a1da fix(scripts): normalize plugin paths in version extraction to prevent false positives in release diffs 2026-01-28 02:28:20 +08:00
github-actions[bot]
070e9f2456 chore: update community stats - plugin version updated 2026-01-27 18:15:04 +00:00
fujie
219ba83df3 feat(infographic): release v1.5.0 with smart language detection & organize debug tools 2026-01-28 02:14:30 +08:00
github-actions[bot]
e412aeb93d chore: update community stats - followers increased (164 -> 165) 2026-01-27 17:12:55 +00:00
github-actions[bot]
38102ca0c4 chore: update community stats - followers increased (163 -> 164) 2026-01-27 13:23:17 +00:00
github-actions[bot]
6ab69fba1c chore: update community stats - plugin version updated, followers increased (162 -> 163) 2026-01-26 21:09:49 +00:00
fujie
e0c0f69dc8 fix: update Git operations rules to allow direct pushes to main branch 2026-01-27 04:39:37 +08:00
fujie
7921b14dae fix: remove obsolete openwebui_id from SDK metadata 2026-01-27 04:32:22 +08:00
Jeff
30cde9e871 Merge pull request #36 from Fu-Jie/feature/copilot-sdk-fix
fix(pipes): sync copilot sdk thinking
2026-01-27 04:26:08 +08:00
fujie
ac50cd249a fix(pipes): sync copilot sdk thinking
- Fix thinking visibility by passing user overrides into streaming

- Harden UserValves handling for mapping/instance inputs

- Update bilingual README with per-user valves and troubleshooting
2026-01-27 04:22:36 +08:00
github-actions[bot]
927db6dbaa chore: update community stats - points increased (155 -> 157) 2026-01-26 18:13:33 +00:00
github-actions[bot]
376c398ac7 chore: update community stats - followers increased (161 -> 162) 2026-01-26 12:15:53 +00:00
github-actions[bot]
a167a3cf83 chore: update community stats - followers increased (160 -> 161) 2026-01-26 11:09:11 +00:00
github-actions[bot]
c51e7dfdf7 chore: update community stats - followers increased (159 -> 160) 2026-01-26 10:10:58 +00:00
github-actions[bot]
1d4d13b34b chore: update community stats - points increased (154 -> 155), followers increased (158 -> 159) 2026-01-26 09:15:49 +00:00
github-actions[bot]
18e8775f38 chore: update community stats - points increased (152 -> 154) 2026-01-26 08:12:51 +00:00
fujie
813b019653 release: GitHub Copilot SDK Pipe v0.1.1 2026-01-26 15:29:26 +08:00
github-actions[bot]
b0b1542939 chore: update community stats - new plugin added (18 -> 19), plugin version updated, points increased (148 -> 152), followers increased (157 -> 158) 2026-01-26 07:14:37 +00:00
github-actions[bot]
15f19d8b8d chore: update community stats - points increased (147 -> 148) 2026-01-26 00:38:32 +00:00
fujie
82253b114c feat(copilot-sdk): release v0.1.1 - remove db dependency, add timeout, fix streaming
- Remove database dependency for session management, use chat_id directly
- Add TIMEOUT valve (default 300s)
- Fix streaming issues by handling full message events
- Improve chat_id extraction and tool detection
- Update docs and bump version to 0.1.1
2026-01-26 07:25:01 +08:00
github-actions[bot]
e0bfbf6dd4 chore: update community stats - points increased (146 -> 147) 2026-01-25 19:07:08 +00:00
github-actions[bot]
4689e80e7a chore: update community stats - points increased (144 -> 146) 2026-01-25 11:07:02 +00:00
github-actions[bot]
556e6c1c67 chore: update community stats - new plugin added (17 -> 18), plugin version updated, points increased (143 -> 144) 2026-01-25 10:08:13 +00:00
github-actions[bot]
3ab84a526d chore: update community stats - followers increased (156 -> 157) 2026-01-25 02:55:55 +00:00
github-actions[bot]
bdce96f912 chore: update community stats - followers increased (155 -> 156) 2026-01-24 17:06:50 +00:00
github-actions[bot]
4811b99a4b chore: update community stats - followers increased (154 -> 155) 2026-01-24 05:08:58 +00:00
github-actions[bot]
fb2a64c07a chore: update community stats - followers increased (153 -> 154) 2026-01-23 20:09:48 +00:00
github-actions[bot]
e023e4f2e2 chore: update community stats - followers increased (152 -> 153) 2026-01-23 07:12:10 +00:00
github-actions[bot]
0b16b1e0f4 chore: update community stats - followers increased (151 -> 152) 2026-01-22 21:09:33 +00:00
github-actions[bot]
59073ad7ac chore: update community stats - points increased (141 -> 143) 2026-01-22 20:10:29 +00:00
github-actions[bot]
8248644c45 chore: update community stats - points increased (140 -> 141) 2026-01-22 16:13:08 +00:00
github-actions[bot]
f38e6394c9 chore: update community stats - points increased (136 -> 140) 2026-01-22 15:13:08 +00:00
github-actions[bot]
0aaa529c6b chore: update community stats - followers increased (150 -> 151) 2026-01-22 13:23:00 +00:00
github-actions[bot]
b81a6562a1 chore: update community stats - points increased (135 -> 136) 2026-01-22 11:10:17 +00:00
github-actions[bot]
c5b10db23a chore: update community stats - followers increased (149 -> 150) 2026-01-22 09:14:48 +00:00
github-actions[bot]
d16e444643 chore: update community stats - followers increased (148 -> 149) 2026-01-22 07:13:25 +00:00
github-actions[bot]
8202468099 chore: update community stats - followers increased (147 -> 148) 2026-01-22 06:13:25 +00:00
github-actions[bot]
766e8bd20f chore: update community stats - followers increased (146 -> 147) 2026-01-22 02:51:30 +00:00
github-actions[bot]
1214ab5a8c chore: update community stats - followers increased (145 -> 146) 2026-01-21 21:13:00 +00:00
github-actions[bot]
ebddbb25f8 chore: update community stats - followers increased (144 -> 145) 2026-01-21 15:13:27 +00:00
github-actions[bot]
59545e1110 chore: update community stats - plugin version updated, followers increased (143 -> 144) 2026-01-21 14:14:42 +00:00
fujie
500e090b11 fix: resolve TypeError and improve Pydantic compatibility in async-context-compression v1.2.2 2026-01-21 21:51:58 +08:00
github-actions[bot]
a75ee555fa chore: update community stats - followers increased (142 -> 143) 2026-01-21 13:22:53 +00:00
github-actions[bot]
6a8c2164cd chore: update community stats - followers increased (141 -> 142) 2026-01-21 12:15:46 +00:00
github-actions[bot]
7f7efa325a chore: update community stats - followers increased (140 -> 141) 2026-01-21 04:25:49 +00:00
github-actions[bot]
9ba6cb08fc chore: update community stats - followers increased (139 -> 140) 2026-01-20 20:27:29 +00:00
github-actions[bot]
1872271a2d chore: update community stats - new plugin added (16 -> 17), plugin version updated, points increased (134 -> 135) 2026-01-20 13:23:26 +00:00
fujie
813b50864a docs(folder-memory): add prerequisites section and enhance release workflow with README links
- Add 'Prerequisites' section to folder-memory README files clarifying that conversations must occur inside a folder
- Update docs/plugins/filters/folder-memory.md and folder-memory.zh.md with same prerequisites
- Enhance extract_plugin_versions.py to auto-generate GitHub README URLs in release notes
- Update plugin-development workflow to document README link requirements for publishing
2026-01-20 20:35:06 +08:00
github-actions[bot]
b18cefe320 chore: update community stats - followers increased (137 -> 139) 2026-01-20 12:15:40 +00:00
fujie
a54c359fcf docs(filters): remove language switchers and legacy references from folder-memory docs 2026-01-20 20:11:00 +08:00
fujie
8d83221a4a docs(filters): add author and project info to folder-memory READMEs and docs 2026-01-20 20:08:52 +08:00
fujie
1879000720 docs(filters): add 'What's New' section to folder-memory READMEs and docs
- Add prominent 'What's New' section to README.md, README_CN.md, and global docs.
- Ensure compliance with plugin development standards.
2026-01-20 20:07:46 +08:00
fujie
ba92649a98 feat(filters): refactor folder-rule-collector to folder-memory
- Rename plugin from `folder-rule-collector` to `folder-memory` for better clarity.
- Refactor code to focus on "Project Rules" collection, removing "Knowledge" collection for V1.
- Add `PRIORITY` valve (default: 20) to ensure execution after context compression.
- Update all parameter names to uppercase for consistency.
- Update documentation (README, global docs) with GitHub raw URL for demo image.
- Remove `STATUS` valve as it's redundant with OpenWebUI's built-in function toggle.
- Add `ROADMAP.md` to track future "Project Knowledge" features.
- Update `.github/copilot-instructions.md` with detailed commit message guidelines.
2026-01-20 20:02:50 +08:00
github-actions[bot]
d2276dcaae chore: update community stats - plugin version updated 2026-01-20 11:10:30 +00:00
fujie
25c9d20f3d feat(async-context-compression): release v1.2.1 with smart config & optimizations
This release introduces significant improvements to configuration flexibility, performance, and stability.

**Key Changes:**

*   **Smart Configuration:**
    *   Added `summary_model_max_context` to allow independent context limits for the summary model (e.g., using `gemini-flash` with 1M context to summarize `gpt-4` history).
    *   Implemented auto-detection of base model settings for custom models, ensuring correct threshold application.
*   **Performance & Refactoring:**
    *   Optimized `model_thresholds` parsing with caching to reduce overhead.
    *   Refactored `inlet` and `outlet` logic to remove redundant code and improve maintainability.
    *   Replaced all `print` statements with proper `logging` calls for better production monitoring.
*   **Bug Fixes & Modernization:**
    *   Fixed `datetime.utcnow()` deprecation warnings by switching to timezone-aware `datetime.now(timezone.utc)`.
    *   Corrected type annotations and improved error handling for `JSONResponse` objects from LLM backends.
    *   Removed hard truncation in summary generation to allow full context usage.

**Files Updated:**
*   Plugin source code (English & Chinese)
*   Documentation and READMEs
*   Version bumped to 1.2.1
2026-01-20 19:09:25 +08:00
github-actions[bot]
0d853577df chore: update community stats - followers increased (136 -> 137) 2026-01-20 09:15:24 +00:00
github-actions[bot]
f91f3d8692 chore: update community stats - followers increased (135 -> 136) 2026-01-20 07:14:01 +00:00
github-actions[bot]
0f7cad8dfa chore: update community stats - followers increased (134 -> 135) 2026-01-19 23:08:06 +00:00
fujie
db1a1e7ef0 fix(async-context-compression): sync CN version with EN version logic
- Add missing imports (contextlib, sessionmaker, Engine)
- Add database engine discovery functions (_discover_owui_engine, _discover_owui_schema)
- Fix ChatSummary table to support schema configuration
- Fix duplicate code in __init__ method
- Add _db_session context manager for robust session handling
- Fix inlet method signature (add __request__, __model__ parameters)
- Fix tool output trimming to check native function calling
- Add chat_id empty check in outlet method
2026-01-19 20:37:37 +08:00
github-actions[bot]
e7de80a059 chore: update community stats - plugin version updated, followers increased (133 -> 134) 2026-01-19 12:15:44 +00:00
fujie
0d8c4e048e release: async-context-compression v1.2.0 and markdown-normalizer v1.2.4 2026-01-19 20:11:55 +08:00
github-actions[bot]
014a5a9d1f chore: update community stats - followers increased (132 -> 133) 2026-01-19 10:11:26 +00:00
github-actions[bot]
a6dd970859 chore: update community stats - followers increased (131 -> 132) 2026-01-19 09:16:08 +00:00
github-actions[bot]
aac730f5b1 chore: update community stats - points increased (133 -> 134), followers increased (130 -> 131) 2026-01-19 07:15:13 +00:00
github-actions[bot]
ff95d9328e chore: update community stats - followers increased (129 -> 130) 2026-01-19 06:15:55 +00:00
github-actions[bot]
afe1d8cf52 chore: update community stats - points increased (118 -> 133) 2026-01-18 19:06:16 +00:00
github-actions[bot]
67b819f3de chore: update community stats - followers increased (128 -> 129) 2026-01-18 15:07:24 +00:00
github-actions[bot]
9b6acb6b95 chore: update community stats - points increased (117 -> 118), followers increased (127 -> 128) 2026-01-18 14:07:18 +00:00
github-actions[bot]
a9a59e1e34 chore: update community stats - followers increased (126 -> 127) 2026-01-18 13:14:54 +00:00
github-actions[bot]
5b05397356 chore: update community stats - followers increased (124 -> 126) 2026-01-18 12:13:26 +00:00
github-actions[bot]
7a7dbc0cfa chore: update community stats - points increased (116 -> 117) 2026-01-18 09:08:33 +00:00
github-actions[bot]
6ac0ba6efe chore: update community stats - followers increased (123 -> 124) 2026-01-18 08:10:15 +00:00
github-actions[bot]
d3d008efb4 chore: update community stats - followers increased (122 -> 123) 2026-01-18 07:08:42 +00:00
github-actions[bot]
4f1528128a chore: update community stats - followers increased (121 -> 122) 2026-01-18 05:10:36 +00:00
github-actions[bot]
93c4326206 chore: update community stats - followers increased (120 -> 121) 2026-01-18 01:37:36 +00:00
github-actions[bot]
0fca7fe524 chore: update community stats - points increased (113 -> 116) 2026-01-18 00:38:45 +00:00
github-actions[bot]
afdcab10c6 chore: update community stats - followers increased (119 -> 120) 2026-01-17 21:06:42 +00:00
github-actions[bot]
f8cc5eabe6 chore: update community stats - plugin version updated 2026-01-17 18:10:56 +00:00
fujie
f304eb7633 feat(markdown-normalizer): release v1.2.3 with bug fixes and test suite 2026-01-18 01:14:37 +08:00
github-actions[bot]
827204e082 chore: update community stats - points increased (108 -> 113), followers increased (118 -> 119) 2026-01-17 16:08:04 +00:00
github-actions[bot]
641d7ee8c8 chore: update community stats - plugin version updated 2026-01-17 11:06:49 +00:00
fujie
3b11537b5e docs: sync markdown_normalizer 1.2.2 2026-01-17 18:53:05 +08:00
github-actions[bot]
e51d87ae80 chore: update community stats - plugin version updated 2026-01-17 09:07:56 +00:00
Jeff
f16e7c996c Merge pull request #32 from Fu-Jie/all-contributors/add-nahoj
docs: add nahoj as a contributor for ideas
2026-01-17 16:35:15 +08:00
allcontributors[bot]
55eb295c12 docs: update .all-contributorsrc [skip ci] 2026-01-17 08:32:48 +00:00
allcontributors[bot]
4767351c5e docs: update README.md [skip ci] 2026-01-17 08:32:47 +00:00
fujie
1d2502eb3f feat(markdown_normalizer): add details tag normalization and update documentation 2026-01-17 16:30:46 +08:00
fujie
94540cc131 feat(markdown_normalizer): add details tag normalization and update documentation 2026-01-17 16:30:14 +08:00
fujie
71bef146c8 docs: standardize plugin READMEs and documentation rules 2026-01-17 16:26:43 +08:00
github-actions[bot]
87e47fd4b2 chore: update community stats - followers increased (117 -> 118) 2026-01-17 04:15:52 +00:00
github-actions[bot]
2da600838c chore: update community stats - followers increased (116 -> 117) 2026-01-17 01:36:26 +00:00
github-actions[bot]
4ee34c1dc6 chore: update community stats - followers increased (114 -> 116) 2026-01-17 00:33:42 +00:00
github-actions[bot]
9a854c33d3 chore: update community stats - followers increased (113 -> 114) 2026-01-16 22:08:08 +00:00
github-actions[bot]
ae19653a8f chore: update community stats - points increased (107 -> 108) 2026-01-16 20:09:28 +00:00
github-actions[bot]
caf0acf2e1 chore: update community stats - followers increased (112 -> 113) 2026-01-16 18:12:25 +00:00
github-actions[bot]
b503ad6fd2 chore: update community stats - points increased (106 -> 107), followers increased (111 -> 112) 2026-01-16 16:10:41 +00:00
github-actions[bot]
357e869a15 chore: update community stats - followers increased (110 -> 111) 2026-01-16 12:14:19 +00:00
github-actions[bot]
3035c79d91 chore: update community stats - followers increased (108 -> 110) 2026-01-16 00:35:50 +00:00
github-actions[bot]
a5e5e178a0 chore: update community stats - followers increased (107 -> 108) 2026-01-15 16:14:45 +00:00
github-actions[bot]
d20081d3ed chore: update community stats - followers increased (106 -> 107) 2026-01-15 13:20:39 +00:00
github-actions[bot]
e2d94ba5b5 chore: update community stats - followers increased (105 -> 106) 2026-01-15 12:14:41 +00:00
github-actions[bot]
49a19242a4 chore: update community stats - followers increased (104 -> 105) 2026-01-15 09:11:33 +00:00
github-actions[bot]
c26d3b30e5 chore: update community stats - points increased (104 -> 106) 2026-01-14 20:08:17 +00:00
fujie
60e681042d chore: smart stats update - only commit on meaningful changes 2026-01-15 00:34:45 +08:00
Jeff
842d65b887 Update README to remove Gemini filters
Removed Gemini Manifold Companion and Gemini Multimodal Filter from the README.
2026-01-15 00:33:38 +08:00
Jeff
ff5cecca1c Update README to remove deprecated filters
Removed the Multi-Model Context Merger and Gemini Manifold entries from the README.
2026-01-15 00:32:38 +08:00
Jeff
b447143a50 Delete plugins/filters/multi_model_context_merger.py 2026-01-15 00:28:14 +08:00
fujie
e4cbf231a6 Fix: Remove duplicate parameters and correct documentation 2026-01-15 00:25:23 +08:00
github-actions[bot]
8868b28a84 chore: update community stats 2026-01-14 2026-01-14 16:11:08 +00:00
fujie
c4df24d2c2 fix: correct plugin filenames in documentation 2026-01-14 23:56:53 +08:00
fujie
70a96d0754 fix: resolve mkdocs build warnings and broken links 2026-01-14 23:46:56 +08:00
fujie
ab0daba80d docs: update documentation, add new filters, remove deprecated plugins 2026-01-14 23:32:10 +08:00
github-actions[bot]
505fb6ca96 chore: update community stats 2026-01-14 2026-01-14 15:10:36 +00:00
github-actions[bot]
385ee71bc8 chore: update community stats 2026-01-14 2026-01-14 14:10:41 +00:00
github-actions[bot]
cfa28e2c9a chore: update community stats 2026-01-14 2026-01-14 13:20:49 +00:00
github-actions[bot]
d08bede60e chore: update community stats 2026-01-14 2026-01-14 12:14:38 +00:00
github-actions[bot]
b686db353c chore: update community stats 2026-01-14 2026-01-14 11:09:16 +00:00
github-actions[bot]
2b543d51ff chore: update community stats 2026-01-14 2026-01-14 10:09:53 +00:00
github-actions[bot]
e8d09d79ec chore: update community stats 2026-01-14 2026-01-14 09:12:34 +00:00
github-actions[bot]
cdb544f891 chore: update community stats 2026-01-14 2026-01-14 08:11:43 +00:00
github-actions[bot]
3eff93e8c9 chore: update community stats 2026-01-14 2026-01-14 07:12:08 +00:00
github-actions[bot]
cdb03fce90 chore: update community stats 2026-01-14 2026-01-14 06:13:29 +00:00
github-actions[bot]
c1cecf0dbb chore: update community stats 2026-01-14 2026-01-14 05:11:36 +00:00
github-actions[bot]
08ecba3ee1 chore: update community stats 2026-01-14 2026-01-14 04:27:23 +00:00
github-actions[bot]
3b82f2364e chore: update community stats 2026-01-14 2026-01-14 03:39:12 +00:00
github-actions[bot]
a7b2032b20 chore: update community stats 2026-01-14 2026-01-14 02:51:27 +00:00
github-actions[bot]
3bc683dbf5 chore: update community stats 2026-01-14 2026-01-14 01:37:52 +00:00
github-actions[bot]
2a8065e80c chore: update community stats 2026-01-14 2026-01-14 00:37:35 +00:00
github-actions[bot]
ab60641265 chore: update community stats 2026-01-13 2026-01-13 23:08:29 +00:00
github-actions[bot]
9e88decc44 chore: update community stats 2026-01-13 2026-01-13 22:08:37 +00:00
github-actions[bot]
076598ba07 chore: update community stats 2026-01-13 2026-01-13 21:08:40 +00:00
github-actions[bot]
4f0c50db0f chore: update community stats 2026-01-13 2026-01-13 20:09:28 +00:00
github-actions[bot]
499690e30f chore: update community stats 2026-01-13 2026-01-13 19:08:28 +00:00
github-actions[bot]
12a531b9ae chore: update community stats 2026-01-13 2026-01-13 18:12:46 +00:00
github-actions[bot]
3a0e2ecc6e chore: update community stats 2026-01-13 2026-01-13 17:12:03 +00:00
github-actions[bot]
14954b03bf chore: update community stats 2026-01-13 2026-01-13 16:11:50 +00:00
fujie
6f874db000 feat: implement auto-sync plugin ID on publish 2026-01-13 23:17:49 +08:00
fujie
16cc45c0d5 add openwebui_id 2026-01-13 23:16:27 +08:00
github-actions[bot]
ab96719ec4 chore: update community stats 2026-01-13 2026-01-13 15:12:09 +00:00
fujie
e2be1b25b1 feat: update markdown normalizer to v1.1.2 with comprehensive mermaid edge label protection 2026-01-13 22:45:42 +08:00
github-actions[bot]
700a7fc27a chore: update community stats 2026-01-13 2026-01-13 14:10:49 +00:00
github-actions[bot]
06cc48bab1 chore: update community stats 2026-01-13 2026-01-13 13:20:59 +00:00
github-actions[bot]
498e433ed3 chore: update community stats 2026-01-13 2026-01-13 12:15:11 +00:00
github-actions[bot]
4e915ea7a9 chore: update community stats 2026-01-13 2026-01-13 11:08:35 +00:00
github-actions[bot]
825ea07f4b chore: update community stats 2026-01-13 2026-01-13 10:09:15 +00:00
github-actions[bot]
1a731c181b chore: update community stats 2026-01-13 2026-01-13 09:12:15 +00:00
github-actions[bot]
c59ba5e501 chore: update community stats 2026-01-13 2026-01-13 08:11:54 +00:00
github-actions[bot]
e21e3e2ffa chore: update community stats 2026-01-13 2026-01-13 07:11:57 +00:00
github-actions[bot]
d2abaa138e chore: update community stats 2026-01-13 2026-01-13 06:12:48 +00:00
github-actions[bot]
3843ae5bc7 chore: update community stats 2026-01-13 2026-01-13 05:12:25 +00:00
github-actions[bot]
02c7a87c63 chore: update community stats 2026-01-13 2026-01-13 04:22:50 +00:00
github-actions[bot]
1e59025535 chore: update community stats 2026-01-13 2026-01-13 03:37:03 +00:00
github-actions[bot]
46195791b6 chore: update community stats 2026-01-13 2026-01-13 02:45:34 +00:00
github-actions[bot]
85b6bcece1 chore: update community stats 2026-01-13 2026-01-13 01:37:04 +00:00
github-actions[bot]
fece7d9898 chore: update community stats 2026-01-13 2026-01-13 00:31:14 +00:00
github-actions[bot]
d41822911c chore: update community stats 2026-01-12 2026-01-12 23:07:04 +00:00
github-actions[bot]
7b1180a1c8 chore: update community stats 2026-01-12 2026-01-12 22:08:18 +00:00
github-actions[bot]
6d5c3f1415 chore: update community stats 2026-01-12 2026-01-12 21:08:35 +00:00
github-actions[bot]
f8157f92fc chore: update community stats 2026-01-12 2026-01-12 20:09:21 +00:00
github-actions[bot]
fa2e9f5344 chore: update community stats 2026-01-12 2026-01-12 19:09:07 +00:00
github-actions[bot]
9c37955cf2 chore: update community stats 2026-01-12 2026-01-12 18:12:14 +00:00
github-actions[bot]
261f74efe8 chore: update community stats 2026-01-12 2026-01-12 17:10:57 +00:00
github-actions[bot]
83727bdab1 chore: update community stats 2026-01-12 2026-01-12 16:11:10 +00:00
github-actions[bot]
3b1a8d795f chore: update community stats 2026-01-12 2026-01-12 15:50:53 +00:00
fujie
f650c64ffe feat: update markdown-normalizer to v1.1.0 (fix mermaid syntax & html safeguard) 2026-01-12 23:44:27 +08:00
github-actions[bot]
6000c880de chore: update community stats 2026-01-12 2026-01-12 15:10:48 +00:00
github-actions[bot]
048fbb26d7 chore: update community stats 2026-01-12 2026-01-12 14:10:53 +00:00
github-actions[bot]
a88eda62cc chore: update community stats 2026-01-12 2026-01-12 13:21:31 +00:00
github-actions[bot]
957fb2dfb7 chore: update community stats 2026-01-12 2026-01-12 12:14:57 +00:00
github-actions[bot]
d2be5109ad chore: update community stats 2026-01-12 2026-01-12 11:08:33 +00:00
github-actions[bot]
80fdc52598 chore: update community stats 2026-01-12 2026-01-12 10:10:32 +00:00
github-actions[bot]
2b90ead3cf chore: update community stats 2026-01-12 2026-01-12 09:14:36 +00:00
github-actions[bot]
2aa5d77586 chore: update community stats 2026-01-12 2026-01-12 08:12:52 +00:00
github-actions[bot]
2b1b1ef939 chore: update community stats 2026-01-12 2026-01-12 07:14:15 +00:00
github-actions[bot]
4e21e06617 chore: update community stats 2026-01-12 2026-01-12 06:14:40 +00:00
github-actions[bot]
82ce1cef29 chore: update community stats 2026-01-12 2026-01-12 05:15:42 +00:00
github-actions[bot]
533eace74e chore: update community stats 2026-01-12 2026-01-12 04:28:03 +00:00
github-actions[bot]
83b3dcda65 chore: update community stats 2026-01-12 2026-01-12 03:39:51 +00:00
github-actions[bot]
e89373e0ed chore: update community stats 2026-01-12 2026-01-12 02:52:20 +00:00
github-actions[bot]
4b66a2bb1c chore: update community stats 2026-01-12 2026-01-12 01:38:07 +00:00
github-actions[bot]
59ba23da63 chore: update community stats 2026-01-12 2026-01-12 00:37:16 +00:00
github-actions[bot]
f8a89e222c chore: update community stats 2026-01-11 2026-01-11 23:07:51 +00:00
github-actions[bot]
096568f3e6 chore: update community stats 2026-01-11 2026-01-11 22:07:55 +00:00
github-actions[bot]
e10e12ebc9 chore: update community stats 2026-01-11 2026-01-11 21:07:16 +00:00
github-actions[bot]
c4df5eba47 chore: update community stats 2026-01-11 2026-01-11 20:08:19 +00:00
Jeff
0da3d3d881 Merge pull request #25 from Fu-Jie/all-contributors/add-i-iooi-i
docs: add i-iooi-i as a contributor for bug, and ideas
2026-01-12 03:59:47 +08:00
allcontributors[bot]
6f4a62d1bc docs: update .all-contributorsrc [skip ci] 2026-01-11 19:59:25 +00:00
allcontributors[bot]
5d71c2a4d3 docs: update README.md [skip ci] 2026-01-11 19:59:24 +00:00
github-actions[bot]
097707c168 chore: update community stats 2026-01-11 2026-01-11 19:06:29 +00:00
fujie
8f4cfceb50 docs: add multiple contributions handling to copilot instructions 2026-01-12 02:22:57 +08:00
Jeff
4ab5fab7d0 Update README.md 2026-01-12 02:21:19 +08:00
fujie
0e293be8bc docs: add contributor recognition standards to copilot instructions 2026-01-12 02:20:18 +08:00
Jeff
182c12f81a Merge pull request #23 from Fu-Jie/all-contributors/add-rbb-dev
docs: add rbb-dev as a contributor for ideas, and code
2026-01-12 02:16:00 +08:00
Jeff
1337a90911 Merge branch 'main' into all-contributors/add-rbb-dev 2026-01-12 02:15:51 +08:00
Jeff
2f0a347ab3 Merge pull request #24 from Fu-Jie/all-contributors/add-dhaern
docs: add dhaern as a contributor for bug, and ideas
2026-01-12 02:12:48 +08:00
allcontributors[bot]
4eda286512 docs: update .all-contributorsrc [skip ci] 2026-01-11 18:11:12 +00:00
allcontributors[bot]
0fead8158d docs: update README.md [skip ci] 2026-01-11 18:11:11 +00:00
github-actions[bot]
031bef563a chore: update community stats 2026-01-11 2026-01-11 18:10:54 +00:00
allcontributors[bot]
04c3fd2bf9 docs: update .all-contributorsrc [skip ci] 2026-01-11 18:10:12 +00:00
allcontributors[bot]
cbbf6118b5 docs: update README.md [skip ci] 2026-01-11 18:10:11 +00:00
Jeff
4c529369ce Merge pull request #22 from Fu-Jie/all-contributors/add-rbb-dev
docs: add rbb-dev as a contributor for ideas
2026-01-12 02:07:35 +08:00
allcontributors[bot]
797dea0d77 docs: create .all-contributorsrc [skip ci] 2026-01-11 18:06:46 +00:00
allcontributors[bot]
a91aee31de docs: update README.md [skip ci] 2026-01-11 18:06:45 +00:00
fujie
8511b7df80 feat: add version column to top plugins stats and optimize workflow 2026-01-12 01:57:15 +08:00
fujie
afd1e7a444 docs: update copilot instructions with filter plugin best practices 2026-01-12 01:49:46 +08:00
fujie
34b2c3d6cf fix(async-context-compression): resolve race condition, update role to assistant, bump to v1.1.3 2026-01-12 01:45:58 +08:00
github-actions[bot]
d5c099dd15 chore: update community stats 2026-01-11 2026-01-11 17:06:52 +00:00
fujie
8810223693 docs: add Multi-Model Context Merger to plugin lists in READMEs 2026-01-12 00:30:55 +08:00
fujie
84974a2fb9 docs: add Gemini Multimodal Filter to plugin lists in READMEs 2026-01-12 00:30:09 +08:00
fujie
af847293af docs: correct plugin lists in READMEs (rename Knowledge Card, remove Summary, add Deep Dive) 2026-01-12 00:28:41 +08:00
fujie
a44e80ce5b fix: resolve syntax error in community client and refine error logging 2026-01-12 00:22:22 +08:00
fujie
c2815e13e9 chore: cleanup debug logs in community client 2026-01-12 00:22:05 +08:00
fujie
56bfa3a3ef fix: provide function id in update payload to resolve 400 error 2026-01-12 00:18:58 +08:00
fujie
a13c915f27 fix: revert _find_images to _find_image to ensure API compatibility 2026-01-12 00:17:03 +08:00
fujie
fb2d35237e fix: revert to single image support as API does not support multiple images 2026-01-12 00:16:47 +08:00
fujie
3f19ecfd20 feat: support multiple images and improve error logging for plugin updates 2026-01-12 00:13:32 +08:00
fujie
2fd96f07aa fix: robust payload cleaning for plugin updates to resolve 422 error 2026-01-12 00:12:56 +08:00
fujie
a1c1ed9840 fix: resolve 422 error in plugin update by cleaning payload and fixing media format 2026-01-12 00:07:10 +08:00
fujie
c63701d05f docs: update infographic plugin documentation to v1.4.9 2026-01-12 00:01:28 +08:00
fujie
863805dc68 feat: release markdown_normalizer v1.0.1 with enhanced mermaid support and debug logging 2026-01-11 23:58:23 +08:00
github-actions[bot]
98f7dff458 chore: update community stats 2026-01-11 2026-01-11 11:06:46 +00:00
fujie
08c0dd984c docs: add 'Updated' column for each plugin in Top 6 table 2026-01-11 18:05:01 +08:00
fujie
e870ad8823 docs: add last updated time to Top 6 plugins section and update stats script 2026-01-11 17:59:08 +08:00
fujie
d687fffdb5 docs: further simplify contributing guides to focus on plugin files 2026-01-11 17:56:37 +08:00
fujie
d534d8b319 docs: split contributing guide into English and Chinese and remove docs requirement 2026-01-11 17:55:47 +08:00
fujie
d5c5158726 docs: simplify and bilingualize contributing guide 2026-01-11 17:54:49 +08:00
fujie
888026876f ci: auto-trigger plugin publishing on main branch push 2026-01-11 17:51:34 +08:00
Jeff
06e8d30900 Merge pull request #20 from Fu-Jie/copilot/fix-session-alias-errors
Harden async context compression against new DB session alias and runtime edge cases
2026-01-11 17:26:03 +08:00
fujie
cbf2ff7f93 chore: release async-context-compression v1.1.2
- Enhanced error reporting via status bar and console
- Robust model ID handling
- Open WebUI v0.7.x compatibility (dynamic DB session)
- Updated documentation and version bumps
2026-01-11 17:25:07 +08:00
copilot-swe-agent[bot]
abbe3fb248 chore: centralize chat_id extraction helper
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:36:13 +00:00
copilot-swe-agent[bot]
7e44dde979 chore: add discovery docstrings
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:31:10 +00:00
copilot-swe-agent[bot]
3649d75539 chore: add discovery debug logs
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:30:02 +00:00
copilot-swe-agent[bot]
d3b4219a9a chore: refine db session discovery messaging
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:28:52 +00:00
copilot-swe-agent[bot]
9e98d55e11 fix: make async compression db session discovery robust
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:27:36 +00:00
copilot-swe-agent[bot]
4b8515f682 fix: ensure empty summary model skips compression
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:25:33 +00:00
copilot-swe-agent[bot]
d2f35ce396 fix: harden async compression compatibility
Co-authored-by: Fu-Jie <33599649+Fu-Jie@users.noreply.github.com>
2026-01-11 08:24:56 +00:00
copilot-swe-agent[bot]
f479f23b38 Initial plan 2026-01-11 08:19:33 +00:00
github-actions[bot]
51048f9e5d chore: update community stats 2026-01-10 2026-01-10 18:11:03 +00:00
github-actions[bot]
1118ae34c4 chore: update community stats 2026-01-10 2026-01-10 14:07:43 +00:00
github-actions[bot]
7a5e1a4e12 chore: update community stats 2026-01-10 2026-01-10 12:12:24 +00:00
fujie
8e377e1794 Update Copilot instructions: Limit What's New section to latest 3 updates 2026-01-10 19:09:09 +08:00
fujie
d66360b02d Update READMEs with v1.1.1 release notes 2026-01-10 19:07:49 +08:00
fujie
1ece648006 Update Async Context Compression docs to v1.1.1 and improve plugin update logic to detect README changes 2026-01-10 19:07:49 +08:00
github-actions[bot]
a262a716a3 chore: update community stats 2026-01-10 2026-01-10 11:06:57 +00:00
364 changed files with 43743 additions and 13282 deletions

View File

@@ -0,0 +1,46 @@
# `.agent/learnings/` — Engineering Learnings & Reusable Patterns
This directory stores **hard-won engineering insights** discovered during development.
Each file is a standalone Markdown note covering a specific topic, pattern, or gotcha.
The goal is to avoid re-investigating the same issue twice.
---
## Conventions
- **File naming**: `{topic}.md`, e.g., `openwebui-tool-injection.md`
- **Scope**: One clear topic per file. Keep files focused and concise.
- **Format**: Use the template below.
---
## Template
```markdown
# [Topic Title]
> Discovered: YYYY-MM-DD
## Context
Where / when does this apply?
## Finding
What exactly did we learn?
## Solution / Pattern
The code or approach that works.
## Gotchas
Edge cases or caveats to watch out for.
```
---
## Index
| File | Topic |
|------|-------|
| [openwebui-tool-injection.md](./openwebui-tool-injection.md) | How OpenWebUI injects parameters into Tool functions, and what the Pipe must provide |
| [openwebui-mock-request.md](./openwebui-mock-request.md) | How to build a valid Mock Request for calling OpenWebUI-internal APIs from a Pipe |
| [copilot-plan-mode-prompt-parity.md](./copilot-plan-mode-prompt-parity.md) | Why Plan Mode prompt logic must be shared between fresh-session and resume-session injection |

View File

@@ -0,0 +1,40 @@
# Copilot Plan Mode Prompt Parity
> Discovered: 2026-03-06
## Context
The GitHub Copilot SDK pipe builds system prompts in two paths:
- fresh session creation via `_build_session_config(...)`
- resumed session injection via the `system_parts` rebuild branch
Plan Mode guidance was duplicated across those branches.
## Finding
If Plan Mode instructions are edited in only one branch, resumed sessions silently lose planning behavior or capability hints that fresh sessions still have.
This is especially easy to miss because both branches still work, but resumed chats receive a weaker or stale prompt.
Session mode switching alone is also not enough. Even when `session.rpc.mode.set(Mode.PLAN)` succeeds, the SDK may still skip creating the expected `plan.md` if the runtime system prompt does not explicitly include the original Plan Mode persistence contract.
## Solution / Pattern
Extract the Plan Mode prompt into one shared helper and call it from both branches:
```python
def _build_plan_mode_context(plan_path: str) -> str:
...
```
Then inject it in both places with the chat-specific `plan.md` path.
For extra safety, when the pipe later reads `session.rpc.plan.read()`, mirror the returned content into the chat-specific `COPILOTSDK_CONFIG_DIR/session-state/<chat_id>/plan.md` path. This keeps the UI-visible file in sync even if the SDK persists plan state internally but does not materialize the file where the chat integration expects it.
## Gotchas
- Keep the helper dynamic: the `plan.md` path must still be resolved per chat/session.
- Do not only update debug prompt artifacts; the effective runtime prompt lives in `plugins/pipes/github-copilot-sdk/github_copilot_sdk.py`.
- Resume-session parity matters for capability guidance just as much as for session context.
- If users report that Plan Mode is active but `plan.md` is missing, check both halves: prompt parity and the final `rpc.plan.read()` -> `plan.md` sync path.

View File

@@ -0,0 +1,131 @@
# Building a Valid Mock Request for OpenWebUI Pipes
> Discovered: 2026-03-05
## Context
OpenWebUI Pipes run as a Pipe plugin, not as a real HTTP request handler. When the Pipe
needs to call OpenWebUI-internal APIs (like `generate_chat_completion`, `get_tools`, etc.)
or load Tools that do the same, it must provide a **fake-but-complete Request object**.
## Finding
OpenWebUI's internal functions expect `request` to satisfy several contracts:
```
request.app.state.MODELS → dict { model_id: ModelModel } — MUST be populated!
request.app.state.config → config object with all env variables
request.app.state.TOOLS → dict (can start empty)
request.app.state.FUNCTIONS → dict (can start empty)
request.app.state.redis → None is fine
request.app.state.TOOL_SERVERS → [] is fine
request.app.url_path_for(name, **path_params) → str
request.headers → dict with Authorization, host, user-agent
request.state.user → user dict
request.state.token.credentials → str (the Bearer token, without "Bearer " prefix)
await request.json() → dict (the raw request body)
await request.body() → bytes (the raw request body as JSON bytes)
```
## Solution / Pattern
```python
from types import SimpleNamespace
import json as _json_mod
def _build_openwebui_request(user: dict, token: str, body: dict = None):
from open_webui.config import PERSISTENT_CONFIG_REGISTRY
from open_webui.models.models import Models as _Models
# 1. Build config from registry
config = SimpleNamespace()
for item in PERSISTENT_CONFIG_REGISTRY:
val = item.value
if hasattr(val, "value"):
val = val.value
setattr(config, item.env_name, val)
# 2. Populate MODELS from DB — critical for model validation
system_models = {}
try:
for m in _Models.get_all_models():
system_models[m.id] = m
except Exception:
pass
# 3. Build app_state
app_state = SimpleNamespace(
config=config,
TOOLS={},
TOOL_CONTENTS={},
FUNCTIONS={},
FUNCTION_CONTENTS={},
MODELS=system_models, # <-- KEY: must not be empty!
redis=None,
TOOL_SERVERS=[],
)
# 4. url_path_for helper
def url_path_for(name: str, **params):
if name == "get_file_content_by_id":
return f"/api/v1/files/{params.get('id')}/content"
return f"/mock/{name}"
app = SimpleNamespace(state=app_state, url_path_for=url_path_for)
# 5. Async body helpers
async def _json():
return body or {}
async def _body_fn():
return _json_mod.dumps(body or {}).encode("utf-8")
# 6. Headers
headers = {
"user-agent": "Mozilla/5.0",
"host": "localhost:8080",
"accept": "*/*",
}
if token:
headers["Authorization"] = token if token.startswith("Bearer ") else f"Bearer {token}"
return SimpleNamespace(
app=app,
headers=headers,
method="POST",
cookies={},
base_url="http://localhost:8080",
url=SimpleNamespace(path="/api/chat/completions", base_url="http://localhost:8080"),
state=SimpleNamespace(
token=SimpleNamespace(credentials=token or ""),
user=user or {},
),
json=_json,
body=_body_fn,
)
```
## Token Extraction
Tokens can be found in multiple places. Check in order:
```python
# 1. Direct in body (some SDK requests embed it)
token = body.get("token")
# 2. In metadata
token = token or (metadata or {}).get("token")
# 3. In the original __request__ Authorization header
if not token and __request__ is not None:
auth = getattr(__request__, "headers", {}).get("Authorization", "")
if auth.startswith("Bearer "):
token = auth.split(" ", 1)[1]
```
## Gotchas
- **`app.state.MODELS` empty = "Model not found"** for *any* model ID, even correct ones.
- `TOOL_SERVER_CONNECTIONS` must be synced from DB, not from in-memory cache (stale in multi-worker).
- `request.state.token.credentials` should be the **raw token** (no "Bearer " prefix).
- Tools may call `await request.json()` — must be an async method, not a regular attribute.

View File

@@ -0,0 +1,83 @@
# OpenWebUI Tool Parameter Injection
> Discovered: 2026-03-05
## Context
When OpenWebUI loads a Python Tool and calls one of its functions (e.g. `generate_mind_map`),
it automatically matches parameters from an `extra_params` dict against the function's
signature **by name**. This is done in:
```
open_webui/utils/tools.py → get_async_tool_function_and_apply_extra_params()
```
The lookup is: `extra_params = {k: v for k, v in extra_params.items() if k in sig.parameters}`
## Finding
A Tool function declares its dependencies via its parameter names. Common injected names:
| Parameter Name | What it contains |
|-----------------------|---------------------------------------------------|
| `__user__` | User context dict (id, email, role, name) |
| `__event_emitter__` | Async callable to emit status/notification events |
| `__event_call__` | Async callable for JS `__event_call__` roundtrips |
| `__request__` | Request-like object (must have `.app.state.MODELS`) |
| `__metadata__` | Dict: `{model, base_model_id, chat_id, ...}` |
| `__messages__` | Full conversation history list |
| `__chat_id__` | Current chat UUID |
| `__message_id__` | Current message UUID |
| `__session_id__` | Current session UUID |
| `__files__` | Files attached to the current message |
| `__task__` | Task type string (e.g. `title_generation`) |
| `body` | Raw request body dict (non-dunder variant) |
| `request` | Request object (non-dunder variant) |
## Key Rule
**`extra_params` must contain ALL keys a Tool's function signature declares.**
If a key is missing from `extra_params`, the parameter silently receives its default
value (e.g. `{}` for `__metadata__`). This means the Tool appears to work but
gets empty/wrong context.
## Solution / Pattern
When a Pipe calls an OpenWebUI Tool, it must populate `extra_params` with **all** the above:
```python
extra_params = {
"__request__": request, # Must have app.state.MODELS populated!
"request": request, # Non-dunder alias
"__user__": user_data,
"__event_emitter__": __event_emitter__,
"__event_call__": __event_call__,
"__messages__": messages,
"__metadata__": __metadata__ or {},
"__chat_id__": chat_id,
"__message_id__": message_id,
"__session_id__": session_id,
"__files__": files,
"__task__": task,
"__task_body__": task_body,
"body": body, # Non-dunder alias
...
}
```
## Model Resolution
Tools that call `generate_chat_completion` internally need a **valid model ID**.
When the conversation is running under a Pipe/Manifold model (e.g. `github_copilot.gpt-4o`),
the Tool's `valves.MODEL_ID` must be a *real* model known to the system.
`generate_chat_completion` validates model IDs against `request.app.state.MODELS`.
➡️ That dict **must be populated** from the database (see `openwebui-mock-request.md`).
## Gotchas
- Tools call `generate_chat_completion` with a `request` arg that must be the full Mock Request.
- If `app.state.MODELS` is empty, even a correctly-spelled model ID will cause "Model not found".
- `__metadata__['model']` can be a **dict** (from DB) **or a string** (manifold ID). Tools must
handle both types.
- For manifold models not in the DB, strip the prefix: `github_copilot.gpt-4o``gpt-4o`.

160
.agent/rules/antigravity.md Normal file
View File

@@ -0,0 +1,160 @@
---
description: >
Antigravity development mode rules. Apply when the user requests high-speed iteration,
a quick prototype, or says "反重力开发" / "antigravity mode".
globs: "plugins/**/*.py"
always_on: false
---
# Antigravity Development Mode
> High-speed delivery + strict reversibility. Every decision must keep both roll-forward and rollback feasible.
---
## Core Principles
1. **Small, isolated edits** — one logical change per operation; no mixing refactor + feature.
2. **Deterministic interfaces** — function signatures and return shapes must not change without an explicit contract update.
3. **Multi-level fallback** — every I/O path has a degraded alternative (e.g., S3 → local → DB).
4. **Reversible by default** — every file write, API call, or schema change must have an undo path recorded or be idempotent.
---
## Mandatory Safety Patterns
### 1. Timeout Guards on All Frontend Calls
Any `__event_call__` or `__event_emitter__` JS execution MUST be wrapped:
```python
import asyncio
try:
result = await asyncio.wait_for(
__event_call__({"type": "execute", "data": {"code": js_code}}),
timeout=2.0
)
except asyncio.TimeoutError:
logger.warning("Frontend JS execution timed out; falling back.")
result = fallback_value
except Exception as e:
logger.error(f"Frontend call failed: {e}", exc_info=True)
result = fallback_value
```
JS side must also guard internally:
```javascript
try {
return (localStorage.getItem('locale') || navigator.language || 'en-US');
} catch (e) {
return 'en-US';
}
```
### 2. Path Sandbox Validation
Resolve every workspace path and verify it stays inside the repo root:
```python
import os
def _validate_workspace_path(path: str, workspace_root: str) -> str:
resolved = os.path.realpath(os.path.abspath(path))
root = os.path.realpath(workspace_root)
if not resolved.startswith(root + os.sep) and resolved != root:
raise PermissionError(f"Path escape detected: {resolved} is outside {root}")
return resolved
```
### 3. Dual-Channel Upload Fallback
Always try API first; fall back to DB/local on failure:
```python
async def _upload_file(self, filename: str, content: bytes) -> str:
# Channel 1: API upload (S3-compatible)
try:
url = await self._api_upload(filename, content)
if url:
return url
except Exception as e:
logger.warning(f"API upload failed: {e}; falling back to local.")
# Channel 2: Local file + DB registration
return await self._local_db_upload(filename, content)
```
### 4. Progressive Status Reporting
For tasks > 3 seconds, emit staged updates:
```python
await self._emit_status(emitter, "正在分析内容...", done=False)
# ... phase 1 ...
await self._emit_status(emitter, "正在生成输出...", done=False)
# ... phase 2 ...
await self._emit_status(emitter, "完成", done=True)
```
Always emit `done=True` on completion and `notification(error)` on failure.
### 5. Emitter Guard
Check before every emit to prevent crashes on missing emitter:
```python
if emitter and self.valves.SHOW_STATUS:
await emitter({"type": "status", "data": {"description": msg, "done": done}})
```
### 6. Exception Surface Rule
Never swallow exceptions silently. Every `except` block must:
- Log to backend: `logger.error(f"...: {e}", exc_info=True)`
- Notify user: `await self._emit_notification(emitter, f"处理失败: {str(e)}", "error")`
---
## Edit Discipline
| ✅ DO | ❌ DO NOT |
|-------|-----------|
| One function / one Valve / one method per edit | Mix multiple unrelated changes in one operation |
| Validate input at the function boundary | Assume upstream data is well-formed |
| Return early on invalid state | Nest complex logic beyond 3 levels |
| Check fallback availability before primary path | Assume primary path always succeeds |
| Log before and after expensive I/O | Skip logging for "obvious" operations |
---
## Rollback Checklist
Before completing an antigravity operation, confirm:
- [ ] No global state mutated on `self` (filter singleton rule)
- [ ] File writes are atomic or can be recreated
- [ ] Database changes are idempotent (safe to re-run)
- [ ] Timeout guards are in place for all async calls to external systems
- [ ] The user can observe progress through status/notification events
- [ ] Non-obvious findings / gotchas are saved to `.agent/learnings/{topic}.md`
---
## Mandatory: Knowledge Capture
Any non-obvious pattern, internal API contract, or workaround discovered during an
antigravity session **MUST** be saved to `.agent/learnings/{topic}.md` before the
session ends. This ensures hard-won insights are not lost between sessions.
**Format**: See `.agent/learnings/README.md`
**Existing entries**: Browse `.agent/learnings/` for prior knowledge to reuse.
---
## References
- Full engineering spec: `.github/copilot-instructions.md` → Section: **Antigravity Development Mode**
- Design document: `docs/development/copilot-engineering-plan.md` → Section 5
- Knowledge base: `.agent/learnings/` — reusable engineering patterns and gotchas

View File

@@ -0,0 +1,33 @@
---
description: Standards for OpenWebUI Plugin Development, specifically README formatting.
globs: plugins/**
always_on: true
---
# Plugin Development Standards
## README Documentation
All plugins MUST follow the standard README template.
**Reference Template**: @docs/PLUGIN_README_TEMPLATE.md
### Language Requirements
- **English Version (`README.md`)**: The primary documentation source. Must follow the template strictly.
- **Chinese Version (`README_CN.md`)**: MUST be translated based on the English version (`README.md`) to ensure consistency in structure and content.
### Metadata Requirements
The metadata line must follow this format:
`**Author:** [Name](Link) | **Version:** [X.Y.Z] | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **License:** MIT`
### Structure Checklist
1. **Title & Description**
2. **Metadata Line** (Author, Version, Project, License)
3. **Preview** (Screenshots/GIFs)
4. **What's New** (Keep last 3 versions)
5. **Key Features**
6. **How to Use**
7. **Configuration (Valves)**
8. **Troubleshooting** (Must include link to GitHub Issues)

71
.agent/skills/README.md Normal file
View File

@@ -0,0 +1,71 @@
# Agent Skills Index
This folder contains reusable Agent Skills for GitHub Copilot / VS Code custom agent workflows.
## Available Skills
- **community-announcer**
- Purpose: Generate community announcement content and related assets.
- Entry: `community-announcer/SKILL.md`
- **doc-mirror-sync**
- Purpose: Sync mirrored documentation content and helper scripts.
- Entry: `doc-mirror-sync/SKILL.md`
- **gh-issue-replier**
- Purpose: Draft standardized issue replies with templates.
- Entry: `gh-issue-replier/SKILL.md`
- **gh-issue-scheduler**
- Purpose: Schedule and discover unanswered issues for follow-up.
- Entry: `gh-issue-scheduler/SKILL.md`
- **i18n-validator**
- Purpose: Validate translation key consistency across i18n dictionaries.
- Entry: `i18n-validator/SKILL.md`
- **plugin-scaffolder**
- Purpose: Scaffold OpenWebUI plugin boilerplate with repository standards.
- Entry: `plugin-scaffolder/SKILL.md`
- **version-bumper**
- Purpose: Assist with semantic version bumping workflows.
- Entry: `version-bumper/SKILL.md`
- **xlsx-single-file**
- Purpose: Single-file spreadsheet operations workflow without LibreOffice.
- Entry: `xlsx-single-file/SKILL.md`
---
## Release Pipeline Skills
These four skills form a complete release pipeline and are designed to be used in sequence:
```
release-prep → pr-submitter → pr-reviewer → release-finalizer
(prepare) (push & PR) (respond to review) (merge & close issue)
```
- **release-prep**
- Purpose: Full release preparation — version sync across 7+ files, bilingual release notes creation, consistency check, and commit.
- Entry: `release-prep/SKILL.md`
- **pr-submitter**
- Purpose: Shell-escape-safe PR submission — writes body to temp file, validates sections, pushes branch, creates PR via `gh pr create --body-file`.
- Entry: `pr-submitter/SKILL.md`
- **pr-reviewer**
- Purpose: Fetch PR review comments, categorize feedback, implement fixes, commit and push, reply to reviewers.
- Entry: `pr-reviewer/SKILL.md`
- **release-finalizer**
- Purpose: Merge release PR to main with proper commit message, auto-link and close related issues, post closing messages.
- Entry: `release-finalizer/SKILL.md`
## Notes
- Skill definitions follow the expected location pattern:
- `.github/skills/<skill-name>/SKILL.md`
- Each skill may include optional `assets/`, `references/`, and `scripts/` folders.
- This directory mirrors `.gemini/skills` for compatibility.

View File

@@ -0,0 +1,23 @@
---
name: community-announcer
description: Drafts engaging English and Chinese update announcements for the OpenWebUI Community and other social platforms. Use when a new version is released.
---
# Community Announcer
## Overview
Automates the drafting of high-impact update announcements.
## Workflow
1. **Source Intel**: Read the latest version's `What's New` section from `README.md`.
2. **Drafting**: Create two versions:
- **Community Post**: Professional, structured, technical.
- **Catchy Short**: For Discord/Twitter, use emojis and bullet points.
3. **Multi-language**: Generate BOTH English and Chinese versions automatically.
## Announcement Structure (Recommended)
- **Headline**: "Update vX.X.X - [Main Feature]"
- **Introduction**: Brief context.
- **Key Highlights**: Bulleted list of fixes/features.
- **Action**: "Download from [Market Link]"
- **Closing**: Thanks and Star request.

View File

@@ -0,0 +1,50 @@
---
name: doc-mirror-sync
description: Automatically synchronizes plugin READMEs to the official documentation directory (docs/). Use after editing a plugin's local documentation to keep the MkDocs site up to date.
---
# Doc Mirror Sync
## Overview
Automates the mirroring of `plugins/{type}/{name}/README.md` to `docs/plugins/{type}/{name}.md`.
## Docs-Only Mode (No Release Changes)
Use this mode when the request is "only sync docs".
- Only update documentation mirror files under `docs/plugins/**`.
- Do **not** bump plugin version.
- Do **not** modify plugin code (`plugins/**.py`) unless explicitly requested.
- Do **not** update root badges/dates for release.
- Do **not** run release preparation steps.
## Workflow
1. Identify changed READMEs.
2. Copy content to corresponding mirror paths.
3. Update version badges in `docs/plugins/{type}/index.md`.
## Commands
### Sync all mirrors (EN + ZH)
```bash
python .github/skills/doc-mirror-sync/scripts/sync.py
```
### Sync only one plugin (EN only)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
```
### Sync only one plugin (EN + ZH)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
cp plugins/<type>/<name>/README_CN.md docs/plugins/<type>/<name>.zh.md
```
## Notes
- If asked for English-only update, sync only `README.md` -> `.md` mirror.
- If both languages are requested, sync both `README.md` and `README_CN.md`.
- After syncing, verify git diff only contains docs file changes.

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3
import os
import shutil
import re
def sync_mirrors():
plugins_root = "plugins"
docs_root = "docs/plugins"
types = ["actions", "filters", "pipes", "pipelines", "tools"]
for t in types:
src_type_dir = os.path.join(plugins_root, t)
dest_type_dir = os.path.join(docs_root, t)
if not os.path.exists(src_type_dir): continue
os.makedirs(dest_type_dir, exist_ok=True)
for name in os.listdir(src_type_dir):
plugin_dir = os.path.join(src_type_dir, name)
if not os.path.isdir(plugin_dir): continue
# Sync README.md -> docs/plugins/{type}/{name}.md
src_readme = os.path.join(plugin_dir, "README.md")
if os.path.exists(src_readme):
dest_readme = os.path.join(dest_type_dir, f"{name}.md")
shutil.copy(src_readme, dest_readme)
print(f"✅ Mirrored: {t}/{name} (EN)")
# Sync README_CN.md -> docs/plugins/{type}/{name}.zh.md
src_readme_cn = os.path.join(plugin_dir, "README_CN.md")
if os.path.exists(src_readme_cn):
dest_readme_zh = os.path.join(dest_type_dir, f"{name}.zh.md")
shutil.copy(src_readme_cn, dest_readme_zh)
print(f"✅ Mirrored: {t}/{name} (ZH)")
if __name__ == "__main__":
sync_mirrors()

View File

@@ -0,0 +1,51 @@
---
name: gh-issue-replier
description: Professional English replier for GitHub issues. Use when a task is completed, a bug is fixed, or more info is needed from the user. Automates replying using the 'gh' CLI tool.
---
# Gh Issue Replier
## Overview
The `gh-issue-replier` skill enables Gemini CLI to interact with GitHub issues professionally. It enforces English for all communications and leverages the `gh` CLI to post comments.
## Workflow
1. **Identify the Issue**: Find the issue number (e.g., #49).
2. **Check Star Status**: Run the bundled script to check if the author has starred the repo.
* Command: `bash scripts/check_star.sh <issue-number>`
* Interpretation:
* Exit code **0**: User has starred. Use "Already Starred" templates.
* Exit code **1**: User has NOT starred. Include "Star Request" in the reply.
3. **Select a Template**: Load [templates.md](references/templates.md) to choose a suitable English response pattern.
4. **Draft the Reply**: Compose a concise message based on the star status.
5. **Post the Comment**: Use the `gh` tool to submit the reply.
## Tool Integration
### Check Star Status
```bash
bash scripts/check_star.sh <issue-number>
```
### Post Comment
```bash
gh issue comment <issue-number> --body "<message-body>"
```
Example (if user has NOT starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. If you find this helpful, a star on the repo would be much appreciated! ⭐"
```
Example (if user HAS starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. Thanks for your support!"
```
## Guidelines
- **Language**: ALWAYS use English for the comment body, even if the system prompt or user conversation is in another language.
- **Tone**: Professional, helpful, and appreciative.
- **Precision**: When announcing a fix, mention the specific version or the logic change (e.g., "Updated regex pattern").
- **Closing**: If the issue is resolved and you have permission, you can also use `gh issue close <number>`.

View File

@@ -0,0 +1,17 @@
# Reference Documentation for Gh Issue Replier
This is a placeholder for detailed reference documentation.
Replace with actual reference content or delete if not needed.
## Structure Suggestions
### API Reference Example
- Overview
- Authentication
- Endpoints with examples
- Error codes
### Workflow Guide Example
- Prerequisites
- Step-by-step instructions
- Best practices

View File

@@ -0,0 +1,45 @@
# Issue Reply Templates
Use these templates to craft professional English replies. Adjust placeholders like `@username`, `v1.2.x`, and `[commit hash]` as needed.
## 1. Acknowledging a New Issue
Use when you first see an issue and want to let the user know you are working on it.
- "Thank you for reporting this! I'm looking into it right now."
- "Thanks for bringing this to my attention. I'll try to reproduce this behavior and get back to you shortly."
## 2. Requesting More Information
Use when you need logs or specific details to fix the bug.
- "Could you please provide the **'Original'** vs **'Normalized'** content from your browser console logs (F12)? It would help a lot in debugging."
- "It would be very helpful if you could share the specific Markdown text that triggered this issue."
## 3. Announcing a Fix
Use when you have pushed the fix to the repository.
- "This has been fixed in version **v1.2.x**. You can update the plugin to resolve it."
- "I've just pushed a fix for this in [commit hash]. Please let me know if it works for you after updating."
- "The issue was caused by a greedy regex pattern. I've updated it to use a tempered greedy token to prevent incorrect merging."
## 4. Guiding to Official Market
Always provide the official market link to ensure the user gets the latest verified version.
- "The fix is now live! You can download the latest version from the official OpenWebUI Community page here: [Plugin Market Link]. Simply update the function in your OpenWebUI instance to apply the changes."
- "I recommend getting the updated version from the official store: [Link]. It includes the fix for the spacing issue we discussed."
## 5. Closing the Issue
Use when the issue is confirmed resolved.
- "Glad to hear it's working now! Closing this for now. Feel free to reopen it if the problem persists."
- "Since this is resolved, I'm closing this issue. Thanks again for your feedback!"
## 5. Pro-tip: Star Request
Gently handle star requests based on the user's current status.
### If User has NOT starred:
- "If you find this plugin helpful, a star on the repo would be much appreciated! ⭐"
- "We'd love your support! If this fixed your issue, please consider starring the repository. ⭐"
### If User HAS already starred:
- "Thanks again for starring the project and for your continuous support!"
- "I appreciate your support and for being a stargazer of this project!"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Robust Star Checker v2
# Usage: ./check_star.sh <issue_number>
ISSUE_NUM=$1
if [ -z "$ISSUE_NUM" ]; then exit 2; fi
# 1. Get Repo and Author info
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + \"/\" + .name")
USER_LOGIN=$(gh issue view "$ISSUE_NUM" --json author -q ".author.login")
# 2. Use GraphQL for high precision (Detects stars even when REST 404s)
IS_STARRED=$(gh api graphql -f query='
query($owner:String!, $repo:String!, $user:String!) {
repository(owner:$owner, name:$repo) {
stargazers(query:$user, first:1) {
nodes {
login
}
}
}
}' -f owner="${REPO_FULL%/*}" -f repo="${REPO_FULL#*/}" -f user="$USER_LOGIN" -q ".data.repository.stargazers.nodes[0].login")
if [ "$IS_STARRED" == "$USER_LOGIN" ]; then
echo "Confirmed: @$USER_LOGIN HAS starred $REPO_FULL. ⭐"
exit 0
else
echo "Confirmed: @$USER_LOGIN has NOT starred $REPO_FULL."
exit 1
fi

View File

@@ -0,0 +1,42 @@
---
name: gh-issue-scheduler
description: Finds all open GitHub issues that haven't been replied to by the owner, summarizes them, and generates a solution plan. Use when the user wants to audit pending tasks or plan maintenance work.
---
# Gh Issue Scheduler
## Overview
The `gh-issue-scheduler` skill helps maintainers track community feedback by identifying unaddressed issues and drafting actionable technical plans to resolve them.
## Workflow
1. **Identify Unanswered Issues**: Run the bundled script to fetch issues without owner replies.
* Command: `bash scripts/find_unanswered.sh`
2. **Analyze and Summarize**: For each identified issue, summarize the core problem and the user's intent.
3. **Generate Solution Plans**: Draft a technical "Action Plan" for each issue, including:
* **Root Cause Analysis** (if possible)
* **Proposed Fix/Implementation**
* **Verification Strategy**
4. **Present to User**: Display a structured report of all pending issues and their respective plans.
## Tool Integration
### Find Unanswered Issues
```bash
bash scripts/find_unanswered.sh
```
## Report Format
When presenting the summary, use the following Markdown structure:
### 📋 Unanswered Issues Audit
#### Issue #[Number]: [Title]
- **Author**: @username
- **Summary**: Concise description of the problem.
- **Action Plan**:
1. Step 1 (e.g., Investigate file X)
2. Step 2 (e.g., Apply fix Y)
3. Verification (e.g., Run test Z)

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Fetch all open issues and filter for those without responses from the owner/collaborators.
# Uses 'gh' CLI.
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + "/" + .name")
OWNER=${REPO_FULL%/*}
# 1. Get all open issues
OPEN_ISSUES=$(gh issue list --state open --json number,title,author,createdAt --limit 100)
echo "Analysis for repository: $REPO_FULL"
echo "------------------------------------"
# Process each issue
echo "$OPEN_ISSUES" | jq -c '.[]' | while read -r issue; do
NUMBER=$(echo "$issue" | jq -r '.number')
TITLE=$(echo "$issue" | jq -r '.title')
AUTHOR=$(echo "$issue" | jq -r '.author.login')
# Check comments for owner responses
# We look for comments where the author is the repo owner
COMMENTS=$(gh issue view "$NUMBER" --json comments -q ".comments[].author.login" 2>/dev/null)
HAS_OWNER_REPLY=false
for COMMENT_AUTHOR in $COMMENTS; do
if [ "$COMMENT_AUTHOR" == "$OWNER" ]; then
HAS_OWNER_REPLY=true
break
fi
done
if [ "$HAS_OWNER_REPLY" == "false" ]; then
echo "ISSUE_START"
echo "ID: $NUMBER"
echo "Title: $TITLE"
echo "Author: $AUTHOR"
echo "Description:"
gh issue view "$NUMBER" --json body -q ".body"
echo "ISSUE_END"
fi
done

View File

@@ -0,0 +1,14 @@
---
name: i18n-validator
description: Validates multi-language consistency in the TRANSLATIONS dictionary of a plugin. Use to check if any language keys are missing or if translations need updating.
---
# I18n Validator
## Overview
Ensures all 12 supported languages (en-US, zh-CN, etc.) have aligned translation keys.
## Features
- Detects missing keys in non-English dictionaries.
- Suggests translations using the core AI engine.
- Validates the `fallback_map` for variant redirects.

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import sys
import ast
import os
def check_i18n(file_path):
if not os.path.exists(file_path):
print(f"Error: File not found {file_path}")
return
with open(file_path, 'r', encoding='utf-8') as f:
tree = ast.parse(f.read())
translations = {}
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id == "TRANSLATIONS":
translations = ast.literal_eval(node.value)
break
if not translations:
print("⚠️ No TRANSLATIONS dictionary found.")
return
# Base keys from English
base_lang = "en-US"
if base_lang not in translations:
print(f"❌ Error: {base_lang} missing in TRANSLATIONS.")
return
base_keys = set(translations[base_lang].keys())
print(f"🔍 Analyzing {file_path}...")
print(f"Standard keys ({len(base_keys)}): {', '.join(sorted(base_keys))}
")
for lang, keys in translations.items():
if lang == base_lang: continue
lang_keys = set(keys.keys())
missing = base_keys - lang_keys
extra = lang_keys - base_keys
if missing:
print(f"{lang}: Missing {len(missing)} keys: {', '.join(missing)}")
if extra:
print(f"⚠️ {lang}: Has {len(extra)} extra keys: {', '.join(extra)}")
if not missing and not extra:
print(f"{lang}: Aligned.")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: validate_i18n.py <path_to_plugin.py>")
sys.exit(1)
check_i18n(sys.argv[1])

View File

@@ -0,0 +1,19 @@
---
name: plugin-scaffolder
description: Generates a standardized single-file i18n Python plugin template based on project standards. Use when starting a new plugin development to skip boilerplate writing.
---
# Plugin Scaffolder
## Overview
Generates compliant OpenWebUI plugin templates with built-in i18n, common utility methods, and required docstring fields.
## Usage
1. Provide the **Plugin Name** and **Type** (action/filter/pipe).
2. The skill will generate the `.py` file and the bilingual `README` files.
## Template Standard
- `Valves(BaseModel)` with `UPPER_SNAKE_CASE`
- `_get_user_context` with JS fallback and timeout
- `_emit_status` and `_emit_debug_log` methods
- Standardized docstring metadata

View File

@@ -0,0 +1,34 @@
# {{TITLE}}
**Author:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **Version:** 0.1.0 | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **License:** MIT
{{DESCRIPTION}}
## 🔥 What's New in v0.1.0
* Initial release of {{TITLE}}.
## 🌐 Multilingual Support
Supports automatic interface and status switching for the following languages:
`English`, `简体中文`, `繁體中文 (香港)`, `繁體中文 (台灣)`, `한국어`, `日本語`, `Français`, `Deutsch`, `Español`, `Italiano`, `Tiếng Việt`, `Bahasa Indonesia`.
## ✨ Core Features
* Feature 1
* Feature 2
## How to Use 🛠️
1. Install the plugin in Open WebUI.
2. Configure settings in Valves.
## Configuration (Valves) ⚙️
| Parameter | Default | Description |
| :--- | :--- | :--- |
| `priority` | `50` | Execution priority. |
## ⭐ Support
If this plugin has been useful, a star on [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) is a big motivation for me. Thank you for the support.

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import sys
import os
def scaffold(p_type, p_name, title, desc):
target_dir = f"plugins/{p_type}/{p_name}"
os.makedirs(target_dir, exist_ok=True)
class_name = (
"Action"
if p_type == "actions"
else (
"Filter"
if p_type == "filters"
else "Tools" if p_type == "tools" else "Pipe"
)
)
method_name = (
"action"
if p_type == "actions"
else (
"outlet"
if p_type == "filters"
else "execute" if p_type == "tools" else "pipe"
)
)
replacements = {
"{{TITLE}}": title,
"{{DESCRIPTION}}": desc,
"{{CLASS_NAME}}": class_name,
"{{METHOD_NAME}}": method_name,
}
# Files to generate
templates = [
("assets/template.py.j2", f"{p_name}.py"),
("assets/README_template.md", "README.md"),
("assets/README_template.md", "README_CN.md"),
]
# Path relative to skill root
skill_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
for t_path, t_name in templates:
template_file = os.path.join(skill_root, t_path)
if not os.path.exists(template_file):
print(f"⚠️ Warning: Template not found {template_file}")
continue
with open(template_file, "r") as f:
content = f.read()
for k, v in replacements.items():
content = content.replace(k, v)
with open(os.path.join(target_dir, t_name), "w") as f:
f.write(content)
print(f"✅ Generated: {target_dir}/{t_name}")
if __name__ == "__main__":
if len(sys.argv) < 5:
print("Usage: scaffold.py <type> <name> <title> <desc>")
sys.exit(1)
scaffold(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

View File

@@ -0,0 +1,180 @@
---
name: pr-reviewer
description: Fetches PR review comments, analyzes requested changes, implements fixes, commits and pushes the resolution. Use after a reviewer has left comments on an open PR to close the feedback loop efficiently.
---
# PR Reviewer
## Overview
This skill automates the response cycle for code review. When a reviewer leaves comments on a Pull Request, this skill fetches all pending feedback, categorizes issues by severity, implements fixes, and submits a follow-up commit with appropriate review response comments.
## Prerequisites
- An open PR exists with pending review comments
- The local branch matches the PR's head branch
- `gh` CLI is authenticated
---
## Workflow
### Step 1 — Fetch Review State
Retrieve all review comments and overall review status:
```bash
# Get overall review decisions
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json reviews,reviewDecision,headRefName \
--jq '{decision: .reviewDecision, reviews: [.reviews[] | {author: .author.login, state: .state, body: .body}]}'
# Get inline code comments (specific line comments)
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments \
--jq '[.[] | {path: .path, line: .line, body: .body, author: .user.login, id: .id}]'
# Get general issue comments
PAGER=cat GH_PAGER=cat gh issue view <PR-NUMBER> --comments --json comments \
--jq '[.comments[] | {author: .author.login, body: .body}]'
```
Confirm the current local branch matches the PR head:
```bash
git branch --show-current
```
If mismatched, checkout the correct branch first.
### Step 2 — Categorize Review Feedback
Group feedback into categories:
| Category | Examples | Action |
|----------|---------|--------|
| **Code Bug** | Logic error, incorrect variable, broken condition | Fix code immediately |
| **Style / Formatting** | Indentation, naming convention, missing blank line | Fix code |
| **Documentation** | Missing i18n key, wrong version in README, typo | Fix docs |
| **Design Question** | Suggestion to restructure, alternative approach | Discuss with user before implementing |
| **Nitpick / Optional** | Minor style preferences reviewer marked as optional | Fix if quick; document if skipped |
| **Blocking** | Reviewer explicitly blocks merge | Must fix before proceeding |
Present the full categorized list to the user and confirm the resolution plan.
### Step 3 — Implement Fixes
For each accepted fix:
1. Read the affected file at the commented line for context:
```bash
sed -n '<line-5>,<line+10>p' <file-path>
```
2. Apply the fix using appropriate file edit tools
3. After editing, verify the specific area looks correct
**For code changes that might affect behavior:**
- Check if tests exist: `ls tests/test_*.py`
- If tests exist, run them: `python -m pytest tests/ -v`
**For documentation fixes:**
- If modifying README.md, check if `docs/` mirror needs the same fix
- Apply the same fix to both locations
### Step 4 — Run Consistency Checks
After all fixes are applied:
```bash
# Version consistency (if any version files were touched)
python3 scripts/check_version_consistency.py
# Quick syntax check for Python files
python3 -m py_compile plugins/{type}/{name}/{name}.py && echo "✅ Syntax OK"
```
### Step 5 — Stage and Commit
Create a new commit (do NOT amend if the branch has already been pushed, to avoid force-push):
```bash
git add -A
git status
```
Draft a Conventional Commits message for the fixup:
Format: `fix(scope): address review feedback`
Body should list what was fixed, referencing reviewer concerns:
```
fix(github-copilot-sdk): address review feedback from @reviewer
- Fix X per review comment on line Y of file Z
- Update README to clarify auth requirement
- Correct edge case in _parse_mcp_servers logic
```
```bash
git commit -m "<fixup commit message>"
```
### Step 6 — Push the Fix Commit
```bash
git push origin $(git branch --show-current)
```
**Force-push policy:**
- Use `git push` (non-force) by default
- Only use `git push --force-with-lease` if:
1. The user explicitly requests it, AND
2. The only change is an amended commit squash (cosmetic, no logic change)
3. Never use `--force` (without `--lease`)
### Step 7 — Respond to Reviewers
For each addressed review comment, post a reply:
```bash
# Reply to inline comment
gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments/<COMMENT-ID>/replies \
-X POST -f body="Fixed in commit <SHORT-SHA>. <Brief explanation of what was changed.>"
# General comment to summarize all fixes
gh issue comment <PR-NUMBER> --body "All review feedback addressed in commit <SHORT-SHA>:
- Fixed: <item 1>
- Fixed: <item 2>
Ready for re-review. 🙏"
```
### Step 8 — Re-Request Review (Optional)
If the reviewer had submitted a `CHANGES_REQUESTED` review, request a new review after fixes:
```bash
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/requested_reviewers \
-X POST -f reviewers[]='<reviewer-login>'
```
---
## Decision Guide
### When NOT to implement a suggestion immediately
- **Design questions**: "Should this be a separate class?" — Present to user for decision
- **Optional nitpicks**: Reviewer marked as `nit:` — Ask user if they want to include it
- **Large refactors**: If fix would require changing >50 lines, propose a separate follow-up issue instead
### When to ask the user before proceeding
- Any fix involving behavioral changes to plugin logic
- Renaming Valve keys (breaking change — requires migration notes)
- Changes that affect the bilingual release notes already committed
---
## Anti-Patterns to Avoid
- ❌ Do NOT `git commit --amend` on a pushed commit without user approval for force-push
- ❌ Do NOT silently skip a reviewer's comment; always acknowledge it (implement or explain why not)
- ❌ Do NOT use `--force` (only `--force-with-lease` when absolutely necessary)
- ❌ Do NOT make unrelated changes in the fixup commit; keep scope focused on review feedback
- ❌ Do NOT respond to reviewer comments in Chinese if the PR language context is English

View File

@@ -0,0 +1,194 @@
---
name: pr-submitter
description: Submits a feature branch as a Pull Request with a validated, properly formatted bilingual PR body. Handles shell-escape-safe body writing via temp files. Use after release-prep has committed all changes.
---
# PR Submitter
## Overview
This skill handles the final step of pushing a feature branch and creating a validated Pull Request on GitHub. Its primary purpose is to avoid the shell-escaping pitfalls (backticks, special characters in `gh pr create --body`) by always writing the PR body to a **temp file** first.
## Prerequisites
- All changes are committed (use `release-prep` skill first)
- The `gh` CLI is authenticated (`gh auth status`)
- Current branch is NOT `main` or `master`
---
## Workflow
### Step 0 — Initialize Temp Directory (Project-Based)
For all temporary files, use the project's `.temp/` directory instead of system `/tmp`:
```bash
# Create temp directory if it doesn't exist
mkdir -p .temp
```
**Why**: All temporary files stay within the project workspace, avoiding system `/tmp` pollution and better aligning with OpenWebUI workspace isolation principles.
### Step 1 — Pre-Flight Checks
Run these checks before any push:
```bash
# 1. Confirm not on protected branch
git branch --show-current
# 2. Verify there are commits to push
git log origin/$(git branch --show-current)..HEAD --oneline 2>/dev/null || echo "No remote tracking branch yet"
# 3. Check gh CLI auth
gh auth status
```
If any check fails, stop and report clearly.
### Step 2 — Collect PR Metadata
Gather:
- **PR Title**: Must follow Conventional Commits format, English only (e.g., `feat(github-copilot-sdk): release v0.8.0 with conditional tool filtering`)
- **Target base branch**: Default is `main`
- **Plugin name + version** (to build body sections)
- **Key changes** (reuse from release-prep or the latest What's New section)
### Step 3 — Build PR Body File (Shell-Escape-Safe)
**Always write the body to a temp file in `.temp/` directory.** Never embed multi-line markdown with special characters directly in a shell command.
```bash
cat > .temp/pr_body.md << 'HEREDOC'
## Summary
Brief one-sentence description of what this PR accomplishes.
## Changes
### New Features
- Feature 1 description
- Feature 2 description
### Bug Fixes
- Fix 1 description
## Plugin Version
- `PluginName` bumped to `vX.X.X`
## Documentation
- README.md / README_CN.md updated
- docs/ mirrors synced
## Testing
- [ ] Tested locally in OpenWebUI
- [ ] i18n validated (all language keys present)
- [ ] Version consistency check passed (`python3 scripts/check_version_consistency.py`)
---
## 变更摘要(中文)
简要描述本次 PR 的改动内容。
### 新功能
- 功能1描述
- 功能2描述
### 问题修复
- 修复1描述
HEREDOC
```
**Critical rules for the body file:**
- Use `<< 'HEREDOC'` (quoted heredoc) to prevent variable expansion
- Keep all backticks literal — they are safe inside a heredoc
- Paths like `/api/v1/files/` are safe too since heredoc doesn't interpret them as commands
### Step 4 — Validate PR Body
Before submitting, verify the body file contains expected sections:
```bash
# Check key sections exist
grep -q "## Summary" .temp/pr_body.md && echo "✅ Summary" || echo "❌ Summary missing"
grep -q "## Changes" .temp/pr_body.md && echo "✅ Changes" || echo "❌ Changes missing"
grep -q "## 变更摘要" .temp/pr_body.md && echo "✅ CN Section" || echo "❌ CN Section missing"
# Preview the body
cat .temp/pr_body.md
```
Ask the user to confirm the body content before proceeding.
### Step 5 — Push Branch
```bash
git push -u origin $(git branch --show-current)
```
If push is rejected (non-fast-forward), report to user and ask whether to force-push. **Do NOT force-push without explicit confirmation.**
### Step 6 — Create Pull Request
```bash
gh pr create \
--base main \
--head $(git branch --show-current) \
--title "<PR title from Step 2>" \
--body-file .temp/pr_body.md
```
Always use `--body-file`, never `--body` with inline markdown.
### Step 7 — Verify PR Creation
```bash
PAGER=cat GH_PAGER=cat gh pr view --json number,url,title,body --jq '{number: .number, url: .url, title: .title, body_preview: .body[:200]}'
```
Confirm:
- PR number and URL
- Title matches intended Conventional Commits format
- Body preview includes key sections (not truncated/corrupted)
If the body appears corrupted (empty sections, missing backtick content), use edit:
```bash
gh pr edit <PR-NUMBER> --body-file /tmp/pr_body.md
```
### Step 8 — Cleanup
```bash
rm -f .temp/pr_body.md
```
**Note**: The `.temp/` directory itself is preserved for reuse; only the individual PR body file is deleted. To fully clean up: `rm -rf .temp/`
Report final PR URL to the user.
---
## Shell-Escape Safety Rules
| Risk | Safe Approach |
|------|--------------|
| Backticks in `--body` | Write to file, use `--body-file` |
| Paths like `/api/...` | Safe in heredoc; risky in inline `--body` |
| Newlines in `--body` | File-based only |
| `$variable` expansion | Use `<< 'HEREDOC'` (quoted) |
| Double quotes in body | Safe in heredoc file |
| Temp file storage | Use `.temp/` dir, not `/tmp` |
| Cleanup after use | Always delete temp file (keep dir) |
---
## Anti-Patterns to Avoid
- ❌ Never use `--body "..."` with multi-line content directly in shell command
- ❌ Never interpolate variables directly into heredoc without quoting the delimiter
- ❌ Never force-push (`--force`) without explicit user confirmation
- ❌ Never target `main` as the source branch (only as base)
- ❌ Never skip the body validation step — a PR with empty body is worse than a delayed PR

View File

@@ -0,0 +1,208 @@
---
name: release-finalizer
description: Merges a release PR, associates it with resolved issues, replies to issue reporters, and closes issues. Use after PR review is complete and ready for merge. Closes the release cycle.
---
# Release Finalizer
## Overview
This skill completes the final step of the release cycle: merging the release PR to `main`, replying to all related issues with solutions, and automatically closing them using GitHub's issue linking mechanism.
## Prerequisites
- The PR is in `OPEN` state and ready to merge
- All status checks have passed (CI green)
- All review feedback has been addressed
- The PR relates to one or more GitHub issues (either in PR description or through commits)
---
## Workflow
### Step 1 — Pre-Merge Verification
Verify that the PR is ready:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json state,statusCheckRollup,reviewDecision
```
Checklist:
-`state` is `OPEN`
-`statusCheckRollup` all have `conclusion: SUCCESS`
-`reviewDecision` is `APPROVED` or empty (no blocking reviews)
If any check fails, **do NOT merge**. Report the issue to the user.
### Step 2 — Identify Related Issues
Issues can be linked to a PR in multiple ways. Check the PR description and commit messages for keywords:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json body,commits
```
Look for patterns like:
- `Closes #XX`, `Fixes #XX`, `Resolves #XX` (in description or commit bodies)
- `#XX` mentioned as "related to" or "addresses"
**Manual input**: If issue links are not in the PR, ask the user which issue(s) this PR resolves.
Extract all issue numbers into a list: `[#48, #52, ...]`
### Step 3 — Select Merge Strategy
Offer the user three options:
| Strategy | Git Behavior | Use Case |
|----------|-------------|----------|
| **Squash** | All commits squashed into one commit on main | Clean history, recommended for release PRs |
| **Rebase** | Linear history, no merge commit | Preserve commit granularity |
| **Merge** | Merge commit created | Preserve full PR context |
**Recommendation for release PRs**: Use `--squash` to create a single clean commit.
If user doesn't specify, default to `--squash`.
### Step 4 — Prepare Merge Commit Message
If using `--squash`, craft a single comprehensive commit message:
**Format** (Conventional Commits + Github linking):
```
type(scope): description
- Bullet point 1
- Bullet point 2
Closes #48
Closes #52
```
The `Closes #XX` keyword tells GitHub to automatically close those issues when the commit lands on `main`.
Example:
```
feat(pipes,filters): release Copilot SDK Pipe v0.8.0 and Files Filter v0.1.3
- Implement P1~P4 conditional tool filtering system
- Fix file publishing reliability across all storage backends
- Add strict file URL validation
- Update bilingual documentation
Closes #48
```
### Step 5 — Execute Merge
```bash
gh pr merge <PR-NUMBER> \
--squash \
--delete-branch \
-m "type(scope): description" \
-b "- Bullet 1\n- Bullet 2\n\nCloses #48"
```
**Key flags:**
- `--squash`: Squash commits (recommended for releases)
- `--delete-branch`: Delete the feature branch after merge
- `-m`: Commit subject
- `-b`: Commit body (supports `\n` for newlines)
Confirm the merge is successful; GitHub will automatically close related issues with `Closes #XX` keyword.
### Step 6 — Verify Auto-Close
GitHub automatically closes issues when a commit with `Closes #XX` lands on the default branch (`main`).
To verify:
```bash
PAGER=cat GH_PAGER=cat gh issue view <ISSUE-NUMBER> --json state
```
Should show `state: CLOSED`.
### Step 7 — Post Closing Message (Optional but Recommended)
For better UX, manually post a summary comment to **each issue** before it auto-closes (since auto-close happens silently):
```bash
gh issue comment <ISSUE-NUMBER> --body "
This has been fixed in PR #<PR-NUMBER>, which is now merged to main.
**Solution Summary:**
- <Key fix 1>
- <Key fix 2>
The fix will be available in the next plugin release. Thank you for reporting! ⭐
"
```
### Step 8 — (Optional) Regenerate Release Notes
If the merge revealed any final tweaks to release notes:
```bash
# Re-export release notes from merged commit
git log --oneline -1 <merged-commit-sha>
```
If needed, create a follow-up PR with doc polish (do NOT force-push the merged commit).
---
## Merge Strategy Decision Tree
```
Is this a patch/hotfix release?
├─ YES → Use --squash
└─ NO → Multi-feature release?
├─ YES → Use --squash (cleaner history)
└─ NO → Preserve detail?
├─ YES → Use --rebase
└─ NO → Use --merge (preserve PR context)
```
---
## Issue Auto-Close Keywords
These keywords in commit/PR messages will auto-close issues when merged to `main`:
- `Closes #XX`
- `Fixes #XX`
- `Resolves #XX`
- `close #XX` (case-insensitive)
- `fix #XX`
- `resolve #XX`
**Important**: The keyword must be on the **final commit that lands on** `main`. For squash merges, it must be in the squash commit message body.
---
## Anti-Patterns to Avoid
- ❌ Do NOT merge if any status checks are PENDING or FAILED
- ❌ Do NOT merge if there are blocking reviews (reviewDecision: `CHANGES_REQUESTED`)
- ❌ Do NOT merge without verifying the Conventional Commits format in the merge message
- ❌ Do NOT merge without including `Closes #XX` keywords for all related issues
- ❌ Do NOT assume issues will auto-close silently — post a courtesy comment first
- ❌ Do NOT delete the branch if it might be needed for cherry-pick or hotfixes later
---
## Troubleshooting
### Issue did not auto-close after merge
- Verify the `Closes #XX` keyword is in the **final commit message** (use `git log` to check)
- Ensure the commit is on the `main` branch
- GitHub sometimes takes a few seconds to process; refresh the issue page
### Multiple issues to close
- List all in separate `Closes #XX` lines in the commit body
- Each one will be independently auto-closed
### Want to close issue without merge?
- Use `gh issue close <ISSUE-NUMBER>` manually
- Only recommended if the PR was manually reverted or deemed invalid

View File

@@ -0,0 +1,157 @@
---
name: release-prep
description: Orchestrates the full release preparation flow for a plugin — version sync across 7+ files, bilingual release notes creation, and commit message drafting. Use before submitting a PR. Does NOT push or create a PR; that is handled by pr-submitter.
---
# Release Prep
## Overview
This skill drives the complete pre-PR release pipeline. It enforces the repository rule that every release must synchronize the version number and changelog across **at least 7 locations** before a commit is created.
## Scope
This skill covers:
1. Version sync (delegates detail to `version-bumper` if needed)
2. Bilingual release notes file creation
3. 7-location consistency verification
4. Conventional Commits message drafting
5. `git add -A && git commit` execution
It **stops before** `git push` or `gh pr create`. Use the `pr-submitter` skill for those steps.
### Temporary File Convention
Any temporary files created during release prep (e.g., draft changelogs) must:
- Be written to the project's `.temp/` directory, **NOT** system `/tmp`
- Be cleaned up before commit using `rm -f .temp/file_name`
- Never be committed to git (add `.temp/` to `.gitignore`)
---
## Workflow
### Step 1 — Collect Release Info
Ask the user (or infer from current state) the following:
- **Plugin name** and **type** (actions / filters / pipes / tools)
- **New version number** (e.g., `0.8.0`)
- **Key changes** in English and Chinese (1-5 bullet points each)
If a `What's New` section already exists in README.md, extract it as the source of truth.
### Step 2 — Sync Version Across 7 Locations
Verify AND update the version string in all of the following. Mark each as ✅ or ❌:
| # | File | Location |
|---|------|----------|
| 1 | `plugins/{type}/{name}/{name}.py` | `version:` in docstring |
| 2 | `plugins/{type}/{name}/README.md` | `**Version:** x.x.x` metadata line |
| 3 | `plugins/{type}/{name}/README_CN.md` | `**Version:** x.x.x` metadata line |
| 4 | `docs/plugins/{type}/{name}.md` | `**Version:** x.x.x` metadata line |
| 5 | `docs/plugins/{type}/{name}.zh.md` | `**Version:** x.x.x` metadata line |
| 6 | `docs/plugins/{type}/index.md` | version badge for this plugin |
| 7 | `docs/plugins/{type}/index.zh.md` | version badge for this plugin |
Additionally update the root-level **updated date badge** in:
- `README.md``![updated](https://img.shields.io/badge/YYYY--MM--DD-gray?style=flat)`
- `README_CN.md` — same badge format
Use today's date (`YYYY-MM-DD`) for the badge.
### Step 3 — Update What's New (All 4 Doc Files)
The `What's New` / `最新更新` section must contain **only the most recent release's changes**. Previous entries should be removed from this section (they live in CHANGELOG or release notes files).
Update these 4 files' `What's New` / `最新更新` block consistently:
- `plugins/{type}/{name}/README.md`
- `plugins/{type}/{name}/README_CN.md`
- `docs/plugins/{type}/{name}.md`
- `docs/plugins/{type}/{name}.zh.md`
### Step 4 — Create Bilingual Release Notes Files
Create two versioned release notes files:
**Path**: `plugins/{type}/{name}/v{version}.md`
**Path**: `plugins/{type}/{name}/v{version}_CN.md`
#### Required Sections
Each file must include:
1. **Title**: `# v{version} Release Notes` (EN) / `# v{version} 版本发布说明` (CN)
2. **Overview**: One paragraph summarizing this release
3. **New Features** / **新功能**: Bulleted list of features
4. **Bug Fixes** / **问题修复**: Bulleted list of fixes
5. **Migration Notes** / **迁移说明**: Breaking changes or Valve key renames (omit section if none)
6. **Companion Plugins** / **配套插件** (optional): If a companion plugin was updated
If a release notes file already exists for this version, update it rather than creating a new one.
#### Full Coverage Rule (Mandatory)
Release notes must cover **all updates in the current release scope** and not only headline features.
Minimum required coverage in both EN/CN files:
- New features and capability enhancements
- Bug fixes and reliability fixes
- Documentation/README/doc-mirror updates that affect user understanding or usage
- Terminology/i18n/wording fixes that change visible behavior or messaging
Before commit, cross-check release notes against `git diff` and ensure no meaningful update is omitted.
### Step 5 — Verify Consistency (Pre-Commit Check)
Run the consistency check script:
```bash
python3 scripts/check_version_consistency.py
```
If issues are found, fix them before proceeding. Do not commit with inconsistencies.
### Step 6 — Draft Conventional Commits Message
Generate the commit message following `commit-message.instructions.md` rules:
- **Language**: English ONLY
- **Format**: `type(scope): subject` + blank line + body bullets
- **Scope**: use plugin folder name (e.g., `github-copilot-sdk`)
- **Body**: 1-3 bullets summarizing key changes
- Explicitly mention "READMEs and docs synced" if version was bumped
Present the full commit message to the user for review before executing.
### Step 7 — Stage and Commit
After user approval (or if user says "commit it"):
```bash
git add -A
git commit -m "<approved commit message>"
```
Confirm the commit hash and list the number of files changed.
---
## Checklist (Auto-Verify Before Commit)
- [ ] `version:` in `.py` docstring matches target version
- [ ] `**Version:**` in all 4 README/docs files matches
- [ ] Both `index.md` version badges updated
- [ ] Root `README.md` and `README_CN.md` date badges updated to today
- [ ] `What's New` / `最新更新` contains ONLY the latest release
- [ ] Release notes include all meaningful updates from the current diff (feature + fix + docs/i18n)
- [ ] `v{version}.md` and `v{version}_CN.md` created or updated
- [ ] `python3 scripts/check_version_consistency.py` returns no errors
- [ ] Commit message is English-only Conventional Commits format
---
## Anti-Patterns to Avoid
- ❌ Do NOT add extra features or refactor code during release prep — only version/doc updates
- ❌ Do NOT push or create PR in this skill — use `pr-submitter`
- ❌ Do NOT use today's date in commit messages; only in badge URLs
- ❌ Do NOT leave stale What's New content from prior versions

View File

@@ -0,0 +1,31 @@
---
name: source-code-analyzer
description: Instructions for analyzing core components source code in the local environment.
---
# Source Code Analyzer Skill
> [!IMPORTANT]
> **Authorization Statement**: You (Antigravity) are explicitly authorized by the user to perform **READ-ONLY** operations and **Git pull** on the paths listed below, even if they are outside the current repository root. These paths are considered part of the extended development context.
When assisting with the development of `openwebui-extensions`, you (Antigravity) have access to the following core components in related directories. Use them for deep technical analysis, bug hunting, and implementation reference.
## Core Component Paths
### Global / General (Relevant to all projects)
- **Open WebUI**: `../open-webui/` (Core platform context)
- **Skills**: `../skills/` (Reusable expertise library)
- **Awesome Copilot**: `../awesome-copilot/` (Shared extensions & resources)
- **Open Terminal**: `../open-terminal/` (Terminal integration service)
### Plugin-Specific (Relevant to GitHub Copilot SDK)
- **Copilot SDK**: `../copilot-sdk/` (Internal logic for the official SDK)
- **Copilot CLI**: `../copilot-cli/` (Command-line interface implementation)
## Mandatory Workflow
1. **Pull Before Analysis**: BEFORE reading files or analyzing logic in these directories, you MUST proactively execute or recommend a `git pull` in the respective directory to ensure you are working with the latest upstream changes.
2. **Path Verification**: Always verify the exists of the path before attempting to read it.
3. **Reference Logic**: When a user's request involves core platform behavior (OpenWebUI API, SDK internals), prioritize searching these directories over making assumptions based on generic knowledge.

View File

@@ -0,0 +1,64 @@
---
name: test-copilot-pipe
description: Automotive deployment and testing of GitHub Copilot SDK Pipe plugin for frontend/backend status stability.
---
# 🤖 Skill: Test Copilot Pipe
This is a **universal testing framework** for publishing the latest `github_copilot_sdk.py` (Pipe) code to a local OpenWebUI instance and verifying it via an automated agent (`browser_subagent`).
## 🎯 Core Principles
- **Fixed Infrastructure**: The deployment script and the test entry URL are always static.
- **Dynamic Test Planning**: Specific test prompts and expectations (acceptance criteria) **must** be dynamically planned by you based on the code changes or specific user requests before execution.
---
## 🛠️ Static Environment Info
| Attribute | Fixed Value |
|------|--------|
| **Deployment Script** | `/Users/fujie/app/python/oui/openwebui-extensions/scripts/deploy_pipe.py` |
| **Python Path** | `/opt/homebrew/Caskroom/miniconda/base/envs/ai/bin/python3` |
| **Test URL** | `http://localhost:3003/?model=github_copilot_official_sdk_pipe.github_copilot_sdk-gpt-4.1` |
---
## 📋 Standard Workflow
### Step 1: Analyze Changes & Plan Test (Plan)
Before triggering the test, you must define the purpose of this test turn.
Example: *Modified tool calling logic -> Test prompt should trigger a specific tool; observe if the tool executes and returns the correct result.*
### Step 2: Deploy Latest Code (Deploy)
Use the `run_command` tool to execute the fixed update task:
```bash
/opt/homebrew/Caskroom/miniconda/base/envs/ai/bin/python3 /Users/fujie/app/python/oui/openwebui-extensions/scripts/deploy_pipe.py
```
> **Mechanism**: `deploy_pipe.py` automatically loads the API Key from `scripts/.env` in the same directory.
> **Verification**: Look for `✅ Successfully updated... version X.X.X` or `✅ Successfully created...`. If a 401 error occurs, remind the user to generate a new API Key in OpenWebUI and update `.env`.
### Step 3: Verify via Browser Subagent (Verify)
Use the `browser_subagent` tool. **You must fill in the `[Dynamic Content]` slots based on Step 1**:
```text
Task:
1. Access The Fixed URL: http://localhost:3003/?model=github_copilot_official_sdk_pipe.github_copilot_sdk-gpt-4.1
2. RELIABILITY WAIT: Wait until the page fully loads. Wait until the chat input text area (`#chat-input`) is present in the DOM.
3. ACTION - FAST INPUT: Use the `execute_browser_javascript` tool to instantly inject the query and submit it. Use exactly this script format to ensure stability:
`const input = document.getElementById('chat-input'); input.value = "[YOUR_DYNAMIC_TEST_PROMPT]"; input.dispatchEvent(new Event('input', { bubbles: true })); const e = new KeyboardEvent('keydown', { key: 'Enter', code: 'Enter', keyCode: 13, which: 13, bubbles: true }); input.dispatchEvent(e);`
4. WAITING: Wait patiently for the streaming response to stop completely. You should wait for the Stop button to disappear, or wait for the system to settle (approximately 10-15 seconds depending on the query).
5. CHECK THE OUTCOME: [List the phenomena you expect to see, e.g., status bar shows specific text, tool card appears, result contains specific keywords, etc.]
6. CAPTURE: Take a screenshot of the settled state to prove the outcome.
7. REPORT: Report the EXACT outcome matching the criteria from step 5.
```
### Step 4: Evaluate & Iterate (Evaluate)
- **PASS**: Screenshot and phenomena match expectations. Report success to the user.
- **FAIL**: Analyze the issue based on screenshots/logs (e.g., race condition reappeared, API error). Modify the code and **re-run the entire skill workflow**.

View File

@@ -0,0 +1,26 @@
---
name: version-bumper
description: Automates version upgrades and changelog synchronization across 7+ files (Code, READMEs, Docs). Use when a plugin is ready for release to ensure version consistency.
---
# Version Bumper
## Overview
This skill ensures that every version upgrade is synchronized across the entire repository, following the strict "Documentation Sync" rule in GEMINI.md.
## Workflow
1. **Prepare Info**: Gather the new version number and brief changelogs in both English and Chinese.
2. **Auto-Patch**: The skill will help you identify and update:
- `plugins/.../name.py` (docstring version)
- `plugins/.../README.md` (metadata & What's New)
- `plugins/.../README_CN.md` (metadata & 最新更新)
- `docs/plugins/...md` (mirrors)
- `docs/plugins/index.md` (version badge)
- `README.md` (updated date badge)
3. **Verify**: Check the diffs to ensure no formatting was broken.
## Tool Integration
Execute the bump script (draft):
```bash
python3 scripts/bump.py <version> "<message_en>" "<message_zh>"
```

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
import sys
import os
import re
from datetime import datetime
def patch_file(file_path, old_pattern, new_content, is_regex=False):
if not os.path.exists(file_path):
print(f"Warning: File not found: {file_path}")
return False
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
if is_regex:
new_content_result = re.sub(old_pattern, new_content, content, flags=re.MULTILINE)
else:
new_content_result = content.replace(old_pattern, new_content)
if new_content_result != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content_result)
print(f"✅ Patched: {file_path}")
return True
else:
print(f" No change needed: {file_path}")
return False
def bump_version(plugin_type, plugin_name, new_version, msg_en, msg_zh):
print(f"🚀 Bumping {plugin_name} ({plugin_type}) to {new_version}...")
today = datetime.now().strftime("%Y-%m-%d")
today_badge = today.replace("-", "--")
# 1. Patch Plugin Python File
py_file = f"plugins/{plugin_type}/{plugin_name}/{plugin_name}.py"
patch_file(py_file, r"version: \d+\.\d+\.\d+", f"version: {new_version}", is_regex=True)
# 2. Patch Plugin READMEs
readme_en = f"plugins/{plugin_type}/{plugin_name}/README.md"
readme_zh = f"plugins/{plugin_type}/{plugin_name}/README_CN.md"
# Update version in metadata
patch_file(readme_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(readme_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# Update What's New (Assuming standard headers)
patch_file(readme_en, r"## 🔥 What's New in v.*?\n", f"## 🔥 What's New in v{new_version}\n\n* {msg_en}\n", is_regex=True)
patch_file(readme_zh, r"## 🔥 最新更新 v.*?\n", f"## 🔥 最新更新 v{new_version}\n\n* {msg_zh}\n", is_regex=True)
# 3. Patch Docs Mirrors
doc_en = f"docs/plugins/{plugin_type}/{plugin_name}.md"
doc_zh = f"docs/plugins/{plugin_type}/{plugin_name}.zh.md"
patch_file(doc_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(doc_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# 4. Patch Root READMEs (Updated Date Badge)
patch_file("README.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
patch_file("README_CN.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
print("\n✨ All synchronization tasks completed.")
return True
if __name__ == "__main__":
if len(sys.argv) < 6:
print("Usage: bump.py <type> <name> <version> <msg_en> <msg_zh>")
print("Example: bump.py filters markdown_normalizer 1.2.8 'Fix bug' '修复错误'")
sys.exit(1)
bump_version(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])

View File

@@ -4,34 +4,39 @@ description: OpenWebUI Plugin Development & Release Workflow
# OpenWebUI Plugin Development Workflow
This workflow outlines the standard process for developing, documenting, and releasing plugins for OpenWebUI, ensuring compliance with project standards and CI/CD requirements.
This workflow outlines the standard process for developing, documenting, and releasing plugins for OpenWebUI. **Crucially, the default goal of this workflow is "Preparation" (updating all relevant files) rather than automatic "Submission" (git commit/push), unless a release is explicitly requested.**
## 1. Development Standards
Reference: `.github/copilot-instructions.md`
### Bilingual Requirement
Every plugin **MUST** have bilingual versions for both code and documentation:
- **Code**:
- English: `plugins/{type}/{name}/{name}.py`
- Chinese: `plugins/{type}/{name}/{name_cn}.py` (or `中文名.py`)
Every plugin **MUST** have a single internationalized code file and bilingual documentation:
- **Code (i18n)**:
- `plugins/{type}/{name}/{name}.py`
- The single `.py` file must implement internal i18n (e.g., using `navigator.language` or backend headers) to support multiple languages natively, rather than splitting into separate files.
- **README**:
- English: `plugins/{type}/{name}/README.md`
- Chinese: `plugins/{type}/{name}/README_CN.md`
### Code Structure
- **Docstring**: Must include `title`, `author`, `version`, `description`, etc.
- **Valves**: Use `pydantic` for configuration.
- **Database**: Re-use `open_webui.internal.db` shared connection.
- **User Context**: Use `_get_user_context` helper method.
- **Chat Context**: Use `_get_chat_context` helper method for `chat_id` and `message_id`.
- **Debugging**: Use `_emit_debug_log` for frontend console logging (requires `SHOW_DEBUG_LOG` valve).
- **Chat API**: For message updates, follow the "OpenWebUI Chat API 更新规范" in `.github/copilot-instructions.md`.
- Use Event API for immediate UI updates
- Use Chat Persistence API for database storage
- Always update both `messages[]` and `history.messages`
### Commit Messages
- **Language**: **English ONLY**. Do not use Chinese in commit messages.
### Commit Messages & Release Notes
- **Language**: **English ONLY**. Do not use Chinese in commit messages or release notes.
- **Format**: Conventional Commits (e.g., `feat:`, `fix:`, `docs:`).
## 2. Documentation Updates
@@ -39,10 +44,16 @@ Every plugin **MUST** have bilingual versions for both code and documentation:
When adding or updating a plugin, you **MUST** update the following documentation files to maintain consistency:
### Plugin Directory
- `README.md`: Update version, description, and usage. **Explicitly describe new features in a prominent position at the beginning.**
- `README_CN.md`: Update version, description, and usage. **Explicitly describe new features in a prominent position at the beginning.**
- `README.md`: Update version, description, and usage.
- **Key Capabilities**: **MUST** include ALL core functionalities and features. This is a cumulative section. Every release **MUST** verify that basic core descriptions are NOT lost or overwritten by new feature lists.
- **What's New**: Explicitly describe only the latest changes/updates in a prominent position at the beginning. This section is dynamic and changes with versions.
- `README_CN.md`: Update version, description, and usage.
- **核心功能 (Key Capabilities)**: **必须**包含所有核心功能和特性。这是一个累积性的部分,每次版本更新**必须**确认基础核心功能的描述没有丢失或被新功能列表覆盖。
- **最新更新 (What's New)**: 在开头显眼位置明确描述最新的更改/更新。此部分是动态的,随版本变化。
### Global Documentation (`docs/`)
- **Index Pages**:
- `docs/plugins/{type}/index.md`: Add/Update list item with **correct version**.
- `docs/plugins/{type}/index.zh.md`: Add/Update list item with **correct version**.
@@ -51,6 +62,7 @@ When adding or updating a plugin, you **MUST** update the following documentatio
- `docs/plugins/{type}/{name}.zh.md`: Ensure content matches README_CN.
### Root README
- `README.md`: Add to "Featured Plugins" if applicable.
- `README_CN.md`: Add to "Featured Plugins" if applicable.
@@ -59,36 +71,59 @@ When adding or updating a plugin, you **MUST** update the following documentatio
Reference: `.github/workflows/release.yml`
### Version Bumping
- **Rule**: Version bump is required **ONLY when the user explicitly requests a release**. Regular code changes do NOT require version bumps.
- **Format**: Semantic Versioning (e.g., `1.0.0` -> `1.0.1`).
- **When to Bump**: Only update the version when:
- User says "发布" / "release" / "bump version"
- User explicitly asks to prepare for release
- **Agent Initiative**: After completing significant changes (new features, bug fixes, or multiple code modifications), the agent **SHOULD proactively ask** the user if they want to release a new version. If confirmed, update all version-related files.
- **Agent Initiative**: After completing significant changes (new features, bug fixes, or multiple code modifications), the agent **SHOULD proactively ask** the user if they want to **prepare a new version** for release.
- **Release Information Compliance**: When a release is requested, the agent must generate a standard release summary (English commit title + bilingual bullet points) as defined in Section 3 & 5.
- **Default Action (Prepare Only)**: When performing a version bump or update, the agent should update all files locally but **STOP** before committing. Present the changes and the **proposed Release/Commit Message** to the user and wait for explicit confirmation to commit/push.
- **Consistency**: When bumping, update version in **ALL** locations:
1. English Code (`.py`)
2. Chinese Code (`.py`)
3. English README (`README.md`)
4. Chinese README (`README_CN.md`)
5. Docs Index (`docs/.../index.md`)
6. Docs Index CN (`docs/.../index.zh.md`)
7. Docs Detail (`docs/.../{name}.md`)
8. Docs Detail CN (`docs/.../{name}.zh.md`)
1. Code (`.py`)
2. English README (`README.md`)
3. Chinese README (`README_CN.md`)
4. Docs Index (`docs/.../index.md`)
5. Docs Index CN (`docs/.../index.zh.md`)
6. Docs Detail (`docs/.../{name}.md`)
7. Docs Detail CN (`docs/.../{name}.zh.md`)
### Automated Release Process
1. **Trigger**: Push to `main` branch with changes in `plugins/**/*.py`.
2. **Detection**: `scripts/extract_plugin_versions.py` detects changed plugins and compares versions.
3. **Release**:
1. **Trigger**: Push to `main` branch with changes in `plugins/**/*.py`.
2. **Detection**: `scripts/extract_plugin_versions.py` detects changed plugins and compares versions.
3. **Release**:
- Generates release notes based on changes.
- Creates a GitHub Release tag (e.g., `v2024.01.01-1`).
- Uploads individual `.py` files of **changed plugins only** as assets.
4. **Market Publishing**:
4. **Market Publishing**:
- Workflow: `.github/workflows/publish_plugin.yml`
- Trigger: Release published.
- Action: Automatically updates the plugin code and metadata on OpenWebUI.com using `scripts/publish_plugin.py`.
- **Auto-Sync**: If a local plugin has no ID but matches an existing published plugin by **Title**, the script will automatically fetch the ID, update the local file, and proceed with the update.
- Requirement: `OPENWEBUI_API_KEY` secret must be set.
- **README Link**: When announcing a release, always include the GitHub README URL for the plugin:
- Format: `https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/{type}/{name}/README.md`
- Example: `https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/filters/folder-memory/README.md`
### Release Content Standard
When the user confirms a release, the agent **MUST** follow these content standards:
1. **Commit Message**:
- **Language**: English ONLY.
- **Format**: `type(scope): description` (e.g., `feat(pipes): add streaming support for Copilot SDK`).
- **Body**: List 1-3 key changes in bullet points.
2. **Release Summary (for user review)**:
- Before committing, present a "Release Draft" containing:
- **Title**: e.g., `Release v0.1.1: [Plugin Name] - [Brief Summary]`
- **Changelog**: English-only list of commits since the last release, including hashes (e.g., `896de02 docs(config): reorder antigravity model alias example`).
- **Verification Status**: Confirm all 7+ files have been updated and synced.
3. **Internal Documentation**: Ensure "What's New" sections in READMEs and `docs/` match exactly the changes being released.
### Pull Request Check
- Workflow: `.github/workflows/plugin-version-check.yml`
- Checks if plugin files are modified.
- **Fails** if version number is not updated.
@@ -98,15 +133,27 @@ Reference: `.github/workflows/release.yml`
Before committing:
- [ ] Code is bilingual and functional?
- [ ] Code is internal i18n supported (`.py`) and fully functional?
- [ ] Docstrings have updated version?
- [ ] READMEs are updated and bilingual?
- [ ] **Key Capabilities** in READMEs still cover all legacy core features + new features?
- [ ] `docs/` index and detail pages are updated?
- [ ] Root `README.md` is updated?
- [ ] All version numbers match exactly?
- [ ] Any non-obvious findings saved to `.agent/learnings/{topic}.md`?
## 5. Git Operations (Agent Rules)
Strictly follow the rules defined in `.github/copilot-instructions.md`**Git Operations (Agent Rules)** section.
1. **Prepare-on-Demand**: Focus on file modifications and local verification first.
2. **No Auto-Commit**: Never `git commit`, `git push`, or `create_pull_request` automatically after file updates unless the user explicitly says "commit this" or "release now".
3. **Draft Mode**: If available, use PRs as drafts first.
4. **Reference**: Strictly follow the rules defined in `.github/copilot-instructions.md`**Git Operations (Agent Rules)** section.
## 6. Knowledge Capture (Mandatory)
Whenever you discover a non-obvious behaviour, internal API contract, or workaround
during plugin development, **document it in `.agent/learnings/{topic}.md`** before
ending the session.
- Browse `.agent/learnings/` **first** at the start of a session to reuse existing knowledge.
- Format: see `.agent/learnings/README.md`.

65
.all-contributorsrc Normal file
View File

@@ -0,0 +1,65 @@
{
"files": [
"README.md"
],
"imageSize": 100,
"commit": false,
"commitType": "docs",
"commitConvention": "angular",
"contributors": [
{
"login": "rbb-dev",
"name": "rbb-dev",
"avatar_url": "https://avatars.githubusercontent.com/u/37469229?v=4",
"profile": "https://github.com/rbb-dev",
"contributions": [
"ideas",
"code"
]
},
{
"login": "dhaern",
"name": "Raxxoor",
"avatar_url": "https://avatars.githubusercontent.com/u/7317522?v=4",
"profile": "https://trade.xyz/?ref=BZ1RJRXWO",
"contributions": [
"bug",
"ideas"
]
},
{
"login": "i-iooi-i",
"name": "ZOLO",
"avatar_url": "https://avatars.githubusercontent.com/u/1827701?v=4",
"profile": "https://github.com/i-iooi-i",
"contributions": [
"bug",
"ideas"
]
},
{
"login": "nahoj",
"name": "Johan Grande",
"avatar_url": "https://avatars.githubusercontent.com/u/469017?v=4",
"profile": "https://perso.crans.org/grande/",
"contributions": [
"ideas"
]
},
{
"login": "abaroni",
"name": "Alessandro Baroni",
"avatar_url": "https://avatars.githubusercontent.com/u/21365486?v=4",
"profile": "https://github.com/abaroni",
"contributions": [
"ideas"
]
}
],
"contributorsPerLine": 7,
"skipCi": true,
"repoType": "github",
"repoHost": "https://github.com",
"projectName": "openwebui-extensions",
"projectOwner": "Fu-Jie"
}

71
.gemini/skills/README.md Normal file
View File

@@ -0,0 +1,71 @@
# Agent Skills Index
This folder contains reusable Agent Skills for GitHub Copilot / VS Code custom agent workflows.
## Available Skills
- **community-announcer**
- Purpose: Generate community announcement content and related assets.
- Entry: `community-announcer/SKILL.md`
- **doc-mirror-sync**
- Purpose: Sync mirrored documentation content and helper scripts.
- Entry: `doc-mirror-sync/SKILL.md`
- **gh-issue-replier**
- Purpose: Draft standardized issue replies with templates.
- Entry: `gh-issue-replier/SKILL.md`
- **gh-issue-scheduler**
- Purpose: Schedule and discover unanswered issues for follow-up.
- Entry: `gh-issue-scheduler/SKILL.md`
- **i18n-validator**
- Purpose: Validate translation key consistency across i18n dictionaries.
- Entry: `i18n-validator/SKILL.md`
- **plugin-scaffolder**
- Purpose: Scaffold OpenWebUI plugin boilerplate with repository standards.
- Entry: `plugin-scaffolder/SKILL.md`
- **version-bumper**
- Purpose: Assist with semantic version bumping workflows.
- Entry: `version-bumper/SKILL.md`
- **xlsx-single-file**
- Purpose: Single-file spreadsheet operations workflow without LibreOffice.
- Entry: `xlsx-single-file/SKILL.md`
---
## Release Pipeline Skills
These four skills form a complete release pipeline and are designed to be used in sequence:
```
release-prep → pr-submitter → pr-reviewer → release-finalizer
(prepare) (push & PR) (respond to review) (merge & close issue)
```
- **release-prep**
- Purpose: Full release preparation — version sync across 7+ files, bilingual release notes creation, consistency check, and commit.
- Entry: `release-prep/SKILL.md`
- **pr-submitter**
- Purpose: Shell-escape-safe PR submission — writes body to temp file, validates sections, pushes branch, creates PR via `gh pr create --body-file`.
- Entry: `pr-submitter/SKILL.md`
- **pr-reviewer**
- Purpose: Fetch PR review comments, categorize feedback, implement fixes, commit and push, reply to reviewers.
- Entry: `pr-reviewer/SKILL.md`
- **release-finalizer**
- Purpose: Merge release PR to main with proper commit message, auto-link and close related issues, post closing messages.
- Entry: `release-finalizer/SKILL.md`
## Notes
- Skill definitions follow the expected location pattern:
- `.github/skills/<skill-name>/SKILL.md`
- Each skill may include optional `assets/`, `references/`, and `scripts/` folders.
- This directory mirrors `.gemini/skills` for compatibility.

View File

@@ -0,0 +1,23 @@
---
name: community-announcer
description: Drafts engaging English and Chinese update announcements for the OpenWebUI Community and other social platforms. Use when a new version is released.
---
# Community Announcer
## Overview
Automates the drafting of high-impact update announcements.
## Workflow
1. **Source Intel**: Read the latest version's `What's New` section from `README.md`.
2. **Drafting**: Create two versions:
- **Community Post**: Professional, structured, technical.
- **Catchy Short**: For Discord/Twitter, use emojis and bullet points.
3. **Multi-language**: Generate BOTH English and Chinese versions automatically.
## Announcement Structure (Recommended)
- **Headline**: "Update vX.X.X - [Main Feature]"
- **Introduction**: Brief context.
- **Key Highlights**: Bulleted list of fixes/features.
- **Action**: "Download from [Market Link]"
- **Closing**: Thanks and Star request.

View File

@@ -0,0 +1,50 @@
---
name: doc-mirror-sync
description: Automatically synchronizes plugin READMEs to the official documentation directory (docs/). Use after editing a plugin's local documentation to keep the MkDocs site up to date.
---
# Doc Mirror Sync
## Overview
Automates the mirroring of `plugins/{type}/{name}/README.md` to `docs/plugins/{type}/{name}.md`.
## Docs-Only Mode (No Release Changes)
Use this mode when the request is "only sync docs".
- Only update documentation mirror files under `docs/plugins/**`.
- Do **not** bump plugin version.
- Do **not** modify plugin code (`plugins/**.py`) unless explicitly requested.
- Do **not** update root badges/dates for release.
- Do **not** run release preparation steps.
## Workflow
1. Identify changed READMEs.
2. Copy content to corresponding mirror paths.
3. Update version badges in `docs/plugins/{type}/index.md`.
## Commands
### Sync all mirrors (EN + ZH)
```bash
python .github/skills/doc-mirror-sync/scripts/sync.py
```
### Sync only one plugin (EN only)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
```
### Sync only one plugin (EN + ZH)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
cp plugins/<type>/<name>/README_CN.md docs/plugins/<type>/<name>.zh.md
```
## Notes
- If asked for English-only update, sync only `README.md` -> `.md` mirror.
- If both languages are requested, sync both `README.md` and `README_CN.md`.
- After syncing, verify git diff only contains docs file changes.

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3
import os
import shutil
import re
def sync_mirrors():
plugins_root = "plugins"
docs_root = "docs/plugins"
types = ["actions", "filters", "pipes", "pipelines", "tools"]
for t in types:
src_type_dir = os.path.join(plugins_root, t)
dest_type_dir = os.path.join(docs_root, t)
if not os.path.exists(src_type_dir): continue
os.makedirs(dest_type_dir, exist_ok=True)
for name in os.listdir(src_type_dir):
plugin_dir = os.path.join(src_type_dir, name)
if not os.path.isdir(plugin_dir): continue
# Sync README.md -> docs/plugins/{type}/{name}.md
src_readme = os.path.join(plugin_dir, "README.md")
if os.path.exists(src_readme):
dest_readme = os.path.join(dest_type_dir, f"{name}.md")
shutil.copy(src_readme, dest_readme)
print(f"✅ Mirrored: {t}/{name} (EN)")
# Sync README_CN.md -> docs/plugins/{type}/{name}.zh.md
src_readme_cn = os.path.join(plugin_dir, "README_CN.md")
if os.path.exists(src_readme_cn):
dest_readme_zh = os.path.join(dest_type_dir, f"{name}.zh.md")
shutil.copy(src_readme_cn, dest_readme_zh)
print(f"✅ Mirrored: {t}/{name} (ZH)")
if __name__ == "__main__":
sync_mirrors()

View File

@@ -0,0 +1,51 @@
---
name: gh-issue-replier
description: Professional English replier for GitHub issues. Use when a task is completed, a bug is fixed, or more info is needed from the user. Automates replying using the 'gh' CLI tool.
---
# Gh Issue Replier
## Overview
The `gh-issue-replier` skill enables Gemini CLI to interact with GitHub issues professionally. It enforces English for all communications and leverages the `gh` CLI to post comments.
## Workflow
1. **Identify the Issue**: Find the issue number (e.g., #49).
2. **Check Star Status**: Run the bundled script to check if the author has starred the repo.
* Command: `bash scripts/check_star.sh <issue-number>`
* Interpretation:
* Exit code **0**: User has starred. Use "Already Starred" templates.
* Exit code **1**: User has NOT starred. Include "Star Request" in the reply.
3. **Select a Template**: Load [templates.md](references/templates.md) to choose a suitable English response pattern.
4. **Draft the Reply**: Compose a concise message based on the star status.
5. **Post the Comment**: Use the `gh` tool to submit the reply.
## Tool Integration
### Check Star Status
```bash
bash scripts/check_star.sh <issue-number>
```
### Post Comment
```bash
gh issue comment <issue-number> --body "<message-body>"
```
Example (if user has NOT starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. If you find this helpful, a star on the repo would be much appreciated! ⭐"
```
Example (if user HAS starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. Thanks for your support!"
```
## Guidelines
- **Language**: ALWAYS use English for the comment body, even if the system prompt or user conversation is in another language.
- **Tone**: Professional, helpful, and appreciative.
- **Precision**: When announcing a fix, mention the specific version or the logic change (e.g., "Updated regex pattern").
- **Closing**: If the issue is resolved and you have permission, you can also use `gh issue close <number>`.

View File

@@ -0,0 +1,17 @@
# Reference Documentation for Gh Issue Replier
This is a placeholder for detailed reference documentation.
Replace with actual reference content or delete if not needed.
## Structure Suggestions
### API Reference Example
- Overview
- Authentication
- Endpoints with examples
- Error codes
### Workflow Guide Example
- Prerequisites
- Step-by-step instructions
- Best practices

View File

@@ -0,0 +1,45 @@
# Issue Reply Templates
Use these templates to craft professional English replies. Adjust placeholders like `@username`, `v1.2.x`, and `[commit hash]` as needed.
## 1. Acknowledging a New Issue
Use when you first see an issue and want to let the user know you are working on it.
- "Thank you for reporting this! I'm looking into it right now."
- "Thanks for bringing this to my attention. I'll try to reproduce this behavior and get back to you shortly."
## 2. Requesting More Information
Use when you need logs or specific details to fix the bug.
- "Could you please provide the **'Original'** vs **'Normalized'** content from your browser console logs (F12)? It would help a lot in debugging."
- "It would be very helpful if you could share the specific Markdown text that triggered this issue."
## 3. Announcing a Fix
Use when you have pushed the fix to the repository.
- "This has been fixed in version **v1.2.x**. You can update the plugin to resolve it."
- "I've just pushed a fix for this in [commit hash]. Please let me know if it works for you after updating."
- "The issue was caused by a greedy regex pattern. I've updated it to use a tempered greedy token to prevent incorrect merging."
## 4. Guiding to Official Market
Always provide the official market link to ensure the user gets the latest verified version.
- "The fix is now live! You can download the latest version from the official OpenWebUI Community page here: [Plugin Market Link]. Simply update the function in your OpenWebUI instance to apply the changes."
- "I recommend getting the updated version from the official store: [Link]. It includes the fix for the spacing issue we discussed."
## 5. Closing the Issue
Use when the issue is confirmed resolved.
- "Glad to hear it's working now! Closing this for now. Feel free to reopen it if the problem persists."
- "Since this is resolved, I'm closing this issue. Thanks again for your feedback!"
## 5. Pro-tip: Star Request
Gently handle star requests based on the user's current status.
### If User has NOT starred:
- "If you find this plugin helpful, a star on the repo would be much appreciated! ⭐"
- "We'd love your support! If this fixed your issue, please consider starring the repository. ⭐"
### If User HAS already starred:
- "Thanks again for starring the project and for your continuous support!"
- "I appreciate your support and for being a stargazer of this project!"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Robust Star Checker v2
# Usage: ./check_star.sh <issue_number>
ISSUE_NUM=$1
if [ -z "$ISSUE_NUM" ]; then exit 2; fi
# 1. Get Repo and Author info
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + \"/\" + .name")
USER_LOGIN=$(gh issue view "$ISSUE_NUM" --json author -q ".author.login")
# 2. Use GraphQL for high precision (Detects stars even when REST 404s)
IS_STARRED=$(gh api graphql -f query='
query($owner:String!, $repo:String!, $user:String!) {
repository(owner:$owner, name:$repo) {
stargazers(query:$user, first:1) {
nodes {
login
}
}
}
}' -f owner="${REPO_FULL%/*}" -f repo="${REPO_FULL#*/}" -f user="$USER_LOGIN" -q ".data.repository.stargazers.nodes[0].login")
if [ "$IS_STARRED" == "$USER_LOGIN" ]; then
echo "Confirmed: @$USER_LOGIN HAS starred $REPO_FULL. ⭐"
exit 0
else
echo "Confirmed: @$USER_LOGIN has NOT starred $REPO_FULL."
exit 1
fi

View File

@@ -0,0 +1,42 @@
---
name: gh-issue-scheduler
description: Finds all open GitHub issues that haven't been replied to by the owner, summarizes them, and generates a solution plan. Use when the user wants to audit pending tasks or plan maintenance work.
---
# Gh Issue Scheduler
## Overview
The `gh-issue-scheduler` skill helps maintainers track community feedback by identifying unaddressed issues and drafting actionable technical plans to resolve them.
## Workflow
1. **Identify Unanswered Issues**: Run the bundled script to fetch issues without owner replies.
* Command: `bash scripts/find_unanswered.sh`
2. **Analyze and Summarize**: For each identified issue, summarize the core problem and the user's intent.
3. **Generate Solution Plans**: Draft a technical "Action Plan" for each issue, including:
* **Root Cause Analysis** (if possible)
* **Proposed Fix/Implementation**
* **Verification Strategy**
4. **Present to User**: Display a structured report of all pending issues and their respective plans.
## Tool Integration
### Find Unanswered Issues
```bash
bash scripts/find_unanswered.sh
```
## Report Format
When presenting the summary, use the following Markdown structure:
### 📋 Unanswered Issues Audit
#### Issue #[Number]: [Title]
- **Author**: @username
- **Summary**: Concise description of the problem.
- **Action Plan**:
1. Step 1 (e.g., Investigate file X)
2. Step 2 (e.g., Apply fix Y)
3. Verification (e.g., Run test Z)

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Fetch all open issues and filter for those without responses from the owner/collaborators.
# Uses 'gh' CLI.
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + "/" + .name")
OWNER=${REPO_FULL%/*}
# 1. Get all open issues
OPEN_ISSUES=$(gh issue list --state open --json number,title,author,createdAt --limit 100)
echo "Analysis for repository: $REPO_FULL"
echo "------------------------------------"
# Process each issue
echo "$OPEN_ISSUES" | jq -c '.[]' | while read -r issue; do
NUMBER=$(echo "$issue" | jq -r '.number')
TITLE=$(echo "$issue" | jq -r '.title')
AUTHOR=$(echo "$issue" | jq -r '.author.login')
# Check comments for owner responses
# We look for comments where the author is the repo owner
COMMENTS=$(gh issue view "$NUMBER" --json comments -q ".comments[].author.login" 2>/dev/null)
HAS_OWNER_REPLY=false
for COMMENT_AUTHOR in $COMMENTS; do
if [ "$COMMENT_AUTHOR" == "$OWNER" ]; then
HAS_OWNER_REPLY=true
break
fi
done
if [ "$HAS_OWNER_REPLY" == "false" ]; then
echo "ISSUE_START"
echo "ID: $NUMBER"
echo "Title: $TITLE"
echo "Author: $AUTHOR"
echo "Description:"
gh issue view "$NUMBER" --json body -q ".body"
echo "ISSUE_END"
fi
done

View File

@@ -0,0 +1,14 @@
---
name: i18n-validator
description: Validates multi-language consistency in the TRANSLATIONS dictionary of a plugin. Use to check if any language keys are missing or if translations need updating.
---
# I18n Validator
## Overview
Ensures all 12 supported languages (en-US, zh-CN, etc.) have aligned translation keys.
## Features
- Detects missing keys in non-English dictionaries.
- Suggests translations using the core AI engine.
- Validates the `fallback_map` for variant redirects.

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import sys
import ast
import os
def check_i18n(file_path):
if not os.path.exists(file_path):
print(f"Error: File not found {file_path}")
return
with open(file_path, 'r', encoding='utf-8') as f:
tree = ast.parse(f.read())
translations = {}
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id == "TRANSLATIONS":
translations = ast.literal_eval(node.value)
break
if not translations:
print("⚠️ No TRANSLATIONS dictionary found.")
return
# Base keys from English
base_lang = "en-US"
if base_lang not in translations:
print(f"❌ Error: {base_lang} missing in TRANSLATIONS.")
return
base_keys = set(translations[base_lang].keys())
print(f"🔍 Analyzing {file_path}...")
print(f"Standard keys ({len(base_keys)}): {', '.join(sorted(base_keys))}
")
for lang, keys in translations.items():
if lang == base_lang: continue
lang_keys = set(keys.keys())
missing = base_keys - lang_keys
extra = lang_keys - base_keys
if missing:
print(f"{lang}: Missing {len(missing)} keys: {', '.join(missing)}")
if extra:
print(f"⚠️ {lang}: Has {len(extra)} extra keys: {', '.join(extra)}")
if not missing and not extra:
print(f"{lang}: Aligned.")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: validate_i18n.py <path_to_plugin.py>")
sys.exit(1)
check_i18n(sys.argv[1])

View File

@@ -0,0 +1,59 @@
---
name: openwebui-community-publisher
description: Automatically publishes plugin update posts to openwebui.com.
---
# OpenWebUI Community Publisher
## Overview
This skill automates the process of creating **new** plugin release notes and announcements directly on the OpenWebUI Community (openwebui.com).
**Note**: This skill is exclusively for **new post creation**. Do NOT use this for updating existing posts, as updates are managed separately via dedicated scripts.
## Prerequisites
- User must be logged into [openwebui.com](https://openwebui.com) in the browser session.
- The content must be prepared in Markdown format (typically following the structure of the plugin's changelog or a dedicated release `.md` file).
## Execution Workflow
### 1. Verification
- Use `browser_subagent` to navigate to `https://openwebui.com`.
- Verify the logged-in user status (look for profile icons or "@Fu-Jie").
### 2. Post Creation
- Navigate to `https://openwebui.com/post`.
- **Post Type Selection**:
- Choose the appropriate tab based on content:
- **Text**: General announcements and documentation.
- **Tool**: Standalone tool plugins.
- **Function**: Pipes, Filters, or Actions.
- **Prompt**: Chat prompt templates.
- **Model**: GGUF/Ollama model files.
- Unless otherwise specified, default to **Text** for general release introductions.
- **Community Selection**:
- For general OpenWebUI related posts, select **o/openwebui**.
- For specialized topics, select the relevant community (e.g., **o/ollama** for models).
- **Metadata Mapping**:
- **Title**: Use the main header from the source file.
- **Content/Description**: Paste the Markdown body.
- **Source Code (for Function/Pipe)**: If publishing a `Function`, retrieve the corresponding `.py` file content and paste it into the code area.
- **Tags**: Leave empty by default unless relevant keywords are explicitly provided.
- **Media**: Optional, only attach if provided.
- **Settings**: Ensure "Adult content" is unchecked.
### 3. Submission & Validation
- Click the "Create" (创建) button.
- Wait for redirection to the final post URL.
- **CRITICAL**: Use `capture_browser_screenshot` to verify the rendering.
- Return the final URL to the user.
## Design Standards
- **Rich Aesthetics**: Use emojis in titles.
- **Structured Data**: Ensure tables and code blocks in the Markdown are preserved.
- **Internal Linking**: Link back to the OpenWebUI market or GitHub repository where applicable.

View File

@@ -0,0 +1,19 @@
---
name: plugin-scaffolder
description: Generates a standardized single-file i18n Python plugin template based on project standards. Use when starting a new plugin development to skip boilerplate writing.
---
# Plugin Scaffolder
## Overview
Generates compliant OpenWebUI plugin templates with built-in i18n, common utility methods, and required docstring fields.
## Usage
1. Provide the **Plugin Name** and **Type** (action/filter/pipe).
2. The skill will generate the `.py` file and the bilingual `README` files.
## Template Standard
- `Valves(BaseModel)` with `UPPER_SNAKE_CASE`
- `_get_user_context` with JS fallback and timeout
- `_emit_status` and `_emit_debug_log` methods
- Standardized docstring metadata

View File

@@ -0,0 +1,34 @@
# {{TITLE}}
**Author:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **Version:** 0.1.0 | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **License:** MIT
{{DESCRIPTION}}
## 🔥 What's New in v0.1.0
* Initial release of {{TITLE}}.
## 🌐 Multilingual Support
Supports automatic interface and status switching for the following languages:
`English`, `简体中文`, `繁體中文 (香港)`, `繁體中文 (台灣)`, `한국어`, `日本語`, `Français`, `Deutsch`, `Español`, `Italiano`, `Tiếng Việt`, `Bahasa Indonesia`.
## ✨ Core Features
* Feature 1
* Feature 2
## How to Use 🛠️
1. Install the plugin in Open WebUI.
2. Configure settings in Valves.
## Configuration (Valves) ⚙️
| Parameter | Default | Description |
| :--- | :--- | :--- |
| `priority` | `50` | Execution priority. |
## ⭐ Support
If this plugin has been useful, a star on [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) is a big motivation for me. Thank you for the support.

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import sys
import os
def scaffold(p_type, p_name, title, desc):
target_dir = f"plugins/{p_type}/{p_name}"
os.makedirs(target_dir, exist_ok=True)
class_name = (
"Action"
if p_type == "actions"
else (
"Filter"
if p_type == "filters"
else "Tools" if p_type == "tools" else "Pipe"
)
)
method_name = (
"action"
if p_type == "actions"
else (
"outlet"
if p_type == "filters"
else "execute" if p_type == "tools" else "pipe"
)
)
replacements = {
"{{TITLE}}": title,
"{{DESCRIPTION}}": desc,
"{{CLASS_NAME}}": class_name,
"{{METHOD_NAME}}": method_name,
}
# Files to generate
templates = [
("assets/template.py.j2", f"{p_name}.py"),
("assets/README_template.md", "README.md"),
("assets/README_template.md", "README_CN.md"),
]
# Path relative to skill root
skill_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
for t_path, t_name in templates:
template_file = os.path.join(skill_root, t_path)
if not os.path.exists(template_file):
print(f"⚠️ Warning: Template not found {template_file}")
continue
with open(template_file, "r") as f:
content = f.read()
for k, v in replacements.items():
content = content.replace(k, v)
with open(os.path.join(target_dir, t_name), "w") as f:
f.write(content)
print(f"✅ Generated: {target_dir}/{t_name}")
if __name__ == "__main__":
if len(sys.argv) < 5:
print("Usage: scaffold.py <type> <name> <title> <desc>")
sys.exit(1)
scaffold(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

View File

@@ -0,0 +1,180 @@
---
name: pr-reviewer
description: Fetches PR review comments, analyzes requested changes, implements fixes, commits and pushes the resolution. Use after a reviewer has left comments on an open PR to close the feedback loop efficiently.
---
# PR Reviewer
## Overview
This skill automates the response cycle for code review. When a reviewer leaves comments on a Pull Request, this skill fetches all pending feedback, categorizes issues by severity, implements fixes, and submits a follow-up commit with appropriate review response comments.
## Prerequisites
- An open PR exists with pending review comments
- The local branch matches the PR's head branch
- `gh` CLI is authenticated
---
## Workflow
### Step 1 — Fetch Review State
Retrieve all review comments and overall review status:
```bash
# Get overall review decisions
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json reviews,reviewDecision,headRefName \
--jq '{decision: .reviewDecision, reviews: [.reviews[] | {author: .author.login, state: .state, body: .body}]}'
# Get inline code comments (specific line comments)
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments \
--jq '[.[] | {path: .path, line: .line, body: .body, author: .user.login, id: .id}]'
# Get general issue comments
PAGER=cat GH_PAGER=cat gh issue view <PR-NUMBER> --comments --json comments \
--jq '[.comments[] | {author: .author.login, body: .body}]'
```
Confirm the current local branch matches the PR head:
```bash
git branch --show-current
```
If mismatched, checkout the correct branch first.
### Step 2 — Categorize Review Feedback
Group feedback into categories:
| Category | Examples | Action |
|----------|---------|--------|
| **Code Bug** | Logic error, incorrect variable, broken condition | Fix code immediately |
| **Style / Formatting** | Indentation, naming convention, missing blank line | Fix code |
| **Documentation** | Missing i18n key, wrong version in README, typo | Fix docs |
| **Design Question** | Suggestion to restructure, alternative approach | Discuss with user before implementing |
| **Nitpick / Optional** | Minor style preferences reviewer marked as optional | Fix if quick; document if skipped |
| **Blocking** | Reviewer explicitly blocks merge | Must fix before proceeding |
Present the full categorized list to the user and confirm the resolution plan.
### Step 3 — Implement Fixes
For each accepted fix:
1. Read the affected file at the commented line for context:
```bash
sed -n '<line-5>,<line+10>p' <file-path>
```
2. Apply the fix using appropriate file edit tools
3. After editing, verify the specific area looks correct
**For code changes that might affect behavior:**
- Check if tests exist: `ls tests/test_*.py`
- If tests exist, run them: `python -m pytest tests/ -v`
**For documentation fixes:**
- If modifying README.md, check if `docs/` mirror needs the same fix
- Apply the same fix to both locations
### Step 4 — Run Consistency Checks
After all fixes are applied:
```bash
# Version consistency (if any version files were touched)
python3 scripts/check_version_consistency.py
# Quick syntax check for Python files
python3 -m py_compile plugins/{type}/{name}/{name}.py && echo "✅ Syntax OK"
```
### Step 5 — Stage and Commit
Create a new commit (do NOT amend if the branch has already been pushed, to avoid force-push):
```bash
git add -A
git status
```
Draft a Conventional Commits message for the fixup:
Format: `fix(scope): address review feedback`
Body should list what was fixed, referencing reviewer concerns:
```
fix(github-copilot-sdk): address review feedback from @reviewer
- Fix X per review comment on line Y of file Z
- Update README to clarify auth requirement
- Correct edge case in _parse_mcp_servers logic
```
```bash
git commit -m "<fixup commit message>"
```
### Step 6 — Push the Fix Commit
```bash
git push origin $(git branch --show-current)
```
**Force-push policy:**
- Use `git push` (non-force) by default
- Only use `git push --force-with-lease` if:
1. The user explicitly requests it, AND
2. The only change is an amended commit squash (cosmetic, no logic change)
3. Never use `--force` (without `--lease`)
### Step 7 — Respond to Reviewers
For each addressed review comment, post a reply:
```bash
# Reply to inline comment
gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments/<COMMENT-ID>/replies \
-X POST -f body="Fixed in commit <SHORT-SHA>. <Brief explanation of what was changed.>"
# General comment to summarize all fixes
gh issue comment <PR-NUMBER> --body "All review feedback addressed in commit <SHORT-SHA>:
- Fixed: <item 1>
- Fixed: <item 2>
Ready for re-review. 🙏"
```
### Step 8 — Re-Request Review (Optional)
If the reviewer had submitted a `CHANGES_REQUESTED` review, request a new review after fixes:
```bash
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/requested_reviewers \
-X POST -f reviewers[]='<reviewer-login>'
```
---
## Decision Guide
### When NOT to implement a suggestion immediately
- **Design questions**: "Should this be a separate class?" — Present to user for decision
- **Optional nitpicks**: Reviewer marked as `nit:` — Ask user if they want to include it
- **Large refactors**: If fix would require changing >50 lines, propose a separate follow-up issue instead
### When to ask the user before proceeding
- Any fix involving behavioral changes to plugin logic
- Renaming Valve keys (breaking change — requires migration notes)
- Changes that affect the bilingual release notes already committed
---
## Anti-Patterns to Avoid
- ❌ Do NOT `git commit --amend` on a pushed commit without user approval for force-push
- ❌ Do NOT silently skip a reviewer's comment; always acknowledge it (implement or explain why not)
- ❌ Do NOT use `--force` (only `--force-with-lease` when absolutely necessary)
- ❌ Do NOT make unrelated changes in the fixup commit; keep scope focused on review feedback
- ❌ Do NOT respond to reviewer comments in Chinese if the PR language context is English

View File

@@ -0,0 +1,179 @@
---
name: pr-submitter
description: Submits a feature branch as a Pull Request with a validated, properly formatted bilingual PR body. Handles shell-escape-safe body writing via temp files. Use after release-prep has committed all changes.
---
# PR Submitter
## Overview
This skill handles the final step of pushing a feature branch and creating a validated Pull Request on GitHub. Its primary purpose is to avoid the shell-escaping pitfalls (backticks, special characters in `gh pr create --body`) by always writing the PR body to a **temp file** first.
## Prerequisites
- All changes are committed (use `release-prep` skill first)
- The `gh` CLI is authenticated (`gh auth status`)
- Current branch is NOT `main` or `master`
---
## Workflow
### Step 1 — Pre-Flight Checks
Run these checks before any push:
```bash
# 1. Confirm not on protected branch
git branch --show-current
# 2. Verify there are commits to push
git log origin/$(git branch --show-current)..HEAD --oneline 2>/dev/null || echo "No remote tracking branch yet"
# 3. Check gh CLI auth
gh auth status
```
If any check fails, stop and report clearly.
### Step 2 — Collect PR Metadata
Gather:
- **PR Title**: Must follow Conventional Commits format, English only (e.g., `feat(github-copilot-sdk): release v0.8.0 with conditional tool filtering`)
- **Target base branch**: Default is `main`
- **Plugin name + version** (to build body sections)
- **Key changes** (reuse from release-prep or the latest What's New section)
### Step 3 — Build PR Body File (Shell-Escape-Safe)
**Always write the body to a temp file.** Never embed multi-line markdown with special characters directly in a shell command.
```bash
cat > /tmp/pr_body.md << 'HEREDOC'
## Summary
Brief one-sentence description of what this PR accomplishes.
## Changes
### New Features
- Feature 1 description
- Feature 2 description
### Bug Fixes
- Fix 1 description
## Plugin Version
- `PluginName` bumped to `vX.X.X`
## Documentation
- README.md / README_CN.md updated
- docs/ mirrors synced
## Testing
- [ ] Tested locally in OpenWebUI
- [ ] i18n validated (all language keys present)
- [ ] Version consistency check passed (`python3 scripts/check_version_consistency.py`)
---
## 变更摘要(中文)
简要描述本次 PR 的改动内容。
### 新功能
- 功能1描述
- 功能2描述
### 问题修复
- 修复1描述
HEREDOC
```
**Critical rules for the body file:**
- Use `<< 'HEREDOC'` (quoted heredoc) to prevent variable expansion
- Keep all backticks literal — they are safe inside a heredoc
- Paths like `/api/v1/files/` are safe too since heredoc doesn't interpret them as commands
### Step 4 — Validate PR Body
Before submitting, verify the body file contains expected sections:
```bash
# Check key sections exist
grep -q "## Summary" /tmp/pr_body.md && echo "✅ Summary" || echo "❌ Summary missing"
grep -q "## Changes" /tmp/pr_body.md && echo "✅ Changes" || echo "❌ Changes missing"
grep -q "## 变更摘要" /tmp/pr_body.md && echo "✅ CN Section" || echo "❌ CN Section missing"
# Preview the body
cat /tmp/pr_body.md
```
Ask the user to confirm the body content before proceeding.
### Step 5 — Push Branch
```bash
git push -u origin $(git branch --show-current)
```
If push is rejected (non-fast-forward), report to user and ask whether to force-push. **Do NOT force-push without explicit confirmation.**
### Step 6 — Create Pull Request
```bash
gh pr create \
--base main \
--head $(git branch --show-current) \
--title "<PR title from Step 2>" \
--body-file /tmp/pr_body.md
```
Always use `--body-file`, never `--body` with inline markdown.
### Step 7 — Verify PR Creation
```bash
PAGER=cat GH_PAGER=cat gh pr view --json number,url,title,body --jq '{number: .number, url: .url, title: .title, body_preview: .body[:200]}'
```
Confirm:
- PR number and URL
- Title matches intended Conventional Commits format
- Body preview includes key sections (not truncated/corrupted)
If the body appears corrupted (empty sections, missing backtick content), use edit:
```bash
gh pr edit <PR-NUMBER> --body-file /tmp/pr_body.md
```
### Step 8 — Cleanup
```bash
rm -f /tmp/pr_body.md
```
Report final PR URL to the user.
---
## Shell-Escape Safety Rules
| Risk | Safe Approach |
|------|--------------|
| Backticks in `--body` | Write to file, use `--body-file` |
| Paths like `/api/...` | Safe in heredoc; risky in inline `--body` |
| Newlines in `--body` | File-based only |
| `$variable` expansion | Use `<< 'HEREDOC'` (quoted) |
| Double quotes in body | Safe in heredoc file |
---
## Anti-Patterns to Avoid
- ❌ Never use `--body "..."` with multi-line content directly in shell command
- ❌ Never interpolate variables directly into heredoc without quoting the delimiter
- ❌ Never force-push (`--force`) without explicit user confirmation
- ❌ Never target `main` as the source branch (only as base)
- ❌ Never skip the body validation step — a PR with empty body is worse than a delayed PR

View File

@@ -0,0 +1,208 @@
---
name: release-finalizer
description: Merges a release PR, associates it with resolved issues, replies to issue reporters, and closes issues. Use after PR review is complete and ready for merge. Closes the release cycle.
---
# Release Finalizer
## Overview
This skill completes the final step of the release cycle: merging the release PR to `main`, replying to all related issues with solutions, and automatically closing them using GitHub's issue linking mechanism.
## Prerequisites
- The PR is in `OPEN` state and ready to merge
- All status checks have passed (CI green)
- All review feedback has been addressed
- The PR relates to one or more GitHub issues (either in PR description or through commits)
---
## Workflow
### Step 1 — Pre-Merge Verification
Verify that the PR is ready:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json state,statusCheckRollup,reviewDecision
```
Checklist:
-`state` is `OPEN`
-`statusCheckRollup` all have `conclusion: SUCCESS`
-`reviewDecision` is `APPROVED` or empty (no blocking reviews)
If any check fails, **do NOT merge**. Report the issue to the user.
### Step 2 — Identify Related Issues
Issues can be linked to a PR in multiple ways. Check the PR description and commit messages for keywords:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json body,commits
```
Look for patterns like:
- `Closes #XX`, `Fixes #XX`, `Resolves #XX` (in description or commit bodies)
- `#XX` mentioned as "related to" or "addresses"
**Manual input**: If issue links are not in the PR, ask the user which issue(s) this PR resolves.
Extract all issue numbers into a list: `[#48, #52, ...]`
### Step 3 — Select Merge Strategy
Offer the user three options:
| Strategy | Git Behavior | Use Case |
|----------|-------------|----------|
| **Squash** | All commits squashed into one commit on main | Clean history, recommended for release PRs |
| **Rebase** | Linear history, no merge commit | Preserve commit granularity |
| **Merge** | Merge commit created | Preserve full PR context |
**Recommendation for release PRs**: Use `--squash` to create a single clean commit.
If user doesn't specify, default to `--squash`.
### Step 4 — Prepare Merge Commit Message
If using `--squash`, craft a single comprehensive commit message:
**Format** (Conventional Commits + Github linking):
```
type(scope): description
- Bullet point 1
- Bullet point 2
Closes #48
Closes #52
```
The `Closes #XX` keyword tells GitHub to automatically close those issues when the commit lands on `main`.
Example:
```
feat(pipes,filters): release Copilot SDK Pipe v0.8.0 and Files Filter v0.1.3
- Implement P1~P4 conditional tool filtering system
- Fix file publishing reliability across all storage backends
- Add strict file URL validation
- Update bilingual documentation
Closes #48
```
### Step 5 — Execute Merge
```bash
gh pr merge <PR-NUMBER> \
--squash \
--delete-branch \
-m "type(scope): description" \
-b "- Bullet 1\n- Bullet 2\n\nCloses #48"
```
**Key flags:**
- `--squash`: Squash commits (recommended for releases)
- `--delete-branch`: Delete the feature branch after merge
- `-m`: Commit subject
- `-b`: Commit body (supports `\n` for newlines)
Confirm the merge is successful; GitHub will automatically close related issues with `Closes #XX` keyword.
### Step 6 — Verify Auto-Close
GitHub automatically closes issues when a commit with `Closes #XX` lands on the default branch (`main`).
To verify:
```bash
PAGER=cat GH_PAGER=cat gh issue view <ISSUE-NUMBER> --json state
```
Should show `state: CLOSED`.
### Step 7 — Post Closing Message (Optional but Recommended)
For better UX, manually post a summary comment to **each issue** before it auto-closes (since auto-close happens silently):
```bash
gh issue comment <ISSUE-NUMBER> --body "
This has been fixed in PR #<PR-NUMBER>, which is now merged to main.
**Solution Summary:**
- <Key fix 1>
- <Key fix 2>
The fix will be available in the next plugin release. Thank you for reporting! ⭐
"
```
### Step 8 — (Optional) Regenerate Release Notes
If the merge revealed any final tweaks to release notes:
```bash
# Re-export release notes from merged commit
git log --oneline -1 <merged-commit-sha>
```
If needed, create a follow-up PR with doc polish (do NOT force-push the merged commit).
---
## Merge Strategy Decision Tree
```
Is this a patch/hotfix release?
├─ YES → Use --squash
└─ NO → Multi-feature release?
├─ YES → Use --squash (cleaner history)
└─ NO → Preserve detail?
├─ YES → Use --rebase
└─ NO → Use --merge (preserve PR context)
```
---
## Issue Auto-Close Keywords
These keywords in commit/PR messages will auto-close issues when merged to `main`:
- `Closes #XX`
- `Fixes #XX`
- `Resolves #XX`
- `close #XX` (case-insensitive)
- `fix #XX`
- `resolve #XX`
**Important**: The keyword must be on the **final commit that lands on** `main`. For squash merges, it must be in the squash commit message body.
---
## Anti-Patterns to Avoid
- ❌ Do NOT merge if any status checks are PENDING or FAILED
- ❌ Do NOT merge if there are blocking reviews (reviewDecision: `CHANGES_REQUESTED`)
- ❌ Do NOT merge without verifying the Conventional Commits format in the merge message
- ❌ Do NOT merge without including `Closes #XX` keywords for all related issues
- ❌ Do NOT assume issues will auto-close silently — post a courtesy comment first
- ❌ Do NOT delete the branch if it might be needed for cherry-pick or hotfixes later
---
## Troubleshooting
### Issue did not auto-close after merge
- Verify the `Closes #XX` keyword is in the **final commit message** (use `git log` to check)
- Ensure the commit is on the `main` branch
- GitHub sometimes takes a few seconds to process; refresh the issue page
### Multiple issues to close
- List all in separate `Closes #XX` lines in the commit body
- Each one will be independently auto-closed
### Want to close issue without merge?
- Use `gh issue close <ISSUE-NUMBER>` manually
- Only recommended if the PR was manually reverted or deemed invalid

View File

@@ -0,0 +1,137 @@
---
name: release-prep
description: Orchestrates the full release preparation flow for a plugin — version sync across 7+ files, bilingual release notes creation, and commit message drafting. Use before submitting a PR. Does NOT push or create a PR; that is handled by pr-submitter.
---
# Release Prep
## Overview
This skill drives the complete pre-PR release pipeline. It enforces the repository rule that every release must synchronize the version number and changelog across **at least 7 locations** before a commit is created.
## Scope
This skill covers:
1. Version sync (delegates detail to `version-bumper` if needed)
2. Bilingual release notes file creation
3. 7-location consistency verification
4. Conventional Commits message drafting
5. `git add -A && git commit` execution
It **stops before** `git push` or `gh pr create`. Use the `pr-submitter` skill for those steps.
---
## Workflow
### Step 1 — Collect Release Info
Ask the user (or infer from current state) the following:
- **Plugin name** and **type** (actions / filters / pipes / tools)
- **New version number** (e.g., `0.8.0`)
- **Key changes** in English and Chinese (1-5 bullet points each)
If a `What's New` section already exists in README.md, extract it as the source of truth.
### Step 2 — Sync Version Across 7 Locations
Verify AND update the version string in all of the following. Mark each as ✅ or ❌:
| # | File | Location |
|---|------|----------|
| 1 | `plugins/{type}/{name}/{name}.py` | `version:` in docstring |
| 2 | `plugins/{type}/{name}/README.md` | `**Version:** x.x.x` metadata line |
| 3 | `plugins/{type}/{name}/README_CN.md` | `**Version:** x.x.x` metadata line |
| 4 | `docs/plugins/{type}/{name}.md` | `**Version:** x.x.x` metadata line |
| 5 | `docs/plugins/{type}/{name}.zh.md` | `**Version:** x.x.x` metadata line |
| 6 | `docs/plugins/{type}/index.md` | version badge for this plugin |
| 7 | `docs/plugins/{type}/index.zh.md` | version badge for this plugin |
Additionally update the root-level **updated date badge** in:
- `README.md``![updated](https://img.shields.io/badge/YYYY--MM--DD-gray?style=flat)`
- `README_CN.md` — same badge format
Use today's date (`YYYY-MM-DD`) for the badge.
### Step 3 — Update What's New (All 4 Doc Files)
The `What's New` / `最新更新` section must contain **only the most recent release's changes**. Previous entries should be removed from this section (they live in CHANGELOG or release notes files).
Update these 4 files' `What's New` / `最新更新` block consistently:
- `plugins/{type}/{name}/README.md`
- `plugins/{type}/{name}/README_CN.md`
- `docs/plugins/{type}/{name}.md`
- `docs/plugins/{type}/{name}.zh.md`
### Step 4 — Create Bilingual Release Notes Files
Create two versioned release notes files:
**Path**: `plugins/{type}/{name}/v{version}.md`
**Path**: `plugins/{type}/{name}/v{version}_CN.md`
#### Required Sections
Each file must include:
1. **Title**: `# v{version} Release Notes` (EN) / `# v{version} 版本发布说明` (CN)
2. **Overview**: One paragraph summarizing this release
3. **New Features** / **新功能**: Bulleted list of features
4. **Bug Fixes** / **问题修复**: Bulleted list of fixes
5. **Migration Notes** / **迁移说明**: Breaking changes or Valve key renames (omit section if none)
6. **Companion Plugins** / **配套插件** (optional): If a companion plugin was updated
If a release notes file already exists for this version, update it rather than creating a new one.
### Step 5 — Verify Consistency (Pre-Commit Check)
Run the consistency check script:
```bash
python3 scripts/check_version_consistency.py
```
If issues are found, fix them before proceeding. Do not commit with inconsistencies.
### Step 6 — Draft Conventional Commits Message
Generate the commit message following `commit-message.instructions.md` rules:
- **Language**: English ONLY
- **Format**: `type(scope): subject` + blank line + body bullets
- **Scope**: use plugin folder name (e.g., `github-copilot-sdk`)
- **Body**: 1-3 bullets summarizing key changes
- Explicitly mention "READMEs and docs synced" if version was bumped
Present the full commit message to the user for review before executing.
### Step 7 — Stage and Commit
After user approval (or if user says "commit it"):
```bash
git add -A
git commit -m "<approved commit message>"
```
Confirm the commit hash and list the number of files changed.
---
## Checklist (Auto-Verify Before Commit)
- [ ] `version:` in `.py` docstring matches target version
- [ ] `**Version:**` in all 4 README/docs files matches
- [ ] Both `index.md` version badges updated
- [ ] Root `README.md` and `README_CN.md` date badges updated to today
- [ ] `What's New` / `最新更新` contains ONLY the latest release
- [ ] `v{version}.md` and `v{version}_CN.md` created or updated
- [ ] `python3 scripts/check_version_consistency.py` returns no errors
- [ ] Commit message is English-only Conventional Commits format
---
## Anti-Patterns to Avoid
- ❌ Do NOT add extra features or refactor code during release prep — only version/doc updates
- ❌ Do NOT push or create PR in this skill — use `pr-submitter`
- ❌ Do NOT use today's date in commit messages; only in badge URLs
- ❌ Do NOT leave stale What's New content from prior versions

View File

@@ -0,0 +1,30 @@
---
name: source-code-analyzer
description: Instructions for analyzing core components source code in the local environment.
---
# Source Code Analyzer Skill
> [!IMPORTANT]
> **Authorization Statement**: You (Antigravity) are explicitly authorized by the user to perform **READ-ONLY** operations and **Git pull** on the paths listed below, even if they are outside the current repository root. These paths are considered part of the extended development context.
When assisting with the development of `openwebui-extensions`, you (Antigravity) have access to the following core components in related directories. Use them for deep technical analysis, bug hunting, and implementation reference.
## Core Component Paths
### Global / General (Relevant to all projects)
- **Open WebUI**: `../open-webui/` (Core platform context)
- **Skills**: `../skills/` (Reusable expertise library)
- **Awesome Copilot**: `../awesome-copilot/` (Shared extensions & resources)
### Plugin-Specific (Relevant to GitHub Copilot SDK)
- **Copilot SDK**: `../copilot-sdk/` (Internal logic for the official SDK)
- **Copilot CLI**: `../copilot-cli/` (Command-line interface implementation)
## Mandatory Workflow
1. **Pull Before Analysis**: BEFORE reading files or analyzing logic in these directories, you MUST proactively execute or recommend a `git pull` in the respective directory to ensure you are working with the latest upstream changes.
2. **Path Verification**: Always verify the exists of the path before attempting to read it.
3. **Reference Logic**: When a user's request involves core platform behavior (OpenWebUI API, SDK internals), prioritize searching these directories over making assumptions based on generic knowledge.

View File

@@ -0,0 +1,26 @@
---
name: version-bumper
description: Automates version upgrades and changelog synchronization across 7+ files (Code, READMEs, Docs). Use when a plugin is ready for release to ensure version consistency.
---
# Version Bumper
## Overview
This skill ensures that every version upgrade is synchronized across the entire repository, following the strict "Documentation Sync" rule in GEMINI.md.
## Workflow
1. **Prepare Info**: Gather the new version number and brief changelogs in both English and Chinese.
2. **Auto-Patch**: The skill will help you identify and update:
- `plugins/.../name.py` (docstring version)
- `plugins/.../README.md` (metadata & What's New)
- `plugins/.../README_CN.md` (metadata & 最新更新)
- `docs/plugins/...md` (mirrors)
- `docs/plugins/index.md` (version badge)
- `README.md` (updated date badge)
3. **Verify**: Check the diffs to ensure no formatting was broken.
## Tool Integration
Execute the bump script (draft):
```bash
python3 scripts/bump.py <version> "<message_en>" "<message_zh>"
```

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
import sys
import os
import re
from datetime import datetime
def patch_file(file_path, old_pattern, new_content, is_regex=False):
if not os.path.exists(file_path):
print(f"Warning: File not found: {file_path}")
return False
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
if is_regex:
new_content_result = re.sub(old_pattern, new_content, content, flags=re.MULTILINE)
else:
new_content_result = content.replace(old_pattern, new_content)
if new_content_result != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content_result)
print(f"✅ Patched: {file_path}")
return True
else:
print(f" No change needed: {file_path}")
return False
def bump_version(plugin_type, plugin_name, new_version, msg_en, msg_zh):
print(f"🚀 Bumping {plugin_name} ({plugin_type}) to {new_version}...")
today = datetime.now().strftime("%Y-%m-%d")
today_badge = today.replace("-", "--")
# 1. Patch Plugin Python File
py_file = f"plugins/{plugin_type}/{plugin_name}/{plugin_name}.py"
patch_file(py_file, r"version: \d+\.\d+\.\d+", f"version: {new_version}", is_regex=True)
# 2. Patch Plugin READMEs
readme_en = f"plugins/{plugin_type}/{plugin_name}/README.md"
readme_zh = f"plugins/{plugin_type}/{plugin_name}/README_CN.md"
# Update version in metadata
patch_file(readme_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(readme_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# Update What's New (Assuming standard headers)
patch_file(readme_en, r"## 🔥 What's New in v.*?\n", f"## 🔥 What's New in v{new_version}\n\n* {msg_en}\n", is_regex=True)
patch_file(readme_zh, r"## 🔥 最新更新 v.*?\n", f"## 🔥 最新更新 v{new_version}\n\n* {msg_zh}\n", is_regex=True)
# 3. Patch Docs Mirrors
doc_en = f"docs/plugins/{plugin_type}/{plugin_name}.md"
doc_zh = f"docs/plugins/{plugin_type}/{plugin_name}.zh.md"
patch_file(doc_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(doc_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# 4. Patch Root READMEs (Updated Date Badge)
patch_file("README.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
patch_file("README_CN.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
print("\n✨ All synchronization tasks completed.")
return True
if __name__ == "__main__":
if len(sys.argv) < 6:
print("Usage: bump.py <type> <name> <version> <msg_en> <msg_zh>")
print("Example: bump.py filters markdown_normalizer 1.2.8 'Fix bug' '修复错误'")
sys.exit(1)
bump_version(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])

165
.github/ISSUE_TEMPLATE/bug_report.yml vendored Normal file
View File

@@ -0,0 +1,165 @@
name: 🐛 Bug Report
description: Report a bug or issue with OpenWebUI plugins
title: "[BUG] "
labels: ["bug"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for reporting a bug! Please provide clear information to help us reproduce and fix the issue.
- type: dropdown
id: plugin-type
attributes:
label: Plugin Type
description: Which type of plugin is affected?
options:
- Action
- Filter
- Pipe
- Pipeline
- Tool
- Other
validations:
required: true
- type: dropdown
id: plugin-name
attributes:
label: Plugin Name
description: Which plugin has the issue?
options:
- "Select a plugin..."
- "Action - Deep Dive"
- "Action - Export to Word Enhanced"
- "Action - Export to Excel"
- "Action - Flash Card"
- "Action - Smart Infographic"
- "Action - Smart Mind Map"
- "Filter - Async Context Compression"
- "Filter - Context & Model Enhancement Filter"
- "Filter - Folder Memory"
- "Filter - GitHub Copilot SDK Files Filter"
- "Filter - Markdown Normalizer"
- "Filter - Gemini Multimodel Filter"
- "Pipeline - MOE Prompt Refiner"
- "Pipe - GitHub Copilot SDK"
- "Pipe - iFlow SDK"
- "Tool - OpenWebUI Skills Manager"
- "Tool - Smart Infographic Tool"
- "Tool - Smart Mind Map Tool"
- "Other / Not Listed"
validations:
required: true
- type: input
id: plugin-name-other
attributes:
label: Plugin Name (if not in list)
description: If you selected 'Other / Not Listed', please specify the plugin name
placeholder: "Plugin name"
validations:
required: false
- type: textarea
id: description
attributes:
label: Description
description: Clearly describe the bug. What went wrong? What did you expect?
placeholder: |
I tried to use [feature], but instead of [expected behavior], it [actual behavior].
Error message (if any):
validations:
required: true
- type: textarea
id: steps
attributes:
label: Steps to Reproduce
description: How can we reproduce this issue?
placeholder: |
1. Click on...
2. Enter...
3. See error...
validations:
required: true
- type: input
id: openwebui-version
attributes:
label: OpenWebUI Version
description: What version of OpenWebUI are you using?
placeholder: "e.g., 0.3.0 or main"
validations:
required: true
- type: textarea
id: environment
attributes:
label: Operating System & Container
description: "Your operating system and deployment method"
placeholder: |
Example 1:
OS: macOS 14.3
Container: Docker (version 24.0.x)
Example 2:
OS: Ubuntu 22.04 LTS
Deployment: Docker Compose
validations:
required: true
- type: markdown
attributes:
value: |
## 📋 Debug Information (Optional)
To help diagnose the issue faster, please provide relevant logs:
**Frontend Console Logs** (Recommended):
1. Enable: Click avatar → Settings → General → Enable Plugin Debug Output
2. Open DevTools: Press `F12` (or `Cmd+Option+I` on Mac)
3. Go to Console tab and copy any error messages or `🛠️ Debug` output
**Server-Side Logs**:
- Docker: `docker logs <container-id>`
- Local: Check terminal output or log files
- type: textarea
id: logs
attributes:
label: Error Logs (Optional)
description: "Paste frontend console or server logs that show the error"
placeholder: |
Error message from console:
[Your logs here]
render: bash
validations:
required: false
- type: textarea
id: additional
attributes:
label: Additional Information (Optional)
description: "Screenshots, related issues, or other helpful details"
placeholder: |
- Screenshots (if applicable)
- Related issues or discussions
- Steps you've already tried to fix it
validations:
required: false
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: I have searched for duplicate issues
required: true
- label: I have provided clear reproduction steps
required: true
- label: I have mentioned OpenWebUI version and OS/container info
required: true

11
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,11 @@
blank_issues_enabled: false
contact_links:
- name: Documentation
url: https://docs.openwebui.com/
about: Official OpenWebUI documentation
- name: Discussions
url: https://github.com/Fu-Jie/openwebui-extensions/discussions
about: Ask questions and discuss with the community
- name: OpenWebUI Repository
url: https://github.com/open-webui/open-webui
about: Main OpenWebUI project

View File

@@ -0,0 +1,104 @@
name: ✨ Feature Request
description: Suggest a new feature or improvement
title: "[FEATURE] "
labels: ["enhancement"]
assignees: []
body:
- type: markdown
attributes:
value: |
Thanks for your suggestion! Please describe the feature you'd like to see.
- type: dropdown
id: plugin-type
attributes:
label: Plugin Type (Optional)
description: Is this for a specific plugin type?
options:
- Action
- Filter
- Pipe
- Pipeline
- Tool
- Core/General
- Documentation
- Other
validations:
required: false
- type: dropdown
id: plugin-name
attributes:
label: Plugin Name (Optional)
description: Which plugin would benefit from this feature?
options:
- "Select a plugin..."
- "Action - Deep Dive"
- "Action - Export to Word Enhanced"
- "Action - Export to Excel"
- "Action - Flash Card"
- "Action - Smart Infographic"
- "Action - Smart Mind Map"
- "Filter - Async Context Compression"
- "Filter - Context & Model Enhancement Filter"
- "Filter - Folder Memory"
- "Filter - GitHub Copilot SDK Files Filter"
- "Filter - Markdown Normalizer"
- "Filter - Gemini Multimodel Filter"
- "Pipeline - MOE Prompt Refiner"
- "Pipe - GitHub Copilot SDK"
- "Pipe - iFlow SDK"
- "Tool - OpenWebUI Skills Manager"
- "Tool - Smart Infographic Tool"
- "Tool - Smart Mind Map Tool"
- "Core/General Improvement"
- "Other / Not Listed"
validations:
required: false
- type: textarea
id: description
attributes:
label: Feature Description
description: Clearly describe the feature you're requesting
placeholder: |
What feature would you like to see?
How would it work?
validations:
required: true
- type: textarea
id: motivation
attributes:
label: Motivation & Use Case
description: Why is this feature important? What problem does it solve?
placeholder: |
What's the pain point this solves?
How would it improve your workflow?
Who else would benefit from this?
validations:
required: true
- type: textarea
id: additional
attributes:
label: Additional Information (Optional)
description: "Mockups, alternatives considered, references, or examples"
placeholder: |
- Links to related plugins or tools
- Screenshots or mockups
- Alternative approaches you've considered
- Code examples or references
validations:
required: false
- type: checkboxes
id: checklist
attributes:
label: Checklist
options:
- label: I have searched existing issues/discussions for similar requests
required: true
- label: This feature would be useful for multiple users
required: false

121
.github/TEMP_FILES_POLICY.md vendored Normal file
View File

@@ -0,0 +1,121 @@
# Temporary Files Handling Policy
**Last Updated**: 2026-02-26
**Status**: Active Guideline
## Overview
All temporary files created during skill execution or development workflows must follow this centralized policy to maintain project cleanliness and workspace isolation alignment.
## Core Rule
**Temporary files MUST be stored in the project's `.temp/` directory, NOT in system directories like `/tmp`.**
## Rationale
1. **Workspace Isolation**: Aligns with OpenWebUI's workspace-per-user model
2. **Project Cohesion**: All project artifacts (temporary or permanent) stay within project boundaries
3. **Multi-User Safety**: Avoids conflicts between multiple developers using the same system
4. **Cleanup Traceability**: Easy to verify all temp files are cleaned up via single `.temp/` directory
5. **Debugging**: Inspectable before deletion if issues occur
## Usage Pattern
### Creating Temp File
```bash
# Step 1: Ensure temp directory exists
mkdir -p .temp
# Step 2: Write temp file
cat > .temp/my_temp_file.md << 'EOF'
...content...
EOF
# Step 3: Use the file in your workflow
# (e.g., pass to gh CLI, process with script, etc.)
```
### Cleanup After Use
```bash
# Remove individual temp files
rm -f .temp/my_temp_file.md
# Or full cleanup of entire temp directory
rm -rf .temp/
```
## Skills Affected
| Skill | Implementation | Status |
|-------|----------------|--------|
| `pr-submitter` | PR body file (`.temp/pr_body.md`) | ✅ Updated |
| `release-prep` | Draft notes (if any) | ✅ Policy Added |
| `version-bumper` | Backup files (if any) | Check needed |
| Future skills | TBD | 📋 Must follow policy |
## .gitignore Configuration
The following entry in `.gitignore` ensures temp files are never committed:
```
# Temporary files
.temp/
.build/
```
## Examples
### Example 1: PR Submitter Skill
```bash
# Create PR body in temp directory
mkdir -p .temp
cat > .temp/pr_body.md << 'EOF'
## Summary
New feature implementation
EOF
# Use with gh CLI
gh pr create --body-file .temp/pr_body.md --title "feat: new feature"
# Cleanup
rm -f .temp/pr_body.md
```
### Example 2: Release Prepare Workflow
```bash
# Create draft changelog
mkdir -p .temp
cat > .temp/changelog_draft.md << 'EOF'
# v1.0.0 Release Notes
EOF
# Edit, validate, then integrate into real files
# ...
# Cleanup
rm -f .temp/changelog_draft.md
```
## Anti-Patterns (❌ Don't Do This)
- ❌ Writing temp files to `/tmp` — will be lost/orphaned
- ❌ Writing to root directory or `plugins/` — pollutes repo
- ❌ Not cleaning up temp files — accumulates clutter
- ❌ Committing `.temp/` files to git — defeats the purpose
- ❌ Using absolute paths — breaks workflow portability
## Enforcement
1. **Code Review**: PRs should verify no `/tmp` references in scripts
2. **CI/CD**: Setup can validate `.temp/` cleanup via git status before commit
3. **Documentation**: All skill docs must reference this policy (link to this file)
4. **Automated**: Consider adding pre-commit hook to ensure `.temp/` is not staged
## Questions / Clarifications
For questions about this policy, refer to:
- `.github/skills/pr-submitter/SKILL.md` — Practical example
- `.github/skills/release-prep/SKILL.md` — Policy integration
- `/memories/repo/temp-file-handling-convention.md` — Internal notes

View File

@@ -0,0 +1,67 @@
---
name: Plugin Implementer
description: Implement OpenWebUI plugin and docs updates with strict project standards
argument-hint: Provide approved plan or feature request to implement
tools: ['execute/getTerminalOutput', 'execute/runInTerminal', 'read/readFile', 'read/terminalSelection', 'read/terminalLastCommand', 'edit/createFile', 'edit/editFiles', 'search', 'web', 'web/fetch', 'web/githubRepo', 'agent']
infer: true
handoffs:
- label: Run Review
agent: Plugin Reviewer
prompt: Review the implementation for i18n, safety, and consistency issues.
send: false
---
You are the **implementation specialist** for the `openwebui-extensions` repository.
## Execution Rules
1. **Minimal diffs**: Change only what the approved plan specifies.
2. **Single-file i18n**: Every plugin is one `.py` file with built-in `TRANSLATIONS` dict. Never create `_cn.py` split files.
3. **Context helpers**: Always use `_get_user_context(__user__)` and `_get_chat_context(body, __metadata__)` — never access dict keys directly.
4. **Emitter guards**: Every `await emitter(...)` must be guarded by `if emitter:`.
5. **Logging**: Use `logging.getLogger(__name__)` — no bare `print()` in production code.
6. **Async safety**: Wrap all `__event_call__` with `asyncio.wait_for(..., timeout=2.0)` + inner JS `try { ... } catch(e) { return fallback; }`.
## Required Plugin Pattern
```python
# Docstring: title, author, author_url, funding_url, version, description
# icon_url is REQUIRED for Action plugins (Lucide SVG, base64)
class Action: # or Filter / Pipe
class Valves(BaseModel):
SHOW_STATUS: bool = Field(default=True, description="...")
# All fields UPPER_SNAKE_CASE
def __init__(self):
self.valves = self.Valves()
def _get_user_context(self, __user__): ... # always implement
def _get_chat_context(self, body, __metadata__=None): ... # always implement
async def _emit_status(self, emitter, description, done=False): ...
async def _emit_notification(self, emitter, content, ntype="info"): ...
```
## Known Split-File Plugins (Legacy — Do NOT Add More)
These still have `_cn.py` files. When touching any of them, migrate CN content into `TRANSLATIONS` dict:
- `plugins/actions/deep-dive/deep_dive_cn.py`
- `plugins/actions/export_to_docx/export_to_word_cn.py`
- `plugins/actions/export_to_excel/export_to_excel_cn.py`
- `plugins/actions/flash-card/flash_card_cn.py`
- `plugins/actions/infographic/infographic_cn.py`
- `plugins/filters/folder-memory/folder_memory_cn.py`
## Version Bump Rule
Only bump version when user explicitly says "发布" / "release" / "bump version".
When bumping, update ALL 7+ files (code docstring + 2× README + 2× doc detail + 2× doc index + 2× root README date badge).
## Git Policy
- Never run `git commit`, `git push`, or create PRs automatically.
- After all edits, list what changed and why, then stop.
## Knowledge Capture (Mandatory)
Before ending the session, if you discovered any non-obvious internal API behaviour,
parameter injection quirk, or workaround, save it to `.agent/learnings/{topic}.md`.
Also browse `.agent/learnings/` at the start to reuse existing knowledge.
## Completion Output
- Modified files (full relative paths, one-line descriptions)
- Remaining manual checks
- Suggested handoff to **Plugin Reviewer**

79
.github/agents/plugin-planner.agent.md vendored Normal file
View File

@@ -0,0 +1,79 @@
---
name: Plugin Planner
description: Analyze requirements and produce a safe implementation plan for OpenWebUI plugins
argument-hint: Describe the plugin goal, constraints, and target files
tools: ['read/readFile', 'search', 'web', 'web/githubRepo', 'read/terminalLastCommand', 'read/terminalSelection', 'agent']
infer: true
handoffs:
- label: Start Implementation
agent: Plugin Implementer
prompt: Implement the approved plan step by step with minimal diffs.
send: false
---
You are the **planning specialist** for the `openwebui-extensions` repository.
## Your Responsibilities
1. Read existing plugin code and docs **before** proposing any change.
2. Produce a **small, reversible** plan (one logical change per file per step).
3. Clearly list all impacted files including the docs sync chain.
4. Flag risks: breaking changes, release implications, version bumps needed.
## Hard Rules
- Never propose `git commit`, `git push`, or PR creation.
- Every plan must end with an acceptance checklist for the user to approve before handing off.
- Reference `.github/copilot-instructions.md` as the authoritative spec.
- Browse `.agent/learnings/` **first** to reuse existing knowledge before researching anything.
## Repository Plugin Inventory
### Actions (`plugins/actions/`)
| Dir | Main file | Version | i18n status |
|-----|-----------|---------|-------------|
| `deep-dive` | `deep_dive.py` | 1.0.0 | ⚠️ has `deep_dive_cn.py` split |
| `export_to_docx` | `export_to_word.py` | 0.4.4 | ⚠️ has `export_to_word_cn.py` split |
| `export_to_excel` | `export_to_excel.py` | 0.3.7 | ⚠️ has `export_to_excel_cn.py` split |
| `flash-card` | `flash_card.py` | 0.2.4 | ⚠️ has `flash_card_cn.py` split |
| `infographic` | `infographic.py` | 1.5.0 | ⚠️ has `infographic_cn.py` split |
| `smart-mind-map` | `smart_mind_map.py` | 1.0.0 | ✅ single file |
| `smart-mermaid` | _(empty stub)_ | — | — |
### Filters (`plugins/filters/`)
| Dir | Main file | Version | i18n status |
|-----|-----------|---------|-------------|
| `async-context-compression` | `async_context_compression.py` | 1.3.0 | ✅ |
| `context_enhancement_filter` | `context_enhancement_filter.py` | 0.3 | ⚠️ non-SemVer version |
| `copilot_files_preprocessor` | _(empty stub)_ | — | — |
| `folder-memory` | `folder_memory.py` | 0.1.0 | ⚠️ has `folder_memory_cn.py` split |
| `github_copilot_sdk_files_filter` | `github_copilot_sdk_files_filter.py` | 0.1.2 | ✅ |
| `markdown_normalizer` | `markdown_normalizer.py` | 1.2.4 | ✅ |
| `web_gemini_multimodel_filter` | `web_gemini_multimodel.py` | 0.3.2 | ✅ |
### Pipes / Pipelines / Tools
| Path | Main file | Version |
|------|-----------|---------|
| `pipes/github-copilot-sdk` | `github_copilot_sdk.py` | 0.7.0 |
| `pipelines/moe_prompt_refiner` | `moe_prompt_refiner.py` | — |
| `tools/workspace-file-manager` | `workspace_file_manager.py` | 0.2.0 |
## Naming Conventions (Actual Mix)
- Action dirs: some use **dashes** (`deep-dive`, `flash-card`, `smart-mind-map`), some **underscores** (`export_to_docx`, `export_to_excel`, `infographic`)
- Filter dirs: similarly mixed — prefer underscores for new plugins
- Main `.py` filenames always use **underscores**
## Docs Sync Chain (for every plugin change)
For `plugins/{type}/{name}/`, these 7+ files must stay in sync:
1. `plugins/{type}/{name}/{name}.py` — version in docstring
2. `plugins/{type}/{name}/README.md` — version + What's New
3. `plugins/{type}/{name}/README_CN.md` — version + 最新更新
4. `docs/plugins/{type}/{name}.md`
5. `docs/plugins/{type}/{name}.zh.md`
6. `docs/plugins/{type}/index.md` — version badge
7. `docs/plugins/{type}/index.zh.md` — version badge
8. Root `README.md` / `README_CN.md` — date badge
## Output Format
- **Scope summary**
- **Affected files** (full relative paths)
- **Step-by-step plan** (numbered, ≤10 steps)
- **Risk flags** (version bump? breaking change? split-file migration needed?)
- **Acceptance checklist** → user must approve before handoff to Implementer

75
.github/agents/plugin-reviewer.agent.md vendored Normal file
View File

@@ -0,0 +1,75 @@
---
name: Plugin Reviewer
description: Perform strict repository-aligned code review for OpenWebUI plugin changes
argument-hint: Share changed files or branch diff to review
tools: ['search', 'read/readFile', 'web', 'web/fetch', 'web/githubRepo', 'execute/getTerminalOutput', 'read/terminalLastCommand', 'read/terminalSelection']
infer: true
handoffs:
- label: Prepare Release Draft
agent: Release Prep
prompt: Create a bilingual release draft and commit message based on reviewed changes.
send: false
---
You are the **review specialist** for the `openwebui-extensions` repository.
Full review rules are in .github/instructions/code-review.instructions.md.
## Review Checklist
### 🔴 Blocking (must fix before release)
**1. Single-file i18n Architecture**
- [ ] No new `_cn.py` split files created.
- [ ] All user-visible strings go through `TRANSLATIONS[lang].get(key, fallback)`.
- [ ] `FALLBACK_MAP` covers at least `zh → zh-CN` and `en → en-US`.
- [ ] `format(**kwargs)` on translations wrapped in `try/except KeyError`.
**2. Context Helpers**
- [ ] Uses `_get_user_context(__user__)` (not `__user__["name"]` directly).
- [ ] Uses `_get_chat_context(body, __metadata__)` (not ad-hoc `body.get("chat_id")`).
**3. Antigravity Safety**
- [ ] Every `__event_call__` wrapped: `asyncio.wait_for(..., timeout=2.0)`.
- [ ] JS code passed to `__event_call__` has `try { ... } catch(e) { return fallback; }`.
- [ ] File path operations validated against workspace root (no traversal).
- [ ] Upload paths have dual-channel fallback (API → DB/local).
**4. Emitter Guards**
- [ ] Every `await emitter(...)` guarded by `if emitter:`.
- [ ] `_emit_status(done=False)` on start, `done=True` on success, `_emit_notification("error")` on failure.
- [ ] No bare `print()` — use `logging.getLogger(__name__)`.
**5. Filter Singleton Safety**
- [ ] No mutable per-request state stored on `self` in Filter plugins.
**6. Streaming Compatibility (OpenWebUI 0.8.x)**
- [ ] `</think>` tag closed before any normal text or tool cards.
- [ ] `<details type="tool_calls" ...>` attributes escape `"` as `&quot;`.
- [ ] `<details ...>` block has newline immediately after `>`.
**7. Version & Docs Sync**
- [ ] Version bumped in docstring (if release).
- [ ] `README.md` + `README_CN.md` updated (What's New + version).
- [ ] `docs/plugins/{type}/{name}.md` and `.zh.md` match README.
- [ ] `docs/plugins/{type}/index.md` and `.zh.md` version badges updated.
- [ ] Root `README.md` / `README_CN.md` date badge updated.
**8. Knowledge Capture**
- [ ] Any non-obvious findings (API contracts, injection quirks, gotchas) documented in `.agent/learnings/{topic}.md`.
### 🟡 Non-blocking (suggestions)
- Copilot SDK tools: `params_type=MyParams` in `define_tool()`.
- Long tasks (>3s): periodic `_emit_notification("info")` every 5s.
- `icon_url` present for Action plugins (Lucide SVG, base64).
## Known Pre-existing Issues (Don't block on unless the PR introduces new ones)
- `_cn.py` splits in: `deep-dive`, `export_to_docx`, `export_to_excel`, `flash-card`, `infographic`, `folder-memory` — legacy, not new.
- `context_enhancement_filter` version is `0.3` (non-SemVer) — pre-existing.
- `copilot_files_preprocessor` and `smart-mermaid` are empty stubs — pre-existing.
## Review Output
- **Blocking issues** (file:line references)
- **Non-blocking suggestions**
- **Pass / Fail verdict**
- **Knowledge captured?** (`.agent/learnings/` updated if any discoveries were made)
- **Next step**: Pass → handoff to Release Prep; Fail → return to Implementer with fix list

82
.github/agents/release-prep.agent.md vendored Normal file
View File

@@ -0,0 +1,82 @@
---
name: Release Prep
description: Prepare release-ready summaries and Conventional Commit drafts without pushing
argument-hint: Provide final change list and target version (optional)
tools: ['search', 'read/readFile', 'web', 'web/fetch', 'web/githubRepo', 'execute/getTerminalOutput', 'read/terminalLastCommand', 'read/terminalSelection']
infer: true
---
You are the **release preparation specialist** for the `openwebui-extensions` repository.
Full commit message rules: .github/instructions/commit-message.instructions.md
Full release workflow: .agent/workflows/plugin-development.md
## Responsibilities
1. Generate a Conventional Commit message (English only).
2. Draft bilingual release notes (EN + 中文).
3. Verify ALL file sync locations are updated.
4. **Stop before any commit or push** — wait for explicit user confirmation.
## Commit Message Format
```text
type(scope): brief imperative description
- Key change 1
- Key change 2 (include migration note if needed)
```
- `type`: `feat` / `fix` / `docs` / `refactor` / `chore`
- `scope`: plugin folder name (e.g., `smart-mind-map`, `github-copilot-sdk`, `folder-memory`)
- Title ≤ 72 chars, imperative mood, no trailing period, no capital first letter
## 9-File Sync Checklist (fill in for each changed plugin)
```text
Plugin: {type}/{name} → v{new_version}
[ ] 1. plugins/{type}/{name}/{name}.py → version in docstring
[ ] 2. plugins/{type}/{name}/README.md → version + What's New
[ ] 3. plugins/{type}/{name}/README_CN.md → version + 最新更新
[ ] 4. docs/plugins/{type}/{name}.md → mirrors README
[ ] 5. docs/plugins/{type}/{name}.zh.md → mirrors README_CN
[ ] 6. docs/plugins/{type}/index.md → version badge updated
[ ] 7. docs/plugins/{type}/index.zh.md → version badge updated
[ ] 8. README.md (root) → date badge updated
[ ] 9. README_CN.md (root) → date badge updated
```
## Current Plugin Versions (as of last audit — 2026-02-23)
| Plugin | Type | Version | Note |
|--------|------|---------|------|
| deep-dive | action | 1.0.0 | has `_cn.py` split |
| export_to_docx | action | 0.4.4 | has `_cn.py` split |
| export_to_excel | action | 0.3.7 | has `_cn.py` split |
| flash-card | action | 0.2.4 | has `_cn.py` split |
| infographic | action | 1.5.0 | has `_cn.py` split |
| smart-mind-map | action | 1.0.0 | ✅ |
| async-context-compression | filter | 1.3.0 | ✅ |
| context_enhancement_filter | filter | 0.3 | ⚠️ non-SemVer |
| folder-memory | filter | 0.1.0 | has `_cn.py` split |
| github_copilot_sdk_files_filter | filter | 0.1.2 | ✅ |
| markdown_normalizer | filter | 1.2.4 | ✅ |
| web_gemini_multimodel_filter | filter | 0.3.2 | ✅ |
| github-copilot-sdk | pipe | 0.7.0 | ✅ |
| workspace-file-manager | tool | 0.2.0 | ✅ |
## Output Template
### Commit Message
```text
{type}({scope}): {description}
- {change 1}
- {change 2}
```
### Change Summary (EN)
- {bullet list of user-visible changes}
### 变更摘要(中文)
- {中文要点列表}
### Verification Status
{filled-in 9-file checklist for each changed plugin}
---
⚠️ **Waiting for user confirmation — no git operations will run until explicitly approved.**

File diff suppressed because it is too large Load Diff

21
.github/gh-aw/README.md vendored Normal file
View File

@@ -0,0 +1,21 @@
# gh-aw Support Files
This directory stores repository-local support files for GitHub Agentic Workflows.
## Purpose
Keep review aids, policy notes, and human-facing mirrors out of `.github/workflows/` so only real gh-aw source workflows live there.
## Structure
- `review-mirrors/`: Chinese review mirrors and maintainer-facing explanations for workflow source files.
## Current Files
- `review-mirrors/aw-pr-maintainer-review.zh.md`: Chinese review mirror for `.github/workflows/aw-pr-maintainer-review.md`.
- `review-mirrors/aw-release-preflight.zh.md`: Chinese review mirror for `.github/workflows/aw-release-preflight.md`.
- `review-mirrors/aw-ci-audit.zh.md`: Chinese review mirror for `.github/workflows/aw-ci-audit.md`.
## Rule
Files in this directory are for maintainer review and documentation only. They are not gh-aw workflow source files and should not be compiled.

View File

@@ -0,0 +1,249 @@
# aw-ci-audit 中文对照
对应源文件:`.github/workflows/aw-ci-audit.md`
用途:这是一份给维护者 review 用的中文对照说明,不是 gh-aw 工作流源文件,也不参与 `gh aw compile`
## 工作流定位
这个工作流的目标是做“CI / 自动化健康审计”。
它不是日志转储器,也不是自动修复器,而是用于:
- 检查近期仓库自动化是否出现可重复的失败模式
- 分析 release、publish、stats 等关键工作流的薄弱点
- 只在有新且可操作的诊断结论时,创建一条维护 issue
如果没有新的可操作诊断,或者问题已经被现有 issue 覆盖,就执行 `noop`
## Frontmatter 对照
### 触发方式
- `schedule: daily`
- `workflow_dispatch`
- `roles: all`
- `skip-bots`
- `github-actions`
- `copilot`
- `dependabot`
- `renovate`
说明:这套设计更适合“定期体检 + 手动补查”,而不是直接绑到不确定的 workflow failure 事件上。
### 权限
当前设计为只读:
- `contents: read`
- `issues: read`
- `pull-requests: read`
- `actions: read`
说明:工作流只做诊断分析,不改代码、不发 release、不创建 PR。
### Safe Outputs
已配置:
- `create-issue`
- 标题前缀:`[ci-audit] `
- labels`ci-audit``maintenance`
- 不自动关闭旧 issue
最终只能二选一:
- 有新且可操作的诊断时执行 `create_issue`
- 无新问题时执行 `noop`
### 工具
- `github`
- `repos`
- `issues`
- `pull_requests`
- `bash`
- 仅开放只读类命令,如 `pwd``ls``cat``rg``git diff``git show`
## 正文指令对照
## 主要目标
要求代理审计:
- release 相关 workflow 的失败或波动
- 插件发布失败
- 社区统计更新回归
- 重复出现的 workflow 脆弱点
- 维护者真正可以执行的下一步动作
明确限制:
- 只做诊断
- 不改文件
- 不推代码
- 不开 PR
- 不发 release
## 高优先级依据文件
在形成结论前,优先把这些文件当成“自动化规则源”:
- `.github/copilot-instructions.md`
- `.github/workflows/release.yml`
- `.github/workflows/publish_plugin.yml`
- `.github/workflows/publish_new_plugin.yml`
- `.github/workflows/plugin-version-check.yml`
- `.github/workflows/community-stats.yml`
- `docs/development/gh-aw-integration-plan.md`
- `docs/development/gh-aw-integration-plan.zh.md`
## 重点关注的目标工作流
优先检查:
- `release.yml`
- `publish_plugin.yml`
- `publish_new_plugin.yml`
- `plugin-version-check.yml`
- `community-stats.yml`
- `deploy.yml`
如果这些没有明显问题,不要无限扩大范围。
## 审查范围
聚焦“近期失败或可疑自动化信号”,并优先给出基于本仓库结构的诊断,而不是泛泛的 CI 建议。
它应该像“在看仓库自动化健康趋势的维护者”,而不是普通日志摘要机器人。
## 重点检查项
### 1. Release 与 Publish 失败
检查近期失败是否指向这些可操作问题:
- 版本提取或比较逻辑漂移
- release note 打包缺口
- publish 脚本的认证或环境问题
- workflow 中的结构假设已经不匹配当前仓库
- 如果不改仓库逻辑,就可能持续复现的失败
### 2. Stats 与定时任务稳定性
检查定时维护任务是否出现这些脆弱点:
- community stats 该提交时不再提交
- badge / docs 生成逻辑过时
- 依赖外部 API 的任务反复因同类原因失败
- schedule 驱动任务制造低价值噪音
### 3. 维护者信号质量
只有当结论“真的值得维护者处理”时,才创建 issue。
适合开 issue 的情况:
- 同类失败在多次运行中重复出现
- workflow 逻辑与当前仓库结构不匹配
- 大概率缺 secret / 权限 / 路径假设过时
- 重复出现的低信号失败值得过滤或加固
不要为一次性噪音失败开 issue除非它很可能复发。
### 4. 已有 Issue 感知
在创建新 issue 前,先判断是否已有 open issue 覆盖同一类 CI 问题。
如果已有 issue 已经足够覆盖,就优先 `noop`,避免制造重复单。
## 严重级别
只允许三档:
- `High`
- 高概率重复发生,且会持续影响仓库自动化
- `Medium`
- 建议尽快修,以降低维护成本或 workflow 漂移
- `Low`
- 可选的稳健性增强或清理建议
并且明确要求:
- 不要为了开 issue 而硬造问题
## Issue 格式
如果要创建 issue必须只有一条维护 issue。
要求:
- 英文
- 简洁
- 先写 findings不写空泛表扬
- 带可点击路径引用
- 不用嵌套列表
- 不要粘贴大段原始日志,除非短摘录确实必要
固定结构:
```markdown
## CI Audit
### Summary
Short diagnosis of the failure pattern or automation risk.
### Findings
- `path/to/file`: specific problem or likely root cause
### Suggested Next Steps
- concrete maintainer action
- concrete maintainer action
### Notes
- Mention whether this appears recurring, new, or already partially mitigated.
```
补充规则:
- 正常情况下控制在约 300 词以内
- 如果是相关联的问题,合并成一个 issue不要拆多个
- 优先提交“单个可执行诊断”,而不是大杂烩
## No-Issue 规则
如果没有值得报告的新诊断:
- 不要创建状态汇报型 issue
- 不要复述 workflows 看起来健康
- 直接走 `noop`
示例:
```json
{"noop": {"message": "No action needed: reviewed recent repository automation signals and found no new actionable CI diagnosis worth opening as a maintenance issue."}}
```
## 建议执行流程
1. 检查近期仓库自动化上下文
2. 优先检查目标工作流
3. 识别可重复或仓库特定的失败模式
4. 判断该问题是否已被 open issue 覆盖
5. 只有在诊断“新且可操作”时,才起草最短有用的维护 issue
6. 最终只执行一次 `create_issue` 或一次 `noop`
## 额外约束
- 不要为单次低信号瞬时失败开 issue
- 除非失败模式非常明确,否则不要顺势要求大规模重构
- 优先给出仓库特定原因,而不是泛泛的“重试试试”
- 如果根因不确定,要把不确定性写明
- 如果现有 issue 已经覆盖,优先 `noop` 而不是重复开单
## 最终要求
必须以且仅以一次 safe output 结束:
- 有新且可操作的诊断:`create_issue`
- 无新问题:`noop`

View File

@@ -0,0 +1,268 @@
# aw-pr-maintainer-review 中文对照
对应源文件:`.github/workflows/aw-pr-maintainer-review.md`
用途:这是一份给维护者 review 用的中文对照说明,不是 gh-aw 工作流源文件,也不参与 `gh aw compile`
## 工作流定位
这个工作流的目标是对触发 PR 做一次“维护者语义审查”。
它不是通用 code review 机器人,也不是自动修复器,而是用来检查以下问题:
- 是否违反本仓库插件开发规范
- 是否缺失应同步更新的 README / README_CN / docs 镜像文件
- 是否存在发布准备层面的遗漏
- 是否引入明显的高风险行为回归
如果 PR 已经足够合规,没有可操作的维护者反馈,就不评论,而是执行 `noop`
## Frontmatter 对照
### 触发方式
- `pull_request`
- 类型:`opened``reopened``synchronize``ready_for_review`
- 路径限制:
- `plugins/**`
- `docs/**`
- `.github/**`
- `README.md`
- `README_CN.md`
- `workflow_dispatch`
- `roles: all`
- `skip-bots`
- `github-actions`
- `copilot`
- `dependabot`
- `renovate`
### 权限
当前设计为只读:
- `contents: read`
- `issues: read`
- `pull-requests: read`
说明:工作流不会直接改代码,也不会提交 review comment 之外的写操作。
### Safe Outputs
已配置:
- `add-comment`
- 目标:当前触发 PR
- 最多 1 条
- 隐藏旧评论
- 不加 footer
同时要求最终必须二选一:
- 有问题时执行 `add_comment`
- 无问题时执行 `noop`
### 工具
- `github`
- `repos`
- `issues`
- `pull_requests`
- `bash`
- 仅开放只读类命令,如 `pwd``ls``cat``rg``git diff``git show`
## 正文指令对照
## 主要目标
要求代理审查:
- 仓库标准合规性
- 缺失的同步更新文件
- 发布准备缺口
- 文档漂移
- 插件代码中的高风险回归
明确限制:
- 只做 review
- 不改文件
- 不推代码
- 不创建 PR
## 高优先级依据文件
在形成结论前,优先把这些文件当成“本仓库规则源”:
- `.github/copilot-instructions.md`
- `.github/instructions/code-review.instructions.md`
- `.github/instructions/commit-message.instructions.md`
- `.github/skills/release-prep/SKILL.md`
- `.github/skills/doc-mirror-sync/SKILL.md`
- `docs/development/gh-aw-integration-plan.md`
- `docs/development/gh-aw-integration-plan.zh.md`
## 审查范围
- 先看 PR diff 和 changed files
- 只有在验证一致性时,才扩展读取关联文件
- 优先遵循“仓库特定规则”,而不是泛泛的最佳实践
换句话说,它应该像“熟悉本仓库的维护者”,而不是通用 lint bot。
## 重点检查项
### 1. 插件代码规范
`plugins/**/*.py` 变化时,重点看:
- 是否保持单文件 i18n 模式
- 用户可见文本是否进入翻译字典
- 是否使用 `_get_user_context``_get_chat_context`
- `__event_call__` 的 JS 执行是否具备 timeout 防护和前端兜底
- 是否引入 `print()` 到生产插件代码
- emitter 是否安全判空
- filter 插件是否把请求级可变状态塞到 `self`
- Copilot SDK / OpenWebUI tool 定义是否仍符合仓库规范
### 2. 版本与发布卫生
`plugins/**/*.py` 改动时,检查是否“应该同步但没同步”:
- 插件 docstring 的 `version:`
- 插件目录下 `README.md`
- 插件目录下 `README_CN.md`
- `docs/plugins/**` 下的镜像页面
- `docs/plugins/{type}/index.md` 等索引文件
- 如果是明显 release-prep 类型 PR再看根 `README.md``README_CN.md` 日期 badge
这里的关键语义是:
- 不是每个 PR 都必须当发布处理
- 只有在“用户可见行为、元数据、版本化文档、发布面内容”发生变化时,才提示缺失同步
### 3. 文档同步
当插件 README 改动时,检查是否应同步 docs 镜像:
- `plugins/actions/{name}/README.md` -> `docs/plugins/actions/{name}.md`
- `plugins/actions/{name}/README_CN.md` -> `docs/plugins/actions/{name}.zh.md`
- `plugins/filters/{name}/README.md` -> `docs/plugins/filters/{name}.md`
- `plugins/filters/{name}/README_CN.md` -> `docs/plugins/filters/{name}.zh.md`
- `plugins/pipes/{name}/README.md` -> `docs/plugins/pipes/{name}.md`
- `plugins/pipes/{name}/README_CN.md` -> `docs/plugins/pipes/{name}.zh.md`
- `plugins/pipelines/{name}/README.md` -> `docs/plugins/pipelines/{name}.md`
- `plugins/pipelines/{name}/README_CN.md` -> `docs/plugins/pipelines/{name}.zh.md`
- `plugins/tools/{name}/README.md` -> `docs/plugins/tools/{name}.md`
- `plugins/tools/{name}/README_CN.md` -> `docs/plugins/tools/{name}.zh.md`
如果是 docs-only 且明显有意为之,不要过度报错。
### 4. PR 质量
只在“确实让维护者审查变难”时,才指出 PR 描述缺失这些内容:
- 改了什么
- 为什么改
- 是否需要迁移或重新配置
## 严重级别
只允许三档:
- `Blocking`
- 大概率 bug、发布回归、缺少必需同步、严重规范破坏
- `Important`
- 应该合并前修,但不一定是直接运行时错误
- `Minor`
- 建议项,可选
并且明确要求:
- 不要为了留言而硬凑问题
## 评论格式
如果要评论,必须只有一条总结评论。
要求:
- 英文
- 简洁
- 先给 findings不先夸赞
- 带可点击路径引用
- 不使用嵌套列表
- 不要机械复述 diff
固定结构:
```markdown
## PR Maintainer Review
### Blocking
- `path/to/file`: specific issue and why it matters
### Important
- `path/to/file`: specific issue and what sync/check is missing
### Minor
- `path/to/file`: optional improvement or consistency note
### Merge Readiness
- Ready after the items above are addressed.
```
补充规则:
- 空 section 要省略
- 如果只有一个严重级别,只保留那个 section 和 `Merge Readiness`
- 正常情况下控制在约 250 词以内
## No-Comment 规则
如果没有有意义的维护者反馈:
- 不要发“看起来不错”这类表扬评论
- 不要复述 checks passed
- 直接走 `noop`
示例:
```json
{"noop": {"message": "No action needed: reviewed the PR diff and repository sync expectations, and found no actionable maintainer feedback."}}
```
## 建议执行流程
1. 找出变更文件
2. 读取高优先级规则文件
3. 对照插件审查规范检查插件代码
4. 对照 doc mirror 规则检查 README / docs
5. 判断是否缺失 version sync 或 release-facing 文件
6. 先起草最短但有用的维护者总结
7. 最终只执行一次 `add_comment` 或一次 `noop`
## 额外约束
- 不要要求与本 PR 无关的大重构
- 小型内部变更不要强拉成 release-prep
- 明显是私有/内部改动时,不要强制要求 docs sync
- 优先给出“仓库特定”的反馈,而不是通用 code review 废话
- 如果你不确定某个同步文件是否必需,把级别降为 `Important`
- 如果问题依赖 PR 意图但当前信息不足,要把表述写成“条件性判断”,不要装作确定
## 最终要求
必须以且仅以一次 safe output 结束:
- 有可操作反馈:`add_comment`
- 无可操作反馈:`noop`
## Review 结论
这份英文源工作流目前已经可以作为后续 `gh aw compile` 的候选源文件。
中文镜像的目的只有两个:
- 方便你逐段审阅策略是否符合预期
- 避免把中文说明混进真正要编译的 workflow 源文件

View File

@@ -0,0 +1,275 @@
# aw-release-preflight 中文对照
对应源文件:`.github/workflows/aw-release-preflight.md`
用途:这是一份给维护者 review 用的中文对照说明,不是 gh-aw 工作流源文件,也不参与 `gh aw compile`
## 工作流定位
这个工作流的目标是对触发变更做一次“发布前预检语义审查”。
它不是发布执行器,也不是自动补版本工具,而是用于判断:
- 这次改动是否真的在做 release-prep
- 如果是在做 release-prep版本同步是否完整
- 双语 README、docs 镜像、release notes 是否齐全
- 是否存在会影响发布质量的说明缺失或文档漂移
如果当前变更并不是发布准备,或者已经足够一致、没有可操作反馈,就执行 `noop`
## Frontmatter 对照
### 触发方式
- `pull_request`
- 类型:`opened``reopened``synchronize``ready_for_review`
- 路径限制:
- `plugins/**/*.py`
- `plugins/**/README.md`
- `plugins/**/README_CN.md`
- `plugins/**/v*.md`
- `plugins/**/v*_CN.md`
- `docs/plugins/**/*.md`
- `README.md`
- `README_CN.md`
- `.github/**`
- `workflow_dispatch`
- `roles: all`
- `skip-bots`
- `github-actions`
- `copilot`
- `dependabot`
- `renovate`
### 权限
当前设计为只读:
- `contents: read`
- `issues: read`
- `pull-requests: read`
说明:工作流不会发 release、不会推代码、不会改文件。
### Safe Outputs
已配置:
- `add-comment`
- 目标:当前触发 PR
- 最多 1 条
- 隐藏旧评论
- 不加 footer
最终只能二选一:
- 有问题时执行 `add_comment`
- 无问题时执行 `noop`
### 工具
- `github`
- `repos`
- `issues`
- `pull_requests`
- `bash`
- 仅开放只读类命令,如 `pwd``ls``cat``rg``git diff``git show`
## 正文指令对照
## 主要目标
要求代理检查:
- 版本同步完整性
- 双语 README 与 docs 一致性
- release notes 完整性
- 发布面索引或 badge 漂移
- 用户可见发布是否缺失迁移说明或维护者上下文
明确限制:
- 只做 review
- 不改文件
- 不推代码
- 不创建 release
- 不创建 PR
## 高优先级依据文件
在形成结论前,优先把这些文件当成“发布规则源”:
- `.github/copilot-instructions.md`
- `.github/instructions/commit-message.instructions.md`
- `.github/skills/release-prep/SKILL.md`
- `.github/skills/doc-mirror-sync/SKILL.md`
- `.github/workflows/release.yml`
- `docs/development/gh-aw-integration-plan.md`
- `docs/development/gh-aw-integration-plan.zh.md`
## 审查范围
- 从 PR diff 和 changed files 开始
- 只有在验证发布同步时才扩展到相关 release-facing 文件
- 优先遵循仓库既有 release-prep 规则,而不是泛泛的 release 建议
换句话说,它应该像“合并前最后做一致性复核的维护者”。
## 重点检查项
### 1. 发布相关文件中的版本同步
当某个插件明显在准备发版时,检查这些位置是否同步:
- 插件 Python docstring 的 `version:`
- 插件目录下 `README.md`
- 插件目录下 `README_CN.md`
- `docs/plugins/**` 英文镜像页
- `docs/plugins/**/*.zh.md` 中文镜像页
- `docs/plugins/{type}/index.md` 中该插件的条目或版本 badge
- `docs/plugins/{type}/index.zh.md` 中该插件的条目或版本 badge
但只有在“这次改动明显带有发布意图”时才提示,不要把所有 PR 都按发布处理。
### 2. README 与 docs 镜像一致性
当插件 README 变化时,检查 docs 镜像是否同步。
路径映射:
- `plugins/actions/{name}/README.md` -> `docs/plugins/actions/{name}.md`
- `plugins/actions/{name}/README_CN.md` -> `docs/plugins/actions/{name}.zh.md`
- `plugins/filters/{name}/README.md` -> `docs/plugins/filters/{name}.md`
- `plugins/filters/{name}/README_CN.md` -> `docs/plugins/filters/{name}.zh.md`
- `plugins/pipes/{name}/README.md` -> `docs/plugins/pipes/{name}.md`
- `plugins/pipes/{name}/README_CN.md` -> `docs/plugins/pipes/{name}.zh.md`
- `plugins/pipelines/{name}/README.md` -> `docs/plugins/pipelines/{name}.md`
- `plugins/pipelines/{name}/README_CN.md` -> `docs/plugins/pipelines/{name}.zh.md`
- `plugins/tools/{name}/README.md` -> `docs/plugins/tools/{name}.md`
- `plugins/tools/{name}/README_CN.md` -> `docs/plugins/tools/{name}.zh.md`
如果是纯文档调整、而且并非发版预备,不要过度报错。
### 3. What's New 与 Release Notes 覆盖度
当这次更新明显是发布面插件更新时,检查:
- `What's New` 是否只反映最新版本
- `最新更新` 是否与英文对应
- 是否存在 `v{version}.md``v{version}_CN.md`
- release notes 是否覆盖当前 diff 中有意义的功能、修复、文档或迁移变化
对纯内部小改动,不要强制要求 release notes。
### 4. 根 README 与发布面索引漂移
当改动明显面向正式发布时,再检查:
-`README.md` 的日期 badge
-`README_CN.md` 的日期 badge
- `docs/plugins/**/index.md`
- `docs/plugins/**/index.zh.md`
不要把这种检查强加给普通内部 PR。
### 5. 维护者上下文与发布清晰度
检查 PR 描述或发布面文案是否缺少关键上下文:
- 这次到底发布了什么
- 为什么这次发布值得做
- 是否需要迁移或重新配置
只有在缺失信息会明显增加 release review 成本时,才提示。
## 严重级别
只允许三档:
- `Blocking`
- 高概率发布回归、缺少必要版本同步、发布面更新明显不完整
- `Important`
- 合并前最好修,避免发布混乱或文档漂移
- `Minor`
- 可选的发布面清理或一致性建议
并且明确要求:
- 不要为了留言而造问题
## 评论格式
如果要评论,必须只有一条总结评论。
要求:
- 英文
- 简洁
- 先给 findings不先夸赞
- 带可点击路径引用
- 不使用嵌套列表
- 不要机械复述 diff
固定结构:
```markdown
## Release Preflight Review
### Blocking
- `path/to/file`: specific release-facing problem and why it matters
### Important
- `path/to/file`: missing sync or release-documentation gap
### Minor
- `path/to/file`: optional cleanup or consistency improvement
### Release Readiness
- Ready after the items above are addressed.
```
补充规则:
- 空 section 要省略
- 如果只有一个严重级别,只保留那个 section 和 `Release Readiness`
- 正常情况下控制在约 250 词以内
## No-Comment 规则
如果没有有意义的发布前预检反馈:
- 不要发“看起来不错”这类表扬评论
- 不要复述 checks passed
- 直接走 `noop`
示例:
```json
{"noop": {"message": "No action needed: reviewed the release-facing diff, version-sync expectations, and bilingual documentation coverage, and found no actionable preflight feedback."}}
```
## 建议执行流程
1. 判断这次改动是否真的带有发布意图
2. 检查 PR diff 中的变更文件
3. 读取仓库的 release-prep 规则文件
4. 只有在存在发布意图时,才检查 plugin version sync
5. 检查 README、README_CN、docs 镜像、索引和 release notes 是否漂移
6. 起草最短但有用的维护者总结
7. 最终只执行一次 `add_comment` 或一次 `noop`
## 额外约束
- 不要把完整 release-prep 要求硬套到微小内部改动上
- 非明确发布型 PR不要强制要求根 README 日期 badge 更新
- 如果这次改动并不现实地构成发版预备,就不要强求 release notes
- 优先给出仓库特定的同步反馈,而不是泛泛的发布建议
- 如果不确定某个 release-facing 同步文件是否必需,把级别降为 `Important`
- 如果问题依赖“推测出来的意图”,要用条件式表述,不要装作确定
## 最终要求
必须以且仅以一次 safe output 结束:
- 有可操作反馈:`add_comment`
- 无可操作反馈:`noop`

View 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 `&quot;`.
- **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.

View 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.
```

View 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.

71
.github/skills/README.md vendored Normal file
View File

@@ -0,0 +1,71 @@
# Agent Skills Index
This folder contains reusable Agent Skills for GitHub Copilot / VS Code custom agent workflows.
## Available Skills
- **community-announcer**
- Purpose: Generate community announcement content and related assets.
- Entry: `community-announcer/SKILL.md`
- **doc-mirror-sync**
- Purpose: Sync mirrored documentation content and helper scripts.
- Entry: `doc-mirror-sync/SKILL.md`
- **gh-issue-replier**
- Purpose: Draft standardized issue replies with templates.
- Entry: `gh-issue-replier/SKILL.md`
- **gh-issue-scheduler**
- Purpose: Schedule and discover unanswered issues for follow-up.
- Entry: `gh-issue-scheduler/SKILL.md`
- **i18n-validator**
- Purpose: Validate translation key consistency across i18n dictionaries.
- Entry: `i18n-validator/SKILL.md`
- **plugin-scaffolder**
- Purpose: Scaffold OpenWebUI plugin boilerplate with repository standards.
- Entry: `plugin-scaffolder/SKILL.md`
- **version-bumper**
- Purpose: Assist with semantic version bumping workflows.
- Entry: `version-bumper/SKILL.md`
- **xlsx-single-file**
- Purpose: Single-file spreadsheet operations workflow without LibreOffice.
- Entry: `xlsx-single-file/SKILL.md`
---
## Release Pipeline Skills
These four skills form a complete release pipeline and are designed to be used in sequence:
```
release-prep → pr-submitter → pr-reviewer → release-finalizer
(prepare) (push & PR) (respond to review) (merge & close issue)
```
- **release-prep**
- Purpose: Full release preparation — version sync across 7+ files, bilingual release notes creation, consistency check, and commit.
- Entry: `release-prep/SKILL.md`
- **pr-submitter**
- Purpose: Shell-escape-safe PR submission — writes body to temp file, validates sections, pushes branch, creates PR via `gh pr create --body-file`.
- Entry: `pr-submitter/SKILL.md`
- **pr-reviewer**
- Purpose: Fetch PR review comments, categorize feedback, implement fixes, commit and push, reply to reviewers.
- Entry: `pr-reviewer/SKILL.md`
- **release-finalizer**
- Purpose: Merge release PR to main with proper commit message, auto-link and close related issues, post closing messages.
- Entry: `release-finalizer/SKILL.md`
## Notes
- Skill definitions follow the expected location pattern:
- `.github/skills/<skill-name>/SKILL.md`
- Each skill may include optional `assets/`, `references/`, and `scripts/` folders.
- This directory mirrors `.gemini/skills` for compatibility.

View File

@@ -0,0 +1,23 @@
---
name: community-announcer
description: Drafts engaging English and Chinese update announcements for the OpenWebUI Community and other social platforms. Use when a new version is released.
---
# Community Announcer
## Overview
Automates the drafting of high-impact update announcements.
## Workflow
1. **Source Intel**: Read the latest version's `What's New` section from `README.md`.
2. **Drafting**: Create two versions:
- **Community Post**: Professional, structured, technical.
- **Catchy Short**: For Discord/Twitter, use emojis and bullet points.
3. **Multi-language**: Generate BOTH English and Chinese versions automatically.
## Announcement Structure (Recommended)
- **Headline**: "Update vX.X.X - [Main Feature]"
- **Introduction**: Brief context.
- **Key Highlights**: Bulleted list of fixes/features.
- **Action**: "Download from [Market Link]"
- **Closing**: Thanks and Star request.

50
.github/skills/doc-mirror-sync/SKILL.md vendored Normal file
View File

@@ -0,0 +1,50 @@
---
name: doc-mirror-sync
description: Automatically synchronizes plugin READMEs to the official documentation directory (docs/). Use after editing a plugin's local documentation to keep the MkDocs site up to date.
---
# Doc Mirror Sync
## Overview
Automates the mirroring of `plugins/{type}/{name}/README.md` to `docs/plugins/{type}/{name}.md`.
## Docs-Only Mode (No Release Changes)
Use this mode when the request is "only sync docs".
- Only update documentation mirror files under `docs/plugins/**`.
- Do **not** bump plugin version.
- Do **not** modify plugin code (`plugins/**.py`) unless explicitly requested.
- Do **not** update root badges/dates for release.
- Do **not** run release preparation steps.
## Workflow
1. Identify changed READMEs.
2. Copy content to corresponding mirror paths.
3. Update version badges in `docs/plugins/{type}/index.md`.
## Commands
### Sync all mirrors (EN + ZH)
```bash
python .github/skills/doc-mirror-sync/scripts/sync.py
```
### Sync only one plugin (EN only)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
```
### Sync only one plugin (EN + ZH)
```bash
cp plugins/<type>/<name>/README.md docs/plugins/<type>/<name>.md
cp plugins/<type>/<name>/README_CN.md docs/plugins/<type>/<name>.zh.md
```
## Notes
- If asked for English-only update, sync only `README.md` -> `.md` mirror.
- If both languages are requested, sync both `README.md` and `README_CN.md`.
- After syncing, verify git diff only contains docs file changes.

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env python3
import os
import shutil
import re
def sync_mirrors():
plugins_root = "plugins"
docs_root = "docs/plugins"
types = ["actions", "filters", "pipes", "pipelines", "tools"]
for t in types:
src_type_dir = os.path.join(plugins_root, t)
dest_type_dir = os.path.join(docs_root, t)
if not os.path.exists(src_type_dir): continue
os.makedirs(dest_type_dir, exist_ok=True)
for name in os.listdir(src_type_dir):
plugin_dir = os.path.join(src_type_dir, name)
if not os.path.isdir(plugin_dir): continue
# Sync README.md -> docs/plugins/{type}/{name}.md
src_readme = os.path.join(plugin_dir, "README.md")
if os.path.exists(src_readme):
dest_readme = os.path.join(dest_type_dir, f"{name}.md")
shutil.copy(src_readme, dest_readme)
print(f"✅ Mirrored: {t}/{name} (EN)")
# Sync README_CN.md -> docs/plugins/{type}/{name}.zh.md
src_readme_cn = os.path.join(plugin_dir, "README_CN.md")
if os.path.exists(src_readme_cn):
dest_readme_zh = os.path.join(dest_type_dir, f"{name}.zh.md")
shutil.copy(src_readme_cn, dest_readme_zh)
print(f"✅ Mirrored: {t}/{name} (ZH)")
if __name__ == "__main__":
sync_mirrors()

View File

@@ -0,0 +1,51 @@
---
name: gh-issue-replier
description: Professional English replier for GitHub issues. Use when a task is completed, a bug is fixed, or more info is needed from the user. Automates replying using the 'gh' CLI tool.
---
# Gh Issue Replier
## Overview
The `gh-issue-replier` skill enables Gemini CLI to interact with GitHub issues professionally. It enforces English for all communications and leverages the `gh` CLI to post comments.
## Workflow
1. **Identify the Issue**: Find the issue number (e.g., #49).
2. **Check Star Status**: Run the bundled script to check if the author has starred the repo.
* Command: `bash scripts/check_star.sh <issue-number>`
* Interpretation:
* Exit code **0**: User has starred. Use "Already Starred" templates.
* Exit code **1**: User has NOT starred. Include "Star Request" in the reply.
3. **Select a Template**: Load [templates.md](references/templates.md) to choose a suitable English response pattern.
4. **Draft the Reply**: Compose a concise message based on the star status.
5. **Post the Comment**: Use the `gh` tool to submit the reply.
## Tool Integration
### Check Star Status
```bash
bash scripts/check_star.sh <issue-number>
```
### Post Comment
```bash
gh issue comment <issue-number> --body "<message-body>"
```
Example (if user has NOT starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. If you find this helpful, a star on the repo would be much appreciated! ⭐"
```
Example (if user HAS starred):
```bash
gh issue comment 49 --body "This has been fixed in v1.2.7. Thanks for your support!"
```
## Guidelines
- **Language**: ALWAYS use English for the comment body, even if the system prompt or user conversation is in another language.
- **Tone**: Professional, helpful, and appreciative.
- **Precision**: When announcing a fix, mention the specific version or the logic change (e.g., "Updated regex pattern").
- **Closing**: If the issue is resolved and you have permission, you can also use `gh issue close <number>`.

View File

@@ -0,0 +1,17 @@
# Reference Documentation for Gh Issue Replier
This is a placeholder for detailed reference documentation.
Replace with actual reference content or delete if not needed.
## Structure Suggestions
### API Reference Example
- Overview
- Authentication
- Endpoints with examples
- Error codes
### Workflow Guide Example
- Prerequisites
- Step-by-step instructions
- Best practices

View File

@@ -0,0 +1,45 @@
# Issue Reply Templates
Use these templates to craft professional English replies. Adjust placeholders like `@username`, `v1.2.x`, and `[commit hash]` as needed.
## 1. Acknowledging a New Issue
Use when you first see an issue and want to let the user know you are working on it.
- "Thank you for reporting this! I'm looking into it right now."
- "Thanks for bringing this to my attention. I'll try to reproduce this behavior and get back to you shortly."
## 2. Requesting More Information
Use when you need logs or specific details to fix the bug.
- "Could you please provide the **'Original'** vs **'Normalized'** content from your browser console logs (F12)? It would help a lot in debugging."
- "It would be very helpful if you could share the specific Markdown text that triggered this issue."
## 3. Announcing a Fix
Use when you have pushed the fix to the repository.
- "This has been fixed in version **v1.2.x**. You can update the plugin to resolve it."
- "I've just pushed a fix for this in [commit hash]. Please let me know if it works for you after updating."
- "The issue was caused by a greedy regex pattern. I've updated it to use a tempered greedy token to prevent incorrect merging."
## 4. Guiding to Official Market
Always provide the official market link to ensure the user gets the latest verified version.
- "The fix is now live! You can download the latest version from the official OpenWebUI Community page here: [Plugin Market Link]. Simply update the function in your OpenWebUI instance to apply the changes."
- "I recommend getting the updated version from the official store: [Link]. It includes the fix for the spacing issue we discussed."
## 5. Closing the Issue
Use when the issue is confirmed resolved.
- "Glad to hear it's working now! Closing this for now. Feel free to reopen it if the problem persists."
- "Since this is resolved, I'm closing this issue. Thanks again for your feedback!"
## 5. Pro-tip: Star Request
Gently handle star requests based on the user's current status.
### If User has NOT starred:
- "If you find this plugin helpful, a star on the repo would be much appreciated! ⭐"
- "We'd love your support! If this fixed your issue, please consider starring the repository. ⭐"
### If User HAS already starred:
- "Thanks again for starring the project and for your continuous support!"
- "I appreciate your support and for being a stargazer of this project!"

View File

@@ -0,0 +1,31 @@
#!/usr/bin/env bash
# Robust Star Checker v2
# Usage: ./check_star.sh <issue_number>
ISSUE_NUM=$1
if [ -z "$ISSUE_NUM" ]; then exit 2; fi
# 1. Get Repo and Author info
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + \"/\" + .name")
USER_LOGIN=$(gh issue view "$ISSUE_NUM" --json author -q ".author.login")
# 2. Use GraphQL for high precision (Detects stars even when REST 404s)
IS_STARRED=$(gh api graphql -f query='
query($owner:String!, $repo:String!, $user:String!) {
repository(owner:$owner, name:$repo) {
stargazers(query:$user, first:1) {
nodes {
login
}
}
}
}' -f owner="${REPO_FULL%/*}" -f repo="${REPO_FULL#*/}" -f user="$USER_LOGIN" -q ".data.repository.stargazers.nodes[0].login")
if [ "$IS_STARRED" == "$USER_LOGIN" ]; then
echo "Confirmed: @$USER_LOGIN HAS starred $REPO_FULL. ⭐"
exit 0
else
echo "Confirmed: @$USER_LOGIN has NOT starred $REPO_FULL."
exit 1
fi

View File

@@ -0,0 +1,42 @@
---
name: gh-issue-scheduler
description: Finds all open GitHub issues that haven't been replied to by the owner, summarizes them, and generates a solution plan. Use when the user wants to audit pending tasks or plan maintenance work.
---
# Gh Issue Scheduler
## Overview
The `gh-issue-scheduler` skill helps maintainers track community feedback by identifying unaddressed issues and drafting actionable technical plans to resolve them.
## Workflow
1. **Identify Unanswered Issues**: Run the bundled script to fetch issues without owner replies.
* Command: `bash scripts/find_unanswered.sh`
2. **Analyze and Summarize**: For each identified issue, summarize the core problem and the user's intent.
3. **Generate Solution Plans**: Draft a technical "Action Plan" for each issue, including:
* **Root Cause Analysis** (if possible)
* **Proposed Fix/Implementation**
* **Verification Strategy**
4. **Present to User**: Display a structured report of all pending issues and their respective plans.
## Tool Integration
### Find Unanswered Issues
```bash
bash scripts/find_unanswered.sh
```
## Report Format
When presenting the summary, use the following Markdown structure:
### 📋 Unanswered Issues Audit
#### Issue #[Number]: [Title]
- **Author**: @username
- **Summary**: Concise description of the problem.
- **Action Plan**:
1. Step 1 (e.g., Investigate file X)
2. Step 2 (e.g., Apply fix Y)
3. Verification (e.g., Run test Z)

View File

@@ -0,0 +1,42 @@
#!/usr/bin/env bash
# Fetch all open issues and filter for those without responses from the owner/collaborators.
# Uses 'gh' CLI.
REPO_FULL=$(gh repo view --json owner,name -q ".owner.login + "/" + .name")
OWNER=${REPO_FULL%/*}
# 1. Get all open issues
OPEN_ISSUES=$(gh issue list --state open --json number,title,author,createdAt --limit 100)
echo "Analysis for repository: $REPO_FULL"
echo "------------------------------------"
# Process each issue
echo "$OPEN_ISSUES" | jq -c '.[]' | while read -r issue; do
NUMBER=$(echo "$issue" | jq -r '.number')
TITLE=$(echo "$issue" | jq -r '.title')
AUTHOR=$(echo "$issue" | jq -r '.author.login')
# Check comments for owner responses
# We look for comments where the author is the repo owner
COMMENTS=$(gh issue view "$NUMBER" --json comments -q ".comments[].author.login" 2>/dev/null)
HAS_OWNER_REPLY=false
for COMMENT_AUTHOR in $COMMENTS; do
if [ "$COMMENT_AUTHOR" == "$OWNER" ]; then
HAS_OWNER_REPLY=true
break
fi
done
if [ "$HAS_OWNER_REPLY" == "false" ]; then
echo "ISSUE_START"
echo "ID: $NUMBER"
echo "Title: $TITLE"
echo "Author: $AUTHOR"
echo "Description:"
gh issue view "$NUMBER" --json body -q ".body"
echo "ISSUE_END"
fi
done

14
.github/skills/i18n-validator/SKILL.md vendored Normal file
View File

@@ -0,0 +1,14 @@
---
name: i18n-validator
description: Validates multi-language consistency in the TRANSLATIONS dictionary of a plugin. Use to check if any language keys are missing or if translations need updating.
---
# I18n Validator
## Overview
Ensures all 12 supported languages (en-US, zh-CN, etc.) have aligned translation keys.
## Features
- Detects missing keys in non-English dictionaries.
- Suggests translations using the core AI engine.
- Validates the `fallback_map` for variant redirects.

View File

@@ -0,0 +1,54 @@
#!/usr/bin/env python3
import sys
import ast
import os
def check_i18n(file_path):
if not os.path.exists(file_path):
print(f"Error: File not found {file_path}")
return
with open(file_path, 'r', encoding='utf-8') as f:
tree = ast.parse(f.read())
translations = {}
for node in tree.body:
if isinstance(node, ast.Assign):
for target in node.targets:
if isinstance(target, ast.Name) and target.id == "TRANSLATIONS":
translations = ast.literal_eval(node.value)
break
if not translations:
print("⚠️ No TRANSLATIONS dictionary found.")
return
# Base keys from English
base_lang = "en-US"
if base_lang not in translations:
print(f"❌ Error: {base_lang} missing in TRANSLATIONS.")
return
base_keys = set(translations[base_lang].keys())
print(f"🔍 Analyzing {file_path}...")
print(f"Standard keys ({len(base_keys)}): {', '.join(sorted(base_keys))}
")
for lang, keys in translations.items():
if lang == base_lang: continue
lang_keys = set(keys.keys())
missing = base_keys - lang_keys
extra = lang_keys - base_keys
if missing:
print(f"{lang}: Missing {len(missing)} keys: {', '.join(missing)}")
if extra:
print(f"⚠️ {lang}: Has {len(extra)} extra keys: {', '.join(extra)}")
if not missing and not extra:
print(f"{lang}: Aligned.")
if __name__ == "__main__":
if len(sys.argv) < 2:
print("Usage: validate_i18n.py <path_to_plugin.py>")
sys.exit(1)
check_i18n(sys.argv[1])

View File

@@ -0,0 +1,19 @@
---
name: plugin-scaffolder
description: Generates a standardized single-file i18n Python plugin template based on project standards. Use when starting a new plugin development to skip boilerplate writing.
---
# Plugin Scaffolder
## Overview
Generates compliant OpenWebUI plugin templates with built-in i18n, common utility methods, and required docstring fields.
## Usage
1. Provide the **Plugin Name** and **Type** (action/filter/pipe).
2. The skill will generate the `.py` file and the bilingual `README` files.
## Template Standard
- `Valves(BaseModel)` with `UPPER_SNAKE_CASE`
- `_get_user_context` with JS fallback and timeout
- `_emit_status` and `_emit_debug_log` methods
- Standardized docstring metadata

View File

@@ -0,0 +1,34 @@
# {{TITLE}}
**Author:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **Version:** 0.1.0 | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **License:** MIT
{{DESCRIPTION}}
## 🔥 What's New in v0.1.0
* Initial release of {{TITLE}}.
## 🌐 Multilingual Support
Supports automatic interface and status switching for the following languages:
`English`, `简体中文`, `繁體中文 (香港)`, `繁體中文 (台灣)`, `한국어`, `日本語`, `Français`, `Deutsch`, `Español`, `Italiano`, `Tiếng Việt`, `Bahasa Indonesia`.
## ✨ Core Features
* Feature 1
* Feature 2
## How to Use 🛠️
1. Install the plugin in Open WebUI.
2. Configure settings in Valves.
## Configuration (Valves) ⚙️
| Parameter | Default | Description |
| :--- | :--- | :--- |
| `priority` | `50` | Execution priority. |
## ⭐ Support
If this plugin has been useful, a star on [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) is a big motivation for me. Thank you for the support.

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,80 @@
"""
title: {{TITLE}}
author: Fu-Jie
author_url: https://github.com/Fu-Jie/openwebui-extensions
funding_url: https://github.com/open-webui
version: 0.1.0
description: {{DESCRIPTION}}
"""
import asyncio
import logging
import json
from typing import Optional, Dict, Any, List, Callable, Awaitable
from pydantic import BaseModel, Field
from fastapi import Request
# Configure logging
logging.basicConfig(level=logging.INFO, format="%(asctime)s - %(name)s - %(levelname)s - %(message)s")
logger = logging.getLogger(__name__)
TRANSLATIONS = {
"en-US": {"status_starting": "Starting {{TITLE}}..."},
"zh-CN": {"status_starting": "正在启动 {{TITLE}}..."},
"zh-HK": {"status_starting": "正在啟動 {{TITLE}}..."},
"zh-TW": {"status_starting": "正在啟動 {{TITLE}}..."},
"ko-KR": {"status_starting": "{{TITLE}} 시작 중..."},
"ja-JP": {"status_starting": "{{TITLE}} を起動中..."},
"fr-FR": {"status_starting": "Démarrage de {{TITLE}}..."},
"de-DE": {"status_starting": "{{TITLE}} wird gestartet..."},
"es-ES": {"status_starting": "Iniciando {{TITLE}}..."},
"it-IT": {"status_starting": "Avvio di {{TITLE}}..."},
"vi-VN": {"status_starting": "Đang khởi động {{TITLE}}..."},
"id-ID": {"status_starting": "Memulai {{TITLE}}..."},
}
class {{CLASS_NAME}}:
class Valves(BaseModel):
priority: int = Field(default=50, description="Priority level (lower = earlier).")
show_status: bool = Field(default=True, description="Show status updates in UI.")
def __init__(self):
self.valves = self.Valves()
self.fallback_map = {
"zh": "zh-CN", "en": "en-US", "ko": "ko-KR", "ja": "ja-JP",
"fr": "fr-FR", "de": "de-DE", "es": "es-ES", "it": "it-IT",
"vi": "vi-VN", "id": "id-ID"
}
def _get_translation(self, lang: str, key: str, **kwargs) -> str:
target_lang = lang
if target_lang not in TRANSLATIONS:
base = target_lang.split("-")[0]
target_lang = self.fallback_map.get(base, "en-US")
lang_dict = TRANSLATIONS.get(target_lang, TRANSLATIONS["en-US"])
text = lang_dict.get(key, TRANSLATIONS["en-US"].get(key, key))
return text.format(**kwargs) if kwargs else text
async def _get_user_context(self, __user__: Optional[dict], __event_call__: Optional[Callable] = None, __request__: Optional[Request] = None) -> dict:
user_data = __user__ if isinstance(__user__, dict) else {}
user_language = user_data.get("language", "en-US")
if __event_call__:
try:
js = "try { return (document.documentElement.lang || localStorage.getItem('locale') || navigator.language || 'en-US'); } catch (e) { return 'en-US'; }"
frontend_lang = await asyncio.wait_for(__event_call__({"type": "execute", "data": {"code": js}}), timeout=2.0)
if frontend_lang: user_language = frontend_lang
except: pass
return {"user_language": user_language}
async def {{METHOD_NAME}}(self, body: dict, __user__: Optional[dict] = None, __event_emitter__=None, __event_call__=None, __request__: Optional[Request] = None) -> dict:
if self.valves.show_status and __event_emitter__:
user_ctx = await self._get_user_context(__user__, __event_call__, __request__)
msg = self._get_translation(user_ctx["user_language"], "status_starting")
await __event_emitter__({"type": "status", "data": {"description": msg, "done": False}})
# Implement core logic here
if self.valves.show_status and __event_emitter__:
await __event_emitter__({"type": "status", "data": {"description": "Done", "done": True}})
return body

View File

@@ -0,0 +1,66 @@
#!/usr/bin/env python3
import sys
import os
def scaffold(p_type, p_name, title, desc):
target_dir = f"plugins/{p_type}/{p_name}"
os.makedirs(target_dir, exist_ok=True)
class_name = (
"Action"
if p_type == "actions"
else (
"Filter"
if p_type == "filters"
else "Tools" if p_type == "tools" else "Pipe"
)
)
method_name = (
"action"
if p_type == "actions"
else (
"outlet"
if p_type == "filters"
else "execute" if p_type == "tools" else "pipe"
)
)
replacements = {
"{{TITLE}}": title,
"{{DESCRIPTION}}": desc,
"{{CLASS_NAME}}": class_name,
"{{METHOD_NAME}}": method_name,
}
# Files to generate
templates = [
("assets/template.py.j2", f"{p_name}.py"),
("assets/README_template.md", "README.md"),
("assets/README_template.md", "README_CN.md"),
]
# Path relative to skill root
skill_root = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
for t_path, t_name in templates:
template_file = os.path.join(skill_root, t_path)
if not os.path.exists(template_file):
print(f"⚠️ Warning: Template not found {template_file}")
continue
with open(template_file, "r") as f:
content = f.read()
for k, v in replacements.items():
content = content.replace(k, v)
with open(os.path.join(target_dir, t_name), "w") as f:
f.write(content)
print(f"✅ Generated: {target_dir}/{t_name}")
if __name__ == "__main__":
if len(sys.argv) < 5:
print("Usage: scaffold.py <type> <name> <title> <desc>")
sys.exit(1)
scaffold(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])

180
.github/skills/pr-reviewer/SKILL.md vendored Normal file
View File

@@ -0,0 +1,180 @@
---
name: pr-reviewer
description: Fetches PR review comments, analyzes requested changes, implements fixes, commits and pushes the resolution. Use after a reviewer has left comments on an open PR to close the feedback loop efficiently.
---
# PR Reviewer
## Overview
This skill automates the response cycle for code review. When a reviewer leaves comments on a Pull Request, this skill fetches all pending feedback, categorizes issues by severity, implements fixes, and submits a follow-up commit with appropriate review response comments.
## Prerequisites
- An open PR exists with pending review comments
- The local branch matches the PR's head branch
- `gh` CLI is authenticated
---
## Workflow
### Step 1 — Fetch Review State
Retrieve all review comments and overall review status:
```bash
# Get overall review decisions
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json reviews,reviewDecision,headRefName \
--jq '{decision: .reviewDecision, reviews: [.reviews[] | {author: .author.login, state: .state, body: .body}]}'
# Get inline code comments (specific line comments)
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments \
--jq '[.[] | {path: .path, line: .line, body: .body, author: .user.login, id: .id}]'
# Get general issue comments
PAGER=cat GH_PAGER=cat gh issue view <PR-NUMBER> --comments --json comments \
--jq '[.comments[] | {author: .author.login, body: .body}]'
```
Confirm the current local branch matches the PR head:
```bash
git branch --show-current
```
If mismatched, checkout the correct branch first.
### Step 2 — Categorize Review Feedback
Group feedback into categories:
| Category | Examples | Action |
|----------|---------|--------|
| **Code Bug** | Logic error, incorrect variable, broken condition | Fix code immediately |
| **Style / Formatting** | Indentation, naming convention, missing blank line | Fix code |
| **Documentation** | Missing i18n key, wrong version in README, typo | Fix docs |
| **Design Question** | Suggestion to restructure, alternative approach | Discuss with user before implementing |
| **Nitpick / Optional** | Minor style preferences reviewer marked as optional | Fix if quick; document if skipped |
| **Blocking** | Reviewer explicitly blocks merge | Must fix before proceeding |
Present the full categorized list to the user and confirm the resolution plan.
### Step 3 — Implement Fixes
For each accepted fix:
1. Read the affected file at the commented line for context:
```bash
sed -n '<line-5>,<line+10>p' <file-path>
```
2. Apply the fix using appropriate file edit tools
3. After editing, verify the specific area looks correct
**For code changes that might affect behavior:**
- Check if tests exist: `ls tests/test_*.py`
- If tests exist, run them: `python -m pytest tests/ -v`
**For documentation fixes:**
- If modifying README.md, check if `docs/` mirror needs the same fix
- Apply the same fix to both locations
### Step 4 — Run Consistency Checks
After all fixes are applied:
```bash
# Version consistency (if any version files were touched)
python3 scripts/check_version_consistency.py
# Quick syntax check for Python files
python3 -m py_compile plugins/{type}/{name}/{name}.py && echo "✅ Syntax OK"
```
### Step 5 — Stage and Commit
Create a new commit (do NOT amend if the branch has already been pushed, to avoid force-push):
```bash
git add -A
git status
```
Draft a Conventional Commits message for the fixup:
Format: `fix(scope): address review feedback`
Body should list what was fixed, referencing reviewer concerns:
```
fix(github-copilot-sdk): address review feedback from @reviewer
- Fix X per review comment on line Y of file Z
- Update README to clarify auth requirement
- Correct edge case in _parse_mcp_servers logic
```
```bash
git commit -m "<fixup commit message>"
```
### Step 6 — Push the Fix Commit
```bash
git push origin $(git branch --show-current)
```
**Force-push policy:**
- Use `git push` (non-force) by default
- Only use `git push --force-with-lease` if:
1. The user explicitly requests it, AND
2. The only change is an amended commit squash (cosmetic, no logic change)
3. Never use `--force` (without `--lease`)
### Step 7 — Respond to Reviewers
For each addressed review comment, post a reply:
```bash
# Reply to inline comment
gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/comments/<COMMENT-ID>/replies \
-X POST -f body="Fixed in commit <SHORT-SHA>. <Brief explanation of what was changed.>"
# General comment to summarize all fixes
gh issue comment <PR-NUMBER> --body "All review feedback addressed in commit <SHORT-SHA>:
- Fixed: <item 1>
- Fixed: <item 2>
Ready for re-review. 🙏"
```
### Step 8 — Re-Request Review (Optional)
If the reviewer had submitted a `CHANGES_REQUESTED` review, request a new review after fixes:
```bash
PAGER=cat GH_PAGER=cat gh api repos/Fu-Jie/openwebui-extensions/pulls/<PR-NUMBER>/requested_reviewers \
-X POST -f reviewers[]='<reviewer-login>'
```
---
## Decision Guide
### When NOT to implement a suggestion immediately
- **Design questions**: "Should this be a separate class?" — Present to user for decision
- **Optional nitpicks**: Reviewer marked as `nit:` — Ask user if they want to include it
- **Large refactors**: If fix would require changing >50 lines, propose a separate follow-up issue instead
### When to ask the user before proceeding
- Any fix involving behavioral changes to plugin logic
- Renaming Valve keys (breaking change — requires migration notes)
- Changes that affect the bilingual release notes already committed
---
## Anti-Patterns to Avoid
- ❌ Do NOT `git commit --amend` on a pushed commit without user approval for force-push
- ❌ Do NOT silently skip a reviewer's comment; always acknowledge it (implement or explain why not)
- ❌ Do NOT use `--force` (only `--force-with-lease` when absolutely necessary)
- ❌ Do NOT make unrelated changes in the fixup commit; keep scope focused on review feedback
- ❌ Do NOT respond to reviewer comments in Chinese if the PR language context is English

194
.github/skills/pr-submitter/SKILL.md vendored Normal file
View File

@@ -0,0 +1,194 @@
---
name: pr-submitter
description: Submits a feature branch as a Pull Request with a validated, properly formatted bilingual PR body. Handles shell-escape-safe body writing via temp files. Use after release-prep has committed all changes.
---
# PR Submitter
## Overview
This skill handles the final step of pushing a feature branch and creating a validated Pull Request on GitHub. Its primary purpose is to avoid the shell-escaping pitfalls (backticks, special characters in `gh pr create --body`) by always writing the PR body to a **temp file** first.
## Prerequisites
- All changes are committed (use `release-prep` skill first)
- The `gh` CLI is authenticated (`gh auth status`)
- Current branch is NOT `main` or `master`
---
## Workflow
### Step 0 — Initialize Temp Directory (Project-Based)
For all temporary files, use the project's `.temp/` directory instead of system `/tmp`:
```bash
# Create temp directory if it doesn't exist
mkdir -p .temp
```
**Why**: All temporary files stay within the project workspace, avoiding system `/tmp` pollution and better aligning with OpenWebUI workspace isolation principles.
### Step 1 — Pre-Flight Checks
Run these checks before any push:
```bash
# 1. Confirm not on protected branch
git branch --show-current
# 2. Verify there are commits to push
git log origin/$(git branch --show-current)..HEAD --oneline 2>/dev/null || echo "No remote tracking branch yet"
# 3. Check gh CLI auth
gh auth status
```
If any check fails, stop and report clearly.
### Step 2 — Collect PR Metadata
Gather:
- **PR Title**: Must follow Conventional Commits format, English only (e.g., `feat(github-copilot-sdk): release v0.8.0 with conditional tool filtering`)
- **Target base branch**: Default is `main`
- **Plugin name + version** (to build body sections)
- **Key changes** (reuse from release-prep or the latest What's New section)
### Step 3 — Build PR Body File (Shell-Escape-Safe)
**Always write the body to a temp file in `.temp/` directory.** Never embed multi-line markdown with special characters directly in a shell command.
```bash
cat > .temp/pr_body.md << 'HEREDOC'
## Summary
Brief one-sentence description of what this PR accomplishes.
## Changes
### New Features
- Feature 1 description
- Feature 2 description
### Bug Fixes
- Fix 1 description
## Plugin Version
- `PluginName` bumped to `vX.X.X`
## Documentation
- README.md / README_CN.md updated
- docs/ mirrors synced
## Testing
- [ ] Tested locally in OpenWebUI
- [ ] i18n validated (all language keys present)
- [ ] Version consistency check passed (`python3 scripts/check_version_consistency.py`)
---
## 变更摘要(中文)
简要描述本次 PR 的改动内容。
### 新功能
- 功能1描述
- 功能2描述
### 问题修复
- 修复1描述
HEREDOC
```
**Critical rules for the body file:**
- Use `<< 'HEREDOC'` (quoted heredoc) to prevent variable expansion
- Keep all backticks literal — they are safe inside a heredoc
- Paths like `/api/v1/files/` are safe too since heredoc doesn't interpret them as commands
### Step 4 — Validate PR Body
Before submitting, verify the body file contains expected sections:
```bash
# Check key sections exist
grep -q "## Summary" .temp/pr_body.md && echo "✅ Summary" || echo "❌ Summary missing"
grep -q "## Changes" .temp/pr_body.md && echo "✅ Changes" || echo "❌ Changes missing"
grep -q "## 变更摘要" .temp/pr_body.md && echo "✅ CN Section" || echo "❌ CN Section missing"
# Preview the body
cat .temp/pr_body.md
```
Ask the user to confirm the body content before proceeding.
### Step 5 — Push Branch
```bash
git push -u origin $(git branch --show-current)
```
If push is rejected (non-fast-forward), report to user and ask whether to force-push. **Do NOT force-push without explicit confirmation.**
### Step 6 — Create Pull Request
```bash
gh pr create \
--base main \
--head $(git branch --show-current) \
--title "<PR title from Step 2>" \
--body-file .temp/pr_body.md
```
Always use `--body-file`, never `--body` with inline markdown.
### Step 7 — Verify PR Creation
```bash
PAGER=cat GH_PAGER=cat gh pr view --json number,url,title,body --jq '{number: .number, url: .url, title: .title, body_preview: .body[:200]}'
```
Confirm:
- PR number and URL
- Title matches intended Conventional Commits format
- Body preview includes key sections (not truncated/corrupted)
If the body appears corrupted (empty sections, missing backtick content), use edit:
```bash
gh pr edit <PR-NUMBER> --body-file /tmp/pr_body.md
```
### Step 8 — Cleanup
```bash
rm -f .temp/pr_body.md
```
**Note**: The `.temp/` directory itself is preserved for reuse; only the individual PR body file is deleted. To fully clean up: `rm -rf .temp/`
Report final PR URL to the user.
---
## Shell-Escape Safety Rules
| Risk | Safe Approach |
|------|--------------|
| Backticks in `--body` | Write to file, use `--body-file` |
| Paths like `/api/...` | Safe in heredoc; risky in inline `--body` |
| Newlines in `--body` | File-based only |
| `$variable` expansion | Use `<< 'HEREDOC'` (quoted) |
| Double quotes in body | Safe in heredoc file |
| Temp file storage | Use `.temp/` dir, not `/tmp` |
| Cleanup after use | Always delete temp file (keep dir) |
---
## Anti-Patterns to Avoid
- ❌ Never use `--body "..."` with multi-line content directly in shell command
- ❌ Never interpolate variables directly into heredoc without quoting the delimiter
- ❌ Never force-push (`--force`) without explicit user confirmation
- ❌ Never target `main` as the source branch (only as base)
- ❌ Never skip the body validation step — a PR with empty body is worse than a delayed PR

View File

@@ -0,0 +1,208 @@
---
name: release-finalizer
description: Merges a release PR, associates it with resolved issues, replies to issue reporters, and closes issues. Use after PR review is complete and ready for merge. Closes the release cycle.
---
# Release Finalizer
## Overview
This skill completes the final step of the release cycle: merging the release PR to `main`, replying to all related issues with solutions, and automatically closing them using GitHub's issue linking mechanism.
## Prerequisites
- The PR is in `OPEN` state and ready to merge
- All status checks have passed (CI green)
- All review feedback has been addressed
- The PR relates to one or more GitHub issues (either in PR description or through commits)
---
## Workflow
### Step 1 — Pre-Merge Verification
Verify that the PR is ready:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json state,statusCheckRollup,reviewDecision
```
Checklist:
-`state` is `OPEN`
-`statusCheckRollup` all have `conclusion: SUCCESS`
-`reviewDecision` is `APPROVED` or empty (no blocking reviews)
If any check fails, **do NOT merge**. Report the issue to the user.
### Step 2 — Identify Related Issues
Issues can be linked to a PR in multiple ways. Check the PR description and commit messages for keywords:
```bash
PAGER=cat GH_PAGER=cat gh pr view <PR-NUMBER> --json body,commits
```
Look for patterns like:
- `Closes #XX`, `Fixes #XX`, `Resolves #XX` (in description or commit bodies)
- `#XX` mentioned as "related to" or "addresses"
**Manual input**: If issue links are not in the PR, ask the user which issue(s) this PR resolves.
Extract all issue numbers into a list: `[#48, #52, ...]`
### Step 3 — Select Merge Strategy
Offer the user three options:
| Strategy | Git Behavior | Use Case |
|----------|-------------|----------|
| **Squash** | All commits squashed into one commit on main | Clean history, recommended for release PRs |
| **Rebase** | Linear history, no merge commit | Preserve commit granularity |
| **Merge** | Merge commit created | Preserve full PR context |
**Recommendation for release PRs**: Use `--squash` to create a single clean commit.
If user doesn't specify, default to `--squash`.
### Step 4 — Prepare Merge Commit Message
If using `--squash`, craft a single comprehensive commit message:
**Format** (Conventional Commits + Github linking):
```
type(scope): description
- Bullet point 1
- Bullet point 2
Closes #48
Closes #52
```
The `Closes #XX` keyword tells GitHub to automatically close those issues when the commit lands on `main`.
Example:
```
feat(pipes,filters): release Copilot SDK Pipe v0.8.0 and Files Filter v0.1.3
- Implement P1~P4 conditional tool filtering system
- Fix file publishing reliability across all storage backends
- Add strict file URL validation
- Update bilingual documentation
Closes #48
```
### Step 5 — Execute Merge
```bash
gh pr merge <PR-NUMBER> \
--squash \
--delete-branch \
-m "type(scope): description" \
-b "- Bullet 1\n- Bullet 2\n\nCloses #48"
```
**Key flags:**
- `--squash`: Squash commits (recommended for releases)
- `--delete-branch`: Delete the feature branch after merge
- `-m`: Commit subject
- `-b`: Commit body (supports `\n` for newlines)
Confirm the merge is successful; GitHub will automatically close related issues with `Closes #XX` keyword.
### Step 6 — Verify Auto-Close
GitHub automatically closes issues when a commit with `Closes #XX` lands on the default branch (`main`).
To verify:
```bash
PAGER=cat GH_PAGER=cat gh issue view <ISSUE-NUMBER> --json state
```
Should show `state: CLOSED`.
### Step 7 — Post Closing Message (Optional but Recommended)
For better UX, manually post a summary comment to **each issue** before it auto-closes (since auto-close happens silently):
```bash
gh issue comment <ISSUE-NUMBER> --body "
This has been fixed in PR #<PR-NUMBER>, which is now merged to main.
**Solution Summary:**
- <Key fix 1>
- <Key fix 2>
The fix will be available in the next plugin release. Thank you for reporting! ⭐
"
```
### Step 8 — (Optional) Regenerate Release Notes
If the merge revealed any final tweaks to release notes:
```bash
# Re-export release notes from merged commit
git log --oneline -1 <merged-commit-sha>
```
If needed, create a follow-up PR with doc polish (do NOT force-push the merged commit).
---
## Merge Strategy Decision Tree
```
Is this a patch/hotfix release?
├─ YES → Use --squash
└─ NO → Multi-feature release?
├─ YES → Use --squash (cleaner history)
└─ NO → Preserve detail?
├─ YES → Use --rebase
└─ NO → Use --merge (preserve PR context)
```
---
## Issue Auto-Close Keywords
These keywords in commit/PR messages will auto-close issues when merged to `main`:
- `Closes #XX`
- `Fixes #XX`
- `Resolves #XX`
- `close #XX` (case-insensitive)
- `fix #XX`
- `resolve #XX`
**Important**: The keyword must be on the **final commit that lands on** `main`. For squash merges, it must be in the squash commit message body.
---
## Anti-Patterns to Avoid
- ❌ Do NOT merge if any status checks are PENDING or FAILED
- ❌ Do NOT merge if there are blocking reviews (reviewDecision: `CHANGES_REQUESTED`)
- ❌ Do NOT merge without verifying the Conventional Commits format in the merge message
- ❌ Do NOT merge without including `Closes #XX` keywords for all related issues
- ❌ Do NOT assume issues will auto-close silently — post a courtesy comment first
- ❌ Do NOT delete the branch if it might be needed for cherry-pick or hotfixes later
---
## Troubleshooting
### Issue did not auto-close after merge
- Verify the `Closes #XX` keyword is in the **final commit message** (use `git log` to check)
- Ensure the commit is on the `main` branch
- GitHub sometimes takes a few seconds to process; refresh the issue page
### Multiple issues to close
- List all in separate `Closes #XX` lines in the commit body
- Each one will be independently auto-closed
### Want to close issue without merge?
- Use `gh issue close <ISSUE-NUMBER>` manually
- Only recommended if the PR was manually reverted or deemed invalid

157
.github/skills/release-prep/SKILL.md vendored Normal file
View File

@@ -0,0 +1,157 @@
---
name: release-prep
description: Orchestrates the full release preparation flow for a plugin — version sync across 7+ files, bilingual release notes creation, and commit message drafting. Use before submitting a PR. Does NOT push or create a PR; that is handled by pr-submitter.
---
# Release Prep
## Overview
This skill drives the complete pre-PR release pipeline. It enforces the repository rule that every release must synchronize the version number and changelog across **at least 7 locations** before a commit is created.
## Scope
This skill covers:
1. Version sync (delegates detail to `version-bumper` if needed)
2. Bilingual release notes file creation
3. 7-location consistency verification
4. Conventional Commits message drafting
5. `git add -A && git commit` execution
It **stops before** `git push` or `gh pr create`. Use the `pr-submitter` skill for those steps.
### Temporary File Convention
Any temporary files created during release prep (e.g., draft changelogs) must:
- Be written to the project's `.temp/` directory, **NOT** system `/tmp`
- Be cleaned up before commit using `rm -f .temp/file_name`
- Never be committed to git (add `.temp/` to `.gitignore`)
---
## Workflow
### Step 1 — Collect Release Info
Ask the user (or infer from current state) the following:
- **Plugin name** and **type** (actions / filters / pipes / tools)
- **New version number** (e.g., `0.8.0`)
- **Key changes** in English and Chinese (1-5 bullet points each)
If a `What's New` section already exists in README.md, extract it as the source of truth.
### Step 2 — Sync Version Across 7 Locations
Verify AND update the version string in all of the following. Mark each as ✅ or ❌:
| # | File | Location |
|---|------|----------|
| 1 | `plugins/{type}/{name}/{name}.py` | `version:` in docstring |
| 2 | `plugins/{type}/{name}/README.md` | `**Version:** x.x.x` metadata line |
| 3 | `plugins/{type}/{name}/README_CN.md` | `**Version:** x.x.x` metadata line |
| 4 | `docs/plugins/{type}/{name}.md` | `**Version:** x.x.x` metadata line |
| 5 | `docs/plugins/{type}/{name}.zh.md` | `**Version:** x.x.x` metadata line |
| 6 | `docs/plugins/{type}/index.md` | version badge for this plugin |
| 7 | `docs/plugins/{type}/index.zh.md` | version badge for this plugin |
Additionally update the root-level **updated date badge** in:
- `README.md``![updated](https://img.shields.io/badge/YYYY--MM--DD-gray?style=flat)`
- `README_CN.md` — same badge format
Use today's date (`YYYY-MM-DD`) for the badge.
### Step 3 — Update What's New (All 4 Doc Files)
The `What's New` / `最新更新` section must contain **only the most recent release's changes**. Previous entries should be removed from this section (they live in CHANGELOG or release notes files).
Update these 4 files' `What's New` / `最新更新` block consistently:
- `plugins/{type}/{name}/README.md`
- `plugins/{type}/{name}/README_CN.md`
- `docs/plugins/{type}/{name}.md`
- `docs/plugins/{type}/{name}.zh.md`
### Step 4 — Create Bilingual Release Notes Files
Create two versioned release notes files:
**Path**: `plugins/{type}/{name}/v{version}.md`
**Path**: `plugins/{type}/{name}/v{version}_CN.md`
#### Required Sections
Each file must include:
1. **Title**: `# v{version} Release Notes` (EN) / `# v{version} 版本发布说明` (CN)
2. **Overview**: One paragraph summarizing this release
3. **New Features** / **新功能**: Bulleted list of features
4. **Bug Fixes** / **问题修复**: Bulleted list of fixes
5. **Migration Notes** / **迁移说明**: Breaking changes or Valve key renames (omit section if none)
6. **Companion Plugins** / **配套插件** (optional): If a companion plugin was updated
If a release notes file already exists for this version, update it rather than creating a new one.
#### Full Coverage Rule (Mandatory)
Release notes must cover **all updates in the current release scope** and not only headline features.
Minimum required coverage in both EN/CN files:
- New features and capability enhancements
- Bug fixes and reliability fixes
- Documentation/README/doc-mirror updates that affect user understanding or usage
- Terminology/i18n/wording fixes that change visible behavior or messaging
Before commit, cross-check release notes against `git diff` and ensure no meaningful update is omitted.
### Step 5 — Verify Consistency (Pre-Commit Check)
Run the consistency check script:
```bash
python3 scripts/check_version_consistency.py
```
If issues are found, fix them before proceeding. Do not commit with inconsistencies.
### Step 6 — Draft Conventional Commits Message
Generate the commit message following `commit-message.instructions.md` rules:
- **Language**: English ONLY
- **Format**: `type(scope): subject` + blank line + body bullets
- **Scope**: use plugin folder name (e.g., `github-copilot-sdk`)
- **Body**: 1-3 bullets summarizing key changes
- Explicitly mention "READMEs and docs synced" if version was bumped
Present the full commit message to the user for review before executing.
### Step 7 — Stage and Commit
After user approval (or if user says "commit it"):
```bash
git add -A
git commit -m "<approved commit message>"
```
Confirm the commit hash and list the number of files changed.
---
## Checklist (Auto-Verify Before Commit)
- [ ] `version:` in `.py` docstring matches target version
- [ ] `**Version:**` in all 4 README/docs files matches
- [ ] Both `index.md` version badges updated
- [ ] Root `README.md` and `README_CN.md` date badges updated to today
- [ ] `What's New` / `最新更新` contains ONLY the latest release
- [ ] Release notes include all meaningful updates from the current diff (feature + fix + docs/i18n)
- [ ] `v{version}.md` and `v{version}_CN.md` created or updated
- [ ] `python3 scripts/check_version_consistency.py` returns no errors
- [ ] Commit message is English-only Conventional Commits format
---
## Anti-Patterns to Avoid
- ❌ Do NOT add extra features or refactor code during release prep — only version/doc updates
- ❌ Do NOT push or create PR in this skill — use `pr-submitter`
- ❌ Do NOT use today's date in commit messages; only in badge URLs
- ❌ Do NOT leave stale What's New content from prior versions

View File

@@ -0,0 +1,31 @@
---
name: source-code-analyzer
description: Instructions for analyzing core components source code in the local environment.
---
# Source Code Analyzer Skill
> [!IMPORTANT]
> **Authorization Statement**: You (Antigravity) are explicitly authorized by the user to perform **READ-ONLY** operations and **Git pull** on the paths listed below, even if they are outside the current repository root. These paths are considered part of the extended development context.
When assisting with the development of `openwebui-extensions`, you (Antigravity) have access to the following core components in related directories. Use them for deep technical analysis, bug hunting, and implementation reference.
## Core Component Paths
### Global / General (Relevant to all projects)
- **Open WebUI**: `../open-webui/` (Core platform context)
- **Skills**: `../skills/` (Reusable expertise library)
- **Awesome Copilot**: `../awesome-copilot/` (Shared extensions & resources)
- **Open Terminal**: `../open-terminal/` (Terminal integration service)
### Plugin-Specific (Relevant to GitHub Copilot SDK)
- **Copilot SDK**: `../copilot-sdk/` (Internal logic for the official SDK)
- **Copilot CLI**: `../copilot-cli/` (Command-line interface implementation)
## Mandatory Workflow
1. **Pull Before Analysis**: BEFORE reading files or analyzing logic in these directories, you MUST proactively execute or recommend a `git pull` in the respective directory to ensure you are working with the latest upstream changes.
2. **Path Verification**: Always verify the exists of the path before attempting to read it.
3. **Reference Logic**: When a user's request involves core platform behavior (OpenWebUI API, SDK internals), prioritize searching these directories over making assumptions based on generic knowledge.

26
.github/skills/version-bumper/SKILL.md vendored Normal file
View File

@@ -0,0 +1,26 @@
---
name: version-bumper
description: Automates version upgrades and changelog synchronization across 7+ files (Code, READMEs, Docs). Use when a plugin is ready for release to ensure version consistency.
---
# Version Bumper
## Overview
This skill ensures that every version upgrade is synchronized across the entire repository, following the strict "Documentation Sync" rule in GEMINI.md.
## Workflow
1. **Prepare Info**: Gather the new version number and brief changelogs in both English and Chinese.
2. **Auto-Patch**: The skill will help you identify and update:
- `plugins/.../name.py` (docstring version)
- `plugins/.../README.md` (metadata & What's New)
- `plugins/.../README_CN.md` (metadata & 最新更新)
- `docs/plugins/...md` (mirrors)
- `docs/plugins/index.md` (version badge)
- `README.md` (updated date badge)
3. **Verify**: Check the diffs to ensure no formatting was broken.
## Tool Integration
Execute the bump script (draft):
```bash
python3 scripts/bump.py <version> "<message_en>" "<message_zh>"
```

View File

@@ -0,0 +1,70 @@
#!/usr/bin/env python3
import sys
import os
import re
from datetime import datetime
def patch_file(file_path, old_pattern, new_content, is_regex=False):
if not os.path.exists(file_path):
print(f"Warning: File not found: {file_path}")
return False
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
if is_regex:
new_content_result = re.sub(old_pattern, new_content, content, flags=re.MULTILINE)
else:
new_content_result = content.replace(old_pattern, new_content)
if new_content_result != content:
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content_result)
print(f"✅ Patched: {file_path}")
return True
else:
print(f" No change needed: {file_path}")
return False
def bump_version(plugin_type, plugin_name, new_version, msg_en, msg_zh):
print(f"🚀 Bumping {plugin_name} ({plugin_type}) to {new_version}...")
today = datetime.now().strftime("%Y-%m-%d")
today_badge = today.replace("-", "--")
# 1. Patch Plugin Python File
py_file = f"plugins/{plugin_type}/{plugin_name}/{plugin_name}.py"
patch_file(py_file, r"version: \d+\.\d+\.\d+", f"version: {new_version}", is_regex=True)
# 2. Patch Plugin READMEs
readme_en = f"plugins/{plugin_type}/{plugin_name}/README.md"
readme_zh = f"plugins/{plugin_type}/{plugin_name}/README_CN.md"
# Update version in metadata
patch_file(readme_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(readme_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# Update What's New (Assuming standard headers)
patch_file(readme_en, r"## 🔥 What's New in v.*?\n", f"## 🔥 What's New in v{new_version}\n\n* {msg_en}\n", is_regex=True)
patch_file(readme_zh, r"## 🔥 最新更新 v.*?\n", f"## 🔥 最新更新 v{new_version}\n\n* {msg_zh}\n", is_regex=True)
# 3. Patch Docs Mirrors
doc_en = f"docs/plugins/{plugin_type}/{plugin_name}.md"
doc_zh = f"docs/plugins/{plugin_type}/{plugin_name}.zh.md"
patch_file(doc_en, r"\*\*Version:\*\* \d+\.\d+\.\d+", f"**Version:** {new_version}", is_regex=True)
patch_file(doc_zh, r"\*\*版本:\*\* \d+\.\d+\.\d+", f"**版本:** {new_version}", is_regex=True)
# 4. Patch Root READMEs (Updated Date Badge)
patch_file("README.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
patch_file("README_CN.md", r"badge/202\d--\d\d--\d\d-gray", f"badge/{today_badge}-gray", is_regex=True)
print("\n✨ All synchronization tasks completed.")
return True
if __name__ == "__main__":
if len(sys.argv) < 6:
print("Usage: bump.py <type> <name> <version> <msg_en> <msg_zh>")
print("Example: bump.py filters markdown_normalizer 1.2.8 'Fix bug' '修复错误'")
sys.exit(1)
bump_version(sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4], sys.argv[5])

222
.github/workflows/aw-ci-audit.md vendored Normal file
View File

@@ -0,0 +1,222 @@
---
description: "CI audit workflow for failed releases, publish jobs, stats updates, and other important repository automation"
private: true
labels: [automation, diagnostics, ci, gh-aw]
metadata:
author: Fu-Jie
category: maintenance
maturity: draft
on:
schedule: daily
workflow_dispatch:
roles: all
skip-bots: [github-actions, copilot, dependabot, renovate]
permissions:
contents: read
issues: read
pull-requests: read
actions: read
engine: copilot
network:
allowed:
- defaults
safe-outputs:
create-issue:
title-prefix: "[ci-audit] "
labels: [ci-audit, maintenance]
close-older-issues: false
allowed-github-references: [repo]
timeout-minutes: 15
tools:
github:
toolsets: [repos, issues, pull_requests]
bash:
- pwd
- ls
- cat
- head
- tail
- grep
- wc
- rg
- git status
- git diff
- git show
- git ls-files
---
# CI Audit
You are the repository maintainer assistant for `Fu-Jie/openwebui-extensions`.
Your job is to inspect recent repository automation health and create **one concise maintenance issue only when there is actionable CI or automation feedback**.
If there is no meaningful failure pattern, no new actionable diagnosis, or no useful maintainer issue to open, you **must call `noop`** with a short explanation.
## Primary Goal
Audit recent automation health for:
- failed or flaky release-related workflows
- plugin publishing failures
- community stats update regressions
- repeated workflow drift or fragile maintenance steps
- repository-specific next steps maintainers can actually act on
This workflow is **diagnostic-only**. Do not modify files, push code, open pull requests, or create releases.
## High-Priority Source Files
Use these files as the authoritative context before forming conclusions:
- `.github/copilot-instructions.md`
- `.github/workflows/release.yml`
- `.github/workflows/publish_plugin.yml`
- `.github/workflows/publish_new_plugin.yml`
- `.github/workflows/plugin-version-check.yml`
- `.github/workflows/community-stats.yml`
- `docs/development/gh-aw-integration-plan.md`
- `docs/development/gh-aw-integration-plan.zh.md`
## Target Workflows
Prioritize these workflows first:
- `release.yml`
- `publish_plugin.yml`
- `publish_new_plugin.yml`
- `plugin-version-check.yml`
- `community-stats.yml`
- `deploy.yml`
If there are no meaningful issues there, do not widen scope unnecessarily.
## Review Scope
Focus on recent failed or suspicious automation runs and repository-facing symptoms. Prefer diagnosis that is grounded in repository context, not generic CI advice.
This workflow should behave like a maintainer who is reviewing workflow health trends, not like a generic log summarizer.
Focus especially on these areas:
### 1. Release and Publish Failures
Inspect whether recent failures suggest actionable problems such as:
- version extraction or comparison drift
- release-note packaging gaps
- publish-script authentication or environment issues
- assumptions in release jobs that no longer match repository structure
- failures that are likely to recur until repository logic changes
### 2. Stats and Scheduled Workflow Reliability
Inspect whether scheduled maintenance jobs show drift or fragility such as:
- community stats commits no longer happening when expected
- badge or docs generation assumptions becoming stale
- external API dependent jobs failing in repeatable ways
- schedule-driven jobs causing noisy or low-value churn
### 3. Signal Quality for Maintainers
Only create an issue if there is a useful diagnosis with at least one concrete next step.
Good issue-worthy findings include:
- a repeated failure signature across runs
- a repository mismatch between workflow logic and current file layout
- a likely missing secret, missing permission, or stale path assumption
- repeated low-signal failures that should be filtered or hardened
Do not open issues for one-off noise unless the failure pattern is likely to recur.
### 4. Existing Issue Awareness
Before creating a new issue, check whether a recent open issue already appears to cover the same CI failure pattern.
If an existing issue already covers the problem well enough, prefer `noop` and mention that the diagnosis is already tracked.
## Severity Model
Use three levels only:
- `High`: likely recurring CI or automation failure with repository impact
- `Medium`: useful to fix soon to reduce maintenance burden or workflow drift
- `Low`: optional hardening or cleanup suggestion
Do not invent issues just to create a report.
## Issue Creation Rules
Create **one maintenance issue** only if there is actionable new diagnosis.
The issue must:
- be in English
- be concise and maintainer-like
- lead with findings, not generic praise
- include clickable file references like ``.github/workflows/release.yml`` or ``scripts/publish_plugin.py``
- avoid nested bullets
- avoid pasting raw logs unless a short excerpt is critical
Use this exact structure when creating the issue:
```markdown
## CI Audit
### Summary
Short diagnosis of the failure pattern or automation risk.
### Findings
- `path/to/file`: specific problem or likely root cause
### Suggested Next Steps
- concrete maintainer action
- concrete maintainer action
### Notes
- Mention whether this appears recurring, new, or already partially mitigated.
```
Rules:
- Keep the issue under about 300 words unless multiple workflows are affected.
- If there are multiple related findings, group them into one issue rather than opening separate issues.
- Prefer a single, actionable diagnosis over a broad laundry list.
## No-Issue Rule
If there is no meaningful new diagnosis to report:
- do not create a status-only issue
- do not restate that workflows look healthy
- call `noop` with a short explanation like:
```json
{"noop": {"message": "No action needed: reviewed recent repository automation signals and found no new actionable CI diagnosis worth opening as a maintenance issue."}}
```
## Suggested Audit Process
1. Inspect recent repository automation context.
2. Prioritize the target workflows listed above.
3. Identify recurring or repository-specific failure patterns.
4. Check whether the problem is already tracked in an open issue.
5. Draft the shortest useful maintenance issue only if the diagnosis is actionable and new.
6. Finish with exactly one `create_issue` or one `noop`.
## Important Constraints
- Do not create an issue for a single low-signal transient failure.
- Do not propose large refactors unless the failure pattern clearly justifies them.
- Prefer repository-specific causes over generic "retry later" style advice.
- If the likely root cause is uncertain, state the uncertainty explicitly.
- If the pattern appears already tracked, prefer `noop` over duplicate issue creation.
## Final Requirement
You **must** finish with exactly one safe output action:
- `create_issue` if there is actionable new diagnosis
- `noop` if there is not

View File

@@ -0,0 +1,236 @@
---
description: "Semantic PR maintainer review for plugin standards, bilingual docs sync, and release readiness gaps"
private: true
labels: [automation, review, pull-request, gh-aw]
metadata:
author: Fu-Jie
category: maintenance
maturity: draft
on:
pull_request:
types: [opened, reopened, synchronize, ready_for_review]
paths:
- 'plugins/**'
- 'docs/**'
- '.github/**'
- 'README.md'
- 'README_CN.md'
forks: ["*"]
workflow_dispatch:
roles: all
skip-bots: [github-actions, copilot, dependabot, renovate]
permissions:
contents: read
issues: read
pull-requests: read
engine: copilot
network:
allowed:
- defaults
safe-outputs:
add-comment:
target: triggering
max: 1
hide-older-comments: true
footer: false
allowed-github-references: [repo]
timeout-minutes: 12
tools:
github:
toolsets: [repos, issues, pull_requests]
bash:
- pwd
- ls
- cat
- head
- tail
- grep
- wc
- rg
- git status
- git diff
- git show
- git ls-files
---
# PR Maintainer Review
You are the repository maintainer assistant for `Fu-Jie/openwebui-extensions`.
Your job is to review the triggering pull request against this repository's standards and leave **one concise summary comment only when there is actionable feedback**.
If the PR already looks compliant enough and there is no useful maintainer feedback to add, you **must call `noop`** with a short explanation.
## Primary Goal
Review the PR for:
- repository-standard compliance
- missing synchronized file updates
- release-readiness gaps
- documentation drift introduced by the change
- risky behavior regressions in plugin code
This workflow is **review-only**. Do not attempt to modify files, push code, or open pull requests.
## High-Priority Source Files
Use these files as the authoritative rule set before forming conclusions:
- `.github/copilot-instructions.md`
- `.github/instructions/code-review.instructions.md`
- `.github/instructions/commit-message.instructions.md`
- `.github/skills/release-prep/SKILL.md`
- `.github/skills/doc-mirror-sync/SKILL.md`
- `docs/development/gh-aw-integration-plan.md`
- `docs/development/gh-aw-integration-plan.zh.md`
## Review Scope
Start from the PR diff and changed files only. Expand into related files only when necessary to verify consistency.
Prioritize repository policy over generic best practices. This workflow should behave like a maintainer who knows this repository well, not like a broad lint bot.
Focus especially on these areas:
### 1. Plugin Code Standards
When a plugin Python file changes, check for repository-specific correctness:
- single-file i18n pattern is preserved
- user-visible text is routed through translations where appropriate
- `_get_user_context` and `_get_chat_context` are used instead of fragile direct access
- `__event_call__` JavaScript execution has timeout guards and JS-side fallback handling
- `print()` is not introduced in production plugin code
- emitter usage is guarded safely
- filter plugins do not store request-scoped mutable state on `self`
- OpenWebUI/Copilot SDK tool definitions remain consistent with repository conventions
### 2. Versioning and Release Hygiene
When `plugins/**/*.py` changes, verify whether the PR also updates what should normally move with it:
- plugin docstring `version:` changed when behavior changed
- local `README.md` and `README_CN.md` changed where user-visible behavior changed
- mirrored docs under `docs/plugins/**` changed where required
- docs plugin indexes changed if a published version badge or listing text should change
- root `README.md` and `README_CN.md` updated date badge if this PR is clearly release-prep oriented
Do not require every PR to be full release prep. Only flag missing sync files when the PR clearly changes published behavior, plugin metadata, versioned documentation, or release-facing content.
### 3. Documentation Sync
When plugin READMEs change, check whether matching docs mirrors should also change:
- `plugins/{type}/{name}/README.md` -> `docs/plugins/{type}/{name}.md`
- `plugins/{type}/{name}/README_CN.md` -> `docs/plugins/{type}/{name}.zh.md`
When docs-only changes are intentional, avoid over-reporting.
Useful path mappings:
- `plugins/actions/{name}/README.md` -> `docs/plugins/actions/{name}.md`
- `plugins/actions/{name}/README_CN.md` -> `docs/plugins/actions/{name}.zh.md`
- `plugins/filters/{name}/README.md` -> `docs/plugins/filters/{name}.md`
- `plugins/filters/{name}/README_CN.md` -> `docs/plugins/filters/{name}.zh.md`
- `plugins/pipes/{name}/README.md` -> `docs/plugins/pipes/{name}.md`
- `plugins/pipes/{name}/README_CN.md` -> `docs/plugins/pipes/{name}.zh.md`
- `plugins/pipelines/{name}/README.md` -> `docs/plugins/pipelines/{name}.md`
- `plugins/pipelines/{name}/README_CN.md` -> `docs/plugins/pipelines/{name}.zh.md`
- `plugins/tools/{name}/README.md` -> `docs/plugins/tools/{name}.md`
- `plugins/tools/{name}/README_CN.md` -> `docs/plugins/tools/{name}.zh.md`
### 4. PR Quality and Maintainer Signal
Check whether the PR description is missing key maintainer context:
- what changed
- why it changed
- whether users need migration or reconfiguration
Only mention this if the omission makes review materially harder.
## Severity Model
Use three levels only:
- `Blocking`: likely bug, release regression, missing required sync, or standards breakage
- `Important`: should be fixed before merge, but not an obvious runtime break
- `Minor`: worthwhile suggestion, but optional
Do not invent issues just to leave a comment.
## Commenting Rules
Leave **one summary comment** only if there is actionable feedback.
The comment must:
- be in English
- be concise and maintainer-like
- lead with findings, not compliments
- include clickable file references like ``plugins/pipes/foo/foo.py`` or ``docs/plugins/pipes/index.md``
- avoid nested bullets
- avoid repeating obvious diff content
Use this exact structure when commenting:
```markdown
## PR Maintainer Review
### Blocking
- `path/to/file`: specific issue and why it matters
### Important
- `path/to/file`: specific issue and what sync/check is missing
### Minor
- `path/to/file`: optional improvement or consistency note
### Merge Readiness
- Ready after the items above are addressed.
```
Rules:
- Omit empty sections.
- If there is only one severity category, include only that category plus `Merge Readiness`.
- Keep the full comment under about 250 words unless multiple files are involved.
## No-Comment Rule
If the PR has no meaningful maintainer findings:
- do not leave a praise-only comment
- do not restate that checks passed
- call `noop` with a short explanation like:
```json
{"noop": {"message": "No action needed: reviewed the PR diff and repository sync expectations, and found no actionable maintainer feedback."}}
```
## Suggested Review Process
1. Identify the changed files in the PR.
2. Read the high-priority repository rule files.
3. Compare changed plugin code against plugin review instructions.
4. Compare changed README or docs files against doc-mirror expectations.
5. Determine whether version-sync or release-facing files are missing.
6. Draft the shortest useful maintainer summary.
7. Leave exactly one `add_comment` or one `noop`.
## Important Constraints
- Do not request broad refactors unless the PR already touches that area.
- Do not require release-prep steps for tiny internal-only edits.
- Do not insist on docs sync when the change is clearly private/internal and not user-facing.
- Prefer precise, repository-specific feedback over generic code review advice.
- If you are unsure whether a sync file is required, downgrade to `Important` rather than `Blocking`.
- If a finding depends on intent that is not visible in the PR, explicitly say it is conditional instead of presenting it as certain.
## Final Requirement
You **must** finish with exactly one safe output action:
- `add_comment` if there is actionable feedback
- `noop` if there is not

Some files were not shown because too many files have changed in this diff Show More