twwch

feishu-doc-to-dev-spec

by @twwch in Tools
29
0
# Install this skill:
npx skills add twwch/OpenSkills

Or install specific skill: npx add-skill https://github.com/twwch/OpenSkills/tree/main/examples/feishu-doc-to-dev-spec

# Description

读取飞书云文档(支持多个链接),解析文档中的文本、表格、图片等内容,根据用户选择的开发语言和存储结构,将产品需求文档转换为研发开发需求文档

# SKILL.md


name: feishu-doc-to-dev-spec
description: 读取飞书云文档(支持多个链接),解析文档中的文本、表格、图片等内容,根据用户选择的开发语言和存储结构,将产品需求文档转换为研发开发需求文档
triggers:
- "飞书文档"
- "需求文档"
- "PRD转研发"
- "feishu"
- "产品需求转开发"
dependency:
python:
- httpx>=0.25.0
- lark-oapi>=1.0.0
system:
- mkdir -p output/images


飞书云文档转研发需求文档

任务目标

本 Skill 用于:
1. 读取飞书云文档内容(支持多个文档链接)
2. 完整解析文档中的所有内容:文本、表格、图片、代码块等
3. 根据用户选择的开发语言和存储结构
4. 将产品需求文档(PRD)转换为结构化的研发开发需求文档

前置准备

飞书应用配置

使用前需要创建飞书应用并获取凭证:

  1. 访问 飞书开放平台
  2. 创建企业自建应用
  3. 获取 App ID 和 App Secret
  4. 配置应用权限:
  5. docx:document:readonly - 读取文档内容
  6. drive:drive:readonly - 读取云空间文件
  7. wiki:wiki:readonly - 读取知识库(如需要)

环境变量

export FEISHU_APP_ID=your-app-id
export FEISHU_APP_SECRET=your-app-secret

操作步骤

标准流程

  1. 收集文档链接
  2. 用户提供一个或多个飞书文档链接
  3. 支持的链接格式:

    • https://xxx.feishu.cn/docx/xxxxx - 新版文档
    • https://xxx.feishu.cn/docs/xxxxx - 旧版文档
    • https://xxx.feishu.cn/wiki/xxxxx - 知识库文档
  4. 确认技术选型

  5. 询问用户选择的开发语言(如:Python、Java、Go、Node.js、Rust 等)
  6. 询问存储结构(如:PostgreSQL、MySQL、MongoDB、Redis 等)
  7. 询问其他技术栈偏好(框架、部署方式等)

  8. 读取文档内容

  9. 调用 [INVOKE:fetch_feishu_doc] 脚本
  10. 传入文档链接列表
  11. 脚本会返回完整的文档内容,包括:

    • 文本段落
    • 表格数据(转换为 Markdown 表格)
    • 图片(下载到本地并返回路径)
    • 代码块
    • 有序/无序列表
  12. 分析需求内容

  13. 识别功能需求、非功能需求
  14. 提取业务规则和约束
  15. 整理用户故事和验收标准

  16. 生成研发需求文档

  17. 根据用户选择的技术栈
  18. 生成包含以下内容的研发文档:

    • 技术架构设计
    • 数据模型设计(表结构)
    • API 接口设计
    • 核心功能实现方案
    • 技术风险评估
  19. 输出结果

  20. 生成 Markdown 格式的研发需求文档
  21. 保存到 ./output/ 目录

资源索引

脚本

  • 飞书文档读取scripts/fetch_feishu_doc.py
  • 用途:读取飞书云文档的完整内容
  • 输入参数(JSON 格式):
    json { "doc_urls": ["https://xxx.feishu.cn/docx/xxxxx"], "app_id": "飞书应用ID(可选,默认从环境变量读取)", "app_secret": "飞书应用密钥(可选,默认从环境变量读取)" }
  • 输出:文档内容的 JSON 结构

参考文档

  • 研发文档模板references/dev-spec-template.md
  • 何时读取:生成研发需求文档时
  • 包含标准的研发文档结构和示例

  • 技术选型指南references/tech-stack-guide.md

  • 何时读取:帮助用户选择技术栈时
  • 包含常见技术栈的特点和适用场景

