feat(batch-install-plugins): initial release v1.0.0
Add Batch Install Plugins from GitHub tool with: - One-click installation of plugins from GitHub repositories - Smart plugin discovery with metadata extraction and validation - Confirmation dialog with plugin list preview - Selective installation with keyword-based filtering - Smart fallback: auto-retry with localhost:8080 on connection failure - Enhanced debugging with frontend and backend logging - 120-second confirmation timeout for user convenience - Async httpx client for non-blocking I/O - Complete i18n support across 11 languages - Event emitter handling with fallback support - Timeout guards on frontend JavaScript execution - Filtered list consistency for confirmation and installation - Auto-exclusion of tool itself from batch operations - 6 regression tests with 100% pass rate Documentation includes: - English and Chinese READMEs with flow diagrams - Popular repository examples (iChristGit, Haervwe, Classic298, suurt8ll) - Mirrored docs for official documentation site - Plugin index entries in both languages - Comprehensive release notes (v1.0.0.md and v1.0.0_CN.md) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
139
docs/plugins/tools/batch-install-plugins-tool.md
Normal file
139
docs/plugins/tools/batch-install-plugins-tool.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# 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
|
||||
|
||||
---
|
||||
|
||||
One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **One-Click Install**: Install all plugins with a single command
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **GitHub Support**: Install plugins from any GitHub repository
|
||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
||||
- **i18n**: Supports 11 languages
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
User Input
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Discover Plugins from GitHub │
|
||||
│ (fetch file tree + parse .py) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Filter by Type & Keywords │
|
||||
│ (tool/filter/pipe/action) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Show Confirmation Dialog │
|
||||
│ (list plugins + exclude hint) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [Cancel] → End
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Install to OpenWebUI │
|
||||
│ (update or create each plugin) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
Done
|
||||
```
|
||||
|
||||
## How to Use
|
||||
|
||||
1. Open OpenWebUI and go to **Workspace > Tools**
|
||||
2. Install **Batch Install Plugins from GitHub** from the official marketplace
|
||||
3. Enable this tool for your model/chat
|
||||
4. Ask the model to install plugins
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```
|
||||
"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
|
||||
|
||||
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 tools from Haervwe's tools collection
|
||||
"Install all plugins from Haervwe/open-webui-tools"
|
||||
|
||||
# Install all plugins from Classic298's repository
|
||||
"Install all plugins from Classic298/open-webui-plugins"
|
||||
|
||||
# Install all functions from suurt8ll's collection
|
||||
"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"
|
||||
```
|
||||
|
||||
### Supported Repositories
|
||||
|
||||
- `Fu-Jie/openwebui-extensions` - Default, official plugin collection
|
||||
- `iChristGit/OpenWebui-Tools` - Comprehensive tool and plugin collection
|
||||
- `Haervwe/open-webui-tools` - Specialized tools and utilities
|
||||
- `Classic298/open-webui-plugins` - Various plugin implementations
|
||||
- `suurt8ll/open_webui_functions` - Function-based plugins
|
||||
|
||||
## Default Repository
|
||||
|
||||
When no repository is specified, defaults to `Fu-Jie/openwebui-extensions`.
|
||||
|
||||
## Plugin Detection Rules
|
||||
|
||||
### Fu-Jie/openwebui-extensions (Strict)
|
||||
|
||||
For the default repository, plugins must have:
|
||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** fields
|
||||
3. Filename must not end with `_cn`
|
||||
|
||||
### Other GitHub Repositories
|
||||
|
||||
For other repositories:
|
||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||
2. A docstring with `title:` and `description:` fields
|
||||
|
||||
## Configuration (Valves)
|
||||
|
||||
| Parameter | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | Comma-separated keywords to skip |
|
||||
| `TIMEOUT` | `20` | Request timeout in seconds |
|
||||
|
||||
## Confirmation Timeout
|
||||
|
||||
User confirmation dialogs have a default timeout of **2 minutes (120 seconds)**, allowing sufficient time for users to:
|
||||
- Read and review the plugin list
|
||||
- Make installation decisions
|
||||
- Handle network delays
|
||||
|
||||
## 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.
|
||||
139
docs/plugins/tools/batch-install-plugins-tool.zh.md
Normal file
139
docs/plugins/tools/batch-install-plugins-tool.zh.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Batch Install Plugins from GitHub - 从 GitHub 批量安装插件
|
||||
|
||||
**作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.0.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可:** MIT
|
||||
|
||||
---
|
||||
|
||||
一键从 GitHub 仓库批量安装插件到你的 OpenWebUI 实例。
|
||||
|
||||
## ✨ 主要特性
|
||||
|
||||
- **一键安装**: 一条命令安装所有插件
|
||||
- **自动更新**: 自动更新之前已安装的插件
|
||||
- **GitHub 支持**: 支持从任何 GitHub 仓库安装插件
|
||||
- **多类型支持**: 支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- **确认机制**: 安装前显示插件列表,允许选择性安装
|
||||
- **国际化**: 支持 11 种语言
|
||||
|
||||
## 工作流
|
||||
|
||||
```
|
||||
用户输入
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 从 GitHub 发现插件 │
|
||||
│ (获取文件树 + 解析 .py) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 按类型和关键词过滤 │
|
||||
│ (tool/filter/pipe/action) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 显示确认对话框 │
|
||||
│ (插件列表 + 排除提示) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [取消] → 结束
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 安装到 OpenWebUI │
|
||||
│ (更新或创建每个插件) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
完成
|
||||
```
|
||||
|
||||
## 🚀 使用方法
|
||||
|
||||
1. 打开 OpenWebUI,进入 **工作区 > 工具**
|
||||
2. 从官方市场安装 **Batch Install Plugins from GitHub**
|
||||
3. 为你的模型/聊天启用此工具
|
||||
4. 让模型安装插件
|
||||
|
||||
## 使用示例
|
||||
|
||||
```
|
||||
"安装所有插件"
|
||||
"从 github.com/username/repo 安装所有插件"
|
||||
"仅安装 pipe 插件"
|
||||
"安装 action 和 filter 插件"
|
||||
"安装所有插件,exclude_keywords=copilot"
|
||||
```
|
||||
|
||||
## 热门插件仓库
|
||||
|
||||
这些是包含大量插件的热门仓库,你可以从中安装插件:
|
||||
|
||||
### 社区合集
|
||||
|
||||
```
|
||||
# 从 iChristGit 的集合安装所有插件
|
||||
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||
|
||||
# 从 Haervwe 的工具集合只安装工具
|
||||
"从 Haervwe/open-webui-tools 安装所有插件"
|
||||
|
||||
# 从 Classic298 的仓库安装所有插件
|
||||
"从 Classic298/open-webui-plugins 安装所有插件"
|
||||
|
||||
# 从 suurt8ll 的集合安装所有函数
|
||||
"从 suurt8ll/open_webui_functions 安装所有插件"
|
||||
|
||||
# 仅安装特定类型的插件(比如只安装工具)
|
||||
"从 iChristGit/OpenWebui-Tools 仅安装 tool 插件"
|
||||
|
||||
# 安装时排除特定关键词
|
||||
"从 Haervwe/open-webui-tools 安装所有插件,exclude_keywords=test,deprecated"
|
||||
```
|
||||
|
||||
### 支持的仓库
|
||||
|
||||
- `Fu-Jie/openwebui-extensions` - 默认的官方插件集合
|
||||
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
||||
- `Haervwe/open-webui-tools` - 专业的工具和实用程序
|
||||
- `Classic298/open-webui-plugins` - 各种插件实现
|
||||
- `suurt8ll/open_webui_functions` - 基于函数的插件
|
||||
|
||||
## 默认仓库
|
||||
|
||||
未指定仓库时,默认使用 `Fu-Jie/openwebui-extensions`。
|
||||
|
||||
## 插件检测规则
|
||||
|
||||
### Fu-Jie/openwebui-extensions(严格模式)
|
||||
|
||||
对于默认仓库,插件必须有:
|
||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||
2. 包含 `title:`、`description:` 和 **`openwebui_id:`** 字段的文档字符串
|
||||
3. 文件名不能以 `_cn` 结尾
|
||||
|
||||
### 其他 GitHub 仓库
|
||||
|
||||
对于其他仓库:
|
||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||
2. 包含 `title:` 和 `description:` 字段的文档字符串
|
||||
|
||||
## 配置 (Valves)
|
||||
|
||||
| 参数 | 默认值 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | 要跳过的关键词,用逗号分隔 |
|
||||
| `TIMEOUT` | `20` | 请求超时时间(秒) |
|
||||
|
||||
## 确认超时时间
|
||||
|
||||
用户确认对话框的默认超时时间为 **2 分钟(120 秒)**,为用户提供充足的时间来:
|
||||
- 阅读和查看插件列表
|
||||
- 做出安装决定
|
||||
- 处理网络延迟
|
||||
|
||||
## 支持
|
||||
|
||||
如果这个插件对你有帮助,欢迎到 [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) 点个 Star,这将是我持续改进的动力,感谢支持。
|
||||
@@ -4,5 +4,6 @@ OpenWebUI native Tool plugins that can be used across models.
|
||||
|
||||
## Available Tool Plugins
|
||||
|
||||
- [Batch Install Plugins from GitHub](batch-install-plugins-tool.md) (v1.0.0) - One-click batch install plugins from GitHub repositories with confirmation and multi-language support.
|
||||
- [OpenWebUI Skills Manager Tool](openwebui-skills-manager-tool.md) (v0.3.0) - Simple native skill management (`list/show/install/create/update/delete`).
|
||||
- [Smart Mind Map Tool](smart-mind-map-tool.md) (v1.0.0) - Intelligently analyzes text content and proactively generates interactive mind maps to help users structure and visualize knowledge.
|
||||
|
||||
@@ -4,5 +4,6 @@
|
||||
|
||||
## 可用 Tool 插件
|
||||
|
||||
- [Batch Install Plugins from GitHub](batch-install-plugins-tool.zh.md) (v1.0.0) - 一键从 GitHub 仓库批量安装插件,支持确认和多语言。
|
||||
- [OpenWebUI Skills 管理工具](openwebui-skills-manager-tool.zh.md) (v0.3.0) - 简化技能管理(`list/show/install/create/update/delete`)。
|
||||
- [智能思维导图工具 (Smart Mind Map Tool)](smart-mind-map-tool.zh.md) (v1.0.0) - 智能分析文本内容并主动生成交互式思维导图,帮助用户结构化与可视化知识。
|
||||
|
||||
137
plugins/tools/batch-install-plugins/README.md
Normal file
137
plugins/tools/batch-install-plugins/README.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# 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)
|
||||
|
||||
One-click batch install plugins from GitHub repositories to your OpenWebUI instance.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **One-Click Install**: Install all plugins with a single command
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **GitHub Support**: Install plugins from any GitHub repository
|
||||
- **Multi-Type Support**: Supports Pipe, Action, Filter, and Tool plugins
|
||||
- **Confirmation**: Shows plugin list before installing, allows selective installation
|
||||
- **i18n**: Supports 11 languages
|
||||
|
||||
## Flow
|
||||
|
||||
```
|
||||
User Input
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Discover Plugins from GitHub │
|
||||
│ (fetch file tree + parse .py) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Filter by Type & Keywords │
|
||||
│ (tool/filter/pipe/action) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Show Confirmation Dialog │
|
||||
│ (list plugins + exclude hint) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [Cancel] → End
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ Install to OpenWebUI │
|
||||
│ (update or create each plugin) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
Done
|
||||
```
|
||||
|
||||
## How to Use
|
||||
|
||||
1. Open OpenWebUI and go to **Workspace > Tools**
|
||||
2. Install **Batch Install Plugins from GitHub** from the official marketplace
|
||||
3. Enable this tool for your model/chat
|
||||
4. Ask the model to install plugins
|
||||
|
||||
## Usage Examples
|
||||
|
||||
```
|
||||
"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
|
||||
|
||||
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 tools from Haervwe's tools collection
|
||||
"Install all plugins from Haervwe/open-webui-tools"
|
||||
|
||||
# Install all plugins from Classic298's repository
|
||||
"Install all plugins from Classic298/open-webui-plugins"
|
||||
|
||||
# Install all functions from suurt8ll's collection
|
||||
"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"
|
||||
```
|
||||
|
||||
### Supported Repositories
|
||||
|
||||
- `Fu-Jie/openwebui-extensions` - Default, official plugin collection
|
||||
- `iChristGit/OpenWebui-Tools` - Comprehensive tool and plugin collection
|
||||
- `Haervwe/open-webui-tools` - Specialized tools and utilities
|
||||
- `Classic298/open-webui-plugins` - Various plugin implementations
|
||||
- `suurt8ll/open_webui_functions` - Function-based plugins
|
||||
|
||||
## Default Repository
|
||||
|
||||
When no repository is specified, defaults to `Fu-Jie/openwebui-extensions`.
|
||||
|
||||
## Plugin Detection Rules
|
||||
|
||||
### Fu-Jie/openwebui-extensions (Strict)
|
||||
|
||||
For the default repository, plugins must have:
|
||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||
2. A docstring with `title:`, `description:`, and **`openwebui_id:`** fields
|
||||
3. Filename must not end with `_cn`
|
||||
|
||||
### Other GitHub Repositories
|
||||
|
||||
For other repositories:
|
||||
1. A `.py` file containing `class Tools:`, `class Filter:`, `class Pipe:`, or `class Action:`
|
||||
2. A docstring with `title:` and `description:` fields
|
||||
|
||||
## Configuration (Valves)
|
||||
|
||||
| Parameter | Default | Description |
|
||||
| --- | --- | --- |
|
||||
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | Comma-separated keywords to skip |
|
||||
| `TIMEOUT` | `20` | Request timeout in seconds |
|
||||
|
||||
## Confirmation Timeout
|
||||
|
||||
User confirmation dialogs have a default timeout of **2 minutes (120 seconds)**, allowing sufficient time for users to:
|
||||
- Read and review the plugin list
|
||||
- Make installation decisions
|
||||
- Handle network delays
|
||||
|
||||
## 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.
|
||||
137
plugins/tools/batch-install-plugins/README_CN.md
Normal file
137
plugins/tools/batch-install-plugins/README_CN.md
Normal file
@@ -0,0 +1,137 @@
|
||||
# Batch Install Plugins from GitHub
|
||||
|
||||
**作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 1.0.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions)
|
||||
|
||||
一键将 GitHub 仓库中的插件批量安装到你的 OpenWebUI 实例。
|
||||
|
||||
## 主要功能
|
||||
|
||||
- 一键安装:单个命令安装所有插件
|
||||
- 自动更新:自动更新之前安装过的插件
|
||||
- GitHub 支持:从任意 GitHub 仓库安装插件
|
||||
- 多类型支持:支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- 安装确认:安装前显示插件列表,支持选择性安装
|
||||
- 国际化:支持 11 种语言
|
||||
|
||||
## 流程
|
||||
|
||||
```
|
||||
用户输入
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 从 GitHub 发现插件 │
|
||||
│ (获取文件树 + 解析 .py 文件) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 按类型和关键词过滤 │
|
||||
│ (tool/filter/pipe/action) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 显示确认对话框 │
|
||||
│ (插件列表 + 排除提示) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
├── [取消] → 结束
|
||||
│
|
||||
▼
|
||||
┌─────────────────────────────────────┐
|
||||
│ 安装到 OpenWebUI │
|
||||
│ (更新或创建每个插件) │
|
||||
└─────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
完成
|
||||
```
|
||||
|
||||
## 使用方法
|
||||
|
||||
1. 打开 OpenWebUI,进入 **Workspace > Tools**
|
||||
2. 从官方市场安装 **Batch Install Plugins from GitHub**
|
||||
3. 为你的模型/对话启用此工具
|
||||
4. 让模型调用工具方法
|
||||
|
||||
## 使用示例
|
||||
|
||||
```
|
||||
"安装所有插件"
|
||||
"从 github.com/username/repo 安装所有插件"
|
||||
"只安装 pipe 插件"
|
||||
"安装 action 和 filter 插件"
|
||||
"安装所有插件, exclude_keywords=copilot"
|
||||
```
|
||||
|
||||
## 热门插件仓库
|
||||
|
||||
这些是包含大量插件的热门仓库,你可以从中安装插件:
|
||||
|
||||
### 社区合集
|
||||
|
||||
```
|
||||
# 从 iChristGit 的集合安装所有插件
|
||||
"从 iChristGit/OpenWebui-Tools 安装所有插件"
|
||||
|
||||
# 从 Haervwe 的工具集合只安装工具
|
||||
"从 Haervwe/open-webui-tools 安装所有插件"
|
||||
|
||||
# 从 Classic298 的仓库安装所有插件
|
||||
"从 Classic298/open-webui-plugins 安装所有插件"
|
||||
|
||||
# 从 suurt8ll 的集合安装所有函数
|
||||
"从 suurt8ll/open_webui_functions 安装所有插件"
|
||||
|
||||
# 只安装特定类型的插件(比如只安装工具)
|
||||
"从 iChristGit/OpenWebui-Tools 只安装 tool 插件"
|
||||
|
||||
# 安装时排除特定关键词
|
||||
"从 Haervwe/open-webui-tools 安装所有插件, exclude_keywords=test,deprecated"
|
||||
```
|
||||
|
||||
### 支持的仓库
|
||||
|
||||
- `Fu-Jie/openwebui-extensions` - 默认的官方插件集合
|
||||
- `iChristGit/OpenWebui-Tools` - 全面的工具和插件集合
|
||||
- `Haervwe/open-webui-tools` - 专业的工具和实用程序
|
||||
- `Classic298/open-webui-plugins` - 各种插件实现
|
||||
- `suurt8ll/open_webui_functions` - 基于函数的插件
|
||||
|
||||
## 默认仓库
|
||||
|
||||
未指定仓库时,默认为 `Fu-Jie/openwebui-extensions`。
|
||||
|
||||
## 插件检测规则
|
||||
|
||||
### Fu-Jie/openwebui-extensions(严格模式)
|
||||
|
||||
默认仓库的插件必须满足:
|
||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||
2. Docstring 中包含 `title:`、`description:` 和 **`openwebui_id:`** 字段
|
||||
3. 文件名不能以 `_cn` 结尾
|
||||
|
||||
### 其他 GitHub 仓库
|
||||
|
||||
其他仓库的插件必须满足:
|
||||
1. 包含 `class Tools:`、`class Filter:`、`class Pipe:` 或 `class Action:` 的 `.py` 文件
|
||||
2. Docstring 中包含 `title:` 和 `description:` 字段
|
||||
|
||||
## 配置(Valves)
|
||||
|
||||
| 参数 | 默认值 | 描述 |
|
||||
| --- | --- | --- |
|
||||
| `SKIP_KEYWORDS` | `test,verify,example,template,mock` | 逗号分隔的跳过关键词 |
|
||||
| `TIMEOUT` | `20` | 请求超时时间(秒)|
|
||||
|
||||
## 确认超时时间
|
||||
|
||||
用户确认对话框的默认超时时间为 **2 分钟(120 秒)**,为用户提供充足的时间来:
|
||||
- 阅读和查看插件列表
|
||||
- 做出安装决定
|
||||
- 处理网络延迟
|
||||
|
||||
## 支持
|
||||
|
||||
如果这个插件对你有帮助,欢迎到 [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) 点个 Star,这将是我持续改进的动力,感谢支持。
|
||||
1262
plugins/tools/batch-install-plugins/batch_install_plugins.py
Normal file
1262
plugins/tools/batch-install-plugins/batch_install_plugins.py
Normal file
File diff suppressed because it is too large
Load Diff
67
plugins/tools/batch-install-plugins/v1.0.0.md
Normal file
67
plugins/tools/batch-install-plugins/v1.0.0.md
Normal file
@@ -0,0 +1,67 @@
|
||||
[](https://openwebui.com/t/fujie/batch_install_plugins)
|
||||
|
||||
## Overview
|
||||
|
||||
Batch Install Plugins from GitHub is a new tool for OpenWebUI that enables one-click installation of multiple plugins directly from GitHub repositories. This initial release includes comprehensive features for discovering, filtering, and installing plugins with user confirmation, extensive multi-language support, and robust debugging capabilities for container deployments.
|
||||
|
||||
**[📖 README](https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/tools/batch-install-plugins/README.md)**
|
||||
|
||||
## Features
|
||||
|
||||
- **One-Click Installation**: Install all plugins from a repository with a single command
|
||||
- **Smart Plugin Discovery**: Parse Python files to extract metadata and validate plugins automatically
|
||||
- **Multi-Type Support**: Support Pipe, Action, Filter, and Tool plugins in a single operation
|
||||
- **Confirmation Dialog**: Display plugin list before installation for user review and approval
|
||||
- **Selective Installation**: Exclude specific plugins using keyword-based filtering
|
||||
- **Smart Fallback**: Container deployments auto-retry with localhost:8080 if primary connection fails
|
||||
- **Enhanced Debugging**: Rich frontend JavaScript and backend Python logs for troubleshooting
|
||||
- **Extended Timeout**: 120-second confirmation window for thoughtful decision-making
|
||||
- **Async Architecture**: Non-blocking I/O operations for better performance
|
||||
- **Full Internationalization**: Complete support for 11 languages with proper fallback maps
|
||||
- **Auto-Update**: Automatically updates previously installed plugins
|
||||
- **Self-Exclusion**: Automatically excludes the tool itself from batch operations
|
||||
|
||||
## Technical Highlights
|
||||
|
||||
- **httpx Integration**: Modern async HTTP client for reliable, non-blocking requests
|
||||
- **Event Emitter Support**: Proper handling of OpenWebUI event injection with fallbacks
|
||||
- **Timeout Protection**: Wrapped frontend execution with timeout guards to prevent hanging
|
||||
- **Filtered List Consistency**: Uses single source of truth for confirmation and installation
|
||||
- **Error Localization**: All error messages are user-facing and properly localized across languages
|
||||
- **Deployment Resilience**: Intelligent base URL resolution handles domain, localhost, and containerized environments
|
||||
|
||||
## Supported Repositories
|
||||
|
||||
- **Default**: Fu-Jie/openwebui-extensions (strict validation)
|
||||
- **Custom**: Any GitHub repository with Python plugin files
|
||||
|
||||
## Testing
|
||||
|
||||
Comprehensive regression tests included:
|
||||
- Filtered installation list consistency
|
||||
- Missing event emitter handling
|
||||
- Confirmation timeout verification
|
||||
- Full failure scenarios
|
||||
- Localization completeness
|
||||
- Connection error debug logging and smart fallback
|
||||
|
||||
All 6 tests pass successfully.
|
||||
|
||||
## Documentation
|
||||
|
||||
- English README with flow diagrams and usage examples
|
||||
- Chinese README (README_CN.md) with complete translations
|
||||
- Mirrored documentation for official docs site
|
||||
- Plugin index entries in both English and Chinese
|
||||
|
||||
## Compatibility
|
||||
|
||||
- OpenWebUI: 0.2.x - 0.8.x
|
||||
- Python: 3.9+
|
||||
- Dependencies: httpx (async HTTP client), pydantic (type validation)
|
||||
|
||||
## Release Notes
|
||||
|
||||
- This initial v1.0.0 release includes complete plugin infrastructure with smart deployment handling.
|
||||
- The plugin is designed to handle diverse deployment scenarios (domain, localhost, containerized) with minimal configuration.
|
||||
|
||||
67
plugins/tools/batch-install-plugins/v1.0.0_CN.md
Normal file
67
plugins/tools/batch-install-plugins/v1.0.0_CN.md
Normal file
@@ -0,0 +1,67 @@
|
||||
[](https://openwebui.com/t/fujie/batch_install_plugins)
|
||||
|
||||
## 概述
|
||||
|
||||
从 GitHub 批量安装插件是一款全新的 OpenWebUI 工具,支持直接从 GitHub 仓库一键安装多个插件。此首个发布版本包含了全面的插件发现、过滤和安装功能,支持用户确认流程、广泛的多语言支持,以及针对容器部署的健壮调试能力。
|
||||
|
||||
**[📖 README](https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/tools/batch-install-plugins/README_CN.md)**
|
||||
|
||||
## 主要功能
|
||||
|
||||
- **一键安装**:通过单个命令安装仓库中的所有插件
|
||||
- **智能插件发现**:解析 Python 文件提取元数据并自动验证插件
|
||||
- **多类型支持**:在单个操作中支持 Pipe、Action、Filter 和 Tool 插件
|
||||
- **确认对话框**:安装前显示插件列表供用户审查和批准
|
||||
- **选择性安装**:通过基于关键词的过滤排除特定插件
|
||||
- **智能降级**:容器环境中主 URL 连接失败时自动重试 localhost:8080
|
||||
- **增强调试**:前端 JavaScript 和后端 Python 富日志输出,便于排查问题
|
||||
- **延长超时**:120 秒确认窗口,给用户充分的思考时间
|
||||
- **异步架构**:非阻塞 I/O 操作,性能更优
|
||||
- **完整国际化**:支持 11 种语言,包含适当的回退机制
|
||||
- **自动更新**:自动更新之前安装过的插件
|
||||
- **自排除机制**:自动排除工具自身,避免在批量操作中重复安装
|
||||
|
||||
## 技术亮点
|
||||
|
||||
- **httpx 集成**:现代化的异步 HTTP 客户端,请求更可靠且非阻塞
|
||||
- **事件注入支持**:正确处理 OpenWebUI 事件注入,提供回退支持
|
||||
- **超时保护**:前端执行周围包装了超时保护,防止进程挂起
|
||||
- **过滤列表一致性**:确认和安装使用同一份过滤列表
|
||||
- **错误本地化**:所有错误消息都是面向用户的,已正确本地化到各语言
|
||||
- **部署弹性**:智能 Base URL 解析处理域名、localhost 和容器化环境
|
||||
|
||||
## 支持的仓库
|
||||
|
||||
- **默认**:Fu-Jie/openwebui-extensions(严格验证)
|
||||
- **自定义**:任意 GitHub 仓库中的 Python 插件文件
|
||||
|
||||
## 测试覆盖
|
||||
|
||||
包含全面的回归测试:
|
||||
- 过滤安装列表一致性
|
||||
- 缺少事件注入器时的处理
|
||||
- 确认超时验证
|
||||
- 完全失败场景
|
||||
- 本地化完整性
|
||||
- 连接错误调试日志和智能降级
|
||||
|
||||
所有 6 个测试均通过。
|
||||
|
||||
## 文档
|
||||
|
||||
- 英文 README,包含流程图和使用示例
|
||||
- 中文 README (README_CN.md),完整翻译
|
||||
- 官方文档站点的镜像文档
|
||||
- 英文和中文的插件索引条目
|
||||
|
||||
## 兼容性
|
||||
|
||||
- OpenWebUI:0.2.x - 0.8.x
|
||||
- Python:3.9+
|
||||
- 依赖:httpx(异步 HTTP 客户端)、pydantic(类型验证)
|
||||
|
||||
## 发布说明
|
||||
|
||||
- 本首发 v1.0.0 版本包含完整的插件基础设施和智能部署处理能力。
|
||||
- 该插件设计用于处理多种部署场景(域名、localhost、容器化),配置最少。
|
||||
|
||||
302
tests/plugins/tools/test_batch_install_plugins.py
Normal file
302
tests/plugins/tools/test_batch_install_plugins.py
Normal file
@@ -0,0 +1,302 @@
|
||||
import asyncio
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
import httpx
|
||||
import pytest
|
||||
|
||||
|
||||
MODULE_PATH = (
|
||||
Path(__file__).resolve().parents[3]
|
||||
/ "plugins"
|
||||
/ "tools"
|
||||
/ "batch-install-plugins"
|
||||
/ "batch_install_plugins.py"
|
||||
)
|
||||
SPEC = importlib.util.spec_from_file_location("batch_install_plugins", MODULE_PATH)
|
||||
batch_install_plugins = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC.loader is not None
|
||||
sys.modules[SPEC.name] = batch_install_plugins
|
||||
SPEC.loader.exec_module(batch_install_plugins)
|
||||
|
||||
|
||||
def make_candidate(title: str, file_path: str, function_id: str):
|
||||
return batch_install_plugins.PluginCandidate(
|
||||
plugin_type="tool",
|
||||
file_path=file_path,
|
||||
metadata={"title": title, "description": f"{title} description"},
|
||||
content="class Tools:\n pass\n",
|
||||
function_id=function_id,
|
||||
)
|
||||
|
||||
|
||||
def make_request():
|
||||
class Request:
|
||||
base_url = "http://localhost:3000/"
|
||||
headers = {"Authorization": "Bearer token"}
|
||||
|
||||
return Request()
|
||||
|
||||
|
||||
class DummyResponse:
|
||||
def __init__(self, status_code: int, json_data=None, text: str = ""):
|
||||
self.status_code = status_code
|
||||
self._json_data = json_data
|
||||
self.text = text
|
||||
|
||||
def json(self):
|
||||
if self._json_data is None:
|
||||
raise ValueError("no json body")
|
||||
return self._json_data
|
||||
|
||||
|
||||
class FakeAsyncClient:
|
||||
posts = []
|
||||
responses = []
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
pass
|
||||
|
||||
async def __aenter__(self):
|
||||
return self
|
||||
|
||||
async def __aexit__(self, exc_type, exc, tb):
|
||||
return False
|
||||
|
||||
async def post(self, url, headers=None, json=None):
|
||||
type(self).posts.append((url, headers, json))
|
||||
if not type(self).responses:
|
||||
raise AssertionError("No fake response configured for POST request")
|
||||
response = type(self).responses.pop(0)
|
||||
if isinstance(response, Exception):
|
||||
raise response
|
||||
return response
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_only_installs_filtered_candidates(monkeypatch):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
exclude = make_candidate(
|
||||
"Exclude Me",
|
||||
"plugins/tools/exclude-me/exclude_me.py",
|
||||
"exclude_me",
|
||||
)
|
||||
self_plugin = make_candidate(
|
||||
"Batch Install Plugins from GitHub",
|
||||
"plugins/tools/batch-install-plugins/batch_install_plugins.py",
|
||||
"batch_install_plugins",
|
||||
)
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep, exclude, self_plugin], []
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
FakeAsyncClient.posts = []
|
||||
FakeAsyncClient.responses = [DummyResponse(404), DummyResponse(201)]
|
||||
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeAsyncClient)
|
||||
|
||||
events = []
|
||||
captured = {}
|
||||
|
||||
async def event_call(payload):
|
||||
if payload["type"] == "confirmation":
|
||||
captured["message"] = payload["data"]["message"]
|
||||
elif payload["type"] == "execute":
|
||||
captured.setdefault("execute_codes", []).append(payload["data"]["code"])
|
||||
return True
|
||||
|
||||
async def emitter(event):
|
||||
events.append(event)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "en-US"},
|
||||
__event_call__=event_call,
|
||||
__request__=make_request(),
|
||||
__event_emitter__=emitter,
|
||||
repo=batch_install_plugins.DEFAULT_REPO,
|
||||
plugin_types=["tool"],
|
||||
exclude_keywords="exclude",
|
||||
)
|
||||
|
||||
assert "Created: Keep Plugin" in result
|
||||
assert "Exclude Me" not in result
|
||||
assert "1/1" in result
|
||||
assert captured["message"].count("[tool]") == 1
|
||||
assert "Keep Plugin" in captured["message"]
|
||||
assert "Exclude Me" not in captured["message"]
|
||||
assert "Batch Install Plugins from GitHub" not in captured["message"]
|
||||
assert "exclude, batch-install-plugins" in captured["message"]
|
||||
|
||||
urls = [url for url, _, _ in FakeAsyncClient.posts]
|
||||
assert urls == [
|
||||
"http://localhost:3000/api/v1/tools/id/keep_plugin/update",
|
||||
"http://localhost:3000/api/v1/tools/create",
|
||||
]
|
||||
assert any(
|
||||
"Starting OpenWebUI install requests" in code
|
||||
for code in captured.get("execute_codes", [])
|
||||
)
|
||||
assert events[-1]["type"] == "notification"
|
||||
assert events[-1]["data"]["type"] == "success"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_supports_missing_event_emitter(monkeypatch):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep], []
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
FakeAsyncClient.posts = []
|
||||
FakeAsyncClient.responses = [DummyResponse(404), DummyResponse(201)]
|
||||
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeAsyncClient)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "en-US"},
|
||||
__request__=make_request(),
|
||||
repo="example/repo",
|
||||
plugin_types=["tool"],
|
||||
)
|
||||
|
||||
assert "Created: Keep Plugin" in result
|
||||
assert "1/1" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_handles_confirmation_timeout(monkeypatch):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep], []
|
||||
|
||||
async def fake_wait_for(awaitable, timeout):
|
||||
awaitable.close()
|
||||
raise asyncio.TimeoutError
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
monkeypatch.setattr(batch_install_plugins.asyncio, "wait_for", fake_wait_for)
|
||||
|
||||
events = []
|
||||
|
||||
async def event_call(payload):
|
||||
return True
|
||||
|
||||
async def emitter(event):
|
||||
events.append(event)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "en-US"},
|
||||
__event_call__=event_call,
|
||||
__request__=make_request(),
|
||||
__event_emitter__=emitter,
|
||||
repo="example/repo",
|
||||
plugin_types=["tool"],
|
||||
)
|
||||
|
||||
assert result == "Confirmation timed out or failed. Installation cancelled."
|
||||
assert events[-1]["type"] == "notification"
|
||||
assert events[-1]["data"]["type"] == "warning"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_marks_total_failure_as_error(monkeypatch):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep], []
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
FakeAsyncClient.posts = []
|
||||
FakeAsyncClient.responses = [
|
||||
DummyResponse(500, {"detail": "update failed"}, "update failed"),
|
||||
DummyResponse(500, {"detail": "create failed"}, "create failed"),
|
||||
]
|
||||
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeAsyncClient)
|
||||
|
||||
events = []
|
||||
|
||||
async def emitter(event):
|
||||
events.append(event)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "en-US"},
|
||||
__request__=make_request(),
|
||||
__event_emitter__=emitter,
|
||||
repo="example/repo",
|
||||
plugin_types=["tool"],
|
||||
)
|
||||
|
||||
assert "Failed: Keep Plugin - status 500:" in result
|
||||
assert "0/1" in result
|
||||
assert events[-1]["type"] == "notification"
|
||||
assert events[-1]["data"]["type"] == "error"
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_localizes_timeout_errors(monkeypatch):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep], []
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
FakeAsyncClient.posts = []
|
||||
FakeAsyncClient.responses = [httpx.TimeoutException("timed out")]
|
||||
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeAsyncClient)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "zh-CN"},
|
||||
__request__=make_request(),
|
||||
repo="example/repo",
|
||||
plugin_types=["tool"],
|
||||
)
|
||||
|
||||
assert "失败:Keep Plugin - 请求超时" in result
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_install_all_plugins_emits_frontend_debug_logs_on_connect_error(
|
||||
monkeypatch,
|
||||
):
|
||||
keep = make_candidate("Keep Plugin", "plugins/tools/keep/keep.py", "keep_plugin")
|
||||
|
||||
async def fake_discover_plugins(url, skip_keywords):
|
||||
return [keep], []
|
||||
|
||||
monkeypatch.setattr(batch_install_plugins, "discover_plugins", fake_discover_plugins)
|
||||
FakeAsyncClient.posts = []
|
||||
# Both initial attempt and fallback retry should fail
|
||||
FakeAsyncClient.responses = [httpx.ConnectError("connect failed"), httpx.ConnectError("connect failed")]
|
||||
monkeypatch.setattr(batch_install_plugins.httpx, "AsyncClient", FakeAsyncClient)
|
||||
|
||||
execute_codes = []
|
||||
events = []
|
||||
|
||||
async def event_call(payload):
|
||||
if payload["type"] == "execute":
|
||||
execute_codes.append(payload["data"]["code"])
|
||||
return True
|
||||
if payload["type"] == "confirmation":
|
||||
return True
|
||||
raise AssertionError(f"Unexpected event_call payload type: {payload['type']}")
|
||||
|
||||
async def emitter(event):
|
||||
events.append(event)
|
||||
|
||||
result = await batch_install_plugins.Tools().install_all_plugins(
|
||||
__user__={"id": "u1", "language": "en-US"},
|
||||
__event_call__=event_call,
|
||||
__request__=make_request(),
|
||||
__event_emitter__=emitter,
|
||||
repo="example/repo",
|
||||
plugin_types=["tool"],
|
||||
)
|
||||
|
||||
assert result == "Cannot connect to OpenWebUI. Is it running?"
|
||||
assert any("OpenWebUI connection failed" in code for code in execute_codes)
|
||||
assert any("console.error" 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]["data"]["type"] == "error"
|
||||
Reference in New Issue
Block a user