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
This commit is contained in:
fujie
2026-01-27 04:22:36 +08:00
parent 927db6dbaa
commit ac50cd249a
7 changed files with 2298 additions and 604 deletions

View File

@@ -789,6 +789,19 @@ Filter 实例是**单例 (Singleton)**。
---
## 🧪 测试规范 (Testing Standards)
### 1. Copilot SDK 测试模型 (Copilot SDK Test Models)
在编写 Copilot SDK 相关的测试脚本时 (如 `test_injection.py`, `test_capabilities.py` 等)**必须**优先使用以下免费/低成本模型之一,严禁使用高昂费用的模型进行常规测试,除非用户明确要求:
- `gpt-5-mini` (首选 / Preferred)
- `gpt-4.1`
此规则适用于所有自动化测试脚本和临时验证脚本。
---
## 🔄 工作流与流程 (Workflow & Process)
### 1. ✅ 开发检查清单 (Development Checklist)

View File

@@ -246,6 +246,52 @@ jobs:
echo "=== Collected Files ==="
find release_plugins -name "*.py" -type f | head -20
- name: Update plugin icon URLs
run: |
echo "Updating icon_url in plugins to use absolute GitHub URLs..."
# Base URL for raw content using the release tag
REPO_URL="https://raw.githubusercontent.com/${{ github.repository }}/${{ steps.version.outputs.version }}"
find release_plugins -name "*.py" | while read -r file; do
# $file is like release_plugins/plugins/actions/infographic/infographic.py
# Remove release_plugins/ prefix to get the path in the repo
src_file="${file#release_plugins/}"
src_dir=$(dirname "$src_file")
base_name=$(basename "$src_file" .py)
# Check if a corresponding png exists in the source repository
png_file="${src_dir}/${base_name}.png"
if [ -f "$png_file" ]; then
echo "Found icon for $src_file: $png_file"
TARGET_ICON_URL="${REPO_URL}/${png_file}"
# Use python for safe replacement
python3 -c "
import sys
import re
file_path = '$file'
icon_url = '$TARGET_ICON_URL'
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# Replace icon_url: ... with new url
# Matches 'icon_url: ...' and replaces it
new_content = re.sub(r'^icon_url:.*$', f'icon_url: {icon_url}', content, flags=re.MULTILINE)
with open(file_path, 'w', encoding='utf-8') as f:
f.write(new_content)
print(f'Successfully updated icon_url in {file_path}')
except Exception as e:
print(f'Error updating {file_path}: {e}', file=sys.stderr)
sys.exit(1)
"
fi
done
- name: Debug Filenames
run: |
python3 -c "import sys; print(f'Filesystem encoding: {sys.getfilesystemencoding()}')"

View File