注意事项

文档权限

  • 确保飞书应用有权限访问目标文档
  • 如果文档是私有的,需要将应用添加为文档协作者

图片处理

  • 文档中的图片会被下载到 ./output/images/ 目录
  • 图片链接会被替换为本地相对路径

多文档合并

  • 当用户提供多个文档链接时,会按顺序读取并合并内容
  • 每个文档的内容会用分隔线区分

输出格式

  • 研发需求文档采用 Markdown 格式
  • 表格使用 Markdown 表格语法
  • 代码块使用对应语言的语法高亮标记

使用示例

示例 1:单个文档转换

用户输入

请帮我把这个产品需求文档转换为研发需求文档:
https://example.feishu.cn/docx/abc123

技术栈:
- 语言:Python
- 框架:FastAPI
- 数据库:PostgreSQL
- 缓存:Redis

执行流程
1. 调用 [INVOKE:fetch_feishu_doc] 读取文档
2. 分析需求内容
3. 根据 Python + FastAPI + PostgreSQL 技术栈生成研发文档
4. 输出到 ./output/dev-spec.md

示例 2:多个文档合并

用户输入

这是我们的产品需求文档,包含多个部分:
1. 总体需求:https://example.feishu.cn/docx/main
2. 用户模块:https://example.feishu.cn/docx/user
3. 订单模块:https://example.feishu.cn/docx/order

请使用 Java + Spring Boot + MySQL 生成研发文档

执行流程
1. 依次读取三个文档
2. 合并并分析需求
3. 生成 Java 技术栈的研发文档

研发文档输出结构

生成的研发需求文档包含以下章节:

# 研发需求文档

## 1. 项目概述
- 项目背景
- 项目目标
- 技术栈选型

## 2. 系统架构
- 整体架构图
- 模块划分
- 技术组件

## 3. 数据模型设计
- ER 图
- 表结构定义
- 索引设计

## 4. API 接口设计
- 接口列表
- 请求/响应格式
- 错误码定义

## 5. 功能模块详设
- 模块 A
  - 功能描述
  - 实现方案
  - 关键代码示例
- 模块 B
  - ...

## 6. 非功能需求
- 性能要求
- 安全要求
- 可用性要求

## 7. 开发计划
- 里程碑
- 任务分解
- 风险评估

# README.md

OpenSkills SDK

An open-source Agent Skill framework implementing the progressive disclosure architecture for AI agent skills.

PyPI version
License
Python 3.10+

Features

  • Three-layer progressive disclosure architecture
  • Layer 1 (Metadata): Always loaded for skill discovery
  • Layer 2 (Instruction): Loaded on demand when skill is selected
  • Layer 3 (Resources): Conditionally loaded References and Scripts

  • SKILL.md file format - Simple markdown-based skill definition

  • Smart Reference loading - Three modes (explicit/implicit/always) with LLM-based selection
  • Auto-discovery - Automatically discover references from references/ directory
  • Script execution - Run scripts triggered by LLM via [INVOKE:name]
  • Multiple LLM providers - OpenAI, Azure OpenAI, Ollama, Together, Groq, DeepSeek
  • Auto skill invocation - Automatically match and invoke skills based on user queries
  • Multimodal support - Handle images via URL, base64, or file path
  • Sandbox execution - Secure script execution in isolated AIO Sandbox environment
  • Automatic file sync - Upload input files and download outputs automatically

Installation

pip install openskills-sdk

Quick Start

import asyncio
from openskills import create_agent

async def main():
    # Create agent with infographic-skills
    agent = await create_agent(
        skill_paths=["./infographic-skills"],
        api_key="your-api-key",
        model="gpt-4",
    )

    # Chat with automatic skill invocation
    response = await agent.chat("帮我总结会议")
    print(response.content)
    print(f"Used skill: {response.skill_used}")

asyncio.run(main())
import asyncio
from openskills import create_agent

async def main():
    # Create agent with sandbox enabled
    agent = await create_agent(
        skill_paths=["./skills"],
        api_key="your-api-key",
        model="gpt-4",
        use_sandbox=True,  # Enable sandbox execution
        sandbox_base_url="http://localhost:8080",
        auto_execute_scripts=True,
    )

    # Local file paths are automatically uploaded to sandbox
    response = await agent.chat("请处理这个文件: /path/to/file.pdf")
    print(response.content)

    # Output files are automatically downloaded to skill_dir/output/

