chore(github-copilot-sdk): release v0.12.2
- support multi-line SKILL.md frontmatter parsing in manage_skills - write multi-line skill descriptions as YAML block scalars - sync README, docs, and release notes for v0.12.2
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
# GitHub Copilot SDK Pipe for OpenWebUI
|
||||
|
||||
| By [Fu-Jie](https://github.com/Fu-Jie) · v0.12.1 | [⭐ Star this repo](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| By [Fu-Jie](https://github.com/Fu-Jie) · v0.12.2 | [⭐ Star this repo](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| :--- | ---: |
|
||||
|
||||
|  |  |  |  |  |  |  |
|
||||
@@ -39,23 +39,12 @@ When the selection dialog opens, search for this plugin, check it, and continue.
|
||||
> [!IMPORTANT]
|
||||
> If the official OpenWebUI Community version is already installed, remove it first. After that, Batch Install Plugins can keep this plugin updated in future runs.
|
||||
|
||||
## ✨ v0.12.0: Adaptive Actions Console, Stream Deduplication & Full TTFT Profiling
|
||||
## ✨ v0.12.2: Multi-line Skill Frontmatter Support for `manage_skills`
|
||||
|
||||
- **📊 Predictive Adaptive Console**: Automatically models continuous decision layouts using `interactive_controls` state tables on the per-session workspace database so visual panels don't go stale.
|
||||
- **🛡️ Stream Overlap Deduplication**: Mitigated overlay dual delivery bugs on `assistant.message_delta` frames using conservative overlap trimming rules during turn resumptions.
|
||||
- **⏱️ Segmented Profiling Loadtimes**: Fine-grained timers identifying local startup overhead and pure cloud network turnaround time tracking calibration.
|
||||
- **🧹 Eliminate Redundancies**: Reduced redundant secondary heavy `_parse_mcp_servers()` loops inside session resumes for faster handshake callbacks.
|
||||
|
||||
---
|
||||
|
||||
## ✨ v0.10.0: Native Prompt Restoration, Live TODO Widget & SDK v0.1.30
|
||||
|
||||
- **⌨️ Authentic Prompt Restoration**: Restored the native Copilot CLI **Plan Mode** for complex task orchestration and native SQLite-backed session management for robust state persistence.
|
||||
- **📋 Live TODO Widget**: Added a compact real-time task tracking widget synchronized with `session.db`, keeping in-progress work visible without cluttering the chat history.
|
||||
- **🧩 OpenWebUI Tool Call Fixes**: Fixed custom tool invocation by syncing injected context with OpenWebUI 0.8.x expectations, including `__request__`, `request`, `body`, `__messages__`, `__metadata__`, `__files__`, `__task__`, and session/chat/message IDs.
|
||||
- **🔒 SDK v0.1.30 + Adaptive Workstyle**: Upgraded the pipe to `github-copilot-sdk==0.1.30`, moving workflow logic into the system prompt for autonomous "Plan-vs-Execute" decisions.
|
||||
- **🐛 Intent + Widget UX Fixes**: Fixed `report_intent` localization and cleaned up TODO widget layout for a more professional look.
|
||||
- **🧾 Better Embedded Tool Results**: Improved HTML/embedded tool outcomes and synchronized documentation surface.
|
||||
- **📝 Multi-line `description` Parsing**: `manage_skills` now understands `description: >` and `description: |` blocks in `SKILL.md`, including CRLF input from external repositories.
|
||||
- **💾 Safer `SKILL.md` Writing**: When a skill description contains line breaks, the pipe now writes YAML block scalars instead of fragile quoted single-line text.
|
||||
- **↩️ Better Metadata Fallbacks**: `title` can now act as the skill name fallback when `name` is absent, reducing generic directory-based names during skill import/sync.
|
||||
- **🧪 Regression Tests**: Added targeted parse/write round-trip coverage so future skill manager updates stay stable.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GitHub Copilot Official SDK Pipe
|
||||
|
||||
| 作者:[Fu-Jie](https://github.com/Fu-Jie) · v0.12.1 | [⭐ 点个 Star 支持项目](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| 作者:[Fu-Jie](https://github.com/Fu-Jie) · v0.12.2 | [⭐ 点个 Star 支持项目](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| :--- | ---: |
|
||||
|
||||
|  |  |  |  |  |  |  |
|
||||
@@ -40,23 +40,12 @@
|
||||
> [!IMPORTANT]
|
||||
> 如果你已经安装了 OpenWebUI 官方社区里的同名版本,请先删除旧版本,否则重新安装时可能报错。删除后,Batch Install Plugins 后续就可以继续负责更新这个插件。
|
||||
|
||||
## ✨ v0.12.0:自适应动作面板、流排重拦截与全链路 TTFT 测定
|
||||
## ✨ v0.12.2:`manage_skills` 支持多行 Skill Frontmatter
|
||||
|
||||
- **📊 连续自适应看板 (Adaptive Actions Console)**:自动在 `interactive_controls` 辅助常驻状态表中追踪动作,引导 LLM 有选择性地在最新输出中展示最可能用到的点击控制面板,实现不翻页连续持久化点击操作。
|
||||
- **🛡️ 叠加流排重拦截 (Deduplicate Stream overlap)**:对接 `_dedupe_stream_chunk` 保守重叠裁剪,彻底消除二轮对话流重叠叠加异常。
|
||||
- **⏱️ 分段 ⏱️ Profiling 埋点**:拆装本地预热阻断与云端网络 Trip 数据时间,直观测算 Time-to-First-Byte。
|
||||
- **🧹 消除冗余解析**:剔除 Resume 过程对 MCP 的二次昂贵循环,提效握手微观时延。
|
||||
|
||||
---
|
||||
|
||||
## ✨ v0.10.0 最新更新:原生提示词恢复、Live TODO 小组件与 SDK v0.1.30 完善
|
||||
|
||||
- **⌨️ 原生提示词恢复**:恢复了原生 Copilot CLI **原生计划模式 (Native Plan Mode)** 复杂任务编排能力,并集成了基于 SQLite 的原生会话与持久化管理,提升 Agent 的状态把控能力。
|
||||
- **📋 Live TODO 小组件**:新增基于 `session.db` 实时任务状态的紧凑型嵌入式 TODO 小组件,任务进度常驻可见,无需在正文中重复显示全部待办列表。
|
||||
- **🧩 OpenWebUI 工具调用修复**:修复自定义工具调用时上下文注入不完整的问题,完全对齐 OpenWebUI 0.8.x 所需的系统级上下文(`__request__`、`body`、`__metadata__` 等)。
|
||||
- **🔒 SDK v0.1.30 与自适应工作流**:升级到 `github-copilot-sdk==0.1.30`,将规划与执行逻辑移至系统提示词,让 Agent 根据任务复杂度自主决策工作流。
|
||||
- **🐛 意图与体验优化**:修复 `report_intent` 国际化问题,优化 TODO 小组件的视觉布局,减少冗余空白。
|
||||
- **🧾 嵌入结果与文档更新**:改进 HTML/嵌入式工具结果处理,同步中英 README 与 docs 镜像页,确保发布状态一致。
|
||||
- **📝 多行 `description` 解析**:`manage_skills` 现在可以正确识别 `SKILL.md` 里的 `description: >` 和 `description: |`,并兼容来自外部仓库的 CRLF 输入。
|
||||
- **💾 更安全的 `SKILL.md` 回写**:当技能描述包含换行时,Pipe 会改用 YAML block scalar 写回,而不是脆弱的单行引号文本。
|
||||
- **↩️ 更稳的元数据回退**:当 `name` 缺失时,`title` 现在可以作为技能名回退,减少导入/同步时退回通用目录名的情况。
|
||||
- **🧪 回归测试补齐**:新增针对解析与写回 round-trip 的定向测试,保证后续技能管理改动更稳定。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Pipes allow you to:
|
||||
|
||||
## Available Pipe Plugins
|
||||
|
||||
- [GitHub Copilot SDK](github-copilot-sdk.md) (v0.12.1) - Official GitHub Copilot SDK integration. Features **Workspace Isolation**, **Zero-config OpenWebUI Tool Bridge**, **BYOK** support, and **dynamic MCP discovery**. **NEW in v0.12.1: Disable terminal tools for AI, RichUI theme-aware CSS variables**. [View Deep Dive](github-copilot-sdk-deep-dive.md) | [**View Advanced Tutorial**](github-copilot-sdk-tutorial.md) | [**View Detailed Usage Guide**](github-copilot-sdk-usage-guide.md).
|
||||
- [GitHub Copilot SDK](github-copilot-sdk.md) (v0.12.2) - Official GitHub Copilot SDK integration. Features **Workspace Isolation**, **Zero-config OpenWebUI Tool Bridge**, **BYOK** support, and **dynamic MCP discovery**. **NEW in v0.12.2: `manage_skills` multi-line `SKILL.md` frontmatter support and safer YAML writes**. [View Deep Dive](github-copilot-sdk-deep-dive.md) | [**View Advanced Tutorial**](github-copilot-sdk-tutorial.md) | [**View Detailed Usage Guide**](github-copilot-sdk-usage-guide.md).
|
||||
- **[Case Study: GitHub 100 Star Growth Analysis](star-prediction-example.md)** - Learn how to use the GitHub Copilot SDK Pipe with Minimax 2.1 to automatically analyze CSV data and generate project growth reports.
|
||||
- **[Case Study: High-Quality Video to GIF Conversion](video-processing-example.md)** - See how the model uses system-level FFmpeg to accelerate, scale, and optimize colors for screen recordings.
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ Pipes 可以用于:
|
||||
|
||||
## 可用的 Pipe 插件
|
||||
|
||||
- [GitHub Copilot SDK](github-copilot-sdk.zh.md) (v0.12.1) - GitHub Copilot SDK 官方集成。具备**工作区安全隔离**、**零配置工具桥接**与**BYOK (自带 Key) 支持**。**v0.12.1 更新:禁用终端工具 AI 调用、RichUI 主题感知 CSS 变量**。[查看深度架构解析](github-copilot-sdk-deep-dive.zh.md) | [**查看进阶 实战教程**](github-copilot-sdk-tutorial.zh.md) | [**查看详细使用手册**](github-copilot-sdk-usage-guide.zh.md)。
|
||||
- [GitHub Copilot SDK](github-copilot-sdk.zh.md) (v0.12.2) - GitHub Copilot SDK 官方集成。具备**工作区安全隔离**、**零配置工具桥接**与**BYOK (自带 Key) 支持**。**v0.12.2 更新:`manage_skills` 支持多行 `SKILL.md` frontmatter,并改进 YAML 回写稳定性**。[查看深度架构解析](github-copilot-sdk-deep-dive.zh.md) | [**查看进阶 实战教程**](github-copilot-sdk-tutorial.zh.md) | [**查看详细使用手册**](github-copilot-sdk-usage-guide.zh.md)。
|
||||
- **[实战案例:GitHub 100 Star 增长预测](star-prediction-example.zh.md)** - 展示如何使用 GitHub Copilot SDK Pipe 结合 Minimax 2.1 模型,自动编写脚本分析 CSV 数据并生成详细的项目增长报告。
|
||||
- **[实战案例:视频高质量 GIF 转换与加速](video-processing-example.zh.md)** - 演示模型如何通过底层 FFmpeg 工具对录屏进行加速、缩放及双阶段色彩优化处理。
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GitHub Copilot SDK Pipe for OpenWebUI
|
||||
|
||||
| By [Fu-Jie](https://github.com/Fu-Jie) · v0.12.1 | [⭐ Star this repo](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| By [Fu-Jie](https://github.com/Fu-Jie) · v0.12.2 | [⭐ Star this repo](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| :--- | ---: |
|
||||
|
||||
|  |  |  |  |  |  |  |
|
||||
@@ -39,23 +39,12 @@ When the selection dialog opens, search for this plugin, check it, and continue.
|
||||
> [!IMPORTANT]
|
||||
> If the official OpenWebUI Community version is already installed, remove it first. After that, Batch Install Plugins can keep this plugin updated in future runs.
|
||||
|
||||
## ✨ v0.12.0: Adaptive Actions Console, Stream Deduplication & Full TTFT Profiling
|
||||
## ✨ v0.12.2: Multi-line Skill Frontmatter Support for `manage_skills`
|
||||
|
||||
- **📊 Predictive Adaptive Console**: Automatically models continuous decision layouts using `interactive_controls` state tables on the per-session workspace database so visual panels don't go stale.
|
||||
- **🛡️ Stream Overlap Deduplication**: Mitigated overlay dual delivery bugs on `assistant.message_delta` frames using conservative overlap trimming rules during turn resumptions.
|
||||
- **⏱️ Segmented Profiling Loadtimes**: Fine-grained timers identifying local startup overhead and pure cloud network turnaround time tracking calibration.
|
||||
- **🧹 Eliminate Redundancies**: Reduced redundant secondary heavy `_parse_mcp_servers()` loops inside session resumes for faster handshake callbacks.
|
||||
|
||||
---
|
||||
|
||||
## ✨ v0.10.0: Native Prompt Restoration, Live TODO Widget & SDK v0.1.30
|
||||
|
||||
- **⌨️ Authentic Prompt Restoration**: Restored the native Copilot CLI **Plan Mode** for complex task orchestration and native SQLite-backed session management for robust state persistence.
|
||||
- **📋 Live TODO Widget**: Added a compact real-time task tracking widget synchronized with `session.db`, keeping in-progress work visible without cluttering the chat history.
|
||||
- **🧩 OpenWebUI Tool Call Fixes**: Fixed custom tool invocation by syncing injected context with OpenWebUI 0.8.x expectations, including `__request__`, `request`, `body`, `__messages__`, `__metadata__`, `__files__`, `__task__`, and session/chat/message IDs.
|
||||
- **🔒 SDK v0.1.30 + Adaptive Workstyle**: Upgraded the pipe to `github-copilot-sdk==0.1.30`, moving workflow logic into the system prompt for autonomous "Plan-vs-Execute" decisions.
|
||||
- **🐛 Intent + Widget UX Fixes**: Fixed `report_intent` localization and cleaned up TODO widget layout for a more professional look.
|
||||
- **🧾 Better Embedded Tool Results**: Improved HTML/embedded tool outcomes and synchronized documentation surface.
|
||||
- **📝 Multi-line `description` Parsing**: `manage_skills` now understands `description: >` and `description: |` blocks in `SKILL.md`, including CRLF input from external repositories.
|
||||
- **💾 Safer `SKILL.md` Writing**: When a skill description contains line breaks, the pipe now writes YAML block scalars instead of fragile quoted single-line text.
|
||||
- **↩️ Better Metadata Fallbacks**: `title` can now act as the skill name fallback when `name` is absent, reducing generic directory-based names during skill import/sync.
|
||||
- **🧪 Regression Tests**: Added targeted parse/write round-trip coverage so future skill manager updates stay stable.
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# GitHub Copilot Official SDK Pipe
|
||||
|
||||
| 作者:[Fu-Jie](https://github.com/Fu-Jie) · v0.12.1 | [⭐ 点个 Star 支持项目](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| 作者:[Fu-Jie](https://github.com/Fu-Jie) · v0.12.2 | [⭐ 点个 Star 支持项目](https://github.com/Fu-Jie/openwebui-extensions) |
|
||||
| :--- | ---: |
|
||||
|
||||
|  |  |  |  |  |  |  |
|
||||
@@ -40,23 +40,12 @@
|
||||
> [!IMPORTANT]
|
||||
> 如果你已经安装了 OpenWebUI 官方社区里的同名版本,请先删除旧版本,否则重新安装时可能报错。删除后,Batch Install Plugins 后续就可以继续负责更新这个插件。
|
||||
|
||||
## ✨ v0.12.0:自适应动作面板、流排重拦截与全链路 TTFT 测定
|
||||
## ✨ v0.12.2:`manage_skills` 支持多行 Skill Frontmatter
|
||||
|
||||
- **📊 连续自适应看板 (Adaptive Actions Console)**:自动在 `interactive_controls` 辅助常驻状态表中追踪动作,引导 LLM 有选择性地在最新输出中展示最可能用到的点击控制面板,实现不翻页连续持久化点击操作。
|
||||
- **🛡️ 叠加流排重拦截 (Deduplicate Stream overlap)**:对接 `_dedupe_stream_chunk` 保守重叠裁剪,彻底消除二轮对话流重叠叠加异常。
|
||||
- **⏱️ 分段 ⏱️ Profiling 埋点**:拆装本地预热阻断与云端网络 Trip 数据时间,直观测算 Time-to-First-Byte。
|
||||
- **🧹 消除冗余解析**:剔除 Resume 过程对 MCP 的二次昂贵循环,提效握手微观时延。
|
||||
|
||||
---
|
||||
|
||||
## ✨ v0.10.0 最新更新:原生提示词恢复、Live TODO 小组件与 SDK v0.1.30 完善
|
||||
|
||||
- **⌨️ 原生提示词恢复**:恢复了原生 Copilot CLI **原生计划模式 (Native Plan Mode)** 复杂任务编排能力,并集成了基于 SQLite 的原生会话与持久化管理,提升 Agent 的状态把控能力。
|
||||
- **📋 Live TODO 小组件**:新增基于 `session.db` 实时任务状态的紧凑型嵌入式 TODO 小组件,任务进度常驻可见,无需在正文中重复显示全部待办列表。
|
||||
- **🧩 OpenWebUI 工具调用修复**:修复自定义工具调用时上下文注入不完整的问题,完全对齐 OpenWebUI 0.8.x 所需的系统级上下文(`__request__`、`body`、`__metadata__` 等)。
|
||||
- **🔒 SDK v0.1.30 与自适应工作流**:升级到 `github-copilot-sdk==0.1.30`,将规划与执行逻辑移至系统提示词,让 Agent 根据任务复杂度自主决策工作流。
|
||||
- **🐛 意图与体验优化**:修复 `report_intent` 国际化问题,优化 TODO 小组件的视觉布局,减少冗余空白。
|
||||
- **🧾 嵌入结果与文档更新**:改进 HTML/嵌入式工具结果处理,同步中英 README 与 docs 镜像页,确保发布状态一致。
|
||||
- **📝 多行 `description` 解析**:`manage_skills` 现在可以正确识别 `SKILL.md` 里的 `description: >` 和 `description: |`,并兼容来自外部仓库的 CRLF 输入。
|
||||
- **💾 更安全的 `SKILL.md` 回写**:当技能描述包含换行时,Pipe 会改用 YAML block scalar 写回,而不是脆弱的单行引号文本。
|
||||
- **↩️ 更稳的元数据回退**:当 `name` 缺失时,`title` 现在可以作为技能名回退,减少导入/同步时退回通用目录名的情况。
|
||||
- **🧪 回归测试补齐**:新增针对解析与写回 round-trip 的定向测试,保证后续技能管理改动更稳定。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ author_url: https://github.com/Fu-Jie/openwebui-extensions
|
||||
funding_url: https://github.com/open-webui
|
||||
openwebui_id: ce96f7b4-12fc-4ac3-9a01-875713e69359
|
||||
description: A powerful Agent SDK integration for OpenWebUI. It deeply bridges GitHub Copilot SDK with OpenWebUI's ecosystem, enabling the Agent to autonomously perform intent recognition, web search, and context compaction. It seamlessly reuses your existing Tools, MCP servers, OpenAPI servers, and Skills for a professional, full-featured experience.
|
||||
version: 0.12.1
|
||||
version: 0.12.2
|
||||
requirements: github-copilot-sdk==0.1.30
|
||||
"""
|
||||
|
||||
@@ -6173,35 +6173,148 @@ class Pipe:
|
||||
shared_dir.mkdir(parents=True, exist_ok=True)
|
||||
return str(shared_dir)
|
||||
|
||||
def _normalize_skill_md_newlines(self, text: str) -> str:
|
||||
"""Normalize CRLF/CR text to LF for stable SKILL.md parsing."""
|
||||
return text.replace("\r\n", "\n").replace("\r", "\n")
|
||||
|
||||
def _strip_skill_meta_quotes(self, value: str) -> str:
|
||||
"""Remove matching wrapping quotes from a frontmatter scalar."""
|
||||
value = (value or "").strip()
|
||||
if len(value) >= 2 and value[0] == value[-1] and value[0] in {"'", '"'}:
|
||||
return value[1:-1]
|
||||
return value
|
||||
|
||||
def _collect_skill_meta_block(
|
||||
self, lines: List[str], start_index: int
|
||||
) -> Tuple[List[str], int]:
|
||||
"""Collect indented frontmatter block lines until the next top-level key."""
|
||||
block_lines: List[str] = []
|
||||
index = start_index
|
||||
|
||||
while index < len(lines):
|
||||
line = lines[index]
|
||||
if not line.strip():
|
||||
block_lines.append("")
|
||||
index += 1
|
||||
continue
|
||||
|
||||
indent = len(line) - len(line.lstrip(" "))
|
||||
if indent == 0 and re.match(r"^[A-Za-z0-9_-]+:(.*)$", line):
|
||||
break
|
||||
if indent == 0:
|
||||
break
|
||||
|
||||
block_lines.append(line)
|
||||
index += 1
|
||||
|
||||
non_empty_indents = [
|
||||
len(line) - len(line.lstrip(" ")) for line in block_lines if line.strip()
|
||||
]
|
||||
min_indent = min(non_empty_indents) if non_empty_indents else 0
|
||||
dedented = [line[min_indent:] if line else "" for line in block_lines]
|
||||
return dedented, index
|
||||
|
||||
def _fold_skill_meta_block(self, lines: List[str]) -> str:
|
||||
"""Fold YAML `>` block lines into paragraphs separated by blank lines."""
|
||||
parts: List[str] = []
|
||||
paragraph: List[str] = []
|
||||
|
||||
for line in lines:
|
||||
if line == "":
|
||||
if paragraph:
|
||||
parts.append(" ".join(segment.strip() for segment in paragraph))
|
||||
paragraph = []
|
||||
if parts and parts[-1] != "":
|
||||
parts.append("")
|
||||
continue
|
||||
paragraph.append(line.strip())
|
||||
|
||||
if paragraph:
|
||||
parts.append(" ".join(segment.strip() for segment in paragraph))
|
||||
|
||||
return "\n".join(parts).strip()
|
||||
|
||||
def _parse_skill_frontmatter_scalars(self, frontmatter_text: str) -> Dict[str, str]:
|
||||
"""Parse simple top-level YAML frontmatter scalars, including block scalars."""
|
||||
lines = self._normalize_skill_md_newlines(frontmatter_text).split("\n")
|
||||
metadata: Dict[str, str] = {}
|
||||
index = 0
|
||||
|
||||
while index < len(lines):
|
||||
line = lines[index]
|
||||
stripped = line.strip()
|
||||
|
||||
if not stripped or stripped.startswith("#") or line.startswith(" "):
|
||||
index += 1
|
||||
continue
|
||||
|
||||
match = re.match(r"^([A-Za-z0-9_-]+):(.*)$", line)
|
||||
if not match:
|
||||
index += 1
|
||||
continue
|
||||
|
||||
key = match.group(1)
|
||||
raw_value = match.group(2).lstrip()
|
||||
|
||||
if raw_value[:1] in {"|", ">"}:
|
||||
block_lines, index = self._collect_skill_meta_block(lines, index + 1)
|
||||
metadata[key] = (
|
||||
"\n".join(block_lines).strip()
|
||||
if raw_value.startswith("|")
|
||||
else self._fold_skill_meta_block(block_lines)
|
||||
)
|
||||
continue
|
||||
|
||||
block_lines, next_index = self._collect_skill_meta_block(lines, index + 1)
|
||||
if block_lines:
|
||||
segments = [self._strip_skill_meta_quotes(raw_value)] + [
|
||||
segment.strip() for segment in block_lines
|
||||
]
|
||||
metadata[key] = self._fold_skill_meta_block(segments)
|
||||
index = next_index
|
||||
continue
|
||||
|
||||
metadata[key] = self._strip_skill_meta_quotes(raw_value)
|
||||
index += 1
|
||||
|
||||
return metadata
|
||||
|
||||
def _parse_skill_md_meta(self, content: str, fallback_name: str) -> tuple:
|
||||
"""Parse SKILL.md content into (name, description, body).
|
||||
|
||||
Handles files with or without YAML frontmatter.
|
||||
Strips quotes from frontmatter string values.
|
||||
"""
|
||||
fm_match = re.match(r"^---\s*\n(.*?)\n---\s*\n", content, re.DOTALL)
|
||||
normalized_content = self._normalize_skill_md_newlines(content)
|
||||
fm_match = re.match(
|
||||
r"^---\s*\n(.*?)\n---\s*(?:\n|$)", normalized_content, re.DOTALL
|
||||
)
|
||||
if fm_match:
|
||||
fm_text = fm_match.group(1)
|
||||
body = content[fm_match.end() :].strip()
|
||||
name = fallback_name
|
||||
description = ""
|
||||
for line in fm_text.split("\n"):
|
||||
m = re.match(r"^name:\s*(.+)$", line)
|
||||
if m:
|
||||
name = m.group(1).strip().strip("\"'")
|
||||
m = re.match(r"^description:\s*(.+)$", line)
|
||||
if m:
|
||||
description = m.group(1).strip().strip("\"'")
|
||||
body = normalized_content[fm_match.end() :].strip()
|
||||
metadata = self._parse_skill_frontmatter_scalars(fm_text)
|
||||
name = (
|
||||
metadata.get("name") or metadata.get("title") or fallback_name
|
||||
).strip()
|
||||
description = (metadata.get("description") or "").strip()
|
||||
return name, description, body
|
||||
# No frontmatter: try to extract H1 as name
|
||||
h1_match = re.search(r"^#\s+(.+)$", content.strip(), re.MULTILINE)
|
||||
stripped_content = normalized_content.strip()
|
||||
h1_match = re.search(r"^#\s+(.+)$", stripped_content, re.MULTILINE)
|
||||
name = h1_match.group(1).strip() if h1_match else fallback_name
|
||||
return name, "", content.strip()
|
||||
return name, "", stripped_content
|
||||
|
||||
def _build_skill_md_content(self, name: str, description: str, body: str) -> str:
|
||||
"""Construct a SKILL.md file string from name, description, and body."""
|
||||
desc_line = description or name
|
||||
if any(c in desc_line for c in ":#\n"):
|
||||
desc_value = (description or name).strip()
|
||||
if "\n" in desc_value:
|
||||
desc_body = "\n".join(
|
||||
f" {line}" if line else "" for line in desc_value.split("\n")
|
||||
)
|
||||
desc_line = f"|\n{desc_body}"
|
||||
else:
|
||||
desc_line = desc_value
|
||||
if any(c in desc_line for c in ":#"):
|
||||
desc_line = f'"{desc_line}"'
|
||||
return (
|
||||
f"---\n"
|
||||
|
||||
29
plugins/pipes/github-copilot-sdk/v0.12.2.md
Normal file
29
plugins/pipes/github-copilot-sdk/v0.12.2.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# GitHub Copilot SDK Pipe v0.12.2
|
||||
|
||||
This patch release hardens the built-in `manage_skills` workflow so the pipe can reliably read and write `SKILL.md` metadata with multi-line descriptions.
|
||||
|
||||
## New Features
|
||||
|
||||
- **Multi-line Frontmatter Parsing**: `manage_skills` now supports folded (`description: >`) and literal (`description: |`) frontmatter blocks, including CRLF input.
|
||||
- **Stable `SKILL.md` Writes**: Multi-line descriptions are now written back as YAML block scalars when creating or editing skills through the pipe.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- Fixed imported skill descriptions being truncated or flattened when source `SKILL.md` files used multi-line YAML frontmatter.
|
||||
- Added `title` fallback when `name` is missing, reducing generic directory-name fallbacks during skill import and sync.
|
||||
|
||||
## Improvements
|
||||
|
||||
- Added regression tests covering parse/write round-trips for multi-line descriptions.
|
||||
- Synced README and docs mirrors so the latest release messaging matches the updated skill metadata behavior.
|
||||
|
||||
## Version Changes
|
||||
|
||||
### Plugin Updates
|
||||
|
||||
- **GitHub Copilot SDK Pipe**: v0.12.1 → v0.12.2 | [📖 README](https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/pipes/github-copilot-sdk/README.md)
|
||||
|
||||
---
|
||||
|
||||
📚 [Documentation Portal](https://fu-jie.github.io/openwebui-extensions/)
|
||||
🐛 [Report Issues](https://github.com/Fu-Jie/openwebui-extensions/issues)
|
||||
29
plugins/pipes/github-copilot-sdk/v0.12.2_CN.md
Normal file
29
plugins/pipes/github-copilot-sdk/v0.12.2_CN.md
Normal file
@@ -0,0 +1,29 @@
|
||||
# GitHub Copilot SDK Pipe v0.12.2
|
||||
|
||||
这个补丁版本重点加固了内置 `manage_skills` 工作流,让 Pipe 能更可靠地读写带有多行描述的 `SKILL.md` 元数据。
|
||||
|
||||
## 新功能
|
||||
|
||||
- **多行 Frontmatter 解析**:`manage_skills` 现已支持 folded(`description: >`)和 literal(`description: |`)两种 frontmatter 描述格式,并兼容 CRLF 输入。
|
||||
- **稳定的 `SKILL.md` 回写**:当通过 Pipe 创建或编辑技能且描述包含换行时,现在会自动写成 YAML block scalar。
|
||||
|
||||
## 问题修复
|
||||
|
||||
- 修复源 `SKILL.md` 使用多行 YAML frontmatter 时,导入后的技能描述被截断或压平成单段文本的问题。
|
||||
- 当 `name` 缺失时新增 `title` 回退,减少技能导入/同步时退回通用目录名的情况。
|
||||
|
||||
## 优化提升
|
||||
|
||||
- 新增覆盖多行描述 parse/write round-trip 的回归测试。
|
||||
- 同步更新 README 与 docs 镜像页,确保最新发布说明与技能元数据行为一致。
|
||||
|
||||
## 版本变更
|
||||
|
||||
### 插件更新
|
||||
|
||||
- **GitHub Copilot SDK Pipe**: v0.12.1 → v0.12.2 | [📖 README](https://github.com/Fu-Jie/openwebui-extensions/blob/main/plugins/pipes/github-copilot-sdk/README_CN.md)
|
||||
|
||||
---
|
||||
|
||||
📚 [文档门户](https://fu-jie.github.io/openwebui-extensions/)
|
||||
🐛 [报告问题](https://github.com/Fu-Jie/openwebui-extensions/issues)
|
||||
62
tests/plugins/pipes/test_github_copilot_sdk_skill_meta.py
Normal file
62
tests/plugins/pipes/test_github_copilot_sdk_skill_meta.py
Normal file
@@ -0,0 +1,62 @@
|
||||
import importlib.util
|
||||
import sys
|
||||
from pathlib import Path
|
||||
|
||||
|
||||
MODULE_PATH = (
|
||||
Path(__file__).resolve().parents[3]
|
||||
/ "plugins"
|
||||
/ "pipes"
|
||||
/ "github-copilot-sdk"
|
||||
/ "github_copilot_sdk.py"
|
||||
)
|
||||
SPEC = importlib.util.spec_from_file_location("github_copilot_sdk", MODULE_PATH)
|
||||
github_copilot_sdk = importlib.util.module_from_spec(SPEC)
|
||||
assert SPEC.loader is not None
|
||||
sys.modules[SPEC.name] = github_copilot_sdk
|
||||
SPEC.loader.exec_module(github_copilot_sdk)
|
||||
|
||||
PIPE = github_copilot_sdk.Pipe()
|
||||
|
||||
|
||||
def test_pipe_parse_skill_md_meta_supports_folded_multiline_description():
|
||||
content = (
|
||||
"---\r\n"
|
||||
"name: persona-selector\r\n"
|
||||
"description: >\r\n"
|
||||
" Two-step persona picker.\r\n"
|
||||
" Step 2 provides persona options.\r\n"
|
||||
"---\r\n\r\n"
|
||||
"# Persona Selector\r\n\r\n"
|
||||
"Body content.\r\n"
|
||||
)
|
||||
|
||||
name, description, body = PIPE._parse_skill_md_meta(content, "fallback-skill")
|
||||
|
||||
assert name == "persona-selector"
|
||||
assert description == "Two-step persona picker. Step 2 provides persona options."
|
||||
assert body == "# Persona Selector\n\nBody content."
|
||||
|
||||
|
||||
def test_pipe_build_skill_md_content_round_trips_multiline_description():
|
||||
content = PIPE._build_skill_md_content(
|
||||
"Data Storyteller",
|
||||
"First line.\nSecond line.\n\nThird paragraph.",
|
||||
"Explain how to turn analysis into a narrative.",
|
||||
)
|
||||
|
||||
assert (
|
||||
"description: |\n"
|
||||
" First line.\n"
|
||||
" Second line.\n"
|
||||
"\n"
|
||||
" Third paragraph.\n"
|
||||
) in content
|
||||
|
||||
name, description, body = PIPE._parse_skill_md_meta(content, "fallback-skill")
|
||||
|
||||
assert name == "Data Storyteller"
|
||||
assert description == "First line.\nSecond line.\n\nThird paragraph."
|
||||
assert body == (
|
||||
"# Data Storyteller\n\nExplain how to turn analysis into a narrative."
|
||||
)
|
||||
Reference in New Issue
Block a user