feat(github-copilot-sdk): add workspace skills support (v0.9.0)#51
Conversation
- Introduce ENABLE_WORKSPACE_SKILLS valve to enable/disable workspace custom tools discovery - Modify _build_session_config() to auto-load tools from .copilot-skills/ directory - Add workspace_skills_example.py template with 3 working example tools - Update README.md and README_CN.md with Workspace Skills guide and usage examples - Create v0.9.0.md and v0.9.0_CN.md release notes - Sync version to all docs files (index.md, index.zh.md, and main docs) - Bump version from 0.8.0 to 0.9.0 across all 7+ locations
✅ Plugin Version Check / 插件版本检查版本更新检测通过!PR 包含版本变化和更新说明。 Version check passed! PR contains version changes and update description. 版本变化 / Version ChangesPlugin Updates
This comment was generated automatically. / 此评论由自动生成。 |
Summary of ChangesHello @Fu-Jie, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces the Workspace Skills feature to the GitHub Copilot SDK Pipe, allowing users to define custom tools within their workspace. It also updates documentation and adds a new valve to control the feature. Highlights
Changelog
Activity
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here. You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension. Footnotes
|
- Add TEMP_FILES_POLICY.md guideline for all skills and workflows - Update pr-submitter skill to use .temp/ directory instead of /tmp - Update release-prep skill documentation with temp file convention - Add .temp/ and .build/ entries to .gitignore - Create internal policy memo in /memories/repo/ This policy ensures: - All temporary files stay within project workspace (not system /tmp) - Alignment with OpenWebUI workspace isolation principles - Multi-user safety and cleanup traceability - Consistent handling across all skills and development workflows
There was a problem hiding this comment.
Code Review
This pull request introduces Workspace Skills support for the GitHub Copilot SDK pipe, a significant feature enhancement. The changes include updates to the core Python pipe, a new example skill file, and extensive documentation updates. While the core implementation is solid, there are several issues in the documentation and the new example file that need attention. Specifically, there are encoding errors in the README files, and the code examples for defining tools are misleading and inconsistent with the project's style guide. The new example skill file also demonstrates tool registration in a redundant and confusing manner, which could misguide users.
| # Example 1: Simple Math Helper Tool | ||
| # ============================================================================ | ||
|
|
||
| @define_tool(description="Perform common mathematical calculations") |
There was a problem hiding this comment.
This function, and the others in this example file, are registered as tools twice: once here with the @define_tool decorator, and again at the end of the file using the define_tool(...)() wrapper syntax. This is redundant and can be confusing, potentially leading to duplicate tool registrations.
To provide a single, clear registration pattern that aligns with the style guide, please remove the decorators from all three example functions (calculate_math, process_text, analyze_data) and rely only on the explicit wrapper registrations at the end of the file. The explicit registration is preferred as it correctly uses params_type.
| - **�️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | ||
| - **�🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. |
There was a problem hiding this comment.
There appear to be encoding issues in the 'Key Capabilities' list, resulting in replacement characters (️, 🛡️). These should be corrected to display the intended emojis for clarity.
| - **�️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | |
| - **�🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. | |
| - **🛠️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | |
| - **🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. |
| 3. Define tools using `@define_tool` decorator: | ||
| ```python | ||
| from pydantic import BaseModel, Field | ||
| from copilot import define_tool | ||
|
|
||
| class SearchParams(BaseModel): | ||
| query: str = Field(..., description="Search query") | ||
| limit: int = Field(default=10, description="Max results") | ||
|
|
||
| @define_tool(description="Search your custom database") | ||
| async def search_custom_db(query: str, limit: int = 10) -> dict: | ||
| # Your implementation | ||
| return {"results": [...]} | ||
| ``` |
There was a problem hiding this comment.
This example for search_custom_db defines a SearchParams model but doesn't use it in the @define_tool decorator. The repository style guide (line 100) requires using params_type for tool definitions to ensure robustness and prevent schema issues.
| 3. Define tools using `@define_tool` decorator: | |
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class SearchParams(BaseModel): | |
| query: str = Field(..., description="Search query") | |
| limit: int = Field(default=10, description="Max results") | |
| @define_tool(description="Search your custom database") | |
| async def search_custom_db(query: str, limit: int = 10) -> dict: | |
| # Your implementation | |
| return {"results": [...]} | |
| ``` | |
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class SearchParams(BaseModel): | |
| query: str = Field(..., description="Search query") | |
| limit: int = Field(default=10, description="Max results") | |
| @define_tool( | |
| description="Search your custom database", | |
| params_type=SearchParams | |
| ) | |
| async def search_custom_db(query: str, limit: int = 10) -> dict: | |
| # Your implementation | |
| return {"results": [...]} |
<details>
<summary>References</summary>
1. The style guide (line 100) mandates the use of `params_type` in `define_tool` to prevent schema hallucination. This example omits it. <sup>([link](https://github.com/Fu-Jie/openwebui-extensions/blob/main/.gemini/styleguide.md))</sup>
</details>
| ```python | ||
| from pydantic import BaseModel, Field | ||
| from copilot import define_tool | ||
|
|
||
| class QueryParams(BaseModel): | ||
| sql: str = Field(..., description="SQL query") | ||
|
|
||
| @define_tool(description="Query local database") | ||
| async def query_database(sql: str) -> dict: | ||
| # Connect to your database and execute query | ||
| return {"data": [...]} | ||
| ``` |
There was a problem hiding this comment.
Similar to the previous example, this query_database tool definition should use the params_type argument in the @define_tool decorator to explicitly link the QueryParams model, as required by the repository's style guide (line 100).
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class QueryParams(BaseModel): | |
| sql: str = Field(..., description="SQL query") | |
| @define_tool(description="Query local database") | |
| async def query_database(sql: str) -> dict: | |
| # Connect to your database and execute query | |
| return {"data": [...]} | |
| ``` | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class QueryParams(BaseModel): | |
| sql: str = Field(..., description="SQL query") | |
| @define_tool( | |
| description="Query local database", | |
| params_type=QueryParams | |
| ) | |
| async def query_database(sql: str) -> dict: | |
| # Connect to your database and execute query | |
| return {"data": [...]} |
References
- The style guide (line 100) mandates the use of
params_typeindefine_toolto prevent schema hallucination. This example omits it. (link)
| - **�️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | ||
| - **�🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 |
There was a problem hiding this comment.
The '核心能力' list contains replacement characters (️, 🛡️) due to an encoding issue. Please correct them to display the proper emojis.
| - **�️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | |
| - **�🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 | |
| - **🛠️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | |
| - **🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 |
| 3. 使用 `@define_tool` 装饰器定义工具: | ||
| ```python | ||
| from pydantic import BaseModel, Field | ||
| from copilot import define_tool | ||
|
|
||
| class SearchParams(BaseModel): | ||
| query: str = Field(..., description="搜索查询") | ||
| limit: int = Field(default=10, description="最大结果数") | ||
|
|
||
| @define_tool(description="搜索您的自定义数据库") | ||
| async def search_custom_db(query: str, limit: int = 10) -> dict: | ||
| # 您的实现 | ||
| return {"results": [...]} | ||
| ``` |
There was a problem hiding this comment.
This example for search_custom_db defines a SearchParams model but doesn't use it in the @define_tool decorator. The repository style guide (line 100) requires using params_type for tool definitions to ensure robustness and prevent schema issues.
| 3. 使用 `@define_tool` 装饰器定义工具: | |
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class SearchParams(BaseModel): | |
| query: str = Field(..., description="搜索查询") | |
| limit: int = Field(default=10, description="最大结果数") | |
| @define_tool(description="搜索您的自定义数据库") | |
| async def search_custom_db(query: str, limit: int = 10) -> dict: | |
| # 您的实现 | |
| return {"results": [...]} | |
| ``` | |
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class SearchParams(BaseModel): | |
| query: str = Field(..., description="搜索查询") | |
| limit: int = Field(default=10, description="最大结果数") | |
| @define_tool( | |
| description="搜索您的自定义数据库", | |
| params_type=SearchParams | |
| ) | |
| async def search_custom_db(query: str, limit: int = 10) -> dict: | |
| # 您的实现 | |
| return {"results": [...]} |
<details>
<summary>References</summary>
1. The style guide (line 100) mandates the use of `params_type` in `define_tool` to prevent schema hallucination. This example omits it. <sup>([link](https://github.com/Fu-Jie/openwebui-extensions/blob/main/.gemini/styleguide.md))</sup>
</details>
| ```python | ||
| from pydantic import BaseModel, Field | ||
| from copilot import define_tool | ||
|
|
||
| class QueryParams(BaseModel): | ||
| sql: str = Field(..., description="SQL 查询") | ||
|
|
||
| @define_tool(description="查询本地数据库") | ||
| async def query_database(sql: str) -> dict: | ||
| # 连接数据库并执行查询 | ||
| return {"data": [...]} | ||
| ``` |
There was a problem hiding this comment.
Similar to the previous example, this query_database tool definition should use the params_type argument in the @define_tool decorator to explicitly link the QueryParams model, as required by the repository's style guide (line 100).
| ```python | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class QueryParams(BaseModel): | |
| sql: str = Field(..., description="SQL 查询") | |
| @define_tool(description="查询本地数据库") | |
| async def query_database(sql: str) -> dict: | |
| # 连接数据库并执行查询 | |
| return {"data": [...]} | |
| ``` | |
| from pydantic import BaseModel, Field | |
| from copilot import define_tool | |
| class QueryParams(BaseModel): | |
| sql: str = Field(..., description="SQL 查询") | |
| @define_tool( | |
| description="查询本地数据库", | |
| params_type=QueryParams | |
| ) | |
| async def query_database(sql: str) -> dict: | |
| # 连接数据库并执行查询 | |
| return {"data": [...]} |
References
- The style guide (line 100) mandates the use of
params_typeindefine_toolto prevent schema hallucination. This example omits it. (link)
…s' for accuracy The term 'Skills' in Anthropic context refers to instruction-based frameworks (SKILL.md files with YAML frontmatter + markdown), not custom tool functions. Our implementation uses @define_tool decorator to define custom tools that the SDK auto-discovers from .copilot-skills/ directory. These are Tools, not Skills. Changes: - Rename ENABLE_WORKSPACE_SKILLS valve -> ENABLE_WORKSPACE_TOOLS - Update all documentation (README, README_CN, docs, release notes) - Fix section headings and descriptions throughout - Ensure consistent terminology across all files This is a terminology-only change; functionality remains identical.
There was a problem hiding this comment.
Pull request overview
Adds “Workspace Skills” support to the github-copilot-sdk Pipe (v0.9.0) so custom Copilot SDK tools can be discovered from a workspace-local .copilot-skills/ directory, alongside version/doc updates across plugin and docs.
Changes:
- Add
ENABLE_WORKSPACE_SKILLSvalve and pass.copilot-skillsasskill_directorieswhen present. - Add a workspace skills example Python file and new v0.9.0 release notes (EN/CN).
- Bump version references to
0.9.0across README and docs indexes/pages.
Reviewed changes
Copilot reviewed 13 out of 14 changed files in this pull request and generated 9 comments.
Show a summary per file
| File | Description |
|---|---|
| plugins/pipes/github-copilot-sdk/github_copilot_sdk.py | Adds valve + session config wiring for workspace skill directories; bumps plugin version to 0.9.0 |
| plugins/pipes/github-copilot-sdk/workspace_skills_example.py | Adds a template/example skills file with sample tools and registration patterns |
| plugins/pipes/github-copilot-sdk/README.md | Updates version + documents Workspace Skills feature |
| plugins/pipes/github-copilot-sdk/README_CN.md | Updates version + documents Workspace Skills feature (CN) |
| plugins/pipes/github-copilot-sdk/v0.9.0.md | Adds v0.9.0 release notes (EN) |
| plugins/pipes/github-copilot-sdk/v0.9.0_CN.md | Adds v0.9.0 release notes (CN) |
| docs/plugins/pipes/index.md | Updates pipe index entry to v0.9.0 and mentions Workspace Skills |
| docs/plugins/pipes/index.zh.md | Updates pipe index entry to v0.9.0 and mentions Workspace Skills (CN) |
| docs/plugins/pipes/github-copilot-sdk.md | Updates docs page metadata/version and “What’s New” section |
| docs/plugins/pipes/github-copilot-sdk.zh.md | Updates docs page “What’s New” section (CN) |
| description="Enable Direct MCP Client connection (Recommended).", | ||
| ) | ||
| ENABLE_WORKSPACE_SKILLS: bool = Field( | ||
| default=True, |
There was a problem hiding this comment.
ENABLE_WORKSPACE_SKILLS is enabled by default, which means Python modules in {workspace}/.copilot-skills/ may be auto-imported/executed as tools. Since the workspace is writable during conversations, this effectively enables arbitrary code execution in the backend context. Consider defaulting this valve to False (opt-in), and/or gating it to admins / requiring an explicit allowlist to avoid untrusted code being loaded.
| default=True, | |
| default=False, |
| @define_tool(description="Perform common mathematical calculations") | ||
| async def calculate_math(operation: str, value1: float, value2: float = 0) -> dict: | ||
| """ |
There was a problem hiding this comment.
This example uses bare @define_tool(description=...) decorators without an explicit params_type. In this repo, tools are typically registered with an explicit Pydantic params model to ensure the SDK exposes a correct JSON schema (and avoids “no properties”/empty params). Consider updating the examples to always provide a params_type model (either via the decorator if supported, or via explicit define_tool(name=..., params_type=...) registration).
| --- | ||
|
|
||
| ## 📋 常见问题与依赖 (Troubleshooting) | ||
| ## �️ 工作区技能 |
There was a problem hiding this comment.
The section heading ## �️ 工作区技能 contains a replacement character (�), which indicates an encoding/copy-paste issue and renders broken in Markdown. Please replace it with the intended emoji (or remove the emoji) so the heading displays correctly.
| ## �️ 工作区技能 | |
| ## 🛠️ 工作区技能 |
| workspace_skills_dir = str(Path(resolved_cwd) / ".copilot-skills") | ||
| if Path(workspace_skills_dir).exists(): | ||
| session_params["skill_directories"] = [workspace_skills_dir] |
There was a problem hiding this comment.
When enabling workspace skills, the code only checks Path(...).exists(). If .copilot-skills exists but is a file/symlink, you may pass an invalid path into the SDK and get confusing failures. Prefer checking is_dir() (and ideally resolve the path once) before setting skill_directories.
| workspace_skills_dir = str(Path(resolved_cwd) / ".copilot-skills") | |
| if Path(workspace_skills_dir).exists(): | |
| session_params["skill_directories"] = [workspace_skills_dir] | |
| workspace_skills_path = (Path(resolved_cwd) / ".copilot-skills").resolve() | |
| if workspace_skills_path.is_dir(): | |
| session_params["skill_directories"] = [str(workspace_skills_path)] |
| math_tool = define_tool( | ||
| name="calculate_math", | ||
| description="Perform mathematical calculations (add, subtract, multiply, divide, power, sqrt)", | ||
| params_type=BaseModel, # Can be complex if needed | ||
| )(calculate_math) |
There was a problem hiding this comment.
params_type=BaseModel is not a valid parameter schema for a tool (it has no fields), so the generated tool JSON schema will be empty/incorrect. Define a dedicated BaseModel subclass (e.g., with operation, value1, value2) and use that as params_type for calculate_math.
| - **�️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | ||
| - **�🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. |
There was a problem hiding this comment.
The “Key Capabilities” list contains invalid replacement characters (�) before emojis, which indicates an encoding/copy-paste issue and renders incorrectly in Markdown. Please replace these with the intended emoji (or remove the emoji entirely) so the bullets display correctly.
| - **�️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | |
| - **�🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. | |
| - **🛠️ Workspace Skills**: Define custom tools in `.copilot-skills/` directory using `@define_tool` decorator. Auto-discovered and registered by the SDK. | |
| - **🛡️ Sandbox Workspace Isolation**: Strict per-session sandboxing for data privacy and security. |
| # GitHub Copilot SDK 官方管道 | ||
|
|
||
| **作者:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **版本:** 0.8.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可证:** MIT | ||
| **作者:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **版本:** 0.9.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可证:** MIT |
There was a problem hiding this comment.
The Author link in the README metadata should point to the profile (https://github.com/Fu-Jie), while the Project link points to the repository. This line currently links Author to the repo, which is inconsistent with the repo README metadata convention.
| **作者:** [Fu-Jie](https://github.com/Fu-Jie/openwebui-extensions) | **版本:** 0.9.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可证:** MIT | |
| **作者:** [Fu-Jie](https://github.com/Fu-Jie) | **版本:** 0.9.0 | **项目:** [OpenWebUI Extensions](https://github.com/Fu-Jie/openwebui-extensions) | **许可证:** MIT |
| - **�️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | ||
| - **�🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 |
There was a problem hiding this comment.
The “核心能力” list contains invalid replacement characters (�) before emojis, indicating an encoding/copy-paste issue that renders incorrectly in Markdown. Please replace these with the intended emoji (or remove the emoji) so the bullets display correctly.
| - **�️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | |
| - **�🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 | |
| - **🛠️ 工作区技能**: 在 `.copilot-skills/` 目录中使用 `@define_tool` 装饰器定义自定义工具,SDK 自动发现和注册。 | |
| - **🛡️ 物理级工作区隔离**: 强制执行严格的用户特定沙箱,确保数据隐私与文件安全。 |
|
|
||
| --- | ||
|
|
||
| ## �📋 常见问题与依赖 (Troubleshooting) |
There was a problem hiding this comment.
The section heading ## �📋 常见问题与依赖 (Troubleshooting) contains a replacement character (�), which will render garbled in Markdown. Please replace it with the intended emoji (or remove the emoji) to avoid broken headings.
| ## �📋 常见问题与依赖 (Troubleshooting) | |
| ## 📋 常见问题与依赖 (Troubleshooting) |
- Integrated OpenWebUI Skills Bridge and manage_skills tool - Reinforced status bar stability with session_finalized logic - Added persistent SDK config directory support
- Added skill manager and best practices guides - Added publishing tool documentation - Included v0.9.0 release notes and deployment script - Updated usage guides
Summary
Introduce Workspace Skills for GitHub Copilot SDK Pipe v0.9.0, enabling developers to define custom tools directly in their workspace without modifying plugin code.
Key Changes
Version: 0.8.0 → 0.9.0
Updated across 7+ files (code, README, docs, etc.)
Status