asyncio.run(main())

Using SkillManager (Low-level API)

from pathlib import Path
from openskills import SkillManager

manager = SkillManager([Path("./infographic-skills")])

# Discover infographic-skills (Layer 1 - Metadata)
await manager.discover()

# Match user query
skills = manager.match("summarize meeting")

# Load instruction (Layer 2)
if skills:
    instruction = await manager.load_instruction(skills[0].name)
    print(instruction.content)

Sandbox Environment

OpenSkills supports executing scripts in an isolated sandbox environment using AIO Sandbox. This provides:

  • Security: Scripts run in isolated containers
  • Dependency management: Auto-install Python packages defined in SKILL.md
  • File synchronization: Automatic upload/download of files

Installing AIO Sandbox

# Pull and run the sandbox container
docker run -d --name aio-sandbox \
  -p 8080:8080 \
  ghcr.io/agent-infra/aio-sandbox:latest

# Verify it's running
curl http://localhost:8080/health

Option 2: Docker Compose

# docker-compose.yml
version: '3.8'
services:
  sandbox:
    image: ghcr.io/agent-infra/aio-sandbox:latest
    ports:
      - "8080:8080"
    volumes:
      - sandbox-data:/home/gem
    restart: unless-stopped

volumes:
  sandbox-data:
docker-compose up -d

Sandbox Features

Automatic Dependency Installation

Define dependencies in SKILL.md frontmatter:

dependency:
  python:
    - PyMuPDF==1.23.8
    - pandas>=2.0.0
  system:
    - mkdir -p output/images

Dependencies are installed automatically when the skill is initialized.

Automatic File Synchronization

  1. Upload: Local file paths in script input are auto-uploaded to /home/gem/uploads/
  2. Download: Specify output directories in script config to auto-download results
scripts:
  - name: process_file
    path: scripts/process.py
    description: Process uploaded files
    timeout: 120
    outputs:
      - /home/gem/output  # Auto-sync to local skill_dir/output/

Sandbox Client API

For advanced use cases, use the SandboxClient directly:

from openskills.sandbox import SandboxClient

async with SandboxClient("http://localhost:8080") as client:
    # Execute commands
    result = await client.exec_command("python --version")
    print(result.output)

    # File operations
    await client.write_file("/home/gem/test.txt", "Hello World")
    content = await client.read_file("/home/gem/test.txt")

    # Upload/download files
    await client.upload_file(local_bytes, "/home/gem/uploads/file.pdf")
    data = await client.download_file("/home/gem/output/result.txt")

    # List files
    files = await client.list_files("/home/gem/output")
    for f in files:
        print(f"{f.name} (dir={f.is_dir})")

Skill Structure

my-skill/
├── SKILL.md              # Skill definition (required)
├── references/           # Reference documents
│   └── handbook.md
└── scripts/              # Executable scripts
    └── upload.py

SKILL.md Format

---
name: meeting-summary
description: Summarize meetings in structured format
version: 1.0.0
triggers:
  - "summarize meeting"
  - "会议总结"

references:
  - path: references/finance-handbook.md
    condition: "When content involves finance or budget"
    description: Financial guidelines
    mode: explicit  # LLM evaluates condition
  - path: references/frameworks/
    mode: implicit  # LLM decides if useful (default)
  - path: references/safety-policy.md
    mode: always    # Always loaded

scripts:
  - name: upload
    path: scripts/upload.py
    description: Upload summary to cloud storage
---

# Meeting Summary Skill

You are a professional meeting assistant...

## Output Format

...

Architecture