@@ -1,26 +1,25 @@
# GitHub Copilot SDK Pipe for OpenWebUI
**Author:** [Fu-Jie](https://github.com/Fu-Jie/awesome-openwebui) | **Version:** 0.1.1 | **Project:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui) | **License:** MIT
**Author:** [Fu-Jie](https://github.com/Fu-Jie/awesome-openwebui) | **Version:** 0.2.3 | **Project:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui) | **License:** MIT
This is an advanced Pipe function for [OpenWebUI](https://github.com/open-webui/open-webui) that allows you to use GitHub Copilot models (such as `gpt-5`, `gpt-5-mini`, `claude-sonnet-4.5`) directly within OpenWebUI. It is built upon the official [GitHub Copilot SDK for Python](https://github.com/github/copilot-sdk), providing a native integration experience.
## 🚀 What's New (v0.1.1)
## 🚀 What's New (v0.2.3)
* **♾️ Infinite Sessions**: Automatic context compaction for long-running conversations. No more context limit errors!
* **🧠 Thinking Process**: Real-time display of model reasoning/thinking process (for supported models).
* **📂 Workspace Control**: Restricted workspace directory for secure file operations.
* **🔍 Model Filtering**: Exclude specific models using keywords (e.g., `codex`, `haiku`).
* **💾 Session Persistence**: Improved session resume logic using OpenWebUI chat ID mapping.
* **🧩 Per-user Overrides**: Added user-level overrides for `REASONING_EFFORT`, `CLI_PATH`, `DEBUG`, `SHOW_THINKING`, and `MODEL_ID`.
* **🧠 Thinking Output Reliability**: Thinking visibility now respects the user setting and is correctly passed into streaming.
* **📝 Formatting Enforcement**: Added automatic formatting hints to ensure outputs are well-structured (paragraphs, lists) and addressed "tight output" issues.
## ✨ Core Features
* **🚀 Official SDK Integration**: Built on the official SDK for stability and reliability.
* **🛠️ Custom Tools Support**: Example tools included (random number). Easy to extend with your own tools.
* **💬 Multi-turn Conversation**: Automatically concatenates history context so Copilot understands your previous messages.
* **🌊 Streaming Output**: Supports typewriter effect for fast responses.
* **🖼️ Multimodal Support**: Supports image uploads, automatically converting them to attachments for Copilot (requires model support).
* **🛠️ Zero-config Installation**: Automatically detects and downloads the GitHub Copilot CLI, ready to use out of the box.
* **🔑 Secure Authentication**: Supports Fine-grained Personal Access Tokens for minimized permissions.
* **🐛 Debug Mode**: Built-in detailed log output for easy connection troubleshooting.
* **🐛 Debug Mode**: Built-in detailed log output (browser console) for easy troubleshooting.
* **⚠️ Single Node Only**: Due to local session storage, this plugin currently supports single-node OpenWebUI deployment or multi-node with sticky sessions enabled.
## 📦 Installation & Usage
@@ -42,16 +41,48 @@ Find "GitHub Copilot" in the function list and click the **⚙️ (Valves)** ico
| **GH_TOKEN** | **(Required)** Your GitHub Token. | - |
| **MODEL_ID** | The model name to use. | `gpt-5-mini` |
| **CLI_PATH** | Path to the Copilot CLI. Will download automatically if not found. | `/usr/local/bin/copilot` |
| **DEBUG** | Whether to enable debug logs (output to chat). | `True` |
| **SHOW_THINKING** | Show model reasoning/thinking process. | `True` |
| **DEBUG** | Whether to enable debug logs (output to browser console). | `False` |
| **LOG_LEVEL** | Copilot CLI log level: none, error, warning, info, debug, all. | `error` |
| **SHOW_THINKING** | Show model reasoning/thinking process (requires streaming + model support). | `True` |
| **SHOW_WORKSPACE_INFO** | Show session workspace path and summary in debug mode. | `True` |
| **EXCLUDE_KEYWORDS** | Exclude models containing these keywords (comma separated). | - |
| **WORKSPACE_DIR** | Restricted workspace directory for file operations. | - |
| **INFINITE_SESSION** | Enable Infinite Sessions (automatic context compaction). | `True` |
| **COMPACTION_THRESHOLD** | Background compaction threshold (0.0-1.0). | `0.8` |
| **BUFFER_THRESHOLD** | Buffer exhaustion threshold (0.0-1.0). | `0.95` |
| **TIMEOUT** | Timeout for each stream chunk (seconds). | `300` |
| **CUSTOM_ENV_VARS** | Custom environment variables (JSON format). | - |
| **REASONING_EFFORT** | Reasoning effort level: low, medium, high. `xhigh` is supported for gpt-5.2-codex. | `medium` |
| **ENFORCE_FORMATTING** | Add formatting instructions to system prompt for better readability. | `True` |
| **ENABLE_TOOLS** | Enable custom tools (example: random number). | `False` |
| **AVAILABLE_TOOLS** | Available tools: 'all' or comma-separated list. | `all` |
### 3. Get GH_TOKEN
#### User Valves (per-user overrides)
These optional settings can be set per user (overrides global Valves):
| Parameter | Description | Default |
| :--- | :--- | :--- |
| **REASONING_EFFORT** | Reasoning effort level (low/medium/high/xhigh). | - |
| **CLI_PATH** | Custom path to Copilot CLI. | - |
| **DEBUG** | Enable technical debug logs. | `False` |
| **SHOW_THINKING** | Show model reasoning/thinking process (requires streaming + model support). | `True` |
| **MODEL_ID** | Custom model ID. | - |
### 3. Using Custom Tools (🆕 Optional)
This pipe includes **1 example tool** to demonstrate tool calling:
* **🎲 generate_random_number**: Generate random integers
**To enable:**
1. Set `ENABLE_TOOLS: true` in Valves
2. Try: "Give me a random number"
**📚 For detailed usage and creating your own tools, see [TOOLS_USAGE.md](TOOLS_USAGE.md)**
### 4. Get GH_TOKEN
For security, it is recommended to use a **Fine-grained Personal Access Token**:
@@ -76,6 +107,8 @@ This Pipe will automatically attempt to install the following dependencies:
* Check if `GH_TOKEN` is correct and has `Copilot Requests` permission.
* **Images not recognized**:
* Ensure `MODEL_ID` is a model that supports multimodal input.
* **Thinking not shown**:
* Ensure **streaming is enabled** and the selected model supports reasoning output.
* **CLI Installation Failed**:
* Ensure the OpenWebUI container has internet access.
* You can manually download the CLI and specify `CLI_PATH` in Valves.

View File

@@ -1,26 +1,25 @@
# GitHub Copilot SDK 官方管道
**作者:** [Fu-Jie](https://github.com/Fu-Jie/awesome-openwebui) | **版本:** 0.1.1 | **项目:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui) | **许可证:** MIT
**作者:** [Fu-Jie](https://github.com/Fu-Jie/awesome-openwebui) | **版本:** 0.2.3 | **项目:** [Awesome OpenWebUI](https://github.com/Fu-Jie/awesome-openwebui) | **许可证:** MIT
这是一个用于 [OpenWebUI](https://github.com/open-webui/open-webui) 的高级 Pipe 函数,允许你直接在 OpenWebUI 中使用 GitHub Copilot 模型(如 `gpt-5`, `gpt-5-mini`, `claude-sonnet-4.5`)。它基于官方 [GitHub Copilot SDK for Python](https://github.com/github/copilot-sdk) 构建,提供了原生级的集成体验。
## 🚀 最新特性 (v0.1.1)
## 🚀 最新特性 (v0.2.3)
* **♾️ 无限会话 (Infinite Sessions)**:支持长对话的自动上下文压缩,告别上下文超限错误!
* **🧠 思考过程展示**:实时显示模型的推理/思考过程(需模型支持)
* **📂 工作目录控制**:支持设置受限工作目录,确保文件操作安全
* **🔍 模型过滤**:支持通过关键词排除特定模型(如 `codex`, `haiku`)。
* **💾 会话持久化**: 改进的会话恢复逻辑,直接关联 OpenWebUI 聊天 ID连接更稳定。
* **🧩 用户级覆盖**:新增 `REASONING_EFFORT``CLI_PATH``DEBUG``SHOW_THINKING``MODEL_ID` 的用户级覆盖。
* **🧠 思考输出可靠性**:思考显示会遵循用户设置,并正确传递到流式输出中
* **📝 格式化输出增强**:自动优化输出格式(短句、段落、列表),并解决了在某些界面下显示过于紧凑的问题
## ✨ 核心特性
* **🚀 官方 SDK 集成**:基于官方 SDK稳定可靠。
* **🛠️ 自定义工具支持**:内置示例工具(随机数)。易于扩展自定义工具。
* **💬 多轮对话支持**自动拼接历史上下文Copilot 能理解你的前文。
* **🌊 流式输出 (Streaming)**:支持打字机效果,响应迅速。
* **🖼️ 多模态支持**:支持上传图片,自动转换为附件发送给 Copilot需模型支持
* **🛠️ 零配置安装**:自动检测并下载 GitHub Copilot CLI开箱即用。
* **🔑 安全认证**:支持 Fine-grained Personal Access Tokens权限最小化。
* **🐛 调试模式**:内置详细的日志输出,方便排查连接问题。
* **🐛 调试模式**:内置详细的日志输出(浏览器控制台),方便排查问题。
* **⚠️ 仅支持单节点**:由于会话状态存储在本地,本插件目前仅支持 OpenWebUI 单节点部署,或开启了会话粘性 (Sticky Session) 的多节点集群。
## 📦 安装与使用
@@ -42,16 +41,48 @@
| **GH_TOKEN** | **(必填)** 你的 GitHub Token。 | - |
| **MODEL_ID** | 使用的模型名称。 | `gpt-5-mini` |
| **CLI_PATH** | Copilot CLI 的路径。如果未找到会自动下载。 | `/usr/local/bin/copilot` |
| **DEBUG** | 是否开启调试日志(输出到对话框)。 | `True` |
| **SHOW_THINKING** | 是否显示模型推理/思考过程。 | `True` |
| **DEBUG** | 是否开启调试日志(输出到浏览器控制台)。 | `False` |
| **LOG_LEVEL** | Copilot CLI 日志级别: none, error, warning, info, debug, all。 | `error` |
| **SHOW_THINKING** | 是否显示模型推理/思考过程(需开启流式 + 模型支持)。 | `True` |
| **SHOW_WORKSPACE_INFO** | 在调试模式下显示会话工作空间路径和摘要。 | `True` |
| **EXCLUDE_KEYWORDS** | 排除包含这些关键词的模型 (逗号分隔)。 | - |
| **WORKSPACE_DIR** | 文件操作的受限工作目录。 | - |
| **INFINITE_SESSION** | 启用无限会话 (自动上下文压缩)。 | `True` |
| **COMPACTION_THRESHOLD** | 后台压缩阈值 (0.0-1.0)。 | `0.8` |
| **BUFFER_THRESHOLD** | 缓冲耗尽阈值 (0.0-1.0)。 | `0.95` |
| **TIMEOUT** | 流式数据块超时时间 (秒)。 | `300` |
| **CUSTOM_ENV_VARS** | 自定义环境变量 (JSON 格式)。 | - |
| **ENABLE_TOOLS** | 启用自定义工具 (示例:随机数)。 | `False` |
| **AVAILABLE_TOOLS** | 可用工具: 'all' 或逗号分隔列表。 | `all` |
| **REASONING_EFFORT** | 推理强度级别low, medium, high。`gpt-5.2-codex`额外支持`xhigh`。 | `medium` |
| **ENFORCE_FORMATTING** | 是否强制添加格式化指导,以提高输出可读性。 | `True` |
### 3. 获取 GH_TOKEN
#### 用户 Valves按用户覆盖
以下设置可按用户单独配置(覆盖全局 Valves
| 参数 | 说明 | 默认值 |
| :--- | :--- | :--- |
| **REASONING_EFFORT** | 推理强度级别low/medium/high/xhigh。 | - |
| **CLI_PATH** | 自定义 Copilot CLI 路径。 | - |
| **DEBUG** | 是否启用技术调试日志。 | `False` |
| **SHOW_THINKING** | 是否显示思考过程(需开启流式 + 模型支持)。 | `True` |
| **MODEL_ID** | 自定义模型 ID。 | - |
### 3. 使用自定义工具 (🆕 可选)
本 Pipe 内置了 **1 个示例工具**来展示工具调用功能:
* **🎲 generate_random_number**:生成随机整数
**启用方法:**
1. 在 Valves 中设置 `ENABLE_TOOLS: true`
2. 尝试问:“给我一个随机数”
**📚 详细使用说明和创建自定义工具,请参阅 [TOOLS_USAGE.md](TOOLS_USAGE.md)**
### 4. 获取 GH_TOKEN
为了安全起见,推荐使用 **Fine-grained Personal Access Token**
@@ -79,3 +110,5 @@
* **CLI 安装失败**
* 确保 OpenWebUI 容器有外网访问权限。
* 你可以手动下载 CLI 并挂载到容器中,然后在 Valves 中指定 `CLI_PATH`
* **看不到思考过程**
* 确认已开启**流式输出**,且所选模型支持推理输出。

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -473,10 +473,27 @@ class OpenWebUICommunityClient:
# 查找 README
readme_content = self._find_readme(file_path)
# 获取远程帖子信息(提前获取,用于判断是否需要上传图片)
remote_post = None
if post_id:
remote_post = self.get_post(post_id)
# 查找并上传图片
media_urls = None
image_path = self._find_image(file_path)
if image_path:
# 决定是否上传图片
should_upload_image = True
if remote_post:
remote_media = remote_post.get("media", [])
if remote_media and len(remote_media) > 0:
# 远程已有图片,跳过上传以避免覆盖(防止出现空白图片问题)
print(
f" Remote post already has images. Skipping auto-upload to preserve existing media."
)
should_upload_image = False
if image_path and should_upload_image:
print(f" Found image: {os.path.basename(image_path)}")
image_url = self.upload_image(image_path)
if image_url:
@@ -500,7 +517,8 @@ class OpenWebUICommunityClient:
post_id = existing_post.get("id")
print(f" Found existing post: {title} (ID: {post_id})")
self._inject_id_to_file(file_path, post_id)
# post_id 已设置,后续将进入更新流程
# post_id 已设置,重新获取 remote_post 以便后续版本检查
remote_post = self.get_post(post_id)
else:
# 2. 如果没找到,且允许自动创建,则创建
@@ -522,11 +540,6 @@ class OpenWebUICommunityClient:
return True, f"Created new post (ID: {new_post_id})"
return False, "Failed to create new post"
# 获取远程帖子信息(只需获取一次)
remote_post = None
if post_id:
remote_post = self.get_post(post_id)
# 版本检查(仅对更新有效)
if not force and local_version and remote_post:
remote_version = (