fix(batch-install-plugins): support CRLF community plugin metadata
- support CRLF docstrings and folded YAML metadata blocks - detect community repo plugins such as iChristGit/OpenWebui-Tools correctly - align README, mirrored docs, and announcement wording with actual behavior Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
# Batch Install Plugins from GitHub
|
# Batch Install Plugins from GitHub
|
||||||
|
|
||||||
**Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** 1.0.0 | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **License:** MIT
|
**Author:** [Fu-Jie](https://github.com/Fu-Jie) | **Version:** 1.0.0 | **Project:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions)
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
||||||
|
|
||||||
@@ -10,7 +8,7 @@ One-click batch install plugins from GitHub repositories to your OpenWebUI insta
|
|||||||
|
|
||||||
- **One-Click Install**: Install all plugins with a single command
|
- **One-Click Install**: Install all plugins with a single command
|
||||||
- **Auto-Update**: Automatically updates previously installed plugins
|
- **Auto-Update**: Automatically updates previously installed plugins
|
||||||
- **GitHub Support**: Install plugins from any GitHub repository
|
- **Public GitHub Support**: Install plugins from any public GitHub repository
|
||||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||||
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
||||||
- **i18n**: Supports 11 languages
|
- **i18n**: Supports 11 languages
|
||||||
@@ -53,68 +51,91 @@ User Input
|
|||||||
## How to Use
|
## How to Use
|
||||||
|
|
||||||
1. Open OpenWebUI and go to **Workspace > Tools**
|
1. Open OpenWebUI and go to **Workspace > Tools**
|
||||||
2. Install **Batch Install Plugins from GitHub** from the official marketplace
|
2. Install **Batch Install Plugins from GitHub** from the marketplace
|
||||||
3. Enable this tool for your model/chat
|
3. Enable this tool for your model/chat
|
||||||
4. Ask the model to install plugins
|
4. Ask the model to install plugins
|
||||||
|
|
||||||
|
## Interactive Installation Workflow
|
||||||
|
|
||||||
|
Each request handles one repository. To mix repositories, send another request after the previous installation completes.
|
||||||
|
|
||||||
|
### Example Installation Sequence
|
||||||
|
|
||||||
|
1. **Start with My Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from Fu-Jie/openwebui-extensions"
|
||||||
|
```
|
||||||
|
Review the confirmation dialog, approve, and the plugins are installed.
|
||||||
|
|
||||||
|
2. **Add a Community Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
```
|
||||||
|
Add more plugins from a different repository. Already installed plugins are updated seamlessly.
|
||||||
|
|
||||||
|
3. **Install a Specific Type**
|
||||||
|
```
|
||||||
|
"Install only pipe plugins from Haervwe/open-webui-tools"
|
||||||
|
```
|
||||||
|
Pick specific plugin types from another repository, or exclude certain keywords.
|
||||||
|
|
||||||
|
4. **Use Your Own Repository**
|
||||||
|
```
|
||||||
|
"Install all plugins from your-username/your-collection"
|
||||||
|
```
|
||||||
|
Works with any public GitHub repository in `owner/repo` format.
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
|
|
||||||
|
Each line below is a separate request:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# Install from my default collection
|
||||||
"Install all plugins"
|
"Install all plugins"
|
||||||
"Install all plugins from github.com/username/repo"
|
|
||||||
"Install only pipe plugins"
|
|
||||||
"Install action and filter plugins"
|
|
||||||
"Install all plugins, exclude_keywords=copilot"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Popular Plugin Repositories
|
# Add another repository in a new request
|
||||||
|
|
||||||
Here are some popular repositories with many plugins you can install:
|
|
||||||
|
|
||||||
### Community Collections
|
|
||||||
|
|
||||||
```
|
|
||||||
# Install all plugins from iChristGit's collection
|
|
||||||
"Install all plugins from iChristGit/OpenWebui-Tools"
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
|
||||||
# Install all tools from Haervwe's tools collection
|
# Add only tools from a different repository
|
||||||
"Install all plugins from Haervwe/open-webui-tools"
|
"Install only tool plugins from Haervwe/open-webui-tools"
|
||||||
|
|
||||||
# Install all plugins from Classic298's repository
|
# Continue building your setup with another request
|
||||||
"Install all plugins from Classic298/open-webui-plugins"
|
"Install only action plugins from Classic298/open-webui-plugins"
|
||||||
|
|
||||||
# Install all functions from suurt8ll's collection
|
# Filter out unwanted plugins
|
||||||
"Install all plugins from suurt8ll/open_webui_functions"
|
|
||||||
|
|
||||||
# Install only specific types (e.g., only tools)
|
|
||||||
"Install only tool plugins from iChristGit/OpenWebui-Tools"
|
|
||||||
|
|
||||||
# Exclude certain keywords while installing
|
|
||||||
"Install all plugins from Haervwe/open-webui-tools, exclude_keywords=test,deprecated"
|
"Install all plugins from Haervwe/open-webui-tools, exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
|
# Install from your own public repository
|
||||||
|
"Install all plugins from your-username/my-plugin-collection"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Supported Repositories
|
## Popular Public Repositories
|
||||||
|
|
||||||
- `Fu-Jie/openwebui-extensions` - Default, official plugin collection
|
The tool works with any public GitHub repository in `owner/repo` format. Popular starting points include:
|
||||||
- `iChristGit/OpenWebui-Tools` - Comprehensive tool and plugin collection
|
|
||||||
- `Haervwe/open-webui-tools` - Specialized tools and utilities
|
- `Fu-Jie/openwebui-extensions` - My personal collection and the default source
|
||||||
- `Classic298/open-webui-plugins` - Various plugin implementations
|
- `iChristGit/OpenWebui-Tools` - Comprehensive tools and plugins
|
||||||
|
- `Haervwe/open-webui-tools` - Utility-focused extensions
|
||||||
|
- `Classic298/open-webui-plugins` - Mixed community plugins
|
||||||
- `suurt8ll/open_webui_functions` - Function-based plugins
|
- `suurt8ll/open_webui_functions` - Function-based plugins
|
||||||
|
- `rbb-dev/Open-WebUI-OpenRouter-pipe` - OpenRouter pipe integration
|
||||||
|
|
||||||
|
To combine repositories, run the tool again with a different `repo` after the previous installation completes.
|
||||||
|
|
||||||
## Default Repository
|
## Default Repository
|
||||||
|
|
||||||
When no repository is specified, defaults to `Fu-Jie/openwebui-extensions`.
|
When no repository is specified, the tool uses `Fu-Jie/openwebui-extensions` (my personal collection).
|
||||||
|
|
||||||
## Plugin Detection Rules
|
## Plugin Detection Rules
|
||||||
|
|
||||||
### Fu-Jie/openwebui-extensions (Strict)
|
### Fu-Jie/openwebui-extensions (Strict)
|
||||||
|
|
||||||
For the default repository, plugins must have:
|
For the default repository, the tool applies stricter filtering:
|
||||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||||
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** fields
|
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** metadata
|
||||||
3. Filename must not end with `_cn`
|
3. Filename must not end with `_cn`
|
||||||
|
|
||||||
### Other GitHub Repositories
|
### Other Public GitHub Repositories
|
||||||
|
|
||||||
For other repositories:
|
For other repositories:
|
||||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||||
|
|||||||
@@ -1,21 +1,19 @@
|
|||||||
# Batch Install Plugins from GitHub - 从 GitHub 批量安装插件
|
# Batch Install Plugins from GitHub
|
||||||
|
|
||||||
**作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.0.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可:** MIT
|
**作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.0.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions)
|
||||||
|
|
||||||
---
|
一键将 GitHub 仓库中的插件批量安装到你的 OpenWebUI 实例。
|
||||||
|
|
||||||
一键从 GitHub 仓库批量安装插件到你的 OpenWebUI 实例。
|
## 主要功能
|
||||||
|
|
||||||
## ✨ 主要特性
|
- 一键安装:单个命令安装所有插件
|
||||||
|
- 自动更新:自动更新之前安装过的插件
|
||||||
|
- 公开 GitHub 支持:支持从任何公开 GitHub 仓库安装插件
|
||||||
|
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||||
|
- 安装确认:安装前显示插件列表,支持选择性安装
|
||||||
|
- 国际化:支持 11 种语言
|
||||||
|
|
||||||
- **一键安装**: 一条命令安装所有插件
|
## 流程
|
||||||
- **自动更新**: 自动更新之前已安装的插件
|
|
||||||
- **GitHub 支持**: 支持从任何 GitHub 仓库安装插件
|
|
||||||
- **多类型支持**: 支持 Pipe、Action、Filter 和 Tool 插件
|
|
||||||
- **确认机制**: 安装前显示插件列表,允许选择性安装
|
|
||||||
- **国际化**: 支持 11 种语言
|
|
||||||
|
|
||||||
## 工作流
|
|
||||||
|
|
||||||
```
|
```
|
||||||
用户输入
|
用户输入
|
||||||
@@ -23,13 +21,13 @@
|
|||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────┐
|
┌─────────────────────────────────────┐
|
||||||
│ 从 GitHub 发现插件 │
|
│ 从 GitHub 发现插件 │
|
||||||
│ (获取文件树 + 解析 .py) │
|
│ (获取文件树 + 解析 .py 文件) │
|
||||||
└─────────────────────────────────────┘
|
└─────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────┐
|
┌─────────────────────────────────────┐
|
||||||
│ 按类型和关键词过滤 │
|
│ 按类型和关键词过滤 │
|
||||||
│ (tool/filter/pipe/action) │
|
│ (tool/filter/pipe/action) │
|
||||||
└─────────────────────────────────────┘
|
└─────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
@@ -42,90 +40,113 @@
|
|||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
┌─────────────────────────────────────┐
|
┌─────────────────────────────────────┐
|
||||||
│ 安装到 OpenWebUI │
|
│ 安装到 OpenWebUI │
|
||||||
│ (更新或创建每个插件) │
|
│ (更新或创建每个插件) │
|
||||||
└─────────────────────────────────────┘
|
└─────────────────────────────────────┘
|
||||||
│
|
│
|
||||||
▼
|
▼
|
||||||
完成
|
完成
|
||||||
```
|
```
|
||||||
|
|
||||||
## 🚀 使用方法
|
## 使用方法
|
||||||
|
|
||||||
1. 打开 OpenWebUI,进入 **工作区 > 工具**
|
1. 打开 OpenWebUI,进入 **Workspace > Tools**
|
||||||
2. 从官方市场安装 **Batch Install Plugins from GitHub**
|
2. 从市场安装 **Batch Install Plugins from GitHub**
|
||||||
3. 为你的模型/聊天启用此工具
|
3. 为你的模型/对话启用此工具
|
||||||
4. 让模型安装插件
|
4. 让模型调用工具来安装插件
|
||||||
|
|
||||||
|
## 交互式安装工作流
|
||||||
|
|
||||||
|
每次请求处理一个仓库。如需混合多个来源,请在上一次安装完成后再发起下一次请求。
|
||||||
|
|
||||||
|
### 安装序列示例
|
||||||
|
|
||||||
|
1. **先从我的合集开始**
|
||||||
|
```
|
||||||
|
"安装 Fu-Jie/openwebui-extensions 中的所有插件"
|
||||||
|
```
|
||||||
|
查看确认对话框,批准后插件开始安装。
|
||||||
|
|
||||||
|
2. **再添加社区合集**
|
||||||
|
```
|
||||||
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
```
|
||||||
|
从不同仓库添加更多插件。已安装的插件会无缝更新。
|
||||||
|
|
||||||
|
3. **按类型继续安装**
|
||||||
|
```
|
||||||
|
"从 Haervwe/open-webui-tools 仅安装 pipe 插件"
|
||||||
|
```
|
||||||
|
从另一个仓库选择特定类型的插件,或排除某些关键词。
|
||||||
|
|
||||||
|
4. **使用你自己的仓库**
|
||||||
|
```
|
||||||
|
"从 your-username/your-collection 安装所有插件"
|
||||||
|
```
|
||||||
|
支持任何公开的 GitHub 仓库,格式为 `owner/repo`。
|
||||||
|
|
||||||
## 使用示例
|
## 使用示例
|
||||||
|
|
||||||
|
下面每一行都是一次独立请求:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# 从默认合集安装
|
||||||
"安装所有插件"
|
"安装所有插件"
|
||||||
"从 github.com/username/repo 安装所有插件"
|
|
||||||
"仅安装 pipe 插件"
|
|
||||||
"安装 action 和 filter 插件"
|
|
||||||
"安装所有插件,exclude_keywords=copilot"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 热门插件仓库
|
# 在下一次请求中加入其他仓库
|
||||||
|
|
||||||
这些是包含大量插件的热门仓库,你可以从中安装插件:
|
|
||||||
|
|
||||||
### 社区合集
|
|
||||||
|
|
||||||
```
|
|
||||||
# 从 iChristGit 的集合安装所有插件
|
|
||||||
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
|
||||||
# 从 Haervwe 的工具集合只安装工具
|
# 从其他仓库只安装工具
|
||||||
"从 Haervwe/open-webui-tools 安装所有插件"
|
"从 Haervwe/open-webui-tools 仅安装 tool 插件"
|
||||||
|
|
||||||
# 从 Classic298 的仓库安装所有插件
|
# 再继续补充另一类插件
|
||||||
"从 Classic298/open-webui-plugins 安装所有插件"
|
"从 Classic298/open-webui-plugins 安装仅 action 插件"
|
||||||
|
|
||||||
# 从 suurt8ll 的集合安装所有函数
|
# 过滤不想安装的插件
|
||||||
"从 suurt8ll/open_webui_functions 安装所有插件"
|
"从 Haervwe/open-webui-tools 安装所有插件, exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
# 仅安装特定类型的插件(比如只安装工具)
|
# 从你自己的公开仓库安装
|
||||||
"从 iChristGit/OpenWebui-Tools 仅安装 tool 插件"
|
"从 your-username/my-plugin-collection 安装所有插件"
|
||||||
|
|
||||||
# 安装时排除特定关键词
|
|
||||||
"从 Haervwe/open-webui-tools 安装所有插件,exclude_keywords=test,deprecated"
|
|
||||||
```
|
```
|
||||||
|
|
||||||
### 支持的仓库
|
## 热门公开仓库
|
||||||
|
|
||||||
- `Fu-Jie/openwebui-extensions` - 默认的官方插件集合
|
该工具支持任何公开 GitHub 仓库,格式为 `owner/repo`。这些都是不错的起点:
|
||||||
|
|
||||||
|
- `Fu-Jie/openwebui-extensions` - 我的个人合集,也是默认来源
|
||||||
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
||||||
- `Haervwe/open-webui-tools` - 专业的工具和实用程序
|
- `Haervwe/open-webui-tools` - 偏工具型的扩展集合
|
||||||
- `Classic298/open-webui-plugins` - 各种插件实现
|
- `Classic298/open-webui-plugins` - 混合型社区插件集合
|
||||||
- `suurt8ll/open_webui_functions` - 基于函数的插件
|
- `suurt8ll/open_webui_functions` - 基于函数的插件集合
|
||||||
|
- `rbb-dev/Open-WebUI-OpenRouter-pipe` - OpenRouter pipe 集成
|
||||||
|
|
||||||
|
如需混合多个来源,请在上一次安装完成后,换一个 `repo` 再调用一次工具。
|
||||||
|
|
||||||
## 默认仓库
|
## 默认仓库
|
||||||
|
|
||||||
未指定仓库时,默认使用 `Fu-Jie/openwebui-extensions`。
|
未指定仓库时,工具会使用 `Fu-Jie/openwebui-extensions`(我的个人合集)。
|
||||||
|
|
||||||
## 插件检测规则
|
## 插件检测规则
|
||||||
|
|
||||||
### Fu-Jie/openwebui-extensions(严格模式)
|
### Fu-Jie/openwebui-extensions(严格模式)
|
||||||
|
|
||||||
对于默认仓库,插件必须有:
|
对于默认仓库,工具会采用更严格的筛选规则:
|
||||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||||
2. 包含 `title:`、`description:` 和 **`openwebui_id:`** 字段的文档字符串
|
2. Docstring 中包含 `title:`、`description:` 和 **`openwebui_id:`** 元数据
|
||||||
3. 文件名不能以 `_cn` 结尾
|
3. 文件名不能以 `_cn` 结尾
|
||||||
|
|
||||||
### 其他 GitHub 仓库
|
### 其他公开 GitHub 仓库
|
||||||
|
|
||||||
对于其他仓库:
|
其他仓库的插件必须满足:
|
||||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||||
2. 包含 `title:` 和 `description:` 字段的文档字符串
|
2. Docstring 中包含 `title:` 和 `description:` 字段
|
||||||
|
|
||||||
## 配置 (Valves)
|
## 配置(Valves)
|
||||||
|
|
||||||
| 参数 | 默认值 | 描述 |
|
| 参数 | 默认值 | 描述 |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | 要跳过的关键词,用逗号分隔 |
|
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | 逗号分隔的跳过关键词 |
|
||||||
| `TIMEOUT` | `20` | 请求超时时间(秒) |
|
| `TIMEOUT` | `20` | 请求超时时间(秒)|
|
||||||
|
|
||||||
## 确认超时时间
|
## 确认超时时间
|
||||||
|
|
||||||
|
|||||||
132
plugins/tools/batch-install-plugins/ANNOUNCEMENT.md
Normal file
132
plugins/tools/batch-install-plugins/ANNOUNCEMENT.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# 🎉 Introducing Batch Install Plugins v1.0.0
|
||||||
|
|
||||||
|
## Headline
|
||||||
|
**One-Click Batch Installation of OpenWebUI Plugins - Solving the Plugin Setup Headache**
|
||||||
|
|
||||||
|
## Introduction
|
||||||
|
Installing plugins in OpenWebUI used to be tedious: searching for plugins, downloading them one by one, and hoping everything works in your environment. Today, we're excited to announce **Batch Install Plugins from GitHub** v1.0.0 — a powerful new tool that transforms plugin installation from a chore into a single command.
|
||||||
|
|
||||||
|
## Key Highlights
|
||||||
|
|
||||||
|
### 🚀 One-Click Bulk Installation
|
||||||
|
- Install multiple plugins from any public GitHub repository with a single command
|
||||||
|
- Automatically discovers plugins and validates them
|
||||||
|
- Updates previously installed plugins seamlessly
|
||||||
|
|
||||||
|
### ✅ Smart Safety Features
|
||||||
|
- Shows a confirmation dialog with the plugin list before installation
|
||||||
|
- Users can review and approve before proceeding
|
||||||
|
- Automatically excludes the tool itself from installation
|
||||||
|
|
||||||
|
### 🌍 Multi-Repository Support
|
||||||
|
Install plugins from **any public GitHub repository**, including your own community collections:
|
||||||
|
- Use one request per repository, then call the tool again to combine multiple sources
|
||||||
|
- **Default**: Fu-Jie/openwebui-extensions (my personal collection)
|
||||||
|
- Works with public repositories in `owner/repo` format
|
||||||
|
- Mix and match plugins: install from my collection first, then add community collections in subsequent calls
|
||||||
|
|
||||||
|
### 🔧 Container-Friendly
|
||||||
|
- Automatically handles port mapping issues in containerized deployments
|
||||||
|
- Smart fallback: retries with localhost:8080 if the primary connection fails
|
||||||
|
- Rich debugging logs for troubleshooting
|
||||||
|
|
||||||
|
### 🌐 Global Support
|
||||||
|
- Complete i18n support for 11 languages
|
||||||
|
- All error messages localized and user-friendly
|
||||||
|
- Works seamlessly across different deployment scenarios
|
||||||
|
|
||||||
|
## How It Works: Interactive Installation Workflow
|
||||||
|
|
||||||
|
Each request handles one repository. To combine multiple repositories, send another request after the previous installation completes.
|
||||||
|
|
||||||
|
1. **Start with My Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from Fu-Jie/openwebui-extensions"
|
||||||
|
```
|
||||||
|
Review the confirmation dialog, approve, and the plugins are installed.
|
||||||
|
|
||||||
|
2. **Add a Community Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
```
|
||||||
|
Add more plugins from a different repository. Already installed plugins are updated seamlessly.
|
||||||
|
|
||||||
|
3. **Install a Specific Type**
|
||||||
|
```
|
||||||
|
"Install only pipe plugins from Haervwe/open-webui-tools"
|
||||||
|
```
|
||||||
|
Pick specific plugin types from another repository, or exclude certain keywords.
|
||||||
|
|
||||||
|
4. **Use Your Own Public Repository**
|
||||||
|
```
|
||||||
|
"Install all plugins from your-username/your-collection"
|
||||||
|
```
|
||||||
|
Works with any public GitHub repository in `owner/repo` format.
|
||||||
|
|
||||||
|
## Popular Community Collections
|
||||||
|
|
||||||
|
Ready-to-install from these community favorites:
|
||||||
|
|
||||||
|
#### **iChristGit/OpenWebui-Tools**
|
||||||
|
Comprehensive tools and plugins for various use cases.
|
||||||
|
|
||||||
|
#### **Haervwe/open-webui-tools**
|
||||||
|
Specialized utilities for extending OpenWebUI functionality.
|
||||||
|
|
||||||
|
#### **Classic298/open-webui-plugins**
|
||||||
|
Diverse plugin implementations for different scenarios.
|
||||||
|
|
||||||
|
#### **suurt8ll/open_webui_functions**
|
||||||
|
Function-based plugins for custom integrations.
|
||||||
|
|
||||||
|
#### **rbb-dev/Open-WebUI-OpenRouter-pipe**
|
||||||
|
OpenRouter API pipe integration for advanced model access.
|
||||||
|
|
||||||
|
## Usage Examples
|
||||||
|
|
||||||
|
Each line below is a separate request:
|
||||||
|
|
||||||
|
```
|
||||||
|
# Start with my collection
|
||||||
|
"Install all plugins"
|
||||||
|
|
||||||
|
# Add community plugins in a new request
|
||||||
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
|
||||||
|
# Add only one plugin type from another repository
|
||||||
|
"Install only tool plugins from Haervwe/open-webui-tools"
|
||||||
|
|
||||||
|
# Continue building your setup
|
||||||
|
"Install only action plugins from Classic298/open-webui-plugins"
|
||||||
|
|
||||||
|
# Filter out unwanted plugins
|
||||||
|
"Install all plugins from Haervwe/open-webui-tools, exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
|
# Install from your own public repository
|
||||||
|
"Install all plugins from your-username/my-plugin-collection"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Technical Excellence
|
||||||
|
|
||||||
|
- **Async Architecture**: Non-blocking I/O for better performance
|
||||||
|
- **httpx Integration**: Modern async HTTP client with timeout protection
|
||||||
|
- **Comprehensive Tests**: 8 regression tests with 100% pass rate
|
||||||
|
- **Full Event Support**: Proper OpenWebUI event injection with fallback handling
|
||||||
|
|
||||||
|
## Installation
|
||||||
|
|
||||||
|
1. Open OpenWebUI → Workspace > Tools
|
||||||
|
2. Install **Batch Install Plugins from GitHub** from the marketplace
|
||||||
|
3. Enable it for your model/chat
|
||||||
|
4. Start using it with commands like "Install all plugins"
|
||||||
|
|
||||||
|
## Links
|
||||||
|
|
||||||
|
- **GitHub Repository**: https://github.com/Fu-Jie/openwebui-extensions/tree/main/plugins/tools/batch-install-plugins
|
||||||
|
- **Release Notes**: https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/tools/batch-install-plugins/v1.0.0.md
|
||||||
|
|
||||||
|
## Community Love
|
||||||
|
|
||||||
|
If this tool has been helpful to you, please give us a ⭐ on [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) — it truly motivates us to keep improving!
|
||||||
|
|
||||||
|
**Thank you for supporting the OpenWebUI community! 🙏**
|
||||||
132
plugins/tools/batch-install-plugins/ANNOUNCEMENT_CN.md
Normal file
132
plugins/tools/batch-install-plugins/ANNOUNCEMENT_CN.md
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
# 🎉 Batch Install Plugins 首发 v1.0.0
|
||||||
|
|
||||||
|
## 标题
|
||||||
|
**一键批量安装 OpenWebUI 插件 - 解决装机烦恼**
|
||||||
|
|
||||||
|
## 前言
|
||||||
|
在 OpenWebUI 中安装插件曾经很麻烦:逐个搜索、逐个下载、祈祷一切顺利。今天,我们欣然宣布 **Batch Install Plugins from GitHub** v1.0.0 的问世 — 一款强大的新工具,让插件安装从苦差事变成一条简单命令。
|
||||||
|
|
||||||
|
## 核心特性
|
||||||
|
|
||||||
|
### 🚀 一键批量安装
|
||||||
|
- 从任意公开 GitHub 仓库用一条命令安装多个插件
|
||||||
|
- 自动发现插件并进行验证
|
||||||
|
- 无缝更新已安装的插件
|
||||||
|
|
||||||
|
### ✅ 智能安全保障
|
||||||
|
- 安装前显示插件列表确认对话框
|
||||||
|
- 用户可在安装前查看和审批
|
||||||
|
- 自动排除工具自身,避免重复安装
|
||||||
|
|
||||||
|
### 🌍 多仓库支持
|
||||||
|
支持从**任意公开 GitHub 仓库**安装插件,包括你自己的社区合集:
|
||||||
|
- 每次请求处理一个仓库,需要时可再次调用工具来组合多个来源
|
||||||
|
- **默认**:Fu-Jie/openwebui-extensions(我的个人合集)
|
||||||
|
- 支持公开仓库,格式为 `owner/repo`
|
||||||
|
- 混合搭配:先从我的合集安装,再通过后续调用添加社区合集
|
||||||
|
|
||||||
|
### 🔧 容器友好
|
||||||
|
- 自动处理容器部署中的端口映射问题
|
||||||
|
- 智能降级:主连接失败时自动重试 localhost:8080
|
||||||
|
- 丰富的调试日志便于故障排除
|
||||||
|
|
||||||
|
### 🌐 全球化支持
|
||||||
|
- 完整支持 11 种语言
|
||||||
|
- 所有错误提示本地化且用户友好
|
||||||
|
- 跨不同部署场景无缝运行
|
||||||
|
|
||||||
|
## 工作流程:交互式安装
|
||||||
|
|
||||||
|
每次请求处理一个仓库。如需组合多个仓库,请在上一次安装完成后再发起下一次请求。
|
||||||
|
|
||||||
|
1. **先从我的合集开始**
|
||||||
|
```
|
||||||
|
"安装 Fu-Jie/openwebui-extensions 中的所有插件"
|
||||||
|
```
|
||||||
|
查看确认对话框,批准后开始安装。
|
||||||
|
|
||||||
|
2. **再添加社区合集**
|
||||||
|
```
|
||||||
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
```
|
||||||
|
从不同仓库添加更多插件。已安装的插件会无缝更新。
|
||||||
|
|
||||||
|
3. **按类型继续安装**
|
||||||
|
```
|
||||||
|
"从 Haervwe/open-webui-tools 仅安装 pipe 插件"
|
||||||
|
```
|
||||||
|
从另一个仓库选择特定类型的插件,或排除某些关键词。
|
||||||
|
|
||||||
|
4. **使用你自己的公开仓库**
|
||||||
|
```
|
||||||
|
"从 your-username/your-collection 安装所有插件"
|
||||||
|
```
|
||||||
|
支持任何公开 GitHub 仓库,格式为 `owner/repo`。
|
||||||
|
|
||||||
|
## 热门社区合集
|
||||||
|
|
||||||
|
这些社区精选都已准备好安装:
|
||||||
|
|
||||||
|
#### **iChristGit/OpenWebui-Tools**
|
||||||
|
包含各种工具和插件的综合集合。
|
||||||
|
|
||||||
|
#### **Haervwe/open-webui-tools**
|
||||||
|
专业工具和实用程序,扩展 OpenWebUI 功能。
|
||||||
|
|
||||||
|
#### **Classic298/open-webui-plugins**
|
||||||
|
多样化的插件实现,满足不同场景。
|
||||||
|
|
||||||
|
#### **suurt8ll/open_webui_functions**
|
||||||
|
基于函数的插件,用于自定义集成。
|
||||||
|
|
||||||
|
#### **rbb-dev/Open-WebUI-OpenRouter-pipe**
|
||||||
|
OpenRouter API pipe 集成,提供高级模型访问。
|
||||||
|
|
||||||
|
## 使用示例
|
||||||
|
|
||||||
|
下面每一行都是一次独立请求:
|
||||||
|
|
||||||
|
```
|
||||||
|
# 先从我的合集开始
|
||||||
|
"安装所有插件"
|
||||||
|
|
||||||
|
# 在下一次请求中加入社区插件
|
||||||
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
|
||||||
|
# 从其他仓库只安装某一种类型
|
||||||
|
"从 Haervwe/open-webui-tools 仅安装 tool 插件"
|
||||||
|
|
||||||
|
# 继续补充你的插件组合
|
||||||
|
"从 Classic298/open-webui-plugins 安装仅 action 插件"
|
||||||
|
|
||||||
|
# 过滤不想安装的插件
|
||||||
|
"从 Haervwe/open-webui-tools 安装所有插件,exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
|
# 从你自己的公开仓库安装
|
||||||
|
"从 your-username/my-plugin-collection 安装所有插件"
|
||||||
|
```
|
||||||
|
|
||||||
|
## 技术亮点
|
||||||
|
|
||||||
|
- **异步架构**:非阻塞 I/O,性能更优
|
||||||
|
- **httpx 集成**:现代化异步 HTTP 客户端,包含超时保护
|
||||||
|
- **完整测试**:8 个回归测试,100% 通过率
|
||||||
|
- **完整事件支持**:正确处理 OpenWebUI 事件注入,提供回退机制
|
||||||
|
|
||||||
|
## 安装方法
|
||||||
|
|
||||||
|
1. 打开 OpenWebUI → 工作区 > 工具
|
||||||
|
2. 从市场安装 **Batch Install Plugins from GitHub**
|
||||||
|
3. 为你的模型/对话启用此工具
|
||||||
|
4. 开始使用,比如说"安装所有插件"
|
||||||
|
|
||||||
|
## 相关链接
|
||||||
|
|
||||||
|
- **GitHub 仓库**:https://github.com/Fu-Jie/openwebui-extensions/tree/main/plugins/tools/batch-install-plugins
|
||||||
|
- **发布说明**:https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/tools/batch-install-plugins/v1.0.0_CN.md
|
||||||
|
|
||||||
|
## 社区支持
|
||||||
|
|
||||||
|
如果这个工具对你有帮助,欢迎到 [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) 点个 ⭐ — 这将是我们持续改进的动力!
|
||||||
|
|
||||||
|
**感谢你支持 OpenWebUI 社区!🙏**
|
||||||
@@ -8,7 +8,7 @@ One-click batch install plugins from GitHub repositories to your OpenWebUI insta
|
|||||||
|
|
||||||
- **One-Click Install**: Install all plugins with a single command
|
- **One-Click Install**: Install all plugins with a single command
|
||||||
- **Auto-Update**: Automatically updates previously installed plugins
|
- **Auto-Update**: Automatically updates previously installed plugins
|
||||||
- **GitHub Support**: Install plugins from any GitHub repository
|
- **Public GitHub Support**: Install plugins from any public GitHub repository
|
||||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||||
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
||||||
- **i18n**: Supports 11 languages
|
- **i18n**: Supports 11 languages
|
||||||
@@ -51,68 +51,91 @@ User Input
|
|||||||
## How to Use
|
## How to Use
|
||||||
|
|
||||||
1. Open OpenWebUI and go to **Workspace > Tools**
|
1. Open OpenWebUI and go to **Workspace > Tools**
|
||||||
2. Install **Batch Install Plugins from GitHub** from the official marketplace
|
2. Install **Batch Install Plugins from GitHub** from the marketplace
|
||||||
3. Enable this tool for your model/chat
|
3. Enable this tool for your model/chat
|
||||||
4. Ask the model to install plugins
|
4. Ask the model to install plugins
|
||||||
|
|
||||||
|
## Interactive Installation Workflow
|
||||||
|
|
||||||
|
Each request handles one repository. To mix repositories, send another request after the previous installation completes.
|
||||||
|
|
||||||
|
### Example Installation Sequence
|
||||||
|
|
||||||
|
1. **Start with My Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from Fu-Jie/openwebui-extensions"
|
||||||
|
```
|
||||||
|
Review the confirmation dialog, approve, and the plugins are installed.
|
||||||
|
|
||||||
|
2. **Add a Community Collection**
|
||||||
|
```
|
||||||
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
```
|
||||||
|
Add more plugins from a different repository. Already installed plugins are updated seamlessly.
|
||||||
|
|
||||||
|
3. **Install a Specific Type**
|
||||||
|
```
|
||||||
|
"Install only pipe plugins from Haervwe/open-webui-tools"
|
||||||
|
```
|
||||||
|
Pick specific plugin types from another repository, or exclude certain keywords.
|
||||||
|
|
||||||
|
4. **Use Your Own Repository**
|
||||||
|
```
|
||||||
|
"Install all plugins from your-username/your-collection"
|
||||||
|
```
|
||||||
|
Works with any public GitHub repository in `owner/repo` format.
|
||||||
|
|
||||||
## Usage Examples
|
## Usage Examples
|
||||||
|
|
||||||
|
Each line below is a separate request:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# Install from my default collection
|
||||||
"Install all plugins"
|
"Install all plugins"
|
||||||
"Install all plugins from github.com/username/repo"
|
|
||||||
"Install only pipe plugins"
|
|
||||||
"Install action and filter plugins"
|
|
||||||
"Install all plugins, exclude_keywords=copilot"
|
|
||||||
```
|
|
||||||
|
|
||||||
## Popular Plugin Repositories
|
# Add another repository in a new request
|
||||||
|
|
||||||
Here are some popular repositories with many plugins you can install:
|
|
||||||
|
|
||||||
### Community Collections
|
|
||||||
|
|
||||||
```
|
|
||||||
# Install all plugins from iChristGit's collection
|
|
||||||
"Install all plugins from iChristGit/OpenWebui-Tools"
|
"Install all plugins from iChristGit/OpenWebui-Tools"
|
||||||
|
|
||||||
# Install all tools from Haervwe's tools collection
|
# Add only tools from a different repository
|
||||||
"Install all plugins from Haervwe/open-webui-tools"
|
"Install only tool plugins from Haervwe/open-webui-tools"
|
||||||
|
|
||||||
# Install all plugins from Classic298's repository
|
# Continue building your setup with another request
|
||||||
"Install all plugins from Classic298/open-webui-plugins"
|
"Install only action plugins from Classic298/open-webui-plugins"
|
||||||
|
|
||||||
# Install all functions from suurt8ll's collection
|
# Filter out unwanted plugins
|
||||||
"Install all plugins from suurt8ll/open_webui_functions"
|
|
||||||
|
|
||||||
# Install only specific types (e.g., only tools)
|
|
||||||
"Install only tool plugins from iChristGit/OpenWebui-Tools"
|
|
||||||
|
|
||||||
# Exclude certain keywords while installing
|
|
||||||
"Install all plugins from Haervwe/open-webui-tools, exclude_keywords=test,deprecated"
|
"Install all plugins from Haervwe/open-webui-tools, exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
|
# Install from your own public repository
|
||||||
|
"Install all plugins from your-username/my-plugin-collection"
|
||||||
```
|
```
|
||||||
|
|
||||||
### Supported Repositories
|
## Popular Public Repositories
|
||||||
|
|
||||||
- `Fu-Jie/openwebui-extensions` - Default, official plugin collection
|
The tool works with any public GitHub repository in `owner/repo` format. Popular starting points include:
|
||||||
- `iChristGit/OpenWebui-Tools` - Comprehensive tool and plugin collection
|
|
||||||
- `Haervwe/open-webui-tools` - Specialized tools and utilities
|
- `Fu-Jie/openwebui-extensions` - My personal collection and the default source
|
||||||
- `Classic298/open-webui-plugins` - Various plugin implementations
|
- `iChristGit/OpenWebui-Tools` - Comprehensive tools and plugins
|
||||||
|
- `Haervwe/open-webui-tools` - Utility-focused extensions
|
||||||
|
- `Classic298/open-webui-plugins` - Mixed community plugins
|
||||||
- `suurt8ll/open_webui_functions` - Function-based plugins
|
- `suurt8ll/open_webui_functions` - Function-based plugins
|
||||||
|
- `rbb-dev/Open-WebUI-OpenRouter-pipe` - OpenRouter pipe integration
|
||||||
|
|
||||||
|
To combine repositories, run the tool again with a different `repo` after the previous installation completes.
|
||||||
|
|
||||||
## Default Repository
|
## Default Repository
|
||||||
|
|
||||||
When no repository is specified, defaults to `Fu-Jie/openwebui-extensions`.
|
When no repository is specified, the tool uses `Fu-Jie/openwebui-extensions` (my personal collection).
|
||||||
|
|
||||||
## Plugin Detection Rules
|
## Plugin Detection Rules
|
||||||
|
|
||||||
### Fu-Jie/openwebui-extensions (Strict)
|
### Fu-Jie/openwebui-extensions (Strict)
|
||||||
|
|
||||||
For the default repository, plugins must have:
|
For the default repository, the tool applies stricter filtering:
|
||||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||||
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** fields
|
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** metadata
|
||||||
3. Filename must not end with `_cn`
|
3. Filename must not end with `_cn`
|
||||||
|
|
||||||
### Other GitHub Repositories
|
### Other Public GitHub Repositories
|
||||||
|
|
||||||
For other repositories:
|
For other repositories:
|
||||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
- 一键安装:单个命令安装所有插件
|
- 一键安装:单个命令安装所有插件
|
||||||
- 自动更新:自动更新之前安装过的插件
|
- 自动更新:自动更新之前安装过的插件
|
||||||
- GitHub 支持:从任意 GitHub 仓库安装插件
|
- 公开 GitHub 支持:支持从任何公开 GitHub 仓库安装插件
|
||||||
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||||
- 安装确认:安装前显示插件列表,支持选择性安装
|
- 安装确认:安装前显示插件列表,支持选择性安装
|
||||||
- 国际化:支持 11 种语言
|
- 国际化:支持 11 种语言
|
||||||
@@ -51,68 +51,91 @@
|
|||||||
## 使用方法
|
## 使用方法
|
||||||
|
|
||||||
1. 打开 OpenWebUI,进入 **Workspace > Tools**
|
1. 打开 OpenWebUI,进入 **Workspace > Tools**
|
||||||
2. 从官方市场安装 **Batch Install Plugins from GitHub**
|
2. 从市场安装 **Batch Install Plugins from GitHub**
|
||||||
3. 为你的模型/对话启用此工具
|
3. 为你的模型/对话启用此工具
|
||||||
4. 让模型调用工具方法
|
4. 让模型调用工具来安装插件
|
||||||
|
|
||||||
|
## 交互式安装工作流
|
||||||
|
|
||||||
|
每次请求处理一个仓库。如需混合多个来源,请在上一次安装完成后再发起下一次请求。
|
||||||
|
|
||||||
|
### 安装序列示例
|
||||||
|
|
||||||
|
1. **先从我的合集开始**
|
||||||
|
```
|
||||||
|
"安装 Fu-Jie/openwebui-extensions 中的所有插件"
|
||||||
|
```
|
||||||
|
查看确认对话框,批准后插件开始安装。
|
||||||
|
|
||||||
|
2. **再添加社区合集**
|
||||||
|
```
|
||||||
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
```
|
||||||
|
从不同仓库添加更多插件。已安装的插件会无缝更新。
|
||||||
|
|
||||||
|
3. **按类型继续安装**
|
||||||
|
```
|
||||||
|
"从 Haervwe/open-webui-tools 仅安装 pipe 插件"
|
||||||
|
```
|
||||||
|
从另一个仓库选择特定类型的插件,或排除某些关键词。
|
||||||
|
|
||||||
|
4. **使用你自己的仓库**
|
||||||
|
```
|
||||||
|
"从 your-username/your-collection 安装所有插件"
|
||||||
|
```
|
||||||
|
支持任何公开的 GitHub 仓库,格式为 `owner/repo`。
|
||||||
|
|
||||||
## 使用示例
|
## 使用示例
|
||||||
|
|
||||||
|
下面每一行都是一次独立请求:
|
||||||
|
|
||||||
```
|
```
|
||||||
|
# 从默认合集安装
|
||||||
"安装所有插件"
|
"安装所有插件"
|
||||||
"从 github.com/username/repo 安装所有插件"
|
|
||||||
"只安装 pipe 插件"
|
|
||||||
"安装 action 和 filter 插件"
|
|
||||||
"安装所有插件, exclude_keywords=copilot"
|
|
||||||
```
|
|
||||||
|
|
||||||
## 热门插件仓库
|
# 在下一次请求中加入其他仓库
|
||||||
|
|
||||||
这些是包含大量插件的热门仓库,你可以从中安装插件:
|
|
||||||
|
|
||||||
### 社区合集
|
|
||||||
|
|
||||||
```
|
|
||||||
# 从 iChristGit 的集合安装所有插件
|
|
||||||
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||||
|
|
||||||
# 从 Haervwe 的工具集合只安装工具
|
# 从其他仓库只安装工具
|
||||||
"从 Haervwe/open-webui-tools 安装所有插件"
|
"从 Haervwe/open-webui-tools 仅安装 tool 插件"
|
||||||
|
|
||||||
# 从 Classic298 的仓库安装所有插件
|
# 再继续补充另一类插件
|
||||||
"从 Classic298/open-webui-plugins 安装所有插件"
|
"从 Classic298/open-webui-plugins 安装仅 action 插件"
|
||||||
|
|
||||||
# 从 suurt8ll 的集合安装所有函数
|
# 过滤不想安装的插件
|
||||||
"从 suurt8ll/open_webui_functions 安装所有插件"
|
|
||||||
|
|
||||||
# 只安装特定类型的插件(比如只安装工具)
|
|
||||||
"从 iChristGit/OpenWebui-Tools 只安装 tool 插件"
|
|
||||||
|
|
||||||
# 安装时排除特定关键词
|
|
||||||
"从 Haervwe/open-webui-tools 安装所有插件, exclude_keywords=test,deprecated"
|
"从 Haervwe/open-webui-tools 安装所有插件, exclude_keywords=test,deprecated"
|
||||||
|
|
||||||
|
# 从你自己的公开仓库安装
|
||||||
|
"从 your-username/my-plugin-collection 安装所有插件"
|
||||||
```
|
```
|
||||||
|
|
||||||
### 支持的仓库
|
## 热门公开仓库
|
||||||
|
|
||||||
- `Fu-Jie/openwebui-extensions` - 默认的官方插件集合
|
该工具支持任何公开 GitHub 仓库,格式为 `owner/repo`。这些都是不错的起点:
|
||||||
|
|
||||||
|
- `Fu-Jie/openwebui-extensions` - 我的个人合集,也是默认来源
|
||||||
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
||||||
- `Haervwe/open-webui-tools` - 专业的工具和实用程序
|
- `Haervwe/open-webui-tools` - 偏工具型的扩展集合
|
||||||
- `Classic298/open-webui-plugins` - 各种插件实现
|
- `Classic298/open-webui-plugins` - 混合型社区插件集合
|
||||||
- `suurt8ll/open_webui_functions` - 基于函数的插件
|
- `suurt8ll/open_webui_functions` - 基于函数的插件集合
|
||||||
|
- `rbb-dev/Open-WebUI-OpenRouter-pipe` - OpenRouter pipe 集成
|
||||||
|
|
||||||
|
如需混合多个来源,请在上一次安装完成后,换一个 `repo` 再调用一次工具。
|
||||||
|
|
||||||
## 默认仓库
|
## 默认仓库
|
||||||
|
|
||||||
未指定仓库时,默认为 `Fu-Jie/openwebui-extensions`。
|
未指定仓库时,工具会使用 `Fu-Jie/openwebui-extensions`(我的个人合集)。
|
||||||
|
|
||||||
## 插件检测规则
|
## 插件检测规则
|
||||||
|
|
||||||
### Fu-Jie/openwebui-extensions(严格模式)
|
### Fu-Jie/openwebui-extensions(严格模式)
|
||||||
|
|
||||||
默认仓库的插件必须满足:
|
对于默认仓库,工具会采用更严格的筛选规则:
|
||||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||||
2. Docstring 中包含 `title:`、`description:` 和 **`openwebui_id:`** 字段
|
2. Docstring 中包含 `title:`、`description:` 和 **`openwebui_id:`** 元数据
|
||||||
3. 文件名不能以 `_cn` 结尾
|
3. 文件名不能以 `_cn` 结尾
|
||||||
|
|
||||||
### 其他 GitHub 仓库
|
### 其他公开 GitHub 仓库
|
||||||
|
|
||||||
其他仓库的插件必须满足:
|
其他仓库的插件必须满足:
|
||||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||||
|
|||||||
@@ -7,11 +7,13 @@ version: 1.0.0
|
|||||||
description: One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
description: One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import ast
|
||||||
import asyncio
|
import asyncio
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
|
import textwrap
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from typing import Any, Dict, List, Optional, Tuple
|
from typing import Any, Dict, List, Optional, Tuple
|
||||||
|
|
||||||
@@ -33,9 +35,10 @@ SELF_EXCLUDE_TERMS = (
|
|||||||
SELF_EXCLUDE_HINT,
|
SELF_EXCLUDE_HINT,
|
||||||
"batch install plugins from github",
|
"batch install plugins from github",
|
||||||
)
|
)
|
||||||
DOCSTRING_PATTERN = re.compile(r'^\s*"""\n(.*?)\n"""', re.DOTALL)
|
DOCSTRING_PATTERN = re.compile(r'^\s*(?P<quote>"""|\'\'\')\s*(.*?)\s*(?P=quote)', re.DOTALL)
|
||||||
CLASS_PATTERN = re.compile(r'^class (Tools|Filter|Pipe|Action)\s*[\(:]', re.MULTILINE)
|
CLASS_PATTERN = re.compile(r'^class (Tools|Filter|Pipe|Action)\s*[\(:]', re.MULTILINE)
|
||||||
EMOJI_PATTERN = re.compile(r'[\U00010000-\U0010ffff]', re.UNICODE)
|
EMOJI_PATTERN = re.compile(r'[\U00010000-\U0010ffff]', re.UNICODE)
|
||||||
|
METADATA_KEY_PATTERN = re.compile(r"^[A-Za-z_][A-Za-z0-9_-]*$")
|
||||||
|
|
||||||
TRANSLATIONS = {
|
TRANSLATIONS = {
|
||||||
"en-US": {
|
"en-US": {
|
||||||
@@ -476,19 +479,109 @@ class PluginCandidate:
|
|||||||
|
|
||||||
|
|
||||||
def extract_metadata(content: str) -> Dict[str, str]:
|
def extract_metadata(content: str) -> Dict[str, str]:
|
||||||
match = DOCSTRING_PATTERN.search(content)
|
docstring = _extract_module_docstring(content)
|
||||||
if not match:
|
if not docstring:
|
||||||
return {}
|
return {}
|
||||||
|
|
||||||
metadata: Dict[str, str] = {}
|
metadata: Dict[str, str] = {}
|
||||||
for raw_line in match.group(1).splitlines():
|
lines = docstring.splitlines()
|
||||||
line = raw_line.strip()
|
index = 0
|
||||||
if not line or line.startswith("#") or ":" not in line:
|
|
||||||
|
while index < len(lines):
|
||||||
|
raw_line = lines[index]
|
||||||
|
stripped = raw_line.strip()
|
||||||
|
|
||||||
|
if not stripped or stripped.startswith("#"):
|
||||||
|
index += 1
|
||||||
continue
|
continue
|
||||||
key, value = line.split(":", 1)
|
|
||||||
metadata[key.strip().lower()] = value.strip()
|
if raw_line[:1].isspace() or ":" not in raw_line:
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
key, value = raw_line.split(":", 1)
|
||||||
|
key = key.strip().lower()
|
||||||
|
if not METADATA_KEY_PATTERN.match(key):
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
|
||||||
|
value = value.strip()
|
||||||
|
if value and value[0] in {">", "|"}:
|
||||||
|
block_lines, index = _consume_indented_block(lines, index + 1)
|
||||||
|
metadata[key] = (
|
||||||
|
_fold_yaml_block(block_lines)
|
||||||
|
if value[0] == ">"
|
||||||
|
else _preserve_yaml_block(block_lines)
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
|
||||||
|
metadata[key] = value
|
||||||
|
index += 1
|
||||||
|
|
||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
|
def _extract_module_docstring(content: str) -> str:
|
||||||
|
normalized = content.lstrip("\ufeff")
|
||||||
|
|
||||||
|
try:
|
||||||
|
module = ast.parse(normalized)
|
||||||
|
except SyntaxError:
|
||||||
|
module = None
|
||||||
|
|
||||||
|
if module is not None:
|
||||||
|
docstring = ast.get_docstring(module, clean=False)
|
||||||
|
if isinstance(docstring, str):
|
||||||
|
return docstring
|
||||||
|
|
||||||
|
fallback = normalized.replace("\r\n", "\n").replace("\r", "\n")
|
||||||
|
match = DOCSTRING_PATTERN.search(fallback)
|
||||||
|
return match.group(2) if match else ""
|
||||||
|
|
||||||
|
|
||||||
|
def _consume_indented_block(lines: List[str], start_index: int) -> Tuple[List[str], int]:
|
||||||
|
block: List[str] = []
|
||||||
|
index = start_index
|
||||||
|
|
||||||
|
while index < len(lines):
|
||||||
|
line = lines[index]
|
||||||
|
if not line.strip():
|
||||||
|
block.append("")
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
if line[:1].isspace():
|
||||||
|
block.append(line)
|
||||||
|
index += 1
|
||||||
|
continue
|
||||||
|
break
|
||||||
|
|
||||||
|
dedented = textwrap.dedent("\n".join(block)).splitlines()
|
||||||
|
return dedented, index
|
||||||
|
|
||||||
|
|
||||||
|
def _fold_yaml_block(lines: List[str]) -> str:
|
||||||
|
paragraphs: List[str] = []
|
||||||
|
current: List[str] = []
|
||||||
|
|
||||||
|
for line in lines:
|
||||||
|
stripped = line.strip()
|
||||||
|
if not stripped:
|
||||||
|
if current:
|
||||||
|
paragraphs.append(" ".join(current))
|
||||||
|
current = []
|
||||||
|
continue
|
||||||
|
current.append(stripped)
|
||||||
|
|
||||||
|
if current:
|
||||||
|
paragraphs.append(" ".join(current))
|
||||||
|
|
||||||
|
return "\n\n".join(paragraphs).strip()
|
||||||
|
|
||||||
|
|
||||||
|
def _preserve_yaml_block(lines: List[str]) -> str:
|
||||||
|
return "\n".join(line.rstrip() for line in lines).strip()
|
||||||
|
|
||||||
|
|
||||||
def detect_plugin_type(content: str) -> Optional[str]:
|
def detect_plugin_type(content: str) -> Optional[str]:
|
||||||
if "\nclass Tools:" in content or "\nclass Tools (" in content:
|
if "\nclass Tools:" in content or "\nclass Tools (" in content:
|
||||||
return "tool"
|
return "tool"
|
||||||
@@ -767,7 +860,7 @@ async def discover_plugins(
|
|||||||
skipped.append((item_path, "missing title/description"))
|
skipped.append((item_path, "missing title/description"))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if has_emoji(metadata.get("title", "")):
|
if is_default_repo and has_emoji(metadata.get("title", "")):
|
||||||
skipped.append((item_path, "title contains emoji"))
|
skipped.append((item_path, "title contains emoji"))
|
||||||
continue
|
continue
|
||||||
|
|
||||||
|
|||||||
@@ -74,6 +74,17 @@ class FakeAsyncClient:
|
|||||||
return response
|
return response
|
||||||
|
|
||||||
|
|
||||||
|
class FakeGithubAsyncClient:
|
||||||
|
def __init__(self, *args, **kwargs):
|
||||||
|
pass
|
||||||
|
|
||||||
|
async def __aenter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
|
async def __aexit__(self, exc_type, exc, tb):
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.asyncio
|
@pytest.mark.asyncio
|
||||||
async def test_install_all_plugins_only_installs_filtered_candidates(monkeypatch):
|
async def test_install_all_plugins_only_installs_filtered_candidates(monkeypatch):
|
||||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||||
@@ -300,3 +311,94 @@ async def test_install_all_plugins_emits_frontend_debug_logs_on_connect_error(
|
|||||||
assert any("http://localhost:3000" in code for code in execute_codes)
|
assert any("http://localhost:3000" in code for code in execute_codes)
|
||||||
assert events[-1]["type"] == "notification"
|
assert events[-1]["type"] == "notification"
|
||||||
assert events[-1]["data"]["type"] == "error"
|
assert events[-1]["data"]["type"] == "error"
|
||||||
|
|
||||||
|
|
||||||
|
def test_extract_metadata_supports_crlf_and_folded_yaml_docstrings():
|
||||||
|
content = (
|
||||||
|
'"""\r\n'
|
||||||
|
"title: Persona Selector\r\n"
|
||||||
|
"author: ichrist\r\n"
|
||||||
|
"description: >\r\n"
|
||||||
|
" Two-step persona picker. Step 1: numbered category list (16 categories).\r\n"
|
||||||
|
" Step 2: numbered persona list (10 per category). 160 personas + Custom.\r\n"
|
||||||
|
"version: 6.0.2\r\n"
|
||||||
|
'"""\r\n\r\n'
|
||||||
|
"class Tools:\r\n"
|
||||||
|
" pass\r\n"
|
||||||
|
)
|
||||||
|
|
||||||
|
metadata = batch_install_plugins.extract_metadata(content)
|
||||||
|
|
||||||
|
assert metadata["title"] == "Persona Selector"
|
||||||
|
assert metadata["author"] == "ichrist"
|
||||||
|
assert metadata["version"] == "6.0.2"
|
||||||
|
assert metadata["description"] == (
|
||||||
|
"Two-step persona picker. Step 1: numbered category list (16 categories). "
|
||||||
|
"Step 2: numbered persona list (10 per category). 160 personas + Custom."
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.asyncio
|
||||||
|
async def test_discover_plugins_supports_community_repo_crlf_docstrings(monkeypatch):
|
||||||
|
tree = [
|
||||||
|
{"type": "blob", "path": "Tools/ask-user.py"},
|
||||||
|
{"type": "blob", "path": "Tools/persona.py"},
|
||||||
|
{"type": "blob", "path": "Tools/orchestrator.py"},
|
||||||
|
]
|
||||||
|
contents = {
|
||||||
|
"Tools/ask-user.py": (
|
||||||
|
'"""\r\n'
|
||||||
|
"title: Ask User\r\n"
|
||||||
|
"author: ichrist\r\n"
|
||||||
|
"version: 1.0\r\n"
|
||||||
|
"description: Allows the LLM to autonomously trigger 1-5 interactive pop-up questions.\r\n"
|
||||||
|
'"""\r\n\r\n'
|
||||||
|
"class Tools:\r\n"
|
||||||
|
" pass\r\n"
|
||||||
|
),
|
||||||
|
"Tools/persona.py": (
|
||||||
|
'"""\r\n'
|
||||||
|
"title: Persona Selector\r\n"
|
||||||
|
"author: ichrist\r\n"
|
||||||
|
"description: >\r\n"
|
||||||
|
" Two-step persona picker. Step 1: numbered category list (16 categories).\r\n"
|
||||||
|
" Step 2: numbered persona list (10 per category). 160 personas + Custom.\r\n"
|
||||||
|
"version: 6.0.2\r\n"
|
||||||
|
'"""\r\n\r\n'
|
||||||
|
"class Tools:\r\n"
|
||||||
|
" pass\r\n"
|
||||||
|
),
|
||||||
|
"Tools/orchestrator.py": (
|
||||||
|
'"""\r\n'
|
||||||
|
"title: 🌌 The Omniscient Orchestrator\r\n"
|
||||||
|
"author: ichrist\r\n"
|
||||||
|
"version: 2.0\r\n"
|
||||||
|
"description: A high-polish, multi-stage workflow engine.\r\n"
|
||||||
|
'"""\r\n\r\n'
|
||||||
|
"class Tools:\r\n"
|
||||||
|
" pass\r\n"
|
||||||
|
),
|
||||||
|
}
|
||||||
|
|
||||||
|
async def fake_fetch_tree(client, owner, repo, branch):
|
||||||
|
assert (owner, repo, branch) == ("iChristGit", "OpenWebui-Tools", "main")
|
||||||
|
return tree
|
||||||
|
|
||||||
|
async def fake_fetch_file(client, owner, repo, branch, path):
|
||||||
|
return contents[path]
|
||||||
|
|
||||||
|
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeGithubAsyncClient)
|
||||||
|
monkeypatch.setattr(batch_install_plugins, "fetch_github_tree", fake_fetch_tree)
|
||||||
|
monkeypatch.setattr(batch_install_plugins, "fetch_github_file", fake_fetch_file)
|
||||||
|
|
||||||
|
candidates, skipped = await batch_install_plugins.discover_plugins(
|
||||||
|
"https://github.com/iChristGit/OpenWebui-Tools/",
|
||||||
|
batch_install_plugins.DEFAULT_SKIP_KEYWORDS,
|
||||||
|
)
|
||||||
|
|
||||||
|
assert sorted(candidate.title for candidate in candidates) == [
|
||||||
|
"Ask User",
|
||||||
|
"Persona Selector",
|
||||||
|
"🌌 The Omniscient Orchestrator",
|
||||||
|
]
|
||||||
|
assert skipped == []
|
||||||
|
|||||||
Reference in New Issue
Block a user