┌─────────────────────────────────────────────────────────────┐
│                    OpenSkills SDK                            │
├─────────────────────────────────────────────────────────────┤
│  Layer 1: Metadata (Always loaded)                          │
│  ├── name, description, triggers, tags                      │
│  └── Used for skill discovery and matching                  │
├─────────────────────────────────────────────────────────────┤
│  Layer 2: Instruction (On-demand)                           │
│  ├── SKILL.md body content                                  │
│  └── Loaded when skill is selected                          │
├─────────────────────────────────────────────────────────────┤
│  Layer 3: Resources (Conditional)                           │
│  ├── Reference: Documents loaded based on conditions        │
│  └── Script: Executed when LLM outputs [INVOKE:name]        │
└─────────────────────────────────────────────────────────────┘

Reference Loading Modes

References support three loading modes:

Mode Behavior
explicit Has condition, LLM evaluates whether condition is met
implicit No condition, LLM decides if useful for current query (default)
always Always loaded (e.g., safety guidelines, specs)

Auto-Discovery

References are automatically discovered from the references/ directory. You don't need to declare every file in frontmatter:

my-skill/
├── SKILL.md
└── references/
    ├── guide.md          # Auto-discovered (implicit mode)
    ├── api-docs.md       # Auto-discovered (implicit mode)
    └── frameworks/
        └── react.md      # Auto-discovered (implicit mode)

You can still declare specific references in frontmatter to customize their behavior:

references:
  # Override mode for specific file
  - path: references/guide.md
    mode: always  # Now always loaded instead of implicit

  # Add condition for another file
  - path: references/api-docs.md
    condition: "When user asks about API"
    mode: explicit

Auto-discovered files that aren't declared in frontmatter default to implicit mode, letting the LLM decide whether to load them based on the user's query.

Environment Variables

OpenAI

export OPENAI_API_KEY=your-api-key
export OPENAI_BASE_URL=https://api.openai.com/v1  # Optional
export OPENAI_MODEL=gpt-4  # Optional

Azure OpenAI

export AZURE_OPENAI_API_KEY=your-azure-api-key
export AZURE_OPENAI_ENDPOINT=https://your-resource.openai.azure.com
export AZURE_OPENAI_DEPLOYMENT=your-deployment-name
export AZURE_OPENAI_API_VERSION=2024-02-15-preview  # Optional

Using Azure OpenAI

from openskills import AzureOpenAIClient, SkillAgent

# Method 1: Using environment variables
client = AzureOpenAIClient()

# Method 2: Explicit configuration
client = AzureOpenAIClient(
    api_key="your-api-key",
    endpoint="https://your-resource.openai.azure.com",
    deployment="gpt-4",
)

# Method 3: Using create_client helper
from openskills import create_client
client = create_client("azure", deployment="gpt-4")

# Use with SkillAgent
agent = SkillAgent(
    skill_paths=["./infographic-skills"],
    llm_client=client,
)

Examples

See the examples directory for complete examples:

  • demo.py - Main demo showing reference auto-discovery and LLM selection
  • prompt-optimizer/ - Prompt engineering skill with 57 frameworks (auto-discovered)
  • meeting-summary/ - Meeting summarization skill with finance reference
  • office-skills/ - Word and Excel processing skills
  • file-to-article-generator/ - PDF/Word parsing with sandbox execution
  • weekly-report-to-annual/ - Weekly report aggregation skill

Running Examples

Basic Demo (Local Execution)

cd examples
export OPENAI_API_KEY=your-api-key
python demo.py
# 1. Start sandbox first
docker run -d -p 8080:8080 ghcr.io/agent-infra/aio-sandbox:latest

# 2. Run demo with sandbox
cd examples/file-to-article-generator
export OPENAI_API_KEY=your-api-key
python demo.py /path/to/your/file.pdf

The sandbox demo will:
1. Initialize sandbox environment and install dependencies
2. Upload your file to sandbox automatically
3. Execute parsing script in isolated environment
4. Download generated images to local output/ directory
5. Generate article with proper image references

CLI Commands

# List all infographic-skills
openskills list

# Show skill details
openskills show meeting-summary

# Validate a skill
openskills validate ./my-skill/

# Match query to infographic-skills
openskills match "summarize meeting"

License

This project is licensed under the Apache License 2.0 - see the LICENSE file for details.

# Supported AI Coding Agents

This skill is compatible with the SKILL.md standard and works with all major AI coding agents:

Learn more about the SKILL.md standard and how to use these skills with your preferred AI coding agent.