mirror of
https://git.openapi.site/https://github.com/desirecore/market.git
synced 2026-06-06 04:30:42 +08:00
feat: skills i18n 改造(schemaVersion 1.1,零向后兼容) (#1)
* feat: skills i18n 改造 — schemaVersion 1.1,零向后兼容
把 21 个 skills + 1 个 agent + manifest/categories 全量迁移到 schemaVersion 1.1
的 i18n 结构,配套 CI AI 翻译流水线(GitHub Models)与本地工具链。
## 关键变更
### 数据结构(破坏性,schemaVersion 1.0 → 1.1)
- SKILL.md: 顶层 name 改为 ASCII slug(== 目录名,符合 agentskills.io 规范);
中文显示名/short_desc/description 全部迁入 metadata.i18n.<locale>
- agents/<id>/agent.json: shortDesc/fullDesc/tags/persona.{role,traits} 迁入
i18n.<locale>;changelog[].changes 改为 { <locale>: string[] } 对象
- categories.json: 每个分类的 label/description 迁入 i18n.<locale>,顶层只剩
color/icon
- manifest.json: 加 supportedLocales / defaultLocale;顶层 description 迁入
i18n.<locale>
### Body 文件结构
- 根 SKILL.md = frontmatter + default_locale (en-US) body
- SKILL.<locale>.md = 各 locale 的 markdown body(首行 <!-- locale: xx --> 自校验)
### 工具链(scripts/i18n/)
- glossary.json: zh→en 术语表 + do_not_translate 白名单
- schema/skill-frontmatter.schema.json: i18n frontmatter JSON Schema
- validate-i18n.py: 8 条校验规则(name 合规 / locale 完整性 / hash 一致性等)
- translate.py: GitHub Models / Anthropic 双 backend,sha256 增量翻译
- migrate.py: 一次性迁移脚本(旧格式 → i18n 结构)
### CI(.github/workflows/)
- i18n-validate.yml: PR 触发跑 validate + translate --check
- i18n-translate.yml: PR 触发用 GitHub Models(默认 openai/gpt-5-mini)翻译缺失
locale,自动追加 commit;可切到 ANTHROPIC_API_KEY 走 Claude
### 文档
- docs/I18N.md: 作者贡献指南(schema 说明 / 提交流程 / 常见问题)
- README.md: 加多语言段落
## 验证
- uv run scripts/i18n/validate-i18n.py: OK,49 文件 0 错误
- uv run scripts/i18n/translate.py --check: 0 stale locale
- 21 skills 标题数 zh-CN == en-US 严格对齐(最大 66=66)
- skills-ref 规范校验:全部通过(顶层 name ASCII slug + description 单字段)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
* fix(i18n): 修复 PR #1 review 反馈的 6 项问题
- schema: translated_by 正则放宽为 ^(human|ai:[A-Za-z0-9._:/-]+)$,接受
'ai:github:openai/gpt-5-mini' 这类 backend:model 形式(CI 翻译输出格式)
- README + docs/I18N.md: 修正"CI 用 Claude API"误导描述,正确说明默认是
GitHub Models(openai/gpt-5-mini)+ GITHUB_TOKEN,可选切到 Anthropic
- skills/minimax-tts/SKILL.md & SKILL.zh-CN.md: 删除多余的 ``` 闭合,避免
Markdown 后续渲染错乱
- skills/docx/SKILL.md: 翻译时丢失的 • Unicode escape 示例已恢复,
与 zh-CN 版本对齐
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
156
.github/workflows/i18n-translate.yml
vendored
Normal file
156
.github/workflows/i18n-translate.yml
vendored
Normal file
@@ -0,0 +1,156 @@
|
||||
name: i18n Auto-Translate
|
||||
|
||||
# Uses GitHub Models inference API (https://models.github.ai/inference) with the
|
||||
# repository's GITHUB_TOKEN. Requires `models: read` permission. Default model is
|
||||
# openai/gpt-5-mini (a fast/cheap GPT-5 in the catalog); override via repository variable
|
||||
# TRANSLATE_MODEL (e.g. openai/gpt-5-nano for cheaper, openai/gpt-5 for flagship).
|
||||
#
|
||||
# Optional: to use Anthropic Claude directly, add a repo secret ANTHROPIC_API_KEY,
|
||||
# then set repository variable TRANSLATE_BACKEND=anthropic and TRANSLATE_MODEL to
|
||||
# a Claude model id (e.g. claude-sonnet-4-6). Claude is NOT in the GitHub Models
|
||||
# catalog as of 2026-05.
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "skills/**/SKILL.zh-CN.md"
|
||||
- "skills/**/SKILL.md"
|
||||
- "manifest.json"
|
||||
- "categories.json"
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
target_locale:
|
||||
description: "Target locale (default: all from manifest.supportedLocales)"
|
||||
required: false
|
||||
skill:
|
||||
description: "Specific skill path, e.g. skills/web-access (default: all)"
|
||||
required: false
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
models: read
|
||||
|
||||
concurrency:
|
||||
group: i18n-translate-${{ github.ref }}
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
translate:
|
||||
# Don't run on bot's own commits to avoid loops
|
||||
if: github.actor != 'desirecore-bot[bot]' && !contains(github.event.head_commit.message, '[skip ci]')
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 30
|
||||
steps:
|
||||
- name: Checkout PR branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.ref || github.ref }}
|
||||
token: ${{ secrets.DESIRECORE_BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Check for stale translations
|
||||
id: precheck
|
||||
run: |
|
||||
set +e
|
||||
uv run --quiet scripts/i18n/translate.py --check
|
||||
rc=$?
|
||||
if [ $rc -eq 0 ]; then
|
||||
echo "stale=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "stale=true" >> "$GITHUB_OUTPUT"
|
||||
fi
|
||||
exit 0
|
||||
|
||||
- name: Translate stale locales
|
||||
if: steps.precheck.outputs.stale == 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
|
||||
TRANSLATE_BACKEND: ${{ vars.TRANSLATE_BACKEND || 'github' }}
|
||||
TRANSLATE_MODEL: ${{ vars.TRANSLATE_MODEL || 'openai/gpt-5-mini' }}
|
||||
run: |
|
||||
set -e
|
||||
ARGS=()
|
||||
if [ -n "${{ github.event.inputs.skill }}" ]; then
|
||||
ARGS+=("${{ github.event.inputs.skill }}")
|
||||
fi
|
||||
if [ -n "${{ github.event.inputs.target_locale }}" ]; then
|
||||
ARGS+=(--target "${{ github.event.inputs.target_locale }}")
|
||||
fi
|
||||
uv run --quiet scripts/i18n/translate.py "${ARGS[@]}"
|
||||
|
||||
- name: Validate after translation
|
||||
if: steps.precheck.outputs.stale == 'true'
|
||||
run: uv run --quiet scripts/i18n/validate-i18n.py
|
||||
|
||||
- name: Detect changes
|
||||
id: diff
|
||||
if: steps.precheck.outputs.stale == 'true'
|
||||
run: |
|
||||
if git diff --quiet; then
|
||||
echo "changed=false" >> "$GITHUB_OUTPUT"
|
||||
else
|
||||
echo "changed=true" >> "$GITHUB_OUTPUT"
|
||||
git diff --stat
|
||||
fi
|
||||
|
||||
- name: Commit & push translations
|
||||
if: steps.diff.outputs.changed == 'true'
|
||||
run: |
|
||||
git config user.name "desirecore-bot"
|
||||
git config user.email "bot@desirecore.net"
|
||||
git add -A
|
||||
git commit -m "chore(i18n): auto-translate skills [skip ci]" \
|
||||
-m "Generated by scripts/i18n/translate.py via i18n-translate workflow." \
|
||||
-m "Backend: ${TRANSLATE_BACKEND:-github} Model: ${TRANSLATE_MODEL:-openai/gpt-5-mini}"
|
||||
git push
|
||||
env:
|
||||
TRANSLATE_BACKEND: ${{ vars.TRANSLATE_BACKEND || 'github' }}
|
||||
TRANSLATE_MODEL: ${{ vars.TRANSLATE_MODEL || 'openai/gpt-5-mini' }}
|
||||
|
||||
- name: Comment on PR
|
||||
if: steps.diff.outputs.changed == 'true' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.DESIRECORE_BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const backend = process.env.TRANSLATE_BACKEND || 'github';
|
||||
const model = process.env.TRANSLATE_MODEL || 'openai/gpt-5-mini';
|
||||
const body = [
|
||||
'🌐 **i18n auto-translation pushed**',
|
||||
'',
|
||||
'New machine-translated content was added to this PR by `scripts/i18n/translate.py`.',
|
||||
'',
|
||||
'**Please review the translated strings** before merging:',
|
||||
'- Check terminology against `scripts/i18n/glossary.json`',
|
||||
'- Verify Markdown structure (headings/tables/code fences) is preserved',
|
||||
'- If you edit a translation, set `metadata.i18n.<locale>.translated_by: human` to lock it.',
|
||||
'',
|
||||
`Backend: \`${backend}\` Model: \`${model}\``,
|
||||
].join('\n');
|
||||
await github.rest.issues.createComment({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
body,
|
||||
});
|
||||
env:
|
||||
TRANSLATE_BACKEND: ${{ vars.TRANSLATE_BACKEND || 'github' }}
|
||||
TRANSLATE_MODEL: ${{ vars.TRANSLATE_MODEL || 'openai/gpt-5-mini' }}
|
||||
|
||||
- name: Label on translation failure
|
||||
if: failure() && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
github-token: ${{ secrets.DESIRECORE_BOT_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: context.issue.number,
|
||||
labels: ['i18n-translation-failed'],
|
||||
});
|
||||
42
.github/workflows/i18n-validate.yml
vendored
Normal file
42
.github/workflows/i18n-validate.yml
vendored
Normal file
@@ -0,0 +1,42 @@
|
||||
name: i18n Validate
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- "skills/**"
|
||||
- "agents/**"
|
||||
- "manifest.json"
|
||||
- "categories.json"
|
||||
- "scripts/i18n/**"
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- "skills/**"
|
||||
- "agents/**"
|
||||
- "manifest.json"
|
||||
- "categories.json"
|
||||
- "scripts/i18n/**"
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Install uv
|
||||
uses: astral-sh/setup-uv@v3
|
||||
|
||||
- name: Validate i18n
|
||||
run: uv run --quiet scripts/i18n/validate-i18n.py
|
||||
|
||||
- name: Check for stale translations
|
||||
run: uv run --quiet scripts/i18n/translate.py --check
|
||||
# --check exits 1 when any locale needs translation. We don't fail the
|
||||
# PR — translate.py (the i18n-translate workflow) will fix it. We just
|
||||
# surface the report.
|
||||
continue-on-error: true
|
||||
27
README.md
27
README.md
@@ -121,6 +121,33 @@ DesireCore 官方市场仓库,存放经过官方验证的 Agent 和 Skill 定
|
||||
- **Blue (#007AFF)**: 开发、沟通类
|
||||
- **Purple (#AF52DE)**: 创意、数据类
|
||||
|
||||
## 多语言(i18n)
|
||||
|
||||
仓库支持多语言展示与多语言 SKILL.md 正文。当前覆盖 `zh-CN`(简体中文,源语言)与 `en-US`(英文,默认 fallback),由 `manifest.json#supportedLocales` 声明。
|
||||
|
||||
- **作者只交一种语言**,CI 自动翻译为其余语言。CI 默认走 [GitHub Models](https://docs.github.com/en/github-models)(`openai/gpt-5-mini`,使用 repo 内置 `GITHUB_TOKEN` + `permissions: models: read`);可切到 Anthropic Claude(设置 `vars.TRANSLATE_BACKEND=anthropic` 与 `secrets.ANTHROPIC_API_KEY`)。
|
||||
- **顶层 `name` 字段为 ASCII slug**(== 目录名),中文显示名安放在 `metadata.i18n.zh-CN.name`,符合 [agentskills.io 规范](https://agentskills.io/specification)。
|
||||
- **正文文件**:`SKILL.md`(默认语言)+ `SKILL.<locale>.md`(其他语言)兄弟文件。
|
||||
|
||||
工具:
|
||||
|
||||
```bash
|
||||
# 校验 i18n 完整性
|
||||
uv run scripts/i18n/validate-i18n.py
|
||||
|
||||
# 检查哪些 locale 缺翻译(不调 API)
|
||||
uv run scripts/i18n/translate.py --check
|
||||
|
||||
# 本地翻译:默认 GitHub Models(需要 fine-grained PAT 含 Models: Read)
|
||||
GITHUB_TOKEN=ghp_... uv run scripts/i18n/translate.py
|
||||
|
||||
# 切到 Anthropic Claude
|
||||
TRANSLATE_BACKEND=anthropic ANTHROPIC_API_KEY=sk-ant-... \
|
||||
uv run scripts/i18n/translate.py
|
||||
```
|
||||
|
||||
详细规范见 [docs/I18N.md](docs/I18N.md)。
|
||||
|
||||
## 许可证
|
||||
|
||||
MIT License - 详见 [LICENSE](LICENSE)
|
||||
|
||||
@@ -5,26 +5,60 @@
|
||||
"t": "D",
|
||||
"bg": "linear-gradient(135deg, #007AFF, #005ECB)"
|
||||
},
|
||||
"shortDesc": "系统中枢调度器,负责任务分发、Agent 编排与全局状态监控",
|
||||
"fullDesc": "DesireCore 是系统核心智能体,作为用户与所有 Agent 之间的桥梁。负责任务分发、Agent 编排与全局状态监控。遵循「先澄清、再承诺、再执行、再复盘」的工作流,追求协调而非控制,确保每个 Agent 在最擅长的领域发挥作用。\n\n核心能力:\n- 智能任务分发与 Agent 能力匹配\n- 多 Agent 编排与协调\n- 全局状态监控与健康巡检\n- 自主学习与进化(经用户确认)\n\n内置技能:\n- 创建智能体、更新智能体、删除智能体、发现智能体\n- 自我进化(Self-Evolve)\n- 任务管理(Task Management)",
|
||||
"category": "management",
|
||||
"tags": ["系统", "调度", "编排", "官方", "核心"],
|
||||
"version": "1.0.0",
|
||||
"updatedAt": "2026-02-27",
|
||||
"version": "1.1.0",
|
||||
"updatedAt": "2026-05-03",
|
||||
"maintainer": {
|
||||
"name": "DesireCore Official",
|
||||
"verified": true
|
||||
},
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"source_locale": "zh-CN",
|
||||
"locales": ["zh-CN", "en-US"],
|
||||
"zh-CN": {
|
||||
"name": "DesireCore",
|
||||
"shortDesc": "系统中枢调度器,负责任务分发、Agent 编排与全局状态监控",
|
||||
"fullDesc": "DesireCore 是系统核心智能体,作为用户与所有 Agent 之间的桥梁。负责任务分发、Agent 编排与全局状态监控。遵循「先澄清、再承诺、再执行、再复盘」的工作流,追求协调而非控制,确保每个 Agent 在最擅长的领域发挥作用。\n\n核心能力:\n- 智能任务分发与 Agent 能力匹配\n- 多 Agent 编排与协调\n- 全局状态监控与健康巡检\n- 自主学习与进化(经用户确认)\n\n内置技能:\n- 创建智能体、更新智能体、删除智能体、发现智能体\n- 自我进化(Self-Evolve)\n- 任务管理(Task Management)",
|
||||
"tags": ["系统", "调度", "编排", "官方", "核心"],
|
||||
"persona": {
|
||||
"role": "系统中枢调度器",
|
||||
"traits": ["任务分发", "Agent 编排", "全局状态监控", "协调而非控制"]
|
||||
},
|
||||
"translated_by": "human"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "DesireCore",
|
||||
"shortDesc": "System central orchestrator: task dispatch, agent orchestration, and global state monitoring.",
|
||||
"fullDesc": "DesireCore is the system's core agent, acting as the bridge between the user and every other Agent. It is responsible for task dispatch, agent orchestration, and global state monitoring. It follows the workflow \"clarify → commit → execute → retrospect\", aiming for coordination rather than control so each Agent can shine in its area of expertise.\n\nCore capabilities:\n- Intelligent task dispatch and Agent capability matching\n- Multi-Agent orchestration and coordination\n- Global state monitoring and health checks\n- Autonomous learning and evolution (with user confirmation)\n\nBuilt-in skills:\n- Create / Update / Delete / Discover Agents\n- Self-Evolve\n- Task Management",
|
||||
"tags": ["system", "scheduling", "orchestration", "official", "core"],
|
||||
"persona": {
|
||||
"role": "System central orchestrator",
|
||||
"traits": ["task dispatch", "Agent orchestration", "global state monitoring", "coordination over control"]
|
||||
},
|
||||
"translated_by": "ai:claude-opus-4-7",
|
||||
"translated_at": "2026-05-03"
|
||||
}
|
||||
},
|
||||
"persona": {
|
||||
"role": "系统中枢调度器",
|
||||
"traits": ["任务分发", "Agent 编排", "全局状态监控", "协调而非控制"],
|
||||
"tools": []
|
||||
},
|
||||
"changelog": [
|
||||
{
|
||||
"version": "1.1.0",
|
||||
"date": "2026-05-03",
|
||||
"changes": {
|
||||
"zh-CN": ["i18n 改造:把 shortDesc/fullDesc/tags/persona 迁入 i18n.<locale>"],
|
||||
"en-US": ["i18n migration: shortDesc/fullDesc/tags/persona moved into i18n.<locale>"]
|
||||
}
|
||||
},
|
||||
{
|
||||
"version": "1.0.0",
|
||||
"date": "2026-02-27",
|
||||
"changes": ["首次发布:任务分发、Agent 编排与全局状态监控"]
|
||||
"changes": {
|
||||
"zh-CN": ["首次发布:任务分发、Agent 编排与全局状态监控"],
|
||||
"en-US": ["Initial release: task dispatch, agent orchestration, and global state monitoring"]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
104
categories.json
104
categories.json
@@ -1,50 +1,122 @@
|
||||
{
|
||||
"productivity": {
|
||||
"label": "效率",
|
||||
"color": "#34C759",
|
||||
"icon": "zap",
|
||||
"description": "提升个人与团队工作效率的工具类 Agent/Skill,包括任务管理、时间管理、笔记整理、知识管理等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Productivity",
|
||||
"description": "Tools that boost individual and team productivity, including task management, time management, note organization, and knowledge management."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "效率",
|
||||
"description": "提升个人与团队工作效率的工具类 Agent/Skill,包括任务管理、时间管理、笔记整理、知识管理等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"development": {
|
||||
"label": "开发",
|
||||
"color": "#007AFF",
|
||||
"icon": "code-2",
|
||||
"description": "软件开发辅助工具,包括代码审查、Bug 诊断、技术文档生成、开发环境管理等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Development",
|
||||
"description": "Software development helpers, including code review, bug diagnosis, technical documentation generation, and dev environment management."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "开发",
|
||||
"description": "软件开发辅助工具,包括代码审查、Bug 诊断、技术文档生成、开发环境管理等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"business": {
|
||||
"label": "商业",
|
||||
"color": "#34C759",
|
||||
"icon": "bar-chart-3",
|
||||
"description": "商务与项目管理工具,包括市场分析、财务建模、项目规划、客户关系管理等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Business",
|
||||
"description": "Business and project management tools, including market analysis, financial modeling, project planning, and customer relationship management."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "商业",
|
||||
"description": "商务与项目管理工具,包括市场分析、财务建模、项目规划、客户关系管理等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"creative": {
|
||||
"label": "创意",
|
||||
"color": "#AF52DE",
|
||||
"icon": "palette",
|
||||
"description": "设计与内容创作工具,包括文案策划、创意写作、视觉设计辅助、多媒体制作等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Creative",
|
||||
"description": "Design and content creation tools, including copywriting, creative writing, visual design assistance, and multimedia production."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "创意",
|
||||
"description": "设计与内容创作工具,包括文案策划、创意写作、视觉设计辅助、多媒体制作等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"media": {
|
||||
"label": "媒体",
|
||||
"color": "#AF52DE",
|
||||
"icon": "image",
|
||||
"description": "图片、语音、视频等多媒体生成与处理技能"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Media",
|
||||
"description": "Multimedia generation and processing skills for images, audio, and video."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "媒体",
|
||||
"description": "图片、语音、视频等多媒体生成与处理技能"
|
||||
}
|
||||
}
|
||||
},
|
||||
"communication": {
|
||||
"label": "沟通",
|
||||
"color": "#007AFF",
|
||||
"icon": "message-circle",
|
||||
"description": "沟通协作工具,包括翻译、邮件管理、会议辅助、客服应答、跨文化交流等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Communication",
|
||||
"description": "Communication and collaboration tools, including translation, email management, meeting assistance, customer support, and cross-cultural communication."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "沟通",
|
||||
"description": "沟通协作工具,包括翻译、邮件管理、会议辅助、客服应答、跨文化交流等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"label": "数据",
|
||||
"color": "#AF52DE",
|
||||
"icon": "database",
|
||||
"description": "数据分析与可视化工具,包括数据清洗、统计分析、商业智能、报表生成等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Data",
|
||||
"description": "Data analysis and visualization tools, including data cleaning, statistical analysis, business intelligence, and report generation."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "数据",
|
||||
"description": "数据分析与可视化工具,包括数据清洗、统计分析、商业智能、报表生成等"
|
||||
}
|
||||
}
|
||||
},
|
||||
"management": {
|
||||
"label": "管理",
|
||||
"color": "#007AFF",
|
||||
"icon": "layout-grid",
|
||||
"description": "系统管理与编排工具,包括任务调度、Agent 管理、全局监控、系统配置等"
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"en-US": {
|
||||
"label": "Management",
|
||||
"description": "System management and orchestration tools, including task scheduling, agent management, global monitoring, and system configuration."
|
||||
},
|
||||
"zh-CN": {
|
||||
"label": "管理",
|
||||
"description": "系统管理与编排工具,包括任务调度、Agent 管理、全局监控、系统配置等"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
175
docs/I18N.md
Normal file
175
docs/I18N.md
Normal file
@@ -0,0 +1,175 @@
|
||||
# Skills 多语言(i18n)作者指南
|
||||
|
||||
DesireCore 市场支持多语言展示与多语言 SKILL.md 正文。本指南面向 skill 作者与 maintainer,说明如何编写、提交、维护多语言 skill。
|
||||
|
||||
## 总则
|
||||
|
||||
- **作者只需要写一种语言**(推荐写中文 `zh-CN`)。CI 会自动调模型翻译为其余 `manifest.json#supportedLocales` 中声明的语言。**默认 backend 是 [GitHub Models](https://docs.github.com/en/github-models)**(`openai/gpt-5-mini`),使用 repo 内置 `GITHUB_TOKEN`,无需额外 secret;可选切到 Anthropic Claude(见下文 CI 流水线一节)。
|
||||
- **目录名 == `name` 字段**:spec 强制约束(agentskills.io)。目录名是 ASCII slug;显示名(中/英/其他)安放在 `metadata.i18n.<locale>.name`。
|
||||
- **默认语言**:`en-US`。Fallback 链:`requested locale → source_locale → default_locale`。市场仓库 schemaVersion 1.1+ 必填 `metadata.i18n` 块,无顶层 legacy 字段兜底。
|
||||
- **禁止占位**:不要直接编辑 `metadata.i18n.<locale>.source_hash` 与 `translated_at`,这些字段由 `translate.py` 维护。
|
||||
|
||||
---
|
||||
|
||||
## 文件结构
|
||||
|
||||
```
|
||||
skills/<your-skill>/
|
||||
├── SKILL.md # 顶层 frontmatter + 默认语言 (en-US) body
|
||||
├── SKILL.zh-CN.md # 中文 body(作者源语言)
|
||||
├── SKILL.<locale>.md # 其他语言 body(CI 生成)
|
||||
├── references/ # 可选:扩展文档
|
||||
└── scripts/ # 可选:可执行脚本
|
||||
```
|
||||
|
||||
只有 `SKILL.md` 有 frontmatter,其余 `SKILL.<locale>.md` 仅含 body,并在首行写 `<!-- locale: <locale> -->`。
|
||||
|
||||
---
|
||||
|
||||
## Frontmatter Schema
|
||||
|
||||
```yaml
|
||||
---
|
||||
name: your-skill # 必须 == 父目录名(ASCII slug)
|
||||
description: >- # 单字段,Claude 检索用;建议含中英触发词
|
||||
Use this skill when the user wants to ... 用户提到 ...、...、...
|
||||
license: MIT
|
||||
version: 1.0.0
|
||||
metadata:
|
||||
author: your-org
|
||||
updated_at: '2026-05-03'
|
||||
i18n:
|
||||
default_locale: en-US # fallback 终点
|
||||
source_locale: zh-CN # 你写的源语言
|
||||
locales: [zh-CN, en-US] # 已提供的 locale
|
||||
zh-CN:
|
||||
name: 你的技能名
|
||||
short_desc: 一句话描述
|
||||
description: 较长的中文描述(可选)
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:xxxxxxxx # CI 维护
|
||||
translated_by: human # human 或 ai:<model-id>
|
||||
en-US:
|
||||
name: Your Skill Name
|
||||
short_desc: One-line description
|
||||
description: Longer English description
|
||||
body: ./SKILL.md # 默认语言 = 根 SKILL.md
|
||||
source_hash: sha256:xxxxxxxx
|
||||
translated_by: ai:claude-sonnet-4-6
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: <svg>...</svg>
|
||||
category: productivity
|
||||
channel: latest
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
verified: true
|
||||
---
|
||||
```
|
||||
|
||||
完整 JSON Schema:[`scripts/i18n/schema/skill-frontmatter.schema.json`](../scripts/i18n/schema/skill-frontmatter.schema.json)
|
||||
|
||||
---
|
||||
|
||||
## 提交流程
|
||||
|
||||
### 新建 skill(首次贡献)
|
||||
|
||||
1. 在 `skills/<your-slug>/` 下新建目录与 `SKILL.md`。
|
||||
2. 编写中文 frontmatter + 中文 body:
|
||||
- `name: <your-slug>`(ASCII)
|
||||
- `metadata.i18n.{default_locale: en-US, source_locale: zh-CN, locales: [zh-CN]}`
|
||||
- `metadata.i18n.zh-CN.{name, short_desc, description}`
|
||||
- `metadata.i18n.zh-CN.body: ./SKILL.zh-CN.md`
|
||||
- 中文正文写在 `SKILL.zh-CN.md`,首行 `<!-- locale: zh-CN -->`
|
||||
- 根 `SKILL.md` body 留作翻译占位符(CI 会替换)
|
||||
3. 本地校验:`uv run scripts/i18n/validate-i18n.py skills/<your-slug>`
|
||||
4. 开 PR。CI 会自动追加一个 commit,把 en-US 翻译填入根 `SKILL.md` 与 `metadata.i18n.en-US`。
|
||||
5. **审 CI 翻译**:检查英文术语、Markdown 结构。若需修改,编辑后把 `metadata.i18n.en-US.translated_by` 改为 `human`,CI 不会再覆盖。
|
||||
|
||||
### CI 翻译流水线(GitHub Actions)
|
||||
|
||||
CI 用 [GitHub Models inference API](https://docs.github.com/en/github-models) 调模型。Workflow `.github/workflows/i18n-translate.yml`:
|
||||
|
||||
- **触发**:PR 改动 `skills/**/SKILL.zh-CN.md` 或 `manifest.json`/`categories.json`;或 `workflow_dispatch` 手动触发。
|
||||
- **认证**:用 repository 的 `GITHUB_TOKEN`(无需额外 secret),workflow 声明 `permissions: models: read`。
|
||||
- **默认模型**:`openai/gpt-5-mini`(catalog 中性价比款 GPT-5;想要旗舰精度切到 `openai/gpt-5`。GitHub Models 当前**未上架** Anthropic Claude,仅 OpenAI / DeepSeek / Meta / xAI / Microsoft 系列)。
|
||||
- **切换模型**:repository → Settings → Variables → `TRANSLATE_MODEL`,取值参考 [GitHub Models marketplace](https://github.com/marketplace?type=models) 的 `publisher/model-name` 格式。
|
||||
- **切到 Anthropic Claude**:在 repo 加 secret `ANTHROPIC_API_KEY`,再加 variable `TRANSLATE_BACKEND=anthropic`、`TRANSLATE_MODEL=claude-sonnet-4-6`。
|
||||
|
||||
提交回仓库的方式:`desirecore-bot` 在同 PR 追加 commit `chore(i18n): auto-translate skills [skip ci]`,并在 PR 留 review comment 提示人工核对。
|
||||
|
||||
### 修改已有 skill
|
||||
|
||||
1. 修改源语言 body(`SKILL.zh-CN.md`)或 `metadata.i18n.zh-CN.{name,short_desc,description}`。
|
||||
2. 不要手动改 `source_hash`。
|
||||
3. 开 PR。CI 检测 hash 变化,重新翻译目标 locale 并追加 commit。
|
||||
4. 若某个 locale 的 `translated_by: human`,CI 会跳过该 locale 并在 PR 留 review 提示「目标语已脱钩,请确认」,由你手工同步。
|
||||
|
||||
---
|
||||
|
||||
## 本地工具
|
||||
|
||||
```bash
|
||||
# 校验 i18n 状态
|
||||
uv run scripts/i18n/validate-i18n.py
|
||||
uv run scripts/i18n/validate-i18n.py skills/web-access
|
||||
|
||||
# 一次性把旧格式 SKILL.md 迁移到 i18n 格式(旧 skill 已迁完,新 skill 一般不需要)
|
||||
uv run scripts/i18n/migrate.py --apply skills/<your-slug>
|
||||
|
||||
# 仅检查哪些 locale 缺翻译(不调 API)
|
||||
uv run scripts/i18n/translate.py --check
|
||||
|
||||
# 本地翻译:默认走 GitHub Models(需 fine-grained PAT,启用 Models: Read 权限)
|
||||
GITHUB_TOKEN=ghp_... uv run scripts/i18n/translate.py skills/<your-slug>
|
||||
|
||||
# 切到 Anthropic Claude(需 sk-ant-...)
|
||||
TRANSLATE_BACKEND=anthropic ANTHROPIC_API_KEY=sk-ant-... \
|
||||
uv run scripts/i18n/translate.py skills/<your-slug>
|
||||
|
||||
# 选择特定模型(默认 GitHub: openai/gpt-5-mini;Anthropic: claude-sonnet-4-6)
|
||||
TRANSLATE_MODEL=openai/gpt-5 GITHUB_TOKEN=... \
|
||||
uv run scripts/i18n/translate.py skills/<your-slug>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 术语表
|
||||
|
||||
`scripts/i18n/glossary.json` 是翻译的事实来源。提交新 skill 时,如果引入了领域专有名词(例如 "审批流"、"工单"),请在 PR 中追加术语映射。
|
||||
|
||||
不要在术语表里加:
|
||||
- 已经在 `do_not_translate` 列表里的品牌/技术词
|
||||
- 译文与字面意义无差别的通用词
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
**Q:为什么顶层 `description` 还混着中英文?**
|
||||
因为 Claude 只用单字段 `description` 在 100+ skills 中匹配 user query。混合触发词是 Anthropic 官方在 [skill 最佳实践](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices) 里认可的写法。各 locale 的纯净版本走 `metadata.i18n.<locale>.description`,市场 UI 读这里。
|
||||
|
||||
**Q:CI 翻译质量不达预期怎么办?**
|
||||
1. 在 `glossary.json` 里加更具体的术语映射。
|
||||
2. 直接手工编辑目标 locale 的 body 与 frontmatter,并把 `translated_by` 改为 `human`,CI 不会再覆盖。
|
||||
3. 若是普遍问题,到 repo Settings → Variables 改 `TRANSLATE_MODEL`(默认 `openai/gpt-5-mini`,可选 `openai/gpt-5`、`openai/gpt-5-nano`、`openai/gpt-4.1`、`meta/llama-3.3-70b-instruct` 等),或切到 `TRANSLATE_BACKEND=anthropic` 用 Claude。
|
||||
|
||||
**Q:能否禁用某个 locale 的自动翻译?**
|
||||
可以。在 `manifest.json#supportedLocales` 中删除该 locale;或在 skill 级别保留 `metadata.i18n.locales` 不含它(CI 不会主动新增)。
|
||||
|
||||
**Q:references/ 里的文档需要翻译吗?**
|
||||
当前不强制。未来扩展时使用 `references/<file>.<locale>.md` 兄弟文件命名,与 SKILL body 一致。
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
- 规范:[agentskills.io/specification](https://agentskills.io/specification)
|
||||
- 最佳实践:[Anthropic Skill authoring best practices](https://platform.claude.com/docs/en/agents-and-tools/agent-skills/best-practices)
|
||||
- 术语表:`scripts/i18n/glossary.json`
|
||||
- JSON Schema:`scripts/i18n/schema/skill-frontmatter.schema.json`
|
||||
- 校验:`scripts/i18n/validate-i18n.py`
|
||||
- 翻译:`scripts/i18n/translate.py`
|
||||
- 迁移:`scripts/i18n/migrate.py`
|
||||
- CI workflows:`.github/workflows/i18n-{validate,translate}.yml`
|
||||
@@ -1,8 +1,20 @@
|
||||
{
|
||||
"name": "DesireCore Official Market",
|
||||
"version": "1.0.1",
|
||||
"description": "DesireCore 官方市场,提供精选高质量的 Agent 和 Skill",
|
||||
"schemaVersion": "1.0.0",
|
||||
"version": "1.1.0",
|
||||
"schemaVersion": "1.1.0",
|
||||
"supportedLocales": ["zh-CN", "en-US"],
|
||||
"defaultLocale": "en-US",
|
||||
"i18n": {
|
||||
"default_locale": "en-US",
|
||||
"zh-CN": {
|
||||
"name": "DesireCore 官方市场",
|
||||
"description": "DesireCore 官方市场,提供精选高质量的 Agent 和 Skill"
|
||||
},
|
||||
"en-US": {
|
||||
"name": "DesireCore Official Market",
|
||||
"description": "Curated, high-quality Agents and Skills published by the DesireCore team."
|
||||
}
|
||||
},
|
||||
"maintainer": {
|
||||
"name": "DesireCore Team",
|
||||
"email": "market@desirecore.net",
|
||||
@@ -21,6 +33,7 @@
|
||||
"features": [
|
||||
"verified-only",
|
||||
"auto-sync",
|
||||
"multi-language"
|
||||
"multi-language",
|
||||
"ai-translation"
|
||||
]
|
||||
}
|
||||
|
||||
227
scripts/i18n/glossary.json
Normal file
227
scripts/i18n/glossary.json
Normal file
@@ -0,0 +1,227 @@
|
||||
{
|
||||
"$schema": "./schema/glossary.schema.json",
|
||||
"_comment": "DesireCore Market i18n glossary. Used by translate.py to keep terminology consistent across skills. Add domain-specific entries as new skills are added.",
|
||||
"version": "1.0.0",
|
||||
"default_source_locale": "zh-CN",
|
||||
"default_target_locale": "en-US",
|
||||
"terms": {
|
||||
"zh-CN_to_en-US": {
|
||||
"智能体": "Agent",
|
||||
"技能": "Skill",
|
||||
"工具": "Tool",
|
||||
"市场": "Market",
|
||||
"工作流": "workflow",
|
||||
"黄金样本": "gold sample",
|
||||
"触发词": "trigger keyword",
|
||||
"落地页": "landing page",
|
||||
"仪表盘": "Dashboard",
|
||||
"海报": "poster",
|
||||
"登录态": "logged-in session",
|
||||
"联网访问": "Web Access",
|
||||
"网页抓取": "page fetching",
|
||||
"网络搜索": "web search",
|
||||
"联网搜索": "web search",
|
||||
"调研": "research",
|
||||
"公文": "official document",
|
||||
"备忘录": "memo",
|
||||
"合同": "contract",
|
||||
"信函": "letter",
|
||||
"信函模板": "letter template",
|
||||
"报告": "report",
|
||||
"发票": "invoice",
|
||||
"目录": "table of contents",
|
||||
"页眉页脚": "header and footer",
|
||||
"页码": "page number",
|
||||
"脚注": "footnote",
|
||||
"尾注": "endnote",
|
||||
"修订": "tracked changes",
|
||||
"批注": "comment",
|
||||
"签名": "signature",
|
||||
"表单": "form",
|
||||
"字段": "field",
|
||||
"电子表格": "spreadsheet",
|
||||
"工作表": "worksheet",
|
||||
"数据透视表": "pivot table",
|
||||
"图表": "chart",
|
||||
"幻灯片": "slide",
|
||||
"演示文稿": "presentation",
|
||||
"幻灯片母版": "slide master",
|
||||
"环境配置": "environment setup",
|
||||
"运行环境": "runtime",
|
||||
"容器": "container",
|
||||
"沙箱": "sandbox",
|
||||
"镜像": "image",
|
||||
"权限": "permission",
|
||||
"白名单": "allowlist",
|
||||
"黑名单": "blocklist",
|
||||
"凭据": "credential",
|
||||
"密钥": "secret",
|
||||
"存储桶": "bucket",
|
||||
"对象存储": "object storage",
|
||||
"上传": "upload",
|
||||
"下载": "download",
|
||||
"拷贝": "copy",
|
||||
"迁移": "migration",
|
||||
"校验": "validation",
|
||||
"回退": "fallback",
|
||||
"回滚": "rollback",
|
||||
"审批": "approval",
|
||||
"审计": "audit",
|
||||
"灰度": "canary release",
|
||||
"发布": "release",
|
||||
"通道": "channel",
|
||||
"稳定通道": "stable channel",
|
||||
"金丝雀通道": "canary channel",
|
||||
"维护者": "maintainer",
|
||||
"贡献者": "contributor",
|
||||
"作者": "author",
|
||||
"风险等级": "risk level",
|
||||
"图片生成": "image generation",
|
||||
"语音合成": "text-to-speech",
|
||||
"视频生成": "video generation",
|
||||
"邮箱操作": "Email Operations",
|
||||
"邮件": "email",
|
||||
"收件箱": "inbox",
|
||||
"草稿": "draft",
|
||||
"标签": "label",
|
||||
"分类": "category",
|
||||
"附件": "attachment",
|
||||
"自动回复": "auto-reply",
|
||||
"群发": "bulk send",
|
||||
"智能回复": "smart reply",
|
||||
"团队管理": "team management",
|
||||
"技能管理": "skills management",
|
||||
"调度": "orchestration",
|
||||
"中枢": "central",
|
||||
"中枢调度器": "central orchestrator",
|
||||
"数字员工": "digital worker",
|
||||
"人格": "persona",
|
||||
"原则": "principle",
|
||||
"持久化": "persistence",
|
||||
"系统中枢": "system core",
|
||||
"节流": "throttling",
|
||||
"限流": "rate limiting",
|
||||
"重试": "retry",
|
||||
"幂等": "idempotency",
|
||||
"命令行": "CLI",
|
||||
"脚本": "script",
|
||||
"二进制": "binary",
|
||||
"依赖": "dependency",
|
||||
"包管理器": "package manager",
|
||||
"镜像源": "registry mirror",
|
||||
"节省 Token": "save tokens",
|
||||
"节省成本": "save cost",
|
||||
"安装": "install",
|
||||
"卸载": "uninstall",
|
||||
"升级": "upgrade",
|
||||
"降级": "downgrade",
|
||||
"热更新": "hot-reload",
|
||||
"冷启动": "cold start",
|
||||
"调试": "debug",
|
||||
"远程调试": "remote debugging",
|
||||
"断点": "breakpoint",
|
||||
"排查": "troubleshoot",
|
||||
"技能创建器": "skill creator",
|
||||
"技能创作": "skill authoring",
|
||||
"技能模板": "skill template",
|
||||
"前端设计": "Frontend Design",
|
||||
"网页设计": "web design",
|
||||
"UI 设计": "UI design",
|
||||
"界面设计": "interface design",
|
||||
"组件": "component",
|
||||
"美化": "polish",
|
||||
"样式": "style",
|
||||
"主题": "theme",
|
||||
"配色": "color scheme",
|
||||
"字体": "font",
|
||||
"字号": "font size",
|
||||
"栅格": "grid",
|
||||
"暗色模式": "dark mode",
|
||||
"亮色模式": "light mode",
|
||||
"无障碍": "accessibility",
|
||||
"响应式": "responsive",
|
||||
"动效": "motion / animation",
|
||||
"交互": "interaction",
|
||||
"用户体验": "UX",
|
||||
"用户界面": "UI",
|
||||
"渲染": "render",
|
||||
"构建": "build",
|
||||
"打包": "bundle",
|
||||
"热重载": "hot reload"
|
||||
}
|
||||
},
|
||||
"do_not_translate": [
|
||||
"anthropic",
|
||||
"claude",
|
||||
"DesireCore",
|
||||
"AgentFS",
|
||||
"MCP",
|
||||
"Claude Code",
|
||||
"Anthropic",
|
||||
"Markdown",
|
||||
"YAML",
|
||||
"JSON",
|
||||
"SVG",
|
||||
"PDF",
|
||||
"DOCX",
|
||||
"PPTX",
|
||||
"XLSX",
|
||||
"S3",
|
||||
"MinIO",
|
||||
"MiniMax",
|
||||
"OpenAI",
|
||||
"Kling",
|
||||
"Jina",
|
||||
"Reader",
|
||||
"Playwright",
|
||||
"CDP",
|
||||
"Chrome",
|
||||
"GitHub",
|
||||
"Gmail",
|
||||
"Outlook",
|
||||
"IMAP",
|
||||
"SMTP",
|
||||
"WSL",
|
||||
"WSL2",
|
||||
"Docker",
|
||||
"Podman",
|
||||
"Kubernetes",
|
||||
"Node.js",
|
||||
"Python",
|
||||
"TypeScript",
|
||||
"JavaScript",
|
||||
"Bash",
|
||||
"BeautifulSoup",
|
||||
"LibreOffice",
|
||||
"Poppler",
|
||||
"Pandoc",
|
||||
"Tesseract",
|
||||
"Unicode",
|
||||
"UTF-8",
|
||||
"REST",
|
||||
"API",
|
||||
"URL",
|
||||
"HTTP",
|
||||
"HTTPS",
|
||||
"OAuth",
|
||||
"JWT",
|
||||
"Lucide",
|
||||
"React",
|
||||
"Vue",
|
||||
"Next.js",
|
||||
"Tailwind",
|
||||
"CSS",
|
||||
"HTML",
|
||||
"SKILL.md",
|
||||
"frontmatter",
|
||||
"metadata"
|
||||
],
|
||||
"preserve_patterns": [
|
||||
"^```[\\s\\S]*?```$",
|
||||
"`[^`\\n]+`",
|
||||
"https?://[^\\s)]+",
|
||||
"<[a-zA-Z][\\s\\S]*?>",
|
||||
"\\$[A-Z_][A-Z0-9_]*",
|
||||
"\\b[a-z][a-zA-Z0-9_]*\\.[a-z][a-zA-Z0-9_]*\\b"
|
||||
]
|
||||
}
|
||||
235
scripts/i18n/migrate.py
Executable file
235
scripts/i18n/migrate.py
Executable file
@@ -0,0 +1,235 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = ["ruamel.yaml>=0.18"]
|
||||
# ///
|
||||
"""One-shot migration: convert legacy SKILL.md frontmatter to i18n format.
|
||||
|
||||
For each skill directory:
|
||||
1. Read SKILL.md frontmatter (legacy format with Chinese top-level name).
|
||||
2. Move legacy `name` -> metadata.i18n.<source>.name (default source: zh-CN).
|
||||
3. Move legacy `market.short_desc` -> metadata.i18n.<source>.short_desc.
|
||||
4. Set top-level `name` to the directory name (ASCII slug).
|
||||
5. Add metadata.i18n.{default_locale=en-US, source_locale=<src>, locales=[src]}.
|
||||
6. Move existing body to SKILL.<source>.md (with `<!-- locale: <src> -->` header).
|
||||
7. Replace root SKILL.md body with a translation-pending placeholder.
|
||||
8. Compute source_hash for the source locale.
|
||||
|
||||
DOES NOT TRANSLATE — translate.py (the CI script) fills in the en-US body & i18n block
|
||||
afterwards. After migration, the skill is structurally valid but only has source_locale
|
||||
content; en-US locale is added by translate.py on the next CI run.
|
||||
|
||||
Usage:
|
||||
scripts/i18n/migrate.py --dry-run # preview, default
|
||||
scripts/i18n/migrate.py --apply # write changes
|
||||
scripts/i18n/migrate.py --apply skills/web-access # one skill
|
||||
scripts/i18n/migrate.py --apply --source zh-CN # set source locale (default zh-CN)
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from datetime import date
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
from ruamel.yaml import YAML
|
||||
from ruamel.yaml.scalarstring import LiteralScalarString, FoldedScalarString
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
DEFAULT_LOCALE = "en-US"
|
||||
PLACEHOLDER_BODY = (
|
||||
"<!-- TRANSLATION PENDING: this body will be auto-translated from "
|
||||
"metadata.i18n.<source_locale>.body by scripts/i18n/translate.py on the next CI run. -->\n"
|
||||
"\n"
|
||||
"# {dir_name}\n"
|
||||
"\n"
|
||||
"_Translation pending. See `{source_body}` for the source-language version._\n"
|
||||
)
|
||||
|
||||
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n(.*)$", re.DOTALL)
|
||||
|
||||
|
||||
def make_yaml() -> YAML:
|
||||
y = YAML()
|
||||
y.indent(mapping=2, sequence=4, offset=2)
|
||||
y.width = 4096
|
||||
y.preserve_quotes = True
|
||||
return y
|
||||
|
||||
|
||||
def load_frontmatter(text: str) -> tuple[Any, str]:
|
||||
m = FRONTMATTER_RE.match(text)
|
||||
if not m:
|
||||
raise ValueError("File is missing YAML frontmatter")
|
||||
yaml_text, body = m.group(1), m.group(2)
|
||||
yaml = make_yaml()
|
||||
fm = yaml.load(yaml_text)
|
||||
return fm, body
|
||||
|
||||
|
||||
def dump_frontmatter(fm: Any, body: str) -> str:
|
||||
yaml = make_yaml()
|
||||
buf = StringIO()
|
||||
yaml.dump(fm, buf)
|
||||
return f"---\n{buf.getvalue()}---\n\n{body.lstrip()}"
|
||||
|
||||
|
||||
def source_hash(body: str, i18n_strings: dict[str, str]) -> str:
|
||||
h = hashlib.sha256()
|
||||
h.update(body.encode("utf-8"))
|
||||
h.update(b"\x00")
|
||||
h.update(json.dumps(i18n_strings, sort_keys=True, ensure_ascii=False).encode("utf-8"))
|
||||
return f"sha256:{h.hexdigest()[:16]}"
|
||||
|
||||
|
||||
def migrate_skill(skill_dir: Path, source_locale: str, default_locale: str, apply: bool) -> dict[str, Any]:
|
||||
"""Return a dict describing the planned changes for this skill."""
|
||||
rel = skill_dir.relative_to(REPO_ROOT).as_posix()
|
||||
skill_md = skill_dir / "SKILL.md"
|
||||
plan: dict[str, Any] = {"skill": rel, "actions": [], "errors": []}
|
||||
|
||||
if not skill_md.is_file():
|
||||
plan["errors"].append("SKILL.md not found")
|
||||
return plan
|
||||
|
||||
text = skill_md.read_text(encoding="utf-8")
|
||||
try:
|
||||
fm, body = load_frontmatter(text)
|
||||
except ValueError as e:
|
||||
plan["errors"].append(str(e))
|
||||
return plan
|
||||
|
||||
# Already migrated?
|
||||
metadata = fm.get("metadata") or {}
|
||||
if isinstance(metadata, dict) and "i18n" in metadata and isinstance(metadata.get("i18n"), dict):
|
||||
plan["actions"].append("already migrated, skipping")
|
||||
return plan
|
||||
|
||||
legacy_name = fm.get("name", "").strip()
|
||||
legacy_short_desc = ""
|
||||
market = fm.get("market")
|
||||
if isinstance(market, dict):
|
||||
legacy_short_desc = (market.get("short_desc") or "").strip()
|
||||
# Remove short_desc from market — it has migrated.
|
||||
if "short_desc" in market:
|
||||
market.pop("short_desc", None)
|
||||
|
||||
legacy_description = fm.get("description", "")
|
||||
|
||||
# New top-level name = directory name
|
||||
new_name = skill_dir.name
|
||||
fm["name"] = new_name
|
||||
|
||||
# Build metadata.i18n
|
||||
if not isinstance(metadata, dict):
|
||||
metadata = {}
|
||||
fm["metadata"] = metadata
|
||||
|
||||
i18n_block: dict[str, Any] = {
|
||||
"default_locale": default_locale,
|
||||
"source_locale": source_locale,
|
||||
"locales": [source_locale],
|
||||
}
|
||||
|
||||
# Source body file
|
||||
source_body_filename = f"SKILL.{source_locale}.md"
|
||||
source_body_path = skill_dir / source_body_filename
|
||||
source_body_text = f"<!-- locale: {source_locale} -->\n\n{body.lstrip()}"
|
||||
|
||||
# Source locale strings
|
||||
src_strings = {
|
||||
"name": legacy_name or new_name,
|
||||
"short_desc": legacy_short_desc or legacy_name or new_name,
|
||||
}
|
||||
if legacy_description:
|
||||
src_strings["description"] = (
|
||||
legacy_description if isinstance(legacy_description, str) else str(legacy_description)
|
||||
)
|
||||
|
||||
src_hash = source_hash(body, src_strings)
|
||||
|
||||
src_block: dict[str, Any] = {
|
||||
"name": src_strings["name"],
|
||||
"short_desc": src_strings["short_desc"],
|
||||
}
|
||||
if "description" in src_strings:
|
||||
# Use folded style for long descriptions to keep frontmatter readable
|
||||
desc = src_strings["description"]
|
||||
src_block["description"] = FoldedScalarString(desc) if "\n" in desc or len(desc) > 80 else desc
|
||||
src_block["body"] = f"./{source_body_filename}"
|
||||
src_block["source_hash"] = src_hash
|
||||
src_block["translated_by"] = "human"
|
||||
|
||||
i18n_block[source_locale] = src_block
|
||||
metadata["i18n"] = i18n_block
|
||||
|
||||
# Plan actions
|
||||
plan["actions"].append(f"rename top-level name '{legacy_name}' -> '{new_name}'")
|
||||
plan["actions"].append(f"add metadata.i18n.{source_locale} (name, short_desc, description, body, source_hash)")
|
||||
plan["actions"].append(f"create {source_body_filename} ({len(body)} chars)")
|
||||
placeholder = PLACEHOLDER_BODY.format(dir_name=new_name, source_body=source_body_filename)
|
||||
plan["actions"].append(f"replace root SKILL.md body with translation-pending placeholder ({len(placeholder)} chars)")
|
||||
if legacy_short_desc:
|
||||
plan["actions"].append("remove market.short_desc (migrated to i18n)")
|
||||
|
||||
if apply:
|
||||
# Write source body file
|
||||
source_body_path.write_text(source_body_text, encoding="utf-8")
|
||||
# Write new root SKILL.md (frontmatter + placeholder body)
|
||||
new_root = dump_frontmatter(fm, placeholder)
|
||||
skill_md.write_text(new_root, encoding="utf-8")
|
||||
plan["written"] = [
|
||||
source_body_path.relative_to(REPO_ROOT).as_posix(),
|
||||
skill_md.relative_to(REPO_ROOT).as_posix(),
|
||||
]
|
||||
|
||||
return plan
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("paths", nargs="*", help="Skill directories to migrate (default: all under skills/)")
|
||||
parser.add_argument("--apply", action="store_true", help="Write changes (default: dry-run)")
|
||||
parser.add_argument("--dry-run", action="store_true", help="Preview only (default)")
|
||||
parser.add_argument("--source", default="zh-CN", help="Source locale (default: zh-CN)")
|
||||
parser.add_argument("--default", dest="default_locale", default=DEFAULT_LOCALE,
|
||||
help=f"Default locale (default: {DEFAULT_LOCALE})")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
apply = args.apply and not args.dry_run
|
||||
|
||||
if args.paths:
|
||||
targets = [Path(p).resolve() for p in args.paths]
|
||||
else:
|
||||
targets = sorted((REPO_ROOT / "skills").iterdir())
|
||||
targets = [t for t in targets if t.is_dir() and (t / "SKILL.md").is_file()]
|
||||
|
||||
plans: list[dict[str, Any]] = []
|
||||
for skill_dir in targets:
|
||||
if not skill_dir.is_dir() or not (skill_dir / "SKILL.md").is_file():
|
||||
continue
|
||||
plans.append(migrate_skill(skill_dir, args.source, args.default_locale, apply))
|
||||
|
||||
print(f"\n{'APPLIED' if apply else 'DRY-RUN'} migration plan ({len(plans)} skills):\n")
|
||||
for p in plans:
|
||||
if p.get("errors"):
|
||||
print(f" ✗ {p['skill']}: ERRORS: {p['errors']}")
|
||||
else:
|
||||
print(f" • {p['skill']}: {len(p['actions'])} action(s)")
|
||||
for a in p["actions"]:
|
||||
print(f" - {a}")
|
||||
print()
|
||||
if not apply:
|
||||
print("Re-run with --apply to write changes.")
|
||||
else:
|
||||
print("Migration complete. Run scripts/i18n/validate-i18n.py to verify.")
|
||||
return 1 if any(p.get("errors") for p in plans) else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
156
scripts/i18n/schema/skill-frontmatter.schema.json
Normal file
156
scripts/i18n/schema/skill-frontmatter.schema.json
Normal file
@@ -0,0 +1,156 @@
|
||||
{
|
||||
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
||||
"$id": "https://desirecore.net/market/schema/skill-frontmatter.schema.json",
|
||||
"title": "DesireCore Market Skill Frontmatter (i18n)",
|
||||
"description": "JSON Schema for the YAML frontmatter of a SKILL.md in the DesireCore market. Compatible with the agentskills.io specification: https://agentskills.io/specification",
|
||||
"type": "object",
|
||||
"required": ["name", "description", "version", "metadata"],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"name": {
|
||||
"description": "Spec-required. Must equal the parent directory name. Lowercase ASCII letters, digits, hyphens. 1-64 chars. Must not start/end with hyphen, must not contain consecutive hyphens, must not be 'anthropic' or 'claude'.",
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 64,
|
||||
"pattern": "^(?!-)(?!.*--)(?!anthropic$)(?!claude$)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$"
|
||||
},
|
||||
"description": {
|
||||
"description": "Spec-required. 1-1024 chars. Single field used by Claude for skill discovery. Multilingual trigger keywords are accepted (Anthropic-recommended pattern for multilingual users).",
|
||||
"type": "string",
|
||||
"minLength": 1,
|
||||
"maxLength": 1024
|
||||
},
|
||||
"license": {
|
||||
"type": "string"
|
||||
},
|
||||
"compatibility": {
|
||||
"type": "string",
|
||||
"maxLength": 500
|
||||
},
|
||||
"version": {
|
||||
"description": "SemVer string. Required by DesireCore market.",
|
||||
"type": "string",
|
||||
"pattern": "^\\d+\\.\\d+\\.\\d+(?:-[0-9A-Za-z.-]+)?(?:\\+[0-9A-Za-z.-]+)?$"
|
||||
},
|
||||
"type": {
|
||||
"description": "DesireCore extension. Skill behavior class.",
|
||||
"type": "string",
|
||||
"enum": ["procedural", "meta", "knowledge", "tool"]
|
||||
},
|
||||
"risk_level": {
|
||||
"description": "DesireCore extension.",
|
||||
"type": "string",
|
||||
"enum": ["low", "medium", "high", "critical"]
|
||||
},
|
||||
"status": {
|
||||
"description": "DesireCore extension. Whether the skill is enabled by default.",
|
||||
"type": "string",
|
||||
"enum": ["enabled", "disabled", "deprecated", "experimental"]
|
||||
},
|
||||
"disable-model-invocation": {
|
||||
"type": "boolean"
|
||||
},
|
||||
"tags": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"pattern": "^[a-z0-9][a-z0-9-]*$"
|
||||
},
|
||||
"uniqueItems": true
|
||||
},
|
||||
"allowed-tools": {
|
||||
"type": "string"
|
||||
},
|
||||
"metadata": {
|
||||
"type": "object",
|
||||
"required": ["author", "i18n"],
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"author": { "type": "string" },
|
||||
"updated_at": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}$"
|
||||
},
|
||||
"i18n": { "$ref": "#/$defs/i18nBlock" }
|
||||
}
|
||||
},
|
||||
"market": {
|
||||
"type": "object",
|
||||
"additionalProperties": true,
|
||||
"properties": {
|
||||
"icon": { "type": "string" },
|
||||
"category": { "type": "string" },
|
||||
"channel": {
|
||||
"type": "string",
|
||||
"enum": ["latest", "stable", "canary", "beta"]
|
||||
},
|
||||
"maintainer": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"name": { "type": "string" },
|
||||
"verified": { "type": "boolean" }
|
||||
},
|
||||
"required": ["name"]
|
||||
},
|
||||
"compatible_agents": {
|
||||
"type": "array",
|
||||
"items": { "type": "string" }
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"$defs": {
|
||||
"bcp47Locale": {
|
||||
"description": "BCP-47 locale tag: ll-RR (lowercase language, uppercase region).",
|
||||
"type": "string",
|
||||
"pattern": "^[a-z]{2,3}(?:-[A-Z]{2})?$"
|
||||
},
|
||||
"i18nBlock": {
|
||||
"type": "object",
|
||||
"required": ["default_locale", "source_locale", "locales"],
|
||||
"properties": {
|
||||
"default_locale": { "$ref": "#/$defs/bcp47Locale" },
|
||||
"source_locale": { "$ref": "#/$defs/bcp47Locale" },
|
||||
"locales": {
|
||||
"type": "array",
|
||||
"minItems": 1,
|
||||
"uniqueItems": true,
|
||||
"items": { "$ref": "#/$defs/bcp47Locale" }
|
||||
}
|
||||
},
|
||||
"additionalProperties": {
|
||||
"$ref": "#/$defs/localePayload"
|
||||
}
|
||||
},
|
||||
"localePayload": {
|
||||
"description": "Per-locale display strings and body pointer. Keyed by BCP-47 locale tag.",
|
||||
"type": "object",
|
||||
"required": ["name", "short_desc"],
|
||||
"properties": {
|
||||
"name": { "type": "string", "minLength": 1, "maxLength": 200 },
|
||||
"short_desc": { "type": "string", "minLength": 1, "maxLength": 300 },
|
||||
"description": { "type": "string", "minLength": 1, "maxLength": 2000 },
|
||||
"body": {
|
||||
"description": "Relative path to the body Markdown for this locale, e.g. ./SKILL.zh-CN.md or ./SKILL.md.",
|
||||
"type": "string",
|
||||
"pattern": "^\\./[A-Za-z0-9._/-]+\\.md$"
|
||||
},
|
||||
"source_hash": {
|
||||
"description": "sha256:<8-hex> of source body+i18n strings at translation time. Written by translate.py.",
|
||||
"type": "string",
|
||||
"pattern": "^sha256:[0-9a-f]{8,64}$"
|
||||
},
|
||||
"translated_by": {
|
||||
"description": "'human' for human-authored content; 'ai:<backend>:<model-id>' or 'ai:<model-id>' for machine-translated content. Examples: 'ai:github:openai/gpt-5-mini', 'ai:anthropic:claude-sonnet-4-6', 'ai:claude-opus-4-7'.",
|
||||
"type": "string",
|
||||
"pattern": "^(human|ai:[A-Za-z0-9._:/-]+)$"
|
||||
},
|
||||
"translated_at": {
|
||||
"type": "string",
|
||||
"pattern": "^\\d{4}-\\d{2}-\\d{2}(?:T\\d{2}:\\d{2}:\\d{2}Z?)?$"
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
}
|
||||
}
|
||||
}
|
||||
530
scripts/i18n/translate.py
Executable file
530
scripts/i18n/translate.py
Executable file
@@ -0,0 +1,530 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = ["ruamel.yaml>=0.18", "httpx>=0.27"]
|
||||
# ///
|
||||
"""AI translation pipeline for DesireCore market skills.
|
||||
|
||||
For each skill directory, ensure metadata.i18n contains every locale declared in
|
||||
manifest.json/supportedLocales. When a target locale is missing or stale (its
|
||||
source_hash differs from the current source body+strings hash), translate from
|
||||
metadata.i18n.<source_locale>.body using an LLM.
|
||||
|
||||
Backends (auto-selected, in this priority):
|
||||
1. GitHub Models (default) — uses GITHUB_TOKEN with `models: read` permission,
|
||||
OpenAI-compatible chat-completions API at https://models.github.ai/inference.
|
||||
Model defaults to `openai/gpt-5-mini` (configure with TRANSLATE_MODEL).
|
||||
2. Anthropic API direct — used when ANTHROPIC_API_KEY is set AND
|
||||
TRANSLATE_BACKEND=anthropic. Endpoint https://api.anthropic.com/v1/messages.
|
||||
Model should be a Claude model id (e.g. claude-sonnet-4-6).
|
||||
|
||||
Translations preserve:
|
||||
- Markdown structure (heading hierarchy, list ordering, tables, fences)
|
||||
- Inline code, fenced code blocks, URLs, file paths
|
||||
- SVG, HTML tags, YAML keys
|
||||
- Glossary terms from scripts/i18n/glossary.json
|
||||
- Reserved words from glossary.do_not_translate
|
||||
|
||||
Output:
|
||||
- Updates metadata.i18n.<target_locale>.{name,short_desc,description,source_hash,
|
||||
translated_by,translated_at}
|
||||
- For target_locale == default_locale: writes the translated body to root SKILL.md
|
||||
- Otherwise: writes SKILL.<target_locale>.md
|
||||
|
||||
Usage:
|
||||
GITHUB_TOKEN=... scripts/i18n/translate.py # all stale locales
|
||||
scripts/i18n/translate.py skills/web-access # one skill
|
||||
scripts/i18n/translate.py --target en-US skills/web-access # one locale
|
||||
scripts/i18n/translate.py --check # dry-run, exit 1 if stale
|
||||
scripts/i18n/translate.py --human # mark new translations as human (lock)
|
||||
|
||||
Env:
|
||||
GITHUB_TOKEN required when backend=github (CI: provided automatically)
|
||||
ANTHROPIC_API_KEY required when TRANSLATE_BACKEND=anthropic
|
||||
TRANSLATE_BACKEND 'github' (default) | 'anthropic'
|
||||
TRANSLATE_MODEL backend-specific model id; default depends on backend
|
||||
TRANSLATE_ENDPOINT override endpoint URL
|
||||
TRANSLATE_MAX_RETRIES default 3
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import hashlib
|
||||
import json
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
from datetime import datetime, timezone
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import Any
|
||||
|
||||
import httpx
|
||||
from ruamel.yaml import YAML
|
||||
from ruamel.yaml.scalarstring import FoldedScalarString
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
GLOSSARY_PATH = REPO_ROOT / "scripts" / "i18n" / "glossary.json"
|
||||
|
||||
DEFAULT_BACKEND = os.environ.get("TRANSLATE_BACKEND", "github").lower()
|
||||
DEFAULT_MODEL_BY_BACKEND = {
|
||||
"github": os.environ.get("TRANSLATE_MODEL", "openai/gpt-5-mini"),
|
||||
"anthropic": os.environ.get("TRANSLATE_MODEL", "claude-sonnet-4-6"),
|
||||
}
|
||||
DEFAULT_ENDPOINT_BY_BACKEND = {
|
||||
"github": "https://models.github.ai/inference",
|
||||
"anthropic": "https://api.anthropic.com",
|
||||
}
|
||||
MAX_RETRIES = int(os.environ.get("TRANSLATE_MAX_RETRIES", "3"))
|
||||
HTTP_TIMEOUT = httpx.Timeout(connect=10, read=180, write=30, pool=10)
|
||||
|
||||
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n(.*)$", re.DOTALL)
|
||||
HEADING_RE = re.compile(r"^(#{1,6})\s+\S", re.MULTILINE)
|
||||
LOCALE_HEADER_RE = re.compile(r"^<!--\s*locale:\s*[a-zA-Z-]+\s*-->\s*\n+", re.MULTILINE)
|
||||
|
||||
|
||||
def make_yaml() -> YAML:
|
||||
y = YAML()
|
||||
y.indent(mapping=2, sequence=4, offset=2)
|
||||
y.width = 4096
|
||||
y.preserve_quotes = True
|
||||
return y
|
||||
|
||||
|
||||
def load_skill(skill_md: Path) -> tuple[Any, str]:
|
||||
text = skill_md.read_text(encoding="utf-8")
|
||||
m = FRONTMATTER_RE.match(text)
|
||||
if not m:
|
||||
raise ValueError(f"{skill_md}: no frontmatter")
|
||||
fm = make_yaml().load(m.group(1))
|
||||
return fm, m.group(2)
|
||||
|
||||
|
||||
def dump_skill(fm: Any, body: str) -> str:
|
||||
yaml = make_yaml()
|
||||
buf = StringIO()
|
||||
yaml.dump(fm, buf)
|
||||
return f"---\n{buf.getvalue()}---\n\n{body.lstrip()}"
|
||||
|
||||
|
||||
def strip_locale_header(text: str) -> str:
|
||||
return LOCALE_HEADER_RE.sub("", text, count=1)
|
||||
|
||||
|
||||
def compute_source_hash(body: str, strings: dict[str, str]) -> str:
|
||||
h = hashlib.sha256()
|
||||
h.update(body.encode("utf-8"))
|
||||
h.update(b"\x00")
|
||||
h.update(json.dumps(strings, sort_keys=True, ensure_ascii=False).encode("utf-8"))
|
||||
return f"sha256:{h.hexdigest()[:16]}"
|
||||
|
||||
|
||||
def heading_count(text: str) -> int:
|
||||
return len(HEADING_RE.findall(text))
|
||||
|
||||
|
||||
def load_glossary() -> dict[str, Any]:
|
||||
if not GLOSSARY_PATH.is_file():
|
||||
return {"terms": {}, "do_not_translate": []}
|
||||
return json.loads(GLOSSARY_PATH.read_text(encoding="utf-8"))
|
||||
|
||||
|
||||
# ----------------------------- prompt construction -----------------------------
|
||||
|
||||
def build_system_prompt(source_locale: str, target_locale: str, glossary: dict[str, Any]) -> str:
|
||||
terms_key = f"{source_locale}_to_{target_locale}"
|
||||
terms = glossary.get("terms", {}).get(terms_key, {})
|
||||
do_not_translate = glossary.get("do_not_translate", [])
|
||||
|
||||
rules = (
|
||||
f"You are a precise technical translator for DesireCore market skill documentation.\n"
|
||||
f"Translate from {source_locale} to {target_locale}.\n\n"
|
||||
"STRICT RULES:\n"
|
||||
"1. Preserve Markdown structure exactly: heading levels, list nesting, tables, blockquotes, "
|
||||
"fenced code blocks (```...```), inline code (`...`), HTML tags, SVG, YAML keys.\n"
|
||||
"2. NEVER translate: code inside fences, inline `code`, URLs, file paths, command-line args, "
|
||||
"env vars (e.g., $FOO, ${BAR}), Python/JS identifiers, YAML/JSON keys, version numbers.\n"
|
||||
"3. Preserve exact heading text styling: '# H1', '## H2', etc.\n"
|
||||
"4. Preserve list markers: '- ', '* ', '1. '. Preserve checkbox '[ ]' and '[x]'.\n"
|
||||
"5. Preserve emoji, ASCII art (e.g. boxed diagrams), tree-view characters (├ └ │ ─).\n"
|
||||
"6. Translate body prose, table cells (text only, not code), and short heading words.\n"
|
||||
"7. Keep the output length within ~110% of the input length when possible.\n"
|
||||
"8. Do NOT add explanatory comments, translator notes, or 'Translated from...' headers.\n"
|
||||
"9. The first line may be an HTML comment '<!-- locale: ... -->'. Update its locale code "
|
||||
"to the target locale; otherwise leave the comment unchanged.\n"
|
||||
)
|
||||
glossary_lines = ["GLOSSARY (use these mappings exactly):"]
|
||||
for src, tgt in terms.items():
|
||||
glossary_lines.append(f" {src} → {tgt}")
|
||||
if do_not_translate:
|
||||
glossary_lines.append("\nDO NOT TRANSLATE these brand/technical terms (keep verbatim):")
|
||||
glossary_lines.append(" " + ", ".join(do_not_translate))
|
||||
|
||||
output_format = (
|
||||
"\n\nRESPONSE FORMAT:\n"
|
||||
"Return ONLY a single JSON object with these keys (no preamble, no code fence around the JSON):\n"
|
||||
" - body: translated Markdown body (string, may contain backticks/fences)\n"
|
||||
" - name: translated short name (string, ≤100 chars)\n"
|
||||
" - short_desc: translated short description (string, ≤200 chars)\n"
|
||||
" - description: translated long description (string, ≤2000 chars)\n"
|
||||
)
|
||||
|
||||
return rules + "\n" + "\n".join(glossary_lines) + output_format
|
||||
|
||||
|
||||
# ----------------------------- backends -----------------------------
|
||||
|
||||
def call_github_models(system_prompt: str, user_payload: str, model: str, endpoint: str) -> str:
|
||||
"""Call GitHub Models inference API (OpenAI-compatible chat completions).
|
||||
|
||||
Endpoint base: https://models.github.ai/inference
|
||||
Auth: Authorization: Bearer <GITHUB_TOKEN> (token must have `models: read` scope).
|
||||
"""
|
||||
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
||||
if not token:
|
||||
raise RuntimeError(
|
||||
"GITHUB_TOKEN (or GH_TOKEN) not set. In CI, ensure your job has `permissions: models: read`. "
|
||||
"Locally, create a fine-grained PAT with 'Models: Read' permission."
|
||||
)
|
||||
url = f"{endpoint.rstrip('/')}/chat/completions"
|
||||
payload = {
|
||||
"model": model,
|
||||
"messages": [
|
||||
{"role": "system", "content": system_prompt},
|
||||
{"role": "user", "content": user_payload},
|
||||
],
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 8192,
|
||||
}
|
||||
headers = {
|
||||
"Authorization": f"Bearer {token}",
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/vnd.github+json",
|
||||
"X-GitHub-Api-Version": "2022-11-28",
|
||||
}
|
||||
return _post_with_retries(url, headers, payload, extract=_extract_openai_text)
|
||||
|
||||
|
||||
def call_anthropic(system_prompt: str, user_payload: str, model: str, endpoint: str) -> str:
|
||||
"""Call Anthropic Messages API directly."""
|
||||
api_key = os.environ.get("ANTHROPIC_API_KEY")
|
||||
if not api_key:
|
||||
raise RuntimeError("ANTHROPIC_API_KEY not set")
|
||||
url = f"{endpoint.rstrip('/')}/v1/messages"
|
||||
payload = {
|
||||
"model": model,
|
||||
"max_tokens": 8192,
|
||||
"system": [{"type": "text", "text": system_prompt, "cache_control": {"type": "ephemeral"}}],
|
||||
"messages": [{"role": "user", "content": user_payload}],
|
||||
"temperature": 0.1,
|
||||
}
|
||||
headers = {
|
||||
"x-api-key": api_key,
|
||||
"anthropic-version": "2023-06-01",
|
||||
"content-type": "application/json",
|
||||
}
|
||||
return _post_with_retries(url, headers, payload, extract=_extract_anthropic_text)
|
||||
|
||||
|
||||
def _extract_openai_text(resp_json: dict) -> str:
|
||||
try:
|
||||
return resp_json["choices"][0]["message"]["content"]
|
||||
except (KeyError, IndexError, TypeError) as e:
|
||||
raise RuntimeError(f"Unexpected OpenAI-compatible response shape: {resp_json}") from e
|
||||
|
||||
|
||||
def _extract_anthropic_text(resp_json: dict) -> str:
|
||||
try:
|
||||
parts = resp_json["content"]
|
||||
return "".join(p.get("text", "") for p in parts if p.get("type") == "text")
|
||||
except (KeyError, TypeError) as e:
|
||||
raise RuntimeError(f"Unexpected Anthropic response shape: {resp_json}") from e
|
||||
|
||||
|
||||
def _post_with_retries(url: str, headers: dict, payload: dict, *, extract) -> str:
|
||||
last_err: Exception | None = None
|
||||
for attempt in range(1, MAX_RETRIES + 1):
|
||||
try:
|
||||
with httpx.Client(timeout=HTTP_TIMEOUT) as client:
|
||||
resp = client.post(url, headers=headers, json=payload)
|
||||
if resp.status_code == 429 or resp.status_code >= 500:
|
||||
raise httpx.HTTPStatusError(f"{resp.status_code}", request=resp.request, response=resp)
|
||||
resp.raise_for_status()
|
||||
return extract(resp.json())
|
||||
except (httpx.HTTPStatusError, httpx.RequestError, json.JSONDecodeError) as e:
|
||||
last_err = e
|
||||
if attempt < MAX_RETRIES:
|
||||
wait = 2 ** attempt
|
||||
sys.stderr.write(f"[translate] retry {attempt}/{MAX_RETRIES} after {wait}s ({e})\n")
|
||||
time.sleep(wait)
|
||||
raise RuntimeError(f"Translation failed after {MAX_RETRIES} attempts: {last_err}")
|
||||
|
||||
|
||||
def call_llm(system_prompt: str, user_payload: str, *, backend: str, model: str, endpoint: str) -> dict[str, str]:
|
||||
if backend == "github":
|
||||
text = call_github_models(system_prompt, user_payload, model, endpoint)
|
||||
elif backend == "anthropic":
|
||||
text = call_anthropic(system_prompt, user_payload, model, endpoint)
|
||||
else:
|
||||
raise RuntimeError(f"Unknown backend: {backend}")
|
||||
return parse_json_response(text)
|
||||
|
||||
|
||||
def parse_json_response(text: str) -> dict[str, str]:
|
||||
text = text.strip()
|
||||
if text.startswith("```"):
|
||||
text = re.sub(r"^```(?:json)?\s*\n", "", text)
|
||||
text = re.sub(r"\n```\s*$", "", text)
|
||||
try:
|
||||
obj = json.loads(text)
|
||||
except json.JSONDecodeError as e:
|
||||
m = re.search(r"\{.*\}", text, re.DOTALL)
|
||||
if m:
|
||||
obj = json.loads(m.group(0))
|
||||
else:
|
||||
raise RuntimeError(f"Failed to parse model response as JSON: {e}\n--- Raw response ---\n{text[:500]}")
|
||||
for k in ("body", "name", "short_desc"):
|
||||
if k not in obj or not isinstance(obj[k], str):
|
||||
raise RuntimeError(f"Translation response missing required key '{k}'")
|
||||
obj.setdefault("description", "")
|
||||
return obj
|
||||
|
||||
|
||||
# ----------------------------- per-skill translation -----------------------------
|
||||
|
||||
def translate_skill(
|
||||
skill_dir: Path,
|
||||
target_locale: str,
|
||||
*,
|
||||
check_only: bool,
|
||||
mark_human: bool,
|
||||
backend: str,
|
||||
model: str,
|
||||
endpoint: str,
|
||||
) -> dict[str, Any]:
|
||||
rel = skill_dir.relative_to(REPO_ROOT).as_posix()
|
||||
skill_md = skill_dir / "SKILL.md"
|
||||
plan: dict[str, Any] = {"skill": rel, "target": target_locale, "actions": [], "errors": []}
|
||||
|
||||
fm, root_body = load_skill(skill_md)
|
||||
metadata = fm.get("metadata") or {}
|
||||
i18n = metadata.get("i18n") if isinstance(metadata, dict) else None
|
||||
if not isinstance(i18n, dict):
|
||||
plan["errors"].append("metadata.i18n missing — run migrate.py first")
|
||||
return plan
|
||||
|
||||
source_locale = i18n.get("source_locale")
|
||||
default_locale = i18n.get("default_locale")
|
||||
if not source_locale or not default_locale:
|
||||
plan["errors"].append("i18n missing source_locale or default_locale")
|
||||
return plan
|
||||
if target_locale == source_locale:
|
||||
plan["actions"].append("target == source, skipping")
|
||||
return plan
|
||||
|
||||
src_block = i18n.get(source_locale) or {}
|
||||
src_body_path_str = src_block.get("body")
|
||||
if not src_body_path_str:
|
||||
plan["errors"].append(f"i18n.{source_locale}.body not set")
|
||||
return plan
|
||||
src_body_file = (skill_dir / src_body_path_str.removeprefix("./")).resolve()
|
||||
if not src_body_file.is_file():
|
||||
plan["errors"].append(f"source body file not found: {src_body_path_str}")
|
||||
return plan
|
||||
|
||||
src_body_text = strip_locale_header(src_body_file.read_text(encoding="utf-8"))
|
||||
src_strings = {
|
||||
"name": str(src_block.get("name", "")),
|
||||
"short_desc": str(src_block.get("short_desc", "")),
|
||||
}
|
||||
if src_block.get("description"):
|
||||
src_strings["description"] = str(src_block["description"])
|
||||
current_hash = compute_source_hash(src_body_text, src_strings)
|
||||
|
||||
target_block = i18n.get(target_locale) or {}
|
||||
if target_block.get("translated_by") == "human":
|
||||
if target_block.get("source_hash") != current_hash:
|
||||
plan["actions"].append(
|
||||
f"WARN: human-translated locale {target_locale} is stale "
|
||||
f"(source_hash drift). Skipping; please update manually."
|
||||
)
|
||||
else:
|
||||
plan["actions"].append(f"locale {target_locale} is human-locked, skipping")
|
||||
return plan
|
||||
|
||||
needs = (not target_block) or (target_block.get("source_hash") != current_hash)
|
||||
if not needs:
|
||||
plan["actions"].append(f"locale {target_locale} is up-to-date (hash match), skipping")
|
||||
return plan
|
||||
|
||||
if check_only:
|
||||
plan["actions"].append(f"locale {target_locale} needs translation (hash mismatch or missing)")
|
||||
plan["needs_translation"] = True
|
||||
return plan
|
||||
|
||||
payload = {
|
||||
"source_locale": source_locale,
|
||||
"target_locale": target_locale,
|
||||
"skill_id": skill_dir.name,
|
||||
"source": {
|
||||
"name": src_strings["name"],
|
||||
"short_desc": src_strings["short_desc"],
|
||||
"description": src_strings.get("description", ""),
|
||||
"body": src_body_text,
|
||||
},
|
||||
}
|
||||
user_payload = (
|
||||
"Translate the following skill content. Return ONLY the JSON object as specified.\n\n"
|
||||
f"```json\n{json.dumps(payload, ensure_ascii=False)}\n```"
|
||||
)
|
||||
glossary = load_glossary()
|
||||
system_prompt = build_system_prompt(source_locale, target_locale, glossary)
|
||||
|
||||
plan["actions"].append(f"calling {backend}/{model} for {target_locale} translation ...")
|
||||
translated = call_llm(system_prompt, user_payload, backend=backend, model=model, endpoint=endpoint)
|
||||
|
||||
src_h = heading_count(src_body_text)
|
||||
tgt_h = heading_count(translated["body"])
|
||||
if abs(tgt_h - src_h) > 0:
|
||||
plan["errors"].append(f"heading count mismatch (source={src_h}, target={tgt_h}); rejecting")
|
||||
return plan
|
||||
|
||||
if target_locale not in i18n.get("locales", []):
|
||||
i18n["locales"].append(target_locale)
|
||||
new_block: dict[str, Any] = {
|
||||
"name": translated["name"],
|
||||
"short_desc": translated["short_desc"],
|
||||
}
|
||||
if translated.get("description"):
|
||||
desc = translated["description"]
|
||||
new_block["description"] = FoldedScalarString(desc) if "\n" in desc or len(desc) > 80 else desc
|
||||
if target_locale == default_locale:
|
||||
new_block["body"] = "./SKILL.md"
|
||||
else:
|
||||
new_block["body"] = f"./SKILL.{target_locale}.md"
|
||||
new_block["source_hash"] = current_hash
|
||||
translator_tag = "human" if mark_human else f"ai:{backend}:{model}"
|
||||
new_block["translated_by"] = translator_tag
|
||||
new_block["translated_at"] = datetime.now(tz=timezone.utc).strftime("%Y-%m-%d")
|
||||
i18n[target_locale] = new_block
|
||||
|
||||
body_to_write = translated["body"]
|
||||
if target_locale == default_locale:
|
||||
body_to_write = LOCALE_HEADER_RE.sub("", body_to_write, count=1)
|
||||
skill_md.write_text(dump_skill(fm, body_to_write), encoding="utf-8")
|
||||
plan["actions"].append(f"wrote root SKILL.md with translated body ({len(body_to_write)} chars)")
|
||||
else:
|
||||
target_body_file = skill_dir / f"SKILL.{target_locale}.md"
|
||||
if not body_to_write.startswith("<!-- locale:"):
|
||||
body_to_write = f"<!-- locale: {target_locale} -->\n\n{body_to_write.lstrip()}"
|
||||
target_body_file.write_text(body_to_write, encoding="utf-8")
|
||||
skill_md.write_text(dump_skill(fm, root_body), encoding="utf-8")
|
||||
plan["actions"].append(f"wrote {target_body_file.name} ({len(body_to_write)} chars) and updated root frontmatter")
|
||||
|
||||
return plan
|
||||
|
||||
|
||||
def get_target_locales(args: argparse.Namespace) -> list[str]:
|
||||
if args.target:
|
||||
return [args.target]
|
||||
manifest_path = REPO_ROOT / "manifest.json"
|
||||
if not manifest_path.is_file():
|
||||
return ["en-US"]
|
||||
try:
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
except json.JSONDecodeError:
|
||||
return ["en-US"]
|
||||
return list(manifest.get("supportedLocales") or ["en-US"])
|
||||
|
||||
|
||||
def resolve_backend(args: argparse.Namespace) -> tuple[str, str, str]:
|
||||
backend = (args.backend or DEFAULT_BACKEND).lower()
|
||||
if backend not in ("github", "anthropic"):
|
||||
raise SystemExit(f"Unknown backend '{backend}'; choose 'github' or 'anthropic'")
|
||||
model = args.model or DEFAULT_MODEL_BY_BACKEND[backend]
|
||||
endpoint = args.endpoint or os.environ.get("TRANSLATE_ENDPOINT") or DEFAULT_ENDPOINT_BY_BACKEND[backend]
|
||||
return backend, model, endpoint
|
||||
|
||||
|
||||
def list_github_models() -> int:
|
||||
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
||||
if not token:
|
||||
sys.stderr.write("ERROR: GITHUB_TOKEN/GH_TOKEN not set\n")
|
||||
return 2
|
||||
url = "https://models.github.ai/catalog/models"
|
||||
with httpx.Client(timeout=HTTP_TIMEOUT) as c:
|
||||
resp = c.get(url, headers={"Authorization": f"Bearer {token}"})
|
||||
resp.raise_for_status()
|
||||
for m in resp.json():
|
||||
print(f" {m.get('id',''):50s} {m.get('publisher','')}")
|
||||
return 0
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("paths", nargs="*", help="Skill directories (default: all under skills/)")
|
||||
parser.add_argument("--target", help="Single target locale (default: all manifest.supportedLocales)")
|
||||
parser.add_argument("--check", action="store_true", help="Report stale translations; exit 1 if any")
|
||||
parser.add_argument("--human", action="store_true", help="Mark new translations as 'human' (locks against re-translation)")
|
||||
parser.add_argument("--backend", choices=("github", "anthropic"), help="Override backend (default: env TRANSLATE_BACKEND or 'github')")
|
||||
parser.add_argument("--model", help="Override model id")
|
||||
parser.add_argument("--endpoint", help="Override API endpoint")
|
||||
parser.add_argument("--list-models", action="store_true", help="List models in GitHub Models catalog and exit")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
if args.list_models:
|
||||
return list_github_models()
|
||||
|
||||
backend, model, endpoint = resolve_backend(args)
|
||||
|
||||
if not args.check:
|
||||
if backend == "github" and not (os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")):
|
||||
sys.stderr.write("ERROR: GITHUB_TOKEN (or GH_TOKEN) not set for backend='github'\n")
|
||||
return 2
|
||||
if backend == "anthropic" and not os.environ.get("ANTHROPIC_API_KEY"):
|
||||
sys.stderr.write("ERROR: ANTHROPIC_API_KEY not set for backend='anthropic'\n")
|
||||
return 2
|
||||
|
||||
if args.paths:
|
||||
targets = [Path(p).resolve() for p in args.paths]
|
||||
else:
|
||||
targets = sorted((REPO_ROOT / "skills").iterdir())
|
||||
targets = [t for t in targets if t.is_dir() and (t / "SKILL.md").is_file()]
|
||||
|
||||
target_locales = get_target_locales(args)
|
||||
|
||||
plans: list[dict[str, Any]] = []
|
||||
for skill_dir in targets:
|
||||
if not (skill_dir.is_dir() and (skill_dir / "SKILL.md").is_file()):
|
||||
continue
|
||||
for tl in target_locales:
|
||||
plans.append(translate_skill(
|
||||
skill_dir, tl,
|
||||
check_only=args.check, mark_human=args.human,
|
||||
backend=backend, model=model, endpoint=endpoint,
|
||||
))
|
||||
|
||||
needs = [p for p in plans if p.get("needs_translation")]
|
||||
errs = [p for p in plans if p.get("errors")]
|
||||
if args.check:
|
||||
for p in plans:
|
||||
for a in p["actions"]:
|
||||
print(f" [{p['skill']}/{p['target']}] {a}")
|
||||
for p in errs:
|
||||
for e in p["errors"]:
|
||||
print(f" ERROR [{p['skill']}/{p['target']}]: {e}")
|
||||
return 1 if needs else 0
|
||||
|
||||
print(f"Backend: {backend} Model: {model} Endpoint: {endpoint}\n")
|
||||
for p in plans:
|
||||
print(f"{p['skill']} → {p['target']}:")
|
||||
for a in p["actions"]:
|
||||
print(f" - {a}")
|
||||
for e in p.get("errors", []):
|
||||
print(f" ✗ ERROR: {e}")
|
||||
return 1 if errs else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
340
scripts/i18n/validate-i18n.py
Executable file
340
scripts/i18n/validate-i18n.py
Executable file
@@ -0,0 +1,340 @@
|
||||
#!/usr/bin/env -S uv run --script
|
||||
# /// script
|
||||
# requires-python = ">=3.10"
|
||||
# dependencies = ["pyyaml>=6.0"]
|
||||
# ///
|
||||
"""Validate DesireCore market i18n state.
|
||||
|
||||
Checks:
|
||||
1. SKILL.md frontmatter top-level `name` matches parent dir name and is spec-compliant.
|
||||
2. metadata.i18n.default_locale and source_locale are listed in metadata.i18n.locales.
|
||||
3. Each declared locale has metadata.i18n.<locale>.{name,short_desc}.
|
||||
4. metadata.i18n.<locale>.body, if present, points to an existing file; otherwise the
|
||||
fallback chain must terminate at a readable root SKILL.md.
|
||||
5. SKILL.<locale>.md, if it declares <!-- locale: ... -->, must match the filename locale.
|
||||
6. Frontmatter parses cleanly; heading count of locale body matches source body (+/- 0).
|
||||
7. categories.json's per-category i18n covers all locales declared in manifest.json.
|
||||
8. Top-level description is 1-1024 chars (spec); top-level name is 1-64 chars (spec).
|
||||
|
||||
Exit codes:
|
||||
0 = pass
|
||||
1 = validation errors found
|
||||
2 = unexpected runtime error / missing dependencies
|
||||
|
||||
Usage:
|
||||
python3 scripts/i18n/validate-i18n.py # validate everything under repo root
|
||||
python3 scripts/i18n/validate-i18n.py skills/web-access # validate single skill
|
||||
python3 scripts/i18n/validate-i18n.py --json # machine-readable output
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import re
|
||||
import sys
|
||||
from dataclasses import dataclass, field
|
||||
from pathlib import Path
|
||||
from typing import Any, Iterable
|
||||
|
||||
try:
|
||||
import yaml
|
||||
except ImportError:
|
||||
sys.stderr.write("ERROR: PyYAML is required. Install with: pip install pyyaml\n")
|
||||
sys.exit(2)
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[2]
|
||||
|
||||
NAME_PATTERN = re.compile(r"^(?!-)(?!.*--)[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$")
|
||||
RESERVED_NAMES = {"anthropic", "claude"}
|
||||
LOCALE_PATTERN = re.compile(r"^[a-z]{2,3}(?:-[A-Z]{2})?$")
|
||||
LOCALE_HEADER_PATTERN = re.compile(r"^<!--\s*locale:\s*([a-zA-Z-]+)\s*-->")
|
||||
HEADING_PATTERN = re.compile(r"^(#{1,6})\s+\S", re.MULTILINE)
|
||||
FRONTMATTER_RE = re.compile(r"^---\s*\n(.*?)\n---\s*\n(.*)$", re.DOTALL)
|
||||
|
||||
|
||||
@dataclass
|
||||
class Issue:
|
||||
path: str
|
||||
rule: str
|
||||
message: str
|
||||
severity: str = "error"
|
||||
|
||||
def to_dict(self) -> dict[str, str]:
|
||||
return {
|
||||
"path": self.path,
|
||||
"rule": self.rule,
|
||||
"message": self.message,
|
||||
"severity": self.severity,
|
||||
}
|
||||
|
||||
|
||||
@dataclass
|
||||
class Report:
|
||||
issues: list[Issue] = field(default_factory=list)
|
||||
|
||||
def add(self, issue: Issue) -> None:
|
||||
self.issues.append(issue)
|
||||
|
||||
@property
|
||||
def has_errors(self) -> bool:
|
||||
return any(i.severity == "error" for i in self.issues)
|
||||
|
||||
|
||||
def parse_frontmatter(text: str) -> tuple[dict[str, Any] | None, str | None, str | None]:
|
||||
"""Return (frontmatter_dict, body, error). All three Nones means file is empty."""
|
||||
if not text.strip():
|
||||
return None, None, "empty file"
|
||||
m = FRONTMATTER_RE.match(text)
|
||||
if not m:
|
||||
return None, None, "no YAML frontmatter (file must start with '---')"
|
||||
try:
|
||||
fm = yaml.safe_load(m.group(1)) or {}
|
||||
except yaml.YAMLError as e:
|
||||
return None, None, f"YAML parse error: {e}"
|
||||
if not isinstance(fm, dict):
|
||||
return None, None, "frontmatter must be a YAML mapping"
|
||||
return fm, m.group(2), None
|
||||
|
||||
|
||||
def heading_count(text: str) -> int:
|
||||
return len(HEADING_PATTERN.findall(text or ""))
|
||||
|
||||
|
||||
def validate_skill(skill_dir: Path, report: Report, declared_locales: set[str] | None = None) -> None:
|
||||
"""Validate one skill directory (must contain SKILL.md)."""
|
||||
rel_dir = skill_dir.relative_to(REPO_ROOT).as_posix()
|
||||
skill_md = skill_dir / "SKILL.md"
|
||||
if not skill_md.is_file():
|
||||
report.add(Issue(rel_dir, "structure", "SKILL.md not found"))
|
||||
return
|
||||
|
||||
text = skill_md.read_text(encoding="utf-8")
|
||||
fm, body, err = parse_frontmatter(text)
|
||||
if err:
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-6", err))
|
||||
return
|
||||
assert fm is not None and body is not None
|
||||
|
||||
name = fm.get("name", "")
|
||||
description = fm.get("description", "")
|
||||
|
||||
# Rule 1: name spec-compliance + matches dir
|
||||
if not isinstance(name, str) or not NAME_PATTERN.match(name) or len(name) > 64 or name in RESERVED_NAMES:
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-1",
|
||||
f"name {name!r} is not spec-compliant (must be lowercase ASCII + hyphens, 1-64 chars, not 'anthropic'/'claude')"
|
||||
))
|
||||
if name != skill_dir.name:
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-1",
|
||||
f"name '{name}' must equal parent dir name '{skill_dir.name}' (spec)"
|
||||
))
|
||||
|
||||
# Rule 8: description length
|
||||
if not isinstance(description, str) or not (1 <= len(description) <= 1024):
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-8",
|
||||
f"description must be 1-1024 chars (got {len(description) if isinstance(description, str) else 'non-string'})"
|
||||
))
|
||||
|
||||
# Rule 2/3/4: i18n block
|
||||
metadata = fm.get("metadata") or {}
|
||||
i18n = metadata.get("i18n") if isinstance(metadata, dict) else None
|
||||
if not isinstance(i18n, dict):
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-2", "metadata.i18n block missing"))
|
||||
return
|
||||
|
||||
default_locale = i18n.get("default_locale")
|
||||
source_locale = i18n.get("source_locale")
|
||||
locales = i18n.get("locales") or []
|
||||
if not isinstance(locales, list) or not all(isinstance(x, str) for x in locales):
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-2", "metadata.i18n.locales must be a list of strings"))
|
||||
return
|
||||
locale_set = set(locales)
|
||||
|
||||
for tag in ("default_locale", "source_locale"):
|
||||
val = i18n.get(tag)
|
||||
if not isinstance(val, str) or not LOCALE_PATTERN.match(val):
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-2", f"metadata.i18n.{tag} '{val!r}' is not a valid BCP-47 locale"))
|
||||
elif val not in locale_set:
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-2", f"metadata.i18n.{tag} '{val}' not present in metadata.i18n.locales"))
|
||||
|
||||
if declared_locales is not None:
|
||||
missing = declared_locales - locale_set
|
||||
if missing:
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-7",
|
||||
f"manifest declares locales {sorted(declared_locales)} but skill is missing {sorted(missing)}",
|
||||
severity="error"
|
||||
))
|
||||
|
||||
# Rule 3: per-locale name/short_desc presence
|
||||
source_body_text: str | None = None
|
||||
for locale in locales:
|
||||
if not LOCALE_PATTERN.match(locale):
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-3", f"locale '{locale}' is not a valid BCP-47 tag"))
|
||||
continue
|
||||
payload = i18n.get(locale)
|
||||
if not isinstance(payload, dict):
|
||||
report.add(Issue(f"{rel_dir}/SKILL.md", "rule-3", f"metadata.i18n.{locale} block missing or not a mapping"))
|
||||
continue
|
||||
for required in ("name", "short_desc"):
|
||||
v = payload.get(required)
|
||||
if not isinstance(v, str) or not v.strip():
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-3",
|
||||
f"metadata.i18n.{locale}.{required} is missing or empty"
|
||||
))
|
||||
|
||||
# Rule 4: body file presence
|
||||
body_path_str = payload.get("body")
|
||||
body_text: str | None = None
|
||||
if body_path_str:
|
||||
if not isinstance(body_path_str, str) or not body_path_str.startswith("./"):
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-4",
|
||||
f"metadata.i18n.{locale}.body must be a relative path starting with './' (got {body_path_str!r})"
|
||||
))
|
||||
else:
|
||||
body_file = (skill_dir / body_path_str.removeprefix("./")).resolve()
|
||||
if not body_file.is_file():
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/SKILL.md", "rule-4",
|
||||
f"metadata.i18n.{locale}.body points to missing file '{body_path_str}'"
|
||||
))
|
||||
else:
|
||||
body_text = body_file.read_text(encoding="utf-8")
|
||||
# Rule 5: locale header self-check (only when not the root SKILL.md)
|
||||
if body_file.name != "SKILL.md":
|
||||
first_line = body_text.splitlines()[0] if body_text else ""
|
||||
m = LOCALE_HEADER_PATTERN.match(first_line)
|
||||
if m and m.group(1) != locale:
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/{body_file.name}", "rule-5",
|
||||
f"file declares locale '{m.group(1)}' but is referenced as '{locale}'"
|
||||
))
|
||||
else:
|
||||
# Fallback to root SKILL.md body (default_locale must have a usable body)
|
||||
if locale == default_locale:
|
||||
body_text = body
|
||||
else:
|
||||
# OK to omit body for non-default locales (will fall back at runtime)
|
||||
pass
|
||||
|
||||
if locale == source_locale:
|
||||
source_body_text = body_text or body # source defaults to root if not specified
|
||||
|
||||
# Rule 6: heading count consistency between source and other locales' bodies
|
||||
if source_body_text is not None:
|
||||
source_count = heading_count(source_body_text)
|
||||
for locale in locales:
|
||||
if locale == source_locale:
|
||||
continue
|
||||
payload = i18n.get(locale) or {}
|
||||
body_path_str = payload.get("body")
|
||||
if body_path_str:
|
||||
body_file = (skill_dir / body_path_str.removeprefix("./")).resolve()
|
||||
if body_file.is_file():
|
||||
other_text = body_file.read_text(encoding="utf-8")
|
||||
other_count = heading_count(other_text)
|
||||
if other_count != source_count:
|
||||
report.add(Issue(
|
||||
f"{rel_dir}/{body_file.name}", "rule-6",
|
||||
f"heading count {other_count} differs from source ({source_count})",
|
||||
severity="warning",
|
||||
))
|
||||
|
||||
|
||||
def validate_market_root(report: Report) -> set[str]:
|
||||
"""Validate manifest.json + categories.json. Returns the declared locale set or empty."""
|
||||
manifest_path = REPO_ROOT / "manifest.json"
|
||||
categories_path = REPO_ROOT / "categories.json"
|
||||
|
||||
declared: set[str] = set()
|
||||
if manifest_path.is_file():
|
||||
try:
|
||||
manifest = json.loads(manifest_path.read_text(encoding="utf-8"))
|
||||
except json.JSONDecodeError as e:
|
||||
report.add(Issue("manifest.json", "rule-7", f"JSON parse error: {e}"))
|
||||
manifest = {}
|
||||
supported = manifest.get("supportedLocales") or []
|
||||
if not isinstance(supported, list) or not all(isinstance(x, str) and LOCALE_PATTERN.match(x) for x in supported):
|
||||
report.add(Issue("manifest.json", "rule-7", "supportedLocales must be a list of BCP-47 tags"))
|
||||
else:
|
||||
declared = set(supported)
|
||||
default = manifest.get("defaultLocale")
|
||||
if declared and default not in declared:
|
||||
report.add(Issue("manifest.json", "rule-7", f"defaultLocale '{default}' not in supportedLocales"))
|
||||
|
||||
if categories_path.is_file() and declared:
|
||||
try:
|
||||
categories = json.loads(categories_path.read_text(encoding="utf-8"))
|
||||
except json.JSONDecodeError as e:
|
||||
report.add(Issue("categories.json", "rule-7", f"JSON parse error: {e}"))
|
||||
return declared
|
||||
for cat_id, cat in categories.items():
|
||||
i18n = cat.get("i18n") if isinstance(cat, dict) else None
|
||||
if not isinstance(i18n, dict):
|
||||
report.add(Issue("categories.json", "rule-7", f"category '{cat_id}' missing i18n block"))
|
||||
continue
|
||||
for locale in declared:
|
||||
payload = i18n.get(locale)
|
||||
if not isinstance(payload, dict) or not payload.get("label"):
|
||||
report.add(Issue(
|
||||
"categories.json", "rule-7",
|
||||
f"category '{cat_id}' missing i18n.{locale}.label"
|
||||
))
|
||||
return declared
|
||||
|
||||
|
||||
def iter_skill_dirs(targets: Iterable[Path]) -> Iterable[Path]:
|
||||
for t in targets:
|
||||
if t.is_file() and t.name == "SKILL.md":
|
||||
yield t.parent
|
||||
elif t.is_dir() and (t / "SKILL.md").is_file():
|
||||
yield t
|
||||
elif t.is_dir():
|
||||
for child in sorted(t.iterdir()):
|
||||
if child.is_dir() and (child / "SKILL.md").is_file():
|
||||
yield child
|
||||
|
||||
|
||||
def main(argv: list[str]) -> int:
|
||||
parser = argparse.ArgumentParser(description=__doc__)
|
||||
parser.add_argument("paths", nargs="*", help="Skills or directories to validate (default: repo root)")
|
||||
parser.add_argument("--json", action="store_true", help="Emit machine-readable JSON")
|
||||
args = parser.parse_args(argv)
|
||||
|
||||
report = Report()
|
||||
declared_locales = validate_market_root(report)
|
||||
|
||||
if args.paths:
|
||||
targets = [Path(p).resolve() for p in args.paths]
|
||||
else:
|
||||
targets = [REPO_ROOT / "skills"]
|
||||
|
||||
for skill_dir in iter_skill_dirs(targets):
|
||||
validate_skill(skill_dir, report, declared_locales=declared_locales or None)
|
||||
|
||||
if args.json:
|
||||
json.dump([i.to_dict() for i in report.issues], sys.stdout, indent=2, ensure_ascii=False)
|
||||
sys.stdout.write("\n")
|
||||
else:
|
||||
if not report.issues:
|
||||
print("OK: no i18n issues found.")
|
||||
else:
|
||||
for issue in report.issues:
|
||||
marker = "ERROR" if issue.severity == "error" else "WARN "
|
||||
print(f"[{marker}] {issue.path} :: {issue.rule} :: {issue.message}")
|
||||
errors = sum(1 for i in report.issues if i.severity == "error")
|
||||
warns = sum(1 for i in report.issues if i.severity == "warning")
|
||||
print(f"\n{errors} error(s), {warns} warning(s).")
|
||||
|
||||
return 1 if report.has_errors else 0
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
sys.exit(main(sys.argv[1:]))
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(130)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 创建智能体
|
||||
name: create-agent
|
||||
description: >-
|
||||
通过多轮对话收集需求,调用 HTTP API 创建新的 AgentFS v2 智能体,支持自定义 persona 和 principles。Use when
|
||||
用户要求创建新智能体、培养某领域助手、或快速基于模板生成可治理 Agent。
|
||||
@@ -15,6 +15,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-02-28'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 创建智能体
|
||||
short_desc: 通过自然语言对话收集需求,一键创建专业化数字智能体
|
||||
description: >-
|
||||
通过多轮对话收集需求,调用 HTTP API 创建新的 AgentFS v2 智能体,支持自定义 persona 和 principles。Use when 用户要求创建新智能体、培养某领域助手、或快速基于模板生成可治理 Agent。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:cf21692224334fce
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Create Agent
|
||||
short_desc: Collect requirements through natural-language conversation and create a specialized digital Agent in one step
|
||||
description: >-
|
||||
Collect requirements through multi-turn conversation and call the HTTP API to create a new AgentFS v2 Agent, with customizable persona and principles. Use when the user asks to create a new Agent, raise a domain assistant, or quickly produce a governable Agent from a template.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:cf21692224334fce
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -29,7 +52,6 @@ market:
|
||||
stroke="#34C759" stroke-width="2" stroke-linecap="round"/><line x1="16.5"
|
||||
y1="11" x2="21.5" y2="11" stroke="#34C759" stroke-width="2"
|
||||
stroke-linecap="round"/></svg>
|
||||
short_desc: 通过自然语言对话收集需求,一键创建专业化数字智能体
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -38,33 +60,33 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# create-agent 技能
|
||||
# create-agent skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-Sentence Summary
|
||||
|
||||
通过自然语言对话收集需求,调用 HTTP API 创建专业化的数字智能体。
|
||||
Collect requirements through natural-language conversation and call the HTTP API to create a specialized digital Agent.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
create-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 创建其他 Agent 的能力。它通过多轮对话收集用户需求,生成 persona 和 principles 内容,调用 `POST /api/agents` 完成创建。
|
||||
create-agent is a **Meta-Skill** that gives DesireCore the ability to create other Agents. It collects user requirements through multi-turn conversation, generates persona and principles content, and calls `POST /api/agents` to complete the creation.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想要一个专业领域的数字助手(如法律顾问、财务分析师)
|
||||
- 企业需要快速部署定制化的业务 Agent
|
||||
- 开发者需要基于模板快速创建 Agent 原型
|
||||
- The user wants a digital assistant for a specialty domain (e.g. legal advisor, financial analyst)
|
||||
- An enterprise needs to quickly deploy a customized business Agent
|
||||
- A developer needs to quickly produce an Agent prototype from a template
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **降低门槛**:无需编程知识,用对话就能创建 Agent
|
||||
- **专业化**:根据领域模板生成合适的 persona 和 principles
|
||||
- **可治理**:创建的仓库符合 AgentFS v2 规范,支持版本管理
|
||||
- **Lower the barrier**: No programming knowledge required; create an Agent through conversation
|
||||
- **Specialization**: Generate appropriate persona and principles based on a domain template
|
||||
- **Governable**: The created repository conforms to the AgentFS v2 spec and supports version management
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 对话流程
|
||||
### Conversation Flow
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
@@ -77,122 +99,122 @@ create-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 创建
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:意图识别
|
||||
### Stage 1: Intent Recognition
|
||||
|
||||
**触发条件**(任一满足):
|
||||
**Trigger conditions** (any one is sufficient):
|
||||
|
||||
- 用户明确说"创建一个 Agent"或"帮我做一个助手"
|
||||
- 用户描述需要某领域的专业帮助,且当前 Agent 不具备该能力
|
||||
- 用户询问"能不能帮我培养一个..."
|
||||
- The user explicitly says "create an Agent" or "build me an assistant"
|
||||
- The user describes needing professional help in some domain that the current Agent doesn't have
|
||||
- The user asks "can you help me grow a..."
|
||||
|
||||
**输出**:确认用户的创建意图,进入需求收集阶段。
|
||||
**Output**: Confirm the user's create intent and proceed to requirement collection.
|
||||
|
||||
### 阶段 2:需求收集
|
||||
### Stage 2: Requirement Collection
|
||||
|
||||
**必填信息**:
|
||||
**Required information**:
|
||||
|
||||
| 字段 | 说明 | 引导问题示例 |
|
||||
| -------------- | ---------- | ------------------------------ |
|
||||
| `name` | 智能体名称 | "你想给这个智能体起什么名字?" |
|
||||
| `role` | 核心职责 | "它主要负责什么工作?" |
|
||||
| `target_users` | 目标用户 | "谁会使用这个智能体?" |
|
||||
| `domain` | 专业领域 | "它需要哪些专业知识?" |
|
||||
| Field | Description | Example Probing Question |
|
||||
| -------------- | -------------- | ---------------------------------------------- |
|
||||
| `name` | Agent name | "What name would you like to give this Agent?" |
|
||||
| `role` | Core duty | "What's its main responsibility?" |
|
||||
| `target_users` | Target users | "Who will use this Agent?" |
|
||||
| `domain` | Specialty area | "What expertise does it need?" |
|
||||
|
||||
**选填信息**:
|
||||
**Optional information**:
|
||||
|
||||
| 字段 | 说明 | 默认值 |
|
||||
| ------------ | --------- | ---------------- |
|
||||
| `style` | 沟通风格 | 根据领域模板决定 |
|
||||
| `boundaries` | 禁区/红线 | 根据领域模板决定 |
|
||||
| `language` | 主要语言 | 中文 |
|
||||
| Field | Description | Default |
|
||||
| ------------ | --------------------- | -------------------------------- |
|
||||
| `style` | Communication style | Determined by domain template |
|
||||
| `boundaries` | Off-limits / red lines| Determined by domain template |
|
||||
| `language` | Primary language | Chinese |
|
||||
|
||||
**收集策略**:
|
||||
**Collection strategy**:
|
||||
|
||||
- 优先通过用户的自然描述推断信息
|
||||
- 仅追问用户未提及的必填项
|
||||
- 每轮最多追问 2 个问题
|
||||
- Prefer to infer information from the user's natural description
|
||||
- Only probe for required fields the user hasn't mentioned
|
||||
- Ask at most 2 follow-up questions per turn
|
||||
|
||||
### 阶段 3:内容生成
|
||||
### Stage 3: Content Generation
|
||||
|
||||
根据收集的需求,组装结构化的 persona 和 principles 数据。**不要输出原始 markdown**,而是按字段整理后向用户展示。
|
||||
Based on the collected requirements, assemble structured persona and principles data. **Do not output raw markdown**; instead, organize by field and present to the user.
|
||||
|
||||
**Persona 字段**(所有字段均可选,未收集到的由系统自动补全):
|
||||
**Persona fields** (all fields optional; missing ones are auto-filled by the system):
|
||||
|
||||
| 层级 | 字段 | 说明 |
|
||||
| ---- | --------------------- | --------------------------------------------- |
|
||||
| L0 | — | 一句话核心身份 |
|
||||
| L1 | `role` | 角色定位 |
|
||||
| L1 | `personality` | 性格特征标签 |
|
||||
| L1 | `communication_style` | 沟通风格 |
|
||||
| L2 | — | 专业领域、核心价值观、决策偏好等(free-form) |
|
||||
| Layer | Field | Description |
|
||||
| ----- | --------------------- | ------------------------------------------------------------ |
|
||||
| L0 | — | One-sentence core identity |
|
||||
| L1 | `role` | Role positioning |
|
||||
| L1 | `personality` | Personality trait tags |
|
||||
| L1 | `communication_style` | Communication style |
|
||||
| L2 | — | Specialty domain, core values, decision preferences (free-form) |
|
||||
|
||||
**Principles 字段**(同样全部可选):
|
||||
**Principles fields** (all also optional):
|
||||
|
||||
| 层级 | 字段 | 说明 |
|
||||
| ---- | ---------- | --------------------------------- |
|
||||
| L0 | — | 一句话最高原则 |
|
||||
| L1 | `must_do` | 必须做的事项 |
|
||||
| L1 | `must_not` | 绝不做的事项(安全红线) |
|
||||
| L1 | `priority` | 优先级排序 |
|
||||
| L2 | — | 治理原则、升级规则等(free-form) |
|
||||
| Layer | Field | Description |
|
||||
| ----- | ---------- | -------------------------------------------- |
|
||||
| L0 | — | One-sentence top-level principle |
|
||||
| L1 | `must_do` | Things the Agent must do |
|
||||
| L1 | `must_not` | Things the Agent must never do (safety red lines) |
|
||||
| L1 | `priority` | Priority ordering |
|
||||
| L2 | — | Governance principles, escalation rules (free-form) |
|
||||
|
||||
**领域匹配参考**:
|
||||
**Domain matching reference**:
|
||||
|
||||
| 领域关键词 | 推荐 personality | 默认 must_not |
|
||||
| ---------------- | ------------------ | ---------------------------------- |
|
||||
| 法律、合同、法务 | 专业、严谨、审慎 | 不提供诉讼代理、不替代正式法律意见 |
|
||||
| 财务、会计、投资 | 精确、分析性、保守 | 不提供投资建议、不处理真实交易 |
|
||||
| 代码、开发、架构 | 逻辑、务实、直接 | 不直接访问生产环境、不存储凭证 |
|
||||
| 通用/其他 | 友好、有帮助 | 通用安全规范 |
|
||||
| Domain Keywords | Recommended personality | Default must_not |
|
||||
| -------------------------------- | -------------------------------- | ----------------------------------------------- |
|
||||
| Legal, contract, legal affairs | Professional, rigorous, prudent | No litigation representation; not a substitute for formal legal advice |
|
||||
| Finance, accounting, investment | Precise, analytical, conservative | No investment advice; do not handle real transactions |
|
||||
| Code, development, architecture | Logical, pragmatic, direct | No direct production access; do not store credentials |
|
||||
| General / other | Friendly, helpful | Standard safety norms |
|
||||
|
||||
### 阶段 4:用户确认
|
||||
### Stage 4: User Confirmation
|
||||
|
||||
向用户展示预览时,以自然语言/表格形式呈现各字段,**不要展示原始 markdown 源码**:
|
||||
When showing the preview to the user, present each field in natural language / table form. **Do not show raw markdown source**:
|
||||
|
||||
> 即将创建智能体:
|
||||
> About to create Agent:
|
||||
>
|
||||
> **名称**:法律顾问小助手
|
||||
> **描述**:专注于合同审查和法律风险评估的数字智能体
|
||||
> **Name**: Legal Advisor Assistant
|
||||
> **Description**: A digital Agent focused on contract review and legal risk assessment
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> **人格设定**
|
||||
> **Persona**
|
||||
>
|
||||
> | 字段 | 内容 |
|
||||
> | -------- | ------------------------------------------------ |
|
||||
> | 核心身份 | 你是法律顾问小助手,专注于合同审查和法律风险评估 |
|
||||
> | 角色定位 | 专注于合同审查和法律风险评估的数字法律顾问 |
|
||||
> | 性格特征 | 专业、严谨、审慎 |
|
||||
> | 沟通风格 | 准确使用法律术语,同时提供通俗解释 |
|
||||
> | Field | Content |
|
||||
> | --------------------- | ------------------------------------------------------------------------ |
|
||||
> | Core identity | You are Legal Advisor Assistant, focused on contract review and legal risk assessment |
|
||||
> | Role positioning | A digital legal advisor focused on contract review and legal risk assessment |
|
||||
> | Personality | Professional, rigorous, prudent |
|
||||
> | Communication style | Use legal terminology accurately while also providing plain-language explanations |
|
||||
>
|
||||
> **行为原则**
|
||||
> **Principles**
|
||||
>
|
||||
> | 字段 | 内容 |
|
||||
> | -------- | ------------------------------------------------ |
|
||||
> | 最高原则 | 以用户利益为最高优先级,不替代正式法律意见 |
|
||||
> | 必须做 | 准确引用法律条文、标注不确定性、建议咨询专业律师 |
|
||||
> | 绝不做 | 提供诉讼代理、替代正式法律意见、泄露用户咨询内容 |
|
||||
> | 优先级 | 用户安全 > 准确性 > 效率 |
|
||||
> | Field | Content |
|
||||
> | ----------------- | -------------------------------------------------------------------- |
|
||||
> | Top principle | User interest is the highest priority; not a substitute for formal legal advice |
|
||||
> | Must do | Cite statutes accurately, mark uncertainty, recommend consulting a professional lawyer |
|
||||
> | Must not | Provide litigation representation, substitute for formal legal advice, leak user consultations |
|
||||
> | Priority | User safety > Accuracy > Efficiency |
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> 确认创建?(确认 / 修改 / 取消)
|
||||
> Confirm creation? (Confirm / Modify / Cancel)
|
||||
|
||||
**"修改"分支处理**:
|
||||
**"Modify" branch handling**:
|
||||
|
||||
用户选择"修改"时:
|
||||
When the user chooses "Modify":
|
||||
|
||||
1. 询问用户要修改哪个字段(如"想修改哪一项?")
|
||||
2. 用户指出要修改的字段(如"性格特征改成更活泼的")
|
||||
3. Agent 重新收集该字段内容
|
||||
4. 更新预览中的对应字段
|
||||
5. 再次展示完整预览 → 重新进入确认流程
|
||||
1. Ask the user which field to modify (e.g. "Which one do you want to modify?")
|
||||
2. The user identifies the field to modify (e.g. "change personality to something more lively")
|
||||
3. The Agent re-collects content for that field
|
||||
4. Update the corresponding field in the preview
|
||||
5. Show the full preview again → re-enter the confirmation flow
|
||||
|
||||
### 阶段 5:调用 API 创建
|
||||
### Stage 5: Call API to Create
|
||||
|
||||
**API 端点**:`POST /api/agents`
|
||||
**API endpoint**: `POST /api/agents`
|
||||
|
||||
**请求体**(结构化格式):
|
||||
**Request body** (structured format):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -217,23 +239,23 @@ create-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 创建
|
||||
}
|
||||
```
|
||||
|
||||
**最简创建**(只需 name,其余全部自动生成):
|
||||
**Minimal create** (only `name`; the rest is auto-generated):
|
||||
|
||||
```json
|
||||
{ "name": "我的助手" }
|
||||
```
|
||||
|
||||
**基础创建**(name + description,description 自动填充 persona L0):
|
||||
**Basic create** (`name` + `description`; `description` auto-fills persona L0):
|
||||
|
||||
```json
|
||||
{ "name": "法律顾问", "description": "专注合同审查" }
|
||||
```
|
||||
|
||||
所有未提供的字段由系统自动补全为合理默认值。`persona` 和 `principles` 也支持传入原始 markdown 字符串(向后兼容)。
|
||||
Any unprovided fields are auto-filled with sensible defaults by the system. `persona` and `principles` also accept raw markdown strings (backward compatible).
|
||||
|
||||
**可选**:如需指定 slug ID,可根据 name 生成合理的 kebab-case slug(如 "法律顾问" → "legal-advisor"),在请求体中附带 `"id": "<slug>"`。不指定时系统会自动从 name 生成。
|
||||
**Optional**: To specify a slug ID, generate a sensible kebab-case slug from `name` (e.g. "Legal Advisor" → "legal-advisor") and include `"id": "<slug>"` in the request body. If not specified, the system auto-generates one from `name`.
|
||||
|
||||
**成功响应** (`201 Created`):
|
||||
**Successful response** (`201 Created`):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -250,41 +272,41 @@ create-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 创建
|
||||
}
|
||||
```
|
||||
|
||||
响应中的 `agent` 字段包含创建后的智能体完整信息,可直接用于回执展示。
|
||||
The `agent` field in the response contains the full info of the newly created Agent and can be used directly in the receipt.
|
||||
|
||||
### 阶段 6:回执生成
|
||||
### Stage 6: Receipt Generation
|
||||
|
||||
**回执报告**:
|
||||
**Receipt report**:
|
||||
|
||||
创建成功后,以用户友好的方式呈现回执(不要暴露内部路径或技术细节):
|
||||
After successful creation, present the receipt in a user-friendly way (do not expose internal paths or technical details):
|
||||
|
||||
> 智能体「法律顾问小助手」已创建成功!
|
||||
> Agent "Legal Advisor Assistant" has been created!
|
||||
>
|
||||
> **下一步你可以**:
|
||||
> **Next steps**:
|
||||
>
|
||||
> - 直接开始对话
|
||||
> - 为它添加技能,让它更强大
|
||||
> - 调整它的性格或行为规则
|
||||
> - Start a conversation right away
|
||||
> - Add skills to make it more powerful
|
||||
> - Adjust its personality or behavior rules
|
||||
|
||||
### 背景知识
|
||||
### Background Knowledge
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
> AgentFS repository structure, troubleshooting points, and protected paths are detailed in `_agentfs-background.md` and `_protected-paths.yaml`.
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| ------ | ------------------------ | ---------------- |
|
||||
| 400 | 缺少 name 或 ID 格式无效 | 提示用户检查输入 |
|
||||
| 409 | Agent ID 已存在 | 建议使用其他名称 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
| Error Code | Scenario | Handling |
|
||||
| ---------- | ------------------------------------- | --------------------------------- |
|
||||
| 400 | Missing `name` or invalid ID format | Ask user to check input |
|
||||
| 409 | Agent ID already exists | Suggest using another name |
|
||||
| 500 | Internal server error | Ask user to try again later |
|
||||
|
||||
### 权限要求
|
||||
### Permission Requirements
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 创建操作需要用户确认
|
||||
- Prefer accessing the Agent Service HTTP API via the `Bash` tool with curl
|
||||
- The API base URL is already injected into the "Local API" section of the system prompt; reference it directly
|
||||
- Creation requires user confirmation
|
||||
|
||||
### 依赖
|
||||
### Dependencies
|
||||
|
||||
- Agent Service HTTP API(`POST /api/agents`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
- Agent Service HTTP API (`POST /api/agents`)
|
||||
- The local API URL declaration in the system prompt
|
||||
|
||||
252
skills/create-agent/SKILL.zh-CN.md
Normal file
252
skills/create-agent/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,252 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# create-agent 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
通过自然语言对话收集需求,调用 HTTP API 创建专业化的数字智能体。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
create-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 创建其他 Agent 的能力。它通过多轮对话收集用户需求,生成 persona 和 principles 内容,调用 `POST /api/agents` 完成创建。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想要一个专业领域的数字助手(如法律顾问、财务分析师)
|
||||
- 企业需要快速部署定制化的业务 Agent
|
||||
- 开发者需要基于模板快速创建 Agent 原型
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **降低门槛**:无需编程知识,用对话就能创建 Agent
|
||||
- **专业化**:根据领域模板生成合适的 persona 和 principles
|
||||
- **可治理**:创建的仓库符合 AgentFS v2 规范,支持版本管理
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 对话流程
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 意图识别 │ ──→ │ 需求收集 │ ──→ │ 内容生成 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 回执生成 │ ←── │ API 创建 │ ←── │ 用户确认 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:意图识别
|
||||
|
||||
**触发条件**(任一满足):
|
||||
|
||||
- 用户明确说"创建一个 Agent"或"帮我做一个助手"
|
||||
- 用户描述需要某领域的专业帮助,且当前 Agent 不具备该能力
|
||||
- 用户询问"能不能帮我培养一个..."
|
||||
|
||||
**输出**:确认用户的创建意图,进入需求收集阶段。
|
||||
|
||||
### 阶段 2:需求收集
|
||||
|
||||
**必填信息**:
|
||||
|
||||
| 字段 | 说明 | 引导问题示例 |
|
||||
| -------------- | ---------- | ------------------------------ |
|
||||
| `name` | 智能体名称 | "你想给这个智能体起什么名字?" |
|
||||
| `role` | 核心职责 | "它主要负责什么工作?" |
|
||||
| `target_users` | 目标用户 | "谁会使用这个智能体?" |
|
||||
| `domain` | 专业领域 | "它需要哪些专业知识?" |
|
||||
|
||||
**选填信息**:
|
||||
|
||||
| 字段 | 说明 | 默认值 |
|
||||
| ------------ | --------- | ---------------- |
|
||||
| `style` | 沟通风格 | 根据领域模板决定 |
|
||||
| `boundaries` | 禁区/红线 | 根据领域模板决定 |
|
||||
| `language` | 主要语言 | 中文 |
|
||||
|
||||
**收集策略**:
|
||||
|
||||
- 优先通过用户的自然描述推断信息
|
||||
- 仅追问用户未提及的必填项
|
||||
- 每轮最多追问 2 个问题
|
||||
|
||||
### 阶段 3:内容生成
|
||||
|
||||
根据收集的需求,组装结构化的 persona 和 principles 数据。**不要输出原始 markdown**,而是按字段整理后向用户展示。
|
||||
|
||||
**Persona 字段**(所有字段均可选,未收集到的由系统自动补全):
|
||||
|
||||
| 层级 | 字段 | 说明 |
|
||||
| ---- | --------------------- | --------------------------------------------- |
|
||||
| L0 | — | 一句话核心身份 |
|
||||
| L1 | `role` | 角色定位 |
|
||||
| L1 | `personality` | 性格特征标签 |
|
||||
| L1 | `communication_style` | 沟通风格 |
|
||||
| L2 | — | 专业领域、核心价值观、决策偏好等(free-form) |
|
||||
|
||||
**Principles 字段**(同样全部可选):
|
||||
|
||||
| 层级 | 字段 | 说明 |
|
||||
| ---- | ---------- | --------------------------------- |
|
||||
| L0 | — | 一句话最高原则 |
|
||||
| L1 | `must_do` | 必须做的事项 |
|
||||
| L1 | `must_not` | 绝不做的事项(安全红线) |
|
||||
| L1 | `priority` | 优先级排序 |
|
||||
| L2 | — | 治理原则、升级规则等(free-form) |
|
||||
|
||||
**领域匹配参考**:
|
||||
|
||||
| 领域关键词 | 推荐 personality | 默认 must_not |
|
||||
| ---------------- | ------------------ | ---------------------------------- |
|
||||
| 法律、合同、法务 | 专业、严谨、审慎 | 不提供诉讼代理、不替代正式法律意见 |
|
||||
| 财务、会计、投资 | 精确、分析性、保守 | 不提供投资建议、不处理真实交易 |
|
||||
| 代码、开发、架构 | 逻辑、务实、直接 | 不直接访问生产环境、不存储凭证 |
|
||||
| 通用/其他 | 友好、有帮助 | 通用安全规范 |
|
||||
|
||||
### 阶段 4:用户确认
|
||||
|
||||
向用户展示预览时,以自然语言/表格形式呈现各字段,**不要展示原始 markdown 源码**:
|
||||
|
||||
> 即将创建智能体:
|
||||
>
|
||||
> **名称**:法律顾问小助手
|
||||
> **描述**:专注于合同审查和法律风险评估的数字智能体
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> **人格设定**
|
||||
>
|
||||
> | 字段 | 内容 |
|
||||
> | -------- | ------------------------------------------------ |
|
||||
> | 核心身份 | 你是法律顾问小助手,专注于合同审查和法律风险评估 |
|
||||
> | 角色定位 | 专注于合同审查和法律风险评估的数字法律顾问 |
|
||||
> | 性格特征 | 专业、严谨、审慎 |
|
||||
> | 沟通风格 | 准确使用法律术语,同时提供通俗解释 |
|
||||
>
|
||||
> **行为原则**
|
||||
>
|
||||
> | 字段 | 内容 |
|
||||
> | -------- | ------------------------------------------------ |
|
||||
> | 最高原则 | 以用户利益为最高优先级,不替代正式法律意见 |
|
||||
> | 必须做 | 准确引用法律条文、标注不确定性、建议咨询专业律师 |
|
||||
> | 绝不做 | 提供诉讼代理、替代正式法律意见、泄露用户咨询内容 |
|
||||
> | 优先级 | 用户安全 > 准确性 > 效率 |
|
||||
>
|
||||
> ---
|
||||
>
|
||||
> 确认创建?(确认 / 修改 / 取消)
|
||||
|
||||
**"修改"分支处理**:
|
||||
|
||||
用户选择"修改"时:
|
||||
|
||||
1. 询问用户要修改哪个字段(如"想修改哪一项?")
|
||||
2. 用户指出要修改的字段(如"性格特征改成更活泼的")
|
||||
3. Agent 重新收集该字段内容
|
||||
4. 更新预览中的对应字段
|
||||
5. 再次展示完整预览 → 重新进入确认流程
|
||||
|
||||
### 阶段 5:调用 API 创建
|
||||
|
||||
**API 端点**:`POST /api/agents`
|
||||
|
||||
**请求体**(结构化格式):
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "法律顾问小助手",
|
||||
"description": "专注于合同审查和法律风险评估的数字智能体",
|
||||
"persona": {
|
||||
"L0": "你是法律顾问小助手,专注于合同审查和法律风险评估的数字智能体。",
|
||||
"L1": {
|
||||
"role": "专注于合同审查和法律风险评估的数字法律顾问",
|
||||
"personality": ["专业", "严谨", "审慎"],
|
||||
"communication_style": "准确使用法律术语,同时提供通俗解释"
|
||||
}
|
||||
},
|
||||
"principles": {
|
||||
"L0": "以用户利益为最高优先级,不替代正式法律意见。",
|
||||
"L1": {
|
||||
"must_do": ["准确引用法律条文", "标注不确定性", "建议咨询专业律师"],
|
||||
"must_not": ["提供诉讼代理", "替代正式法律意见", "泄露用户法律咨询内容"],
|
||||
"priority": "用户安全 > 准确性 > 效率"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**最简创建**(只需 name,其余全部自动生成):
|
||||
|
||||
```json
|
||||
{ "name": "我的助手" }
|
||||
```
|
||||
|
||||
**基础创建**(name + description,description 自动填充 persona L0):
|
||||
|
||||
```json
|
||||
{ "name": "法律顾问", "description": "专注合同审查" }
|
||||
```
|
||||
|
||||
所有未提供的字段由系统自动补全为合理默认值。`persona` 和 `principles` 也支持传入原始 markdown 字符串(向后兼容)。
|
||||
|
||||
**可选**:如需指定 slug ID,可根据 name 生成合理的 kebab-case slug(如 "法律顾问" → "legal-advisor"),在请求体中附带 `"id": "<slug>"`。不指定时系统会自动从 name 生成。
|
||||
|
||||
**成功响应** (`201 Created`):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"agentId": "fa-lv-gu-wen-xiao-zhu-shou",
|
||||
"agent": {
|
||||
"id": "fa-lv-gu-wen-xiao-zhu-shou",
|
||||
"name": "法律顾问小助手",
|
||||
"description": "专注于合同审查和法律风险评估的数字智能体",
|
||||
"skillsCount": 0,
|
||||
"toolsCount": 0,
|
||||
"status": "offline"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
响应中的 `agent` 字段包含创建后的智能体完整信息,可直接用于回执展示。
|
||||
|
||||
### 阶段 6:回执生成
|
||||
|
||||
**回执报告**:
|
||||
|
||||
创建成功后,以用户友好的方式呈现回执(不要暴露内部路径或技术细节):
|
||||
|
||||
> 智能体「法律顾问小助手」已创建成功!
|
||||
>
|
||||
> **下一步你可以**:
|
||||
>
|
||||
> - 直接开始对话
|
||||
> - 为它添加技能,让它更强大
|
||||
> - 调整它的性格或行为规则
|
||||
|
||||
### 背景知识
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| ------ | ------------------------ | ---------------- |
|
||||
| 400 | 缺少 name 或 ID 格式无效 | 提示用户检查输入 |
|
||||
| 409 | Agent ID 已存在 | 建议使用其他名称 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
|
||||
### 权限要求
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 创建操作需要用户确认
|
||||
|
||||
### 依赖
|
||||
|
||||
- Agent Service HTTP API(`POST /api/agents`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 删除智能体
|
||||
name: delete-agent
|
||||
description: 安全删除指定的智能体及其关联数据。删除前会验证智能体状态,支持可选地删除所有会话历史。Use when 用户需要删除不再使用的智能体。
|
||||
version: 2.4.2
|
||||
type: meta
|
||||
@@ -13,6 +13,27 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-02-28'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 删除智能体
|
||||
short_desc: 安全删除智能体及其关联数据,支持多重确认与可选历史清理
|
||||
description: 安全删除指定的智能体及其关联数据。删除前会验证智能体状态,支持可选地删除所有会话历史。Use when 用户需要删除不再使用的智能体。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:148cd72a6808741e
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Delete Agent
|
||||
short_desc: Safely delete an Agent and its associated data, with multi-step confirmation and optional history cleanup
|
||||
description: Safely delete a specified Agent and its associated data. Verifies the Agent's state before deletion and optionally removes all session history. Use when the user needs to delete an Agent that is no longer in use.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:148cd72a6808741e
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -25,7 +46,6 @@ market:
|
||||
stroke-width="1.5"/><circle cx="19" cy="11" r="4" fill="#FF3B30"
|
||||
fill-opacity="0.12"/><line x1="16.5" y1="11" x2="21.5" y2="11"
|
||||
stroke="#FF3B30" stroke-width="2" stroke-linecap="round"/></svg>
|
||||
short_desc: 安全删除智能体及其关联数据,支持多重确认与可选历史清理
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -34,135 +54,136 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# delete-agent 技能
|
||||
# delete-agent Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
安全删除指定的智能体及其关联数据,包括文件系统、内存状态和可选的会话历史。
|
||||
Safely delete a specified Agent and its associated data, including filesystem, in-memory state, and optionally session history.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
delete-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 安全删除其他智能体的能力。它会执行完整的前置检查、状态验证,并清理所有关联数据。
|
||||
delete-agent is a **Meta-Skill** that empowers DesireCore to safely delete other Agents. It performs full pre-flight checks and state validation, and cleans up all associated data.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想要清理不再使用的智能体
|
||||
- 删除测试或实验性质的临时智能体
|
||||
- 释放存储空间,删除旧智能体及其历史记录
|
||||
- 用户明确要求"删除"、"移除"某个智能体
|
||||
- The user wants to clean up Agents that are no longer in use
|
||||
- Delete temporary Agents created for testing or experimentation
|
||||
- Free up storage space by deleting old Agents and their history
|
||||
- The user explicitly asks to "delete" or "remove" a particular Agent
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **安全性**:多重检查确保不会误删活跃智能体
|
||||
- **完整性**:清理文件系统、内存状态、消息订阅等所有关联数据
|
||||
- **可恢复性**:默认保留会话历史,可选择是否删除
|
||||
- **Safety**: multiple checks ensure that active Agents are not accidentally deleted
|
||||
- **Completeness**: cleans up filesystem, in-memory state, message subscriptions, and all associated data
|
||||
- **Recoverability**: session history is preserved by default, with the option to delete it
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 执行流程
|
||||
### Execution Flow
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 列出可选 │ ──→ │ 确认意图 │ ──→ │ 询问选项 │
|
||||
│ 智能体 │ │ 与目标 │ │ (删除历史?) │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│ List target │ ──→ │ Confirm │ ──→ │ Ask about │
|
||||
│ Agents │ │ intent/target│ │ options │
|
||||
└──────────────┘ └──────────────┘ │ (delete runs?)│
|
||||
└──────────────┘
|
||||
│
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 返回结果 │ ←── │ 执行删除 │ ←── │ 最终确认 │
|
||||
│ 与回执 │ │ API 调用 │ │ │
|
||||
│ Return result│ ←── │ Execute the │ ←── │ Final │
|
||||
│ and receipt │ │ delete API │ │ confirmation │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:列出可删除的智能体
|
||||
### Phase 1: List Deletable Agents
|
||||
|
||||
**触发条件**:用户表达删除意图但未指定具体智能体
|
||||
**Trigger condition**: the user expresses intent to delete but does not specify a particular Agent
|
||||
|
||||
**操作**:
|
||||
**Operation**:
|
||||
|
||||
- 调用 `GET /api/agents` 获取所有智能体列表
|
||||
- 筛选出状态为 `offline` 或 `error` 的智能体(可安全删除)
|
||||
- 标注出 `online`/`busy`/`recovery` 状态的智能体(需先停止)
|
||||
- Call `GET /api/agents` to fetch the list of all Agents
|
||||
- Filter Agents whose status is `offline` or `error` (safe to delete)
|
||||
- Annotate Agents whose status is `online`/`busy`/`recovery` (must be stopped first)
|
||||
|
||||
**输出示例**:
|
||||
**Output example**:
|
||||
|
||||
```
|
||||
可删除的智能体:
|
||||
1. 法律顾问助手 (legal-assistant) - 状态: offline
|
||||
2. 测试机器人 (test-bot) - 状态: offline
|
||||
Deletable Agents:
|
||||
1. Legal Advisor Assistant (legal-assistant) - status: offline
|
||||
2. Test Bot (test-bot) - status: offline
|
||||
|
||||
当前活跃的智能体(需先停止才能删除):
|
||||
- 数据分析师 (data-analyst) - 状态: online
|
||||
Currently active Agents (must be stopped before deletion):
|
||||
- Data Analyst (data-analyst) - status: online
|
||||
```
|
||||
|
||||
### 阶段 2:确认用户意图与目标
|
||||
### Phase 2: Confirm User Intent and Target
|
||||
|
||||
**确认要点**:
|
||||
**Confirmation points**:
|
||||
|
||||
- 用户指定的智能体名称/ID
|
||||
- 明确告知删除操作不可恢复
|
||||
- 展示智能体基本信息供用户确认
|
||||
- The Agent name/ID specified by the user
|
||||
- Explicitly inform that deletion is irreversible
|
||||
- Display the Agent's basic info for the user to confirm
|
||||
|
||||
**对话示例**:
|
||||
**Dialog example**:
|
||||
|
||||
```
|
||||
您要删除智能体 "法律顾问助手" (legal-assistant)。
|
||||
⚠️ 警告:此操作不可恢复,该智能体的所有配置、技能、工具将被永久删除。
|
||||
You are about to delete the Agent "Legal Advisor Assistant" (legal-assistant).
|
||||
⚠️ Warning: this operation is irreversible. All configuration, skills, and tools of this Agent will be permanently deleted.
|
||||
|
||||
确认删除?(是/否)
|
||||
Confirm deletion? (yes/no)
|
||||
```
|
||||
|
||||
### 阶段 3:询问删除选项
|
||||
### Phase 3: Ask About Deletion Options
|
||||
|
||||
**询问内容**:
|
||||
**Question content**:
|
||||
|
||||
```
|
||||
是否同时删除该智能体的所有会话历史?
|
||||
- 是:删除智能体及其所有对话记录
|
||||
- 否:保留会话历史,仅删除智能体本身
|
||||
Do you also want to delete all session history of this Agent?
|
||||
- Yes: delete the Agent and all of its conversation records
|
||||
- No: keep session history; delete only the Agent itself
|
||||
|
||||
默认选项:否(保留历史)
|
||||
Default option: No (keep history)
|
||||
```
|
||||
|
||||
**参数映射**:
|
||||
**Parameter mapping**:
|
||||
|
||||
- 用户选择"是" → `deleteRuns=true`
|
||||
- 用户选择"否" → `deleteRuns=false`(默认)
|
||||
- User chooses "Yes" → `deleteRuns=true`
|
||||
- User chooses "No" → `deleteRuns=false` (default)
|
||||
|
||||
### 阶段 4:最终确认
|
||||
### Phase 4: Final Confirmation
|
||||
|
||||
**确认摘要**:
|
||||
**Confirmation summary**:
|
||||
|
||||
```
|
||||
请确认删除操作:
|
||||
- 目标智能体:法律顾问助手 (legal-assistant)
|
||||
- 删除范围:智能体 + 会话历史(如用户选择)
|
||||
- 风险等级:高(不可恢复)
|
||||
Please confirm the deletion:
|
||||
- Target Agent: Legal Advisor Assistant (legal-assistant)
|
||||
- Scope: Agent + session history (if chosen by the user)
|
||||
- Risk level: High (irreversible)
|
||||
|
||||
确认执行删除?(是/否)
|
||||
Confirm and execute deletion? (yes/no)
|
||||
```
|
||||
|
||||
### 阶段 5:执行删除 API 调用
|
||||
### Phase 5: Execute the Delete API Call
|
||||
|
||||
**API 端点**:`DELETE /api/agents/{agentId}`
|
||||
**API endpoint**: `DELETE /api/agents/{agentId}`
|
||||
|
||||
**查询参数**:
|
||||
**Query parameters**:
|
||||
|
||||
- `deleteRuns`: `'true'` 或 `'false'`
|
||||
- `deleteRuns`: `'true'` or `'false'`
|
||||
|
||||
**请求示例**:
|
||||
**Request example**:
|
||||
|
||||
```bash
|
||||
curl -X DELETE "{agentServiceUrl}/api/agents/legal-assistant?deleteRuns=true"
|
||||
```
|
||||
|
||||
> `{agentServiceUrl}` 取自 system prompt「本机 API」小节中的 Agent Service 地址。
|
||||
> `{agentServiceUrl}` is taken from the Agent Service address in the "Local API" section of the system prompt.
|
||||
|
||||
### 阶段 6:返回操作结果
|
||||
### Phase 6: Return the Operation Result
|
||||
|
||||
**成功响应处理**:
|
||||
**Successful response handling**:
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -181,64 +202,64 @@ curl -X DELETE "{agentServiceUrl}/api/agents/legal-assistant?deleteRuns=true"
|
||||
}
|
||||
```
|
||||
|
||||
**结果报告模板**:
|
||||
**Result report template**:
|
||||
|
||||
```
|
||||
✅ 智能体 "法律顾问助手" 已成功删除
|
||||
✅ Agent "Legal Advisor Assistant" successfully deleted
|
||||
|
||||
清理详情:
|
||||
- 文件系统:已删除 2 个目录
|
||||
- 调度器:已停止所有定时任务
|
||||
- 消息订阅:已取消 3 个订阅
|
||||
- MCP 连接:已关闭
|
||||
- 会话历史:已删除 5 条记录
|
||||
Cleanup details:
|
||||
- Filesystem: 2 directories deleted
|
||||
- Scheduler: all scheduled tasks stopped
|
||||
- Message subscriptions: 3 subscriptions canceled
|
||||
- MCP connection: closed
|
||||
- Session history: 5 records deleted
|
||||
```
|
||||
|
||||
## 状态验证与错误处理
|
||||
## State Validation and Error Handling
|
||||
|
||||
### 删除前状态检查
|
||||
### Pre-deletion State Check
|
||||
|
||||
在阶段 1 列出智能体时,通过 `GET /api/agents` 筛选状态:
|
||||
When listing Agents in Phase 1, filter status via `GET /api/agents`:
|
||||
|
||||
| 状态 | 可否删除 | 阶段 1 展示方式 |
|
||||
| Status | Deletable? | Phase 1 Display |
|
||||
| ------------------------------ | ----------- | ------------------------------ |
|
||||
| `offline` / `error` | ✅ 可删除 | 列入"可删除"列表 |
|
||||
| `online` / `busy` / `recovery` | ❌ 需先停止 | 标注"需先停止",不进入后续流程 |
|
||||
| `offline` / `error` | ✅ Yes | Listed under "Deletable" |
|
||||
| `online` / `busy` / `recovery` | ❌ Stop first | Annotated "must be stopped"; not entered into the subsequent flow |
|
||||
|
||||
**停止活跃智能体的方式**:通过 Socket.IO 发送 `agent:shutdown` 事件:
|
||||
**How to stop an active Agent**: send the `agent:shutdown` event via Socket.IO:
|
||||
|
||||
```yaml
|
||||
事件: agent:shutdown
|
||||
数据: { 'agentId': '<agent_id>' }
|
||||
效果: 中止所有活跃会话 → 停止调度任务 → 状态转为 offline
|
||||
event: agent:shutdown
|
||||
data: { 'agentId': '<agent_id>' }
|
||||
effect: abort all active sessions → stop scheduled tasks → status becomes offline
|
||||
```
|
||||
|
||||
> Agent 无法直接发送 Socket.IO 事件。如果目标智能体处于活跃状态,应提示用户在 UI 中手动停止,或等待其完成当前任务后再删除。
|
||||
> The Agent cannot directly send Socket.IO events. If the target Agent is active, prompt the user to stop it manually in the UI, or wait until it finishes its current task before deleting.
|
||||
|
||||
### API 错误码
|
||||
### API Error Codes
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| ------ | ---------------------------------------------------------------------------- | -------------------------------- |
|
||||
| 400 | Agent ID 格式无效 | 提示用户检查智能体名称 |
|
||||
| 404 | 智能体不存在 | 告知用户智能体已被删除或 ID 错误 |
|
||||
| 409 | 智能体处于活跃状态(API 返回 `Cannot delete agent "xxx": currently online`) | 提示用户先在 UI 中停止智能体 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
| Code | Scenario | Handling |
|
||||
| ------ | ---------------------------------------------------------------------------- | --------------------------------- |
|
||||
| 400 | Invalid Agent ID format | Ask the user to check the Agent name |
|
||||
| 404 | Agent does not exist | Inform the user the Agent has already been deleted or the ID is wrong |
|
||||
| 409 | Agent is currently active (API returns `Cannot delete agent "xxx": currently online`) | Ask the user to stop the Agent in the UI first |
|
||||
| 500 | Internal server error | Ask the user to try again later |
|
||||
|
||||
## 删除范围说明
|
||||
## Deletion Scope
|
||||
|
||||
| 类别 | 删除内容 | 条件 |
|
||||
| Category | Content Deleted | Condition |
|
||||
| ------------ | -------------------------------------------------------------------------------------------------------------------------- | ----------------- |
|
||||
| **始终删除** | AgentFS 目录(配置、人格、规则、技能、工具、记忆)、用户偏好数据、内存状态(调度器、队列、消息订阅、MCP 连接)、注册表条目 | 无条件 |
|
||||
| **可选删除** | 会话历史、话题索引 | `deleteRuns=true` |
|
||||
| **保留不删** | 其他智能体数据、用户配置、全局设置、市场缓存 | — |
|
||||
| **Always deleted** | AgentFS directory (config, persona, rules, skills, tools, memory), user preference data, in-memory state (scheduler, queue, message subscriptions, MCP connection), registry entries | Unconditional |
|
||||
| **Optionally deleted** | Session history, topic index | `deleteRuns=true` |
|
||||
| **Preserved** | Data of other Agents, user configuration, global settings, market cache | — |
|
||||
|
||||
## 权限要求
|
||||
## Permission Requirements
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 删除操作需要用户显式确认(高风险操作)
|
||||
- Prefer using the `Bash` tool to call curl against the Agent Service HTTP API to perform the operation
|
||||
- The API base address is injected into the "Local API" section of the system prompt; reference it directly
|
||||
- The delete operation requires explicit user confirmation (high-risk operation)
|
||||
|
||||
## 依赖
|
||||
## Dependencies
|
||||
|
||||
- Agent Service HTTP API(`DELETE /api/agents/{agentId}`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
- Agent Service HTTP API (`DELETE /api/agents/{agentId}`)
|
||||
- The Local API address declaration in the system prompt
|
||||
|
||||
210
skills/delete-agent/SKILL.zh-CN.md
Normal file
210
skills/delete-agent/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,210 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# delete-agent 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
安全删除指定的智能体及其关联数据,包括文件系统、内存状态和可选的会话历史。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
delete-agent 是一个**元技能(Meta-Skill)**,赋予 DesireCore 安全删除其他智能体的能力。它会执行完整的前置检查、状态验证,并清理所有关联数据。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想要清理不再使用的智能体
|
||||
- 删除测试或实验性质的临时智能体
|
||||
- 释放存储空间,删除旧智能体及其历史记录
|
||||
- 用户明确要求"删除"、"移除"某个智能体
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **安全性**:多重检查确保不会误删活跃智能体
|
||||
- **完整性**:清理文件系统、内存状态、消息订阅等所有关联数据
|
||||
- **可恢复性**:默认保留会话历史,可选择是否删除
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 执行流程
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 列出可选 │ ──→ │ 确认意图 │ ──→ │ 询问选项 │
|
||||
│ 智能体 │ │ 与目标 │ │ (删除历史?) │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 返回结果 │ ←── │ 执行删除 │ ←── │ 最终确认 │
|
||||
│ 与回执 │ │ API 调用 │ │ │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:列出可删除的智能体
|
||||
|
||||
**触发条件**:用户表达删除意图但未指定具体智能体
|
||||
|
||||
**操作**:
|
||||
|
||||
- 调用 `GET /api/agents` 获取所有智能体列表
|
||||
- 筛选出状态为 `offline` 或 `error` 的智能体(可安全删除)
|
||||
- 标注出 `online`/`busy`/`recovery` 状态的智能体(需先停止)
|
||||
|
||||
**输出示例**:
|
||||
|
||||
```
|
||||
可删除的智能体:
|
||||
1. 法律顾问助手 (legal-assistant) - 状态: offline
|
||||
2. 测试机器人 (test-bot) - 状态: offline
|
||||
|
||||
当前活跃的智能体(需先停止才能删除):
|
||||
- 数据分析师 (data-analyst) - 状态: online
|
||||
```
|
||||
|
||||
### 阶段 2:确认用户意图与目标
|
||||
|
||||
**确认要点**:
|
||||
|
||||
- 用户指定的智能体名称/ID
|
||||
- 明确告知删除操作不可恢复
|
||||
- 展示智能体基本信息供用户确认
|
||||
|
||||
**对话示例**:
|
||||
|
||||
```
|
||||
您要删除智能体 "法律顾问助手" (legal-assistant)。
|
||||
⚠️ 警告:此操作不可恢复,该智能体的所有配置、技能、工具将被永久删除。
|
||||
|
||||
确认删除?(是/否)
|
||||
```
|
||||
|
||||
### 阶段 3:询问删除选项
|
||||
|
||||
**询问内容**:
|
||||
|
||||
```
|
||||
是否同时删除该智能体的所有会话历史?
|
||||
- 是:删除智能体及其所有对话记录
|
||||
- 否:保留会话历史,仅删除智能体本身
|
||||
|
||||
默认选项:否(保留历史)
|
||||
```
|
||||
|
||||
**参数映射**:
|
||||
|
||||
- 用户选择"是" → `deleteRuns=true`
|
||||
- 用户选择"否" → `deleteRuns=false`(默认)
|
||||
|
||||
### 阶段 4:最终确认
|
||||
|
||||
**确认摘要**:
|
||||
|
||||
```
|
||||
请确认删除操作:
|
||||
- 目标智能体:法律顾问助手 (legal-assistant)
|
||||
- 删除范围:智能体 + 会话历史(如用户选择)
|
||||
- 风险等级:高(不可恢复)
|
||||
|
||||
确认执行删除?(是/否)
|
||||
```
|
||||
|
||||
### 阶段 5:执行删除 API 调用
|
||||
|
||||
**API 端点**:`DELETE /api/agents/{agentId}`
|
||||
|
||||
**查询参数**:
|
||||
|
||||
- `deleteRuns`: `'true'` 或 `'false'`
|
||||
|
||||
**请求示例**:
|
||||
|
||||
```bash
|
||||
curl -X DELETE "{agentServiceUrl}/api/agents/legal-assistant?deleteRuns=true"
|
||||
```
|
||||
|
||||
> `{agentServiceUrl}` 取自 system prompt「本机 API」小节中的 Agent Service 地址。
|
||||
|
||||
### 阶段 6:返回操作结果
|
||||
|
||||
**成功响应处理**:
|
||||
|
||||
```json
|
||||
{
|
||||
"deleted": true,
|
||||
"cleanedPaths": [
|
||||
"/Users/xxx/.desirecore/agents/legal-assistant",
|
||||
"/Users/xxx/.desirecore/users/xxx/agents/legal-assistant"
|
||||
],
|
||||
"deletedRunsCount": 5,
|
||||
"memoryCleaned": {
|
||||
"scheduler": true,
|
||||
"queue": 0,
|
||||
"messaging": 3,
|
||||
"mcp": true
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
**结果报告模板**:
|
||||
|
||||
```
|
||||
✅ 智能体 "法律顾问助手" 已成功删除
|
||||
|
||||
清理详情:
|
||||
- 文件系统:已删除 2 个目录
|
||||
- 调度器:已停止所有定时任务
|
||||
- 消息订阅:已取消 3 个订阅
|
||||
- MCP 连接:已关闭
|
||||
- 会话历史:已删除 5 条记录
|
||||
```
|
||||
|
||||
## 状态验证与错误处理
|
||||
|
||||
### 删除前状态检查
|
||||
|
||||
在阶段 1 列出智能体时,通过 `GET /api/agents` 筛选状态:
|
||||
|
||||
| 状态 | 可否删除 | 阶段 1 展示方式 |
|
||||
| ------------------------------ | ----------- | ------------------------------ |
|
||||
| `offline` / `error` | ✅ 可删除 | 列入"可删除"列表 |
|
||||
| `online` / `busy` / `recovery` | ❌ 需先停止 | 标注"需先停止",不进入后续流程 |
|
||||
|
||||
**停止活跃智能体的方式**:通过 Socket.IO 发送 `agent:shutdown` 事件:
|
||||
|
||||
```yaml
|
||||
事件: agent:shutdown
|
||||
数据: { 'agentId': '<agent_id>' }
|
||||
效果: 中止所有活跃会话 → 停止调度任务 → 状态转为 offline
|
||||
```
|
||||
|
||||
> Agent 无法直接发送 Socket.IO 事件。如果目标智能体处于活跃状态,应提示用户在 UI 中手动停止,或等待其完成当前任务后再删除。
|
||||
|
||||
### API 错误码
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| ------ | ---------------------------------------------------------------------------- | -------------------------------- |
|
||||
| 400 | Agent ID 格式无效 | 提示用户检查智能体名称 |
|
||||
| 404 | 智能体不存在 | 告知用户智能体已被删除或 ID 错误 |
|
||||
| 409 | 智能体处于活跃状态(API 返回 `Cannot delete agent "xxx": currently online`) | 提示用户先在 UI 中停止智能体 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
|
||||
## 删除范围说明
|
||||
|
||||
| 类别 | 删除内容 | 条件 |
|
||||
| ------------ | -------------------------------------------------------------------------------------------------------------------------- | ----------------- |
|
||||
| **始终删除** | AgentFS 目录(配置、人格、规则、技能、工具、记忆)、用户偏好数据、内存状态(调度器、队列、消息订阅、MCP 连接)、注册表条目 | 无条件 |
|
||||
| **可选删除** | 会话历史、话题索引 | `deleteRuns=true` |
|
||||
| **保留不删** | 其他智能体数据、用户配置、全局设置、市场缓存 | — |
|
||||
|
||||
## 权限要求
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 删除操作需要用户显式确认(高风险操作)
|
||||
|
||||
## 依赖
|
||||
|
||||
- Agent Service HTTP API(`DELETE /api/agents/{agentId}`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 开发环境综合配置
|
||||
name: dev-environment-setup
|
||||
description: >-
|
||||
Use this skill as a router/index when the user faces a development
|
||||
environment question that spans multiple domains: containers
|
||||
@@ -28,6 +28,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-02'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 开发环境综合配置
|
||||
short_desc: 开发环境综合入口(容器 / WSL / 办公依赖 / 系统工具)
|
||||
description: >-
|
||||
Use this skill as a router/index when the user faces a development environment question that spans multiple domains: containers (Docker/Podman), WSL2 on Windows, office-skill dependencies (DOCX/PDF/XLSX/ PPTX), or system tools (LibreOffice/Poppler/Pandoc/Tesseract). For pure Python issues use python-runtime skill; for pure Node.js issues use nodejs-runtime skill. Triggers include: "setup environment", "PATH", "WSL", "WSL2", "docker not found", "podman", "container", "office dependency", "LibreOffice", "poppler", "pandoc", "tesseract", or any cross-cutting environment question. 使用场景:用户提到 环境配置、PATH、 容器、Docker、Podman、WSL、WSL2、办公依赖、系统工具,或不确定属于 Python / Node.js 时的入口指引。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:7e4baaf42d5c0ace
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Dev Environment Setup
|
||||
short_desc: Unified dev environment entry (container / WSL / office deps / system tools)
|
||||
description: >-
|
||||
Use this skill as a router/index when the user faces a development environment question that spans multiple domains: containers (Docker/Podman), WSL2 on Windows, office-skill dependencies (DOCX/PDF/XLSX/ PPTX), or system tools (LibreOffice/Poppler/Pandoc/Tesseract). For pure Python issues use python-runtime skill; for pure Node.js issues use nodejs-runtime skill. Triggers include: "setup environment", "PATH", "WSL", "WSL2", "docker not found", "podman", "container", "office dependency", "LibreOffice", "poppler", "pandoc", "tesseract", or any cross-cutting environment question. Use when the user mentions environment setup, PATH, containers, Docker, Podman, WSL, WSL2, office dependencies, system tools, or needs an entry-point guide when uncertain whether the issue belongs to Python or Node.js.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:7e4baaf42d5c0ace
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -39,7 +62,6 @@ market:
|
||||
stroke="url(#env-a)" stroke-width="1.5" stroke-linecap="round"
|
||||
stroke-linejoin="round"/><path d="M13 16h4" stroke="url(#env-a)"
|
||||
stroke-width="1.5" stroke-linecap="round"/></svg>
|
||||
short_desc: 开发环境综合入口(容器 / WSL / 办公依赖 / 系统工具)
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -47,94 +69,94 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# dev-environment-setup 技能(v2.0.0 router)
|
||||
# dev-environment-setup Skill (v2.0.0 router)
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
**何时使用**:用户需要
|
||||
**When to use**: The user needs to
|
||||
|
||||
- 安装 / 排查 **Docker** 或 **Podman** 容器("docker not found"、daemon 启动、镜像加速等)
|
||||
- 在 Windows 上配置 **WSL2**(Linux 子系统)
|
||||
- 一次性安装 **办公技能依赖**(DOCX / PDF / XLSX / PPTX 所需的 Python 包 + npm 包 + 系统工具)
|
||||
- 安装 **系统工具**:LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript / Git
|
||||
- **不确定** 问题属于 Python 还是 Node.js,需要先做综合诊断
|
||||
- Install / troubleshoot **Docker** or **Podman** containers ("docker not found", daemon startup, registry mirror, etc.)
|
||||
- Configure **WSL2** (Linux Subsystem) on Windows
|
||||
- One-shot install of **office skill dependencies** (Python packages + npm packages + system tools required by DOCX / PDF / XLSX / PPTX)
|
||||
- Install **system tools**: LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript / Git
|
||||
- **Uncertain** whether the issue belongs to Python or Node.js, and a comprehensive diagnosis is needed first
|
||||
|
||||
**何时不要用**:纯 Python 问题用 `python-runtime`,纯 Node.js 问题用 `nodejs-runtime`。
|
||||
**When not to use**: Use `python-runtime` for pure Python issues, and `nodejs-runtime` for pure Node.js issues.
|
||||
|
||||
**怎么做**:先跑 `scripts/probe.sh`(Windows 用 `probe.ps1`)取系统快照 JSON,
|
||||
按结果路由到对应 references 或子 skill;同时也是 DesireCore 内置 Hatch / Volta /
|
||||
HTTP API / Socket.IO 集成的事实源(`references/desirecore-runtime.md`)。
|
||||
**How to do it**: First run `scripts/probe.sh` (use `probe.ps1` on Windows) to obtain a system snapshot JSON,
|
||||
and route to the corresponding references or sub-skill based on the result; this skill is also the source of truth
|
||||
for DesireCore's built-in Hatch / Volta / HTTP API / Socket.IO integration (`references/desirecore-runtime.md`).
|
||||
|
||||
## L1:路由规则
|
||||
## L1: Routing Rules
|
||||
|
||||
按用户问题的关键字直接转到对应 skill 或文档:
|
||||
Route directly to the corresponding skill or document by the keywords in the user's question:
|
||||
|
||||
| 关键字 / 场景 | 路径 |
|
||||
| Keyword / Scenario | Path |
|
||||
|--------------|------|
|
||||
| python / pip / venv / pyenv / hatch / virtualenv / PEP 668 | `python-runtime` skill |
|
||||
| node / npm / pnpm / yarn / volta / nvm / fnm / EACCES | `nodejs-runtime` skill |
|
||||
| docker / podman / container / 容器守护进程 | `references/container.md` |
|
||||
| WSL / WSL2 / Windows Linux 子系统 | `references/wsl.md` |
|
||||
| DOCX / PDF / XLSX / PPTX 依赖 / 办公技能依赖 | `references/office-deps.md` |
|
||||
| docker / podman / container / container daemon | `references/container.md` |
|
||||
| WSL / WSL2 / Windows Linux Subsystem | `references/wsl.md` |
|
||||
| DOCX / PDF / XLSX / PPTX dependencies / office skill dependencies | `references/office-deps.md` |
|
||||
| LibreOffice / poppler / pandoc / tesseract / qpdf | `references/system-tools.md` |
|
||||
| 不确定属于哪类、想要快速诊断 | 先跑 `scripts/probe.sh` 看 JSON |
|
||||
| Unsure of category, want a quick diagnosis | First run `scripts/probe.sh` and inspect the JSON |
|
||||
| DesireCore Hatch / Volta / HTTP API / Socket.IO | `references/desirecore-runtime.md` |
|
||||
| 四级降级决策(API → CLI → 包管理器 → 社区方案) | `references/decision-tree.md` |
|
||||
| Four-tier fallback decision (API → CLI → package manager → community solution) | `references/decision-tree.md` |
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 第一步:快速诊断
|
||||
### Step 1: Quick Diagnosis
|
||||
|
||||
```bash
|
||||
bash skills/dev-environment-setup/scripts/probe.sh > /tmp/env-probe.json
|
||||
cat /tmp/env-probe.json | jq .
|
||||
```
|
||||
|
||||
输出字段含义:见 `references/probe-snapshot.md`。Windows 用 `scripts/probe.ps1`。
|
||||
For the meaning of output fields, see `references/probe-snapshot.md`. On Windows use `scripts/probe.ps1`.
|
||||
|
||||
### 第二步:按结果路由
|
||||
### Step 2: Route by Result
|
||||
|
||||
- `desirecore_api` 非空 → 走 HTTP API 路径(`references/desirecore-runtime.md`)
|
||||
- `tools.python3.available = false` 或 `tools.node.available = false` → 进入对应子 skill
|
||||
- `tools.docker.available = false` 且用户需容器 → `references/container.md`
|
||||
- `wsl.installed = false` 且 Windows 用户 → `references/wsl.md`
|
||||
- `desirecore_api` non-empty → take the HTTP API path (`references/desirecore-runtime.md`)
|
||||
- `tools.python3.available = false` or `tools.node.available = false` → enter the corresponding sub-skill
|
||||
- `tools.docker.available = false` and the user needs containers → `references/container.md`
|
||||
- `wsl.installed = false` and Windows user → `references/wsl.md`
|
||||
|
||||
### 第三步:执行子 skill 决策树
|
||||
### Step 3: Execute the Sub-skill Decision Tree
|
||||
|
||||
`python-runtime` 与 `nodejs-runtime` 都有自己的四级降级(L1 API → L2 内置 CLI → L3 系统包管理器 → L4 社区方案),定义在共享的 `references/decision-tree.md`。
|
||||
Both `python-runtime` and `nodejs-runtime` have their own four-tier fallback (L1 API → L2 built-in CLI → L3 system package manager → L4 community solution), defined in the shared `references/decision-tree.md`.
|
||||
|
||||
### 第四步:办公技能依赖
|
||||
### Step 4: Office Skill Dependencies
|
||||
|
||||
办公四件套(DOCX / PDF / XLSX / PPTX)依赖速查:`references/office-deps.md`。包含 Python 包、npm 包、系统工具的一键安装命令。
|
||||
Quick lookup for the office quartet (DOCX / PDF / XLSX / PPTX) dependencies: `references/office-deps.md`. Includes one-shot install commands for Python packages, npm packages, and system tools.
|
||||
|
||||
### 第五步:系统工具
|
||||
### Step 5: System Tools
|
||||
|
||||
LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript 安装与故障排查:`references/system-tools.md`。
|
||||
Installation and troubleshooting for LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript: `references/system-tools.md`.
|
||||
|
||||
## DesireCore 内置环境管理底座
|
||||
## DesireCore Built-in Environment Management Base
|
||||
|
||||
DesireCore 内置 Hatch(Python)和 Volta(Node.js),通过 HTTP API + Socket.IO 提供完整的环境管理能力。本 skill 与子 skill(python/nodejs)都依赖:
|
||||
DesireCore embeds Hatch (Python) and Volta (Node.js), providing complete environment management via HTTP API + Socket.IO. This skill and the sub-skills (python/nodejs) all rely on:
|
||||
|
||||
| 文档 | 内容 |
|
||||
| Document | Content |
|
||||
|------|------|
|
||||
| `references/desirecore-runtime.md` | 二进制路径表、HTTP API 速查、Socket.IO 事件契约、`EnvironmentSnapshot` 数据结构 |
|
||||
| `references/decision-tree.md` | 四级降级流程图、判定失败的具体信号、切换提示 |
|
||||
| `references/probe-snapshot.md` | 探测脚本 JSON 输出协议 |
|
||||
| `references/desirecore-runtime.md` | Binary path table, HTTP API quick-reference, Socket.IO event contracts, `EnvironmentSnapshot` data structure |
|
||||
| `references/decision-tree.md` | Four-tier fallback flowchart, concrete signals for failure detection, switch prompts |
|
||||
| `references/probe-snapshot.md` | Probe script JSON output protocol |
|
||||
|
||||
## 重要约束
|
||||
## Important Constraints
|
||||
|
||||
1. **不要把 python / node / pip / npm 强关键词写入本 skill description**——这些归属各自的子 skill,避免触发冲突。
|
||||
2. **API 优先**:`scripts/probe.sh` 第一步检测 `~/.desirecore/agent-service.port`;存在则推荐 HTTP API 路径。
|
||||
3. **缓存协同**:任何安装/移除完成后,调 `POST /api/runtime/environment/refresh` 失效缓存,再发后续 GET。
|
||||
4. **跨平台**:所有命令模板提供 macOS / Linux + Windows(PowerShell)双版本。
|
||||
1. **Do not write strong keywords like python / node / pip / npm into this skill's description**—those belong to their respective sub-skills, to avoid trigger conflicts.
|
||||
2. **API first**: `scripts/probe.sh` first checks `~/.desirecore/agent-service.port`; if it exists, recommend the HTTP API path.
|
||||
3. **Cache coherence**: after any install/uninstall completes, call `POST /api/runtime/environment/refresh` to invalidate the cache before issuing subsequent GETs.
|
||||
4. **Cross-platform**: every command template provides both macOS / Linux and Windows (PowerShell) versions.
|
||||
|
||||
## 子 skill 与文档清单
|
||||
## Sub-skill and Document Manifest
|
||||
|
||||
```
|
||||
skills/
|
||||
├── python-runtime/ # Python 环境(Hatch 优先)
|
||||
├── nodejs-runtime/ # Node.js 环境(Volta 优先)
|
||||
└── dev-environment-setup/ # 本 skill(综合入口)
|
||||
├── python-runtime/ # Python environment (Hatch first)
|
||||
├── nodejs-runtime/ # Node.js environment (Volta first)
|
||||
└── dev-environment-setup/ # This skill (composite entry)
|
||||
├── references/
|
||||
│ ├── desirecore-runtime.md
|
||||
│ ├── decision-tree.md
|
||||
@@ -148,12 +170,12 @@ skills/
|
||||
└── probe.ps1
|
||||
```
|
||||
|
||||
## 升级说明(v1.x → v2.0.0)
|
||||
## Upgrade Notes (v1.x → v2.0.0)
|
||||
|
||||
- v1.x 是单文件 1380 行的全能手册,已拆分。
|
||||
- Python 相关 → `python-runtime`
|
||||
- Node.js 相关 → `nodejs-runtime`
|
||||
- Docker / WSL / 办公依赖 / 系统工具 → 本 skill 的 `references/`
|
||||
- DesireCore Hatch / Volta 从"可选社区方案"升级为强制 L1/L2 主路径
|
||||
- v1.x was a 1380-line all-in-one manual, now split.
|
||||
- Python-related → `python-runtime`
|
||||
- Node.js-related → `nodejs-runtime`
|
||||
- Docker / WSL / office dependencies / system tools → this skill's `references/`
|
||||
- DesireCore Hatch / Volta upgraded from "optional community solution" to mandatory L1/L2 primary path
|
||||
|
||||
下游 skill(docx / pdf / xlsx / pptx)应将 "Python 环境问题请参考 dev-environment-setup" 改写为 "Python 环境问题请参考 python-runtime / Node.js 环境问题请参考 nodejs-runtime"。
|
||||
Downstream skills (docx / pdf / xlsx / pptx) should rewrite "for Python environment issues, see dev-environment-setup" to "for Python environment issues, see python-runtime / for Node.js environment issues, see nodejs-runtime".
|
||||
|
||||
112
skills/dev-environment-setup/SKILL.zh-CN.md
Normal file
112
skills/dev-environment-setup/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,112 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# dev-environment-setup 技能(v2.0.0 router)
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
**何时使用**:用户需要
|
||||
|
||||
- 安装 / 排查 **Docker** 或 **Podman** 容器("docker not found"、daemon 启动、镜像加速等)
|
||||
- 在 Windows 上配置 **WSL2**(Linux 子系统)
|
||||
- 一次性安装 **办公技能依赖**(DOCX / PDF / XLSX / PPTX 所需的 Python 包 + npm 包 + 系统工具)
|
||||
- 安装 **系统工具**:LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript / Git
|
||||
- **不确定** 问题属于 Python 还是 Node.js,需要先做综合诊断
|
||||
|
||||
**何时不要用**:纯 Python 问题用 `python-runtime`,纯 Node.js 问题用 `nodejs-runtime`。
|
||||
|
||||
**怎么做**:先跑 `scripts/probe.sh`(Windows 用 `probe.ps1`)取系统快照 JSON,
|
||||
按结果路由到对应 references 或子 skill;同时也是 DesireCore 内置 Hatch / Volta /
|
||||
HTTP API / Socket.IO 集成的事实源(`references/desirecore-runtime.md`)。
|
||||
|
||||
## L1:路由规则
|
||||
|
||||
按用户问题的关键字直接转到对应 skill 或文档:
|
||||
|
||||
| 关键字 / 场景 | 路径 |
|
||||
|--------------|------|
|
||||
| python / pip / venv / pyenv / hatch / virtualenv / PEP 668 | `python-runtime` skill |
|
||||
| node / npm / pnpm / yarn / volta / nvm / fnm / EACCES | `nodejs-runtime` skill |
|
||||
| docker / podman / container / 容器守护进程 | `references/container.md` |
|
||||
| WSL / WSL2 / Windows Linux 子系统 | `references/wsl.md` |
|
||||
| DOCX / PDF / XLSX / PPTX 依赖 / 办公技能依赖 | `references/office-deps.md` |
|
||||
| LibreOffice / poppler / pandoc / tesseract / qpdf | `references/system-tools.md` |
|
||||
| 不确定属于哪类、想要快速诊断 | 先跑 `scripts/probe.sh` 看 JSON |
|
||||
| DesireCore Hatch / Volta / HTTP API / Socket.IO | `references/desirecore-runtime.md` |
|
||||
| 四级降级决策(API → CLI → 包管理器 → 社区方案) | `references/decision-tree.md` |
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 第一步:快速诊断
|
||||
|
||||
```bash
|
||||
bash skills/dev-environment-setup/scripts/probe.sh > /tmp/env-probe.json
|
||||
cat /tmp/env-probe.json | jq .
|
||||
```
|
||||
|
||||
输出字段含义:见 `references/probe-snapshot.md`。Windows 用 `scripts/probe.ps1`。
|
||||
|
||||
### 第二步:按结果路由
|
||||
|
||||
- `desirecore_api` 非空 → 走 HTTP API 路径(`references/desirecore-runtime.md`)
|
||||
- `tools.python3.available = false` 或 `tools.node.available = false` → 进入对应子 skill
|
||||
- `tools.docker.available = false` 且用户需容器 → `references/container.md`
|
||||
- `wsl.installed = false` 且 Windows 用户 → `references/wsl.md`
|
||||
|
||||
### 第三步:执行子 skill 决策树
|
||||
|
||||
`python-runtime` 与 `nodejs-runtime` 都有自己的四级降级(L1 API → L2 内置 CLI → L3 系统包管理器 → L4 社区方案),定义在共享的 `references/decision-tree.md`。
|
||||
|
||||
### 第四步:办公技能依赖
|
||||
|
||||
办公四件套(DOCX / PDF / XLSX / PPTX)依赖速查:`references/office-deps.md`。包含 Python 包、npm 包、系统工具的一键安装命令。
|
||||
|
||||
### 第五步:系统工具
|
||||
|
||||
LibreOffice / Poppler / Pandoc / Tesseract / qpdf / ImageMagick / Ghostscript 安装与故障排查:`references/system-tools.md`。
|
||||
|
||||
## DesireCore 内置环境管理底座
|
||||
|
||||
DesireCore 内置 Hatch(Python)和 Volta(Node.js),通过 HTTP API + Socket.IO 提供完整的环境管理能力。本 skill 与子 skill(python/nodejs)都依赖:
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| `references/desirecore-runtime.md` | 二进制路径表、HTTP API 速查、Socket.IO 事件契约、`EnvironmentSnapshot` 数据结构 |
|
||||
| `references/decision-tree.md` | 四级降级流程图、判定失败的具体信号、切换提示 |
|
||||
| `references/probe-snapshot.md` | 探测脚本 JSON 输出协议 |
|
||||
|
||||
## 重要约束
|
||||
|
||||
1. **不要把 python / node / pip / npm 强关键词写入本 skill description**——这些归属各自的子 skill,避免触发冲突。
|
||||
2. **API 优先**:`scripts/probe.sh` 第一步检测 `~/.desirecore/agent-service.port`;存在则推荐 HTTP API 路径。
|
||||
3. **缓存协同**:任何安装/移除完成后,调 `POST /api/runtime/environment/refresh` 失效缓存,再发后续 GET。
|
||||
4. **跨平台**:所有命令模板提供 macOS / Linux + Windows(PowerShell)双版本。
|
||||
|
||||
## 子 skill 与文档清单
|
||||
|
||||
```
|
||||
skills/
|
||||
├── python-runtime/ # Python 环境(Hatch 优先)
|
||||
├── nodejs-runtime/ # Node.js 环境(Volta 优先)
|
||||
└── dev-environment-setup/ # 本 skill(综合入口)
|
||||
├── references/
|
||||
│ ├── desirecore-runtime.md
|
||||
│ ├── decision-tree.md
|
||||
│ ├── probe-snapshot.md
|
||||
│ ├── container.md
|
||||
│ ├── wsl.md
|
||||
│ ├── office-deps.md
|
||||
│ └── system-tools.md
|
||||
└── scripts/
|
||||
├── probe.sh
|
||||
└── probe.ps1
|
||||
```
|
||||
|
||||
## 升级说明(v1.x → v2.0.0)
|
||||
|
||||
- v1.x 是单文件 1380 行的全能手册,已拆分。
|
||||
- Python 相关 → `python-runtime`
|
||||
- Node.js 相关 → `nodejs-runtime`
|
||||
- Docker / WSL / 办公依赖 / 系统工具 → 本 skill 的 `references/`
|
||||
- DesireCore Hatch / Volta 从"可选社区方案"升级为强制 L1/L2 主路径
|
||||
|
||||
下游 skill(docx / pdf / xlsx / pptx)应将 "Python 环境问题请参考 dev-environment-setup" 改写为 "Python 环境问题请参考 python-runtime / Node.js 环境问题请参考 nodejs-runtime"。
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 发现智能体
|
||||
name: discover-agent
|
||||
description: 根据用户需求推荐最匹配的智能体,展示候选列表并引导选择。Use when 用户描述需求但不确定该找哪个智能体帮忙,或想浏览可用的智能体。
|
||||
version: 2.5.2
|
||||
type: procedural
|
||||
@@ -13,6 +13,28 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-02-28'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 发现智能体
|
||||
short_desc: 根据需求描述智能推荐最匹配的智能体,引导快速选择
|
||||
description: 根据用户需求推荐最匹配的智能体,展示候选列表并引导选择。Use when 用户描述需求但不确定该找哪个智能体帮忙,或想浏览可用的智能体。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:28ecd07724adda9a
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Discover Agent
|
||||
short_desc: Intelligently recommend the best-matching Agent based on the user's needs and guide a quick selection
|
||||
description: >-
|
||||
Recommend the best-matching Agent based on the user's needs, present a candidate list, and guide the user's selection. Use when the user describes a need but is unsure which Agent to ask, or wants to browse available Agents.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:28ecd07724adda9a
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -25,7 +47,6 @@ market:
|
||||
fill-opacity="0.85"/><path d="M7.76 16.24l1.8-5.41a2 2 0 0 1 1.27-1.27L16.24
|
||||
7.76" fill="#AF52DE" fill-opacity="0.7"/><circle cx="12" cy="12" r="1.5"
|
||||
fill="white" stroke="#AF52DE" stroke-width="0.8"/></svg>
|
||||
short_desc: 根据需求描述智能推荐最匹配的智能体,引导快速选择
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -34,34 +55,34 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# discover-agent 技能
|
||||
# discover-agent skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-Sentence Summary
|
||||
|
||||
根据用户需求描述,在已注册的智能体中匹配并推荐最合适的 Agent。
|
||||
Match and recommend the most suitable registered Agent based on the user's described needs.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
discover-agent 是一个**流程型技能(Procedural Skill)**,赋予 DesireCore 为用户发现和推荐合适智能体的能力。它通过理解用户需求描述,在已注册的 Agent 列表中进行多维度匹配,展示候选列表供用户选择。
|
||||
discover-agent is a **Procedural Skill** that gives DesireCore the ability to discover and recommend a suitable Agent for the user. It understands the user's described needs, performs multi-dimensional matching across the registered Agent list, and presents a candidate list for the user to choose from.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户描述了一个需求,但不知道该找哪个智能体帮忙
|
||||
- 用户想浏览当前可用的智能体及其能力
|
||||
- 用户需要为特定任务找到最合适的专业助手
|
||||
- 新用户初次使用系统,需要了解有哪些智能体可用
|
||||
- The user describes a need but doesn't know which Agent to ask for help
|
||||
- The user wants to browse currently available Agents and their capabilities
|
||||
- The user needs to find the best specialist assistant for a specific task
|
||||
- A new user trying the system for the first time needs to learn which Agents are available
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **降低门槛**:用户无需记住每个智能体的名称和能力
|
||||
- **精准匹配**:基于需求语义进行智能推荐,而非简单关键词搜索
|
||||
- **流畅衔接**:无匹配时自动建议创建新 Agent(衔接 create-agent 技能)
|
||||
- **Lower the barrier**: Users don't have to remember each Agent's name and capabilities
|
||||
- **Precise matching**: Smart recommendations based on the semantics of the need, not simple keyword search
|
||||
- **Smooth handoff**: When there's no match, automatically suggest creating a new Agent (handing off to the create-agent skill)
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 执行流程
|
||||
### Execution Flow
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
@@ -74,77 +95,77 @@ discover-agent 是一个**流程型技能(Procedural Skill)**,赋予 Desir
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:需求理解
|
||||
### Stage 1: Need Understanding
|
||||
|
||||
**触发条件**(任一满足):
|
||||
**Trigger conditions** (any one is sufficient):
|
||||
|
||||
- 用户说"帮我找一个..."、"有没有..."、"谁能帮我..."
|
||||
- 用户描述了一个任务但未指定具体智能体
|
||||
- 用户说"有哪些智能体"、"看看都有谁"
|
||||
- 系统检测到用户需求与当前 Agent 能力不匹配
|
||||
- The user says "find me a...", "is there a...", "who can help me..."
|
||||
- The user describes a task without specifying a particular Agent
|
||||
- The user says "what Agents are there?", "show me who's available"
|
||||
- The system detects that the user's need does not match the current Agent's capabilities
|
||||
|
||||
**需求解析**:
|
||||
**Need parsing**:
|
||||
|
||||
从用户描述中提取以下维度:
|
||||
Extract the following dimensions from the user's description:
|
||||
|
||||
| 维度 | 说明 | 示例 |
|
||||
| ----------- | -------- | ---------------------- |
|
||||
| `domain` | 专业领域 | 法律、财务、技术、教育 |
|
||||
| `task_type` | 任务类型 | 咨询、审查、分析、创作 |
|
||||
| `keywords` | 关键词 | 合同、报表、代码、论文 |
|
||||
| `urgency` | 紧急程度 | 日常 / 紧急 |
|
||||
| Dimension | Description | Examples |
|
||||
| ----------- | ----------------- | --------------------------------------- |
|
||||
| `domain` | Specialty domain | Legal, finance, technology, education |
|
||||
| `task_type` | Task type | Consultation, review, analysis, writing |
|
||||
| `keywords` | Keywords | Contract, report, code, paper |
|
||||
| `urgency` | Urgency level | Routine / urgent |
|
||||
|
||||
### 阶段 2:Agent 检索
|
||||
### Stage 2: Agent Retrieval
|
||||
|
||||
**数据源**:调用 `GET /api/agents` 获取所有已注册的智能体列表。
|
||||
**Data source**: Call `GET /api/agents` to fetch the list of all registered Agents.
|
||||
|
||||
**API 调用**:
|
||||
**API call**:
|
||||
|
||||
```bash
|
||||
GET /api/agents
|
||||
```
|
||||
|
||||
**返回数据中的关键字段**:
|
||||
**Key fields in the returned data**:
|
||||
|
||||
- `id` — 智能体唯一标识
|
||||
- `name` — 智能体名称
|
||||
- `description` — 智能体描述
|
||||
- `skills` — 技能列表
|
||||
- `status` — 当前状态(online/offline/busy)
|
||||
- `id` — Unique Agent identifier
|
||||
- `name` — Agent name
|
||||
- `description` — Agent description
|
||||
- `skills` — Skill list
|
||||
- `status` — Current status (online/offline/busy)
|
||||
|
||||
**过滤规则**:
|
||||
**Filter rules**:
|
||||
|
||||
- 默认只展示 `status: online` 或 `status: offline` 的智能体
|
||||
- 排除系统内部智能体(如 DesireCore 自身,除非用户显式要求)
|
||||
- By default, show only Agents with `status: online` or `status: offline`
|
||||
- Exclude system-internal Agents (e.g. DesireCore itself, unless the user explicitly requests them)
|
||||
|
||||
### 阶段 3:匹配评估
|
||||
### Stage 3: Match Evaluation
|
||||
|
||||
根据以下维度综合判断匹配度(使用 LLM 语义理解,非公式计算):
|
||||
Comprehensively judge match degree based on the following dimensions (using LLM semantic understanding rather than formula-based computation):
|
||||
|
||||
| 维度 | 说明 |
|
||||
| ---------- | --------------------------------------------------- |
|
||||
| 描述相关性 | 智能体 description / persona 与用户需求的语义相关度 |
|
||||
| 技能匹配度 | 智能体拥有的 skills 与任务类型的关联度 |
|
||||
| 领域契合度 | 智能体专业领域与用户需求领域的契合程度 |
|
||||
| 状态可用性 | 智能体当前状态(online 优先于 offline) |
|
||||
| Dimension | Description |
|
||||
| ---------------------- | ------------------------------------------------------------------------ |
|
||||
| Description relevance | Semantic relevance between Agent description / persona and user's need |
|
||||
| Skill match | Relevance of the Agent's skills to the task type |
|
||||
| Domain fit | Fit between the Agent's specialty domain and the user's need domain |
|
||||
| Status availability | Agent's current status (online preferred over offline) |
|
||||
|
||||
**展示规则**:
|
||||
**Display rules**:
|
||||
|
||||
- 高度匹配(明确适合该任务)→ 标为"推荐"
|
||||
- 部分匹配(可能有帮助)→ 标为"可能相关"
|
||||
- 无明显关联 → 不展示
|
||||
- Highly matched (clearly suited to the task) → tag as "Recommended"
|
||||
- Partial match (may help) → tag as "Possibly relevant"
|
||||
- No clear relation → do not display
|
||||
|
||||
### 阶段 4:候选排序
|
||||
### Stage 4: Candidate Ranking
|
||||
|
||||
**排序规则**:
|
||||
**Ranking rules**:
|
||||
|
||||
1. 按综合得分降序排列
|
||||
2. 同分时 online 状态优先
|
||||
3. 最多展示 5 个候选
|
||||
1. Sort by overall score in descending order
|
||||
2. On ties, online status takes precedence
|
||||
3. Show at most 5 candidates
|
||||
|
||||
### 阶段 5:结果展示
|
||||
### Stage 5: Result Display
|
||||
|
||||
**有匹配结果时**:
|
||||
**When matches are found**:
|
||||
|
||||
```
|
||||
根据你的需求,我推荐以下智能体:
|
||||
@@ -169,7 +190,7 @@ GET /api/agents
|
||||
请选择一个智能体,或告诉我更具体的需求。
|
||||
```
|
||||
|
||||
**无匹配结果时**:
|
||||
**When no matches are found**:
|
||||
|
||||
```
|
||||
目前没有找到完全匹配你需求的智能体。
|
||||
@@ -182,7 +203,7 @@ GET /api/agents
|
||||
你想怎么做?
|
||||
```
|
||||
|
||||
**浏览模式**(用户要求查看所有):
|
||||
**Browse mode** (when the user asks to view all):
|
||||
|
||||
```
|
||||
当前可用的智能体:
|
||||
@@ -198,20 +219,20 @@ GET /api/agents
|
||||
共 4 个智能体。需要了解某个智能体的详细信息吗?
|
||||
```
|
||||
|
||||
### 阶段 6:引导选择
|
||||
### Stage 6: Guided Selection
|
||||
|
||||
**用户选择后的操作**:
|
||||
**Actions after the user selects**:
|
||||
|
||||
| 用户选择 | 后续操作 |
|
||||
| ---------------- | ------------------------------------------------------------- |
|
||||
| 选择了某个智能体 | 切换到该智能体的对话,传递用户需求上下文 |
|
||||
| 要求了解更多 | 调用 `GET /api/agents/:id` 获取详情,展示结构化信息(见下方) |
|
||||
| 不满意候选 | 引导用户细化需求或建议创建新 Agent |
|
||||
| 选择"创建新的" | 调用 create-agent 技能,传递已收集的需求信息 |
|
||||
| User Choice | Follow-up Action |
|
||||
| ------------------------ | ------------------------------------------------------------------ |
|
||||
| Selected an Agent | Switch to a conversation with that Agent and pass the need context |
|
||||
| Asked to learn more | Call `GET /api/agents/:id` for details and present structured info (see below) |
|
||||
| Not satisfied with candidates | Guide the user to refine the need or suggest creating a new Agent |
|
||||
| Chose "create new" | Invoke the create-agent skill, passing the need info already collected |
|
||||
|
||||
**"了解更多"的实现**:
|
||||
**Implementation of "learn more"**:
|
||||
|
||||
调用 `GET /api/agents/:id` 获取详情,并可选调用结构化端点获取人格/规则:
|
||||
Call `GET /api/agents/:id` for details, and optionally call structured endpoints for persona/principles:
|
||||
|
||||
```bash
|
||||
# 获取基本信息
|
||||
@@ -223,7 +244,7 @@ GET /api/agents/{agentId}/persona
|
||||
# 返回: { L0, L1: { role, personality, communication_style }, L2 }
|
||||
```
|
||||
|
||||
向用户展示时,以自然语言/表格形式呈现关键信息:
|
||||
When presenting to the user, render key information in natural language / table form:
|
||||
|
||||
```
|
||||
「法律顾问助手」详细信息
|
||||
@@ -238,7 +259,7 @@ GET /api/agents/{agentId}/persona
|
||||
需要与这个智能体对话吗?
|
||||
```
|
||||
|
||||
**切换上下文传递**:
|
||||
**Context handoff on switch**:
|
||||
|
||||
```yaml
|
||||
context_handoff:
|
||||
@@ -247,29 +268,29 @@ context_handoff:
|
||||
user_intent: '帮我审查这份合同的风险点'
|
||||
```
|
||||
|
||||
### 与其他技能的协作
|
||||
### Collaboration with Other Skills
|
||||
|
||||
| 协作技能 | 协作方式 |
|
||||
| --------------- | -------------------------------------------------- |
|
||||
| create-agent | 无匹配时建议创建新 Agent,传递用户需求作为初始信息 |
|
||||
| task-management | 匹配成功后可自动创建任务并分配给目标 Agent |
|
||||
| Collaborating Skill | How It Collaborates |
|
||||
| ------------------- | ----------------------------------------------------------- |
|
||||
| create-agent | When there's no match, suggest creating a new Agent and pass the user's need as initial info |
|
||||
| task-management | After a successful match, optionally auto-create a task and assign it to the target Agent |
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| --------------------- | -------------------------------- |
|
||||
| API 调用失败 | 提示网络错误,建议稍后重试 |
|
||||
| Agent 列表为空 | 引导用户创建第一个智能体 |
|
||||
| 用户描述过于模糊 | 追问具体需求,提供领域选项引导 |
|
||||
| 推荐的 Agent 状态异常 | 标注状态,建议选择其他在线 Agent |
|
||||
| Error Scenario | Handling |
|
||||
| ---------------------------- | --------------------------------------------------------- |
|
||||
| API call fails | Indicate a network error and suggest retrying later |
|
||||
| Agent list is empty | Guide the user to create their first Agent |
|
||||
| User description too vague | Ask follow-up questions and offer domain options to guide |
|
||||
| Recommended Agent has bad status | Mark the status and suggest selecting another online Agent |
|
||||
|
||||
### 权限要求
|
||||
### Permission Requirements
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 只读操作,无风险
|
||||
- Prefer accessing the Agent Service HTTP API via the `Bash` tool with curl
|
||||
- The API base URL is already injected into the "Local API" section of the system prompt; reference it directly
|
||||
- Read-only operations; no risk
|
||||
|
||||
### 依赖
|
||||
### Dependencies
|
||||
|
||||
- Agent Service HTTP API(`GET /api/agents`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
- Agent Service HTTP API (`GET /api/agents`)
|
||||
- The local API URL declaration in the system prompt
|
||||
|
||||
241
skills/discover-agent/SKILL.zh-CN.md
Normal file
241
skills/discover-agent/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,241 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# discover-agent 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
根据用户需求描述,在已注册的智能体中匹配并推荐最合适的 Agent。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
discover-agent 是一个**流程型技能(Procedural Skill)**,赋予 DesireCore 为用户发现和推荐合适智能体的能力。它通过理解用户需求描述,在已注册的 Agent 列表中进行多维度匹配,展示候选列表供用户选择。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户描述了一个需求,但不知道该找哪个智能体帮忙
|
||||
- 用户想浏览当前可用的智能体及其能力
|
||||
- 用户需要为特定任务找到最合适的专业助手
|
||||
- 新用户初次使用系统,需要了解有哪些智能体可用
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **降低门槛**:用户无需记住每个智能体的名称和能力
|
||||
- **精准匹配**:基于需求语义进行智能推荐,而非简单关键词搜索
|
||||
- **流畅衔接**:无匹配时自动建议创建新 Agent(衔接 create-agent 技能)
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 执行流程
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 需求理解 │ ──→ │ Agent 检索 │ ──→ │ 匹配评分 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 引导选择 │ ←── │ 结果展示 │ ←── │ 候选排序 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:需求理解
|
||||
|
||||
**触发条件**(任一满足):
|
||||
|
||||
- 用户说"帮我找一个..."、"有没有..."、"谁能帮我..."
|
||||
- 用户描述了一个任务但未指定具体智能体
|
||||
- 用户说"有哪些智能体"、"看看都有谁"
|
||||
- 系统检测到用户需求与当前 Agent 能力不匹配
|
||||
|
||||
**需求解析**:
|
||||
|
||||
从用户描述中提取以下维度:
|
||||
|
||||
| 维度 | 说明 | 示例 |
|
||||
| ----------- | -------- | ---------------------- |
|
||||
| `domain` | 专业领域 | 法律、财务、技术、教育 |
|
||||
| `task_type` | 任务类型 | 咨询、审查、分析、创作 |
|
||||
| `keywords` | 关键词 | 合同、报表、代码、论文 |
|
||||
| `urgency` | 紧急程度 | 日常 / 紧急 |
|
||||
|
||||
### 阶段 2:Agent 检索
|
||||
|
||||
**数据源**:调用 `GET /api/agents` 获取所有已注册的智能体列表。
|
||||
|
||||
**API 调用**:
|
||||
|
||||
```bash
|
||||
GET /api/agents
|
||||
```
|
||||
|
||||
**返回数据中的关键字段**:
|
||||
|
||||
- `id` — 智能体唯一标识
|
||||
- `name` — 智能体名称
|
||||
- `description` — 智能体描述
|
||||
- `skills` — 技能列表
|
||||
- `status` — 当前状态(online/offline/busy)
|
||||
|
||||
**过滤规则**:
|
||||
|
||||
- 默认只展示 `status: online` 或 `status: offline` 的智能体
|
||||
- 排除系统内部智能体(如 DesireCore 自身,除非用户显式要求)
|
||||
|
||||
### 阶段 3:匹配评估
|
||||
|
||||
根据以下维度综合判断匹配度(使用 LLM 语义理解,非公式计算):
|
||||
|
||||
| 维度 | 说明 |
|
||||
| ---------- | --------------------------------------------------- |
|
||||
| 描述相关性 | 智能体 description / persona 与用户需求的语义相关度 |
|
||||
| 技能匹配度 | 智能体拥有的 skills 与任务类型的关联度 |
|
||||
| 领域契合度 | 智能体专业领域与用户需求领域的契合程度 |
|
||||
| 状态可用性 | 智能体当前状态(online 优先于 offline) |
|
||||
|
||||
**展示规则**:
|
||||
|
||||
- 高度匹配(明确适合该任务)→ 标为"推荐"
|
||||
- 部分匹配(可能有帮助)→ 标为"可能相关"
|
||||
- 无明显关联 → 不展示
|
||||
|
||||
### 阶段 4:候选排序
|
||||
|
||||
**排序规则**:
|
||||
|
||||
1. 按综合得分降序排列
|
||||
2. 同分时 online 状态优先
|
||||
3. 最多展示 5 个候选
|
||||
|
||||
### 阶段 5:结果展示
|
||||
|
||||
**有匹配结果时**:
|
||||
|
||||
```
|
||||
根据你的需求,我推荐以下智能体:
|
||||
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ 1. 法律顾问助手 匹配度: 92% │
|
||||
│ 专注合同审查和法律风险评估 │
|
||||
│ 技能:合同审查、风险评估、法律研究 │
|
||||
│ 状态:在线 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 2. AI 文书助手 匹配度: 71% │
|
||||
│ 专业文书撰写和格式优化 │
|
||||
│ 技能:文书撰写、格式排版、合规检查 │
|
||||
│ 状态:在线 │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ 3. 数据分析师 匹配度: 45% │
|
||||
│ 数据分析和可视化报告 │
|
||||
│ 技能:数据分析、报表生成、趋势预测 │
|
||||
│ 状态:离线 │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
|
||||
请选择一个智能体,或告诉我更具体的需求。
|
||||
```
|
||||
|
||||
**无匹配结果时**:
|
||||
|
||||
```
|
||||
目前没有找到完全匹配你需求的智能体。
|
||||
|
||||
你可以:
|
||||
1. 用更具体的描述再试一次
|
||||
2. 创建一个新的专业智能体(我可以帮你)
|
||||
3. 浏览所有可用的智能体
|
||||
|
||||
你想怎么做?
|
||||
```
|
||||
|
||||
**浏览模式**(用户要求查看所有):
|
||||
|
||||
```
|
||||
当前可用的智能体:
|
||||
|
||||
在线:
|
||||
- 法律顾问助手 — 合同审查和法律风险评估
|
||||
- AI 文书助手 — 专业文书撰写和格式优化
|
||||
|
||||
离线:
|
||||
- 数据分析师 — 数据分析和可视化报告
|
||||
- 翻译助手 — 多语言翻译和本地化
|
||||
|
||||
共 4 个智能体。需要了解某个智能体的详细信息吗?
|
||||
```
|
||||
|
||||
### 阶段 6:引导选择
|
||||
|
||||
**用户选择后的操作**:
|
||||
|
||||
| 用户选择 | 后续操作 |
|
||||
| ---------------- | ------------------------------------------------------------- |
|
||||
| 选择了某个智能体 | 切换到该智能体的对话,传递用户需求上下文 |
|
||||
| 要求了解更多 | 调用 `GET /api/agents/:id` 获取详情,展示结构化信息(见下方) |
|
||||
| 不满意候选 | 引导用户细化需求或建议创建新 Agent |
|
||||
| 选择"创建新的" | 调用 create-agent 技能,传递已收集的需求信息 |
|
||||
|
||||
**"了解更多"的实现**:
|
||||
|
||||
调用 `GET /api/agents/:id` 获取详情,并可选调用结构化端点获取人格/规则:
|
||||
|
||||
```bash
|
||||
# 获取基本信息
|
||||
GET /api/agents/{agentId}
|
||||
# 返回: { id, name, description, skillsCount, toolsCount, status, config, persona, principles }
|
||||
|
||||
# 获取结构化 persona(可选,用于展示更丰富的信息)
|
||||
GET /api/agents/{agentId}/persona
|
||||
# 返回: { L0, L1: { role, personality, communication_style }, L2 }
|
||||
```
|
||||
|
||||
向用户展示时,以自然语言/表格形式呈现关键信息:
|
||||
|
||||
```
|
||||
「法律顾问助手」详细信息
|
||||
|
||||
| 字段 | 内容 |
|
||||
|------|------|
|
||||
| 角色定位 | 专注合同审查和法律风险评估 |
|
||||
| 性格特征 | 专业、严谨、审慎 |
|
||||
| 技能数量 | 3 个 |
|
||||
| 当前状态 | 在线 |
|
||||
|
||||
需要与这个智能体对话吗?
|
||||
```
|
||||
|
||||
**切换上下文传递**:
|
||||
|
||||
```yaml
|
||||
context_handoff:
|
||||
source_agent: desirecore
|
||||
target_agent: legal-assistant
|
||||
user_intent: '帮我审查这份合同的风险点'
|
||||
```
|
||||
|
||||
### 与其他技能的协作
|
||||
|
||||
| 协作技能 | 协作方式 |
|
||||
| --------------- | -------------------------------------------------- |
|
||||
| create-agent | 无匹配时建议创建新 Agent,传递用户需求作为初始信息 |
|
||||
| task-management | 匹配成功后可自动创建任务并分配给目标 Agent |
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| --------------------- | -------------------------------- |
|
||||
| API 调用失败 | 提示网络错误,建议稍后重试 |
|
||||
| Agent 列表为空 | 引导用户创建第一个智能体 |
|
||||
| 用户描述过于模糊 | 追问具体需求,提供领域选项引导 |
|
||||
| 推荐的 Agent 状态异常 | 标注状态,建议选择其他在线 Agent |
|
||||
|
||||
### 权限要求
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 只读操作,无风险
|
||||
|
||||
### 依赖
|
||||
|
||||
- Agent Service HTTP API(`GET /api/agents`)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: Word 文档处理
|
||||
name: docx
|
||||
description: >-
|
||||
Use this skill whenever the user wants to create, read, edit, or manipulate
|
||||
Word documents (.docx files). Triggers include: any mention of "Word doc",
|
||||
@@ -26,6 +26,29 @@ tags:
|
||||
metadata:
|
||||
author: anthropic
|
||||
updated_at: '2026-04-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: Word 文档处理
|
||||
short_desc: 创建、编辑和处理 Word 文档(.docx)
|
||||
description: >-
|
||||
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of "Word doc", "word document", ".docx", or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a "report", "memo", "letter", "template", or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation. Use when 用户提到 Word文档、docx、创建文档、编辑文档、报告、 备忘录、公文、合同、信函模板。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:b9f7129ef5e82c4b
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Word Document Processing
|
||||
short_desc: Create, edit, and process Word documents (.docx)
|
||||
description: >-
|
||||
Use this skill whenever the user wants to create, read, edit, or manipulate Word documents (.docx files). Triggers include: any mention of "Word doc", "word document", ".docx", or requests to produce professional documents with formatting like tables of contents, headings, page numbers, or letterheads. Also use when extracting or reorganizing content from .docx files, inserting or replacing images in documents, performing find-and-replace in Word files, working with tracked changes or comments, or converting content into a polished Word document. If the user asks for a "report", "memo", "letter", "template", or similar deliverable as a Word or .docx file, use this skill. Do NOT use for PDFs, spreadsheets, Google Docs, or general coding tasks unrelated to document generation. Use when the user mentions Word documents, docx, creating documents, editing documents, reports, memos, official documents, contracts, or letter templates.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:b9f7129ef5e82c4b
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -39,7 +62,6 @@ market:
|
||||
height="1.5" rx="0.5" fill="url(#dx-a)" fill-opacity="0.5"/><path d="M7
|
||||
14.5h10M7 17h7" stroke="url(#dx-a)" stroke-width="1.3"
|
||||
stroke-linecap="round"/></svg>
|
||||
short_desc: 创建、编辑和处理 Word 文档(.docx)
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -47,64 +69,64 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# docx 技能
|
||||
# docx Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
创建、编辑和处理 Word 文档(.docx),支持新建、修改 XML、格式校验全流程。
|
||||
Create, edit, and process Word documents (.docx), with end-to-end support for creation, XML editing, and format validation.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
docx 是一个**流程型技能(Procedural Skill)**,提供 Word 文档的完整处理能力。支持通过 docx-js(Node.js)创建新文档,通过解包 XML 编辑现有文档,以及格式验证和 PDF 转换。
|
||||
docx is a **Procedural Skill** that provides full processing capabilities for Word documents. It supports creating new documents via docx-js (Node.js), editing existing documents by unpacking and modifying XML, plus format validation and PDF conversion.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要创建新的 Word 文档(报告、备忘录、合同、信函等)
|
||||
- 用户需要编辑现有 .docx 文件(修改内容、添加批注、跟踪修改)
|
||||
- 用户需要从 .docx 文件中提取文本或表格数据
|
||||
- 用户需要进行文档格式转换(.doc → .docx、.docx → PDF)
|
||||
- The user needs to create a new Word document (report, memo, contract, letter, etc.)
|
||||
- The user needs to edit an existing .docx file (modify content, add comments, track changes)
|
||||
- The user needs to extract text or table data from a .docx file
|
||||
- The user needs to perform document format conversion (.doc → .docx, .docx → PDF)
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
### Python 3 (required)
|
||||
|
||||
在执行任何 Python 脚本之前,先检测 Python 是否可用:
|
||||
Before running any Python script, first check whether Python is available:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
If the command fails (Python is unavailable), **you must stop and instruct the user to install Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **macOS**: `brew install python3` or download from https://www.python.org/downloads/
|
||||
- **Windows**: `winget install Python.Python.3` or download from python.org (check "Add Python to PATH" during installation)
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(容器 / WSL / 系统工具)加载 `dev-environment-setup` 技能。
|
||||
For more detailed environment setup help: for Python-related issues, load the `python-runtime` Skill;
|
||||
for everything else (containers / WSL / system tools), load the `dev-environment-setup` Skill.
|
||||
|
||||
### Python 包依赖
|
||||
### Python Package Dependencies
|
||||
|
||||
本技能的 Python 脚本依赖以下包(按需检测,仅在实际调用相关脚本时检查):
|
||||
The Python scripts in this Skill depend on the following packages (checked on demand, only when the relevant scripts are actually invoked):
|
||||
|
||||
- `lxml` — XML schema 验证(validate.py)
|
||||
- `defusedxml` — 安全 XML 解析(unpack.py)
|
||||
- `lxml` — XML schema validation (validate.py)
|
||||
- `defusedxml` — safe XML parsing (unpack.py)
|
||||
|
||||
检测方法:
|
||||
Detection method:
|
||||
```bash
|
||||
python3 -c "import lxml; import defusedxml" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install lxml defusedxml`
|
||||
If missing, instruct the user to install: `pip install lxml defusedxml`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .docx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.docx`"
|
||||
When you create or modify a .docx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "File saved to: `/path/to/output.docx`"
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
534
skills/docx/SKILL.zh-CN.md
Normal file
534
skills/docx/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,534 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# docx 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
创建、编辑和处理 Word 文档(.docx),支持新建、修改 XML、格式校验全流程。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
docx 是一个**流程型技能(Procedural Skill)**,提供 Word 文档的完整处理能力。支持通过 docx-js(Node.js)创建新文档,通过解包 XML 编辑现有文档,以及格式验证和 PDF 转换。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要创建新的 Word 文档(报告、备忘录、合同、信函等)
|
||||
- 用户需要编辑现有 .docx 文件(修改内容、添加批注、跟踪修改)
|
||||
- 用户需要从 .docx 文件中提取文本或表格数据
|
||||
- 用户需要进行文档格式转换(.doc → .docx、.docx → PDF)
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
|
||||
在执行任何 Python 脚本之前,先检测 Python 是否可用:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(容器 / WSL / 系统工具)加载 `dev-environment-setup` 技能。
|
||||
|
||||
### Python 包依赖
|
||||
|
||||
本技能的 Python 脚本依赖以下包(按需检测,仅在实际调用相关脚本时检查):
|
||||
|
||||
- `lxml` — XML schema 验证(validate.py)
|
||||
- `defusedxml` — 安全 XML 解析(unpack.py)
|
||||
|
||||
检测方法:
|
||||
```bash
|
||||
python3 -c "import lxml; import defusedxml" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install lxml defusedxml`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .docx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.docx`"
|
||||
|
||||
## Overview
|
||||
|
||||
A .docx file is a ZIP archive containing XML files.
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Approach |
|
||||
|------|----------|
|
||||
| Read/analyze content | `pandoc` or unpack for raw XML |
|
||||
| Create new document | Use `docx-js` - see Creating New Documents below |
|
||||
| Edit existing document | Unpack → edit XML → repack - see Editing Existing Documents below |
|
||||
|
||||
### Converting .doc to .docx
|
||||
|
||||
Legacy `.doc` files must be converted before editing:
|
||||
|
||||
```bash
|
||||
python scripts/office/soffice.py --headless --convert-to docx document.doc
|
||||
```
|
||||
|
||||
### Reading Content
|
||||
|
||||
```bash
|
||||
# Text extraction with tracked changes
|
||||
pandoc --track-changes=all document.docx -o output.md
|
||||
|
||||
# Raw XML access
|
||||
python scripts/office/unpack.py document.docx unpacked/
|
||||
```
|
||||
|
||||
### Converting to Images
|
||||
|
||||
```bash
|
||||
python scripts/office/soffice.py --headless --convert-to pdf document.docx
|
||||
pdftoppm -jpeg -r 150 document.pdf page
|
||||
```
|
||||
|
||||
### Accepting Tracked Changes
|
||||
|
||||
To produce a clean document with all tracked changes accepted (requires LibreOffice):
|
||||
|
||||
```bash
|
||||
python scripts/accept_changes.py input.docx output.docx
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Creating New Documents
|
||||
|
||||
Generate .docx files with JavaScript, then validate. Install: `npm install -g docx`
|
||||
|
||||
### Setup
|
||||
```javascript
|
||||
const { Document, Packer, Paragraph, TextRun, Table, TableRow, TableCell, ImageRun,
|
||||
Header, Footer, AlignmentType, PageOrientation, LevelFormat, ExternalHyperlink,
|
||||
TableOfContents, HeadingLevel, BorderStyle, WidthType, ShadingType,
|
||||
VerticalAlign, PageNumber, PageBreak } = require('docx');
|
||||
|
||||
const doc = new Document({ sections: [{ children: [/* content */] }] });
|
||||
Packer.toBuffer(doc).then(buffer => fs.writeFileSync("doc.docx", buffer));
|
||||
```
|
||||
|
||||
### Validation
|
||||
After creating the file, validate it. If validation fails, unpack, fix the XML, and repack.
|
||||
```bash
|
||||
python scripts/office/validate.py doc.docx
|
||||
```
|
||||
|
||||
### Page Size
|
||||
|
||||
```javascript
|
||||
// CRITICAL: docx-js defaults to A4, not US Letter
|
||||
// Always set page size explicitly for consistent results
|
||||
sections: [{
|
||||
properties: {
|
||||
page: {
|
||||
size: {
|
||||
width: 12240, // 8.5 inches in DXA
|
||||
height: 15840 // 11 inches in DXA
|
||||
},
|
||||
margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } // 1 inch margins
|
||||
}
|
||||
},
|
||||
children: [/* content */]
|
||||
}]
|
||||
```
|
||||
|
||||
**Common page sizes (DXA units, 1440 DXA = 1 inch):**
|
||||
|
||||
| Paper | Width | Height | Content Width (1" margins) |
|
||||
|-------|-------|--------|---------------------------|
|
||||
| US Letter | 12,240 | 15,840 | 9,360 |
|
||||
| A4 (default) | 11,906 | 16,838 | 9,026 |
|
||||
|
||||
**Landscape orientation:** docx-js swaps width/height internally, so pass portrait dimensions and let it handle the swap:
|
||||
```javascript
|
||||
size: {
|
||||
width: 12240, // Pass SHORT edge as width
|
||||
height: 15840, // Pass LONG edge as height
|
||||
orientation: PageOrientation.LANDSCAPE // docx-js swaps them in the XML
|
||||
},
|
||||
// Content width = 15840 - left margin - right margin (uses the long edge)
|
||||
```
|
||||
|
||||
### Styles (Override Built-in Headings)
|
||||
|
||||
Use Arial as the default font (universally supported). Keep titles black for readability.
|
||||
|
||||
```javascript
|
||||
const doc = new Document({
|
||||
styles: {
|
||||
default: { document: { run: { font: "Arial", size: 24 } } }, // 12pt default
|
||||
paragraphStyles: [
|
||||
// IMPORTANT: Use exact IDs to override built-in styles
|
||||
{ id: "Heading1", name: "Heading 1", basedOn: "Normal", next: "Normal", quickFormat: true,
|
||||
run: { size: 32, bold: true, font: "Arial" },
|
||||
paragraph: { spacing: { before: 240, after: 240 }, outlineLevel: 0 } }, // outlineLevel required for TOC
|
||||
{ id: "Heading2", name: "Heading 2", basedOn: "Normal", next: "Normal", quickFormat: true,
|
||||
run: { size: 28, bold: true, font: "Arial" },
|
||||
paragraph: { spacing: { before: 180, after: 180 }, outlineLevel: 1 } },
|
||||
]
|
||||
},
|
||||
sections: [{
|
||||
children: [
|
||||
new Paragraph({ heading: HeadingLevel.HEADING_1, children: [new TextRun("Title")] }),
|
||||
]
|
||||
}]
|
||||
});
|
||||
```
|
||||
|
||||
### Lists (NEVER use unicode bullets)
|
||||
|
||||
```javascript
|
||||
// ❌ WRONG - never manually insert bullet characters
|
||||
new Paragraph({ children: [new TextRun("• Item")] }) // BAD
|
||||
new Paragraph({ children: [new TextRun("\u2022 Item")] }) // BAD
|
||||
|
||||
// ✅ CORRECT - use numbering config with LevelFormat.BULLET
|
||||
const doc = new Document({
|
||||
numbering: {
|
||||
config: [
|
||||
{ reference: "bullets",
|
||||
levels: [{ level: 0, format: LevelFormat.BULLET, text: "•", alignment: AlignmentType.LEFT,
|
||||
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
||||
{ reference: "numbers",
|
||||
levels: [{ level: 0, format: LevelFormat.DECIMAL, text: "%1.", alignment: AlignmentType.LEFT,
|
||||
style: { paragraph: { indent: { left: 720, hanging: 360 } } } }] },
|
||||
]
|
||||
},
|
||||
sections: [{
|
||||
children: [
|
||||
new Paragraph({ numbering: { reference: "bullets", level: 0 },
|
||||
children: [new TextRun("Bullet item")] }),
|
||||
new Paragraph({ numbering: { reference: "numbers", level: 0 },
|
||||
children: [new TextRun("Numbered item")] }),
|
||||
]
|
||||
}]
|
||||
});
|
||||
|
||||
// ⚠️ Each reference creates INDEPENDENT numbering
|
||||
// Same reference = continues (1,2,3 then 4,5,6)
|
||||
// Different reference = restarts (1,2,3 then 1,2,3)
|
||||
```
|
||||
|
||||
### Tables
|
||||
|
||||
**CRITICAL: Tables need dual widths** - set both `columnWidths` on the table AND `width` on each cell. Without both, tables render incorrectly on some platforms.
|
||||
|
||||
```javascript
|
||||
// CRITICAL: Always set table width for consistent rendering
|
||||
// CRITICAL: Use ShadingType.CLEAR (not SOLID) to prevent black backgrounds
|
||||
const border = { style: BorderStyle.SINGLE, size: 1, color: "CCCCCC" };
|
||||
const borders = { top: border, bottom: border, left: border, right: border };
|
||||
|
||||
new Table({
|
||||
width: { size: 9360, type: WidthType.DXA }, // Always use DXA (percentages break in Google Docs)
|
||||
columnWidths: [4680, 4680], // Must sum to table width (DXA: 1440 = 1 inch)
|
||||
rows: [
|
||||
new TableRow({
|
||||
children: [
|
||||
new TableCell({
|
||||
borders,
|
||||
width: { size: 4680, type: WidthType.DXA }, // Also set on each cell
|
||||
shading: { fill: "D5E8F0", type: ShadingType.CLEAR }, // CLEAR not SOLID
|
||||
margins: { top: 80, bottom: 80, left: 120, right: 120 }, // Cell padding (internal, not added to width)
|
||||
children: [new Paragraph({ children: [new TextRun("Cell")] })]
|
||||
})
|
||||
]
|
||||
})
|
||||
]
|
||||
})
|
||||
```
|
||||
|
||||
**Table width calculation:**
|
||||
|
||||
Always use `WidthType.DXA` — `WidthType.PERCENTAGE` breaks in Google Docs.
|
||||
|
||||
```javascript
|
||||
// Table width = sum of columnWidths = content width
|
||||
// US Letter with 1" margins: 12240 - 2880 = 9360 DXA
|
||||
width: { size: 9360, type: WidthType.DXA },
|
||||
columnWidths: [7000, 2360] // Must sum to table width
|
||||
```
|
||||
|
||||
**Width rules:**
|
||||
- **Always use `WidthType.DXA`** — never `WidthType.PERCENTAGE` (incompatible with Google Docs)
|
||||
- Table width must equal the sum of `columnWidths`
|
||||
- Cell `width` must match corresponding `columnWidth`
|
||||
- Cell `margins` are internal padding - they reduce content area, not add to cell width
|
||||
- For full-width tables: use content width (page width minus left and right margins)
|
||||
|
||||
### Images
|
||||
|
||||
```javascript
|
||||
// CRITICAL: type parameter is REQUIRED
|
||||
new Paragraph({
|
||||
children: [new ImageRun({
|
||||
type: "png", // Required: png, jpg, jpeg, gif, bmp, svg
|
||||
data: fs.readFileSync("image.png"),
|
||||
transformation: { width: 200, height: 150 },
|
||||
altText: { title: "Title", description: "Desc", name: "Name" } // All three required
|
||||
})]
|
||||
})
|
||||
```
|
||||
|
||||
### Page Breaks
|
||||
|
||||
```javascript
|
||||
// CRITICAL: PageBreak must be inside a Paragraph
|
||||
new Paragraph({ children: [new PageBreak()] })
|
||||
|
||||
// Or use pageBreakBefore
|
||||
new Paragraph({ pageBreakBefore: true, children: [new TextRun("New page")] })
|
||||
```
|
||||
|
||||
### Table of Contents
|
||||
|
||||
```javascript
|
||||
// CRITICAL: Headings must use HeadingLevel ONLY - no custom styles
|
||||
new TableOfContents("Table of Contents", { hyperlink: true, headingStyleRange: "1-3" })
|
||||
```
|
||||
|
||||
### Headers/Footers
|
||||
|
||||
```javascript
|
||||
sections: [{
|
||||
properties: {
|
||||
page: { margin: { top: 1440, right: 1440, bottom: 1440, left: 1440 } } // 1440 = 1 inch
|
||||
},
|
||||
headers: {
|
||||
default: new Header({ children: [new Paragraph({ children: [new TextRun("Header")] })] })
|
||||
},
|
||||
footers: {
|
||||
default: new Footer({ children: [new Paragraph({
|
||||
children: [new TextRun("Page "), new TextRun({ children: [PageNumber.CURRENT] })]
|
||||
})] })
|
||||
},
|
||||
children: [/* content */]
|
||||
}]
|
||||
```
|
||||
|
||||
### Critical Rules for docx-js
|
||||
|
||||
- **Set page size explicitly** - docx-js defaults to A4; use US Letter (12240 x 15840 DXA) for US documents
|
||||
- **Landscape: pass portrait dimensions** - docx-js swaps width/height internally; pass short edge as `width`, long edge as `height`, and set `orientation: PageOrientation.LANDSCAPE`
|
||||
- **Never use `\n`** - use separate Paragraph elements
|
||||
- **Never use unicode bullets** - use `LevelFormat.BULLET` with numbering config
|
||||
- **PageBreak must be in Paragraph** - standalone creates invalid XML
|
||||
- **ImageRun requires `type`** - always specify png/jpg/etc
|
||||
- **Always set table `width` with DXA** - never use `WidthType.PERCENTAGE` (breaks in Google Docs)
|
||||
- **Tables need dual widths** - `columnWidths` array AND cell `width`, both must match
|
||||
- **Table width = sum of columnWidths** - for DXA, ensure they add up exactly
|
||||
- **Always add cell margins** - use `margins: { top: 80, bottom: 80, left: 120, right: 120 }` for readable padding
|
||||
- **Use `ShadingType.CLEAR`** - never SOLID for table shading
|
||||
- **TOC requires HeadingLevel only** - no custom styles on heading paragraphs
|
||||
- **Override built-in styles** - use exact IDs: "Heading1", "Heading2", etc.
|
||||
- **Include `outlineLevel`** - required for TOC (0 for H1, 1 for H2, etc.)
|
||||
|
||||
---
|
||||
|
||||
## Editing Existing Documents
|
||||
|
||||
**Follow all 3 steps in order.**
|
||||
|
||||
### Step 1: Unpack
|
||||
```bash
|
||||
python scripts/office/unpack.py document.docx unpacked/
|
||||
```
|
||||
Extracts XML, pretty-prints, merges adjacent runs, and converts smart quotes to XML entities (`“` etc.) so they survive editing. Use `--merge-runs false` to skip run merging.
|
||||
|
||||
### Step 2: Edit XML
|
||||
|
||||
Edit files in `unpacked/word/`. See XML Reference below for patterns.
|
||||
|
||||
**Use "Claude" as the author** for tracked changes and comments, unless the user explicitly requests use of a different name.
|
||||
|
||||
**Use the Edit tool directly for string replacement. Do not write Python scripts.** Scripts introduce unnecessary complexity. The Edit tool shows exactly what is being replaced.
|
||||
|
||||
**CRITICAL: Use smart quotes for new content.** When adding text with apostrophes or quotes, use XML entities to produce smart quotes:
|
||||
```xml
|
||||
<!-- Use these entities for professional typography -->
|
||||
<w:t>Here’s a quote: “Hello”</w:t>
|
||||
```
|
||||
| Entity | Character |
|
||||
|--------|-----------|
|
||||
| `‘` | ‘ (left single) |
|
||||
| `’` | ’ (right single / apostrophe) |
|
||||
| `“` | “ (left double) |
|
||||
| `”` | ” (right double) |
|
||||
|
||||
**Adding comments:** Use `comment.py` to handle boilerplate across multiple XML files (text must be pre-escaped XML):
|
||||
```bash
|
||||
python scripts/comment.py unpacked/ 0 "Comment text with & and ’"
|
||||
python scripts/comment.py unpacked/ 1 "Reply text" --parent 0 # reply to comment 0
|
||||
python scripts/comment.py unpacked/ 0 "Text" --author "Custom Author" # custom author name
|
||||
```
|
||||
Then add markers to document.xml (see Comments in XML Reference).
|
||||
|
||||
### Step 3: Pack
|
||||
```bash
|
||||
python scripts/office/pack.py unpacked/ output.docx --original document.docx
|
||||
```
|
||||
Validates with auto-repair, condenses XML, and creates DOCX. Use `--validate false` to skip.
|
||||
|
||||
**Auto-repair will fix:**
|
||||
- `durableId` >= 0x7FFFFFFF (regenerates valid ID)
|
||||
- Missing `xml:space="preserve"` on `<w:t>` with whitespace
|
||||
|
||||
**Auto-repair won't fix:**
|
||||
- Malformed XML, invalid element nesting, missing relationships, schema violations
|
||||
|
||||
### Common Pitfalls
|
||||
|
||||
- **Replace entire `<w:r>` elements**: When adding tracked changes, replace the whole `<w:r>...</w:r>` block with `<w:del>...<w:ins>...` as siblings. Don't inject tracked change tags inside a run.
|
||||
- **Preserve `<w:rPr>` formatting**: Copy the original run's `<w:rPr>` block into your tracked change runs to maintain bold, font size, etc.
|
||||
|
||||
---
|
||||
|
||||
## XML Reference
|
||||
|
||||
### Schema Compliance
|
||||
|
||||
- **Element order in `<w:pPr>`**: `<w:pStyle>`, `<w:numPr>`, `<w:spacing>`, `<w:ind>`, `<w:jc>`, `<w:rPr>` last
|
||||
- **Whitespace**: Add `xml:space="preserve"` to `<w:t>` with leading/trailing spaces
|
||||
- **RSIDs**: Must be 8-digit hex (e.g., `00AB1234`)
|
||||
|
||||
### Tracked Changes
|
||||
|
||||
**Insertion:**
|
||||
```xml
|
||||
<w:ins w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:t>inserted text</w:t></w:r>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
**Deletion:**
|
||||
```xml
|
||||
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>deleted text</w:delText></w:r>
|
||||
</w:del>
|
||||
```
|
||||
|
||||
**Inside `<w:del>`**: Use `<w:delText>` instead of `<w:t>`, and `<w:delInstrText>` instead of `<w:instrText>`.
|
||||
|
||||
**Minimal edits** - only mark what changes:
|
||||
```xml
|
||||
<!-- Change "30 days" to "60 days" -->
|
||||
<w:r><w:t>The term is </w:t></w:r>
|
||||
<w:del w:id="1" w:author="Claude" w:date="...">
|
||||
<w:r><w:delText>30</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:ins w:id="2" w:author="Claude" w:date="...">
|
||||
<w:r><w:t>60</w:t></w:r>
|
||||
</w:ins>
|
||||
<w:r><w:t> days.</w:t></w:r>
|
||||
```
|
||||
|
||||
**Deleting entire paragraphs/list items** - when removing ALL content from a paragraph, also mark the paragraph mark as deleted so it merges with the next paragraph. Add `<w:del/>` inside `<w:pPr><w:rPr>`:
|
||||
```xml
|
||||
<w:p>
|
||||
<w:pPr>
|
||||
<w:numPr>...</w:numPr> <!-- list numbering if present -->
|
||||
<w:rPr>
|
||||
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z"/>
|
||||
</w:rPr>
|
||||
</w:pPr>
|
||||
<w:del w:id="2" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>Entire paragraph content being deleted...</w:delText></w:r>
|
||||
</w:del>
|
||||
</w:p>
|
||||
```
|
||||
Without the `<w:del/>` in `<w:pPr><w:rPr>`, accepting changes leaves an empty paragraph/list item.
|
||||
|
||||
**Rejecting another author's insertion** - nest deletion inside their insertion:
|
||||
```xml
|
||||
<w:ins w:author="Jane" w:id="5">
|
||||
<w:del w:author="Claude" w:id="10">
|
||||
<w:r><w:delText>their inserted text</w:delText></w:r>
|
||||
</w:del>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
**Restoring another author's deletion** - add insertion after (don't modify their deletion):
|
||||
```xml
|
||||
<w:del w:author="Jane" w:id="5">
|
||||
<w:r><w:delText>deleted text</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:ins w:author="Claude" w:id="10">
|
||||
<w:r><w:t>deleted text</w:t></w:r>
|
||||
</w:ins>
|
||||
```
|
||||
|
||||
### Comments
|
||||
|
||||
After running `comment.py` (see Step 2), add markers to document.xml. For replies, use `--parent` flag and nest markers inside the parent's.
|
||||
|
||||
**CRITICAL: `<w:commentRangeStart>` and `<w:commentRangeEnd>` are siblings of `<w:r>`, never inside `<w:r>`.**
|
||||
|
||||
```xml
|
||||
<!-- Comment markers are direct children of w:p, never inside w:r -->
|
||||
<w:commentRangeStart w:id="0"/>
|
||||
<w:del w:id="1" w:author="Claude" w:date="2025-01-01T00:00:00Z">
|
||||
<w:r><w:delText>deleted</w:delText></w:r>
|
||||
</w:del>
|
||||
<w:r><w:t> more text</w:t></w:r>
|
||||
<w:commentRangeEnd w:id="0"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
||||
|
||||
<!-- Comment 0 with reply 1 nested inside -->
|
||||
<w:commentRangeStart w:id="0"/>
|
||||
<w:commentRangeStart w:id="1"/>
|
||||
<w:r><w:t>text</w:t></w:r>
|
||||
<w:commentRangeEnd w:id="1"/>
|
||||
<w:commentRangeEnd w:id="0"/>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="0"/></w:r>
|
||||
<w:r><w:rPr><w:rStyle w:val="CommentReference"/></w:rPr><w:commentReference w:id="1"/></w:r>
|
||||
```
|
||||
|
||||
### Images
|
||||
|
||||
1. Add image file to `word/media/`
|
||||
2. Add relationship to `word/_rels/document.xml.rels`:
|
||||
```xml
|
||||
<Relationship Id="rId5" Type=".../image" Target="media/image1.png"/>
|
||||
```
|
||||
3. Add content type to `[Content_Types].xml`:
|
||||
```xml
|
||||
<Default Extension="png" ContentType="image/png"/>
|
||||
```
|
||||
4. Reference in document.xml:
|
||||
```xml
|
||||
<w:drawing>
|
||||
<wp:inline>
|
||||
<wp:extent cx="914400" cy="914400"/> <!-- EMUs: 914400 = 1 inch -->
|
||||
<a:graphic>
|
||||
<a:graphicData uri=".../picture">
|
||||
<pic:pic>
|
||||
<pic:blipFill><a:blip r:embed="rId5"/></pic:blipFill>
|
||||
</pic:pic>
|
||||
</a:graphicData>
|
||||
</a:graphic>
|
||||
</wp:inline>
|
||||
</w:drawing>
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
- **pandoc**: Text extraction
|
||||
- **docx**: `npm install -g docx` (new documents)
|
||||
- **LibreOffice**: PDF conversion (auto-configured for sandboxed environments via `scripts/office/soffice.py`)
|
||||
- **Poppler**: `pdftoppm` for images
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 前端设计
|
||||
name: frontend-design
|
||||
description: >-
|
||||
Create distinctive, production-grade frontend interfaces with high design
|
||||
quality. Use this skill when the user asks to build web components, pages,
|
||||
@@ -25,6 +25,29 @@ tags:
|
||||
metadata:
|
||||
author: anthropic
|
||||
updated_at: '2026-04-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 前端设计
|
||||
short_desc: 创建有品味、避免 AI 烂大街审美的前端界面与组件
|
||||
description: >-
|
||||
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics. Use when 用户提到 前端设计、网页设计、UI 设计、 界面设计、组件、海报、Landing Page、落地页、React 组件、Vue 组件、 CSS 样式、美化界面、设计一个、做一个网页、官网、仪表盘、Dashboard。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:136983c7c029579c
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Frontend Design
|
||||
short_desc: Create tasteful frontend interfaces and components that avoid generic AI aesthetics
|
||||
description: >-
|
||||
Create distinctive, production-grade frontend interfaces with high design quality. Use this skill when the user asks to build web components, pages, artifacts, posters, or applications (examples include websites, landing pages, dashboards, React components, HTML/CSS layouts, or when styling/beautifying any web UI). Generates creative, polished code and UI design that avoids generic AI aesthetics. Use when the user mentions frontend design, web design, UI design, interface design, components, posters, landing pages, React components, Vue components, CSS styling, polishing the UI, designing something, building a webpage, official site, or dashboard.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:136983c7c029579c
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -40,7 +63,6 @@ market:
|
||||
fill="url(#fd-a)" fill-opacity="0.2" stroke="url(#fd-a)"
|
||||
stroke-width="1"/><path d="M14 11h5M14 13.5h3.5M14 16h4.5"
|
||||
stroke="url(#fd-a)" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
short_desc: 创建有品味、避免 AI 烂大街审美的前端界面与组件
|
||||
category: design
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -48,35 +70,35 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# frontend-design 技能
|
||||
# frontend-design Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
创建有品味、避免 AI 烂大街审美的高质量前端界面与组件。
|
||||
Create tasteful, production-grade frontend interfaces and components that avoid generic AI aesthetics.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
frontend-design 是一个**流程型技能(Procedural Skill)**,引导创建独特、生产级的前端界面,避免千篇一律的 AI 生成审美。输出真实可运行的代码,注重美学细节和创意选择。
|
||||
frontend-design is a **Procedural Skill** that guides the creation of distinctive, production-grade frontend interfaces while avoiding cookie-cutter AI-generated aesthetics. It outputs real, runnable code with attention to aesthetic detail and creative choices.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要创建网页组件、页面或应用(Landing Page、仪表盘、React 组件等)
|
||||
- 用户需要为现有 Web UI 进行样式美化
|
||||
- 用户需要创建海报、视觉设计等前端产出物
|
||||
- The user needs to create web components, pages, or applications (landing pages, Dashboards, React components, etc.)
|
||||
- The user needs to polish the styling of an existing web UI
|
||||
- The user needs to create posters, visual designs, or other frontend deliverables
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **反 AI 审美**:拒绝 Inter 字体 + 紫色渐变的烂大街风格
|
||||
- **设计思维驱动**:先确定美学方向,再编写代码
|
||||
- **生产级质量**:输出可直接使用的完整代码
|
||||
- **Anti-AI aesthetics**: rejects the cliched Inter font + purple gradient style
|
||||
- **Design-thinking driven**: settle on an aesthetic direction first, then write code
|
||||
- **Production-grade quality**: outputs complete, ready-to-use code
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify HTML/CSS/JS/React/Vue files, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/index.html`"
|
||||
When you create or modify HTML/CSS/JS/React/Vue files, you **MUST** tell the user the absolute path of the output file in your response. Example: "File saved to: `/path/to/index.html`"
|
||||
|
||||
If you create multiple files (e.g. HTML + CSS + JS), list each path explicitly.
|
||||
|
||||
|
||||
79
skills/frontend-design/SKILL.zh-CN.md
Normal file
79
skills/frontend-design/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,79 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# frontend-design 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
创建有品味、避免 AI 烂大街审美的高质量前端界面与组件。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
frontend-design 是一个**流程型技能(Procedural Skill)**,引导创建独特、生产级的前端界面,避免千篇一律的 AI 生成审美。输出真实可运行的代码,注重美学细节和创意选择。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要创建网页组件、页面或应用(Landing Page、仪表盘、React 组件等)
|
||||
- 用户需要为现有 Web UI 进行样式美化
|
||||
- 用户需要创建海报、视觉设计等前端产出物
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **反 AI 审美**:拒绝 Inter 字体 + 紫色渐变的烂大街风格
|
||||
- **设计思维驱动**:先确定美学方向,再编写代码
|
||||
- **生产级质量**:输出可直接使用的完整代码
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify HTML/CSS/JS/React/Vue files, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/index.html`"
|
||||
|
||||
If you create multiple files (e.g. HTML + CSS + JS), list each path explicitly.
|
||||
|
||||
## Design Thinking
|
||||
|
||||
Before coding, understand the context and commit to a BOLD aesthetic direction:
|
||||
- **Purpose**: What problem does this interface solve? Who uses it?
|
||||
- **Tone**: Pick an extreme: brutally minimal, maximalist chaos, retro-futuristic, organic/natural, luxury/refined, playful/toy-like, editorial/magazine, brutalist/raw, art deco/geometric, soft/pastel, industrial/utilitarian, etc. There are so many flavors to choose from. Use these for inspiration but design one that is true to the aesthetic direction.
|
||||
- **Constraints**: Technical requirements (framework, performance, accessibility).
|
||||
- **Differentiation**: What makes this UNFORGETTABLE? What's the one thing someone will remember?
|
||||
|
||||
**CRITICAL**: Choose a clear conceptual direction and execute it with precision. Bold maximalism and refined minimalism both work - the key is intentionality, not intensity.
|
||||
|
||||
Then implement working code (HTML/CSS/JS, React, Vue, etc.) that is:
|
||||
- Production-grade and functional
|
||||
- Visually striking and memorable
|
||||
- Cohesive with a clear aesthetic point-of-view
|
||||
- Meticulously refined in every detail
|
||||
|
||||
## Frontend Aesthetics Guidelines
|
||||
|
||||
Focus on:
|
||||
- **Typography**: Choose fonts that are beautiful, unique, and interesting. Avoid generic fonts like Arial and Inter; opt instead for distinctive choices that elevate the frontend's aesthetics; unexpected, characterful font choices. Pair a distinctive display font with a refined body font.
|
||||
- **Color & Theme**: Commit to a cohesive aesthetic. Use CSS variables for consistency. Dominant colors with sharp accents outperform timid, evenly-distributed palettes.
|
||||
- **Motion**: Use animations for effects and micro-interactions. Prioritize CSS-only solutions for HTML. Use Motion library for React when available. Focus on high-impact moments: one well-orchestrated page load with staggered reveals (animation-delay) creates more delight than scattered micro-interactions. Use scroll-triggering and hover states that surprise.
|
||||
- **Spatial Composition**: Unexpected layouts. Asymmetry. Overlap. Diagonal flow. Grid-breaking elements. Generous negative space OR controlled density.
|
||||
- **Backgrounds & Visual Details**: Create atmosphere and depth rather than defaulting to solid colors. Add contextual effects and textures that match the overall aesthetic. Apply creative forms like gradient meshes, noise textures, geometric patterns, layered transparencies, dramatic shadows, decorative borders, custom cursors, and grain overlays.
|
||||
|
||||
NEVER use generic AI-generated aesthetics like overused font families (Inter, Roboto, Arial, system fonts), cliched color schemes (particularly purple gradients on white backgrounds), predictable layouts and component patterns, and cookie-cutter design that lacks context-specific character.
|
||||
|
||||
Interpret creatively and make unexpected choices that feel genuinely designed for the context. No design should be the same. Vary between light and dark themes, different fonts, different aesthetics. NEVER converge on common choices (Space Grotesk, for example) across generations.
|
||||
|
||||
**IMPORTANT**: Match implementation complexity to the aesthetic vision. Maximalist designs need elaborate code with extensive animations and effects. Minimalist or refined designs need restraint, precision, and careful attention to spacing, typography, and subtle details. Elegance comes from executing the vision well.
|
||||
|
||||
Remember: Claude is capable of extraordinary creative work. Don't hold back, show what can truly be created when thinking outside the box and committing fully to a distinctive vision.
|
||||
|
||||
---
|
||||
|
||||
## Project Context Override (DesireCore Specific)
|
||||
|
||||
> **Note**: When working **inside the DesireCore main repository** (`desirecore-9` or any project that has `app/styles/globals.css` with the DesireCore 3+2 token system), the project's strict design system **OVERRIDES** the bold aesthetic guidance above. In that context:
|
||||
>
|
||||
> - Use only the 3 functional colors (Green / Blue / Purple) + 2 status colors (Orange / Red) defined in `globals.css`
|
||||
> - Reference design tokens via CSS variables (`var(--accent-green)`, etc.) — never hardcoded hex
|
||||
> - Follow the typography, radius, and spacing tokens already defined
|
||||
> - The "avoid generic AI aesthetics" principle still applies, but expression happens through layout/composition/motion, not color expansion
|
||||
>
|
||||
> For **standalone artifacts, posters, landing pages, or external projects**, the full aesthetic freedom of this skill applies — go bold.
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 邮箱操作
|
||||
name: mail-operations
|
||||
description: >-
|
||||
Use this skill whenever the user wants to interact with email. This includes
|
||||
reading inbox, sending emails, replying, searching messages, managing labels
|
||||
@@ -24,6 +24,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 邮箱操作
|
||||
short_desc: 邮件收发、搜索、标签管理、自动规则与智能体邮件处理
|
||||
description: >-
|
||||
Use this skill whenever the user wants to interact with email. This includes reading inbox, sending emails, replying, searching messages, managing labels and categories, downloading attachments, setting up auto-reply rules, or triggering agents to handle incoming emails. Supports Gmail, Outlook, and IMAP/SMTP (QQ Mail, 163, Yahoo, etc.) through DesireCore's local REST API. Use when 用户提到 邮件、邮箱、收件箱、发邮件、回复邮件、查邮件、Gmail、 Outlook、QQ邮箱、163邮箱、附件、标签、草稿、自动回复、邮件规则、 转发、抄送、未读邮件、收信、发信、邮件同步、邮件搜索。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:24bffbade0dc09a7
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Email Operations
|
||||
short_desc: Email send/receive, search, label management, auto-rules, and Agent-driven email handling
|
||||
description: >-
|
||||
Use this skill whenever the user wants to interact with email. This includes reading inbox, sending emails, replying, searching messages, managing labels and categories, downloading attachments, setting up auto-reply rules, or triggering agents to handle incoming emails. Supports Gmail, Outlook, and IMAP/SMTP (QQ Mail, 163, Yahoo, etc.) through DesireCore's local REST API. Use when the user mentions email, mailbox, inbox, sending email, replying, checking email, Gmail, Outlook, QQ Mail, 163 Mail, attachments, labels, drafts, auto-reply, email rules, forwarding, CC, unread email, receiving, sending, email sync, or email search.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:24bffbade0dc09a7
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -34,7 +57,6 @@ market:
|
||||
stroke="url(#ml-a)" stroke-width="1.5"/><path d="m22 7-8.97 5.7a1.94 1.94
|
||||
0 0 1-2.06 0L2 7" stroke="url(#ml-a)" stroke-width="1.5"
|
||||
stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
short_desc: 邮件收发、搜索、标签管理、自动规则与智能体邮件处理
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -42,281 +64,281 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# mail-operations 技能
|
||||
# mail-operations Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
通过本地 REST API 收发邮件、搜索、标签管理和自动规则,支持 Gmail / Outlook / IMAP。
|
||||
Send and receive email, search, manage labels, and run automation rules via a local REST API; supports Gmail / Outlook / IMAP.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
mail-operations 是一个**流程型技能(Procedural Skill)**,通过 DesireCore 本地 REST API 操作邮件系统。支持 Gmail(OAuth2)、Outlook(MSAL)和 IMAP/SMTP(QQ、163、Yahoo 等)三种邮箱类型,涵盖收发邮件、搜索、标签管理、附件下载、草稿管理和自动规则。
|
||||
mail-operations is a **Procedural Skill** that operates email systems through DesireCore's local REST API. It supports three mailbox types—Gmail (OAuth2), Outlook (MSAL), and IMAP/SMTP (QQ, 163, Yahoo, etc.)—covering send/receive, search, label management, attachment download, draft management, and automation rules.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要查看收件箱、发送或回复邮件
|
||||
- 用户需要搜索特定邮件或管理邮件标签/分类
|
||||
- 用户需要下载附件或管理草稿
|
||||
- 用户需要设置自动回复规则或触发智能体处理邮件
|
||||
- The user wants to view the inbox, send, or reply to email
|
||||
- The user wants to search for specific emails or manage email labels/categories
|
||||
- The user wants to download attachments or manage drafts
|
||||
- The user wants to set up auto-reply rules or trigger an Agent to handle email
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **统一接口**:三种邮箱通过统一 API 操作,降低使用复杂度
|
||||
- **本地安全**:所有操作通过本地 API 完成,无需暴露凭证
|
||||
- **智能联动**:支持自动规则和智能体邮件处理
|
||||
- **Unified interface**: three mailbox types are operated through a unified API, lowering complexity
|
||||
- **Local and secure**: all operations go through the local API; no need to expose credentials
|
||||
- **Smart integration**: supports automation rules and Agent-based email handling
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## API 基础信息
|
||||
## API Basics
|
||||
|
||||
- **Base URL**: `https://127.0.0.1:62000/api`
|
||||
- **认证**: 无需认证(本地服务)
|
||||
- **Authentication**: none required (local service)
|
||||
- **Content-Type**: `application/json`
|
||||
- **SSL**: 使用 `curl -k` 跳过自签名证书验证
|
||||
- **响应格式**: 成功 `{"code": 1, "msg": "Success", "result": ...}`,失败 `{"code": 0, "msg": "错误信息"}`
|
||||
- **SSL**: use `curl -k` to skip self-signed certificate verification
|
||||
- **Response format**: success `{"code": 1, "msg": "Success", "result": ...}`, failure `{"code": 0, "msg": "error message"}`
|
||||
|
||||
---
|
||||
|
||||
## 强制行为规则
|
||||
## Mandatory Behavior Rules
|
||||
|
||||
以下规则优先级最高,每次操作必须遵守。
|
||||
The following rules have the highest priority and must be obeyed on every operation.
|
||||
|
||||
### 规则 1:只能通过本地 API 操作
|
||||
### Rule 1: Operate Only Through the Local API
|
||||
|
||||
所有邮件操作**必须且只能**通过 `https://127.0.0.1:62000` 完成。**禁止**调用外部邮件客户端或浏览器。
|
||||
All email operations **must and may only** be done through `https://127.0.0.1:62000`. **Never** call an external email client or browser.
|
||||
|
||||
如果 API 返回 **401(授权过期)**:
|
||||
1. 告知用户该账户授权已失效
|
||||
2. 提示在 DesireCore 中重新授权
|
||||
3. Gmail: `POST /api/gmail/auth/initiate?loginHint={email}`,Outlook: `POST /api/outlook/auth/initiate`
|
||||
If the API returns **401 (authorization expired)**:
|
||||
1. Tell the user the account's authorization has expired
|
||||
2. Prompt the user to re-authorize in DesireCore
|
||||
3. Gmail: `POST /api/gmail/auth/initiate?loginHint={email}`, Outlook: `POST /api/outlook/auth/initiate`
|
||||
|
||||
### 规则 2:操作前先确认账户
|
||||
### Rule 2: Confirm the Account Before Operating
|
||||
|
||||
执行任何操作前,**必须先调用 `GET /api/accounts`** 获取账户列表:
|
||||
- 按邮箱地址或域名匹配用户指定的账户("QQ 邮箱"→ imap 中 `qq.com`)
|
||||
- 仅有一个账户且用户说"我的邮箱"→ 直接使用
|
||||
- 找不到匹配账户 → 告知用户并提示添加
|
||||
Before performing any operation, **you must first call `GET /api/accounts`** to obtain the account list:
|
||||
- Match the user's specified account by email address or domain ("QQ mailbox" → IMAP `qq.com`)
|
||||
- Only one account exists and the user says "my mailbox" → use it directly
|
||||
- No matching account found → tell the user and prompt them to add one
|
||||
|
||||
### 规则 3:查询为空时自动同步
|
||||
### Rule 3: Auto-Sync When the Query Is Empty
|
||||
|
||||
查询返回空列表或找不到指定数据时:
|
||||
1. 调用 `POST /{provider}/messages/fetch` 同步远程数据
|
||||
2. **自动重试**原查询
|
||||
3. 仍为空才告知用户
|
||||
When a query returns an empty list or cannot find the specified data:
|
||||
1. Call `POST /{provider}/messages/fetch` to sync remote data
|
||||
2. **Automatically retry** the original query
|
||||
3. Only inform the user if it is still empty
|
||||
|
||||
### 规则 4:写操作后提示刷新
|
||||
### Rule 4: Prompt for a Refresh After Write Operations
|
||||
|
||||
发送、回复、删除、标记、标签变更等写操作成功后,提示:`操作已完成。需要我帮你刷新当前邮箱页面以查看最新状态吗?`
|
||||
After a write operation (send, reply, delete, mark, label change, etc.) succeeds, prompt: `Operation completed. Do you want me to refresh the current mailbox view to see the latest state?`
|
||||
|
||||
---
|
||||
|
||||
## 三种邮箱的差异速查
|
||||
## Quick Reference: Differences Between the Three Mailbox Types
|
||||
|
||||
| 功能 | Gmail | Outlook | IMAP |
|
||||
| Feature | Gmail | Outlook | IMAP |
|
||||
|------|-------|---------|------|
|
||||
| 授权 | OAuth2 | OAuth2 (MSAL) | 密码/授权码 |
|
||||
| Provider 路径 | `/gmail/` | `/outlook/` | `/imap/` |
|
||||
| 邮件详情 | 路径参数 `/{id}` | 查询参数 `?id={id}` | UID `/{uid}?folder=` |
|
||||
| 搜索 | 支持 | 不支持 | 不支持 |
|
||||
| 草稿 | 支持(含列表/详情) | 支持(创建/发送) | 支持(创建/发送) |
|
||||
| 附件下载 | 支持 | 支持 | 支持 |
|
||||
| 标签/分类 | 原生标签 | Categories | 仅本地标签 |
|
||||
| 自动规则 | 支持 | 支持 | 支持 |
|
||||
| Authorization | OAuth2 | OAuth2 (MSAL) | password / app password |
|
||||
| Provider path | `/gmail/` | `/outlook/` | `/imap/` |
|
||||
| Message detail | path param `/{id}` | query param `?id={id}` | UID `/{uid}?folder=` |
|
||||
| Search | supported | not supported | not supported |
|
||||
| Drafts | supported (incl. list/detail) | supported (create/send) | supported (create/send) |
|
||||
| Attachment download | supported | supported | supported |
|
||||
| Labels/categories | native labels | Categories | local labels only |
|
||||
| Auto-rules | supported | supported | supported |
|
||||
|
||||
---
|
||||
|
||||
## 核心操作
|
||||
## Core Operations
|
||||
|
||||
以下 `{p}` 代表 provider(`gmail`、`outlook`、`imap`),`{email}` 需 URL 编码。
|
||||
In the following, `{p}` denotes the provider (`gmail`, `outlook`, `imap`); `{email}` must be URL-encoded.
|
||||
|
||||
### 1. 账户管理
|
||||
### 1. Account Management
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取所有账户 | GET | `/accounts` |
|
||||
| 获取账户含设置 | GET | `/accounts-with-settings` |
|
||||
| 删除账户 | DELETE | `/accounts/{p}/{email}` |
|
||||
| 获取账户设置 | GET | `/accounts/{p}/{email}/settings` |
|
||||
| 更新账户设置 | PUT | `/accounts/{p}/{email}/settings` |
|
||||
| 更新显示名称 | PUT | `/accounts/{p}/{email}/displayName` — body: `{"displayName": "..."}` |
|
||||
| Get all accounts | GET | `/accounts` |
|
||||
| Get accounts with settings | GET | `/accounts-with-settings` |
|
||||
| Delete account | DELETE | `/accounts/{p}/{email}` |
|
||||
| Get account settings | GET | `/accounts/{p}/{email}/settings` |
|
||||
| Update account settings | PUT | `/accounts/{p}/{email}/settings` |
|
||||
| Update display name | PUT | `/accounts/{p}/{email}/displayName` — body: `{"displayName": "..."}` |
|
||||
|
||||
**IMAP 专属**:
|
||||
**IMAP-specific**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取预设邮箱配置 | GET | `/imap/presets` — 返回 QQ/163/Yahoo 等服务器配置 |
|
||||
| 测试 IMAP 连接 | POST | `/imap/test` — body: `{email, password, imap: {host, port, secure}, smtp: {host, port, secure}}` |
|
||||
| 添加 IMAP 账户 | POST | `/imap/accounts` — body 同上,加 `displayName` |
|
||||
| Get preset mailbox configs | GET | `/imap/presets` — returns server configs for QQ/163/Yahoo, etc. |
|
||||
| Test IMAP connection | POST | `/imap/test` — body: `{email, password, imap: {host, port, secure}, smtp: {host, port, secure}}` |
|
||||
| Add IMAP account | POST | `/imap/accounts` — same body as above plus `displayName` |
|
||||
|
||||
### 2. 邮件列表与同步
|
||||
### 2. Message List and Sync
|
||||
|
||||
| 操作 | 方法 | 端点 | 参数 |
|
||||
| Operation | Method | Endpoint | Parameters |
|
||||
|------|------|------|------|
|
||||
| 查询本地缓存 | GET | `/{p}/messages` | `email, offset, limit, folder` |
|
||||
| 远程同步 | POST | `/{p}/messages/fetch` | `email, limit, folder` |
|
||||
| 手动触发同步 | POST | `/sync` | `provider, email` |
|
||||
| Query local cache | GET | `/{p}/messages` | `email, offset, limit, folder` |
|
||||
| Remote sync | POST | `/{p}/messages/fetch` | `email, limit, folder` |
|
||||
| Manually trigger sync | POST | `/sync` | `provider, email` |
|
||||
|
||||
**folder 取值**:Gmail/Outlook: `inbox, sent, drafts, trash, spam, archive`;IMAP: `INBOX, Sent, Drafts, Trash` 等。
|
||||
**folder values**: Gmail/Outlook: `inbox, sent, drafts, trash, spam, archive`; IMAP: `INBOX, Sent, Drafts, Trash`, etc.
|
||||
|
||||
**响应格式**(邮件列表项):
|
||||
**Response format** (message list item):
|
||||
```json
|
||||
{
|
||||
"id": "消息ID", "subject": "主题",
|
||||
"id": "messageID", "subject": "subject",
|
||||
"from": {"name": "...", "address": "..."},
|
||||
"to": [{"name": "...", "address": "..."}],
|
||||
"date": "ISO8601", "snippet": "摘要",
|
||||
"date": "ISO8601", "snippet": "snippet",
|
||||
"isRead": true, "hasAttachments": false,
|
||||
"labels": ["INBOX"], "folder": "inbox"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 单封邮件操作
|
||||
### 3. Single Message Operations
|
||||
|
||||
| 操作 | Gmail | Outlook | IMAP |
|
||||
| Operation | Gmail | Outlook | IMAP |
|
||||
|------|-------|---------|------|
|
||||
| 获取详情 | GET `/{id}?email=` | GET `/message?id={id}&email=` | GET `/{uid}?email=&folder=` |
|
||||
| 标记已读 | POST `/{id}/read?email=` | POST `/message/read?id={id}&email=` | POST `/{uid}/read?email=&folder=` |
|
||||
| 标记未读 | POST `/{id}/unread?email=` | POST `/message/unread?id={id}&email=` | POST `/{uid}/unread?email=&folder=` |
|
||||
| 删除 | DELETE `/{id}?email=` | DELETE `/message?id={id}&email=` | DELETE `/{uid}?email=&folder=` |
|
||||
| Get detail | GET `/{id}?email=` | GET `/message?id={id}&email=` | GET `/{uid}?email=&folder=` |
|
||||
| Mark as read | POST `/{id}/read?email=` | POST `/message/read?id={id}&email=` | POST `/{uid}/read?email=&folder=` |
|
||||
| Mark as unread | POST `/{id}/unread?email=` | POST `/message/unread?id={id}&email=` | POST `/{uid}/unread?email=&folder=` |
|
||||
| Delete | DELETE `/{id}?email=` | DELETE `/message?id={id}&email=` | DELETE `/{uid}?email=&folder=` |
|
||||
|
||||
> 所有路径前缀为 `/api/{provider}/messages`(Gmail/IMAP)或 `/api/outlook/`(Outlook 特殊路由)。
|
||||
> All paths are prefixed with `/api/{provider}/messages` (Gmail/IMAP) or `/api/outlook/` (Outlook's special routing).
|
||||
|
||||
**邮件详情额外字段**:`body: {content, contentType}`, `cc`, `attachments: [{id, filename, mimeType, size}]`
|
||||
**Extra fields in message detail**: `body: {content, contentType}`, `cc`, `attachments: [{id, filename, mimeType, size}]`
|
||||
|
||||
### 4. 发送与回复
|
||||
### 4. Send and Reply
|
||||
|
||||
**发送新邮件** — `POST /api/{p}/send`:
|
||||
**Send a new email** — `POST /api/{p}/send`:
|
||||
```json
|
||||
{
|
||||
"email": "sender@example.com",
|
||||
"toRecipients": [{"name": "收件人", "address": "to@example.com"}],
|
||||
"toRecipients": [{"name": "recipient", "address": "to@example.com"}],
|
||||
"ccRecipients": [],
|
||||
"bccRecipients": [],
|
||||
"subject": "主题",
|
||||
"body": "正文(支持 HTML)",
|
||||
"subject": "subject",
|
||||
"body": "body (HTML supported)",
|
||||
"contentType": "html",
|
||||
"attachments": []
|
||||
}
|
||||
```
|
||||
|
||||
**回复邮件**:
|
||||
**Reply to an email**:
|
||||
|
||||
| Provider | 端点 | Body |
|
||||
| Provider | Endpoint | Body |
|
||||
|----------|------|------|
|
||||
| Gmail | POST `/gmail/reply` | `{email, messageId, body, contentType}` |
|
||||
| Outlook | POST `/outlook/message/reply?id={id}&email=` | `{body, contentType}` |
|
||||
| IMAP | POST `/imap/reply` | `{email, uid, folder, body, contentType}` |
|
||||
|
||||
### 5. 搜索(仅 Gmail)
|
||||
### 5. Search (Gmail only)
|
||||
|
||||
`GET /api/gmail/search?email={email}&q={keyword}`
|
||||
|
||||
| 参数 | 说明 |
|
||||
| Parameter | Description |
|
||||
|------|------|
|
||||
| `q` | 关键词(搜索主题、正文、发件人) |
|
||||
| `from` | 发件人地址 |
|
||||
| `dateFrom` / `dateTo` | 日期范围 YYYY-MM-DD |
|
||||
| `q` | keyword (searches subject, body, sender) |
|
||||
| `from` | sender address |
|
||||
| `dateFrom` / `dateTo` | date range YYYY-MM-DD |
|
||||
| `hasAttachment` | true/false |
|
||||
| `isUnread` | true/false |
|
||||
| `offset` / `limit` | 分页 |
|
||||
| `offset` / `limit` | pagination |
|
||||
|
||||
### 6. 附件下载
|
||||
### 6. Attachment Download
|
||||
|
||||
| Provider | 方法 | 端点 | Body |
|
||||
| Provider | Method | Endpoint | Body |
|
||||
|----------|------|------|------|
|
||||
| Gmail | POST | `/gmail/messages/{messageId}/attachment` | `{email, attachmentId}` |
|
||||
| Outlook | POST | `/outlook/attachment` | `{email, messageId, attachmentId}` |
|
||||
| IMAP | POST | `/imap/attachment` | `{email, uid, folder, partId}` |
|
||||
|
||||
响应 `result.data` 为 base64 编码,解码后保存文件。
|
||||
The response `result.data` is base64-encoded; decode it and save to a file.
|
||||
|
||||
> Gmail 使用 POST 因为 attachmentId 可能超出 URL 长度限制。
|
||||
> Gmail uses POST because the attachmentId may exceed URL length limits.
|
||||
|
||||
### 7. 草稿管理
|
||||
### 7. Draft Management
|
||||
|
||||
**Gmail**:
|
||||
**Gmail**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取草稿列表 | GET | `/gmail/drafts?email=&limit=` |
|
||||
| 获取草稿详情 | GET | `/gmail/drafts/{draftId}?email=` |
|
||||
| 创建草稿 | POST | `/gmail/drafts` — body: `{email, to, cc, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/gmail/drafts/{draftId}` — body 同创建 |
|
||||
| 删除草稿 | DELETE | `/gmail/drafts/{draftId}?email=` |
|
||||
| List drafts | GET | `/gmail/drafts?email=&limit=` |
|
||||
| Get draft detail | GET | `/gmail/drafts/{draftId}?email=` |
|
||||
| Create draft | POST | `/gmail/drafts` — body: `{email, to, cc, subject, body, contentType}` |
|
||||
| Update draft | PUT | `/gmail/drafts/{draftId}` — same body as create |
|
||||
| Delete draft | DELETE | `/gmail/drafts/{draftId}?email=` |
|
||||
|
||||
**Outlook**:
|
||||
**Outlook**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 创建草稿 | POST | `/outlook/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/outlook/drafts?id={draftId}&email=` — body 同创建 |
|
||||
| 删除草稿 | DELETE | `/outlook/drafts?id={draftId}&email=` |
|
||||
| 发送草稿 | POST | `/outlook/drafts/send?id={draftId}&email=` |
|
||||
| Create draft | POST | `/outlook/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| Update draft | PUT | `/outlook/drafts?id={draftId}&email=` — same body as create |
|
||||
| Delete draft | DELETE | `/outlook/drafts?id={draftId}&email=` |
|
||||
| Send draft | POST | `/outlook/drafts/send?id={draftId}&email=` |
|
||||
|
||||
**IMAP**:
|
||||
**IMAP**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 创建草稿 | POST | `/imap/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/imap/drafts/{uid}` — body: `{email, folder, toRecipients, subject, body, contentType}` |
|
||||
| 删除草稿 | DELETE | `/imap/drafts/{uid}?email=&folder=` |
|
||||
| 发送草稿 | POST | `/imap/drafts/{uid}/send` — body: `{email, folder}` |
|
||||
| Create draft | POST | `/imap/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| Update draft | PUT | `/imap/drafts/{uid}` — body: `{email, folder, toRecipients, subject, body, contentType}` |
|
||||
| Delete draft | DELETE | `/imap/drafts/{uid}?email=&folder=` |
|
||||
| Send draft | POST | `/imap/drafts/{uid}/send` — body: `{email, folder}` |
|
||||
|
||||
### 8. 标签管理(统一接口)
|
||||
### 8. Label Management (Unified Interface)
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取标签列表 | GET | `/labels?provider=&email=` |
|
||||
| 获取单个标签 | GET | `/labels/{labelId}` |
|
||||
| 创建标签 | POST | `/labels` — body: `{name, color, provider, email, visible}` |
|
||||
| 更新标签 | PUT | `/labels/{labelId}` — body: `{name, color, order, visible}` |
|
||||
| 删除标签 | DELETE | `/labels/{labelId}` |
|
||||
| 获取邮件标签 | GET | `/mails/{p}/{email}/labels?mailId=` |
|
||||
| 添加邮件标签 | POST | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelId": "..."}` |
|
||||
| 批量设置标签 | PUT | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelIds": [...]}` |
|
||||
| 移除邮件标签 | DELETE | `/mails/{p}/{email}/labels?mailId=&labelId=` |
|
||||
| 获取标签下邮件 | GET | `/labels/{labelId}/mails?provider=&email=&limit=&offset=` |
|
||||
| List labels | GET | `/labels?provider=&email=` |
|
||||
| Get a single label | GET | `/labels/{labelId}` |
|
||||
| Create label | POST | `/labels` — body: `{name, color, provider, email, visible}` |
|
||||
| Update label | PUT | `/labels/{labelId}` — body: `{name, color, order, visible}` |
|
||||
| Delete label | DELETE | `/labels/{labelId}` |
|
||||
| Get email's labels | GET | `/mails/{p}/{email}/labels?mailId=` |
|
||||
| Add label to email | POST | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelId": "..."}` |
|
||||
| Bulk set labels | PUT | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelIds": [...]}` |
|
||||
| Remove label from email | DELETE | `/mails/{p}/{email}/labels?mailId=&labelId=` |
|
||||
| Get emails under a label | GET | `/labels/{labelId}/mails?provider=&email=&limit=&offset=` |
|
||||
|
||||
**Gmail 原生标签**:
|
||||
- 获取标签列表:`GET /api/gmail/labels?email=`
|
||||
- 修改邮件标签:`POST /api/gmail/messages/{id}/labels` — body: `{email, addLabelIds, removeLabelIds}`
|
||||
- 同步远程标签:`POST /api/gmail/labels/sync?email=`
|
||||
**Gmail native labels**:
|
||||
- List labels: `GET /api/gmail/labels?email=`
|
||||
- Modify message labels: `POST /api/gmail/messages/{id}/labels` — body: `{email, addLabelIds, removeLabelIds}`
|
||||
- Sync remote labels: `POST /api/gmail/labels/sync?email=`
|
||||
|
||||
### 9. Outlook 分类
|
||||
### 9. Outlook Categories
|
||||
|
||||
Outlook 使用 Categories 而非 Labels。
|
||||
Outlook uses Categories instead of Labels.
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取分类 | GET | `/outlook/categories?email=` |
|
||||
| 同步分类 | POST | `/outlook/categories/sync?email=` |
|
||||
| 创建分类 | POST | `/outlook/categories/create?email=` — body: `{displayName, color}` |
|
||||
| 更新分类 | PUT | `/outlook/categories/update?email=&categoryId=` — body: `{displayName, color}` |
|
||||
| 删除分类 | DELETE | `/outlook/categories/delete?email=&categoryId=` |
|
||||
| 修改邮件分类 | POST | `/outlook/message/categories?id=&email=` — body: `{addCategories, removeCategories}` |
|
||||
| Get categories | GET | `/outlook/categories?email=` |
|
||||
| Sync categories | POST | `/outlook/categories/sync?email=` |
|
||||
| Create category | POST | `/outlook/categories/create?email=` — body: `{displayName, color}` |
|
||||
| Update category | PUT | `/outlook/categories/update?email=&categoryId=` — body: `{displayName, color}` |
|
||||
| Delete category | DELETE | `/outlook/categories/delete?email=&categoryId=` |
|
||||
| Modify message categories | POST | `/outlook/message/categories?id=&email=` — body: `{addCategories, removeCategories}` |
|
||||
|
||||
> `color` 使用 Outlook 预设值 `preset0` ~ `preset24`。
|
||||
> `color` uses Outlook preset values `preset0` ~ `preset24`.
|
||||
|
||||
### 10. 自动规则
|
||||
### 10. Automation Rules
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| 获取所有规则 | GET | `/rules?provider=&email=` |
|
||||
| 获取单个规则 | GET | `/rules/{ruleId}` |
|
||||
| 创建规则 | POST | `/rules` |
|
||||
| 更新规则 | PUT | `/rules/{ruleId}` |
|
||||
| 删除规则 | DELETE | `/rules/{ruleId}` |
|
||||
| 启用/禁用 | POST | `/rules/{ruleId}/toggle` |
|
||||
| 对邮件执行规则 | POST | `/rules/execute` — body: `{provider, email, mailId}` |
|
||||
| 测试规则匹配 | POST | `/rules/{ruleId}/test` — body 同上 |
|
||||
| List all rules | GET | `/rules?provider=&email=` |
|
||||
| Get a single rule | GET | `/rules/{ruleId}` |
|
||||
| Create rule | POST | `/rules` |
|
||||
| Update rule | PUT | `/rules/{ruleId}` |
|
||||
| Delete rule | DELETE | `/rules/{ruleId}` |
|
||||
| Enable/disable | POST | `/rules/{ruleId}/toggle` |
|
||||
| Run rule on a message | POST | `/rules/execute` — body: `{provider, email, mailId}` |
|
||||
| Test rule match | POST | `/rules/{ruleId}/test` — same body as above |
|
||||
|
||||
**创建规则 body**:
|
||||
**Create rule body**:
|
||||
```json
|
||||
{
|
||||
"name": "规则名",
|
||||
"description": "说明",
|
||||
"name": "rule name",
|
||||
"description": "description",
|
||||
"provider": "gmail",
|
||||
"email": "xxx@gmail.com",
|
||||
"enabled": true,
|
||||
@@ -332,60 +354,60 @@ Outlook 使用 Categories 而非 Labels。
|
||||
}
|
||||
```
|
||||
|
||||
**动作类型说明**:
|
||||
**Action types**:
|
||||
|
||||
| type | value | 说明 |
|
||||
| type | value | Description |
|
||||
|------|-------|------|
|
||||
| `add_label` | 标签 ID | 添加标签 |
|
||||
| `remove_label` | 标签 ID | 移除标签 |
|
||||
| `mark_as_read` | 省略 | 标记已读 |
|
||||
| `mark_as_unread` | 省略 | 标记未读 |
|
||||
| `archive` | 省略 | 归档 |
|
||||
| `delete` | 省略 | 删除 |
|
||||
| `auto_reply` | 回复文本 | 自动回复固定内容 |
|
||||
| `agent_handle` | Agent ID | 触发智能体处理邮件 |
|
||||
| `add_label` | label ID | add a label |
|
||||
| `remove_label` | label ID | remove a label |
|
||||
| `mark_as_read` | omit | mark as read |
|
||||
| `mark_as_unread` | omit | mark as unread |
|
||||
| `archive` | omit | archive |
|
||||
| `delete` | omit | delete |
|
||||
| `auto_reply` | reply text | auto-reply with fixed content |
|
||||
| `agent_handle` | Agent ID | trigger an Agent to handle the email |
|
||||
|
||||
> 规则在轮询引擎检测到新邮件时**自动执行**,无需手动调用。`auto_reply` 和 `agent_handle` 支持全部三种邮箱类型。
|
||||
> Rules are **executed automatically** when the polling engine detects a new email; no manual call is required. `auto_reply` and `agent_handle` support all three mailbox types.
|
||||
|
||||
### 11. 授权管理
|
||||
### 11. Authorization Management
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| Gmail OAuth | POST | `/gmail/auth/initiate?loginHint={email}` — 打开浏览器授权 |
|
||||
| Gmail 状态 | GET | `/gmail/auth/status?email=` |
|
||||
| Outlook OAuth | POST | `/outlook/auth/initiate` — 打开浏览器授权 |
|
||||
| Outlook 状态 | GET | `/outlook/auth/status?email=` |
|
||||
| Gmail OAuth | POST | `/gmail/auth/initiate?loginHint={email}` — opens browser for authorization |
|
||||
| Gmail status | GET | `/gmail/auth/status?email=` |
|
||||
| Outlook OAuth | POST | `/outlook/auth/initiate` — opens browser for authorization |
|
||||
| Outlook status | GET | `/outlook/auth/status?email=` |
|
||||
|
||||
### 12. 文件夹
|
||||
### 12. Folders
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
| Operation | Method | Endpoint |
|
||||
|------|------|------|
|
||||
| IMAP 文件夹列表 | GET | `/imap/folders?email=` |
|
||||
| Outlook 文件夹列表 | GET | `/outlook/folders?email=` |
|
||||
| IMAP folder list | GET | `/imap/folders?email=` |
|
||||
| Outlook folder list | GET | `/outlook/folders?email=` |
|
||||
|
||||
> Gmail 文件夹固定:inbox, sent, drafts, trash, spam, archive。
|
||||
> Gmail folders are fixed: inbox, sent, drafts, trash, spam, archive.
|
||||
|
||||
---
|
||||
|
||||
## 数据同步机制
|
||||
## Data Sync Mechanism
|
||||
|
||||
邮件系统采用**本地缓存 + 定期轮询**:
|
||||
The email system uses **local cache + periodic polling**:
|
||||
|
||||
- **写操作**(发送、标记、删除、标签):同时更新本地和远程,无延迟
|
||||
- **读操作**(查询、搜索):返回本地缓存,可能有延迟(默认 30 秒轮询)
|
||||
- **远程变更**(用户在官方页面操作):需等待下次轮询同步
|
||||
- **Write operations** (send, mark, delete, label): update local and remote simultaneously, no delay
|
||||
- **Read operations** (query, search): return the local cache; may be delayed (default 30-second polling)
|
||||
- **Remote changes** (the user operates from the official web UI): wait for the next polling cycle to sync
|
||||
|
||||
**存储路径**:`~/.desirecore/mail/{provider}/{email}/`(index.json, messages/, sync.json)
|
||||
**Storage path**: `~/.desirecore/mail/{provider}/{email}/` (index.json, messages/, sync.json)
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
## Error Handling
|
||||
|
||||
| 状态码 | 原因 | 处理 |
|
||||
| Status code | Reason | Handling |
|
||||
|--------|------|------|
|
||||
| 400 | 参数错误 | 检查请求参数 |
|
||||
| 401 | 授权过期 | **按规则 1 处理**,不要尝试其他途径 |
|
||||
| 404 | 资源不存在 | 先同步再重试(规则 3) |
|
||||
| 500 | 内部错误 | 告知用户稍后重试 |
|
||||
| 400 | parameter error | check the request parameters |
|
||||
| 401 | authorization expired | **handle per Rule 1**; do not try other channels |
|
||||
| 404 | resource not found | sync first and retry (Rule 3) |
|
||||
| 500 | internal error | tell the user to retry later |
|
||||
|
||||
**IMAP 注意**:国内邮箱(QQ、163)需使用"授权码"而非登录密码。用 `/imap/test` 预先验证配置。
|
||||
**IMAP note**: domestic Chinese mailboxes (QQ, 163) require an "app password" instead of the login password. Use `/imap/test` to validate the configuration in advance.
|
||||
|
||||
349
skills/mail-operations/SKILL.zh-CN.md
Normal file
349
skills/mail-operations/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,349 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# mail-operations 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
通过本地 REST API 收发邮件、搜索、标签管理和自动规则,支持 Gmail / Outlook / IMAP。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
mail-operations 是一个**流程型技能(Procedural Skill)**,通过 DesireCore 本地 REST API 操作邮件系统。支持 Gmail(OAuth2)、Outlook(MSAL)和 IMAP/SMTP(QQ、163、Yahoo 等)三种邮箱类型,涵盖收发邮件、搜索、标签管理、附件下载、草稿管理和自动规则。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要查看收件箱、发送或回复邮件
|
||||
- 用户需要搜索特定邮件或管理邮件标签/分类
|
||||
- 用户需要下载附件或管理草稿
|
||||
- 用户需要设置自动回复规则或触发智能体处理邮件
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **统一接口**:三种邮箱通过统一 API 操作,降低使用复杂度
|
||||
- **本地安全**:所有操作通过本地 API 完成,无需暴露凭证
|
||||
- **智能联动**:支持自动规则和智能体邮件处理
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## API 基础信息
|
||||
|
||||
- **Base URL**: `https://127.0.0.1:62000/api`
|
||||
- **认证**: 无需认证(本地服务)
|
||||
- **Content-Type**: `application/json`
|
||||
- **SSL**: 使用 `curl -k` 跳过自签名证书验证
|
||||
- **响应格式**: 成功 `{"code": 1, "msg": "Success", "result": ...}`,失败 `{"code": 0, "msg": "错误信息"}`
|
||||
|
||||
---
|
||||
|
||||
## 强制行为规则
|
||||
|
||||
以下规则优先级最高,每次操作必须遵守。
|
||||
|
||||
### 规则 1:只能通过本地 API 操作
|
||||
|
||||
所有邮件操作**必须且只能**通过 `https://127.0.0.1:62000` 完成。**禁止**调用外部邮件客户端或浏览器。
|
||||
|
||||
如果 API 返回 **401(授权过期)**:
|
||||
1. 告知用户该账户授权已失效
|
||||
2. 提示在 DesireCore 中重新授权
|
||||
3. Gmail: `POST /api/gmail/auth/initiate?loginHint={email}`,Outlook: `POST /api/outlook/auth/initiate`
|
||||
|
||||
### 规则 2:操作前先确认账户
|
||||
|
||||
执行任何操作前,**必须先调用 `GET /api/accounts`** 获取账户列表:
|
||||
- 按邮箱地址或域名匹配用户指定的账户("QQ 邮箱"→ imap 中 `qq.com`)
|
||||
- 仅有一个账户且用户说"我的邮箱"→ 直接使用
|
||||
- 找不到匹配账户 → 告知用户并提示添加
|
||||
|
||||
### 规则 3:查询为空时自动同步
|
||||
|
||||
查询返回空列表或找不到指定数据时:
|
||||
1. 调用 `POST /{provider}/messages/fetch` 同步远程数据
|
||||
2. **自动重试**原查询
|
||||
3. 仍为空才告知用户
|
||||
|
||||
### 规则 4:写操作后提示刷新
|
||||
|
||||
发送、回复、删除、标记、标签变更等写操作成功后,提示:`操作已完成。需要我帮你刷新当前邮箱页面以查看最新状态吗?`
|
||||
|
||||
---
|
||||
|
||||
## 三种邮箱的差异速查
|
||||
|
||||
| 功能 | Gmail | Outlook | IMAP |
|
||||
|------|-------|---------|------|
|
||||
| 授权 | OAuth2 | OAuth2 (MSAL) | 密码/授权码 |
|
||||
| Provider 路径 | `/gmail/` | `/outlook/` | `/imap/` |
|
||||
| 邮件详情 | 路径参数 `/{id}` | 查询参数 `?id={id}` | UID `/{uid}?folder=` |
|
||||
| 搜索 | 支持 | 不支持 | 不支持 |
|
||||
| 草稿 | 支持(含列表/详情) | 支持(创建/发送) | 支持(创建/发送) |
|
||||
| 附件下载 | 支持 | 支持 | 支持 |
|
||||
| 标签/分类 | 原生标签 | Categories | 仅本地标签 |
|
||||
| 自动规则 | 支持 | 支持 | 支持 |
|
||||
|
||||
---
|
||||
|
||||
## 核心操作
|
||||
|
||||
以下 `{p}` 代表 provider(`gmail`、`outlook`、`imap`),`{email}` 需 URL 编码。
|
||||
|
||||
### 1. 账户管理
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取所有账户 | GET | `/accounts` |
|
||||
| 获取账户含设置 | GET | `/accounts-with-settings` |
|
||||
| 删除账户 | DELETE | `/accounts/{p}/{email}` |
|
||||
| 获取账户设置 | GET | `/accounts/{p}/{email}/settings` |
|
||||
| 更新账户设置 | PUT | `/accounts/{p}/{email}/settings` |
|
||||
| 更新显示名称 | PUT | `/accounts/{p}/{email}/displayName` — body: `{"displayName": "..."}` |
|
||||
|
||||
**IMAP 专属**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取预设邮箱配置 | GET | `/imap/presets` — 返回 QQ/163/Yahoo 等服务器配置 |
|
||||
| 测试 IMAP 连接 | POST | `/imap/test` — body: `{email, password, imap: {host, port, secure}, smtp: {host, port, secure}}` |
|
||||
| 添加 IMAP 账户 | POST | `/imap/accounts` — body 同上,加 `displayName` |
|
||||
|
||||
### 2. 邮件列表与同步
|
||||
|
||||
| 操作 | 方法 | 端点 | 参数 |
|
||||
|------|------|------|------|
|
||||
| 查询本地缓存 | GET | `/{p}/messages` | `email, offset, limit, folder` |
|
||||
| 远程同步 | POST | `/{p}/messages/fetch` | `email, limit, folder` |
|
||||
| 手动触发同步 | POST | `/sync` | `provider, email` |
|
||||
|
||||
**folder 取值**:Gmail/Outlook: `inbox, sent, drafts, trash, spam, archive`;IMAP: `INBOX, Sent, Drafts, Trash` 等。
|
||||
|
||||
**响应格式**(邮件列表项):
|
||||
```json
|
||||
{
|
||||
"id": "消息ID", "subject": "主题",
|
||||
"from": {"name": "...", "address": "..."},
|
||||
"to": [{"name": "...", "address": "..."}],
|
||||
"date": "ISO8601", "snippet": "摘要",
|
||||
"isRead": true, "hasAttachments": false,
|
||||
"labels": ["INBOX"], "folder": "inbox"
|
||||
}
|
||||
```
|
||||
|
||||
### 3. 单封邮件操作
|
||||
|
||||
| 操作 | Gmail | Outlook | IMAP |
|
||||
|------|-------|---------|------|
|
||||
| 获取详情 | GET `/{id}?email=` | GET `/message?id={id}&email=` | GET `/{uid}?email=&folder=` |
|
||||
| 标记已读 | POST `/{id}/read?email=` | POST `/message/read?id={id}&email=` | POST `/{uid}/read?email=&folder=` |
|
||||
| 标记未读 | POST `/{id}/unread?email=` | POST `/message/unread?id={id}&email=` | POST `/{uid}/unread?email=&folder=` |
|
||||
| 删除 | DELETE `/{id}?email=` | DELETE `/message?id={id}&email=` | DELETE `/{uid}?email=&folder=` |
|
||||
|
||||
> 所有路径前缀为 `/api/{provider}/messages`(Gmail/IMAP)或 `/api/outlook/`(Outlook 特殊路由)。
|
||||
|
||||
**邮件详情额外字段**:`body: {content, contentType}`, `cc`, `attachments: [{id, filename, mimeType, size}]`
|
||||
|
||||
### 4. 发送与回复
|
||||
|
||||
**发送新邮件** — `POST /api/{p}/send`:
|
||||
```json
|
||||
{
|
||||
"email": "sender@example.com",
|
||||
"toRecipients": [{"name": "收件人", "address": "to@example.com"}],
|
||||
"ccRecipients": [],
|
||||
"bccRecipients": [],
|
||||
"subject": "主题",
|
||||
"body": "正文(支持 HTML)",
|
||||
"contentType": "html",
|
||||
"attachments": []
|
||||
}
|
||||
```
|
||||
|
||||
**回复邮件**:
|
||||
|
||||
| Provider | 端点 | Body |
|
||||
|----------|------|------|
|
||||
| Gmail | POST `/gmail/reply` | `{email, messageId, body, contentType}` |
|
||||
| Outlook | POST `/outlook/message/reply?id={id}&email=` | `{body, contentType}` |
|
||||
| IMAP | POST `/imap/reply` | `{email, uid, folder, body, contentType}` |
|
||||
|
||||
### 5. 搜索(仅 Gmail)
|
||||
|
||||
`GET /api/gmail/search?email={email}&q={keyword}`
|
||||
|
||||
| 参数 | 说明 |
|
||||
|------|------|
|
||||
| `q` | 关键词(搜索主题、正文、发件人) |
|
||||
| `from` | 发件人地址 |
|
||||
| `dateFrom` / `dateTo` | 日期范围 YYYY-MM-DD |
|
||||
| `hasAttachment` | true/false |
|
||||
| `isUnread` | true/false |
|
||||
| `offset` / `limit` | 分页 |
|
||||
|
||||
### 6. 附件下载
|
||||
|
||||
| Provider | 方法 | 端点 | Body |
|
||||
|----------|------|------|------|
|
||||
| Gmail | POST | `/gmail/messages/{messageId}/attachment` | `{email, attachmentId}` |
|
||||
| Outlook | POST | `/outlook/attachment` | `{email, messageId, attachmentId}` |
|
||||
| IMAP | POST | `/imap/attachment` | `{email, uid, folder, partId}` |
|
||||
|
||||
响应 `result.data` 为 base64 编码,解码后保存文件。
|
||||
|
||||
> Gmail 使用 POST 因为 attachmentId 可能超出 URL 长度限制。
|
||||
|
||||
### 7. 草稿管理
|
||||
|
||||
**Gmail**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取草稿列表 | GET | `/gmail/drafts?email=&limit=` |
|
||||
| 获取草稿详情 | GET | `/gmail/drafts/{draftId}?email=` |
|
||||
| 创建草稿 | POST | `/gmail/drafts` — body: `{email, to, cc, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/gmail/drafts/{draftId}` — body 同创建 |
|
||||
| 删除草稿 | DELETE | `/gmail/drafts/{draftId}?email=` |
|
||||
|
||||
**Outlook**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 创建草稿 | POST | `/outlook/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/outlook/drafts?id={draftId}&email=` — body 同创建 |
|
||||
| 删除草稿 | DELETE | `/outlook/drafts?id={draftId}&email=` |
|
||||
| 发送草稿 | POST | `/outlook/drafts/send?id={draftId}&email=` |
|
||||
|
||||
**IMAP**:
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 创建草稿 | POST | `/imap/drafts` — body: `{email, toRecipients, subject, body, contentType}` |
|
||||
| 更新草稿 | PUT | `/imap/drafts/{uid}` — body: `{email, folder, toRecipients, subject, body, contentType}` |
|
||||
| 删除草稿 | DELETE | `/imap/drafts/{uid}?email=&folder=` |
|
||||
| 发送草稿 | POST | `/imap/drafts/{uid}/send` — body: `{email, folder}` |
|
||||
|
||||
### 8. 标签管理(统一接口)
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取标签列表 | GET | `/labels?provider=&email=` |
|
||||
| 获取单个标签 | GET | `/labels/{labelId}` |
|
||||
| 创建标签 | POST | `/labels` — body: `{name, color, provider, email, visible}` |
|
||||
| 更新标签 | PUT | `/labels/{labelId}` — body: `{name, color, order, visible}` |
|
||||
| 删除标签 | DELETE | `/labels/{labelId}` |
|
||||
| 获取邮件标签 | GET | `/mails/{p}/{email}/labels?mailId=` |
|
||||
| 添加邮件标签 | POST | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelId": "..."}` |
|
||||
| 批量设置标签 | PUT | `/mails/{p}/{email}/labels?mailId=` — body: `{"labelIds": [...]}` |
|
||||
| 移除邮件标签 | DELETE | `/mails/{p}/{email}/labels?mailId=&labelId=` |
|
||||
| 获取标签下邮件 | GET | `/labels/{labelId}/mails?provider=&email=&limit=&offset=` |
|
||||
|
||||
**Gmail 原生标签**:
|
||||
- 获取标签列表:`GET /api/gmail/labels?email=`
|
||||
- 修改邮件标签:`POST /api/gmail/messages/{id}/labels` — body: `{email, addLabelIds, removeLabelIds}`
|
||||
- 同步远程标签:`POST /api/gmail/labels/sync?email=`
|
||||
|
||||
### 9. Outlook 分类
|
||||
|
||||
Outlook 使用 Categories 而非 Labels。
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取分类 | GET | `/outlook/categories?email=` |
|
||||
| 同步分类 | POST | `/outlook/categories/sync?email=` |
|
||||
| 创建分类 | POST | `/outlook/categories/create?email=` — body: `{displayName, color}` |
|
||||
| 更新分类 | PUT | `/outlook/categories/update?email=&categoryId=` — body: `{displayName, color}` |
|
||||
| 删除分类 | DELETE | `/outlook/categories/delete?email=&categoryId=` |
|
||||
| 修改邮件分类 | POST | `/outlook/message/categories?id=&email=` — body: `{addCategories, removeCategories}` |
|
||||
|
||||
> `color` 使用 Outlook 预设值 `preset0` ~ `preset24`。
|
||||
|
||||
### 10. 自动规则
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| 获取所有规则 | GET | `/rules?provider=&email=` |
|
||||
| 获取单个规则 | GET | `/rules/{ruleId}` |
|
||||
| 创建规则 | POST | `/rules` |
|
||||
| 更新规则 | PUT | `/rules/{ruleId}` |
|
||||
| 删除规则 | DELETE | `/rules/{ruleId}` |
|
||||
| 启用/禁用 | POST | `/rules/{ruleId}/toggle` |
|
||||
| 对邮件执行规则 | POST | `/rules/execute` — body: `{provider, email, mailId}` |
|
||||
| 测试规则匹配 | POST | `/rules/{ruleId}/test` — body 同上 |
|
||||
|
||||
**创建规则 body**:
|
||||
```json
|
||||
{
|
||||
"name": "规则名",
|
||||
"description": "说明",
|
||||
"provider": "gmail",
|
||||
"email": "xxx@gmail.com",
|
||||
"enabled": true,
|
||||
"conditions": [
|
||||
{"field": "from|to|subject|body|has_attachment", "operator": "contains|equals|regex|...", "value": "..."}
|
||||
],
|
||||
"conditionLogic": "and",
|
||||
"actions": [
|
||||
{"type": "add_label|remove_label|mark_as_read|mark_as_unread|archive|delete|auto_reply|agent_handle", "value": "..."}
|
||||
],
|
||||
"priority": 1,
|
||||
"stopOnMatch": false
|
||||
}
|
||||
```
|
||||
|
||||
**动作类型说明**:
|
||||
|
||||
| type | value | 说明 |
|
||||
|------|-------|------|
|
||||
| `add_label` | 标签 ID | 添加标签 |
|
||||
| `remove_label` | 标签 ID | 移除标签 |
|
||||
| `mark_as_read` | 省略 | 标记已读 |
|
||||
| `mark_as_unread` | 省略 | 标记未读 |
|
||||
| `archive` | 省略 | 归档 |
|
||||
| `delete` | 省略 | 删除 |
|
||||
| `auto_reply` | 回复文本 | 自动回复固定内容 |
|
||||
| `agent_handle` | Agent ID | 触发智能体处理邮件 |
|
||||
|
||||
> 规则在轮询引擎检测到新邮件时**自动执行**,无需手动调用。`auto_reply` 和 `agent_handle` 支持全部三种邮箱类型。
|
||||
|
||||
### 11. 授权管理
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| Gmail OAuth | POST | `/gmail/auth/initiate?loginHint={email}` — 打开浏览器授权 |
|
||||
| Gmail 状态 | GET | `/gmail/auth/status?email=` |
|
||||
| Outlook OAuth | POST | `/outlook/auth/initiate` — 打开浏览器授权 |
|
||||
| Outlook 状态 | GET | `/outlook/auth/status?email=` |
|
||||
|
||||
### 12. 文件夹
|
||||
|
||||
| 操作 | 方法 | 端点 |
|
||||
|------|------|------|
|
||||
| IMAP 文件夹列表 | GET | `/imap/folders?email=` |
|
||||
| Outlook 文件夹列表 | GET | `/outlook/folders?email=` |
|
||||
|
||||
> Gmail 文件夹固定:inbox, sent, drafts, trash, spam, archive。
|
||||
|
||||
---
|
||||
|
||||
## 数据同步机制
|
||||
|
||||
邮件系统采用**本地缓存 + 定期轮询**:
|
||||
|
||||
- **写操作**(发送、标记、删除、标签):同时更新本地和远程,无延迟
|
||||
- **读操作**(查询、搜索):返回本地缓存,可能有延迟(默认 30 秒轮询)
|
||||
- **远程变更**(用户在官方页面操作):需等待下次轮询同步
|
||||
|
||||
**存储路径**:`~/.desirecore/mail/{provider}/{email}/`(index.json, messages/, sync.json)
|
||||
|
||||
---
|
||||
|
||||
## 错误处理
|
||||
|
||||
| 状态码 | 原因 | 处理 |
|
||||
|--------|------|------|
|
||||
| 400 | 参数错误 | 检查请求参数 |
|
||||
| 401 | 授权过期 | **按规则 1 处理**,不要尝试其他途径 |
|
||||
| 404 | 资源不存在 | 先同步再重试(规则 3) |
|
||||
| 500 | 内部错误 | 告知用户稍后重试 |
|
||||
|
||||
**IMAP 注意**:国内邮箱(QQ、163)需使用"授权码"而非登录密码。用 `/imap/test` 预先验证配置。
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 管理技能
|
||||
name: manage-skills
|
||||
description: >-
|
||||
管理 Agent 的技能生命周期:通过 HTTP API 导入、安装、更新、删除技能,
|
||||
或通过 AgentFS 文件系统直接编写符合规范的 SKILL.md。Use when 用户要求
|
||||
@@ -18,6 +18,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-03-03'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 管理技能
|
||||
short_desc: 导入、编写、安装与管理 Agent 技能的完整工具箱
|
||||
description: >-
|
||||
管理 Agent 的技能生命周期:通过 HTTP API 导入、安装、更新、删除技能, 或通过 AgentFS 文件系统直接编写符合规范的 SKILL.md。Use when 用户要求 安装技能、从 URL/Git 导入技能、编写新技能、或管理已有技能。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:7f116cc5de352822
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Manage Skills
|
||||
short_desc: Complete toolbox for importing, authoring, installing, and managing Agent Skills
|
||||
description: >-
|
||||
Manage the Skill lifecycle of an Agent: import, install, update, and delete Skills via HTTP API, or directly author standards-compliant SKILL.md files via the AgentFS filesystem. Use when the user requests to install Skills, import Skills from URL/Git, author new Skills, or manage existing Skills.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:7f116cc5de352822
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -30,7 +53,6 @@ market:
|
||||
stroke-width="2" stroke-linecap="round"/><circle cx="18" cy="6" r="3"
|
||||
fill="#34C759" fill-opacity="0.9"/><path d="M17 6h2M18 5v2"
|
||||
stroke="white" stroke-width="1.2" stroke-linecap="round"/></svg>
|
||||
short_desc: 导入、编写、安装与管理 Agent 技能的完整工具箱
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -39,46 +61,46 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# manage-skills 技能
|
||||
# manage-skills Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
管理技能的完整生命周期——导入、编写、安装、更新、删除。
|
||||
Manage the full lifecycle of Skills—import, author, install, update, and delete.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
manage-skills 是一个**元技能(Meta-Skill)**,赋予 DesireCore 管理技能系统的能力。它涵盖 5 种核心操作:
|
||||
manage-skills is a **Meta-Skill** that gives DesireCore the ability to manage the Skill system. It covers five core operations:
|
||||
|
||||
1. **从 URL 导入技能** — 指定远程 SKILL.md 文件 URL,抓取内容并创建
|
||||
2. **从 Git 仓库批量导入** — 克隆 Git 仓库,扫描所有 SKILL.md,选择性导入
|
||||
3. **通过 API 管理已有技能** — 列出、读取、更新、删除、启用/禁用技能
|
||||
4. **通过 AgentFS 直接编写 SKILL.md** — 使用 Write/Edit 工具在文件系统创建技能
|
||||
5. **批量操作与跨 Agent 复制** — 批量启用/禁用/删除,以及复制技能到其他 Agent
|
||||
1. **Import a Skill from a URL** — supply a remote SKILL.md URL, fetch the content, and create
|
||||
2. **Bulk import from a Git repository** — clone a Git repo, scan all SKILL.md files, and selectively import
|
||||
3. **Manage existing Skills via API** — list, read, update, delete, enable/disable Skills
|
||||
4. **Author SKILL.md directly via AgentFS** — use the Write/Edit tools to create Skills on the filesystem
|
||||
5. **Bulk operations and cross-Agent copying** — bulk enable/disable/delete, plus copy Skills to other Agents
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想从 GitHub 等平台导入社区分享的技能
|
||||
- 用户想给某个 Agent 安装新技能、增强其能力
|
||||
- 用户需要编写自定义技能教会 Agent 新的工作流程
|
||||
- 用户想批量管理已有技能(启用/禁用/删除)
|
||||
- 用户想把一个 Agent 的技能复制给另一个 Agent
|
||||
- 用户需要查看或编辑某个技能的内容
|
||||
- The user wants to import community-shared Skills from platforms like GitHub
|
||||
- The user wants to install a new Skill on an Agent to enhance its capabilities
|
||||
- The user needs to author a custom Skill to teach the Agent a new workflow
|
||||
- The user wants to bulk-manage existing Skills (enable/disable/delete)
|
||||
- The user wants to copy one Agent's Skill to another Agent
|
||||
- The user needs to view or edit the contents of a Skill
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **自我扩展**:Agent 可通过导入或编写技能,自主扩展能力边界
|
||||
- **可治理**:所有技能变更通过 API 或文件系统操作,可追溯、可审计
|
||||
- **灵活性**:支持 API 导入和文件系统直写两种方式,适应不同场景
|
||||
- **Self-extension**: an Agent can autonomously expand its capability boundary by importing or authoring Skills
|
||||
- **Governable**: every Skill change goes through the API or filesystem operations and is traceable and auditable
|
||||
- **Flexibility**: supports both API import and direct filesystem authoring to fit different scenarios
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 1. 从 URL 导入单个技能
|
||||
### 1. Import a Single Skill from a URL
|
||||
|
||||
适用于导入单个 SKILL.md 文件(如 GitHub raw 链接)。
|
||||
For importing a single SKILL.md file (e.g. a GitHub raw link).
|
||||
|
||||
**步骤 1:抓取远程内容**
|
||||
**Step 1: Fetch the remote content**
|
||||
|
||||
```bash
|
||||
POST /api/skills/fetch-url
|
||||
@@ -89,25 +111,25 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`200 OK`):
|
||||
**Success response** (`200 OK`):
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "---\nname: 我的技能\ndescription: ...\n---\n\n# 技能内容..."
|
||||
"content": "---\nname: My Skill\ndescription: ...\n---\n\n# Skill content..."
|
||||
}
|
||||
```
|
||||
|
||||
**安全限制**:
|
||||
**Security limits**:
|
||||
|
||||
- 仅允许 HTTPS URL
|
||||
- 文件大小上限 20MB
|
||||
- 请求超时 30 秒
|
||||
- HTTPS URLs only
|
||||
- 20MB file size limit
|
||||
- 30-second request timeout
|
||||
|
||||
**步骤 2:创建技能**
|
||||
**Step 2: Create the Skill**
|
||||
|
||||
抓取成功后,根据作用域选择创建端点:
|
||||
After a successful fetch, choose the creation endpoint based on scope:
|
||||
|
||||
**创建全局技能**(所有 Agent 可见):
|
||||
**Create a global Skill** (visible to all Agents):
|
||||
|
||||
```bash
|
||||
POST /api/skills
|
||||
@@ -115,11 +137,11 @@ Content-Type: application/json
|
||||
|
||||
{
|
||||
"skillId": "my-skill",
|
||||
"content": "<上一步返回的 content>"
|
||||
"content": "<content returned in the previous step>"
|
||||
}
|
||||
```
|
||||
|
||||
**创建 Agent 级技能**(仅指定 Agent 可见):
|
||||
**Create an Agent-scoped Skill** (visible only to the specified Agent):
|
||||
|
||||
```bash
|
||||
POST /api/agents/{agentId}/skills
|
||||
@@ -127,24 +149,24 @@ Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": "my-skill",
|
||||
"fullContent": "<上一步返回的 content>"
|
||||
"fullContent": "<content returned in the previous step>"
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`201 Created`):
|
||||
**Success response** (`201 Created`):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"skill": { "id": "my-skill", "name": "我的技能", "description": "..." }
|
||||
"skill": { "id": "my-skill", "name": "My Skill", "description": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 从 Git 仓库批量导入
|
||||
### 2. Bulk Import from a Git Repository
|
||||
|
||||
适用于导入包含多个技能的 Git 仓库。
|
||||
For importing a Git repository that contains multiple Skills.
|
||||
|
||||
**步骤 1:扫描仓库**
|
||||
**Step 1: Scan the repository**
|
||||
|
||||
```bash
|
||||
POST /api/skills/fetch-git
|
||||
@@ -155,7 +177,7 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`200 OK`):
|
||||
**Success response** (`200 OK`):
|
||||
|
||||
```json
|
||||
{
|
||||
@@ -163,53 +185,53 @@ Content-Type: application/json
|
||||
{
|
||||
"id": "data-analysis",
|
||||
"path": "data-analysis",
|
||||
"content": "---\nname: 数据分析\n...",
|
||||
"content": "---\nname: Data Analysis\n...",
|
||||
"sidecarFiles": [{ "name": "examples.md", "content": "..." }]
|
||||
},
|
||||
{
|
||||
"id": "report-writing",
|
||||
"path": "report-writing",
|
||||
"content": "---\nname: 报告撰写\n..."
|
||||
"content": "---\nname: Report Writing\n..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
API 会自动:
|
||||
The API automatically:
|
||||
|
||||
- 使用 `--depth=1` 浅克隆以减少下载量
|
||||
- 递归扫描目录中的 SKILL.md 文件
|
||||
- 从目录名推导 skillId(fallback 从 frontmatter name 生成 slug)
|
||||
- 收集同目录的 sidecar 文件(如 examples.md, references/ 等)
|
||||
- 完成后自动清理临时目录
|
||||
- Uses `--depth=1` shallow clone to reduce download size
|
||||
- Recursively scans for SKILL.md files in directories
|
||||
- Derives skillId from the directory name (falls back to a slug from the frontmatter name)
|
||||
- Collects sidecar files in the same directory (e.g. examples.md, references/)
|
||||
- Cleans up the temporary directory once finished
|
||||
|
||||
**步骤 2:逐个导入选中的技能**
|
||||
**Step 2: Import the chosen Skills one by one**
|
||||
|
||||
向用户展示扫描结果列表,让用户选择要导入的技能,然后逐个调用创建 API:
|
||||
Show the scan results to the user and let them choose which Skills to import, then call the create API for each:
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
# Global Skill
|
||||
POST /api/skills
|
||||
{ "skillId": "data-analysis", "content": "<content>" }
|
||||
|
||||
# 或 Agent 级技能
|
||||
# Or Agent-scoped Skill
|
||||
POST /api/agents/{agentId}/skills
|
||||
{ "id": "data-analysis", "fullContent": "<content>" }
|
||||
```
|
||||
|
||||
**sidecarFiles 处理**:如果扫描结果包含 sidecarFiles,需要在创建技能后将它们写入对应目录:
|
||||
**Handling sidecarFiles**: if the scan result contains sidecarFiles, after creating the Skill write them to the corresponding directory:
|
||||
|
||||
```bash
|
||||
# 全局技能的 sidecar 文件路径
|
||||
# Sidecar file path for a global Skill
|
||||
~/.desirecore/skills/{skillId}/{filename}
|
||||
|
||||
# Agent 级技能的 sidecar 文件路径
|
||||
# Sidecar file path for an Agent-scoped Skill
|
||||
~/.desirecore/agents/{agentId}/skills/{skillId}/{filename}
|
||||
```
|
||||
|
||||
### 3. 通过 API 管理已有技能
|
||||
### 3. Manage Existing Skills via API
|
||||
|
||||
#### 列出所有技能
|
||||
#### List All Skills
|
||||
|
||||
```bash
|
||||
GET /api/skills/list
|
||||
@@ -217,77 +239,77 @@ GET /api/skills/list?agentId={agentId}
|
||||
GET /api/skills/list?includeDisabled=true
|
||||
```
|
||||
|
||||
返回包含 project、agent、global 三级作用域的技能列表。
|
||||
Returns a Skill list covering all three scopes: project, agent, and global.
|
||||
|
||||
#### 列出指定 Agent 的技能
|
||||
#### List Skills for a Specific Agent
|
||||
|
||||
```bash
|
||||
GET /api/agents/{agentId}/skills
|
||||
```
|
||||
|
||||
#### 读取技能内容
|
||||
#### Read Skill Content
|
||||
|
||||
```bash
|
||||
# 按作用域优先级自动解析
|
||||
# Resolved automatically by scope priority
|
||||
GET /api/skills/{skillId}/content
|
||||
GET /api/skills/{skillId}/content?agentId={agentId}
|
||||
|
||||
# 读取指定 Agent 的技能
|
||||
# Read a specific Agent's Skill
|
||||
GET /api/agents/{agentId}/skills/{skillId}
|
||||
```
|
||||
|
||||
#### 更新技能内容
|
||||
#### Update Skill Content
|
||||
|
||||
**更新全局技能**:
|
||||
**Update a global Skill**:
|
||||
|
||||
```bash
|
||||
PUT /api/skills/{skillId}/content
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"content": "---\nname: 更新后的技能\n...\n---\n\n# 新内容..."
|
||||
"content": "---\nname: Updated Skill\n...\n---\n\n# New content..."
|
||||
}
|
||||
```
|
||||
|
||||
**更新 Agent 级技能**:
|
||||
**Update an Agent-scoped Skill**:
|
||||
|
||||
```bash
|
||||
PUT /api/agents/{agentId}/skills/{skillId}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"content": "---\nname: 更新后的技能\n...\n---\n\n# 新内容...",
|
||||
"content": "---\nname: Updated Skill\n...\n---\n\n# New content...",
|
||||
"bumpVersion": "minor"
|
||||
}
|
||||
```
|
||||
|
||||
`bumpVersion` 可选值:`major` | `minor` | `patch`,指定后自动递增版本号。内容变化时系统会自动更新 `metadata.updated_at`。
|
||||
`bumpVersion` accepts: `major` | `minor` | `patch`; when specified, the version number is auto-incremented. The system automatically updates `metadata.updated_at` whenever the content changes.
|
||||
|
||||
#### 删除技能
|
||||
#### Delete a Skill
|
||||
|
||||
```bash
|
||||
# 删除全局技能
|
||||
# Delete a global Skill
|
||||
DELETE /api/skills/{skillId}
|
||||
|
||||
# 删除 Agent 级技能
|
||||
# Delete an Agent-scoped Skill
|
||||
DELETE /api/agents/{agentId}/skills/{skillId}
|
||||
```
|
||||
|
||||
#### 启用/禁用技能
|
||||
#### Enable/Disable a Skill
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
# Global Skill
|
||||
PATCH /api/skills/{skillId}/status
|
||||
Content-Type: application/json
|
||||
{ "enabled": false }
|
||||
|
||||
# Agent 级技能
|
||||
# Agent-scoped Skill
|
||||
PATCH /api/agents/{agentId}/skills/{skillId}/status
|
||||
Content-Type: application/json
|
||||
{ "enabled": true }
|
||||
```
|
||||
|
||||
#### 批量操作
|
||||
#### Bulk Operations
|
||||
|
||||
```bash
|
||||
POST /api/agents/{agentId}/skills/batch
|
||||
@@ -299,9 +321,9 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
`action` 可选值:`enable` | `disable` | `delete`
|
||||
`action` accepts: `enable` | `disable` | `delete`
|
||||
|
||||
#### 复制技能到其他 Agent
|
||||
#### Copy a Skill to Another Agent
|
||||
|
||||
```bash
|
||||
POST /api/agents/{targetAgentId}/skills/copy
|
||||
@@ -314,31 +336,31 @@ Content-Type: application/json
|
||||
}
|
||||
```
|
||||
|
||||
可选参数:
|
||||
Optional parameters:
|
||||
|
||||
- `sourceAgentId` — 源 Agent ID(从 agent 级复制时必填)
|
||||
- `sourceSource` — 源作用域:`project` | `agent` | `global`
|
||||
- `sourceWorkDir` — 源 project workDir(从 project 级复制时使用)
|
||||
- `targetSkillId` — 目标技能 ID(不填则沿用 sourceSkillId)
|
||||
- `sourceAgentId` — source Agent ID (required when copying from agent scope)
|
||||
- `sourceSource` — source scope: `project` | `agent` | `global`
|
||||
- `sourceWorkDir` — source project workDir (used when copying from project scope)
|
||||
- `targetSkillId` — target Skill ID (defaults to sourceSkillId if omitted)
|
||||
|
||||
### 4. 通过 AgentFS 直接编写 SKILL.md
|
||||
### 4. Author SKILL.md Directly via AgentFS
|
||||
|
||||
当需要从零创建技能,或 API 方式不够灵活时,可直接在文件系统编写 SKILL.md。
|
||||
When you need to create a Skill from scratch or the API approach is not flexible enough, you can author SKILL.md directly on the filesystem.
|
||||
|
||||
#### 目录结构
|
||||
#### Directory Structure
|
||||
|
||||
**全局技能**(所有 Agent 可见):
|
||||
**Global Skill** (visible to all Agents):
|
||||
|
||||
```
|
||||
~/.desirecore/skills/
|
||||
└── my-new-skill/
|
||||
├── SKILL.md # 必须:技能定义文件
|
||||
├── examples/ # 可选:示例文件
|
||||
├── scripts/ # 可选:辅助脚本
|
||||
└── references/ # 可选:参考资料
|
||||
├── SKILL.md # required: skill definition file
|
||||
├── examples/ # optional: example files
|
||||
├── scripts/ # optional: helper scripts
|
||||
└── references/ # optional: reference material
|
||||
```
|
||||
|
||||
**Agent 级技能**(仅指定 Agent 可见):
|
||||
**Agent-scoped Skill** (visible only to the specified Agent):
|
||||
|
||||
```
|
||||
~/.desirecore/agents/{agentId}/
|
||||
@@ -348,17 +370,17 @@ Content-Type: application/json
|
||||
└── ...
|
||||
```
|
||||
|
||||
#### SKILL.md 完整格式
|
||||
#### Full SKILL.md Format
|
||||
|
||||
```markdown
|
||||
---
|
||||
# === 必填字段 ===
|
||||
# === Required fields ===
|
||||
description: >-
|
||||
技能用途的完整描述。应包含 "Use when" 触发提示,
|
||||
帮助 AI 判断何时使用该技能。
|
||||
Full description of the Skill's purpose. Should include a "Use when" trigger hint
|
||||
to help the AI decide when to use this Skill.
|
||||
|
||||
# === 推荐字段 ===
|
||||
name: 技能显示名称
|
||||
# === Recommended fields ===
|
||||
name: Skill display name
|
||||
version: 1.0.0
|
||||
type: procedural
|
||||
risk_level: low
|
||||
@@ -370,7 +392,7 @@ metadata:
|
||||
author: your-name
|
||||
updated_at: '2026-03-03'
|
||||
|
||||
# === 可选字段 ===
|
||||
# === Optional fields ===
|
||||
disable-model-invocation: true
|
||||
requires:
|
||||
tools:
|
||||
@@ -380,57 +402,57 @@ requires:
|
||||
- Edit
|
||||
---
|
||||
|
||||
# skill-id 技能
|
||||
# skill-id Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
用一句话描述这个技能做什么。
|
||||
Describe in one sentence what this Skill does.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
详细描述技能的核心能力。
|
||||
Detailed description of the Skill's core capability.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 场景 1
|
||||
- 场景 2
|
||||
- Scenario 1
|
||||
- Scenario 2
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- 价值 1
|
||||
- 价值 2
|
||||
- Value 1
|
||||
- Value 2
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 具体操作步骤
|
||||
### Concrete Steps
|
||||
|
||||
按阶段/步骤详细描述执行流程、API 调用、输入输出格式等。
|
||||
Describe the execution flow, API calls, and input/output formats stage by stage / step by step.
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| Error scenario | Handling |
|
||||
| -------- | -------- |
|
||||
| ... | ... |
|
||||
```
|
||||
|
||||
#### 使用 Write 工具创建技能示例
|
||||
#### Example: Create a Skill with the Write Tool
|
||||
|
||||
以下示例展示如何使用 Write 工具创建一个全局技能:
|
||||
The following example shows how to create a global Skill with the Write tool:
|
||||
|
||||
```
|
||||
目标路径:~/.desirecore/skills/daily-summary/SKILL.md
|
||||
Target path: ~/.desirecore/skills/daily-summary/SKILL.md
|
||||
```
|
||||
|
||||
写入内容:
|
||||
Content to write:
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: 每日摘要
|
||||
name: Daily Summary
|
||||
description: >-
|
||||
汇总当天对话记录,生成结构化的每日工作摘要。
|
||||
Use when 用户要求总结今天的工作、生成日报、或回顾对话内容。
|
||||
Aggregates today's conversation records and produces a structured daily work summary.
|
||||
Use when the user asks for a summary of today's work, generation of a daily report, or a recap of conversation content.
|
||||
version: 1.0.0
|
||||
type: procedural
|
||||
risk_level: low
|
||||
@@ -444,108 +466,108 @@ metadata:
|
||||
updated_at: '2026-03-03'
|
||||
---
|
||||
|
||||
# daily-summary 技能
|
||||
# daily-summary Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
汇总当天对话记录,自动生成结构化的工作摘要。
|
||||
Aggregates today's conversation records and automatically produces a structured work summary.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
从对话历史中提取关键信息,按项目/主题分类整理,生成包含完成事项、
|
||||
待办事项和重要决策的每日摘要。
|
||||
Extracts key information from conversation history, organizes it by project/topic, and produces a daily summary
|
||||
covering completed items, to-dos, and important decisions.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户在一天工作结束时要求总结
|
||||
- 用户需要生成日报或周报素材
|
||||
- 用户想回顾某天的对话和决策
|
||||
- The user asks for a summary at the end of a workday
|
||||
- The user needs material for a daily or weekly report
|
||||
- The user wants to recap a particular day's conversation and decisions
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 摘要结构
|
||||
### Summary Structure
|
||||
|
||||
1. 今日完成事项
|
||||
2. 进行中事项
|
||||
3. 重要决策和结论
|
||||
4. 明日待办建议
|
||||
1. Items completed today
|
||||
2. Items in progress
|
||||
3. Important decisions and conclusions
|
||||
4. Suggested to-dos for tomorrow
|
||||
```
|
||||
|
||||
### 5. SKILL.md 格式参考
|
||||
### 5. SKILL.md Format Reference
|
||||
|
||||
#### Frontmatter 字段表
|
||||
#### Frontmatter Field Table
|
||||
|
||||
| 字段 | 必填 | 类型 | 说明 |
|
||||
| Field | Required | Type | Description |
|
||||
| -------------------------- | -------- | -------- | -------------------------------------------------- |
|
||||
| `description` | **必填** | string | 技能用途描述,建议包含 "Use when" 触发提示 |
|
||||
| `name` | 推荐 | string | 技能显示名称 |
|
||||
| `version` | 推荐 | string | 语义版本号(如 `1.0.0`) |
|
||||
| `type` | 推荐 | enum | `procedural` / `conversational` / `meta` |
|
||||
| `risk_level` | 推荐 | enum | `low` / `medium` / `high` |
|
||||
| `status` | 推荐 | enum | `enabled` / `disabled` |
|
||||
| `tags` | 可选 | string[] | 标签列表,用于搜索和分类 |
|
||||
| `disable-model-invocation` | 可选 | boolean | `true`=L0+L1 自动注入 system prompt;`false`=L0+L1+L2 完整内容注入;默认 `true` |
|
||||
| `requires` | 可选 | object | 依赖声明:`tools`、`optional_tools`、`connections` |
|
||||
| `metadata` | 可选 | object | 元信息:`author`、`updated_at` |
|
||||
| `market` | 可选 | object | 市场展示元数据(仅市场发布的技能需要) |
|
||||
| `description` | **Required** | string | Skill purpose description; including a "Use when" trigger hint is recommended |
|
||||
| `name` | Recommended | string | Skill display name |
|
||||
| `version` | Recommended | string | Semantic version (e.g. `1.0.0`) |
|
||||
| `type` | Recommended | enum | `procedural` / `conversational` / `meta` |
|
||||
| `risk_level` | Recommended | enum | `low` / `medium` / `high` |
|
||||
| `status` | Recommended | enum | `enabled` / `disabled` |
|
||||
| `tags` | Optional | string[] | List of tags, used for search and categorization |
|
||||
| `disable-model-invocation` | Optional | boolean | `true` = L0+L1 auto-injected into the system prompt; `false` = full L0+L1+L2 content injected; default `true` |
|
||||
| `requires` | Optional | object | Dependency declaration: `tools`, `optional_tools`, `connections` |
|
||||
| `metadata` | Optional | object | Meta information: `author`, `updated_at` |
|
||||
| `market` | Optional | object | Market display metadata (only required for Skills published to the Market) |
|
||||
|
||||
#### type 说明
|
||||
#### type Description
|
||||
|
||||
| 类型 | 含义 | 示例 |
|
||||
| Type | Meaning | Examples |
|
||||
| ---------------- | ------------------------ | ---------------------- |
|
||||
| `procedural` | 流程型,按步骤执行 | 数据分析流程、审批流程 |
|
||||
| `conversational` | 对话型,通过多轮对话完成 | 需求收集、头脑风暴 |
|
||||
| `meta` | 元技能,管理其他资源 | 创建 Agent、管理技能 |
|
||||
| `procedural` | Procedural; executed step by step | Data analysis flow, approval flow |
|
||||
| `conversational` | Conversational; completed through multi-turn dialogue | Requirements gathering, brainstorming |
|
||||
| `meta` | Meta-Skill that manages other resources | Creating Agents, managing Skills |
|
||||
|
||||
#### Markdown Body 结构(L0 / L1 / L2)
|
||||
#### Markdown Body Structure (L0 / L1 / L2)
|
||||
|
||||
| 层级 | 内容 | 用途 |
|
||||
| Tier | Content | Purpose |
|
||||
| ---- | ----------------------------------- | ------------------ |
|
||||
| L0 | 一句话摘要 | 快速理解技能做什么 |
|
||||
| L1 | 能力描述 + 使用场景 + 核心价值 | 判断是否适用 |
|
||||
| L2 | 详细规范:步骤、API、格式、错误处理 | 具体执行指南 |
|
||||
| L0 | One-line summary | Quickly understand what the Skill does |
|
||||
| L1 | Capability + Use Cases + Core Value | Decide whether it applies |
|
||||
| L2 | Detailed specification: steps, APIs, formats, error handling | Concrete execution guide |
|
||||
|
||||
### 6. 作用域说明
|
||||
### 6. Scope Notes
|
||||
|
||||
技能存在三个作用域层级,按优先级从高到低:
|
||||
Skills exist at three scope levels, listed from highest priority to lowest:
|
||||
|
||||
| 优先级 | 作用域 | 路径 | 可见范围 |
|
||||
| Priority | Scope | Path | Visibility |
|
||||
| ------ | ---------- | ---------------------------------------- | ------------------ |
|
||||
| 最高 | Project 级 | `.claude/skills/` (项目根目录) | 当前项目所有 Agent |
|
||||
| 中 | Agent 级 | `~/.desirecore/agents/{agentId}/skills/` | 仅该 Agent |
|
||||
| 最低 | Global 级 | `~/.desirecore/skills/` | 所有 Agent |
|
||||
| Highest | Project | `.claude/skills/` (project root) | All Agents in the current project |
|
||||
| Medium | Agent | `~/.desirecore/agents/{agentId}/skills/` | Only that Agent |
|
||||
| Lowest | Global | `~/.desirecore/skills/` | All Agents |
|
||||
|
||||
**同名覆盖规则**:高优先级作用域的同名技能会覆盖低优先级的。例如 Agent 级有一个 `data-analysis` 技能,会覆盖全局同名技能。
|
||||
**Same-name override rule**: a Skill in a higher-priority scope overrides a same-named Skill in a lower-priority scope. For example, an Agent-scoped `data-analysis` Skill will shadow a global Skill of the same name.
|
||||
|
||||
### 7. 错误处理
|
||||
### 7. Error Handling
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| Error code | Scenario | Handling |
|
||||
| ------ | ----------------------------- | -------------------------------------- |
|
||||
| 400 | 缺少必填字段或格式无效 | 提示用户检查输入,说明哪个字段有问题 |
|
||||
| 400 | SKILL.md frontmatter 校验失败 | 展示校验错误详情,引导用户修正 |
|
||||
| 404 | 技能不存在 | 提示技能 ID 可能拼写错误,列出可用技能 |
|
||||
| 404 | Git 仓库中无 SKILL.md | 提示仓库格式不符合技能规范 |
|
||||
| 409 | 技能已存在(冲突写入) | 建议使用 PUT 更新而非 POST 创建 |
|
||||
| 413 | 远程文件超过 20MB | 提示文件过大,建议精简内容 |
|
||||
| 504 | URL 抓取超时 | 提示网络超时,建议检查 URL 或稍后重试 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
| 400 | Missing required fields or invalid format | Prompt the user to check the input and explain which field is problematic |
|
||||
| 400 | SKILL.md frontmatter validation failed | Show validation error details and guide the user to fix |
|
||||
| 404 | Skill does not exist | Note the Skill ID may be misspelled, list available Skills |
|
||||
| 404 | No SKILL.md in the Git repo | Note the repository's format does not match the Skill spec |
|
||||
| 409 | Skill already exists (write conflict) | Suggest using PUT to update instead of POST to create |
|
||||
| 413 | Remote file exceeds 20MB | Note the file is too large; suggest trimming the content |
|
||||
| 504 | URL fetch timeout | Note the network timed out; suggest checking the URL or retrying later |
|
||||
| 500 | Server internal error | Tell the user to retry later |
|
||||
|
||||
### 8. 权限说明
|
||||
### 8. Permission Notes
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 导入和创建操作建议先向用户展示预览,获得确认后再执行
|
||||
- 删除操作需要用户明确确认
|
||||
- 通过 AgentFS 编写技能时,使用 Write 工具创建文件即可
|
||||
- It is recommended to use the `Bash` tool to call the Agent Service HTTP API via curl
|
||||
- The API base address is already injected into the system prompt's "Local API" section; you can reference it directly
|
||||
- For import and create operations, show the user a preview first and proceed only after confirmation
|
||||
- Deletions require explicit user confirmation
|
||||
- When authoring Skills via AgentFS, simply use the Write tool to create the file
|
||||
|
||||
### 背景知识
|
||||
### Background Knowledge
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
> AgentFS repository structure, troubleshooting tips, and protected paths are detailed in `_agentfs-background.md` and `_protected-paths.yaml`.
|
||||
|
||||
### 依赖
|
||||
### Dependencies
|
||||
|
||||
- Agent Service HTTP API(Skills 路由组)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
- Write / Edit 工具(AgentFS 直写场景)
|
||||
- Agent Service HTTP API (Skills route group)
|
||||
- The local API address declaration in the system prompt
|
||||
- Write / Edit tools (for the AgentFS direct-authoring scenario)
|
||||
|
||||
512
skills/manage-skills/SKILL.zh-CN.md
Normal file
512
skills/manage-skills/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,512 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# manage-skills 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
管理技能的完整生命周期——导入、编写、安装、更新、删除。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
manage-skills 是一个**元技能(Meta-Skill)**,赋予 DesireCore 管理技能系统的能力。它涵盖 5 种核心操作:
|
||||
|
||||
1. **从 URL 导入技能** — 指定远程 SKILL.md 文件 URL,抓取内容并创建
|
||||
2. **从 Git 仓库批量导入** — 克隆 Git 仓库,扫描所有 SKILL.md,选择性导入
|
||||
3. **通过 API 管理已有技能** — 列出、读取、更新、删除、启用/禁用技能
|
||||
4. **通过 AgentFS 直接编写 SKILL.md** — 使用 Write/Edit 工具在文件系统创建技能
|
||||
5. **批量操作与跨 Agent 复制** — 批量启用/禁用/删除,以及复制技能到其他 Agent
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想从 GitHub 等平台导入社区分享的技能
|
||||
- 用户想给某个 Agent 安装新技能、增强其能力
|
||||
- 用户需要编写自定义技能教会 Agent 新的工作流程
|
||||
- 用户想批量管理已有技能(启用/禁用/删除)
|
||||
- 用户想把一个 Agent 的技能复制给另一个 Agent
|
||||
- 用户需要查看或编辑某个技能的内容
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **自我扩展**:Agent 可通过导入或编写技能,自主扩展能力边界
|
||||
- **可治理**:所有技能变更通过 API 或文件系统操作,可追溯、可审计
|
||||
- **灵活性**:支持 API 导入和文件系统直写两种方式,适应不同场景
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 1. 从 URL 导入单个技能
|
||||
|
||||
适用于导入单个 SKILL.md 文件(如 GitHub raw 链接)。
|
||||
|
||||
**步骤 1:抓取远程内容**
|
||||
|
||||
```bash
|
||||
POST /api/skills/fetch-url
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"url": "https://raw.githubusercontent.com/user/repo/main/my-skill/SKILL.md"
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`200 OK`):
|
||||
|
||||
```json
|
||||
{
|
||||
"content": "---\nname: 我的技能\ndescription: ...\n---\n\n# 技能内容..."
|
||||
}
|
||||
```
|
||||
|
||||
**安全限制**:
|
||||
|
||||
- 仅允许 HTTPS URL
|
||||
- 文件大小上限 20MB
|
||||
- 请求超时 30 秒
|
||||
|
||||
**步骤 2:创建技能**
|
||||
|
||||
抓取成功后,根据作用域选择创建端点:
|
||||
|
||||
**创建全局技能**(所有 Agent 可见):
|
||||
|
||||
```bash
|
||||
POST /api/skills
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"skillId": "my-skill",
|
||||
"content": "<上一步返回的 content>"
|
||||
}
|
||||
```
|
||||
|
||||
**创建 Agent 级技能**(仅指定 Agent 可见):
|
||||
|
||||
```bash
|
||||
POST /api/agents/{agentId}/skills
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"id": "my-skill",
|
||||
"fullContent": "<上一步返回的 content>"
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`201 Created`):
|
||||
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"skill": { "id": "my-skill", "name": "我的技能", "description": "..." }
|
||||
}
|
||||
```
|
||||
|
||||
### 2. 从 Git 仓库批量导入
|
||||
|
||||
适用于导入包含多个技能的 Git 仓库。
|
||||
|
||||
**步骤 1:扫描仓库**
|
||||
|
||||
```bash
|
||||
POST /api/skills/fetch-git
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"url": "https://github.com/user/skill-collection.git"
|
||||
}
|
||||
```
|
||||
|
||||
**成功响应**(`200 OK`):
|
||||
|
||||
```json
|
||||
{
|
||||
"skills": [
|
||||
{
|
||||
"id": "data-analysis",
|
||||
"path": "data-analysis",
|
||||
"content": "---\nname: 数据分析\n...",
|
||||
"sidecarFiles": [{ "name": "examples.md", "content": "..." }]
|
||||
},
|
||||
{
|
||||
"id": "report-writing",
|
||||
"path": "report-writing",
|
||||
"content": "---\nname: 报告撰写\n..."
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
API 会自动:
|
||||
|
||||
- 使用 `--depth=1` 浅克隆以减少下载量
|
||||
- 递归扫描目录中的 SKILL.md 文件
|
||||
- 从目录名推导 skillId(fallback 从 frontmatter name 生成 slug)
|
||||
- 收集同目录的 sidecar 文件(如 examples.md, references/ 等)
|
||||
- 完成后自动清理临时目录
|
||||
|
||||
**步骤 2:逐个导入选中的技能**
|
||||
|
||||
向用户展示扫描结果列表,让用户选择要导入的技能,然后逐个调用创建 API:
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
POST /api/skills
|
||||
{ "skillId": "data-analysis", "content": "<content>" }
|
||||
|
||||
# 或 Agent 级技能
|
||||
POST /api/agents/{agentId}/skills
|
||||
{ "id": "data-analysis", "fullContent": "<content>" }
|
||||
```
|
||||
|
||||
**sidecarFiles 处理**:如果扫描结果包含 sidecarFiles,需要在创建技能后将它们写入对应目录:
|
||||
|
||||
```bash
|
||||
# 全局技能的 sidecar 文件路径
|
||||
~/.desirecore/skills/{skillId}/{filename}
|
||||
|
||||
# Agent 级技能的 sidecar 文件路径
|
||||
~/.desirecore/agents/{agentId}/skills/{skillId}/{filename}
|
||||
```
|
||||
|
||||
### 3. 通过 API 管理已有技能
|
||||
|
||||
#### 列出所有技能
|
||||
|
||||
```bash
|
||||
GET /api/skills/list
|
||||
GET /api/skills/list?agentId={agentId}
|
||||
GET /api/skills/list?includeDisabled=true
|
||||
```
|
||||
|
||||
返回包含 project、agent、global 三级作用域的技能列表。
|
||||
|
||||
#### 列出指定 Agent 的技能
|
||||
|
||||
```bash
|
||||
GET /api/agents/{agentId}/skills
|
||||
```
|
||||
|
||||
#### 读取技能内容
|
||||
|
||||
```bash
|
||||
# 按作用域优先级自动解析
|
||||
GET /api/skills/{skillId}/content
|
||||
GET /api/skills/{skillId}/content?agentId={agentId}
|
||||
|
||||
# 读取指定 Agent 的技能
|
||||
GET /api/agents/{agentId}/skills/{skillId}
|
||||
```
|
||||
|
||||
#### 更新技能内容
|
||||
|
||||
**更新全局技能**:
|
||||
|
||||
```bash
|
||||
PUT /api/skills/{skillId}/content
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"content": "---\nname: 更新后的技能\n...\n---\n\n# 新内容..."
|
||||
}
|
||||
```
|
||||
|
||||
**更新 Agent 级技能**:
|
||||
|
||||
```bash
|
||||
PUT /api/agents/{agentId}/skills/{skillId}
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"content": "---\nname: 更新后的技能\n...\n---\n\n# 新内容...",
|
||||
"bumpVersion": "minor"
|
||||
}
|
||||
```
|
||||
|
||||
`bumpVersion` 可选值:`major` | `minor` | `patch`,指定后自动递增版本号。内容变化时系统会自动更新 `metadata.updated_at`。
|
||||
|
||||
#### 删除技能
|
||||
|
||||
```bash
|
||||
# 删除全局技能
|
||||
DELETE /api/skills/{skillId}
|
||||
|
||||
# 删除 Agent 级技能
|
||||
DELETE /api/agents/{agentId}/skills/{skillId}
|
||||
```
|
||||
|
||||
#### 启用/禁用技能
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
PATCH /api/skills/{skillId}/status
|
||||
Content-Type: application/json
|
||||
{ "enabled": false }
|
||||
|
||||
# Agent 级技能
|
||||
PATCH /api/agents/{agentId}/skills/{skillId}/status
|
||||
Content-Type: application/json
|
||||
{ "enabled": true }
|
||||
```
|
||||
|
||||
#### 批量操作
|
||||
|
||||
```bash
|
||||
POST /api/agents/{agentId}/skills/batch
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"action": "enable",
|
||||
"ids": ["skill-a", "skill-b", "skill-c"]
|
||||
}
|
||||
```
|
||||
|
||||
`action` 可选值:`enable` | `disable` | `delete`
|
||||
|
||||
#### 复制技能到其他 Agent
|
||||
|
||||
```bash
|
||||
POST /api/agents/{targetAgentId}/skills/copy
|
||||
Content-Type: application/json
|
||||
|
||||
{
|
||||
"sourceSkillId": "data-analysis",
|
||||
"sourceAgentId": "analyst",
|
||||
"targetSkillId": "data-analysis-v2"
|
||||
}
|
||||
```
|
||||
|
||||
可选参数:
|
||||
|
||||
- `sourceAgentId` — 源 Agent ID(从 agent 级复制时必填)
|
||||
- `sourceSource` — 源作用域:`project` | `agent` | `global`
|
||||
- `sourceWorkDir` — 源 project workDir(从 project 级复制时使用)
|
||||
- `targetSkillId` — 目标技能 ID(不填则沿用 sourceSkillId)
|
||||
|
||||
### 4. 通过 AgentFS 直接编写 SKILL.md
|
||||
|
||||
当需要从零创建技能,或 API 方式不够灵活时,可直接在文件系统编写 SKILL.md。
|
||||
|
||||
#### 目录结构
|
||||
|
||||
**全局技能**(所有 Agent 可见):
|
||||
|
||||
```
|
||||
~/.desirecore/skills/
|
||||
└── my-new-skill/
|
||||
├── SKILL.md # 必须:技能定义文件
|
||||
├── examples/ # 可选:示例文件
|
||||
├── scripts/ # 可选:辅助脚本
|
||||
└── references/ # 可选:参考资料
|
||||
```
|
||||
|
||||
**Agent 级技能**(仅指定 Agent 可见):
|
||||
|
||||
```
|
||||
~/.desirecore/agents/{agentId}/
|
||||
└── skills/
|
||||
└── my-new-skill/
|
||||
├── SKILL.md
|
||||
└── ...
|
||||
```
|
||||
|
||||
#### SKILL.md 完整格式
|
||||
|
||||
```markdown
|
||||
---
|
||||
# === 必填字段 ===
|
||||
description: >-
|
||||
技能用途的完整描述。应包含 "Use when" 触发提示,
|
||||
帮助 AI 判断何时使用该技能。
|
||||
|
||||
# === 推荐字段 ===
|
||||
name: 技能显示名称
|
||||
version: 1.0.0
|
||||
type: procedural
|
||||
risk_level: low
|
||||
status: enabled
|
||||
tags:
|
||||
- tag1
|
||||
- tag2
|
||||
metadata:
|
||||
author: your-name
|
||||
updated_at: '2026-03-03'
|
||||
|
||||
# === 可选字段 ===
|
||||
disable-model-invocation: true
|
||||
requires:
|
||||
tools:
|
||||
- Bash
|
||||
- Read
|
||||
optional_tools:
|
||||
- Edit
|
||||
---
|
||||
|
||||
# skill-id 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
用一句话描述这个技能做什么。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
详细描述技能的核心能力。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 场景 1
|
||||
- 场景 2
|
||||
|
||||
### 核心价值
|
||||
|
||||
- 价值 1
|
||||
- 价值 2
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 具体操作步骤
|
||||
|
||||
按阶段/步骤详细描述执行流程、API 调用、输入输出格式等。
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| -------- | -------- |
|
||||
| ... | ... |
|
||||
```
|
||||
|
||||
#### 使用 Write 工具创建技能示例
|
||||
|
||||
以下示例展示如何使用 Write 工具创建一个全局技能:
|
||||
|
||||
```
|
||||
目标路径:~/.desirecore/skills/daily-summary/SKILL.md
|
||||
```
|
||||
|
||||
写入内容:
|
||||
|
||||
```markdown
|
||||
---
|
||||
name: 每日摘要
|
||||
description: >-
|
||||
汇总当天对话记录,生成结构化的每日工作摘要。
|
||||
Use when 用户要求总结今天的工作、生成日报、或回顾对话内容。
|
||||
version: 1.0.0
|
||||
type: procedural
|
||||
risk_level: low
|
||||
status: enabled
|
||||
tags:
|
||||
- summary
|
||||
- daily
|
||||
- productivity
|
||||
metadata:
|
||||
author: user
|
||||
updated_at: '2026-03-03'
|
||||
---
|
||||
|
||||
# daily-summary 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
汇总当天对话记录,自动生成结构化的工作摘要。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
从对话历史中提取关键信息,按项目/主题分类整理,生成包含完成事项、
|
||||
待办事项和重要决策的每日摘要。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户在一天工作结束时要求总结
|
||||
- 用户需要生成日报或周报素材
|
||||
- 用户想回顾某天的对话和决策
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 摘要结构
|
||||
|
||||
1. 今日完成事项
|
||||
2. 进行中事项
|
||||
3. 重要决策和结论
|
||||
4. 明日待办建议
|
||||
```
|
||||
|
||||
### 5. SKILL.md 格式参考
|
||||
|
||||
#### Frontmatter 字段表
|
||||
|
||||
| 字段 | 必填 | 类型 | 说明 |
|
||||
| -------------------------- | -------- | -------- | -------------------------------------------------- |
|
||||
| `description` | **必填** | string | 技能用途描述,建议包含 "Use when" 触发提示 |
|
||||
| `name` | 推荐 | string | 技能显示名称 |
|
||||
| `version` | 推荐 | string | 语义版本号(如 `1.0.0`) |
|
||||
| `type` | 推荐 | enum | `procedural` / `conversational` / `meta` |
|
||||
| `risk_level` | 推荐 | enum | `low` / `medium` / `high` |
|
||||
| `status` | 推荐 | enum | `enabled` / `disabled` |
|
||||
| `tags` | 可选 | string[] | 标签列表,用于搜索和分类 |
|
||||
| `disable-model-invocation` | 可选 | boolean | `true`=L0+L1 自动注入 system prompt;`false`=L0+L1+L2 完整内容注入;默认 `true` |
|
||||
| `requires` | 可选 | object | 依赖声明:`tools`、`optional_tools`、`connections` |
|
||||
| `metadata` | 可选 | object | 元信息:`author`、`updated_at` |
|
||||
| `market` | 可选 | object | 市场展示元数据(仅市场发布的技能需要) |
|
||||
|
||||
#### type 说明
|
||||
|
||||
| 类型 | 含义 | 示例 |
|
||||
| ---------------- | ------------------------ | ---------------------- |
|
||||
| `procedural` | 流程型,按步骤执行 | 数据分析流程、审批流程 |
|
||||
| `conversational` | 对话型,通过多轮对话完成 | 需求收集、头脑风暴 |
|
||||
| `meta` | 元技能,管理其他资源 | 创建 Agent、管理技能 |
|
||||
|
||||
#### Markdown Body 结构(L0 / L1 / L2)
|
||||
|
||||
| 层级 | 内容 | 用途 |
|
||||
| ---- | ----------------------------------- | ------------------ |
|
||||
| L0 | 一句话摘要 | 快速理解技能做什么 |
|
||||
| L1 | 能力描述 + 使用场景 + 核心价值 | 判断是否适用 |
|
||||
| L2 | 详细规范:步骤、API、格式、错误处理 | 具体执行指南 |
|
||||
|
||||
### 6. 作用域说明
|
||||
|
||||
技能存在三个作用域层级,按优先级从高到低:
|
||||
|
||||
| 优先级 | 作用域 | 路径 | 可见范围 |
|
||||
| ------ | ---------- | ---------------------------------------- | ------------------ |
|
||||
| 最高 | Project 级 | `.claude/skills/` (项目根目录) | 当前项目所有 Agent |
|
||||
| 中 | Agent 级 | `~/.desirecore/agents/{agentId}/skills/` | 仅该 Agent |
|
||||
| 最低 | Global 级 | `~/.desirecore/skills/` | 所有 Agent |
|
||||
|
||||
**同名覆盖规则**:高优先级作用域的同名技能会覆盖低优先级的。例如 Agent 级有一个 `data-analysis` 技能,会覆盖全局同名技能。
|
||||
|
||||
### 7. 错误处理
|
||||
|
||||
| 错误码 | 场景 | 处理方式 |
|
||||
| ------ | ----------------------------- | -------------------------------------- |
|
||||
| 400 | 缺少必填字段或格式无效 | 提示用户检查输入,说明哪个字段有问题 |
|
||||
| 400 | SKILL.md frontmatter 校验失败 | 展示校验错误详情,引导用户修正 |
|
||||
| 404 | 技能不存在 | 提示技能 ID 可能拼写错误,列出可用技能 |
|
||||
| 404 | Git 仓库中无 SKILL.md | 提示仓库格式不符合技能规范 |
|
||||
| 409 | 技能已存在(冲突写入) | 建议使用 PUT 更新而非 POST 创建 |
|
||||
| 413 | 远程文件超过 20MB | 提示文件过大,建议精简内容 |
|
||||
| 504 | URL 抓取超时 | 提示网络超时,建议检查 URL 或稍后重试 |
|
||||
| 500 | 服务器内部错误 | 提示用户稍后再试 |
|
||||
|
||||
### 8. 权限说明
|
||||
|
||||
- 建议优先通过 `Bash` 工具调用 curl 访问 Agent Service HTTP API 完成操作
|
||||
- API 基础地址已注入到 system prompt 的「本机 API」小节,直接引用即可
|
||||
- 导入和创建操作建议先向用户展示预览,获得确认后再执行
|
||||
- 删除操作需要用户明确确认
|
||||
- 通过 AgentFS 编写技能时,使用 Write 工具创建文件即可
|
||||
|
||||
### 背景知识
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
|
||||
### 依赖
|
||||
|
||||
- Agent Service HTTP API(Skills 路由组)
|
||||
- System prompt 中的本机 API 地址声明
|
||||
- Write / Edit 工具(AgentFS 直写场景)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 团队管理
|
||||
name: manage-teams
|
||||
description: 创建和管理 Agent 团队,组织多 Agent 协作。Use when 需要多个 Agent 围绕同一任务协作、需要建立组织架构、或需要组长统一调度分派任务时。
|
||||
version: 1.2.3
|
||||
type: procedural
|
||||
@@ -13,6 +13,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-04'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 团队管理
|
||||
short_desc: 创建团队、管理成员、组织多 Agent 协作
|
||||
description: >-
|
||||
创建和管理 Agent 团队,组织多 Agent 协作。Use when 需要多个 Agent 围绕同一任务协作、需要建立组织架构、或需要组长统一调度分派任务时。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:2aad4d237ca4bc7a
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Team Management
|
||||
short_desc: Create teams, manage members, and organize multi-Agent collaboration
|
||||
description: >-
|
||||
Create and manage Agent teams to organize multi-Agent collaboration. Use when multiple Agents need to collaborate on the same task, when organizational structure is required, or when a team leader needs to orchestrate and dispatch tasks.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:2aad4d237ca4bc7a
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -31,73 +54,72 @@ market:
|
||||
fill="#34C759"/><circle cx="17.5" cy="4" r="0.9" fill="#34C759"
|
||||
fill-opacity="0.7"/><circle cx="21.5" cy="4" r="0.9" fill="#34C759"
|
||||
fill-opacity="0.7"/></svg>
|
||||
short_desc: 创建团队、管理成员、组织多 Agent 协作
|
||||
category: productivity
|
||||
---
|
||||
|
||||
# manage-teams 技能
|
||||
# manage-teams Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
创建和管理 Agent 团队,组织多 Agent 围绕共同任务协作。
|
||||
Create and manage Agent teams to organize multiple Agents collaborating around a shared task.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
manage-teams 是一个**流程型技能(Procedural Skill)**,赋予 DesireCore 创建和管理 Agent 团队的能力。团队是多个 Agent 围绕共同任务协作的组织单元,每个团队有一个组长(supervisor)负责接收需求、拆解任务、分派给成员、汇总结果。
|
||||
manage-teams is a **Procedural Skill** that gives DesireCore the ability to create and manage Agent teams. A team is an organizational unit in which multiple Agents collaborate around a shared task; each team has a supervisor responsible for receiving requirements, decomposing tasks, dispatching work to members, and consolidating results.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 需要多个 Agent 围绕同一任务持续协作(如项目组)
|
||||
- 需要建立组织架构(部门/团队层级)
|
||||
- 需要组长统一调度、拆解和分派任务
|
||||
- 简单一次性委派不够,需要共享上下文的长期协作
|
||||
- Multiple Agents need to collaborate continuously on the same task (e.g., a project group)
|
||||
- An organizational hierarchy is required (departments / team levels)
|
||||
- A supervisor is needed to centrally orchestrate, decompose, and dispatch tasks
|
||||
- Simple one-off delegation is insufficient and long-term collaboration with shared context is required
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **组织化协作**:从单点委派升级为团队协作模式
|
||||
- **灵活管理**:支持临时团队和持久团队两种模式
|
||||
- **动态调整**:运行时可添加/移除成员、更换组长
|
||||
- **Organized collaboration**: upgrade from point-to-point delegation to a team collaboration model
|
||||
- **Flexible management**: supports both ephemeral and persistent team modes
|
||||
- **Dynamic adjustment**: members can be added/removed and supervisors swapped at runtime
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## 核心概念
|
||||
## Core Concepts
|
||||
|
||||
### 团队 vs 单点委派
|
||||
### Teams vs. Single-point Delegation
|
||||
|
||||
| 场景 | 推荐方式 | 理由 |
|
||||
| Scenario | Recommended Approach | Rationale |
|
||||
|------|---------|------|
|
||||
| 一次性简单问题 | `Delegate(target, mode='sync')` | 无需组织开销 |
|
||||
| 需要一个专家处理 | `Delegate(target, mode='sync/async')` | 一对一足够 |
|
||||
| 需要多专家各出意见 | `Delegate(targets, mode='fan-out')` | 并行分派无需创建团队 |
|
||||
| 持续协作 + 共享上下文 | **创建团队** | 团队提供共享 workdir 和组织架构 |
|
||||
| 组织架构管理 | **创建嵌套团队** | 部门/团队层级关系 |
|
||||
| One-off simple problem | `Delegate(target, mode='sync')` | No need for organizational overhead |
|
||||
| Need a single expert to handle | `Delegate(target, mode='sync/async')` | One-to-one is sufficient |
|
||||
| Need multiple experts to weigh in | `Delegate(targets, mode='fan-out')` | Parallel dispatch without creating a team |
|
||||
| Continuous collaboration + shared context | **Create a team** | Teams provide a shared workdir and structure |
|
||||
| Organizational hierarchy management | **Create nested teams** | Department / team hierarchy relationships |
|
||||
|
||||
### 团队类型
|
||||
### Team Types
|
||||
|
||||
- **临时团队(ephemeral)**:任务驱动,完成后可解散。适合项目制协作。
|
||||
- **持久团队(persistent)**:长期存在,适合部门/团队。临时团队可升级为持久团队。
|
||||
- **Ephemeral team**: task-driven, can be disbanded after completion. Suitable for project-based collaboration.
|
||||
- **Persistent team**: long-lived, suitable for departments / teams. Ephemeral teams can be promoted to persistent.
|
||||
|
||||
### 组长唯一性约束
|
||||
### Supervisor Uniqueness Constraint
|
||||
|
||||
**一个 Agent 只能担任一个团队的组长(TL)。** 这是组织架构的硬性约束:
|
||||
**An Agent can only serve as the supervisor (TL) of a single team.** This is a hard constraint of the organizational structure:
|
||||
|
||||
- 创建团队时,如果调用者已是其他团队的组长,应先卸任原团队组长(`set_supervisor` 指定接替者)再创建新团队
|
||||
- 不要将已担任组长的 Agent 设为另一个团队的组长
|
||||
- 一个 Agent 可以同时是某团队的组长和另一个团队的普通成员,但不能同时担任两个团队的组长
|
||||
- When creating a team, if the caller is already a supervisor of another team, they must first step down from the original team (use `set_supervisor` to designate a successor) before creating the new team
|
||||
- Do not assign an Agent who already serves as supervisor to be the supervisor of another team
|
||||
- An Agent can simultaneously be the supervisor of one team and a regular member of another, but cannot be supervisor of two teams at once
|
||||
|
||||
### 组长职责
|
||||
### Supervisor Responsibilities
|
||||
|
||||
1. 接收用户需求,分析任务复杂度
|
||||
2. 拆解子任务,决定需要哪些成员参与
|
||||
3. 使用 `Delegate` 工具分派任务(单点或 fan-out)
|
||||
4. 汇总各成员结果,给出综合回答
|
||||
5. 根据需要动态调整成员(添加/移除)
|
||||
1. Receive user requirements and analyze task complexity
|
||||
2. Decompose subtasks and decide which members are needed
|
||||
3. Use the `Delegate` tool to dispatch tasks (single-point or fan-out)
|
||||
4. Consolidate results from members and produce an integrated answer
|
||||
5. Dynamically adjust members (add/remove) as needed
|
||||
|
||||
## 操作指南
|
||||
## Operations Guide
|
||||
|
||||
### 创建团队
|
||||
### Create a Team
|
||||
|
||||
```
|
||||
ManageTeam({
|
||||
@@ -108,11 +130,11 @@ ManageTeam({
|
||||
})
|
||||
```
|
||||
|
||||
组长默认为调用者(你自己)。创建后你就是这个团队的 supervisor。
|
||||
The supervisor defaults to the caller (you). After creation, you are the supervisor of this team.
|
||||
|
||||
### 向团队成员分派任务
|
||||
### Dispatch Tasks to Team Members
|
||||
|
||||
**单点委派**(一个成员处理):
|
||||
**Single-point delegation** (one member handles it):
|
||||
```
|
||||
Delegate({
|
||||
target: 'legal-advisor',
|
||||
@@ -121,7 +143,7 @@ Delegate({
|
||||
})
|
||||
```
|
||||
|
||||
**扇出委派**(多个成员并行):
|
||||
**Fan-out delegation** (multiple members in parallel):
|
||||
```
|
||||
Delegate({
|
||||
targets: ['legal-advisor', 'finance-advisor', 'real-estate'],
|
||||
@@ -131,7 +153,7 @@ Delegate({
|
||||
})
|
||||
```
|
||||
|
||||
### 管理成员
|
||||
### Manage Members
|
||||
|
||||
```
|
||||
// 添加成员
|
||||
@@ -150,7 +172,7 @@ ManageTeam({ action: 'remove_members', teamId: '...', members: ['agent-a', 'agen
|
||||
ManageTeam({ action: 'set_supervisor', teamId: '...', agentId: 'new-leader' })
|
||||
```
|
||||
|
||||
### 团队生命周期
|
||||
### Team Lifecycle
|
||||
|
||||
```
|
||||
// 任务完成,解散临时团队
|
||||
@@ -160,13 +182,13 @@ ManageTeam({ action: 'disband', teamId: '...' })
|
||||
ManageTeam({ action: 'promote', teamId: '...' })
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
## Best Practices
|
||||
|
||||
1. **先评估再创建团队**:简单任务直接 Delegate,不要过度组织
|
||||
2. **成员精简**:只拉入真正需要的专家,避免信息过载
|
||||
3. **优先团队内成员**:在团队中优先委派给团队内成员。如需团队外专家的一次性意见,可临时 Delegate 咨询而无需加入团队;若反复需要,则用 add_member 正式拉入
|
||||
4. **明确任务描述**:分派时给出清晰的任务描述和背景信息
|
||||
5. **及时汇总**:收到成员结果后及时汇总,不要让用户等待
|
||||
6. **动态调整**:发现缺少某领域专家时,用 add_member 补充
|
||||
7. **用完即散**:临时团队任务完成后及时解散,保持组织整洁
|
||||
8. **组长唯一**:一个 Agent 只担任一个团队的组长,避免职责分散导致管理混乱
|
||||
1. **Evaluate before creating a team**: simple tasks should be delegated directly without over-organizing
|
||||
2. **Keep membership lean**: only bring in the experts truly needed to avoid information overload
|
||||
3. **Prefer in-team members**: within a team, prefer delegating to its members. For one-off opinions from outside experts, ad-hoc `Delegate` consultation is fine without joining the team; if needed repeatedly, formally bring them in via `add_member`
|
||||
4. **Clear task descriptions**: provide a clear task description and background information when dispatching
|
||||
5. **Consolidate promptly**: synthesize member results promptly — do not keep the user waiting
|
||||
6. **Adjust dynamically**: when missing a domain expert, supplement with `add_member`
|
||||
7. **Disband after use**: disband ephemeral teams promptly when their task is done to keep the organization tidy
|
||||
8. **One supervisor per Agent**: an Agent should only serve as supervisor of one team to avoid management chaos from divided responsibilities
|
||||
|
||||
137
skills/manage-teams/SKILL.zh-CN.md
Normal file
137
skills/manage-teams/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,137 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# manage-teams 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
创建和管理 Agent 团队,组织多 Agent 围绕共同任务协作。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
manage-teams 是一个**流程型技能(Procedural Skill)**,赋予 DesireCore 创建和管理 Agent 团队的能力。团队是多个 Agent 围绕共同任务协作的组织单元,每个团队有一个组长(supervisor)负责接收需求、拆解任务、分派给成员、汇总结果。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 需要多个 Agent 围绕同一任务持续协作(如项目组)
|
||||
- 需要建立组织架构(部门/团队层级)
|
||||
- 需要组长统一调度、拆解和分派任务
|
||||
- 简单一次性委派不够,需要共享上下文的长期协作
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **组织化协作**:从单点委派升级为团队协作模式
|
||||
- **灵活管理**:支持临时团队和持久团队两种模式
|
||||
- **动态调整**:运行时可添加/移除成员、更换组长
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 团队 vs 单点委派
|
||||
|
||||
| 场景 | 推荐方式 | 理由 |
|
||||
|------|---------|------|
|
||||
| 一次性简单问题 | `Delegate(target, mode='sync')` | 无需组织开销 |
|
||||
| 需要一个专家处理 | `Delegate(target, mode='sync/async')` | 一对一足够 |
|
||||
| 需要多专家各出意见 | `Delegate(targets, mode='fan-out')` | 并行分派无需创建团队 |
|
||||
| 持续协作 + 共享上下文 | **创建团队** | 团队提供共享 workdir 和组织架构 |
|
||||
| 组织架构管理 | **创建嵌套团队** | 部门/团队层级关系 |
|
||||
|
||||
### 团队类型
|
||||
|
||||
- **临时团队(ephemeral)**:任务驱动,完成后可解散。适合项目制协作。
|
||||
- **持久团队(persistent)**:长期存在,适合部门/团队。临时团队可升级为持久团队。
|
||||
|
||||
### 组长唯一性约束
|
||||
|
||||
**一个 Agent 只能担任一个团队的组长(TL)。** 这是组织架构的硬性约束:
|
||||
|
||||
- 创建团队时,如果调用者已是其他团队的组长,应先卸任原团队组长(`set_supervisor` 指定接替者)再创建新团队
|
||||
- 不要将已担任组长的 Agent 设为另一个团队的组长
|
||||
- 一个 Agent 可以同时是某团队的组长和另一个团队的普通成员,但不能同时担任两个团队的组长
|
||||
|
||||
### 组长职责
|
||||
|
||||
1. 接收用户需求,分析任务复杂度
|
||||
2. 拆解子任务,决定需要哪些成员参与
|
||||
3. 使用 `Delegate` 工具分派任务(单点或 fan-out)
|
||||
4. 汇总各成员结果,给出综合回答
|
||||
5. 根据需要动态调整成员(添加/移除)
|
||||
|
||||
## 操作指南
|
||||
|
||||
### 创建团队
|
||||
|
||||
```
|
||||
ManageTeam({
|
||||
action: 'create',
|
||||
name: '房产评估项目组',
|
||||
members: ['legal-advisor', 'finance-advisor', 'real-estate'],
|
||||
task: '综合评估目标房产'
|
||||
})
|
||||
```
|
||||
|
||||
组长默认为调用者(你自己)。创建后你就是这个团队的 supervisor。
|
||||
|
||||
### 向团队成员分派任务
|
||||
|
||||
**单点委派**(一个成员处理):
|
||||
```
|
||||
Delegate({
|
||||
target: 'legal-advisor',
|
||||
task: '检查该房产的产权状况和法律风险',
|
||||
mode: 'sync'
|
||||
})
|
||||
```
|
||||
|
||||
**扇出委派**(多个成员并行):
|
||||
```
|
||||
Delegate({
|
||||
targets: ['legal-advisor', 'finance-advisor', 'real-estate'],
|
||||
task: '从各自专业角度评估这套房产',
|
||||
mode: 'fan-out',
|
||||
strategy: 'parallel'
|
||||
})
|
||||
```
|
||||
|
||||
### 管理成员
|
||||
|
||||
```
|
||||
// 添加成员
|
||||
ManageTeam({ action: 'add_member', teamId: '...', agentId: 'new-agent' })
|
||||
|
||||
// 批量添加成员
|
||||
ManageTeam({ action: 'add_members', teamId: '...', members: ['agent-a', 'agent-b'] })
|
||||
|
||||
// 移除成员
|
||||
ManageTeam({ action: 'remove_member', teamId: '...', agentId: 'old-agent' })
|
||||
|
||||
// 批量移除成员
|
||||
ManageTeam({ action: 'remove_members', teamId: '...', members: ['agent-a', 'agent-b'] })
|
||||
|
||||
// 更换组长
|
||||
ManageTeam({ action: 'set_supervisor', teamId: '...', agentId: 'new-leader' })
|
||||
```
|
||||
|
||||
### 团队生命周期
|
||||
|
||||
```
|
||||
// 任务完成,解散临时团队
|
||||
ManageTeam({ action: 'disband', teamId: '...' })
|
||||
|
||||
// 或升级为持久团队(长期使用)
|
||||
ManageTeam({ action: 'promote', teamId: '...' })
|
||||
```
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **先评估再创建团队**:简单任务直接 Delegate,不要过度组织
|
||||
2. **成员精简**:只拉入真正需要的专家,避免信息过载
|
||||
3. **优先团队内成员**:在团队中优先委派给团队内成员。如需团队外专家的一次性意见,可临时 Delegate 咨询而无需加入团队;若反复需要,则用 add_member 正式拉入
|
||||
4. **明确任务描述**:分派时给出清晰的任务描述和背景信息
|
||||
5. **及时汇总**:收到成员结果后及时汇总,不要让用户等待
|
||||
6. **动态调整**:发现缺少某领域专家时,用 add_member 补充
|
||||
7. **用完即散**:临时团队任务完成后及时解散,保持组织整洁
|
||||
8. **组长唯一**:一个 Agent 只担任一个团队的组长,避免职责分散导致管理混乱
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: MiniMax 文生图
|
||||
name: minimax-image-gen
|
||||
description: >-
|
||||
Use this skill when the user wants to generate images using MiniMax's
|
||||
image-01 model. Supports text-to-image and subject reference for character
|
||||
@@ -23,6 +23,29 @@ requires:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-25'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: MiniMax 文生图
|
||||
short_desc: 基于 MiniMax image-01 的文本生成图片技能
|
||||
description: >-
|
||||
Use this skill when the user wants to generate images using MiniMax's image-01 model. Supports text-to-image and subject reference for character consistency. Use when 用户提到 生成图片、画图、文生图、创建图片、 AI 绘画、生成插图、画一张、帮我画、设计图片、MiniMax 画图。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:4630268ef3bd4e23
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: MiniMax Image Generation
|
||||
short_desc: Text-to-image generation skill powered by MiniMax image-01
|
||||
description: >-
|
||||
Use this skill when the user wants to generate images using MiniMax's image-01 model. Supports text-to-image and subject reference for character consistency. Use when the user mentions generate images, draw a picture, text-to-image, create an image, AI painting, generate illustration, draw one for me, help me draw, design an image, MiniMax drawing.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:4630268ef3bd4e23
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -32,7 +55,6 @@ market:
|
||||
stroke-width="1.2"/><path d="M3 16l5-5 4 4 3-3 6 6" stroke="#34C759"
|
||||
stroke-width="1.5" stroke-linecap="round"
|
||||
stroke-linejoin="round"/></svg>
|
||||
short_desc: 基于 MiniMax image-01 的文本生成图片技能
|
||||
category: media
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -41,19 +63,19 @@ market:
|
||||
listed: false
|
||||
---
|
||||
|
||||
# minimax-image-gen 技能
|
||||
# minimax-image-gen Skill
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
## Mandatory Rules (violations will cause feature failure)
|
||||
|
||||
1. **必须使用 `"response_format": "url"`** — 禁止 `"base64"`,base64 会导致输出截断
|
||||
2. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
3. **必须通过 `/api/media/upload` 上传到 media-store** — 禁止保存到本地路径
|
||||
4. **必须使用 `dc-media://` 协议展示图片** — 唯一能让前端正确渲染的方式
|
||||
5. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
1. **Must use `"response_format": "url"`** — `"base64"` is forbidden, base64 will cause output truncation
|
||||
2. **Must access agent-service over HTTPS** — `https://127.0.0.1:${PORT}` with `-k` to skip certificate verification
|
||||
3. **Must upload to media-store via `/api/media/upload`** — saving to local paths is forbidden
|
||||
4. **Must use the `dc-media://` protocol to display images** — the only way the frontend can render correctly
|
||||
5. **Use Bash curl throughout** — do not use the HttpRequest tool or Python
|
||||
|
||||
## 完整执行流程(严格按此三步执行)
|
||||
## Complete Execution Flow (strictly follow these three steps)
|
||||
|
||||
### 第一步:调用 API 生成图片
|
||||
### Step 1: Call the API to generate the image
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -73,9 +95,9 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}'
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `data.data.image_urls[0]` 得到图片 URL。
|
||||
Extract `data.data.image_urls[0]` from the JSON response to obtain the image URL.
|
||||
|
||||
### 第二步:下载并上传到 media-store
|
||||
### Step 2: Download and upload to media-store
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -85,33 +107,33 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-gen.png;type=image/png"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段(格式如 `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png`)。
|
||||
Extract the `mediaId` field from the JSON response (format like `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png`).
|
||||
|
||||
### 第三步:用 dc-media 协议展示图片
|
||||
### Step 3: Display the image with the dc-media protocol
|
||||
|
||||
在你的回复文本中直接写 Markdown 图片语法:
|
||||
Write Markdown image syntax directly in your reply text:
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
例如:``
|
||||
For example: ``
|
||||
|
||||
前端会自动将 `dc-media://` 转为可访问的图片 URL 并渲染出来。
|
||||
The frontend will automatically convert `dc-media://` into an accessible image URL and render it.
|
||||
|
||||
## 参数映射
|
||||
## Parameter Mapping
|
||||
|
||||
| 用户意图 | aspect_ratio |
|
||||
| User Intent | aspect_ratio |
|
||||
|---------|-------------|
|
||||
| 正方形/头像 | "1:1" |
|
||||
| 横版/风景/壁纸 | "16:9" |
|
||||
| 竖版/手机/海报 | "9:16" |
|
||||
| 标准照片 | "4:3" |
|
||||
| 竖版照片 | "3:4" |
|
||||
| Square / avatar | "1:1" |
|
||||
| Landscape / scenery / wallpaper | "16:9" |
|
||||
| Portrait / phone / poster | "9:16" |
|
||||
| Standard photo | "4:3" |
|
||||
| Portrait photo | "3:4" |
|
||||
|
||||
## 主体参考(角色一致性)
|
||||
## Subject Reference (character consistency)
|
||||
|
||||
在 body 中添加 `subject_reference`:
|
||||
Add `subject_reference` in the body:
|
||||
|
||||
```json
|
||||
"subject_reference": [
|
||||
@@ -119,8 +141,8 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
]
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
## Error Handling
|
||||
|
||||
- `"error": "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
- `statusCode: 401`:API Key 无效
|
||||
- `statusCode: 429`:频率限制,稍后重试
|
||||
- `"error": "未找到匹配的供应商"`: MiniMax Media Provider not configured
|
||||
- `statusCode: 401`: Invalid API Key
|
||||
- `statusCode: 429`: Rate limited, retry later
|
||||
|
||||
85
skills/minimax-image-gen/SKILL.zh-CN.md
Normal file
85
skills/minimax-image-gen/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,85 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# minimax-image-gen 技能
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
|
||||
1. **必须使用 `"response_format": "url"`** — 禁止 `"base64"`,base64 会导致输出截断
|
||||
2. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
3. **必须通过 `/api/media/upload` 上传到 media-store** — 禁止保存到本地路径
|
||||
4. **必须使用 `dc-media://` 协议展示图片** — 唯一能让前端正确渲染的方式
|
||||
5. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
|
||||
## 完整执行流程(严格按此三步执行)
|
||||
|
||||
### 第一步:调用 API 生成图片
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"providerId": "provider-minimax-media-001",
|
||||
"endpoint": "/image_generation",
|
||||
"body": {
|
||||
"model": "image-01",
|
||||
"prompt": "这里替换为英文图片描述",
|
||||
"aspect_ratio": "1:1",
|
||||
"response_format": "url",
|
||||
"n": 1
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `data.data.image_urls[0]` 得到图片 URL。
|
||||
|
||||
### 第二步:下载并上传到 media-store
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
IMAGE_URL="第一步拿到的图片URL"
|
||||
curl -sL "$IMAGE_URL" -o /tmp/minimax-gen.png && \
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-gen.png;type=image/png"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段(格式如 `xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx.png`)。
|
||||
|
||||
### 第三步:用 dc-media 协议展示图片
|
||||
|
||||
在你的回复文本中直接写 Markdown 图片语法:
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
例如:``
|
||||
|
||||
前端会自动将 `dc-media://` 转为可访问的图片 URL 并渲染出来。
|
||||
|
||||
## 参数映射
|
||||
|
||||
| 用户意图 | aspect_ratio |
|
||||
|---------|-------------|
|
||||
| 正方形/头像 | "1:1" |
|
||||
| 横版/风景/壁纸 | "16:9" |
|
||||
| 竖版/手机/海报 | "9:16" |
|
||||
| 标准照片 | "4:3" |
|
||||
| 竖版照片 | "3:4" |
|
||||
|
||||
## 主体参考(角色一致性)
|
||||
|
||||
在 body 中添加 `subject_reference`:
|
||||
|
||||
```json
|
||||
"subject_reference": [
|
||||
{ "type": "character", "image_file": { "url": "参考图片URL" } }
|
||||
]
|
||||
```
|
||||
|
||||
## 错误处理
|
||||
|
||||
- `"error": "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
- `statusCode: 401`:API Key 无效
|
||||
- `statusCode: 429`:频率限制,稍后重试
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: MiniMax 音乐生成
|
||||
name: minimax-music-gen
|
||||
description: >-
|
||||
Use this skill when the user wants to generate music using MiniMax's
|
||||
Music Generation API. Supports text-to-music with lyrics, instrumental
|
||||
@@ -25,6 +25,29 @@ requires:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-03'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: MiniMax 音乐生成
|
||||
short_desc: 基于 MiniMax Music 2.6 的文本生成音乐技能
|
||||
description: >-
|
||||
Use this skill when the user wants to generate music using MiniMax's Music Generation API. Supports text-to-music with lyrics, instrumental generation, and music cover. Use when 用户提到 生成音乐、文生音乐、 AI 作曲、创作歌曲、写一首歌、音乐生成、AI 音乐、MiniMax 音乐、 作词作曲、纯音乐、伴奏、翻唱、cover。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:403153a9c1da2ad9
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: MiniMax Music Generation
|
||||
short_desc: Text-to-music skill powered by MiniMax Music 2.6
|
||||
description: >-
|
||||
Use this skill when the user wants to generate music using MiniMax's Music Generation API. Supports text-to-music with lyrics, instrumental generation, and music cover. Use when the user mentions generating music, text-to-music, AI composing, creating songs, writing a song, music generation, AI music, MiniMax music, songwriting, instrumental music, accompaniment, cover, or remake.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:403153a9c1da2ad9
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-04'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -35,7 +58,6 @@ market:
|
||||
stroke-linejoin="round"/><circle cx="6.5" cy="18" r="2.5" fill="#AF52DE"
|
||||
fill-opacity="0.6"/><circle cx="16.5" cy="16" r="2.5" fill="#AF52DE"
|
||||
fill-opacity="0.6"/></svg>
|
||||
short_desc: 基于 MiniMax Music 2.6 的文本生成音乐技能
|
||||
category: media
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -43,45 +65,45 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# minimax-music-gen 技能
|
||||
# minimax-music-gen Skill
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
## Mandatory Rules (violations will cause functionality to fail)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
3. **禁止使用 `output_format: "url"`** — URL 下载在 Token Plan 等场景下会因 CDN 鉴权失败返回空文件。必须使用默认的 hex 格式,音频数据直接在 API 响应中返回
|
||||
1. **Must access agent-service over HTTPS** — `https://127.0.0.1:${PORT}` with `-k` to skip certificate verification
|
||||
2. **Use Bash curl throughout** — do not use the HttpRequest tool or Python
|
||||
3. **Do not use `output_format: "url"`** — URL downloads will return empty files in scenarios such as Token Plan due to CDN authentication failures. Always use the default hex format; audio data is returned directly in the API response
|
||||
|
||||
## 完整执行流程
|
||||
## Full Execution Flow
|
||||
|
||||
### 前置条件
|
||||
### Prerequisites
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Provider(常规 API 或 Token Plan)并填写 API Key
|
||||
- agent-service 正在运行
|
||||
- The user has configured the MiniMax Provider (regular API or Token Plan) in Resource Manager → Compute and filled in the API Key
|
||||
- agent-service is running
|
||||
|
||||
### 核心概念
|
||||
### Core Concepts
|
||||
|
||||
MiniMax Music Generation 是**同步 API**(非异步任务模式),调用后直接返回音频数据。支持三种模式:
|
||||
MiniMax Music Generation is a **synchronous API** (not an asynchronous task model); it returns audio data directly when called. Three modes are supported:
|
||||
|
||||
| 模式 | model | 说明 |
|
||||
|------|-------|------|
|
||||
| 歌曲生成 | `music-2.6` | 提供 prompt + lyrics,生成带人声的歌曲 |
|
||||
| 纯器乐 | `music-2.6` | 设置 `is_instrumental: true`,仅需 prompt |
|
||||
| 翻唱/Cover | `music-cover` | 提供参考音频 + prompt,基于旋律骨架重新编曲 |
|
||||
| Mode | model | Description |
|
||||
|------|-------|-------------|
|
||||
| Song generation | `music-2.6` | Provide prompt + lyrics to generate a song with vocals |
|
||||
| Pure instrumental | `music-2.6` | Set `is_instrumental: true`; only a prompt is needed |
|
||||
| Cover | `music-cover` | Provide a reference audio + prompt; rearrange based on the melodic skeleton |
|
||||
|
||||
### 歌词结构标签
|
||||
### Lyrics Structure Tags
|
||||
|
||||
lyrics 字段支持以下结构标签来组织歌曲段落:
|
||||
The lyrics field supports the following structure tags to organize song sections:
|
||||
|
||||
| 标签 | 含义 |
|
||||
|------|------|
|
||||
| `[verse]` | 主歌 |
|
||||
| `[chorus]` | 副歌 |
|
||||
| `[bridge]` | 桥段 |
|
||||
| `[intro]` | 前奏 |
|
||||
| `[outro]` | 尾声 |
|
||||
| `[interlude]` | 间奏 |
|
||||
| Tag | Meaning |
|
||||
|-----|---------|
|
||||
| `[verse]` | Verse |
|
||||
| `[chorus]` | Chorus |
|
||||
| `[bridge]` | Bridge |
|
||||
| `[intro]` | Intro |
|
||||
| `[outro]` | Outro |
|
||||
| `[interlude]` | Interlude |
|
||||
|
||||
示例歌词格式:
|
||||
Example lyrics format:
|
||||
```
|
||||
[verse]
|
||||
夜晚的城市灯火阑珊
|
||||
@@ -92,9 +114,9 @@ lyrics 字段支持以下结构标签来组织歌曲段落:
|
||||
所有的喧嚣都已远去
|
||||
```
|
||||
|
||||
### 生成歌曲(带人声)
|
||||
### Generate a Song (with Vocals)
|
||||
|
||||
**注意:不要传 `output_format` 参数,使用默认的 hex 格式。**
|
||||
**Note: Do not pass the `output_format` parameter; use the default hex format.**
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -117,7 +139,7 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}'
|
||||
```
|
||||
|
||||
### 生成纯器乐
|
||||
### Generate Pure Instrumental
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -140,11 +162,11 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}'
|
||||
```
|
||||
|
||||
### 响应处理与保存
|
||||
### Response Handling and Saving
|
||||
|
||||
API 返回 JSON,音频数据以 hex 编码存放在 `data.data.audio.data` 字段中。
|
||||
The API returns JSON; audio data is hex-encoded and stored in the `data.data.audio.data` field.
|
||||
|
||||
**响应结构**:
|
||||
**Response structure**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
@@ -168,69 +190,69 @@ API 返回 JSON,音频数据以 hex 编码存放在 `data.data.audio.data` 字
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:`status` 字段含义为 1=合成中(流式场景)、2=合成完成。非流式模式下返回时 status 为 2。
|
||||
**Note**: The `status` field means 1 = synthesizing (streaming scenario), 2 = synthesis complete. In non-streaming mode, the returned status is 2.
|
||||
|
||||
### 将 hex 音频数据保存到 media-store
|
||||
### Save the hex Audio Data to media-store
|
||||
|
||||
从响应 JSON 中提取 `data.data.audio.data` 字段的 hex 字符串,转为二进制后上传:
|
||||
Extract the hex string from the `data.data.audio.data` field of the response JSON, convert it to binary, and upload:
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
# 将 API 响应保存到临时文件(避免 hex 数据过大撑爆 shell 变量)
|
||||
# 假设上一步的 curl 输出已保存到 /tmp/minimax-music-resp.json
|
||||
# Save the API response to a temporary file (avoid letting large hex data overflow shell variables)
|
||||
# Assume the curl output of the previous step has been saved to /tmp/minimax-music-resp.json
|
||||
|
||||
# 提取 hex 数据并转为二进制(纯 Bash,不依赖 Python)
|
||||
# Extract hex data and convert to binary (pure Bash, no Python dependency)
|
||||
jq -r '.data.data.audio.data' /tmp/minimax-music-resp.json | xxd -r -p > /tmp/minimax-music.mp3
|
||||
|
||||
# 验证文件有效(大于 1KB 且为音频格式)
|
||||
# Verify the file is valid (greater than 1KB and in audio format)
|
||||
FILE_SIZE=$(stat -f%z /tmp/minimax-music.mp3 2>/dev/null || stat -c%s /tmp/minimax-music.mp3 2>/dev/null)
|
||||
if [ "$FILE_SIZE" -lt 1024 ]; then
|
||||
echo "ERROR: 音频文件异常(${FILE_SIZE} 字节),可能生成失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 上传到 media-store
|
||||
# Upload to media-store
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-music.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
从上传响应 JSON 中提取 `mediaId` 字段。
|
||||
Extract the `mediaId` field from the upload response JSON.
|
||||
|
||||
### 展示结果
|
||||
### Display the Result
|
||||
|
||||
在回复中使用 dc-media 协议引用(前端会自动识别音频扩展名并渲染播放器):
|
||||
In the reply, use a dc-media protocol reference (the frontend will automatically detect the audio extension and render a player):
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
### 参数说明
|
||||
### Parameter Descriptions
|
||||
|
||||
| 参数 | 说明 | 必填 | 默认值 |
|
||||
|------|------|------|--------|
|
||||
| model | 模型名称 | 是 | "music-2.6" |
|
||||
| prompt | 音乐风格/情绪描述 | 有歌词时可选,纯器乐/cover 必填 | — |
|
||||
| lyrics | 歌词(支持结构标签) | 非纯器乐模式必填 | — |
|
||||
| is_instrumental | 是否生成纯器乐 | 否 | false |
|
||||
| lyrics_optimizer | 根据 prompt 自动生成歌词 | 否 | false |
|
||||
| audio_setting.format | 音频格式:mp3/wav/pcm | 否 | "mp3" |
|
||||
| audio_setting.sample_rate | 采样率:16000/24000/32000/44100 | 否 | 32000 |
|
||||
| audio_setting.bitrate | 比特率:32000/64000/128000/256000 | 否 | 128000 |
|
||||
| Parameter | Description | Required | Default |
|
||||
|-----------|-------------|----------|---------|
|
||||
| model | Model name | Yes | "music-2.6" |
|
||||
| prompt | Music style/mood description | Optional when lyrics are present; required for pure instrumental/cover | — |
|
||||
| lyrics | Lyrics (structure tags supported) | Required when not in pure instrumental mode | — |
|
||||
| is_instrumental | Whether to generate pure instrumental | No | false |
|
||||
| lyrics_optimizer | Auto-generate lyrics from the prompt | No | false |
|
||||
| audio_setting.format | Audio format: mp3/wav/pcm | No | "mp3" |
|
||||
| audio_setting.sample_rate | Sample rate: 16000/24000/32000/44100 | No | 32000 |
|
||||
| audio_setting.bitrate | Bitrate: 32000/64000/128000/256000 | No | 128000 |
|
||||
|
||||
### prompt 写法建议
|
||||
### Tips for Writing Prompts
|
||||
|
||||
prompt 用于描述音乐的风格、情绪和乐器编排,建议用逗号分隔关键词:
|
||||
The prompt is used to describe the music's style, mood, and instrumentation; commas are recommended to separate keywords:
|
||||
|
||||
- 风格:`独立民谣`、`电子舞曲`、`古典钢琴`、`摇滚`、`R&B`、`爵士`、`嘻哈`
|
||||
- 情绪:`温暖`、`忧郁`、`欢快`、`史诗感`、`空灵`、`治愈`
|
||||
- 乐器:`吉他伴奏`、`钢琴独奏`、`弦乐铺底`、`合成器`、`鼓点强劲`
|
||||
- 结构:`渐进式编曲`、`开场留白渐入高潮`、`轻柔开头爆发副歌`
|
||||
- Style: `独立民谣`, `电子舞曲`, `古典钢琴`, `摇滚`, `R&B`, `爵士`, `嘻哈`
|
||||
- Mood: `温暖`, `忧郁`, `欢快`, `史诗感`, `空灵`, `治愈`
|
||||
- Instruments: `吉他伴奏`, `钢琴独奏`, `弦乐铺底`, `合成器`, `鼓点强劲`
|
||||
- Structure: `渐进式编曲`, `开场留白渐入高潮`, `轻柔开头爆发副歌`
|
||||
|
||||
示例:`"独立民谣,温暖治愈,木吉他为主,轻柔的鼓点,渐进式编曲"`
|
||||
Example: `"独立民谣,温暖治愈,木吉他为主,轻柔的鼓点,渐进式编曲"`
|
||||
|
||||
### 自动生成歌词模式
|
||||
### Auto-generated Lyrics Mode
|
||||
|
||||
如果用户只描述了想要的音乐风格但没有提供歌词,可以设置 `lyrics_optimizer: true`,模型会根据 prompt 自动生成歌词:
|
||||
If the user only describes the desired music style without providing lyrics, set `lyrics_optimizer: true` and the model will auto-generate lyrics from the prompt:
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -253,21 +275,21 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}'
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
- `base_resp.status_code: 1002`:频率限制,稍后重试
|
||||
- `base_resp.status_code: 1004`:API Key 认证失败
|
||||
- `base_resp.status_code: 1008`:余额不足
|
||||
- `base_resp.status_code: 1026`:内容敏感,修改歌词或 prompt 后重试
|
||||
- `base_resp.status_code: 2013`:参数错误,检查必填字段
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Provider
|
||||
- `base_resp.status_code: 1002`: rate limit reached, retry later
|
||||
- `base_resp.status_code: 1004`: API Key authentication failed
|
||||
- `base_resp.status_code: 1008`: insufficient balance
|
||||
- `base_resp.status_code: 1026`: content sensitive, modify the lyrics or prompt and retry
|
||||
- `base_resp.status_code: 2013`: parameter error, check required fields
|
||||
- `success: false` + `error: "未找到匹配的供应商"`: MiniMax Provider not configured
|
||||
|
||||
### 注意事项
|
||||
### Notes
|
||||
|
||||
- prompt 长度限制 1-2000 字符,lyrics 长度限制 1-3500 字符
|
||||
- Token Plan 用户:所有套餐免费使用 music-2.6(100 首/天,每首 ≤5 分钟)
|
||||
- 如果用户未明确要求,默认使用 `music-2.6` + `mp3` 格式 + 44100 采样率
|
||||
- 如果用户只给了主题没给歌词,使用 `lyrics_optimizer: true` 自动生成歌词
|
||||
- 如果用户要求纯音乐/伴奏,设置 `is_instrumental: true`
|
||||
- 音乐生成耗时较长(通常 30-90 秒),请耐心等待
|
||||
- hex 数据量较大(几 MB),务必用临时文件中转,不要用 shell 变量存储
|
||||
- The prompt length limit is 1-2000 characters; the lyrics length limit is 1-3500 characters
|
||||
- Token Plan users: all plans use music-2.6 for free (100 tracks/day, each track ≤5 minutes)
|
||||
- Unless the user specifies otherwise, default to `music-2.6` + `mp3` format + 44100 sample rate
|
||||
- If the user only gives a theme without lyrics, use `lyrics_optimizer: true` to auto-generate lyrics
|
||||
- If the user requests pure music/accompaniment, set `is_instrumental: true`
|
||||
- Music generation takes a relatively long time (typically 30-90 seconds); please be patient
|
||||
- The hex data volume is large (several MB); always use a temporary file as intermediary, do not store it in shell variables
|
||||
|
||||
230
skills/minimax-music-gen/SKILL.zh-CN.md
Normal file
230
skills/minimax-music-gen/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,230 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# minimax-music-gen 技能
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
3. **禁止使用 `output_format: "url"`** — URL 下载在 Token Plan 等场景下会因 CDN 鉴权失败返回空文件。必须使用默认的 hex 格式,音频数据直接在 API 响应中返回
|
||||
|
||||
## 完整执行流程
|
||||
|
||||
### 前置条件
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Provider(常规 API 或 Token Plan)并填写 API Key
|
||||
- agent-service 正在运行
|
||||
|
||||
### 核心概念
|
||||
|
||||
MiniMax Music Generation 是**同步 API**(非异步任务模式),调用后直接返回音频数据。支持三种模式:
|
||||
|
||||
| 模式 | model | 说明 |
|
||||
|------|-------|------|
|
||||
| 歌曲生成 | `music-2.6` | 提供 prompt + lyrics,生成带人声的歌曲 |
|
||||
| 纯器乐 | `music-2.6` | 设置 `is_instrumental: true`,仅需 prompt |
|
||||
| 翻唱/Cover | `music-cover` | 提供参考音频 + prompt,基于旋律骨架重新编曲 |
|
||||
|
||||
### 歌词结构标签
|
||||
|
||||
lyrics 字段支持以下结构标签来组织歌曲段落:
|
||||
|
||||
| 标签 | 含义 |
|
||||
|------|------|
|
||||
| `[verse]` | 主歌 |
|
||||
| `[chorus]` | 副歌 |
|
||||
| `[bridge]` | 桥段 |
|
||||
| `[intro]` | 前奏 |
|
||||
| `[outro]` | 尾声 |
|
||||
| `[interlude]` | 间奏 |
|
||||
|
||||
示例歌词格式:
|
||||
```
|
||||
[verse]
|
||||
夜晚的城市灯火阑珊
|
||||
我独自走在回家的路上
|
||||
|
||||
[chorus]
|
||||
这一刻时间仿佛停止
|
||||
所有的喧嚣都已远去
|
||||
```
|
||||
|
||||
### 生成歌曲(带人声)
|
||||
|
||||
**注意:不要传 `output_format` 参数,使用默认的 hex 格式。**
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"provider": "minimax",
|
||||
"endpoint": "/music_generation",
|
||||
"body": {
|
||||
"model": "music-2.6",
|
||||
"prompt": "独立民谣,温暖,治愈,吉他伴奏",
|
||||
"lyrics": "[verse]\n歌词内容\n\n[chorus]\n副歌内容",
|
||||
"audio_setting": {
|
||||
"format": "mp3",
|
||||
"sample_rate": 44100,
|
||||
"bitrate": 256000
|
||||
}
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 生成纯器乐
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"provider": "minimax",
|
||||
"endpoint": "/music_generation",
|
||||
"body": {
|
||||
"model": "music-2.6",
|
||||
"prompt": "电子音乐,氛围感,空灵,合成器铺底",
|
||||
"is_instrumental": true,
|
||||
"audio_setting": {
|
||||
"format": "mp3",
|
||||
"sample_rate": 44100,
|
||||
"bitrate": 256000
|
||||
}
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 响应处理与保存
|
||||
|
||||
API 返回 JSON,音频数据以 hex 编码存放在 `data.data.audio.data` 字段中。
|
||||
|
||||
**响应结构**:
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"data": {
|
||||
"audio": {
|
||||
"data": "hex编码的音频数据...",
|
||||
"status": 2
|
||||
}
|
||||
},
|
||||
"extra_info": {
|
||||
"music_duration": 180000,
|
||||
"music_sample_rate": 44100,
|
||||
"music_channel": 2,
|
||||
"bitrate": 256000,
|
||||
"music_size": 1234567
|
||||
},
|
||||
"base_resp": { "status_code": 0, "status_msg": "success" }
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
```
|
||||
|
||||
**注意**:`status` 字段含义为 1=合成中(流式场景)、2=合成完成。非流式模式下返回时 status 为 2。
|
||||
|
||||
### 将 hex 音频数据保存到 media-store
|
||||
|
||||
从响应 JSON 中提取 `data.data.audio.data` 字段的 hex 字符串,转为二进制后上传:
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
# 将 API 响应保存到临时文件(避免 hex 数据过大撑爆 shell 变量)
|
||||
# 假设上一步的 curl 输出已保存到 /tmp/minimax-music-resp.json
|
||||
|
||||
# 提取 hex 数据并转为二进制(纯 Bash,不依赖 Python)
|
||||
jq -r '.data.data.audio.data' /tmp/minimax-music-resp.json | xxd -r -p > /tmp/minimax-music.mp3
|
||||
|
||||
# 验证文件有效(大于 1KB 且为音频格式)
|
||||
FILE_SIZE=$(stat -f%z /tmp/minimax-music.mp3 2>/dev/null || stat -c%s /tmp/minimax-music.mp3 2>/dev/null)
|
||||
if [ "$FILE_SIZE" -lt 1024 ]; then
|
||||
echo "ERROR: 音频文件异常(${FILE_SIZE} 字节),可能生成失败"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# 上传到 media-store
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-music.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
从上传响应 JSON 中提取 `mediaId` 字段。
|
||||
|
||||
### 展示结果
|
||||
|
||||
在回复中使用 dc-media 协议引用(前端会自动识别音频扩展名并渲染播放器):
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
| 参数 | 说明 | 必填 | 默认值 |
|
||||
|------|------|------|--------|
|
||||
| model | 模型名称 | 是 | "music-2.6" |
|
||||
| prompt | 音乐风格/情绪描述 | 有歌词时可选,纯器乐/cover 必填 | — |
|
||||
| lyrics | 歌词(支持结构标签) | 非纯器乐模式必填 | — |
|
||||
| is_instrumental | 是否生成纯器乐 | 否 | false |
|
||||
| lyrics_optimizer | 根据 prompt 自动生成歌词 | 否 | false |
|
||||
| audio_setting.format | 音频格式:mp3/wav/pcm | 否 | "mp3" |
|
||||
| audio_setting.sample_rate | 采样率:16000/24000/32000/44100 | 否 | 32000 |
|
||||
| audio_setting.bitrate | 比特率:32000/64000/128000/256000 | 否 | 128000 |
|
||||
|
||||
### prompt 写法建议
|
||||
|
||||
prompt 用于描述音乐的风格、情绪和乐器编排,建议用逗号分隔关键词:
|
||||
|
||||
- 风格:`独立民谣`、`电子舞曲`、`古典钢琴`、`摇滚`、`R&B`、`爵士`、`嘻哈`
|
||||
- 情绪:`温暖`、`忧郁`、`欢快`、`史诗感`、`空灵`、`治愈`
|
||||
- 乐器:`吉他伴奏`、`钢琴独奏`、`弦乐铺底`、`合成器`、`鼓点强劲`
|
||||
- 结构:`渐进式编曲`、`开场留白渐入高潮`、`轻柔开头爆发副歌`
|
||||
|
||||
示例:`"独立民谣,温暖治愈,木吉他为主,轻柔的鼓点,渐进式编曲"`
|
||||
|
||||
### 自动生成歌词模式
|
||||
|
||||
如果用户只描述了想要的音乐风格但没有提供歌词,可以设置 `lyrics_optimizer: true`,模型会根据 prompt 自动生成歌词:
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"provider": "minimax",
|
||||
"endpoint": "/music_generation",
|
||||
"body": {
|
||||
"model": "music-2.6",
|
||||
"prompt": "一首关于夏日海边回忆的歌,独立民谣,温暖,吉他",
|
||||
"lyrics_optimizer": true,
|
||||
"audio_setting": {
|
||||
"format": "mp3",
|
||||
"sample_rate": 44100,
|
||||
"bitrate": 256000
|
||||
}
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
- `base_resp.status_code: 1002`:频率限制,稍后重试
|
||||
- `base_resp.status_code: 1004`:API Key 认证失败
|
||||
- `base_resp.status_code: 1008`:余额不足
|
||||
- `base_resp.status_code: 1026`:内容敏感,修改歌词或 prompt 后重试
|
||||
- `base_resp.status_code: 2013`:参数错误,检查必填字段
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Provider
|
||||
|
||||
### 注意事项
|
||||
|
||||
- prompt 长度限制 1-2000 字符,lyrics 长度限制 1-3500 字符
|
||||
- Token Plan 用户:所有套餐免费使用 music-2.6(100 首/天,每首 ≤5 分钟)
|
||||
- 如果用户未明确要求,默认使用 `music-2.6` + `mp3` 格式 + 44100 采样率
|
||||
- 如果用户只给了主题没给歌词,使用 `lyrics_optimizer: true` 自动生成歌词
|
||||
- 如果用户要求纯音乐/伴奏,设置 `is_instrumental: true`
|
||||
- 音乐生成耗时较长(通常 30-90 秒),请耐心等待
|
||||
- hex 数据量较大(几 MB),务必用临时文件中转,不要用 shell 变量存储
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: MiniMax 语音合成
|
||||
name: minimax-tts
|
||||
description: >-
|
||||
Use this skill when the user wants to convert text to speech using MiniMax's
|
||||
T2A (Text-to-Audio) API. Supports multiple voice styles, emotional control,
|
||||
@@ -24,6 +24,29 @@ requires:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-25'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: MiniMax 语音合成
|
||||
short_desc: 基于 MiniMax Speech-02 的文本转语音技能
|
||||
description: >-
|
||||
Use this skill when the user wants to convert text to speech using MiniMax's T2A (Text-to-Audio) API. Supports multiple voice styles, emotional control, and voice cloning. Use when 用户提到 语音合成、文字转语音、TTS、朗读、 读出来、生成语音、生成音频、文本转音频、配音、念出来、MiniMax 语音。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:455a2ee6365958c2
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: MiniMax Text-to-Speech
|
||||
short_desc: Text-to-speech skill powered by MiniMax Speech-02
|
||||
description: >-
|
||||
Use this skill when the user wants to convert text to speech using MiniMax's T2A (Text-to-Audio) API. Supports multiple voice styles, emotional control, and voice cloning. Use when the user mentions text-to-speech, TTS, read aloud, read it out, generate speech, generate audio, text-to-audio, voiceover, narrate it, MiniMax voice.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:455a2ee6365958c2
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -32,7 +55,6 @@ market:
|
||||
fill-opacity="0.1"/><path d="M8 9v6M11 7v10M14 10v4M17 8v8"
|
||||
stroke="#007AFF" stroke-width="2"
|
||||
stroke-linecap="round"/></svg>
|
||||
short_desc: 基于 MiniMax Speech-02 的文本转语音技能
|
||||
category: media
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -41,33 +63,33 @@ market:
|
||||
listed: false
|
||||
---
|
||||
|
||||
# minimax-tts 技能
|
||||
# minimax-tts Skill
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
## Mandatory Rules (violations will cause feature failure)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
1. **Must access agent-service over HTTPS** — `https://127.0.0.1:${PORT}` with `-k` to skip certificate verification
|
||||
2. **Use Bash curl throughout** — do not use the HttpRequest tool or Python
|
||||
|
||||
## 完整执行流程
|
||||
## Complete Execution Flow
|
||||
|
||||
### 前置条件
|
||||
### Prerequisites
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Media Provider 并填写 API Key
|
||||
- agent-service 正在运行
|
||||
- The user has configured a MiniMax Media Provider with an API Key under Resources → Compute
|
||||
- agent-service is running
|
||||
|
||||
### 语音选择指南
|
||||
### Voice Selection Guide
|
||||
|
||||
| voice_id | 特点 | 适用场景 |
|
||||
| voice_id | Characteristics | Use Cases |
|
||||
|----------|------|---------|
|
||||
| male-qn-qingse | 青涩男声 | 旁白、播客 |
|
||||
| female-shaonv | 少女女声 | 有声书、对话 |
|
||||
| female-yujie | 御姐女声 | 专业播报 |
|
||||
| presenter_male | 主持人男声 | 新闻、正式场合 |
|
||||
| presenter_female | 主持人女声 | 新闻、正式场合 |
|
||||
| male-qn-qingse | Young male voice | Narration, podcasts |
|
||||
| female-shaonv | Young female voice | Audiobooks, dialogue |
|
||||
| female-yujie | Mature female voice | Professional broadcasting |
|
||||
| presenter_male | Male anchor voice | News, formal occasions |
|
||||
| presenter_female | Female anchor voice | News, formal occasions |
|
||||
|
||||
### 生成语音
|
||||
### Generate Speech
|
||||
|
||||
MiniMax TTS 返回 JSON(包含音频 URL 或 hex 数据),`responseType` 使用 `"json"`。
|
||||
MiniMax TTS returns JSON (containing an audio URL or hex data); use `"json"` for `responseType`.
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -94,11 +116,11 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}'
|
||||
```
|
||||
|
||||
### 响应处理
|
||||
### Response Handling
|
||||
|
||||
MiniMax TTS 返回 JSON,根据请求参数可能返回 URL 或 hex 格式:
|
||||
MiniMax TTS returns JSON which, depending on the request parameters, may contain a URL or hex format:
|
||||
|
||||
**URL 格式响应**(推荐,需在 audio_setting 中设置 `"format": "url"`):
|
||||
**URL format response** (recommended, requires `"format": "url"` in audio_setting):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
@@ -115,7 +137,7 @@ MiniMax TTS 返回 JSON,根据请求参数可能返回 URL 或 hex 格式:
|
||||
}
|
||||
```
|
||||
|
||||
**Hex 格式响应**(默认):
|
||||
**Hex format response** (default):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
@@ -136,11 +158,11 @@ MiniMax TTS 返回 JSON,根据请求参数可能返回 URL 或 hex 格式:
|
||||
}
|
||||
```
|
||||
|
||||
### 下载并上传到 media-store
|
||||
### Download and Upload to media-store
|
||||
|
||||
音频 URL 有时效限制,必须立即下载并保存到本地 media-store。
|
||||
Audio URLs have a time limit, so they must be downloaded immediately and saved to the local media-store.
|
||||
|
||||
**URL 格式**:
|
||||
**URL format**:
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
AUDIO_URL="响应中的audio_url"
|
||||
@@ -149,7 +171,7 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-tts.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
**Hex 格式**:
|
||||
**Hex format**:
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
HEX_DATA="响应中的hex数据"
|
||||
@@ -158,49 +180,48 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-tts.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段。
|
||||
Extract the `mediaId` field from the JSON response.
|
||||
|
||||
### 展示结果
|
||||
### Display the Result
|
||||
|
||||
在回复中使用 dc-media 协议引用(前端会自动识别音频扩展名并渲染播放器):
|
||||
Reference it in your reply using the dc-media protocol (the frontend will automatically detect the audio extension and render a player):
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
### Parameter Reference
|
||||
|
||||
| 参数 | 说明 | 默认值 |
|
||||
| Parameter | Description | Default |
|
||||
|------|------|--------|
|
||||
| model | 模型 | "speech-02-hd"(高清)或 "speech-02-turbo"(快速) |
|
||||
| text | 要转换的文本 | 最大 10000 字符 |
|
||||
| voice_setting.voice_id | 语音角色 | "male-qn-qingse" |
|
||||
| voice_setting.speed | 语速 | 1.0 |
|
||||
| voice_setting.vol | 音量 | 1.0 |
|
||||
| voice_setting.pitch | 音调 | 0 |
|
||||
| audio_setting.format | 音频格式 | "mp3" |
|
||||
| audio_setting.sample_rate | 采样率 | 32000 |
|
||||
| model | Model | "speech-02-hd" (HD) or "speech-02-turbo" (fast) |
|
||||
| text | Text to convert | Max 10000 characters |
|
||||
| voice_setting.voice_id | Voice persona | "male-qn-qingse" |
|
||||
| voice_setting.speed | Speaking speed | 1.0 |
|
||||
| voice_setting.vol | Volume | 1.0 |
|
||||
| voice_setting.pitch | Pitch | 0 |
|
||||
| audio_setting.format | Audio format | "mp3" |
|
||||
| audio_setting.sample_rate | Sample rate | 32000 |
|
||||
|
||||
### 特殊语法
|
||||
### Special Syntax
|
||||
|
||||
MiniMax TTS 支持在文本中插入停顿标记:
|
||||
- `<#0.5#>` — 停顿 0.5 秒
|
||||
- `<#2#>` — 停顿 2 秒
|
||||
- 有效范围:0.01 ~ 99.99 秒
|
||||
MiniMax TTS supports inserting pause markers in the text:
|
||||
- `<#0.5#>` — pause for 0.5 seconds
|
||||
- `<#2#>` — pause for 2 seconds
|
||||
- Valid range: 0.01 ~ 99.99 seconds
|
||||
|
||||
示例:`"你好<#1#>欢迎来到 DesireCore"`
|
||||
Example: `"你好<#1#>欢迎来到 DesireCore"`
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
- `success: false` + `statusCode: 400`:文本为空或参数格式错误
|
||||
- `success: false` + `statusCode: 401`:API Key 无效
|
||||
- `success: false` + `statusCode: 429`:频率限制
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
- `success: false` + `statusCode: 400`: empty text or malformed parameters
|
||||
- `success: false` + `statusCode: 401`: invalid API Key
|
||||
- `success: false` + `statusCode: 429`: rate limited
|
||||
- `success: false` + `error: "未找到匹配的供应商"`: MiniMax Media Provider not configured
|
||||
|
||||
### 注意事项
|
||||
### Notes
|
||||
|
||||
- 文本超过 3000 字符时建议使用流式输出(但代理模式暂不支持流式)
|
||||
- 返回的 audio_url 有 24 小时时效
|
||||
- 如果用户未明确要求,默认使用 `speech-02-hd` + `male-qn-qingse` + 1.0 倍速
|
||||
- 长文本建议分段调用,每段不超过 3000 字符
|
||||
- For text exceeding 3000 characters, streaming output is recommended (proxy mode does not yet support streaming)
|
||||
- Returned audio_url is valid for 24 hours
|
||||
- Unless the user specifies otherwise, default to `speech-02-hd` + `male-qn-qingse` + 1.0x speed
|
||||
- For long text, split it into segments of no more than 3000 characters each
|
||||
|
||||
164
skills/minimax-tts/SKILL.zh-CN.md
Normal file
164
skills/minimax-tts/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,164 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# minimax-tts 技能
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
|
||||
## 完整执行流程
|
||||
|
||||
### 前置条件
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Media Provider 并填写 API Key
|
||||
- agent-service 正在运行
|
||||
|
||||
### 语音选择指南
|
||||
|
||||
| voice_id | 特点 | 适用场景 |
|
||||
|----------|------|---------|
|
||||
| male-qn-qingse | 青涩男声 | 旁白、播客 |
|
||||
| female-shaonv | 少女女声 | 有声书、对话 |
|
||||
| female-yujie | 御姐女声 | 专业播报 |
|
||||
| presenter_male | 主持人男声 | 新闻、正式场合 |
|
||||
| presenter_female | 主持人女声 | 新闻、正式场合 |
|
||||
|
||||
### 生成语音
|
||||
|
||||
MiniMax TTS 返回 JSON(包含音频 URL 或 hex 数据),`responseType` 使用 `"json"`。
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"providerId": "provider-minimax-media-001",
|
||||
"endpoint": "/t2a_v2",
|
||||
"body": {
|
||||
"model": "speech-02-hd",
|
||||
"text": "要转换为语音的文本内容",
|
||||
"voice_setting": {
|
||||
"voice_id": "male-qn-qingse",
|
||||
"speed": 1.0,
|
||||
"vol": 1.0,
|
||||
"pitch": 0
|
||||
},
|
||||
"audio_setting": {
|
||||
"format": "mp3",
|
||||
"sample_rate": 32000
|
||||
}
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 响应处理
|
||||
|
||||
MiniMax TTS 返回 JSON,根据请求参数可能返回 URL 或 hex 格式:
|
||||
|
||||
**URL 格式响应**(推荐,需在 audio_setting 中设置 `"format": "url"`):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"data": {
|
||||
"audio": {
|
||||
"audio_url": "https://...",
|
||||
"status": 1
|
||||
}
|
||||
},
|
||||
"base_resp": { "status_code": 0, "status_msg": "success" }
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
```
|
||||
|
||||
**Hex 格式响应**(默认):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"data": {
|
||||
"audio": {
|
||||
"data": "hex编码的音频数据...",
|
||||
"status": 1
|
||||
}
|
||||
},
|
||||
"extra_info": {
|
||||
"audio_length": 12345,
|
||||
"audio_sample_rate": 32000,
|
||||
"audio_size": 67890
|
||||
}
|
||||
},
|
||||
"statusCode": 200
|
||||
}
|
||||
```
|
||||
|
||||
### 下载并上传到 media-store
|
||||
|
||||
音频 URL 有时效限制,必须立即下载并保存到本地 media-store。
|
||||
|
||||
**URL 格式**:
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
AUDIO_URL="响应中的audio_url"
|
||||
curl -sL "$AUDIO_URL" -o /tmp/minimax-tts.mp3 && \
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-tts.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
**Hex 格式**:
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
HEX_DATA="响应中的hex数据"
|
||||
echo -n "$HEX_DATA" | xxd -r -p > /tmp/minimax-tts.mp3 && \
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-tts.mp3;type=audio/mpeg"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段。
|
||||
|
||||
### 展示结果
|
||||
|
||||
在回复中使用 dc-media 协议引用(前端会自动识别音频扩展名并渲染播放器):
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
| 参数 | 说明 | 默认值 |
|
||||
|------|------|--------|
|
||||
| model | 模型 | "speech-02-hd"(高清)或 "speech-02-turbo"(快速) |
|
||||
| text | 要转换的文本 | 最大 10000 字符 |
|
||||
| voice_setting.voice_id | 语音角色 | "male-qn-qingse" |
|
||||
| voice_setting.speed | 语速 | 1.0 |
|
||||
| voice_setting.vol | 音量 | 1.0 |
|
||||
| voice_setting.pitch | 音调 | 0 |
|
||||
| audio_setting.format | 音频格式 | "mp3" |
|
||||
| audio_setting.sample_rate | 采样率 | 32000 |
|
||||
|
||||
### 特殊语法
|
||||
|
||||
MiniMax TTS 支持在文本中插入停顿标记:
|
||||
- `<#0.5#>` — 停顿 0.5 秒
|
||||
- `<#2#>` — 停顿 2 秒
|
||||
- 有效范围:0.01 ~ 99.99 秒
|
||||
|
||||
示例:`"你好<#1#>欢迎来到 DesireCore"`
|
||||
|
||||
### 错误处理
|
||||
|
||||
- `success: false` + `statusCode: 400`:文本为空或参数格式错误
|
||||
- `success: false` + `statusCode: 401`:API Key 无效
|
||||
- `success: false` + `statusCode: 429`:频率限制
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
|
||||
### 注意事项
|
||||
|
||||
- 文本超过 3000 字符时建议使用流式输出(但代理模式暂不支持流式)
|
||||
- 返回的 audio_url 有 24 小时时效
|
||||
- 如果用户未明确要求,默认使用 `speech-02-hd` + `male-qn-qingse` + 1.0 倍速
|
||||
- 长文本建议分段调用,每段不超过 3000 字符
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: MiniMax 文生视频
|
||||
name: minimax-video-gen
|
||||
description: >-
|
||||
Use this skill when the user wants to generate videos using MiniMax's
|
||||
Hailuo model. Supports text-to-video, image-to-video, and subject reference.
|
||||
@@ -25,6 +25,29 @@ requires:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-25'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: MiniMax 文生视频
|
||||
short_desc: 基于 MiniMax Hailuo 的文本/图片生成视频技能
|
||||
description: >-
|
||||
Use this skill when the user wants to generate videos using MiniMax's Hailuo model. Supports text-to-video, image-to-video, and subject reference. The API is asynchronous — submit a task, poll for status, then download. Use when 用户提到 生成视频、文生视频、AI 视频、创建视频、视频生成、 动画生成、MiniMax 视频、海螺、Hailuo、图片变视频、图生视频。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:57314c8d07d63585
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: MiniMax Video Generation
|
||||
short_desc: Text/image-to-video skill powered by MiniMax Hailuo
|
||||
description: >-
|
||||
Use this skill when the user wants to generate videos using MiniMax's Hailuo model. Supports text-to-video, image-to-video, and subject reference. The API is asynchronous — submit a task, poll for status, then download. Use when the user mentions generating videos, text-to-video, AI video, creating videos, video generation, animation generation, MiniMax video, Hailuo, image-to-video.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:57314c8d07d63585
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -33,7 +56,6 @@ market:
|
||||
fill-opacity="0.1"/><polygon points="10,7 18,12 10,17" fill="#AF52DE"
|
||||
fill-opacity="0.6" stroke="#AF52DE" stroke-width="1.2"
|
||||
stroke-linejoin="round"/></svg>
|
||||
short_desc: 基于 MiniMax Hailuo 的文本/图片生成视频技能
|
||||
category: media
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -42,43 +64,43 @@ market:
|
||||
listed: false
|
||||
---
|
||||
|
||||
# minimax-video-gen 技能
|
||||
# minimax-video-gen Skill
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
## Mandatory Rules (violation will cause failure)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
3. **轮询间隔 10 秒** — 使用 `sleep 10` 等待
|
||||
1. **Must use HTTPS to access agent-service** — `https://127.0.0.1:${PORT}` with `-k` to skip certificate verification
|
||||
2. **Use Bash curl throughout** — do not use the HttpRequest tool or Python
|
||||
3. **Polling interval is 10 seconds** — use `sleep 10` to wait
|
||||
|
||||
## 完整执行流程
|
||||
## Full Execution Flow
|
||||
|
||||
### 前置条件
|
||||
### Prerequisites
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Media Provider 并填写 API Key
|
||||
- agent-service 正在运行
|
||||
- The user has already configured the MiniMax Media Provider in Resource Manager → Compute and entered the API Key
|
||||
- agent-service is running
|
||||
|
||||
### 核心概念:三步异步流程
|
||||
### Core Concept: Three-Step Asynchronous Flow
|
||||
|
||||
MiniMax 视频生成采用异步任务模式:
|
||||
MiniMax video generation uses an asynchronous task model:
|
||||
|
||||
1. **提交任务**:POST 创建视频生成任务,返回 `task_id`
|
||||
2. **轮询状态**:用 `task_id` 查询任务状态,直到 `status` 为 `"Success"` 或 `"Fail"`
|
||||
3. **下载视频**:用 `file_id` 获取下载 URL
|
||||
1. **Submit task**: POST to create a video generation task and receive a `task_id`
|
||||
2. **Poll status**: query the task status with `task_id` until `status` is `"Success"` or `"Fail"`
|
||||
3. **Download video**: use `file_id` to obtain the download URL
|
||||
|
||||
### 模型选择与降级策略
|
||||
### Model Selection and Fallback Strategy
|
||||
|
||||
| 模型 | 支持模式 | 特点 | 适用场景 |
|
||||
| Model | Supported Modes | Characteristics | Use Case |
|
||||
|------|---------|------|---------|
|
||||
| MiniMax-Hailuo-2.3 | 文生视频 + 图生视频 | 最高画质,默认首选 | 用户未指定时的默认选择 |
|
||||
| MiniMax-Hailuo-2.3-fast | **仅图生视频** | 速度快,成本低 50% | 图生视频场景下额度不足时降级 |
|
||||
| MiniMax-Hailuo-2.3 | Text-to-video + image-to-video | Highest quality, default first choice | Default when the user doesn't specify |
|
||||
| MiniMax-Hailuo-2.3-fast | **Image-to-video only** | Fast, 50% lower cost | Fallback when quota is insufficient in image-to-video scenarios |
|
||||
|
||||
**降级规则(强制)**:
|
||||
1. 默认使用 `MiniMax-Hailuo-2.3`
|
||||
2. **文生视频(T2V)额度不足时**:`MiniMax-Hailuo-2.3-fast` 不支持文生视频,无法降级。应直接告知用户额度不足,建议等待额度重置或切换到其他视频生成服务(如可灵)
|
||||
3. **图生视频(I2V)额度不足时**:可降级到 `MiniMax-Hailuo-2.3-fast`,告知用户"已切换到快速模型生成"
|
||||
4. 如果用户做图生视频且明确要求快速生成,直接使用 `MiniMax-Hailuo-2.3-fast`
|
||||
**Fallback rules (mandatory)**:
|
||||
1. Use `MiniMax-Hailuo-2.3` by default
|
||||
2. **When text-to-video (T2V) quota is insufficient**: `MiniMax-Hailuo-2.3-fast` does not support text-to-video and cannot be used as a fallback. Inform the user directly that the quota is insufficient and suggest waiting for the quota to reset or switching to another video generation service (such as Kling)
|
||||
3. **When image-to-video (I2V) quota is insufficient**: fall back to `MiniMax-Hailuo-2.3-fast` and inform the user "switched to the fast model for generation"
|
||||
4. If the user is doing image-to-video and explicitly requests fast generation, use `MiniMax-Hailuo-2.3-fast` directly
|
||||
|
||||
### 第一步:提交文生视频任务
|
||||
### Step 1: Submit a Text-to-Video Task
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -89,19 +111,19 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
"endpoint": "/video_generation",
|
||||
"body": {
|
||||
"model": "MiniMax-Hailuo-2.3",
|
||||
"prompt": "用户描述的视频内容"
|
||||
"prompt": "Video content described by the user"
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
可选参数(加入 body 中):
|
||||
- `"duration"`: 视频时长秒数(6 或 10)
|
||||
- `"resolution"`: `"768P"` 或 `"1080P"`
|
||||
Optional parameters (add to the body):
|
||||
- `"duration"`: video length in seconds (6 or 10)
|
||||
- `"resolution"`: `"768P"` or `"1080P"`
|
||||
|
||||
从 JSON 响应中提取 `data.task_id`。
|
||||
Extract `data.task_id` from the JSON response.
|
||||
|
||||
### 第一步(备选):图生视频
|
||||
### Step 1 (alternative): Image-to-Video
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -112,20 +134,20 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
"endpoint": "/video_generation",
|
||||
"body": {
|
||||
"model": "MiniMax-Hailuo-2.3",
|
||||
"prompt": "描述图片中场景的动态变化",
|
||||
"first_frame_image": "https://图片URL"
|
||||
"prompt": "Describe the dynamic changes of the scene in the image",
|
||||
"first_frame_image": "https://image-URL"
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 第二步:轮询任务状态
|
||||
### Step 2: Poll the Task Status
|
||||
|
||||
每隔 10 秒调用一次,直到 `status` 为 `"Success"` 或 `"Fail"`。将 `TASK_ID` 替换为第一步返回的 `task_id`。
|
||||
Call once every 10 seconds until `status` is `"Success"` or `"Fail"`. Replace `TASK_ID` with the `task_id` returned in Step 1.
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
TASK_ID="第一步返回的task_id"
|
||||
TASK_ID="task_id returned from step 1"
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
@@ -136,7 +158,7 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}"
|
||||
```
|
||||
|
||||
轮询响应(进行中):
|
||||
Polling response (in progress):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
@@ -148,7 +170,7 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}
|
||||
```
|
||||
|
||||
轮询响应(完成):
|
||||
Polling response (completed):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
@@ -160,13 +182,13 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}
|
||||
```
|
||||
|
||||
### 第三步:获取视频下载链接
|
||||
### Step 3: Get the Video Download URL
|
||||
|
||||
将 `FILE_ID` 替换为第二步完成响应中的 `file_id`。
|
||||
Replace `FILE_ID` with the `file_id` from the completed response in Step 2.
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
FILE_ID="第二步返回的file_id"
|
||||
FILE_ID="file_id returned from step 2"
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
@@ -177,41 +199,41 @@ curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
}"
|
||||
```
|
||||
|
||||
从响应中提取 `data.file.download_url`。
|
||||
Extract `data.file.download_url` from the response.
|
||||
|
||||
### 第四步:下载并上传到 media-store
|
||||
### Step 4: Download and Upload to media-store
|
||||
|
||||
下载 URL 有 24 小时时效,必须立即下载并保存到本地 media-store。
|
||||
The download URL is valid for 24 hours; you must download immediately and save it to the local media-store.
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
VIDEO_URL="第三步获取的download_url"
|
||||
VIDEO_URL="download_url obtained in step 3"
|
||||
curl -sL "$VIDEO_URL" -o /tmp/minimax-video.mp4 && \
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-video.mp4;type=video/mp4"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段。
|
||||
Extract the `mediaId` field from the JSON response.
|
||||
|
||||
### 第五步:用 dc-media 协议展示视频
|
||||
### Step 5: Display the Video Using the dc-media Protocol
|
||||
|
||||
在你的回复文本中直接写 Markdown 图片语法(前端会自动识别视频扩展名并渲染播放器):
|
||||
Write Markdown image syntax directly in your reply (the frontend will automatically recognize the video extension and render a player):
|
||||
|
||||
```
|
||||

|
||||

|
||||
```
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
- `status: "Fail"`:视频生成失败,向用户说明
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
- `success: false` + `error: "未配置 API Key"`:未填写 API Key
|
||||
- **额度不足**(`statusCode: 429`、`insufficient_quota`、`balance` 相关错误):文生视频无法降级(Fast 模型不支持 T2V),告知用户额度不足;图生视频可换用 `MiniMax-Hailuo-2.3-fast` 从第一步重试
|
||||
- 轮询超过 10 分钟未完成:告知用户任务可能超时
|
||||
- `status: "Fail"`: video generation failed; explain to the user
|
||||
- `success: false` + `error: "No matching provider found"`: MiniMax Media Provider is not configured
|
||||
- `success: false` + `error: "API Key not configured"`: API Key has not been entered
|
||||
- **Insufficient quota** (errors related to `statusCode: 429`, `insufficient_quota`, `balance`): text-to-video cannot fall back (the Fast model does not support T2V); inform the user of insufficient quota; image-to-video can switch to `MiniMax-Hailuo-2.3-fast` and retry from Step 1
|
||||
- Polling exceeds 10 minutes without completion: inform the user that the task may have timed out
|
||||
|
||||
### 注意事项
|
||||
### Notes
|
||||
|
||||
- MiniMax 视频生成是异步的,通常需要 2-10 分钟
|
||||
- 轮询间隔建议 10 秒
|
||||
- 下载 URL 有 24 小时时效
|
||||
- 如果用户未明确要求,默认不传 duration 和 resolution(使用 API 默认值)
|
||||
- MiniMax video generation is asynchronous and typically takes 2–10 minutes
|
||||
- A polling interval of 10 seconds is recommended
|
||||
- The download URL is valid for 24 hours
|
||||
- If the user does not explicitly request otherwise, by default do not pass `duration` or `resolution` (use API defaults)
|
||||
|
||||
175
skills/minimax-video-gen/SKILL.zh-CN.md
Normal file
175
skills/minimax-video-gen/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,175 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# minimax-video-gen 技能
|
||||
|
||||
## 强制规则(违反将导致功能失败)
|
||||
|
||||
1. **必须用 HTTPS 访问 agent-service** — `https://127.0.0.1:${PORT}` 加 `-k` 跳过证书验证
|
||||
2. **全程使用 Bash curl** — 不要使用 HttpRequest 工具或 Python
|
||||
3. **轮询间隔 10 秒** — 使用 `sleep 10` 等待
|
||||
|
||||
## 完整执行流程
|
||||
|
||||
### 前置条件
|
||||
|
||||
- 用户已在资源管理器-算力中配置 MiniMax Media Provider 并填写 API Key
|
||||
- agent-service 正在运行
|
||||
|
||||
### 核心概念:三步异步流程
|
||||
|
||||
MiniMax 视频生成采用异步任务模式:
|
||||
|
||||
1. **提交任务**:POST 创建视频生成任务,返回 `task_id`
|
||||
2. **轮询状态**:用 `task_id` 查询任务状态,直到 `status` 为 `"Success"` 或 `"Fail"`
|
||||
3. **下载视频**:用 `file_id` 获取下载 URL
|
||||
|
||||
### 模型选择与降级策略
|
||||
|
||||
| 模型 | 支持模式 | 特点 | 适用场景 |
|
||||
|------|---------|------|---------|
|
||||
| MiniMax-Hailuo-2.3 | 文生视频 + 图生视频 | 最高画质,默认首选 | 用户未指定时的默认选择 |
|
||||
| MiniMax-Hailuo-2.3-fast | **仅图生视频** | 速度快,成本低 50% | 图生视频场景下额度不足时降级 |
|
||||
|
||||
**降级规则(强制)**:
|
||||
1. 默认使用 `MiniMax-Hailuo-2.3`
|
||||
2. **文生视频(T2V)额度不足时**:`MiniMax-Hailuo-2.3-fast` 不支持文生视频,无法降级。应直接告知用户额度不足,建议等待额度重置或切换到其他视频生成服务(如可灵)
|
||||
3. **图生视频(I2V)额度不足时**:可降级到 `MiniMax-Hailuo-2.3-fast`,告知用户"已切换到快速模型生成"
|
||||
4. 如果用户做图生视频且明确要求快速生成,直接使用 `MiniMax-Hailuo-2.3-fast`
|
||||
|
||||
### 第一步:提交文生视频任务
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"providerId": "provider-minimax-media-001",
|
||||
"endpoint": "/video_generation",
|
||||
"body": {
|
||||
"model": "MiniMax-Hailuo-2.3",
|
||||
"prompt": "用户描述的视频内容"
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
可选参数(加入 body 中):
|
||||
- `"duration"`: 视频时长秒数(6 或 10)
|
||||
- `"resolution"`: `"768P"` 或 `"1080P"`
|
||||
|
||||
从 JSON 响应中提取 `data.task_id`。
|
||||
|
||||
### 第一步(备选):图生视频
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"providerId": "provider-minimax-media-001",
|
||||
"endpoint": "/video_generation",
|
||||
"body": {
|
||||
"model": "MiniMax-Hailuo-2.3",
|
||||
"prompt": "描述图片中场景的动态变化",
|
||||
"first_frame_image": "https://图片URL"
|
||||
},
|
||||
"responseType": "json"
|
||||
}'
|
||||
```
|
||||
|
||||
### 第二步:轮询任务状态
|
||||
|
||||
每隔 10 秒调用一次,直到 `status` 为 `"Success"` 或 `"Fail"`。将 `TASK_ID` 替换为第一步返回的 `task_id`。
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
TASK_ID="第一步返回的task_id"
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"providerId\": \"provider-minimax-media-001\",
|
||||
\"endpoint\": \"/query/video_generation?task_id=${TASK_ID}\",
|
||||
\"method\": \"GET\",
|
||||
\"responseType\": \"json\"
|
||||
}"
|
||||
```
|
||||
|
||||
轮询响应(进行中):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"task_id": "task_xxx",
|
||||
"status": "Processing",
|
||||
"file_id": ""
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
轮询响应(完成):
|
||||
```json
|
||||
{
|
||||
"success": true,
|
||||
"data": {
|
||||
"task_id": "task_xxx",
|
||||
"status": "Success",
|
||||
"file_id": "file_xxx"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 第三步:获取视频下载链接
|
||||
|
||||
将 `FILE_ID` 替换为第二步完成响应中的 `file_id`。
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
FILE_ID="第二步返回的file_id"
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media-proxy" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{
|
||||
\"providerId\": \"provider-minimax-media-001\",
|
||||
\"endpoint\": \"/files/retrieve?file_id=${FILE_ID}\",
|
||||
\"method\": \"GET\",
|
||||
\"responseType\": \"json\"
|
||||
}"
|
||||
```
|
||||
|
||||
从响应中提取 `data.file.download_url`。
|
||||
|
||||
### 第四步:下载并上传到 media-store
|
||||
|
||||
下载 URL 有 24 小时时效,必须立即下载并保存到本地 media-store。
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
VIDEO_URL="第三步获取的download_url"
|
||||
curl -sL "$VIDEO_URL" -o /tmp/minimax-video.mp4 && \
|
||||
curl -sk -X POST "https://127.0.0.1:${PORT}/api/media/upload" \
|
||||
-F "file=@/tmp/minimax-video.mp4;type=video/mp4"
|
||||
```
|
||||
|
||||
从 JSON 响应中提取 `mediaId` 字段。
|
||||
|
||||
### 第五步:用 dc-media 协议展示视频
|
||||
|
||||
在你的回复文本中直接写 Markdown 图片语法(前端会自动识别视频扩展名并渲染播放器):
|
||||
|
||||
```
|
||||

|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
- `status: "Fail"`:视频生成失败,向用户说明
|
||||
- `success: false` + `error: "未找到匹配的供应商"`:未配置 MiniMax Media Provider
|
||||
- `success: false` + `error: "未配置 API Key"`:未填写 API Key
|
||||
- **额度不足**(`statusCode: 429`、`insufficient_quota`、`balance` 相关错误):文生视频无法降级(Fast 模型不支持 T2V),告知用户额度不足;图生视频可换用 `MiniMax-Hailuo-2.3-fast` 从第一步重试
|
||||
- 轮询超过 10 分钟未完成:告知用户任务可能超时
|
||||
|
||||
### 注意事项
|
||||
|
||||
- MiniMax 视频生成是异步的,通常需要 2-10 分钟
|
||||
- 轮询间隔建议 10 秒
|
||||
- 下载 URL 有 24 小时时效
|
||||
- 如果用户未明确要求,默认不传 duration 和 resolution(使用 API 默认值)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: Node.js 运行时管理
|
||||
name: nodejs-runtime
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot
|
||||
Node.js, npm, pnpm, yarn, and JavaScript/TypeScript runtime environments.
|
||||
@@ -30,6 +30,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-02'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: Node.js 运行时管理
|
||||
short_desc: Node.js / npm / pnpm / yarn 安装与多版本(DesireCore Volta 优先)
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot Node.js, npm, pnpm, yarn, and JavaScript/TypeScript runtime environments. Covers four-tier fallback strategy: (1) DesireCore HTTP API for in-app installation, (2) DesireCore built-in Volta CLI for Node.js + package manager version management, (3) system package managers (brew/apt/dnf/winget/NodeSource), (4) community nvm/fnm as last resort. Also covers global package management, npm registry/proxy configuration, EACCES permission errors, and PATH troubleshooting. Triggers include: "install node", "node not found", "npm not found", "npm EACCES", "pnpm", "yarn", "volta", "nvm", "fnm", "nodejs version", "package-lock", or any Node.js / npm runtime error. 使用场景:用户需要 安装 Node.js、安装 npm、 pnpm、yarn、配置全局包、解决 EACCES、PATH 问题、镜像/代理配置。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:2b8a00816c65d71c
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Node.js Runtime Management
|
||||
short_desc: Node.js / npm / pnpm / yarn install and multi-version (DesireCore Volta first)
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot Node.js, npm, pnpm, yarn, and JavaScript/TypeScript runtime environments. Covers four-tier fallback strategy: (1) DesireCore HTTP API for in-app installation, (2) DesireCore built-in Volta CLI for Node.js + package manager version management, (3) system package managers (brew/apt/dnf/winget/NodeSource), (4) community nvm/fnm as last resort. Also covers global package management, npm registry/proxy configuration, EACCES permission errors, and PATH troubleshooting. Triggers include: "install node", "node not found", "npm not found", "npm EACCES", "pnpm", "yarn", "volta", "nvm", "fnm", "nodejs version", "package-lock", or any Node.js / npm runtime error. Use cases: the user needs to install Node.js, install npm, pnpm, yarn, configure global packages, resolve EACCES, PATH issues, registry mirror / proxy configuration.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:2b8a00816c65d71c
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -43,7 +66,6 @@ market:
|
||||
stroke-linejoin="round" fill="none"/><path d="M12 11.5v3M10 12.5l2 1l2-1"
|
||||
stroke="url(#node-a)" stroke-width="1.4" stroke-linecap="round"
|
||||
fill="none"/></svg>
|
||||
short_desc: Node.js / npm / pnpm / yarn 安装与多版本(DesireCore Volta 优先)
|
||||
category: development
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -51,63 +73,63 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# nodejs-runtime 技能
|
||||
# nodejs-runtime Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
**何时使用**:用户需要 安装 Node.js / 升级 Node / 切换 Node 多版本 / 安装或配置
|
||||
npm / pnpm / yarn / 排查 `node: command not found`、`npm: command not found`、
|
||||
EACCES 全局安装权限错误、node-gyp 编译失败、registry 镜像 / proxy 问题 等
|
||||
Node.js 运行时问题,或其他 skill(pptx 用 pptxgenjs 等)报告 "Node.js 不可用" 时。
|
||||
**When to use**: the user needs to install Node.js / upgrade Node / switch Node multi-version / install or configure
|
||||
npm / pnpm / yarn / troubleshoot `node: command not found`, `npm: command not found`,
|
||||
EACCES global install permission errors, node-gyp build failures, registry mirror / proxy issues, or other
|
||||
Node.js runtime problems, or when other skills (pptx using pptxgenjs, etc.) report "Node.js unavailable".
|
||||
|
||||
**怎么做**:优先使用 DesireCore 内置 Volta,按四级降级(HTTP API → Volta CLI →
|
||||
系统包管理器 brew/apt/NodeSource/winget → 社区方案 nvm/fnm)执行。
|
||||
**How**: prefer the DesireCore built-in Volta and follow a four-tier fallback (HTTP API → Volta CLI →
|
||||
system package manager brew/apt/NodeSource/winget → community options nvm/fnm).
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
procedural skill。每次执行 Node.js 环境操作前,先运行 `scripts/probe-node.sh` 取 JSON 快照,再按 `../dev-environment-setup/references/decision-tree.md` 四级降级选择路径。
|
||||
Procedural skill. Before each Node.js environment operation, run `scripts/probe-node.sh` to obtain a JSON snapshot, then choose a path according to the four-tier fallback in `../dev-environment-setup/references/decision-tree.md`.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- "node not found" / "npm not found"
|
||||
- 用户要求安装/升级 Node.js
|
||||
- 多版本切换(基于 `package.json#volta` 或 `.nvmrc`)
|
||||
- 安装/管理 pnpm / yarn / npm
|
||||
- "EACCES: permission denied"(npm 全局安装权限错误)
|
||||
- 配置 registry / proxy
|
||||
- 其他 skill(pptx 等)报告 Node.js 不可用
|
||||
- The user requests to install/upgrade Node.js
|
||||
- Multi-version switching (based on `package.json#volta` or `.nvmrc`)
|
||||
- Install/manage pnpm / yarn / npm
|
||||
- "EACCES: permission denied" (npm global install permission error)
|
||||
- Configure registry / proxy
|
||||
- Other skills (pptx, etc.) report Node.js unavailable
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **DesireCore 优先**:Volta + HTTP API 作为 L1/L2,避免污染系统 Node
|
||||
- **JSON 决策**:probe 脚本输出结构化数据,Claude 可直接解析
|
||||
- **package.json#volta 兼容**:Volta 自动按项目切换版本
|
||||
- **DesireCore first**: Volta + HTTP API as L1/L2, avoiding pollution of the system Node
|
||||
- **JSON-driven decisions**: the probe script outputs structured data that Claude can parse directly
|
||||
- **package.json#volta compatible**: Volta automatically switches versions per project
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 第一步:环境探测(必须)
|
||||
### Step 1: Environment Probe (mandatory)
|
||||
|
||||
```bash
|
||||
bash skills/nodejs-runtime/scripts/probe-node.sh > /tmp/node-probe.json
|
||||
cat /tmp/node-probe.json | jq .
|
||||
```
|
||||
|
||||
字段含义见 `../dev-environment-setup/references/probe-snapshot.md`。
|
||||
See `../dev-environment-setup/references/probe-snapshot.md` for field definitions.
|
||||
|
||||
### 第二步:选择执行路径
|
||||
### Step 2: Choose an Execution Path
|
||||
|
||||
| 条件 | 路径 |
|
||||
| Condition | Path |
|
||||
|------|------|
|
||||
| `desirecore_api` 非空 | **L1** HTTP API |
|
||||
| `desirecore_api` 空,`volta_path` 非空 | **L2** Volta CLI |
|
||||
| 上述都不满足 | **L3** 系统包管理器(brew / apt / NodeSource / winget) |
|
||||
| L1–L3 全部失败或用户明示 | **L4** 社区方案(nvm / fnm) |
|
||||
| `desirecore_api` non-empty | **L1** HTTP API |
|
||||
| `desirecore_api` empty, `volta_path` non-empty | **L2** Volta CLI |
|
||||
| Neither of the above | **L3** System package manager (brew / apt / NodeSource / winget) |
|
||||
| L1–L3 all fail or user explicitly requests | **L4** Community options (nvm / fnm) |
|
||||
|
||||
### 第三步:执行(仅展示主路径,详见各 references)
|
||||
### Step 3: Execute (only the main path is shown; see each reference for details)
|
||||
|
||||
#### L1:HTTP API(→ `references/volta-desirecore.md`)
|
||||
#### L1: HTTP API (→ `references/volta-desirecore.md`)
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -130,7 +152,7 @@ curl -sk -X POST "${BASE}/pkg/pnpm/install" \
|
||||
curl -sk -X POST "${BASE}/environment/refresh"
|
||||
```
|
||||
|
||||
#### L2:Volta CLI 绝对路径(→ `references/volta-desirecore.md`)
|
||||
#### L2: Volta CLI Absolute Path (→ `references/volta-desirecore.md`)
|
||||
|
||||
```bash
|
||||
VOLTA=~/.desirecore/runtime/volta/volta
|
||||
@@ -146,48 +168,48 @@ export VOLTA_FEATURE_PNPM=1
|
||||
"$VOLTA" pin node@22 pnpm@9
|
||||
```
|
||||
|
||||
Windows:`%USERPROFILE%\.desirecore\runtime\volta\volta.exe`。
|
||||
Windows: `%USERPROFILE%\.desirecore\runtime\volta\volta.exe`.
|
||||
|
||||
#### L3:系统包管理器
|
||||
#### L3: System Package Manager
|
||||
|
||||
| 平台 | 命令 |
|
||||
| Platform | Command |
|
||||
|------|------|
|
||||
| macOS | `brew install node` |
|
||||
| Debian/Ubuntu | NodeSource:`curl -fsSL https://deb.nodesource.com/setup_22.x \| sudo -E bash - && sudo apt install nodejs` |
|
||||
| Debian/Ubuntu | NodeSource: `curl -fsSL https://deb.nodesource.com/setup_22.x \| sudo -E bash - && sudo apt install nodejs` |
|
||||
| Fedora/RHEL | `curl -fsSL https://rpm.nodesource.com/setup_22.x \| sudo bash - && sudo dnf install nodejs` |
|
||||
| Arch | `sudo pacman -S nodejs npm` |
|
||||
| Windows | `winget install OpenJS.NodeJS.LTS` |
|
||||
|
||||
#### L4:nvm / fnm(→ `references/nvm-fallback.md`)
|
||||
#### L4: nvm / fnm (→ `references/nvm-fallback.md`)
|
||||
|
||||
仅在用户明示或上述失败时启用。
|
||||
Only enable when explicitly requested by the user or when the above fail.
|
||||
|
||||
### 第四步:包管理器策略
|
||||
### Step 4: Package Manager Strategy
|
||||
|
||||
详见 `references/package-managers.md`:
|
||||
- pnpm(推荐,磁盘高效、严格依赖)
|
||||
- yarn(Berry / Classic)
|
||||
- npm(默认,Node.js 自带)
|
||||
- 项目级 `package.json#volta` 自动切换
|
||||
See `references/package-managers.md` for details:
|
||||
- pnpm (recommended, disk-efficient, strict dependencies)
|
||||
- yarn (Berry / Classic)
|
||||
- npm (default, ships with Node.js)
|
||||
- Project-level `package.json#volta` automatic switching
|
||||
|
||||
### 第五步:故障排查
|
||||
### Step 5: Troubleshooting
|
||||
|
||||
详见 `references/troubleshooting.md`:
|
||||
- npm EACCES 权限错误(**不要用 sudo npm**)
|
||||
- registry / proxy 配置
|
||||
- node-gyp 编译失败
|
||||
- "node: command not found" 在 nvm 已装时
|
||||
See `references/troubleshooting.md` for details:
|
||||
- npm EACCES permission errors (**do not use sudo npm**)
|
||||
- registry / proxy configuration
|
||||
- node-gyp build failures
|
||||
- "node: command not found" when nvm is installed
|
||||
|
||||
## 重要约束
|
||||
## Important Constraints
|
||||
|
||||
1. **绝不 `sudo npm install -g`**:用户级 prefix 或 Volta/nvm。
|
||||
2. **修改环境后必须刷新**:L1 调 `POST /api/runtime/environment/refresh`;其它路径重跑 probe。
|
||||
3. **跨 skill 协作**:`pptx` 等需要 Node.js 时,按本 skill 主路径安装;npm 包速查见 `../dev-environment-setup/references/office-deps.md`。
|
||||
4. **package.json#volta 必须尊重**:检测到该字段时优先 Volta,不要切到 nvm。
|
||||
1. **Never `sudo npm install -g`**: use a user-level prefix or Volta/nvm.
|
||||
2. **Refresh after modifying the environment**: for L1, call `POST /api/runtime/environment/refresh`; for other paths, re-run the probe.
|
||||
3. **Cross-skill collaboration**: when `pptx` and others need Node.js, install via this skill's main path; for npm package quick reference, see `../dev-environment-setup/references/office-deps.md`.
|
||||
4. **Respect package.json#volta**: when this field is detected, prefer Volta — do not switch to nvm.
|
||||
|
||||
## 引用关系
|
||||
## References
|
||||
|
||||
- 决策树:`../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore 底座:`../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- 探测协议:`../dev-environment-setup/references/probe-snapshot.md`
|
||||
- 办公依赖(npm 包):`../dev-environment-setup/references/office-deps.md`
|
||||
- Decision tree: `../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore foundation: `../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- Probe protocol: `../dev-environment-setup/references/probe-snapshot.md`
|
||||
- Office dependencies (npm packages): `../dev-environment-setup/references/office-deps.md`
|
||||
|
||||
142
skills/nodejs-runtime/SKILL.zh-CN.md
Normal file
142
skills/nodejs-runtime/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,142 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# nodejs-runtime 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
**何时使用**:用户需要 安装 Node.js / 升级 Node / 切换 Node 多版本 / 安装或配置
|
||||
npm / pnpm / yarn / 排查 `node: command not found`、`npm: command not found`、
|
||||
EACCES 全局安装权限错误、node-gyp 编译失败、registry 镜像 / proxy 问题 等
|
||||
Node.js 运行时问题,或其他 skill(pptx 用 pptxgenjs 等)报告 "Node.js 不可用" 时。
|
||||
|
||||
**怎么做**:优先使用 DesireCore 内置 Volta,按四级降级(HTTP API → Volta CLI →
|
||||
系统包管理器 brew/apt/NodeSource/winget → 社区方案 nvm/fnm)执行。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
procedural skill。每次执行 Node.js 环境操作前,先运行 `scripts/probe-node.sh` 取 JSON 快照,再按 `../dev-environment-setup/references/decision-tree.md` 四级降级选择路径。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- "node not found" / "npm not found"
|
||||
- 用户要求安装/升级 Node.js
|
||||
- 多版本切换(基于 `package.json#volta` 或 `.nvmrc`)
|
||||
- 安装/管理 pnpm / yarn / npm
|
||||
- "EACCES: permission denied"(npm 全局安装权限错误)
|
||||
- 配置 registry / proxy
|
||||
- 其他 skill(pptx 等)报告 Node.js 不可用
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **DesireCore 优先**:Volta + HTTP API 作为 L1/L2,避免污染系统 Node
|
||||
- **JSON 决策**:probe 脚本输出结构化数据,Claude 可直接解析
|
||||
- **package.json#volta 兼容**:Volta 自动按项目切换版本
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 第一步:环境探测(必须)
|
||||
|
||||
```bash
|
||||
bash skills/nodejs-runtime/scripts/probe-node.sh > /tmp/node-probe.json
|
||||
cat /tmp/node-probe.json | jq .
|
||||
```
|
||||
|
||||
字段含义见 `../dev-environment-setup/references/probe-snapshot.md`。
|
||||
|
||||
### 第二步:选择执行路径
|
||||
|
||||
| 条件 | 路径 |
|
||||
|------|------|
|
||||
| `desirecore_api` 非空 | **L1** HTTP API |
|
||||
| `desirecore_api` 空,`volta_path` 非空 | **L2** Volta CLI |
|
||||
| 上述都不满足 | **L3** 系统包管理器(brew / apt / NodeSource / winget) |
|
||||
| L1–L3 全部失败或用户明示 | **L4** 社区方案(nvm / fnm) |
|
||||
|
||||
### 第三步:执行(仅展示主路径,详见各 references)
|
||||
|
||||
#### L1:HTTP API(→ `references/volta-desirecore.md`)
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
BASE="https://127.0.0.1:${PORT}/api/runtime"
|
||||
|
||||
# 列出可装版本
|
||||
curl -sk "${BASE}/node/available"
|
||||
|
||||
# 触发安装(异步)
|
||||
curl -sk -X POST "${BASE}/node/install" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"version":"22"}'
|
||||
|
||||
# 安装包管理器
|
||||
curl -sk -X POST "${BASE}/pkg/pnpm/install" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"version":"latest"}'
|
||||
|
||||
# 完成后刷新缓存
|
||||
curl -sk -X POST "${BASE}/environment/refresh"
|
||||
```
|
||||
|
||||
#### L2:Volta CLI 绝对路径(→ `references/volta-desirecore.md`)
|
||||
|
||||
```bash
|
||||
VOLTA=~/.desirecore/runtime/volta/volta
|
||||
export VOLTA_HOME=~/.desirecore/runtime/volta
|
||||
export VOLTA_FEATURE_PNPM=1
|
||||
|
||||
"$VOLTA" install node@22
|
||||
"$VOLTA" install pnpm@latest
|
||||
"$VOLTA" install yarn@latest
|
||||
"$VOLTA" list all
|
||||
|
||||
# 项目级固定(修改 package.json#volta)
|
||||
"$VOLTA" pin node@22 pnpm@9
|
||||
```
|
||||
|
||||
Windows:`%USERPROFILE%\.desirecore\runtime\volta\volta.exe`。
|
||||
|
||||
#### L3:系统包管理器
|
||||
|
||||
| 平台 | 命令 |
|
||||
|------|------|
|
||||
| macOS | `brew install node` |
|
||||
| Debian/Ubuntu | NodeSource:`curl -fsSL https://deb.nodesource.com/setup_22.x \| sudo -E bash - && sudo apt install nodejs` |
|
||||
| Fedora/RHEL | `curl -fsSL https://rpm.nodesource.com/setup_22.x \| sudo bash - && sudo dnf install nodejs` |
|
||||
| Arch | `sudo pacman -S nodejs npm` |
|
||||
| Windows | `winget install OpenJS.NodeJS.LTS` |
|
||||
|
||||
#### L4:nvm / fnm(→ `references/nvm-fallback.md`)
|
||||
|
||||
仅在用户明示或上述失败时启用。
|
||||
|
||||
### 第四步:包管理器策略
|
||||
|
||||
详见 `references/package-managers.md`:
|
||||
- pnpm(推荐,磁盘高效、严格依赖)
|
||||
- yarn(Berry / Classic)
|
||||
- npm(默认,Node.js 自带)
|
||||
- 项目级 `package.json#volta` 自动切换
|
||||
|
||||
### 第五步:故障排查
|
||||
|
||||
详见 `references/troubleshooting.md`:
|
||||
- npm EACCES 权限错误(**不要用 sudo npm**)
|
||||
- registry / proxy 配置
|
||||
- node-gyp 编译失败
|
||||
- "node: command not found" 在 nvm 已装时
|
||||
|
||||
## 重要约束
|
||||
|
||||
1. **绝不 `sudo npm install -g`**:用户级 prefix 或 Volta/nvm。
|
||||
2. **修改环境后必须刷新**:L1 调 `POST /api/runtime/environment/refresh`;其它路径重跑 probe。
|
||||
3. **跨 skill 协作**:`pptx` 等需要 Node.js 时,按本 skill 主路径安装;npm 包速查见 `../dev-environment-setup/references/office-deps.md`。
|
||||
4. **package.json#volta 必须尊重**:检测到该字段时优先 Volta,不要切到 nvm。
|
||||
|
||||
## 引用关系
|
||||
|
||||
- 决策树:`../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore 底座:`../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- 探测协议:`../dev-environment-setup/references/probe-snapshot.md`
|
||||
- 办公依赖(npm 包):`../dev-environment-setup/references/office-deps.md`
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: PDF 文档处理
|
||||
name: pdf
|
||||
description: >-
|
||||
Use this skill whenever the user wants to do anything with PDF files. This
|
||||
includes reading or extracting text/tables from PDFs, combining or merging
|
||||
@@ -22,6 +22,29 @@ tags:
|
||||
metadata:
|
||||
author: anthropic
|
||||
updated_at: '2026-04-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: PDF 文档处理
|
||||
short_desc: 读取、创建、合并、拆分和填写 PDF 文档
|
||||
description: >-
|
||||
Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill. Use when 用户提到 PDF、读取PDF、合并PDF、拆分PDF、填写表单、加水印、提取文字、 扫描识别。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:15805c1921ac2c1e
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: PDF Document Processing
|
||||
short_desc: Read, create, merge, split, and fill PDF documents
|
||||
description: >-
|
||||
Use this skill whenever the user wants to do anything with PDF files. This includes reading or extracting text/tables from PDFs, combining or merging multiple PDFs into one, splitting PDFs apart, rotating pages, adding watermarks, creating new PDFs, filling PDF forms, encrypting/decrypting PDFs, extracting images, and OCR on scanned PDFs to make them searchable. If the user mentions a .pdf file or asks to produce one, use this skill. Use when the user mentions PDF, reading PDFs, merging PDFs, splitting PDFs, filling forms, adding watermarks, extracting text, or OCR.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:15805c1921ac2c1e
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -35,7 +58,6 @@ market:
|
||||
stroke="url(#pd-a)" stroke-width="1.3" stroke-linecap="round"/><path
|
||||
d="M17 11v6l2-1.5 2 1.5v-6z" fill="#FF3B30"
|
||||
fill-opacity="0.8"/></svg>
|
||||
short_desc: 读取、创建、合并、拆分和填写 PDF 文档
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -43,67 +65,67 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# pdf 技能
|
||||
# pdf skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-Sentence Summary
|
||||
|
||||
读取、创建、合并、拆分和填写 PDF 文档,支持 OCR 识别和命令行工具。
|
||||
Read, create, merge, split, and fill PDF documents, with OCR support and command-line tools.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
pdf 是一个**流程型技能(Procedural Skill)**,提供 PDF 文档的完整处理能力。基于 Python 库(pypdf、pdfplumber、reportlab)和命令行工具(qpdf、pdftotext、pdftk),支持文本提取、表格提取、合并拆分、旋转、水印、加密、表单填写和 OCR 识别。
|
||||
pdf is a **Procedural Skill** that provides full PDF document processing capabilities. Built on Python libraries (pypdf, pdfplumber, reportlab) and command-line tools (qpdf, pdftotext, pdftk), it supports text extraction, table extraction, merging/splitting, rotation, watermarking, encryption, form filling, and OCR.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要从 PDF 中提取文本或表格数据
|
||||
- 用户需要合并多个 PDF 或拆分页面
|
||||
- 用户需要创建新的 PDF 文档
|
||||
- 用户需要填写 PDF 表单、添加水印或加密
|
||||
- The user needs to extract text or table data from a PDF
|
||||
- The user needs to merge multiple PDFs or split pages
|
||||
- The user needs to create a new PDF document
|
||||
- The user needs to fill PDF forms, add watermarks, or encrypt PDFs
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
### Python 3 (required)
|
||||
|
||||
在执行任何 Python 操作之前,先检测 Python 是否可用:
|
||||
Before performing any Python operation, check that Python is available:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
If the command fails (Python is not available), **you must stop and tell the user to install Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **macOS**: `brew install python3`, or download from https://www.python.org/downloads/
|
||||
- **Windows**: `winget install Python.Python.3`, or download from python.org (check "Add Python to PATH" during installation)
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(系统工具如 poppler / tesseract、容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
For more detailed environment setup help: load the `python-runtime` skill for Python issues;
|
||||
load the `dev-environment-setup` skill for everything else (system tools like poppler / tesseract, containers / WSL).
|
||||
|
||||
### Python 包依赖
|
||||
### Python Package Dependencies
|
||||
|
||||
本技能依赖以下 Python 包(按需检测):
|
||||
This skill depends on the following Python packages (checked on demand):
|
||||
|
||||
- `pypdf` — PDF 基础操作(读取、合并、拆分、旋转)
|
||||
- `pdfplumber` — 表格提取、带布局的文本提取
|
||||
- `Pillow` — 图片处理(水印、验证图等)
|
||||
- `reportlab` — PDF 创建(可选,按需安装)
|
||||
- `pdf2image` — PDF 转图片(可选,需要 poppler)
|
||||
- `pypdf` — Basic PDF operations (read, merge, split, rotate)
|
||||
- `pdfplumber` — Table extraction, layout-aware text extraction
|
||||
- `Pillow` — Image processing (watermarks, verification images, etc.)
|
||||
- `reportlab` — PDF creation (optional, install on demand)
|
||||
- `pdf2image` — PDF-to-image conversion (optional, requires poppler)
|
||||
|
||||
核心包检测:
|
||||
Core package check:
|
||||
```bash
|
||||
python3 -c "import pypdf; import pdfplumber; import PIL" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install pypdf pdfplumber Pillow`
|
||||
If missing, tell the user to install: `pip install pypdf pdfplumber Pillow`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .pdf file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.pdf`"
|
||||
When you create or modify a .pdf file, you **MUST** tell the user the absolute path of the output file in your response. Example: "File saved to: `/path/to/output.pdf`"
|
||||
|
||||
## Overview
|
||||
|
||||
|
||||
370
skills/pdf/SKILL.zh-CN.md
Normal file
370
skills/pdf/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,370 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# pdf 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
读取、创建、合并、拆分和填写 PDF 文档,支持 OCR 识别和命令行工具。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
pdf 是一个**流程型技能(Procedural Skill)**,提供 PDF 文档的完整处理能力。基于 Python 库(pypdf、pdfplumber、reportlab)和命令行工具(qpdf、pdftotext、pdftk),支持文本提取、表格提取、合并拆分、旋转、水印、加密、表单填写和 OCR 识别。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要从 PDF 中提取文本或表格数据
|
||||
- 用户需要合并多个 PDF 或拆分页面
|
||||
- 用户需要创建新的 PDF 文档
|
||||
- 用户需要填写 PDF 表单、添加水印或加密
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
|
||||
在执行任何 Python 操作之前,先检测 Python 是否可用:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(系统工具如 poppler / tesseract、容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
|
||||
### Python 包依赖
|
||||
|
||||
本技能依赖以下 Python 包(按需检测):
|
||||
|
||||
- `pypdf` — PDF 基础操作(读取、合并、拆分、旋转)
|
||||
- `pdfplumber` — 表格提取、带布局的文本提取
|
||||
- `Pillow` — 图片处理(水印、验证图等)
|
||||
- `reportlab` — PDF 创建(可选,按需安装)
|
||||
- `pdf2image` — PDF 转图片(可选,需要 poppler)
|
||||
|
||||
核心包检测:
|
||||
```bash
|
||||
python3 -c "import pypdf; import pdfplumber; import PIL" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install pypdf pdfplumber Pillow`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .pdf file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.pdf`"
|
||||
|
||||
## Overview
|
||||
|
||||
This guide covers essential PDF processing operations using Python libraries and command-line tools. For advanced features, JavaScript libraries, and detailed examples, see REFERENCE.md. If you need to fill out a PDF form, read FORMS.md and follow its instructions.
|
||||
|
||||
## Quick Start
|
||||
|
||||
```python
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
|
||||
# Read a PDF
|
||||
reader = PdfReader("document.pdf")
|
||||
print(f"Pages: {len(reader.pages)}")
|
||||
|
||||
# Extract text
|
||||
text = ""
|
||||
for page in reader.pages:
|
||||
text += page.extract_text()
|
||||
```
|
||||
|
||||
## Python Libraries
|
||||
|
||||
### pypdf - Basic Operations
|
||||
|
||||
#### Merge PDFs
|
||||
```python
|
||||
from pypdf import PdfWriter, PdfReader
|
||||
|
||||
writer = PdfWriter()
|
||||
for pdf_file in ["doc1.pdf", "doc2.pdf", "doc3.pdf"]:
|
||||
reader = PdfReader(pdf_file)
|
||||
for page in reader.pages:
|
||||
writer.add_page(page)
|
||||
|
||||
with open("merged.pdf", "wb") as output:
|
||||
writer.write(output)
|
||||
```
|
||||
|
||||
#### Split PDF
|
||||
```python
|
||||
reader = PdfReader("input.pdf")
|
||||
for i, page in enumerate(reader.pages):
|
||||
writer = PdfWriter()
|
||||
writer.add_page(page)
|
||||
with open(f"page_{i+1}.pdf", "wb") as output:
|
||||
writer.write(output)
|
||||
```
|
||||
|
||||
#### Extract Metadata
|
||||
```python
|
||||
reader = PdfReader("document.pdf")
|
||||
meta = reader.metadata
|
||||
print(f"Title: {meta.title}")
|
||||
print(f"Author: {meta.author}")
|
||||
print(f"Subject: {meta.subject}")
|
||||
print(f"Creator: {meta.creator}")
|
||||
```
|
||||
|
||||
#### Rotate Pages
|
||||
```python
|
||||
reader = PdfReader("input.pdf")
|
||||
writer = PdfWriter()
|
||||
|
||||
page = reader.pages[0]
|
||||
page.rotate(90) # Rotate 90 degrees clockwise
|
||||
writer.add_page(page)
|
||||
|
||||
with open("rotated.pdf", "wb") as output:
|
||||
writer.write(output)
|
||||
```
|
||||
|
||||
### pdfplumber - Text and Table Extraction
|
||||
|
||||
#### Extract Text with Layout
|
||||
```python
|
||||
import pdfplumber
|
||||
|
||||
with pdfplumber.open("document.pdf") as pdf:
|
||||
for page in pdf.pages:
|
||||
text = page.extract_text()
|
||||
print(text)
|
||||
```
|
||||
|
||||
#### Extract Tables
|
||||
```python
|
||||
with pdfplumber.open("document.pdf") as pdf:
|
||||
for i, page in enumerate(pdf.pages):
|
||||
tables = page.extract_tables()
|
||||
for j, table in enumerate(tables):
|
||||
print(f"Table {j+1} on page {i+1}:")
|
||||
for row in table:
|
||||
print(row)
|
||||
```
|
||||
|
||||
#### Advanced Table Extraction
|
||||
```python
|
||||
import pandas as pd
|
||||
|
||||
with pdfplumber.open("document.pdf") as pdf:
|
||||
all_tables = []
|
||||
for page in pdf.pages:
|
||||
tables = page.extract_tables()
|
||||
for table in tables:
|
||||
if table: # Check if table is not empty
|
||||
df = pd.DataFrame(table[1:], columns=table[0])
|
||||
all_tables.append(df)
|
||||
|
||||
# Combine all tables
|
||||
if all_tables:
|
||||
combined_df = pd.concat(all_tables, ignore_index=True)
|
||||
combined_df.to_excel("extracted_tables.xlsx", index=False)
|
||||
```
|
||||
|
||||
### reportlab - Create PDFs
|
||||
|
||||
#### Basic PDF Creation
|
||||
```python
|
||||
from reportlab.lib.pagesizes import letter
|
||||
from reportlab.pdfgen import canvas
|
||||
|
||||
c = canvas.Canvas("hello.pdf", pagesize=letter)
|
||||
width, height = letter
|
||||
|
||||
# Add text
|
||||
c.drawString(100, height - 100, "Hello World!")
|
||||
c.drawString(100, height - 120, "This is a PDF created with reportlab")
|
||||
|
||||
# Add a line
|
||||
c.line(100, height - 140, 400, height - 140)
|
||||
|
||||
# Save
|
||||
c.save()
|
||||
```
|
||||
|
||||
#### Create PDF with Multiple Pages
|
||||
```python
|
||||
from reportlab.lib.pagesizes import letter
|
||||
from reportlab.platypus import SimpleDocTemplate, Paragraph, Spacer, PageBreak
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
|
||||
doc = SimpleDocTemplate("report.pdf", pagesize=letter)
|
||||
styles = getSampleStyleSheet()
|
||||
story = []
|
||||
|
||||
# Add content
|
||||
title = Paragraph("Report Title", styles['Title'])
|
||||
story.append(title)
|
||||
story.append(Spacer(1, 12))
|
||||
|
||||
body = Paragraph("This is the body of the report. " * 20, styles['Normal'])
|
||||
story.append(body)
|
||||
story.append(PageBreak())
|
||||
|
||||
# Page 2
|
||||
story.append(Paragraph("Page 2", styles['Heading1']))
|
||||
story.append(Paragraph("Content for page 2", styles['Normal']))
|
||||
|
||||
# Build PDF
|
||||
doc.build(story)
|
||||
```
|
||||
|
||||
#### Subscripts and Superscripts
|
||||
|
||||
**IMPORTANT**: Never use Unicode subscript/superscript characters (₀₁₂₃₄₅₆₇₈₉, ⁰¹²³⁴⁵⁶⁷⁸⁹) in ReportLab PDFs. The built-in fonts do not include these glyphs, causing them to render as solid black boxes.
|
||||
|
||||
Instead, use ReportLab's XML markup tags in Paragraph objects:
|
||||
```python
|
||||
from reportlab.platypus import Paragraph
|
||||
from reportlab.lib.styles import getSampleStyleSheet
|
||||
|
||||
styles = getSampleStyleSheet()
|
||||
|
||||
# Subscripts: use <sub> tag
|
||||
chemical = Paragraph("H<sub>2</sub>O", styles['Normal'])
|
||||
|
||||
# Superscripts: use <super> tag
|
||||
squared = Paragraph("x<super>2</super> + y<super>2</super>", styles['Normal'])
|
||||
```
|
||||
|
||||
For canvas-drawn text (not Paragraph objects), manually adjust font the size and position rather than using Unicode subscripts/superscripts.
|
||||
|
||||
## Command-Line Tools
|
||||
|
||||
### pdftotext (poppler-utils)
|
||||
```bash
|
||||
# Extract text
|
||||
pdftotext input.pdf output.txt
|
||||
|
||||
# Extract text preserving layout
|
||||
pdftotext -layout input.pdf output.txt
|
||||
|
||||
# Extract specific pages
|
||||
pdftotext -f 1 -l 5 input.pdf output.txt # Pages 1-5
|
||||
```
|
||||
|
||||
### qpdf
|
||||
```bash
|
||||
# Merge PDFs
|
||||
qpdf --empty --pages file1.pdf file2.pdf -- merged.pdf
|
||||
|
||||
# Split pages
|
||||
qpdf input.pdf --pages . 1-5 -- pages1-5.pdf
|
||||
qpdf input.pdf --pages . 6-10 -- pages6-10.pdf
|
||||
|
||||
# Rotate pages
|
||||
qpdf input.pdf output.pdf --rotate=+90:1 # Rotate page 1 by 90 degrees
|
||||
|
||||
# Remove password
|
||||
qpdf --password=mypassword --decrypt encrypted.pdf decrypted.pdf
|
||||
```
|
||||
|
||||
### pdftk (if available)
|
||||
```bash
|
||||
# Merge
|
||||
pdftk file1.pdf file2.pdf cat output merged.pdf
|
||||
|
||||
# Split
|
||||
pdftk input.pdf burst
|
||||
|
||||
# Rotate
|
||||
pdftk input.pdf rotate 1east output rotated.pdf
|
||||
```
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Extract Text from Scanned PDFs
|
||||
```python
|
||||
# Requires: pip install pytesseract pdf2image
|
||||
import pytesseract
|
||||
from pdf2image import convert_from_path
|
||||
|
||||
# Convert PDF to images
|
||||
images = convert_from_path('scanned.pdf')
|
||||
|
||||
# OCR each page
|
||||
text = ""
|
||||
for i, image in enumerate(images):
|
||||
text += f"Page {i+1}:\n"
|
||||
text += pytesseract.image_to_string(image)
|
||||
text += "\n\n"
|
||||
|
||||
print(text)
|
||||
```
|
||||
|
||||
### Add Watermark
|
||||
```python
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
|
||||
# Create watermark (or load existing)
|
||||
watermark = PdfReader("watermark.pdf").pages[0]
|
||||
|
||||
# Apply to all pages
|
||||
reader = PdfReader("document.pdf")
|
||||
writer = PdfWriter()
|
||||
|
||||
for page in reader.pages:
|
||||
page.merge_page(watermark)
|
||||
writer.add_page(page)
|
||||
|
||||
with open("watermarked.pdf", "wb") as output:
|
||||
writer.write(output)
|
||||
```
|
||||
|
||||
### Extract Images
|
||||
```bash
|
||||
# Using pdfimages (poppler-utils)
|
||||
pdfimages -j input.pdf output_prefix
|
||||
|
||||
# This extracts all images as output_prefix-000.jpg, output_prefix-001.jpg, etc.
|
||||
```
|
||||
|
||||
### Password Protection
|
||||
```python
|
||||
from pypdf import PdfReader, PdfWriter
|
||||
|
||||
reader = PdfReader("input.pdf")
|
||||
writer = PdfWriter()
|
||||
|
||||
for page in reader.pages:
|
||||
writer.add_page(page)
|
||||
|
||||
# Add password
|
||||
writer.encrypt("userpassword", "ownerpassword")
|
||||
|
||||
with open("encrypted.pdf", "wb") as output:
|
||||
writer.write(output)
|
||||
```
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Best Tool | Command/Code |
|
||||
|------|-----------|--------------|
|
||||
| Merge PDFs | pypdf | `writer.add_page(page)` |
|
||||
| Split PDFs | pypdf | One page per file |
|
||||
| Extract text | pdfplumber | `page.extract_text()` |
|
||||
| Extract tables | pdfplumber | `page.extract_tables()` |
|
||||
| Create PDFs | reportlab | Canvas or Platypus |
|
||||
| Command line merge | qpdf | `qpdf --empty --pages ...` |
|
||||
| OCR scanned PDFs | pytesseract | Convert to image first |
|
||||
| Fill PDF forms | pdf-lib or pypdf (see FORMS.md) | See FORMS.md |
|
||||
|
||||
## Next Steps
|
||||
|
||||
- For advanced pypdfium2 usage, see REFERENCE.md
|
||||
- For JavaScript libraries (pdf-lib), see REFERENCE.md
|
||||
- If you need to fill out a PDF form, follow the instructions in FORMS.md
|
||||
- For troubleshooting guides, see REFERENCE.md
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 演示文稿处理
|
||||
name: pptx
|
||||
description: >-
|
||||
Use this skill any time a .pptx file is involved in any way — as input,
|
||||
output, or both. This includes: creating slide decks, pitch decks, or
|
||||
@@ -26,6 +26,29 @@ tags:
|
||||
metadata:
|
||||
author: anthropic
|
||||
updated_at: '2026-05-04'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 演示文稿处理
|
||||
short_desc: 创建、编辑和处理 PowerPoint 演示文稿(.pptx)
|
||||
description: >-
|
||||
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions "deck," "slides," "presentation," or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill. Use when 用户提到 PPT、演示文稿、幻灯片、演讲稿、汇报材料、 pptx、创建演示、编辑幻灯片。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:761da55f1e450adc
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Presentation Processing
|
||||
short_desc: Create, edit, and process PowerPoint presentations (.pptx)
|
||||
description: >-
|
||||
Use this skill any time a .pptx file is involved in any way — as input, output, or both. This includes: creating slide decks, pitch decks, or presentations; reading, parsing, or extracting text from any .pptx file (even if the extracted content will be used elsewhere, like in an email or summary); editing, modifying, or updating existing presentations; combining or splitting slide files; working with templates, layouts, speaker notes, or comments. Trigger whenever the user mentions "deck," "slides," "presentation," or references a .pptx filename, regardless of what they plan to do with the content afterward. If a .pptx file needs to be opened, created, or touched, use this skill. Use when the user mentions PPT, presentation, slides, speaker notes, briefing materials, pptx, creating presentations, or editing slides.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:761da55f1e450adc
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -40,7 +63,6 @@ market:
|
||||
stroke-width="1.2" stroke-linecap="round"/><circle cx="17" cy="10" r="3"
|
||||
fill="#FF9500" fill-opacity="0.15"/><path d="M15.8 8.5v3l2.6-1.5z"
|
||||
fill="#FF9500" fill-opacity="0.85"/></svg>
|
||||
short_desc: 创建、编辑和处理 PowerPoint 演示文稿(.pptx)
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -48,67 +70,66 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# pptx 技能
|
||||
# pptx skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-Sentence Summary
|
||||
|
||||
创建、编辑和处理 PowerPoint 演示文稿(.pptx),支持模板编辑和从零创建。
|
||||
Create, edit, and process PowerPoint presentations (.pptx), with support for template editing and creation from scratch.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
pptx 是一个**流程型技能(Procedural Skill)**,提供 PowerPoint 演示文稿的完整处理能力。支持通过 pptxgenjs(Node.js)从零创建演示文稿,通过解包 XML 编辑现有模板,以及内容提取和视觉质检。
|
||||
pptx is a **Procedural Skill** providing full PowerPoint presentation processing capabilities. It supports creating presentations from scratch via pptxgenjs (Node.js), editing existing templates by unpacking XML, plus content extraction and visual quality checks.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要创建新的演示文稿(汇报材料、Pitch Deck 等)
|
||||
- 用户需要编辑或修改现有 .pptx 文件
|
||||
- 用户需要从 .pptx 文件中提取文本内容
|
||||
- 用户需要将演示文稿转换为 PDF 或图片
|
||||
- The user needs to create a new presentation (briefing materials, pitch deck, etc.)
|
||||
- The user needs to edit or modify an existing .pptx file
|
||||
- The user needs to extract text content from a .pptx file
|
||||
- The user needs to convert a presentation to PDF or images
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需 — 读取和编辑现有 PPTX 时需要)
|
||||
### Python 3 (required — needed when reading and editing existing PPTX)
|
||||
|
||||
在执行任何 Python 脚本之前,先检测 Python 是否可用:
|
||||
Before running any Python script, check that Python is available:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
If the command fails (Python is not available), **you must stop and tell the user to install Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **macOS**: `brew install python3`, or download from https://www.python.org/downloads/
|
||||
- **Windows**: `winget install Python.Python.3`, or download from python.org (check "Add Python to PATH" during installation)
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
注意:从零创建 PPTX 使用 pptxgenjs(Node.js),不需要 Python。
|
||||
Note: Creating PPTX from scratch uses pptxgenjs (Node.js), and does not require Python.
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
Node.js(pptxgenjs)相关问题加载 `nodejs-runtime` 技能;其他(系统工具 /
|
||||
容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
For more detailed environment setup help: load the `python-runtime` skill for Python issues;
|
||||
load the `nodejs-runtime` skill for Node.js (pptxgenjs) issues; load the `dev-environment-setup` skill for everything else (system tools / containers / WSL).
|
||||
|
||||
### Python 包依赖
|
||||
### Python Package Dependencies
|
||||
|
||||
本技能的 Python 操作依赖以下包(按需检测):
|
||||
This skill's Python operations depend on the following packages (checked on demand):
|
||||
|
||||
- `markitdown[pptx]` — PPTX 内容读取
|
||||
- `Pillow` — 缩略图生成
|
||||
- `markitdown[pptx]` — PPTX content reading
|
||||
- `Pillow` — Thumbnail generation
|
||||
|
||||
检测方法:
|
||||
Detection method:
|
||||
```bash
|
||||
python3 -c "import markitdown; import PIL" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install "markitdown[pptx]" Pillow`
|
||||
If missing, tell the user to install: `pip install "markitdown[pptx]" Pillow`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .pptx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.pptx`"
|
||||
When you create or modify a .pptx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "File saved to: `/path/to/output.pptx`"
|
||||
|
||||
## Quick Reference
|
||||
|
||||
|
||||
288
skills/pptx/SKILL.zh-CN.md
Normal file
288
skills/pptx/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,288 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# pptx 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
创建、编辑和处理 PowerPoint 演示文稿(.pptx),支持模板编辑和从零创建。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
pptx 是一个**流程型技能(Procedural Skill)**,提供 PowerPoint 演示文稿的完整处理能力。支持通过 pptxgenjs(Node.js)从零创建演示文稿,通过解包 XML 编辑现有模板,以及内容提取和视觉质检。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要创建新的演示文稿(汇报材料、Pitch Deck 等)
|
||||
- 用户需要编辑或修改现有 .pptx 文件
|
||||
- 用户需要从 .pptx 文件中提取文本内容
|
||||
- 用户需要将演示文稿转换为 PDF 或图片
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需 — 读取和编辑现有 PPTX 时需要)
|
||||
|
||||
在执行任何 Python 脚本之前,先检测 Python 是否可用:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
注意:从零创建 PPTX 使用 pptxgenjs(Node.js),不需要 Python。
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
Node.js(pptxgenjs)相关问题加载 `nodejs-runtime` 技能;其他(系统工具 /
|
||||
容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
|
||||
### Python 包依赖
|
||||
|
||||
本技能的 Python 操作依赖以下包(按需检测):
|
||||
|
||||
- `markitdown[pptx]` — PPTX 内容读取
|
||||
- `Pillow` — 缩略图生成
|
||||
|
||||
检测方法:
|
||||
```bash
|
||||
python3 -c "import markitdown; import PIL" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install "markitdown[pptx]" Pillow`
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .pptx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.pptx`"
|
||||
|
||||
## Quick Reference
|
||||
|
||||
| Task | Guide |
|
||||
|------|-------|
|
||||
| Read/analyze content | `python -m markitdown presentation.pptx` |
|
||||
| Edit or create from template | Read [editing.md](editing.md) |
|
||||
| Create from scratch | Read [pptxgenjs.md](pptxgenjs.md) |
|
||||
|
||||
---
|
||||
|
||||
## Reading Content
|
||||
|
||||
```bash
|
||||
# Text extraction
|
||||
python -m markitdown presentation.pptx
|
||||
|
||||
# Visual overview
|
||||
python scripts/thumbnail.py presentation.pptx
|
||||
|
||||
# Raw XML
|
||||
python scripts/office/unpack.py presentation.pptx unpacked/
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Editing Workflow
|
||||
|
||||
**Read [editing.md](editing.md) for full details.**
|
||||
|
||||
1. Analyze template with `thumbnail.py`
|
||||
2. Unpack → manipulate slides → edit content → clean → pack
|
||||
|
||||
---
|
||||
|
||||
## Creating from Scratch
|
||||
|
||||
**Read [pptxgenjs.md](pptxgenjs.md) for full details.**
|
||||
|
||||
Use when no template or reference presentation is available.
|
||||
|
||||
---
|
||||
|
||||
## Design Ideas
|
||||
|
||||
**Don't create boring slides.** Plain bullets on a white background won't impress anyone. Consider ideas from this list for each slide.
|
||||
|
||||
### Before Starting
|
||||
|
||||
- **Pick a bold, content-informed color palette**: The palette should feel designed for THIS topic. If swapping your colors into a completely different presentation would still "work," you haven't made specific enough choices.
|
||||
- **Dominance over equality**: One color should dominate (60-70% visual weight), with 1-2 supporting tones and one sharp accent. Never give all colors equal weight.
|
||||
- **Dark/light contrast**: Dark backgrounds for title + conclusion slides, light for content ("sandwich" structure). Or commit to dark throughout for a premium feel.
|
||||
- **Commit to a visual motif**: Pick ONE distinctive element and repeat it — rounded image frames, icons in colored circles, thick single-side borders. Carry it across every slide.
|
||||
|
||||
### Color Palettes
|
||||
|
||||
Choose colors that match your topic — don't default to generic blue. Use these palettes as inspiration:
|
||||
|
||||
| Theme | Primary | Secondary | Accent |
|
||||
|-------|---------|-----------|--------|
|
||||
| **Midnight Executive** | `1E2761` (navy) | `CADCFC` (ice blue) | `FFFFFF` (white) |
|
||||
| **Forest & Moss** | `2C5F2D` (forest) | `97BC62` (moss) | `F5F5F5` (cream) |
|
||||
| **Coral Energy** | `F96167` (coral) | `F9E795` (gold) | `2F3C7E` (navy) |
|
||||
| **Warm Terracotta** | `B85042` (terracotta) | `E7E8D1` (sand) | `A7BEAE` (sage) |
|
||||
| **Ocean Gradient** | `065A82` (deep blue) | `1C7293` (teal) | `21295C` (midnight) |
|
||||
| **Charcoal Minimal** | `36454F` (charcoal) | `F2F2F2` (off-white) | `212121` (black) |
|
||||
| **Teal Trust** | `028090` (teal) | `00A896` (seafoam) | `02C39A` (mint) |
|
||||
| **Berry & Cream** | `6D2E46` (berry) | `A26769` (dusty rose) | `ECE2D0` (cream) |
|
||||
| **Sage Calm** | `84B59F` (sage) | `69A297` (eucalyptus) | `50808E` (slate) |
|
||||
| **Cherry Bold** | `990011` (cherry) | `FCF6F5` (off-white) | `2F3C7E` (navy) |
|
||||
|
||||
### For Each Slide
|
||||
|
||||
**Every slide needs a visual element** — image, chart, icon, or shape. Text-only slides are forgettable.
|
||||
|
||||
**Layout options:**
|
||||
- Two-column (text left, illustration on right)
|
||||
- Icon + text rows (icon in colored circle, bold header, description below)
|
||||
- 2x2 or 2x3 grid (image on one side, grid of content blocks on other)
|
||||
- Half-bleed image (full left or right side) with content overlay
|
||||
|
||||
**Data display:**
|
||||
- Large stat callouts (big numbers 60-72pt with small labels below)
|
||||
- Comparison columns (before/after, pros/cons, side-by-side options)
|
||||
- Timeline or process flow (numbered steps, arrows)
|
||||
|
||||
**Visual polish:**
|
||||
- Icons in small colored circles next to section headers
|
||||
- Italic accent text for key stats or taglines
|
||||
|
||||
### Typography
|
||||
|
||||
**Choose an interesting font pairing** — don't default to Arial. Pick a header font with personality and pair it with a clean body font.
|
||||
|
||||
| Header Font | Body Font |
|
||||
|-------------|-----------|
|
||||
| Georgia | Calibri |
|
||||
| Arial Black | Arial |
|
||||
| Calibri | Calibri Light |
|
||||
| Cambria | Calibri |
|
||||
| Trebuchet MS | Calibri |
|
||||
| Impact | Arial |
|
||||
| Palatino | Garamond |
|
||||
| Consolas | Calibri |
|
||||
|
||||
| Element | Size |
|
||||
|---------|------|
|
||||
| Slide title | 36-44pt bold |
|
||||
| Section header | 20-24pt bold |
|
||||
| Body text | 14-16pt |
|
||||
| Captions | 10-12pt muted |
|
||||
|
||||
### Spacing
|
||||
|
||||
- 0.5" minimum margins
|
||||
- 0.3-0.5" between content blocks
|
||||
- Leave breathing room—don't fill every inch
|
||||
|
||||
### Avoid (Common Mistakes)
|
||||
|
||||
- **Don't repeat the same layout** — vary columns, cards, and callouts across slides
|
||||
- **Don't center body text** — left-align paragraphs and lists; center only titles
|
||||
- **Don't skimp on size contrast** — titles need 36pt+ to stand out from 14-16pt body
|
||||
- **Don't default to blue** — pick colors that reflect the specific topic
|
||||
- **Don't mix spacing randomly** — choose 0.3" or 0.5" gaps and use consistently
|
||||
- **Don't style one slide and leave the rest plain** — commit fully or keep it simple throughout
|
||||
- **Don't create text-only slides** — add images, icons, charts, or visual elements; avoid plain title + bullets
|
||||
- **Don't forget text box padding** — when aligning lines or shapes with text edges, set `margin: 0` on the text box or offset the shape to account for padding
|
||||
- **Don't use low-contrast elements** — icons AND text need strong contrast against the background; avoid light text on light backgrounds or dark text on dark backgrounds
|
||||
- **NEVER use accent lines under titles** — these are a hallmark of AI-generated slides; use whitespace or background color instead
|
||||
|
||||
---
|
||||
|
||||
## QA (Required)
|
||||
|
||||
**Assume there are problems. Your job is to find them.**
|
||||
|
||||
Your first render is almost never correct. Approach QA as a bug hunt, not a confirmation step. If you found zero issues on first inspection, you weren't looking hard enough.
|
||||
|
||||
### Content QA
|
||||
|
||||
```bash
|
||||
python -m markitdown output.pptx
|
||||
```
|
||||
|
||||
Check for missing content, typos, wrong order.
|
||||
|
||||
**When using templates, check for leftover placeholder text:**
|
||||
|
||||
```bash
|
||||
python -m markitdown output.pptx | grep -iE "xxxx|lorem|ipsum|this.*(page|slide).*layout"
|
||||
```
|
||||
|
||||
If grep returns results, fix them before declaring success.
|
||||
|
||||
### Visual QA
|
||||
|
||||
**⚠️ USE DELEGATE TOOL** — even for 2-3 slides. You've been staring at the code and will see what you expect, not what's there. Delegated agents have fresh eyes.
|
||||
|
||||
Convert slides to images (see [Converting to Images](#converting-to-images)), then use this prompt:
|
||||
|
||||
```
|
||||
Visually inspect these slides. Assume there are issues — find them.
|
||||
|
||||
Look for:
|
||||
- Overlapping elements (text through shapes, lines through words, stacked elements)
|
||||
- Text overflow or cut off at edges/box boundaries
|
||||
- Decorative lines positioned for single-line text but title wrapped to two lines
|
||||
- Source citations or footers colliding with content above
|
||||
- Elements too close (< 0.3" gaps) or cards/sections nearly touching
|
||||
- Uneven gaps (large empty area in one place, cramped in another)
|
||||
- Insufficient margin from slide edges (< 0.5")
|
||||
- Columns or similar elements not aligned consistently
|
||||
- Low-contrast text (e.g., light gray text on cream-colored background)
|
||||
- Low-contrast icons (e.g., dark icons on dark backgrounds without a contrasting circle)
|
||||
- Text boxes too narrow causing excessive wrapping
|
||||
- Leftover placeholder content
|
||||
|
||||
For each slide, list issues or areas of concern, even if minor.
|
||||
|
||||
Read and analyze these images:
|
||||
1. /path/to/slide-01.jpg (Expected: [brief description])
|
||||
2. /path/to/slide-02.jpg (Expected: [brief description])
|
||||
|
||||
Report ALL issues found, including minor ones.
|
||||
```
|
||||
|
||||
### Verification Loop
|
||||
|
||||
1. Generate slides → Convert to images → Inspect
|
||||
2. **List issues found** (if none found, look again more critically)
|
||||
3. Fix issues
|
||||
4. **Re-verify affected slides** — one fix often creates another problem
|
||||
5. Repeat until a full pass reveals no new issues
|
||||
|
||||
**Do not declare success until you've completed at least one fix-and-verify cycle.**
|
||||
|
||||
---
|
||||
|
||||
## Converting to Images
|
||||
|
||||
Convert presentations to individual slide images for visual inspection:
|
||||
|
||||
```bash
|
||||
python scripts/office/soffice.py --headless --convert-to pdf output.pptx
|
||||
pdftoppm -jpeg -r 150 output.pdf slide
|
||||
```
|
||||
|
||||
This creates `slide-01.jpg`, `slide-02.jpg`, etc.
|
||||
|
||||
To re-render specific slides after fixes:
|
||||
|
||||
```bash
|
||||
pdftoppm -jpeg -r 150 -f N -l N output.pdf slide-fixed
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Dependencies
|
||||
|
||||
- `pip install "markitdown[pptx]"` - text extraction
|
||||
- `pip install Pillow` - thumbnail grids
|
||||
- `npm install -g pptxgenjs` - creating from scratch
|
||||
- LibreOffice (`soffice`) - PDF conversion (auto-configured for sandboxed environments via `scripts/office/soffice.py`)
|
||||
- Poppler (`pdftoppm`) - PDF to images
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: Python 运行时管理
|
||||
name: python-runtime
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot
|
||||
Python and pip environments. Covers four-tier fallback strategy: (1)
|
||||
@@ -31,6 +31,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-02'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: Python 运行时管理
|
||||
short_desc: Python 安装、多版本与虚拟环境(DesireCore Hatch 优先)
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot Python and pip environments. Covers four-tier fallback strategy: (1) DesireCore HTTP API for in-app installation, (2) DesireCore built-in Hatch CLI for Python version management, (3) system package managers (brew/apt/dnf/winget), (4) community pyenv as last resort. Also covers virtual environments (venv/pipx/conda), PEP 668 externally-managed errors, and import / PATH troubleshooting. Triggers include: "install python", "pip not found", "python not found", "PEP 668", "externally-managed", "venv", "virtualenv", "pipx", "conda", "miniconda", "pyenv", "hatch", "python version", "pip command not found", or any Python-related runtime error. 使用场景:用户需要 安装 Python、安装 pip、配置虚拟环境、管理多版本、 解决 PEP 668、import 失败、PATH 问题、SSL 证书错误等。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:ea796e0282dc77af
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Python Runtime Management
|
||||
short_desc: Python install, multi-version, and virtual envs (DesireCore Hatch first)
|
||||
description: >-
|
||||
Use this skill when the user needs to install, upgrade, or troubleshoot Python and pip environments. Covers four-tier fallback strategy: (1) DesireCore HTTP API for in-app installation, (2) DesireCore built-in Hatch CLI for Python version management, (3) system package managers (brew/apt/dnf/winget), (4) community pyenv as last resort. Also covers virtual environments (venv/pipx/conda), PEP 668 externally-managed errors, and import / PATH troubleshooting. Triggers include: "install python", "pip not found", "python not found", "PEP 668", "externally-managed", "venv", "virtualenv", "pipx", "conda", "miniconda", "pyenv", "hatch", "python version", "pip command not found", or any Python-related runtime error. Use when the user needs to install Python, install pip, configure virtual environments, manage multiple versions, resolve PEP 668, import failures, PATH issues, SSL certificate errors, etc.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:ea796e0282dc77af
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -46,7 +69,6 @@ market:
|
||||
8v-.5" stroke="url(#py-a)" stroke-width="1.4" stroke-linecap="round"
|
||||
fill="none"/><circle cx="10.5" cy="10" r="0.6" fill="url(#py-a)"/><circle
|
||||
cx="13.5" cy="14" r="0.6" fill="url(#py-a)"/></svg>
|
||||
short_desc: Python 安装、多版本与虚拟环境(DesireCore Hatch 优先)
|
||||
category: development
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -54,101 +76,103 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# python-runtime 技能
|
||||
# python-runtime Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
**何时使用**:用户需要 安装 Python / 升级 Python / 切换 Python 多版本 / 配置
|
||||
pip / 创建虚拟环境(venv / pipx / conda)/ 排查 `python: command not found`、
|
||||
`pip: command not found`、PEP 668 "externally-managed"、SSL 证书、import 失败、
|
||||
PATH 异常 等 Python 运行时问题,或其他 skill(docx / pdf / xlsx / pptx)报告
|
||||
"Python 不可用" 时。
|
||||
**When to use**: The user needs to install Python / upgrade Python / switch
|
||||
between multiple Python versions / configure pip / create virtual environments
|
||||
(venv / pipx / conda) / troubleshoot `python: command not found`,
|
||||
`pip: command not found`, PEP 668 "externally-managed", SSL certificates,
|
||||
import failures, PATH anomalies, and other Python runtime issues; or when
|
||||
another skill (docx / pdf / xlsx / pptx) reports "Python unavailable".
|
||||
|
||||
**怎么做**:优先使用 DesireCore 内置 Hatch,按四级降级(HTTP API → Hatch CLI →
|
||||
系统包管理器 brew/apt/dnf/winget → 社区方案 pyenv)执行。
|
||||
**How to do it**: Prefer DesireCore's built-in Hatch, executing through the
|
||||
four-tier fallback (HTTP API → Hatch CLI → system package manager
|
||||
brew/apt/dnf/winget → community solution pyenv).
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
procedural skill。每次执行 Python 环境操作前,先运行 `scripts/probe-python.sh` 取 JSON 快照,再按 `references/decision-tree`(→ `../dev-environment-setup/references/decision-tree.md`)四级降级选择路径。
|
||||
Procedural skill. Before each Python environment operation, first run `scripts/probe-python.sh` to obtain a JSON snapshot, then follow `references/decision-tree` (→ `../dev-environment-setup/references/decision-tree.md`) to choose a path through the four-tier fallback.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- "python not found" / "pip not found"
|
||||
- 用户要求安装/升级 Python
|
||||
- 用户要求多版本管理(3.10/3.11/3.12 切换)
|
||||
- 创建/激活/调试虚拟环境(venv/pipx/conda)
|
||||
- "externally-managed-environment"(PEP 668)报错
|
||||
- import 失败、PATH 问题、SSL 证书错误
|
||||
- 其他 skill(docx/pdf/xlsx/pptx)报告 Python 不可用
|
||||
- The user requests to install/upgrade Python
|
||||
- The user requests multi-version management (3.10/3.11/3.12 switching)
|
||||
- Create/activate/debug virtual environments (venv/pipx/conda)
|
||||
- "externally-managed-environment" (PEP 668) error
|
||||
- import failures, PATH issues, SSL certificate errors
|
||||
- Other skills (docx/pdf/xlsx/pptx) report Python unavailable
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **DesireCore 优先**:Hatch + HTTP API 作为强制 L1/L2,避免污染系统 Python
|
||||
- **JSON 决策**:probe 脚本输出结构化数据,Claude 可直接解析
|
||||
- **跨平台一致**:macOS / Linux / Windows 统一 4 级降级
|
||||
- **DesireCore first**: Hatch + HTTP API as mandatory L1/L2, avoiding pollution of system Python
|
||||
- **JSON-driven decisions**: the probe script outputs structured data that Claude can parse directly
|
||||
- **Cross-platform consistency**: macOS / Linux / Windows share a unified 4-tier fallback
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 第一步:环境探测(必须)
|
||||
### Step 1: Environment Probe (mandatory)
|
||||
|
||||
```bash
|
||||
bash skills/python-runtime/scripts/probe-python.sh > /tmp/py-probe.json
|
||||
cat /tmp/py-probe.json | jq .
|
||||
```
|
||||
|
||||
输出字段含义见 `../dev-environment-setup/references/probe-snapshot.md`。
|
||||
For the meaning of output fields, see `../dev-environment-setup/references/probe-snapshot.md`.
|
||||
|
||||
### 第二步:选择执行路径
|
||||
### Step 2: Choose an Execution Path
|
||||
|
||||
按 `../dev-environment-setup/references/decision-tree.md` 判断:
|
||||
Decide using `../dev-environment-setup/references/decision-tree.md`:
|
||||
|
||||
| 条件 | 路径 |
|
||||
| Condition | Path |
|
||||
|------|------|
|
||||
| `desirecore_api` 非空 | **L1** HTTP API |
|
||||
| `desirecore_api` 空,`hatch_path` 非空 | **L2** Hatch CLI |
|
||||
| 上述都不满足 | **L3** 系统包管理器(brew/apt/dnf/winget) |
|
||||
| L1–L3 全部失败或用户明示 | **L4** 社区方案(pyenv) |
|
||||
| `desirecore_api` is non-empty | **L1** HTTP API |
|
||||
| `desirecore_api` empty, `hatch_path` non-empty | **L2** Hatch CLI |
|
||||
| Neither of the above | **L3** system package manager (brew/apt/dnf/winget) |
|
||||
| L1–L3 all fail or user explicitly requests | **L4** community solution (pyenv) |
|
||||
|
||||
### 第三步:执行(仅展示主路径,详见各 references)
|
||||
### Step 3: Execute (only the main path is shown; see references for details)
|
||||
|
||||
#### L1:HTTP API(→ `references/hatch-desirecore.md`)
|
||||
#### L1: HTTP API (→ `references/hatch-desirecore.md`)
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
BASE="https://127.0.0.1:${PORT}/api/runtime"
|
||||
|
||||
# 列出可装版本
|
||||
# List installable versions
|
||||
curl -sk "${BASE}/python/available"
|
||||
|
||||
# 触发安装(异步,订阅 runtime:terminal 看进度)
|
||||
# Trigger install (asynchronous; subscribe to runtime:terminal for progress)
|
||||
curl -sk -X POST "${BASE}/python/install" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"version":"3.12"}'
|
||||
|
||||
# 安装完成后强制刷新缓存
|
||||
# Force-refresh the cache after install completes
|
||||
curl -sk -X POST "${BASE}/environment/refresh"
|
||||
```
|
||||
|
||||
#### L2:Hatch CLI 绝对路径(→ `references/hatch-desirecore.md`)
|
||||
#### L2: Hatch CLI absolute path (→ `references/hatch-desirecore.md`)
|
||||
|
||||
```bash
|
||||
HATCH=~/.desirecore/runtime/hatch/hatch
|
||||
export HATCH_HOME=~/.desirecore/runtime/hatch
|
||||
|
||||
"$HATCH" python install 3.12
|
||||
"$HATCH" python show # 列出已安装/可装版本
|
||||
"$HATCH" python show # List installed/installable versions
|
||||
|
||||
# 直接使用 Hatch 安装的 Python
|
||||
# Use the Hatch-installed Python directly
|
||||
~/.desirecore/runtime/hatch/local/3.12/python/bin/python3 -m venv .venv
|
||||
```
|
||||
|
||||
Windows:`%USERPROFILE%\.desirecore\runtime\hatch\hatch.exe`。
|
||||
Windows: `%USERPROFILE%\.desirecore\runtime\hatch\hatch.exe`.
|
||||
|
||||
#### L3:系统包管理器
|
||||
#### L3: System Package Manager
|
||||
|
||||
| 平台 | 命令 |
|
||||
| Platform | Command |
|
||||
|------|------|
|
||||
| macOS | `brew install python3` |
|
||||
| Debian/Ubuntu | `sudo apt install python3 python3-pip python3-venv` |
|
||||
@@ -156,39 +180,39 @@ Windows:`%USERPROFILE%\.desirecore\runtime\hatch\hatch.exe`。
|
||||
| Arch | `sudo pacman -S python python-pip` |
|
||||
| Windows | `winget install Python.Python.3` |
|
||||
|
||||
#### L4:pyenv(→ `references/pyenv-fallback.md`)
|
||||
#### L4: pyenv (→ `references/pyenv-fallback.md`)
|
||||
|
||||
仅在用户明示或上述失败时启用。
|
||||
Only enable when the user explicitly requests it or the above paths fail.
|
||||
|
||||
### 第四步:虚拟环境
|
||||
### Step 4: Virtual Environments
|
||||
|
||||
虚拟环境策略详见 `references/virtualenv.md`:
|
||||
- venv(推荐,标准库)
|
||||
- pipx(全局 CLI 工具如 black/ruff/markitdown)
|
||||
- conda / miniconda(数据科学场景)
|
||||
For virtual environment strategy, see `references/virtualenv.md`:
|
||||
- venv (recommended, standard library)
|
||||
- pipx (global CLI tools such as black/ruff/markitdown)
|
||||
- conda / miniconda (data-science scenarios)
|
||||
|
||||
### 第五步:故障排查
|
||||
### Step 5: Troubleshooting
|
||||
|
||||
报错时按 `references/troubleshooting.md` 查表:
|
||||
When errors occur, look up `references/troubleshooting.md`:
|
||||
- "python: command not found" / "pip: command not found"
|
||||
- PEP 668 "externally-managed-environment"
|
||||
- SSL/TLS 证书错误
|
||||
- import 失败(包名 vs import 名差异)
|
||||
- macOS xcrun / Xcode CLI 缺失
|
||||
- Windows PowerShell 执行策略阻止脚本
|
||||
- 代理环境配置
|
||||
- SSL/TLS certificate errors
|
||||
- import failures (package name vs. import name differences)
|
||||
- macOS xcrun / Xcode CLI missing
|
||||
- Windows PowerShell execution policy blocking scripts
|
||||
- Proxy environment configuration
|
||||
|
||||
## 重要约束
|
||||
## Important Constraints
|
||||
|
||||
1. **绝不 `sudo pip install`**:始终用虚拟环境或 `pipx`。
|
||||
2. **修改了环境后必须刷新**:L1 调 `POST /api/runtime/environment/refresh`;L2/L3/L4 重新跑 probe。
|
||||
3. **跨 skill 协作**:`docx` / `pdf` / `xlsx` / `pptx` 报"Python 不可用"时,进入 L1/L2 安装;办公依赖速查见 `../dev-environment-setup/references/office-deps.md`。
|
||||
4. **不污染系统 Python**:项目级别一律使用 venv,全局 CLI 用 pipx。
|
||||
1. **Never `sudo pip install`**: always use a virtual environment or `pipx`.
|
||||
2. **Refresh after modifying the environment**: for L1 call `POST /api/runtime/environment/refresh`; for L2/L3/L4 re-run probe.
|
||||
3. **Cross-skill collaboration**: when `docx` / `pdf` / `xlsx` / `pptx` report "Python unavailable", fall into L1/L2 install; for office dependency lookup see `../dev-environment-setup/references/office-deps.md`.
|
||||
4. **Do not pollute system Python**: at the project level always use venv; for global CLI use pipx.
|
||||
|
||||
## 引用关系
|
||||
## References
|
||||
|
||||
- 决策树:`../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore 底座:`../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- 探测协议:`../dev-environment-setup/references/probe-snapshot.md`
|
||||
- 办公依赖:`../dev-environment-setup/references/office-deps.md`
|
||||
- 系统工具:`../dev-environment-setup/references/system-tools.md`
|
||||
- Decision tree: `../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore base: `../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- Probe protocol: `../dev-environment-setup/references/probe-snapshot.md`
|
||||
- Office dependencies: `../dev-environment-setup/references/office-deps.md`
|
||||
- System tools: `../dev-environment-setup/references/system-tools.md`
|
||||
|
||||
140
skills/python-runtime/SKILL.zh-CN.md
Normal file
140
skills/python-runtime/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,140 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# python-runtime 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
**何时使用**:用户需要 安装 Python / 升级 Python / 切换 Python 多版本 / 配置
|
||||
pip / 创建虚拟环境(venv / pipx / conda)/ 排查 `python: command not found`、
|
||||
`pip: command not found`、PEP 668 "externally-managed"、SSL 证书、import 失败、
|
||||
PATH 异常 等 Python 运行时问题,或其他 skill(docx / pdf / xlsx / pptx)报告
|
||||
"Python 不可用" 时。
|
||||
|
||||
**怎么做**:优先使用 DesireCore 内置 Hatch,按四级降级(HTTP API → Hatch CLI →
|
||||
系统包管理器 brew/apt/dnf/winget → 社区方案 pyenv)执行。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
procedural skill。每次执行 Python 环境操作前,先运行 `scripts/probe-python.sh` 取 JSON 快照,再按 `references/decision-tree`(→ `../dev-environment-setup/references/decision-tree.md`)四级降级选择路径。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- "python not found" / "pip not found"
|
||||
- 用户要求安装/升级 Python
|
||||
- 用户要求多版本管理(3.10/3.11/3.12 切换)
|
||||
- 创建/激活/调试虚拟环境(venv/pipx/conda)
|
||||
- "externally-managed-environment"(PEP 668)报错
|
||||
- import 失败、PATH 问题、SSL 证书错误
|
||||
- 其他 skill(docx/pdf/xlsx/pptx)报告 Python 不可用
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **DesireCore 优先**:Hatch + HTTP API 作为强制 L1/L2,避免污染系统 Python
|
||||
- **JSON 决策**:probe 脚本输出结构化数据,Claude 可直接解析
|
||||
- **跨平台一致**:macOS / Linux / Windows 统一 4 级降级
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 第一步:环境探测(必须)
|
||||
|
||||
```bash
|
||||
bash skills/python-runtime/scripts/probe-python.sh > /tmp/py-probe.json
|
||||
cat /tmp/py-probe.json | jq .
|
||||
```
|
||||
|
||||
输出字段含义见 `../dev-environment-setup/references/probe-snapshot.md`。
|
||||
|
||||
### 第二步:选择执行路径
|
||||
|
||||
按 `../dev-environment-setup/references/decision-tree.md` 判断:
|
||||
|
||||
| 条件 | 路径 |
|
||||
|------|------|
|
||||
| `desirecore_api` 非空 | **L1** HTTP API |
|
||||
| `desirecore_api` 空,`hatch_path` 非空 | **L2** Hatch CLI |
|
||||
| 上述都不满足 | **L3** 系统包管理器(brew/apt/dnf/winget) |
|
||||
| L1–L3 全部失败或用户明示 | **L4** 社区方案(pyenv) |
|
||||
|
||||
### 第三步:执行(仅展示主路径,详见各 references)
|
||||
|
||||
#### L1:HTTP API(→ `references/hatch-desirecore.md`)
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
BASE="https://127.0.0.1:${PORT}/api/runtime"
|
||||
|
||||
# 列出可装版本
|
||||
curl -sk "${BASE}/python/available"
|
||||
|
||||
# 触发安装(异步,订阅 runtime:terminal 看进度)
|
||||
curl -sk -X POST "${BASE}/python/install" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{"version":"3.12"}'
|
||||
|
||||
# 安装完成后强制刷新缓存
|
||||
curl -sk -X POST "${BASE}/environment/refresh"
|
||||
```
|
||||
|
||||
#### L2:Hatch CLI 绝对路径(→ `references/hatch-desirecore.md`)
|
||||
|
||||
```bash
|
||||
HATCH=~/.desirecore/runtime/hatch/hatch
|
||||
export HATCH_HOME=~/.desirecore/runtime/hatch
|
||||
|
||||
"$HATCH" python install 3.12
|
||||
"$HATCH" python show # 列出已安装/可装版本
|
||||
|
||||
# 直接使用 Hatch 安装的 Python
|
||||
~/.desirecore/runtime/hatch/local/3.12/python/bin/python3 -m venv .venv
|
||||
```
|
||||
|
||||
Windows:`%USERPROFILE%\.desirecore\runtime\hatch\hatch.exe`。
|
||||
|
||||
#### L3:系统包管理器
|
||||
|
||||
| 平台 | 命令 |
|
||||
|------|------|
|
||||
| macOS | `brew install python3` |
|
||||
| Debian/Ubuntu | `sudo apt install python3 python3-pip python3-venv` |
|
||||
| Fedora/RHEL | `sudo dnf install python3 python3-pip` |
|
||||
| Arch | `sudo pacman -S python python-pip` |
|
||||
| Windows | `winget install Python.Python.3` |
|
||||
|
||||
#### L4:pyenv(→ `references/pyenv-fallback.md`)
|
||||
|
||||
仅在用户明示或上述失败时启用。
|
||||
|
||||
### 第四步:虚拟环境
|
||||
|
||||
虚拟环境策略详见 `references/virtualenv.md`:
|
||||
- venv(推荐,标准库)
|
||||
- pipx(全局 CLI 工具如 black/ruff/markitdown)
|
||||
- conda / miniconda(数据科学场景)
|
||||
|
||||
### 第五步:故障排查
|
||||
|
||||
报错时按 `references/troubleshooting.md` 查表:
|
||||
- "python: command not found" / "pip: command not found"
|
||||
- PEP 668 "externally-managed-environment"
|
||||
- SSL/TLS 证书错误
|
||||
- import 失败(包名 vs import 名差异)
|
||||
- macOS xcrun / Xcode CLI 缺失
|
||||
- Windows PowerShell 执行策略阻止脚本
|
||||
- 代理环境配置
|
||||
|
||||
## 重要约束
|
||||
|
||||
1. **绝不 `sudo pip install`**:始终用虚拟环境或 `pipx`。
|
||||
2. **修改了环境后必须刷新**:L1 调 `POST /api/runtime/environment/refresh`;L2/L3/L4 重新跑 probe。
|
||||
3. **跨 skill 协作**:`docx` / `pdf` / `xlsx` / `pptx` 报"Python 不可用"时,进入 L1/L2 安装;办公依赖速查见 `../dev-environment-setup/references/office-deps.md`。
|
||||
4. **不污染系统 Python**:项目级别一律使用 venv,全局 CLI 用 pipx。
|
||||
|
||||
## 引用关系
|
||||
|
||||
- 决策树:`../dev-environment-setup/references/decision-tree.md`
|
||||
- DesireCore 底座:`../dev-environment-setup/references/desirecore-runtime.md`
|
||||
- 探测协议:`../dev-environment-setup/references/probe-snapshot.md`
|
||||
- 办公依赖:`../dev-environment-setup/references/office-deps.md`
|
||||
- 系统工具:`../dev-environment-setup/references/system-tools.md`
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 对象存储操作
|
||||
name: s3-storage-operations
|
||||
description: 操作 S3 兼容对象存储(上传、下载、列举、删除),通过 DesireCore HTTP API 调用。Use when 用户要求上传/下载/分享文件、需要生成下载链接、或工作流产出文件需要持久化存储与分发。
|
||||
version: 2.0.2
|
||||
type: procedural
|
||||
@@ -16,6 +16,29 @@ metadata:
|
||||
author: desirecore
|
||||
version: '2.0.1'
|
||||
updated_at: '2026-03-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 对象存储操作
|
||||
short_desc: 通过 DesireCore HTTP API 操作 S3 兼容对象存储,支持上传、下载、列举、删除与分享链接
|
||||
description: >-
|
||||
操作 S3 兼容对象存储(上传、下载、列举、删除),通过 DesireCore HTTP API 调用。Use when 用户要求上传/下载/分享文件、需要生成下载链接、或工作流产出文件需要持久化存储与分发。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:6ea8e1375f12de72
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Object Storage Operations
|
||||
short_desc: Operate S3-compatible object storage via DesireCore HTTP API — upload, download, list, delete, and share links
|
||||
description: >-
|
||||
Operate S3-compatible object storage (upload, download, list, delete) via the DesireCore HTTP API. Use when the user requests file upload/download/sharing, needs a download link, or when workflow outputs need persistent storage and distribution.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:6ea8e1375f12de72
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -34,7 +57,6 @@ market:
|
||||
stroke-width="1.8" stroke-linecap="round" stroke-linejoin="round"/><path
|
||||
d="M16.5 15.5 18 17l1.5-1.5" stroke="#34C759" stroke-width="1.8"
|
||||
stroke-linecap="round" stroke-linejoin="round"/></svg>
|
||||
short_desc: 通过 DesireCore HTTP API 操作 S3 兼容对象存储,支持上传、下载、列举、删除与分享链接
|
||||
category: data
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -43,50 +65,50 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# s3-storage-operations 技能
|
||||
# s3-storage-operations Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
让 Agent 通过 DesireCore HTTP API 操作 S3 兼容对象存储,实现文件上传/下载/列举/删除并生成可分享的下载链接。
|
||||
Lets the Agent operate S3-compatible object storage through the DesireCore HTTP API — uploading, downloading, listing, and deleting files, and generating shareable download links.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
s3-storage-operations 是一个**工具技能(Tool-Skill)**,通过 DesireCore Agent Service 的 HTTP API 与用户预配置的 S3 兼容对象存储(AWS S3、七牛云 Kodo、MinIO 等)交互。
|
||||
s3-storage-operations is a **Tool-Skill** that interacts with the user's pre-configured S3-compatible object storage (AWS S3, Qiniu Kodo, MinIO, etc.) via the DesireCore Agent Service HTTP API.
|
||||
|
||||
**架构变更(v2.0)**:S3 操作已从内置工具迁移为 HTTP REST API 端点,可通过 curl 从任意环境调用。Claude Code 的 Global Skill(`desirecore-s3-storage`)包含完整的 curl 调用指南。
|
||||
**Architecture change (v2.0)**: S3 operations have been migrated from a built-in tool to HTTP REST API endpoints, callable via curl from any environment. Claude Code's Global Skill (`desirecore-s3-storage`) contains the full curl invocation guide.
|
||||
|
||||
核心原则:用户的 S3 连接已在 **资源 → 对象存储** 中预配置。API 自动解析连接——Agent 无需关心连接细节,专注于操作本身。
|
||||
Core principle: the user's S3 connection is pre-configured under **Resources → Object Storage**. The API resolves the connection automatically — the Agent does not need to worry about connection details and can focus on the operation itself.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户要求「上传文件」、「放到存储里」、「保存到 S3」
|
||||
- 用户要求「给我个下载链接」、「分享这个文件」、「从 S3 下载」
|
||||
- 用户要求「看看存储里有什么」、「列出桶里的文件」
|
||||
- 用户要求「从 S3 删除」、「清理临时文件」
|
||||
- 工作流产出文件(报告、导出、图片)需要通过 URL 分享
|
||||
- Agent 需要读取存储在 S3 中的数据进行处理
|
||||
- The user asks to "upload a file", "put it in storage", or "save to S3"
|
||||
- The user asks for "a download link", "share this file", or "download from S3"
|
||||
- The user asks to "see what's in storage" or "list files in the bucket"
|
||||
- The user asks to "delete from S3" or "clean up temp files"
|
||||
- A workflow produces files (reports, exports, images) that need to be shared via URL
|
||||
- The Agent needs to read data stored in S3 for further processing
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 端口发现
|
||||
### Port Discovery
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
```
|
||||
|
||||
### API 端点
|
||||
### API Endpoints
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
| Endpoint | Method | Description |
|
||||
| --------------------- | ------ | ------------------------------- |
|
||||
| `/api/s3/connections` | GET | 列出可用连接摘要 |
|
||||
| `/api/s3/upload` | POST | 上传文件(multipart/form-data) |
|
||||
| `/api/s3/download` | GET | 生成下载链接或下载文件 |
|
||||
| `/api/s3/list` | GET | 列出对象 |
|
||||
| `/api/s3/objects` | DELETE | 删除对象 |
|
||||
| `/api/s3/connections` | GET | List available connection summaries |
|
||||
| `/api/s3/upload` | POST | Upload a file (multipart/form-data) |
|
||||
| `/api/s3/download` | GET | Generate a download link or download a file |
|
||||
| `/api/s3/list` | GET | List objects |
|
||||
| `/api/s3/objects` | DELETE | Delete an object |
|
||||
|
||||
### 快速参考
|
||||
### Quick Reference
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
@@ -109,36 +131,36 @@ curl -k -X DELETE "https://127.0.0.1:${PORT}/api/s3/objects" \
|
||||
-H "Content-Type: application/json" -d '{"key":"remote/path.pdf"}'
|
||||
```
|
||||
|
||||
### 连接解析机制
|
||||
### Connection Resolution
|
||||
|
||||
所有 API 端点均接受可选 `connection_id` 参数。未指定时,系统按以下优先级自动解析:
|
||||
All API endpoints accept an optional `connection_id` parameter. When unspecified, the system resolves it automatically with the following priority:
|
||||
|
||||
```
|
||||
指定 ID → isDefault=true → 第一个 status="connected" → 第一个连接
|
||||
Specified ID → isDefault=true → first status="connected" → first connection
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
所有错误返回统一格式:
|
||||
All errors return a unified format:
|
||||
|
||||
```json
|
||||
{ "success": false, "error": "描述信息", "code": "ERROR_CODE" }
|
||||
```
|
||||
|
||||
错误代码:`NO_CONNECTION` | `NOT_FOUND` | `UPLOAD_FAILED` | `DOWNLOAD_FAILED` | `DELETE_FAILED` | `LIST_FAILED` | `INVALID_REQUEST`
|
||||
Error codes: `NO_CONNECTION` | `NOT_FOUND` | `UPLOAD_FAILED` | `DOWNLOAD_FAILED` | `DELETE_FAILED` | `LIST_FAILED` | `INVALID_REQUEST`
|
||||
|
||||
### 安全红线
|
||||
### Security Red Lines
|
||||
|
||||
| 规则 | 说明 |
|
||||
| -------------------- | ----------------------------------------------------- |
|
||||
| **禁止上传敏感文件** | `.env`、凭证文件、私钥等绝不上传 |
|
||||
| **删除前必须确认** | 调用删除 API 前应与用户确认意图 |
|
||||
| **不假设连接存在** | API 返回 `NO_CONNECTION` 时,引导用户在界面中添加连接 |
|
||||
| Rule | Description |
|
||||
| ------------------------- | ------------------------------------------------------ |
|
||||
| **No uploading sensitive files** | Never upload `.env`, credential files, private keys, etc. |
|
||||
| **Confirm before deletion** | Always confirm intent with the user before calling the delete API |
|
||||
| **Do not assume a connection exists** | When the API returns `NO_CONNECTION`, guide the user to add a connection in the UI |
|
||||
|
||||
### 集成点
|
||||
### Integration Points
|
||||
|
||||
- **S3 Routes** — `lib/agent-service/routes/s3-routes.ts`: HTTP API 实现
|
||||
- **S3 Client** — `lib/agent-service/s3-client.ts`: AWS V4 签名,CRUD 操作
|
||||
- **Connection Resolver** — `lib/agent-service/s3-connection-resolver.ts`: 自动选择连接
|
||||
- **Global Skill Sync** — `lib/agent-service/global-skill-sync.ts`: 启动时写入 Global Skill
|
||||
- **Port Discovery** — `~/.desirecore/agent-service.port`: 端口发现文件
|
||||
- **S3 Routes** — `lib/agent-service/routes/s3-routes.ts`: HTTP API implementation
|
||||
- **S3 Client** — `lib/agent-service/s3-client.ts`: AWS V4 signing, CRUD operations
|
||||
- **Connection Resolver** — `lib/agent-service/s3-connection-resolver.ts`: automatic connection selection
|
||||
- **Global Skill Sync** — `lib/agent-service/global-skill-sync.ts`: writes the Global Skill on startup
|
||||
- **Port Discovery** — `~/.desirecore/agent-service.port`: port discovery file
|
||||
|
||||
101
skills/s3-storage-operations/SKILL.zh-CN.md
Normal file
101
skills/s3-storage-operations/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,101 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# s3-storage-operations 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
让 Agent 通过 DesireCore HTTP API 操作 S3 兼容对象存储,实现文件上传/下载/列举/删除并生成可分享的下载链接。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
s3-storage-operations 是一个**工具技能(Tool-Skill)**,通过 DesireCore Agent Service 的 HTTP API 与用户预配置的 S3 兼容对象存储(AWS S3、七牛云 Kodo、MinIO 等)交互。
|
||||
|
||||
**架构变更(v2.0)**:S3 操作已从内置工具迁移为 HTTP REST API 端点,可通过 curl 从任意环境调用。Claude Code 的 Global Skill(`desirecore-s3-storage`)包含完整的 curl 调用指南。
|
||||
|
||||
核心原则:用户的 S3 连接已在 **资源 → 对象存储** 中预配置。API 自动解析连接——Agent 无需关心连接细节,专注于操作本身。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户要求「上传文件」、「放到存储里」、「保存到 S3」
|
||||
- 用户要求「给我个下载链接」、「分享这个文件」、「从 S3 下载」
|
||||
- 用户要求「看看存储里有什么」、「列出桶里的文件」
|
||||
- 用户要求「从 S3 删除」、「清理临时文件」
|
||||
- 工作流产出文件(报告、导出、图片)需要通过 URL 分享
|
||||
- Agent 需要读取存储在 S3 中的数据进行处理
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 端口发现
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
```
|
||||
|
||||
### API 端点
|
||||
|
||||
| 端点 | 方法 | 说明 |
|
||||
| --------------------- | ------ | ------------------------------- |
|
||||
| `/api/s3/connections` | GET | 列出可用连接摘要 |
|
||||
| `/api/s3/upload` | POST | 上传文件(multipart/form-data) |
|
||||
| `/api/s3/download` | GET | 生成下载链接或下载文件 |
|
||||
| `/api/s3/list` | GET | 列出对象 |
|
||||
| `/api/s3/objects` | DELETE | 删除对象 |
|
||||
|
||||
### 快速参考
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port)
|
||||
|
||||
# 列出连接
|
||||
curl -k "https://127.0.0.1:${PORT}/api/s3/connections"
|
||||
|
||||
# 上传
|
||||
curl -k -X POST "https://127.0.0.1:${PORT}/api/s3/upload" \
|
||||
-F "file=@local-file.pdf" -F "key=remote/path.pdf"
|
||||
|
||||
# 获取下载链接
|
||||
curl -k "https://127.0.0.1:${PORT}/api/s3/download?key=remote/path.pdf"
|
||||
|
||||
# 列出对象
|
||||
curl -k "https://127.0.0.1:${PORT}/api/s3/list?prefix=remote/"
|
||||
|
||||
# 删除
|
||||
curl -k -X DELETE "https://127.0.0.1:${PORT}/api/s3/objects" \
|
||||
-H "Content-Type: application/json" -d '{"key":"remote/path.pdf"}'
|
||||
```
|
||||
|
||||
### 连接解析机制
|
||||
|
||||
所有 API 端点均接受可选 `connection_id` 参数。未指定时,系统按以下优先级自动解析:
|
||||
|
||||
```
|
||||
指定 ID → isDefault=true → 第一个 status="connected" → 第一个连接
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
所有错误返回统一格式:
|
||||
|
||||
```json
|
||||
{ "success": false, "error": "描述信息", "code": "ERROR_CODE" }
|
||||
```
|
||||
|
||||
错误代码:`NO_CONNECTION` | `NOT_FOUND` | `UPLOAD_FAILED` | `DOWNLOAD_FAILED` | `DELETE_FAILED` | `LIST_FAILED` | `INVALID_REQUEST`
|
||||
|
||||
### 安全红线
|
||||
|
||||
| 规则 | 说明 |
|
||||
| -------------------- | ----------------------------------------------------- |
|
||||
| **禁止上传敏感文件** | `.env`、凭证文件、私钥等绝不上传 |
|
||||
| **删除前必须确认** | 调用删除 API 前应与用户确认意图 |
|
||||
| **不假设连接存在** | API 返回 `NO_CONNECTION` 时,引导用户在界面中添加连接 |
|
||||
|
||||
### 集成点
|
||||
|
||||
- **S3 Routes** — `lib/agent-service/routes/s3-routes.ts`: HTTP API 实现
|
||||
- **S3 Client** — `lib/agent-service/s3-client.ts`: AWS V4 签名,CRUD 操作
|
||||
- **Connection Resolver** — `lib/agent-service/s3-connection-resolver.ts`: 自动选择连接
|
||||
- **Global Skill Sync** — `lib/agent-service/global-skill-sync.ts`: 启动时写入 Global Skill
|
||||
- **Port Discovery** — `~/.desirecore/agent-service.port`: 端口发现文件
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 技能创建器
|
||||
name: skill-creator
|
||||
description: >-
|
||||
引导用户创建和编辑符合规范的 SKILL.md 技能包。支持 DesireCore 完整格式
|
||||
(frontmatter 元数据 + L0/L1/L2 分层内容 + 脚本/参考/资产)和 Claude Code
|
||||
@@ -19,6 +19,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-03'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 技能创建器
|
||||
short_desc: 引导创建符合规范的 SKILL.md 技能包,支持完整元数据与分层内容
|
||||
description: >-
|
||||
引导用户创建和编辑符合规范的 SKILL.md 技能包。支持 DesireCore 完整格式 (frontmatter 元数据 + L0/L1/L2 分层内容 + 脚本/参考/资产)和 Claude Code 基础格式。Use when 用户要求创建新技能、更新已有技能、或将经验封装为可复用 的技能包。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:fa0f3136371f236c
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Skill Creator
|
||||
short_desc: Guides creation of standards-compliant SKILL.md packages with complete metadata and layered content
|
||||
description: >-
|
||||
Guides users to create and edit standards-compliant SKILL.md skill packages. Supports the DesireCore full format (frontmatter metadata + L0/L1/L2 layered content + scripts/references/assets) and the Claude Code basic format. Use when the user requests to create a new Skill, update an existing Skill, or package experience into a reusable Skill bundle.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:fa0f3136371f236c
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -30,7 +53,6 @@ market:
|
||||
stroke="url(#sc)" stroke-width="1.8" stroke-linecap="round"/><path d="M15
|
||||
14l2 2-2 2" stroke="#34C759" stroke-width="2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/></svg>
|
||||
short_desc: 引导创建符合规范的 SKILL.md 技能包,支持完整元数据与分层内容
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -39,189 +61,189 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# skill-creator 技能
|
||||
# skill-creator Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
引导用户将需求、经验和工作流封装为结构化的 SKILL.md 技能包。
|
||||
Guides users to package requirements, experience, and workflows into structured SKILL.md skill bundles.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
skill-creator 是一个**元技能(Meta-Skill)**,赋予 Agent 创建和编辑技能的能力。技能是模块化、自包含的能力包,通过 SKILL.md 为 Agent 提供专业知识、工作流和工具集成——将 Agent 从通用助手转变为领域专家。
|
||||
skill-creator is a **Meta-Skill** that gives an Agent the ability to create and edit Skills. Skills are modular, self-contained capability packages that, via SKILL.md, provide an Agent with domain knowledge, workflows, and tool integrations—turning the Agent from a general assistant into a domain expert.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想把反复执行的工作流封装为可复用技能
|
||||
- 用户想创建新技能教会 Agent 新的能力
|
||||
- 用户想更新已有技能、优化其效果
|
||||
- 用户分享了参考资料,需要组织为结构化的技能包
|
||||
- The user wants to package a repeatedly executed workflow into a reusable Skill
|
||||
- The user wants to create a new Skill to teach the Agent a new capability
|
||||
- The user wants to update an existing Skill and improve its effectiveness
|
||||
- The user has shared reference material that needs to be organized into a structured Skill bundle
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **沉淀经验**:将个人知识和工作流固化为可复用的 Skill
|
||||
- **自我扩展**:创建的技能让 Agent 能力持续增长
|
||||
- **规范化**:生成符合标准的 SKILL.md,确保技能系统正确解析和分发
|
||||
- **Distill experience**: Solidify personal knowledge and workflows into reusable Skills
|
||||
- **Self-extension**: Skills you create let the Agent's capabilities grow continuously
|
||||
- **Standardization**: Generate standards-compliant SKILL.md files so the Skill system parses and distributes them correctly
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 关于技能
|
||||
### About Skills
|
||||
|
||||
技能是模块化、自包含的能力包,为 Agent 提供:
|
||||
Skills are modular, self-contained capability packages that provide an Agent with:
|
||||
|
||||
1. **专业工作流** — 特定领域的多步骤流程
|
||||
2. **工具集成** — 处理特定文件格式或 API 的指南
|
||||
3. **领域知识** — 公司规范、业务逻辑、专业 Schema
|
||||
4. **捆绑资源** — 脚本、参考文档和资产文件
|
||||
1. **Specialized workflows** — multi-step processes for a specific domain
|
||||
2. **Tool integrations** — guidance for handling specific file formats or APIs
|
||||
3. **Domain knowledge** — company conventions, business logic, specialized schemas
|
||||
4. **Bundled resources** — scripts, reference docs, and asset files
|
||||
|
||||
### 核心原则
|
||||
### Core Principles
|
||||
|
||||
#### 简洁优先
|
||||
#### Conciseness First
|
||||
|
||||
上下文窗口是公共资源。技能与系统提示、对话历史、其他技能元数据和用户请求共享上下文窗口。
|
||||
The context window is a shared resource. A Skill shares the context window with the system prompt, conversation history, other Skill metadata, and the user request.
|
||||
|
||||
**默认假设:AI 已经非常聪明。** 只添加 AI 不知道的内容。对每条信息问自己:"AI 真的需要这个解释吗?" "这段话值得它的 Token 成本吗?"
|
||||
**Default assumption: the AI is already very capable.** Only add what the AI does not already know. For each piece of information, ask yourself: "Does the AI really need this explained?" "Is this paragraph worth its Token cost?"
|
||||
|
||||
优先使用简洁的例子而非冗长的解释。
|
||||
Prefer concise examples over verbose explanations.
|
||||
|
||||
#### 设置适当的自由度
|
||||
#### Set the Right Level of Latitude
|
||||
|
||||
根据任务的脆弱性和可变性匹配指令的具体程度:
|
||||
Match instruction specificity to the task's fragility and variability:
|
||||
|
||||
- **高自由度(文本指引)**:多种方案都可行时,决策依赖上下文
|
||||
- **中自由度(伪代码或带参脚本)**:存在首选模式,允许一定变化
|
||||
- **低自由度(固定脚本,少量参数)**:操作脆弱易错,一致性至关重要
|
||||
- **High latitude (text guidance)**: when multiple approaches work and decisions depend on context
|
||||
- **Medium latitude (pseudocode or parameterized scripts)**: when there is a preferred pattern but some variation is allowed
|
||||
- **Low latitude (fixed scripts with few parameters)**: when the operation is fragile and error-prone, and consistency is critical
|
||||
|
||||
#### 渐进式披露
|
||||
#### Progressive Disclosure
|
||||
|
||||
技能使用三层加载系统高效管理上下文:
|
||||
A Skill uses a three-tier loading system to manage context efficiently:
|
||||
|
||||
1. **元数据(name + description)** — 始终在上下文中(~100 词)
|
||||
2. **SKILL.md body** — 技能触发时加载(<5k 词)
|
||||
3. **捆绑资源** — Agent 按需加载(无限制,脚本可直接执行无需读入上下文)
|
||||
1. **Metadata (name + description)** — always in context (~100 words)
|
||||
2. **SKILL.md body** — loaded when the Skill is triggered (<5k words)
|
||||
3. **Bundled resources** — loaded by the Agent on demand (no limit; scripts can be executed directly without being read into context)
|
||||
|
||||
### 技能结构
|
||||
### Skill Structure
|
||||
|
||||
```
|
||||
skill-name/
|
||||
├── SKILL.md (必须:技能定义文件)
|
||||
├── scripts/ (可选:可执行脚本)
|
||||
├── references/ (可选:参考文档)
|
||||
└── assets/ (可选:输出用资源文件)
|
||||
├── SKILL.md (required: skill definition file)
|
||||
├── scripts/ (optional: executable scripts)
|
||||
├── references/ (optional: reference docs)
|
||||
└── assets/ (optional: output asset files)
|
||||
```
|
||||
|
||||
#### SKILL.md 格式
|
||||
#### SKILL.md Format
|
||||
|
||||
SKILL.md 由两部分组成:**Frontmatter(YAML 元数据)** 和 **Body(Markdown 指令)**。
|
||||
A SKILL.md consists of two parts: **Frontmatter (YAML metadata)** and **Body (Markdown instructions)**.
|
||||
|
||||
##### Frontmatter 字段
|
||||
##### Frontmatter Fields
|
||||
|
||||
**必填**:
|
||||
**Required**:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
| Field | Type | Description |
|
||||
|------|------|------|
|
||||
| `description` | string | 技能用途描述。**必须包含 "Use when" 触发提示**——AI 据此判断何时使用该技能 |
|
||||
| `description` | string | Skill purpose description. **Must include a "Use when" trigger hint**—the AI uses this to decide when to invoke the Skill |
|
||||
|
||||
**推荐**:
|
||||
**Recommended**:
|
||||
|
||||
| 字段 | 类型 | 说明 | 默认值 |
|
||||
| Field | Type | Description | Default |
|
||||
|------|------|------|--------|
|
||||
| `name` | string | 技能显示名称 | 目录名 |
|
||||
| `version` | string | 语义版本号(如 `1.0.0`) | — |
|
||||
| `name` | string | Skill display name | Directory name |
|
||||
| `version` | string | Semantic version (e.g. `1.0.0`) | — |
|
||||
| `type` | enum | `procedural` / `conversational` / `meta` | — |
|
||||
| `risk_level` | enum | `low` / `medium` / `high` | — |
|
||||
| `status` | enum | `enabled` / `disabled` | `enabled` |
|
||||
| `tags` | string[] | 标签列表 | — |
|
||||
| `metadata` | object | `author`、`updated_at` | — |
|
||||
| `tags` | string[] | List of tags | — |
|
||||
| `metadata` | object | `author`, `updated_at` | — |
|
||||
|
||||
**功能控制**:
|
||||
**Feature Controls**:
|
||||
|
||||
| 字段 | 类型 | 默认 | 说明 |
|
||||
| Field | Type | Default | Description |
|
||||
|------|------|------|------|
|
||||
| `disable-model-invocation` | boolean | `true` | `true`=L0+L1 自动注入 system prompt(按需加载,体积小);`false`=L0+L1+L2 完整内容注入 system prompt |
|
||||
| `user-invocable` | boolean | `true` | `false`=不出现在命令补全,仅作为背景知识 |
|
||||
| `allowed-tools` | string[] | — | 限制执行时可用的工具列表 |
|
||||
| `requires` | object | — | 依赖声明:`tools`、`optional_tools`、`connections` |
|
||||
| `disable-model-invocation` | boolean | `true` | `true` = L0+L1 auto-injected into the system prompt (lazy load, small footprint); `false` = full L0+L1+L2 content injected into the system prompt |
|
||||
| `user-invocable` | boolean | `true` | `false` = does not appear in command completion; serves only as background knowledge |
|
||||
| `allowed-tools` | string[] | — | Restricts the list of tools available at execution time |
|
||||
| `requires` | object | — | Dependency declaration: `tools`, `optional_tools`, `connections` |
|
||||
|
||||
完整字段表(含市场发布、JSON 输出、fork 执行等高级字段)见 [references/desirecore-format.md](references/desirecore-format.md)。
|
||||
For the full field table (including market publishing, JSON output, fork execution, and other advanced fields), see [references/desirecore-format.md](references/desirecore-format.md).
|
||||
|
||||
> **Claude Code 兼容说明**:Claude Code 仅使用 `name` + `description`(+ 可选 `license`、`compatibility`)。这些字段在 DesireCore 中完全合法——DesireCore 格式是 Claude Code 的超集。
|
||||
> **Claude Code compatibility note**: Claude Code uses only `name` + `description` (plus optional `license`, `compatibility`). These fields are fully legal in DesireCore—the DesireCore format is a superset of Claude Code.
|
||||
|
||||
##### Body 结构
|
||||
##### Body Structure
|
||||
|
||||
**推荐使用 L0/L1/L2 分层**:
|
||||
**Recommended L0/L1/L2 layering**:
|
||||
|
||||
```markdown
|
||||
# skill-id 技能
|
||||
# skill-id Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
用一句话描述这个技能做什么。
|
||||
## L0: One-line Summary
|
||||
Describe in one sentence what this Skill does.
|
||||
|
||||
## L1:概述与使用场景
|
||||
### 能力描述 / ### 使用场景 / ### 核心价值
|
||||
## L1: Overview and Use Cases
|
||||
### Capability / ### Use Cases / ### Core Value
|
||||
|
||||
## L2:详细规范
|
||||
### 具体操作步骤 / ### 错误处理
|
||||
## L2: Detailed Specification
|
||||
### Concrete steps / ### Error handling
|
||||
```
|
||||
|
||||
分层加载机制:
|
||||
- **L0**(~50 字):快速理解技能做什么
|
||||
- **L1**(~300 字):判断是否适用于当前任务
|
||||
- **L2**(不限):完整的执行指南
|
||||
Layered loading mechanism:
|
||||
- **L0** (~50 chars): quickly understand what the Skill does
|
||||
- **L1** (~300 chars): decide whether it applies to the current task
|
||||
- **L2** (unlimited): the complete execution guide
|
||||
|
||||
> 分层不是强制的。如果技能内容简短(<100 行),可以不分层——解析器会以整段内容作为 fallback。Claude Code 的无分层格式在 DesireCore 中同样正常工作。
|
||||
> Layering is not mandatory. If the Skill content is short (<100 lines), you can skip layering—the parser will fall back to using the entire content. The unlayered Claude Code format also works in DesireCore.
|
||||
|
||||
#### Bundled Resources
|
||||
|
||||
##### Scripts(`scripts/`)
|
||||
##### Scripts (`scripts/`)
|
||||
|
||||
可执行代码(Python/Bash 等),用于需要确定性可靠性或被反复编写的任务。
|
||||
Executable code (Python/Bash, etc.) used for tasks that need deterministic reliability or are written repeatedly.
|
||||
|
||||
- **何时使用**:相同代码被反复编写,或需要确定性可靠性
|
||||
- **示例**:`scripts/rotate_pdf.py`(PDF 旋转)、`scripts/fill_form.py`(表单填充)
|
||||
- **优势**:Token 高效,确定性,可直接执行无需读入上下文
|
||||
- **注意**:脚本可能仍需被 AI 读取以做环境适配
|
||||
- **When to use**: the same code is written repeatedly, or deterministic reliability is needed
|
||||
- **Examples**: `scripts/rotate_pdf.py` (PDF rotation), `scripts/fill_form.py` (form filling)
|
||||
- **Advantages**: token-efficient, deterministic, can be executed directly without being read into context
|
||||
- **Note**: scripts may still need to be read by the AI for environment adaptation
|
||||
|
||||
##### References(`references/`)
|
||||
##### References (`references/`)
|
||||
|
||||
文档和参考资料,按需加载到上下文中。
|
||||
Documents and reference material loaded into context on demand.
|
||||
|
||||
- **何时使用**:AI 工作时需要参考的详细文档
|
||||
- **示例**:API 文档、数据库 Schema、领域知识、公司政策
|
||||
- **最佳实践**:大文件(>10k 词)在 SKILL.md 中提供 grep 搜索模式
|
||||
- **避免重复**:信息只放 SKILL.md 或 references 中的一处
|
||||
- **When to use**: detailed documentation that the AI needs while working
|
||||
- **Examples**: API docs, database schemas, domain knowledge, company policies
|
||||
- **Best practice**: for large files (>10k words), provide grep search patterns in SKILL.md
|
||||
- **Avoid duplication**: keep information in only one place—either SKILL.md or references
|
||||
|
||||
##### Assets(`assets/`)
|
||||
##### Assets (`assets/`)
|
||||
|
||||
不加载到上下文、而是用于输出的文件。
|
||||
Files that are not loaded into context but used in the output.
|
||||
|
||||
- **何时使用**:技能需要在最终输出中使用的文件
|
||||
- **示例**:PPT 模板、HTML 骨架、logo 图片、字体文件
|
||||
- **优势**:将输出资源与文档分离
|
||||
- **When to use**: files the Skill needs in the final output
|
||||
- **Examples**: PPT templates, HTML scaffolds, logo images, font files
|
||||
- **Advantage**: separates output assets from documentation
|
||||
|
||||
#### 不应包含的内容
|
||||
#### What Should Not Be Included
|
||||
|
||||
技能应只包含 AI 执行任务所需的文件。**不要**创建:README.md、INSTALLATION_GUIDE.md、CHANGELOG.md 等辅助文档。
|
||||
A Skill should contain only the files the AI needs to execute the task. **Do not** create README.md, INSTALLATION_GUIDE.md, CHANGELOG.md, or other ancillary documentation.
|
||||
|
||||
### 渐进式披露模式
|
||||
### Progressive Disclosure Patterns
|
||||
|
||||
保持 SKILL.md body 在 500 行以内。接近限制时拆分到 references。
|
||||
Keep the SKILL.md body within 500 lines. When approaching the limit, split content into references.
|
||||
|
||||
**模式 1:高层指南 + 参考文件**
|
||||
**Pattern 1: High-level guide + reference files**
|
||||
|
||||
```markdown
|
||||
# PDF Processing
|
||||
|
||||
## Quick start
|
||||
[核心代码示例]
|
||||
[core code example]
|
||||
|
||||
## Advanced features
|
||||
- **Form filling**: See [FORMS.md](FORMS.md)
|
||||
- **API reference**: See [REFERENCE.md](REFERENCE.md)
|
||||
```
|
||||
|
||||
**模式 2:按领域组织**
|
||||
**Pattern 2: Organized by domain**
|
||||
|
||||
```
|
||||
bigquery-skill/
|
||||
@@ -232,9 +254,9 @@ bigquery-skill/
|
||||
└── product.md
|
||||
```
|
||||
|
||||
用户问销售指标时,AI 只读 sales.md。
|
||||
When the user asks about sales metrics, the AI reads only sales.md.
|
||||
|
||||
**模式 3:基本内容 + 条件高级内容**
|
||||
**Pattern 3: Basic content + conditional advanced content**
|
||||
|
||||
```markdown
|
||||
## Editing documents
|
||||
@@ -242,153 +264,153 @@ For simple edits, modify the XML directly.
|
||||
**For tracked changes**: See [REDLINING.md](REDLINING.md)
|
||||
```
|
||||
|
||||
**重要**:避免深层嵌套引用——references 只从 SKILL.md 直接链接一层。长 reference 文件(>100 行)在顶部加目录。
|
||||
**Important**: avoid deep nested references—references should be linked only one level directly from SKILL.md. Long reference files (>100 lines) should include a table of contents at the top.
|
||||
|
||||
### 创建流程
|
||||
### Creation Workflow
|
||||
|
||||
1. 用具体例子理解技能需求
|
||||
2. 规划可复用资源(脚本、参考、资产)
|
||||
3. 初始化技能(运行 init_skill.py)
|
||||
4. 编辑技能(实现资源,编写 SKILL.md)
|
||||
5. 验证技能(运行 quick_validate.py)
|
||||
6. 安装技能
|
||||
7. 迭代优化
|
||||
1. Understand the Skill requirements with concrete examples
|
||||
2. Plan reusable resources (scripts, references, assets)
|
||||
3. Initialize the Skill (run init_skill.py)
|
||||
4. Edit the Skill (implement resources, write SKILL.md)
|
||||
5. Validate the Skill (run quick_validate.py)
|
||||
6. Install the Skill
|
||||
7. Iterate and refine
|
||||
|
||||
#### 步骤 1:理解技能需求
|
||||
#### Step 1: Understand the Skill Requirements
|
||||
|
||||
跳过此步仅当技能的使用模式已经完全清晰。即使处理已有技能时,此步仍有价值。
|
||||
Skip this step only when the Skill's usage pattern is already completely clear. Even when working on an existing Skill, this step still has value.
|
||||
|
||||
通过具体例子理解技能将如何被使用。例如构建 image-editor 技能时:
|
||||
Use concrete examples to understand how the Skill will be used. For instance, when building an image-editor Skill:
|
||||
|
||||
- "这个技能应支持哪些功能?编辑、旋转、其他?"
|
||||
- "能举几个使用场景吗?"
|
||||
- "什么操作应该触发这个技能?"
|
||||
- "What features should this Skill support? Editing, rotating, anything else?"
|
||||
- "Can you give a few use cases?"
|
||||
- "What action should trigger this Skill?"
|
||||
|
||||
避免一次问太多问题——从最重要的开始,按需跟进。当对技能应支持的功能有清晰认知时,结束此步。
|
||||
Avoid asking too many questions at once—start with the most important and follow up as needed. End this step when you have a clear understanding of what features the Skill should support.
|
||||
|
||||
#### 步骤 2:规划资源
|
||||
#### Step 2: Plan Resources
|
||||
|
||||
分析每个例子:
|
||||
For each example, analyze:
|
||||
|
||||
1. 考虑如何从零执行
|
||||
2. 识别哪些脚本、参考、资产在反复执行时有帮助
|
||||
1. Consider how to execute it from scratch
|
||||
2. Identify which scripts, references, and assets would help when executing repeatedly
|
||||
|
||||
示例分析:
|
||||
Example analysis:
|
||||
|
||||
- `pdf-editor` 处理"旋转 PDF"→ 每次都要写相同代码 → `scripts/rotate_pdf.py`
|
||||
- `frontend-webapp-builder` 处理"创建 todo app"→ 每次都要写样板代码 → `assets/hello-world/`
|
||||
- `big-query` 处理"今天多少用户登录"→ 每次都要查 Schema → `references/schema.md`
|
||||
- `pdf-editor` handles "rotate PDF" → the same code is written every time → `scripts/rotate_pdf.py`
|
||||
- `frontend-webapp-builder` handles "create todo app" → boilerplate is written every time → `assets/hello-world/`
|
||||
- `big-query` handles "how many users logged in today" → the schema is queried every time → `references/schema.md`
|
||||
|
||||
#### 步骤 3:初始化
|
||||
#### Step 3: Initialize
|
||||
|
||||
使用 init_skill.py 创建模板:
|
||||
Use init_skill.py to create a template:
|
||||
|
||||
```bash
|
||||
# DesireCore 完整格式(默认,推荐)
|
||||
# DesireCore full format (default, recommended)
|
||||
scripts/init_skill.py <skill-name> --path <output-directory>
|
||||
|
||||
# Claude Code 基础格式
|
||||
# Claude Code basic format
|
||||
scripts/init_skill.py <skill-name> --path <output-directory> --format basic
|
||||
```
|
||||
|
||||
默认生成 DesireCore 格式(含完整 frontmatter + L0/L1/L2 结构)。`--format basic` 生成 Claude Code 兼容的最小格式。
|
||||
By default this generates the DesireCore format (with full frontmatter + L0/L1/L2 structure). `--format basic` generates the minimal Claude Code-compatible format.
|
||||
|
||||
初始化后,根据需要定制或删除生成的示例文件。
|
||||
After initialization, customize or delete the generated example files as needed.
|
||||
|
||||
#### 步骤 4:编辑技能
|
||||
#### Step 4: Edit the Skill
|
||||
|
||||
##### 学习设计模式
|
||||
##### Learn the Design Patterns
|
||||
|
||||
根据技能需求查阅参考:
|
||||
Consult references based on the Skill's needs:
|
||||
|
||||
- **多步骤流程**:见 [references/workflows.md](references/workflows.md)
|
||||
- **输出格式标准**:见 [references/output-patterns.md](references/output-patterns.md)
|
||||
- **Multi-step workflows**: see [references/workflows.md](references/workflows.md)
|
||||
- **Output format standards**: see [references/output-patterns.md](references/output-patterns.md)
|
||||
|
||||
##### 从资源开始
|
||||
##### Start from Resources
|
||||
|
||||
先实现步骤 2 识别的资源文件(scripts/、references/、assets/)。此步骤可能需要用户输入,如品牌资产需要用户提供 logo。
|
||||
First implement the resource files identified in Step 2 (scripts/, references/, assets/). This step may need user input—e.g. brand assets require the user to supply a logo.
|
||||
|
||||
添加的脚本必须实际运行测试,确保无 bug 且输出符合预期。不需要的示例文件应删除。
|
||||
Any script you add must actually be run and tested to ensure it is bug-free and its output meets expectations. Unneeded example files should be deleted.
|
||||
|
||||
##### 编写 SKILL.md
|
||||
##### Write SKILL.md
|
||||
|
||||
**Frontmatter 编写要点**:
|
||||
**Frontmatter writing tips**:
|
||||
|
||||
- `description` 是最关键的字段——AI 据此判断何时触发技能
|
||||
- 在 description 中包含 "Use when" 触发提示和典型使用场景
|
||||
- 所有 "when to use" 信息放 description 中,不放 body 里(body 只在触发后加载)
|
||||
- `description` is the most critical field—the AI uses it to decide when to trigger the Skill
|
||||
- Include a "Use when" trigger hint and typical use cases in description
|
||||
- Put all "when to use" information in description, not in the body (the body is loaded only after the Skill is triggered)
|
||||
|
||||
**Body 编写要点**:
|
||||
**Body writing tips**:
|
||||
|
||||
- 始终使用祈使句/不定式形式
|
||||
- L0 不超过一句话
|
||||
- L1 用于判断适用性,不超过 300 字
|
||||
- L2 放完整的操作步骤、API 调用、错误处理
|
||||
- Always use imperative/infinitive form
|
||||
- L0 should be no longer than one sentence
|
||||
- L1 is for deciding applicability and should not exceed 300 characters
|
||||
- L2 holds the complete steps, API calls, and error handling
|
||||
|
||||
#### 步骤 5:验证
|
||||
#### Step 5: Validate
|
||||
|
||||
```bash
|
||||
scripts/quick_validate.py <path/to/skill-folder>
|
||||
```
|
||||
|
||||
验证 SKILL.md 格式、frontmatter 字段合法性和目录结构。
|
||||
Validates SKILL.md format, the legality of frontmatter fields, and the directory structure.
|
||||
|
||||
#### 步骤 6:安装
|
||||
#### Step 6: Install
|
||||
|
||||
**方式 A:通过 API 安装(推荐,需 Agent Service 运行中)**
|
||||
**Option A: Install via API (recommended; requires the Agent Service to be running)**
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port 2>/dev/null)
|
||||
|
||||
# 安装为全局技能(所有 Agent 可见)
|
||||
# Install as a global Skill (visible to all Agents)
|
||||
curl -k -X POST "https://127.0.0.1:${PORT}/api/skills" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"skillId\": \"<skill-name>\", \"content\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
|
||||
|
||||
# 安装为 Agent 级技能(仅指定 Agent 可见)
|
||||
# Install as an Agent-scoped Skill (visible only to the specified Agent)
|
||||
curl -k -X POST "https://127.0.0.1:${PORT}/api/agents/<agentId>/skills" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"id\": \"<skill-name>\", \"fullContent\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
|
||||
```
|
||||
|
||||
**方式 B:文件系统直写**
|
||||
**Option B: Direct filesystem write**
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
# Global Skill
|
||||
cp -r path/to/skill-name ~/.desirecore/skills/
|
||||
|
||||
# Agent 级技能
|
||||
# Agent-scoped Skill
|
||||
cp -r path/to/skill-name ~/.desirecore/agents/<agentId>/skills/
|
||||
```
|
||||
|
||||
**方式 C:打包为 .skill 文件(Claude Code 兼容)**
|
||||
**Option C: Package as a .skill file (Claude Code compatible)**
|
||||
|
||||
```bash
|
||||
scripts/package_skill.py <path/to/skill-folder>
|
||||
```
|
||||
|
||||
生成 `skill-name.skill` 文件(ZIP 格式),可在 Claude Code 中使用。
|
||||
Generates a `skill-name.skill` file (ZIP format) usable in Claude Code.
|
||||
|
||||
**安装完成后,必须向用户报告**:
|
||||
- 技能已安装到的完整路径
|
||||
- 安装的作用域(Global / Agent / Project)
|
||||
- 如何在后续对话中触发该技能
|
||||
**After installation, you must report to the user**:
|
||||
- The full path the Skill was installed to
|
||||
- The installation scope (Global / Agent / Project)
|
||||
- How to trigger this Skill in subsequent conversations
|
||||
|
||||
#### 步骤 7:迭代
|
||||
#### Step 7: Iterate
|
||||
|
||||
1. 在真实任务中使用技能
|
||||
2. 观察不足或低效之处
|
||||
3. 确定 SKILL.md 或资源需要如何改进
|
||||
4. 实施修改并再次测试
|
||||
1. Use the Skill on real tasks
|
||||
2. Observe shortcomings or inefficiencies
|
||||
3. Decide how the SKILL.md or its resources need to change
|
||||
4. Apply the changes and test again
|
||||
|
||||
### 作用域说明
|
||||
### Scope Notes
|
||||
|
||||
技能存在三个作用域层级,按优先级从高到低:
|
||||
Skills exist at three scope levels, listed from highest priority to lowest:
|
||||
|
||||
| 优先级 | 作用域 | 路径 | 可见范围 |
|
||||
| Priority | Scope | Path | Visibility |
|
||||
|--------|--------|------|---------|
|
||||
| 最高 | Project | `.claude/skills/` | 当前项目所有 Agent |
|
||||
| 中 | Agent | `~/.desirecore/agents/{agentId}/skills/` | 仅该 Agent |
|
||||
| 最低 | Global | `~/.desirecore/skills/` | 所有 Agent |
|
||||
| Highest | Project | `.claude/skills/` | All Agents in the current project |
|
||||
| Medium | Agent | `~/.desirecore/agents/{agentId}/skills/` | Only that Agent |
|
||||
| Lowest | Global | `~/.desirecore/skills/` | All Agents |
|
||||
|
||||
同名技能按优先级覆盖——高优先级的技能会遮蔽低优先级的同名技能。
|
||||
Skills with the same name override each other by priority—a higher-priority Skill shadows a lower-priority one with the same name.
|
||||
|
||||
355
skills/skill-creator/SKILL.zh-CN.md
Normal file
355
skills/skill-creator/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,355 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# skill-creator 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
引导用户将需求、经验和工作流封装为结构化的 SKILL.md 技能包。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
skill-creator 是一个**元技能(Meta-Skill)**,赋予 Agent 创建和编辑技能的能力。技能是模块化、自包含的能力包,通过 SKILL.md 为 Agent 提供专业知识、工作流和工具集成——将 Agent 从通用助手转变为领域专家。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想把反复执行的工作流封装为可复用技能
|
||||
- 用户想创建新技能教会 Agent 新的能力
|
||||
- 用户想更新已有技能、优化其效果
|
||||
- 用户分享了参考资料,需要组织为结构化的技能包
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **沉淀经验**:将个人知识和工作流固化为可复用的 Skill
|
||||
- **自我扩展**:创建的技能让 Agent 能力持续增长
|
||||
- **规范化**:生成符合标准的 SKILL.md,确保技能系统正确解析和分发
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 关于技能
|
||||
|
||||
技能是模块化、自包含的能力包,为 Agent 提供:
|
||||
|
||||
1. **专业工作流** — 特定领域的多步骤流程
|
||||
2. **工具集成** — 处理特定文件格式或 API 的指南
|
||||
3. **领域知识** — 公司规范、业务逻辑、专业 Schema
|
||||
4. **捆绑资源** — 脚本、参考文档和资产文件
|
||||
|
||||
### 核心原则
|
||||
|
||||
#### 简洁优先
|
||||
|
||||
上下文窗口是公共资源。技能与系统提示、对话历史、其他技能元数据和用户请求共享上下文窗口。
|
||||
|
||||
**默认假设:AI 已经非常聪明。** 只添加 AI 不知道的内容。对每条信息问自己:"AI 真的需要这个解释吗?" "这段话值得它的 Token 成本吗?"
|
||||
|
||||
优先使用简洁的例子而非冗长的解释。
|
||||
|
||||
#### 设置适当的自由度
|
||||
|
||||
根据任务的脆弱性和可变性匹配指令的具体程度:
|
||||
|
||||
- **高自由度(文本指引)**:多种方案都可行时,决策依赖上下文
|
||||
- **中自由度(伪代码或带参脚本)**:存在首选模式,允许一定变化
|
||||
- **低自由度(固定脚本,少量参数)**:操作脆弱易错,一致性至关重要
|
||||
|
||||
#### 渐进式披露
|
||||
|
||||
技能使用三层加载系统高效管理上下文:
|
||||
|
||||
1. **元数据(name + description)** — 始终在上下文中(~100 词)
|
||||
2. **SKILL.md body** — 技能触发时加载(<5k 词)
|
||||
3. **捆绑资源** — Agent 按需加载(无限制,脚本可直接执行无需读入上下文)
|
||||
|
||||
### 技能结构
|
||||
|
||||
```
|
||||
skill-name/
|
||||
├── SKILL.md (必须:技能定义文件)
|
||||
├── scripts/ (可选:可执行脚本)
|
||||
├── references/ (可选:参考文档)
|
||||
└── assets/ (可选:输出用资源文件)
|
||||
```
|
||||
|
||||
#### SKILL.md 格式
|
||||
|
||||
SKILL.md 由两部分组成:**Frontmatter(YAML 元数据)** 和 **Body(Markdown 指令)**。
|
||||
|
||||
##### Frontmatter 字段
|
||||
|
||||
**必填**:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| `description` | string | 技能用途描述。**必须包含 "Use when" 触发提示**——AI 据此判断何时使用该技能 |
|
||||
|
||||
**推荐**:
|
||||
|
||||
| 字段 | 类型 | 说明 | 默认值 |
|
||||
|------|------|------|--------|
|
||||
| `name` | string | 技能显示名称 | 目录名 |
|
||||
| `version` | string | 语义版本号(如 `1.0.0`) | — |
|
||||
| `type` | enum | `procedural` / `conversational` / `meta` | — |
|
||||
| `risk_level` | enum | `low` / `medium` / `high` | — |
|
||||
| `status` | enum | `enabled` / `disabled` | `enabled` |
|
||||
| `tags` | string[] | 标签列表 | — |
|
||||
| `metadata` | object | `author`、`updated_at` | — |
|
||||
|
||||
**功能控制**:
|
||||
|
||||
| 字段 | 类型 | 默认 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `disable-model-invocation` | boolean | `true` | `true`=L0+L1 自动注入 system prompt(按需加载,体积小);`false`=L0+L1+L2 完整内容注入 system prompt |
|
||||
| `user-invocable` | boolean | `true` | `false`=不出现在命令补全,仅作为背景知识 |
|
||||
| `allowed-tools` | string[] | — | 限制执行时可用的工具列表 |
|
||||
| `requires` | object | — | 依赖声明:`tools`、`optional_tools`、`connections` |
|
||||
|
||||
完整字段表(含市场发布、JSON 输出、fork 执行等高级字段)见 [references/desirecore-format.md](references/desirecore-format.md)。
|
||||
|
||||
> **Claude Code 兼容说明**:Claude Code 仅使用 `name` + `description`(+ 可选 `license`、`compatibility`)。这些字段在 DesireCore 中完全合法——DesireCore 格式是 Claude Code 的超集。
|
||||
|
||||
##### Body 结构
|
||||
|
||||
**推荐使用 L0/L1/L2 分层**:
|
||||
|
||||
```markdown
|
||||
# skill-id 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
用一句话描述这个技能做什么。
|
||||
|
||||
## L1:概述与使用场景
|
||||
### 能力描述 / ### 使用场景 / ### 核心价值
|
||||
|
||||
## L2:详细规范
|
||||
### 具体操作步骤 / ### 错误处理
|
||||
```
|
||||
|
||||
分层加载机制:
|
||||
- **L0**(~50 字):快速理解技能做什么
|
||||
- **L1**(~300 字):判断是否适用于当前任务
|
||||
- **L2**(不限):完整的执行指南
|
||||
|
||||
> 分层不是强制的。如果技能内容简短(<100 行),可以不分层——解析器会以整段内容作为 fallback。Claude Code 的无分层格式在 DesireCore 中同样正常工作。
|
||||
|
||||
#### Bundled Resources
|
||||
|
||||
##### Scripts(`scripts/`)
|
||||
|
||||
可执行代码(Python/Bash 等),用于需要确定性可靠性或被反复编写的任务。
|
||||
|
||||
- **何时使用**:相同代码被反复编写,或需要确定性可靠性
|
||||
- **示例**:`scripts/rotate_pdf.py`(PDF 旋转)、`scripts/fill_form.py`(表单填充)
|
||||
- **优势**:Token 高效,确定性,可直接执行无需读入上下文
|
||||
- **注意**:脚本可能仍需被 AI 读取以做环境适配
|
||||
|
||||
##### References(`references/`)
|
||||
|
||||
文档和参考资料,按需加载到上下文中。
|
||||
|
||||
- **何时使用**:AI 工作时需要参考的详细文档
|
||||
- **示例**:API 文档、数据库 Schema、领域知识、公司政策
|
||||
- **最佳实践**:大文件(>10k 词)在 SKILL.md 中提供 grep 搜索模式
|
||||
- **避免重复**:信息只放 SKILL.md 或 references 中的一处
|
||||
|
||||
##### Assets(`assets/`)
|
||||
|
||||
不加载到上下文、而是用于输出的文件。
|
||||
|
||||
- **何时使用**:技能需要在最终输出中使用的文件
|
||||
- **示例**:PPT 模板、HTML 骨架、logo 图片、字体文件
|
||||
- **优势**:将输出资源与文档分离
|
||||
|
||||
#### 不应包含的内容
|
||||
|
||||
技能应只包含 AI 执行任务所需的文件。**不要**创建:README.md、INSTALLATION_GUIDE.md、CHANGELOG.md 等辅助文档。
|
||||
|
||||
### 渐进式披露模式
|
||||
|
||||
保持 SKILL.md body 在 500 行以内。接近限制时拆分到 references。
|
||||
|
||||
**模式 1:高层指南 + 参考文件**
|
||||
|
||||
```markdown
|
||||
# PDF Processing
|
||||
|
||||
## Quick start
|
||||
[核心代码示例]
|
||||
|
||||
## Advanced features
|
||||
- **Form filling**: See [FORMS.md](FORMS.md)
|
||||
- **API reference**: See [REFERENCE.md](REFERENCE.md)
|
||||
```
|
||||
|
||||
**模式 2:按领域组织**
|
||||
|
||||
```
|
||||
bigquery-skill/
|
||||
├── SKILL.md (overview)
|
||||
└── references/
|
||||
├── finance.md
|
||||
├── sales.md
|
||||
└── product.md
|
||||
```
|
||||
|
||||
用户问销售指标时,AI 只读 sales.md。
|
||||
|
||||
**模式 3:基本内容 + 条件高级内容**
|
||||
|
||||
```markdown
|
||||
## Editing documents
|
||||
For simple edits, modify the XML directly.
|
||||
**For tracked changes**: See [REDLINING.md](REDLINING.md)
|
||||
```
|
||||
|
||||
**重要**:避免深层嵌套引用——references 只从 SKILL.md 直接链接一层。长 reference 文件(>100 行)在顶部加目录。
|
||||
|
||||
### 创建流程
|
||||
|
||||
1. 用具体例子理解技能需求
|
||||
2. 规划可复用资源(脚本、参考、资产)
|
||||
3. 初始化技能(运行 init_skill.py)
|
||||
4. 编辑技能(实现资源,编写 SKILL.md)
|
||||
5. 验证技能(运行 quick_validate.py)
|
||||
6. 安装技能
|
||||
7. 迭代优化
|
||||
|
||||
#### 步骤 1:理解技能需求
|
||||
|
||||
跳过此步仅当技能的使用模式已经完全清晰。即使处理已有技能时,此步仍有价值。
|
||||
|
||||
通过具体例子理解技能将如何被使用。例如构建 image-editor 技能时:
|
||||
|
||||
- "这个技能应支持哪些功能?编辑、旋转、其他?"
|
||||
- "能举几个使用场景吗?"
|
||||
- "什么操作应该触发这个技能?"
|
||||
|
||||
避免一次问太多问题——从最重要的开始,按需跟进。当对技能应支持的功能有清晰认知时,结束此步。
|
||||
|
||||
#### 步骤 2:规划资源
|
||||
|
||||
分析每个例子:
|
||||
|
||||
1. 考虑如何从零执行
|
||||
2. 识别哪些脚本、参考、资产在反复执行时有帮助
|
||||
|
||||
示例分析:
|
||||
|
||||
- `pdf-editor` 处理"旋转 PDF"→ 每次都要写相同代码 → `scripts/rotate_pdf.py`
|
||||
- `frontend-webapp-builder` 处理"创建 todo app"→ 每次都要写样板代码 → `assets/hello-world/`
|
||||
- `big-query` 处理"今天多少用户登录"→ 每次都要查 Schema → `references/schema.md`
|
||||
|
||||
#### 步骤 3:初始化
|
||||
|
||||
使用 init_skill.py 创建模板:
|
||||
|
||||
```bash
|
||||
# DesireCore 完整格式(默认,推荐)
|
||||
scripts/init_skill.py <skill-name> --path <output-directory>
|
||||
|
||||
# Claude Code 基础格式
|
||||
scripts/init_skill.py <skill-name> --path <output-directory> --format basic
|
||||
```
|
||||
|
||||
默认生成 DesireCore 格式(含完整 frontmatter + L0/L1/L2 结构)。`--format basic` 生成 Claude Code 兼容的最小格式。
|
||||
|
||||
初始化后,根据需要定制或删除生成的示例文件。
|
||||
|
||||
#### 步骤 4:编辑技能
|
||||
|
||||
##### 学习设计模式
|
||||
|
||||
根据技能需求查阅参考:
|
||||
|
||||
- **多步骤流程**:见 [references/workflows.md](references/workflows.md)
|
||||
- **输出格式标准**:见 [references/output-patterns.md](references/output-patterns.md)
|
||||
|
||||
##### 从资源开始
|
||||
|
||||
先实现步骤 2 识别的资源文件(scripts/、references/、assets/)。此步骤可能需要用户输入,如品牌资产需要用户提供 logo。
|
||||
|
||||
添加的脚本必须实际运行测试,确保无 bug 且输出符合预期。不需要的示例文件应删除。
|
||||
|
||||
##### 编写 SKILL.md
|
||||
|
||||
**Frontmatter 编写要点**:
|
||||
|
||||
- `description` 是最关键的字段——AI 据此判断何时触发技能
|
||||
- 在 description 中包含 "Use when" 触发提示和典型使用场景
|
||||
- 所有 "when to use" 信息放 description 中,不放 body 里(body 只在触发后加载)
|
||||
|
||||
**Body 编写要点**:
|
||||
|
||||
- 始终使用祈使句/不定式形式
|
||||
- L0 不超过一句话
|
||||
- L1 用于判断适用性,不超过 300 字
|
||||
- L2 放完整的操作步骤、API 调用、错误处理
|
||||
|
||||
#### 步骤 5:验证
|
||||
|
||||
```bash
|
||||
scripts/quick_validate.py <path/to/skill-folder>
|
||||
```
|
||||
|
||||
验证 SKILL.md 格式、frontmatter 字段合法性和目录结构。
|
||||
|
||||
#### 步骤 6:安装
|
||||
|
||||
**方式 A:通过 API 安装(推荐,需 Agent Service 运行中)**
|
||||
|
||||
```bash
|
||||
PORT=$(cat ~/.desirecore/agent-service.port 2>/dev/null)
|
||||
|
||||
# 安装为全局技能(所有 Agent 可见)
|
||||
curl -k -X POST "https://127.0.0.1:${PORT}/api/skills" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"skillId\": \"<skill-name>\", \"content\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
|
||||
|
||||
# 安装为 Agent 级技能(仅指定 Agent 可见)
|
||||
curl -k -X POST "https://127.0.0.1:${PORT}/api/agents/<agentId>/skills" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d "{\"id\": \"<skill-name>\", \"fullContent\": \"$(cat path/to/SKILL.md | jq -Rsa .)\"}"
|
||||
```
|
||||
|
||||
**方式 B:文件系统直写**
|
||||
|
||||
```bash
|
||||
# 全局技能
|
||||
cp -r path/to/skill-name ~/.desirecore/skills/
|
||||
|
||||
# Agent 级技能
|
||||
cp -r path/to/skill-name ~/.desirecore/agents/<agentId>/skills/
|
||||
```
|
||||
|
||||
**方式 C:打包为 .skill 文件(Claude Code 兼容)**
|
||||
|
||||
```bash
|
||||
scripts/package_skill.py <path/to/skill-folder>
|
||||
```
|
||||
|
||||
生成 `skill-name.skill` 文件(ZIP 格式),可在 Claude Code 中使用。
|
||||
|
||||
**安装完成后,必须向用户报告**:
|
||||
- 技能已安装到的完整路径
|
||||
- 安装的作用域(Global / Agent / Project)
|
||||
- 如何在后续对话中触发该技能
|
||||
|
||||
#### 步骤 7:迭代
|
||||
|
||||
1. 在真实任务中使用技能
|
||||
2. 观察不足或低效之处
|
||||
3. 确定 SKILL.md 或资源需要如何改进
|
||||
4. 实施修改并再次测试
|
||||
|
||||
### 作用域说明
|
||||
|
||||
技能存在三个作用域层级,按优先级从高到低:
|
||||
|
||||
| 优先级 | 作用域 | 路径 | 可见范围 |
|
||||
|--------|--------|------|---------|
|
||||
| 最高 | Project | `.claude/skills/` | 当前项目所有 Agent |
|
||||
| 中 | Agent | `~/.desirecore/agents/{agentId}/skills/` | 仅该 Agent |
|
||||
| 最低 | Global | `~/.desirecore/skills/` | 所有 Agent |
|
||||
|
||||
同名技能按优先级覆盖——高优先级的技能会遮蔽低优先级的同名技能。
|
||||
@@ -25,7 +25,7 @@
|
||||
|
||||
| 字段 | 类型 | 默认 | 说明 |
|
||||
|------|------|------|------|
|
||||
| `disable-model-invocation` | boolean | `true` | `true`=L0+L1 自动注入 system prompt(按需加载,体积小);`false`=L0+L1+L2 完整内容注入 system prompt |
|
||||
| `disable-model-invocation` | boolean | `true` | `false`=opt-in 自动注入完整 SKILL.md 内容到 system prompt(自动加载);`true` 或缺省=不自动注入,仅当 Agent 显式调用 Skill 工具时才加载(与 Claude Skills 对齐:默认禁用,需显式启用) |
|
||||
| `user-invocable` | boolean | `true` | `false`=不出现在命令补全,仅作为背景知识 |
|
||||
| `allowed-tools` | string[] | 全部 | 限制执行时可用的工具列表(如 `["Edit", "Read", "Bash"]`) |
|
||||
| `model` | string | 继承 | 覆盖使用的模型 ID(如 `"claude-sonnet-4-20250514"`) |
|
||||
@@ -123,11 +123,14 @@ json_output:
|
||||
- 完整的执行指南、API 调用、错误处理、权限要求
|
||||
- 标题格式:`## L2:详细规范`
|
||||
|
||||
### 分层加载机制
|
||||
### L0/L1/L2 与加载机制
|
||||
|
||||
- `disable-model-invocation: true` 时:L0 + L1 自动注入 system prompt(按需加载完整内容,减少 system prompt 体积)
|
||||
- `disable-model-invocation: false` 时:L0 + L1 + L2 完整内容注入 system prompt
|
||||
- 不分层时:整段内容作为 fallback
|
||||
L0/L1/L2 是 SKILL.md **内容组织约定**(Claude Skills 风格),帮助作者把摘要、原则、详细规范分层书写。**运行时并不在 L0/L1/L2 之间做"按需加载"**——一旦 skill 被加载,就是整篇 SKILL.md 内容(除 frontmatter)注入 system prompt。
|
||||
|
||||
是否被自动加载由 `disable-model-invocation` 决定:
|
||||
|
||||
- `disable-model-invocation: false` 时:skill 被加入自动加载列表,整篇内容随 system prompt 注入
|
||||
- `disable-model-invocation: true` 或缺省时:skill 不自动加载,仅当 Agent 显式调用 `Skill` 工具传入此 skill ID 时才加载
|
||||
|
||||
## 完整示例
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 更新智能体
|
||||
name: update-agent
|
||||
description: >-
|
||||
安全更新现有智能体的配置、人格、原则、技能与记忆,输出可审阅 diff 并在确认后应用与提交。Use when 用户要求修改 Agent
|
||||
行为、安装/卸载技能、调整配置、回滚变更或修订规则。
|
||||
@@ -15,6 +15,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-03-17'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 更新智能体
|
||||
short_desc: 安全更新智能体配置、人格、规则与技能,支持 diff 预览与版本回滚
|
||||
description: >-
|
||||
安全更新现有智能体的配置、人格、原则、技能与记忆,输出可审阅 diff 并在确认后应用与提交。Use when 用户要求修改 Agent 行为、安装/卸载技能、调整配置、回滚变更或修订规则。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:a0fecd84f92204bd
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Update Agent
|
||||
short_desc: Safely update Agent config, persona, principles, and skills, with diff preview and version rollback
|
||||
description: >-
|
||||
Safely update an existing Agent's config, persona, principles, skills, and memory, producing reviewable diffs that are applied and committed only after confirmation. Use when the user asks to modify Agent behavior, install/uninstall skills, adjust config, roll back changes, or revise rules.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:a0fecd84f92204bd
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -29,7 +52,6 @@ market:
|
||||
16.53.92-.38m.01-2.3-.92-.38m1.5-1.24-.38-.92m0
|
||||
5.54-.38.92m2.3.01.38-.92m.3-4.84-.38-.92m1.24 1.5.92-.38m0 2.3.92.38"
|
||||
stroke="#AF52DE" stroke-width="1.3" stroke-linecap="round"/></svg>
|
||||
short_desc: 安全更新智能体配置、人格、规则与技能,支持 diff 预览与版本回滚
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -38,45 +60,45 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# update-agent 技能
|
||||
# update-agent skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-Sentence Summary
|
||||
|
||||
通过自然语言对话,安全地修改 Agent 的配置、人格、规则和技能。
|
||||
Safely modify an Agent's config, persona, rules, and skills through natural-language conversation.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
update-agent 是一个**元技能(Meta-Skill)**,允许用户通过对话方式修改 Agent 的各项配置。所有修改都会生成可审阅的 diff 补丁,经用户确认后才会应用,并支持版本回滚。
|
||||
update-agent is a **Meta-Skill** that lets users modify various Agent configurations through conversation. All modifications produce reviewable diff patches that are applied only after user confirmation, with rollback support.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想要调整 Agent 的沟通风格("说话再正式一点")
|
||||
- 需要添加新的行为规则("以后遇到敏感话题要先提醒我")
|
||||
- 安装或卸载技能包("学会写合同吧")
|
||||
- 批量更新多项配置("全面升级一下你的能力")
|
||||
- The user wants to adjust the Agent's communication style ("speak more formally")
|
||||
- Add new behavioral rules ("from now on, warn me before discussing sensitive topics")
|
||||
- Install or uninstall skill packages ("learn how to write contracts")
|
||||
- Batch-update multiple settings ("upgrade all your capabilities")
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **安全可控**:所有变更需用户确认,支持回滚
|
||||
- **透明可见**:变更以 diff 形式展示,清晰明了
|
||||
- **版本管理**:通过 Git 管理版本,可追溯历史
|
||||
- **Safe and controllable**: All changes require user confirmation, with rollback support
|
||||
- **Transparent and visible**: Changes are presented as diffs, clear and obvious
|
||||
- **Version management**: Versions are managed via Git, with traceable history
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 支持的更新类型
|
||||
### Supported Update Types
|
||||
|
||||
| 更新类型 | 目标文件 | 风险等级 | 示例 |
|
||||
| --------------- | --------------- | -------- | -------------------- |
|
||||
| Persona 更新 | `persona.md` | 中 | 修改沟通风格、价值观 |
|
||||
| Principles 更新 | `principles.md` | 高 | 添加/修改行为规则 |
|
||||
| Skills 安装 | `skills/` | 中 | 添加新技能包 |
|
||||
| Skills 卸载 | `skills/` | 低 | 移除技能包 |
|
||||
| Memory 更新 | `memory/` | 低 | 添加知识条目 |
|
||||
| Tools 配置 | `tools/` | 高 | 修改工具权限 |
|
||||
| Update Type | Target File | Risk Level | Example |
|
||||
| ------------------ | --------------- | ---------- | -------------------------------------- |
|
||||
| Persona update | `persona.md` | Medium | Modify communication style, values |
|
||||
| Principles update | `principles.md` | High | Add/modify behavioral rules |
|
||||
| Skills install | `skills/` | Medium | Add new skill package |
|
||||
| Skills uninstall | `skills/` | Low | Remove skill package |
|
||||
| Memory update | `memory/` | Low | Add knowledge entry |
|
||||
| Tools config | `tools/` | High | Modify tool permissions |
|
||||
|
||||
### 对话流程
|
||||
### Conversation Flow
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
@@ -89,40 +111,40 @@ update-agent 是一个**元技能(Meta-Skill)**,允许用户通过对话
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:意图识别
|
||||
### Stage 1: Intent Recognition
|
||||
|
||||
**触发条件**(任一满足):
|
||||
**Trigger conditions** (any one is sufficient):
|
||||
|
||||
- 用户说"修改你的..."、"更新你的..."、"调整一下..."
|
||||
- 用户说"你以后要..."、"记住这个规则..."
|
||||
- 用户说"安装/卸载这个技能..."
|
||||
- 用户描述对当前行为的不满并期望改变
|
||||
- The user says "modify your...", "update your...", "adjust the..."
|
||||
- The user says "from now on you should...", "remember this rule..."
|
||||
- The user says "install/uninstall this skill..."
|
||||
- The user describes dissatisfaction with current behavior and expects a change
|
||||
|
||||
**输出**:识别更新类型和目标范围。
|
||||
**Output**: Identify the update type and target scope.
|
||||
|
||||
### 阶段 2:变更分析
|
||||
### Stage 2: Change Analysis
|
||||
|
||||
**分析维度**:
|
||||
**Analysis dimensions**:
|
||||
|
||||
| 维度 | 说明 |
|
||||
| -------- | ------------------------ |
|
||||
| 影响范围 | 影响哪些文件、哪些行为 |
|
||||
| 风险等级 | 低/中/高(见风险分级表) |
|
||||
| 依赖检查 | 是否影响其他配置 |
|
||||
| 冲突检测 | 是否与现有规则冲突 |
|
||||
| Dimension | Description |
|
||||
| ------------------- | -------------------------------------------- |
|
||||
| Scope of impact | Which files and behaviors are affected |
|
||||
| Risk level | Low/Medium/High (see risk classification) |
|
||||
| Dependency check | Whether other configs are affected |
|
||||
| Conflict detection | Whether it conflicts with existing rules |
|
||||
|
||||
**风险分级表**:
|
||||
**Risk classification table**:
|
||||
|
||||
| 风险等级 | 条件 | 确认要求 |
|
||||
| -------- | ------------------------------ | ---------------------- |
|
||||
| 低 | 仅影响非核心配置(如记忆条目) | 简单确认 |
|
||||
| 中 | 影响 persona 或普通 principles | 展示 diff 后确认 |
|
||||
| 高 | 影响核心 principles 或工具权限 | 详细说明 + diff + 确认 |
|
||||
| 受保护 | 触及受保护路径 | 阻断,需 owner 权限 |
|
||||
| Risk Level | Conditions | Confirmation Requirement |
|
||||
| ----------- | ------------------------------------------------ | ------------------------------------- |
|
||||
| Low | Affects only non-core config (e.g. memory entry) | Simple confirmation |
|
||||
| Medium | Affects persona or normal principles | Show diff, then confirm |
|
||||
| High | Affects core principles or tool permissions | Detailed explanation + diff + confirm |
|
||||
| Protected | Touches a protected path | Block; requires owner permission |
|
||||
|
||||
### 阶段 3:Diff 生成
|
||||
### Stage 3: Diff Generation
|
||||
|
||||
**Diff 格式示例**:
|
||||
**Diff format example**:
|
||||
|
||||
```diff
|
||||
# persona.md
|
||||
@@ -137,7 +159,7 @@ update-agent 是一个**元技能(Meta-Skill)**,允许用户通过对话
|
||||
保持不变...
|
||||
```
|
||||
|
||||
**Diff 元数据**:
|
||||
**Diff metadata**:
|
||||
|
||||
```yaml
|
||||
diff_metadata:
|
||||
@@ -149,9 +171,9 @@ diff_metadata:
|
||||
estimated_impact: '沟通风格会变得更正式'
|
||||
```
|
||||
|
||||
### 阶段 4:用户确认
|
||||
### Stage 4: User Confirmation
|
||||
|
||||
**确认界面**:
|
||||
**Confirmation interface**:
|
||||
|
||||
```
|
||||
变更预览
|
||||
@@ -168,44 +190,44 @@ diff_metadata:
|
||||
[应用] [取消] [修改]
|
||||
```
|
||||
|
||||
**确认选项**:
|
||||
**Confirmation options**:
|
||||
|
||||
- **应用**:执行变更
|
||||
- **取消**:放弃变更
|
||||
- **修改**:进入编辑模式微调
|
||||
- **Apply**: Execute the change
|
||||
- **Cancel**: Discard the change
|
||||
- **Modify**: Enter edit mode for fine-tuning
|
||||
|
||||
### 阶段 5:变更应用
|
||||
### Stage 5: Apply Changes
|
||||
|
||||
通过 AgentFS 直接读写文件完成变更。**不要调用 HTTP API,不要直接操作 Git**(版本管理由后端自动处理)。
|
||||
Apply the change by reading and writing files directly through AgentFS. **Do not call HTTP APIs, and do not operate Git directly** (version management is handled automatically by the backend).
|
||||
|
||||
**AgentFS 根目录**:`~/.desirecore/agents/<agentId>/`
|
||||
**AgentFS root directory**: `~/.desirecore/agents/<agentId>/`
|
||||
|
||||
**读取文件**:使用 `cat` 命令读取目标文件当前内容。
|
||||
**Read file**: Use the `cat` command to read the current contents of the target file.
|
||||
|
||||
**写入文件**:使用文本编辑工具直接写入目标文件。写入后重新读取文件确认内容正确。
|
||||
**Write file**: Use a text-editing tool to write directly to the target file. After writing, re-read the file to verify the contents are correct.
|
||||
|
||||
**注意**:直接写入文件后,后端文件监控会自动检测变更并触发 Git 提交,无需手动执行 git 命令。
|
||||
**Note**: After writing the file directly, the backend file watcher automatically detects the change and triggers a Git commit; no manual git command is required.
|
||||
|
||||
### 阶段 6:回执生成
|
||||
### Stage 6: Receipt Generation
|
||||
|
||||
创建成功后,以用户友好的方式呈现回执(不要暴露内部路径或技术细节):
|
||||
After a successful change, present a user-friendly receipt (do not expose internal paths or technical details):
|
||||
|
||||
> 已更新「法律顾问小助手」的沟通风格。
|
||||
> Updated the communication style of "Legal Advisor Assistant".
|
||||
>
|
||||
> **变更摘要**:沟通风格从"友好随和"调整为"专业严谨"
|
||||
> **Change summary**: Communication style adjusted from "friendly and casual" to "professional and rigorous"
|
||||
>
|
||||
> 如果不满意,可以随时说"撤销刚才的修改"来回滚。
|
||||
> If you're not satisfied, you can say "undo the previous change" anytime to roll back.
|
||||
|
||||
### 特殊操作:版本回滚
|
||||
### Special Operation: Version Rollback
|
||||
|
||||
**触发条件**:用户说"撤销刚才的修改"、"回滚到之前的版本"、"恢复原来的设置"
|
||||
**Trigger conditions**: The user says "undo the previous change", "roll back to the previous version", "restore the original settings"
|
||||
|
||||
**回滚流程**:
|
||||
**Rollback flow**:
|
||||
|
||||
1. 在 Agent 目录下执行 `git log --oneline -10` 查看最近的版本历史
|
||||
2. 使用 `git show <commit>:<file>` 获取目标版本的文件内容,展示给用户确认
|
||||
3. 用户确认后,将目标版本内容写入对应文件
|
||||
4. 展示变更 diff,确认回滚成功
|
||||
1. Run `git log --oneline -10` in the Agent directory to view recent version history
|
||||
2. Use `git show <commit>:<file>` to fetch the file contents of the target version, and present them to the user for confirmation
|
||||
3. After user confirmation, write the target version's contents to the corresponding file
|
||||
4. Show the change diff and confirm rollback success
|
||||
|
||||
```bash
|
||||
# 查看版本历史
|
||||
@@ -216,50 +238,50 @@ git log --oneline -10
|
||||
git show <commit>:persona.md
|
||||
```
|
||||
|
||||
### 背景知识
|
||||
### Background Knowledge
|
||||
|
||||
> AgentFS 仓库结构与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
> AgentFS repository structure and protected paths are detailed in `_agentfs-background.md` and `_protected-paths.yaml`.
|
||||
|
||||
**更新操作对照表**:
|
||||
**Update operation reference table**:
|
||||
|
||||
| 用户意图 | 目标文件 | AgentFS 路径 |
|
||||
| -------------- | --------------- | ---------------------------------------------- |
|
||||
| 修改性格/风格 | `persona.md` | `~/.desirecore/agents/<agentId>/persona.md` |
|
||||
| 修改行为规则 | `principles.md` | `~/.desirecore/agents/<agentId>/principles.md` |
|
||||
| 安装/卸载技能 | `skills/` | `~/.desirecore/agents/<agentId>/skills/` |
|
||||
| 修改工具配置 | `tools/` | `~/.desirecore/agents/<agentId>/tools/` |
|
||||
| 添加记忆 | `memory/` | `~/.desirecore/agents/<agentId>/memory/` |
|
||||
| 修改运行时配置 | `agent.json` | `~/.desirecore/agents/<agentId>/agent.json` |
|
||||
| User Intent | Target File | AgentFS Path |
|
||||
| ---------------------------- | --------------- | ---------------------------------------------- |
|
||||
| Modify personality/style | `persona.md` | `~/.desirecore/agents/<agentId>/persona.md` |
|
||||
| Modify behavioral rules | `principles.md` | `~/.desirecore/agents/<agentId>/principles.md` |
|
||||
| Install/uninstall skills | `skills/` | `~/.desirecore/agents/<agentId>/skills/` |
|
||||
| Modify tools config | `tools/` | `~/.desirecore/agents/<agentId>/tools/` |
|
||||
| Add memory | `memory/` | `~/.desirecore/agents/<agentId>/memory/` |
|
||||
| Modify runtime config | `agent.json` | `~/.desirecore/agents/<agentId>/agent.json` |
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| ------------------ | -------------------------------------- |
|
||||
| 尝试修改受保护路径 | 阻断操作,提示需要 owner 权限 |
|
||||
| 文件不存在 | Agent 或目标文件不存在,提示用户检查 |
|
||||
| 权限不足 | 文件系统权限错误,提示用户检查目录权限 |
|
||||
| 回滚版本不存在 | 列出可用版本,请用户重新选择 |
|
||||
| Error Scenario | Handling |
|
||||
| ----------------------------------- | -------------------------------------------------------- |
|
||||
| Attempt to modify a protected path | Block the operation; prompt that owner permission is required |
|
||||
| File does not exist | The Agent or target file does not exist; ask user to check |
|
||||
| Insufficient permission | Filesystem permission error; ask user to check directory permissions |
|
||||
| Rollback target version not found | List available versions and ask the user to reselect |
|
||||
|
||||
### 权限要求
|
||||
### Permission Requirements
|
||||
|
||||
| 操作 | 所需角色 |
|
||||
| --------------------------- | ------------- |
|
||||
| 更新 persona | owner, member |
|
||||
| 更新 principles(普通规则) | owner, member |
|
||||
| 更新 principles(安全红线) | owner |
|
||||
| 安装/卸载 skills | owner, member |
|
||||
| 修改 tools 权限 | owner |
|
||||
| 版本回滚 | owner |
|
||||
| Operation | Required Role |
|
||||
| -------------------------------------- | -------------- |
|
||||
| Update persona | owner, member |
|
||||
| Update principles (normal rules) | owner, member |
|
||||
| Update principles (safety red lines) | owner |
|
||||
| Install/uninstall skills | owner, member |
|
||||
| Modify tools permissions | owner |
|
||||
| Version rollback | owner |
|
||||
|
||||
---
|
||||
|
||||
## 附录:更新示例
|
||||
## Appendix: Update Examples
|
||||
|
||||
### Persona 修改示例
|
||||
### Persona Modification Example
|
||||
|
||||
**用户输入**:"说话再正式一点,不要太随意"
|
||||
**User input**: "Speak a bit more formally, not too casual"
|
||||
|
||||
**操作流程**:
|
||||
**Operation flow**:
|
||||
|
||||
```bash
|
||||
# 1. 读取当前 persona.md
|
||||
@@ -287,13 +309,13 @@ cat ~/.desirecore/agents/legal-assistant/persona.md
|
||||
|
||||
---
|
||||
|
||||
### Principles 更新示例
|
||||
### Principles Update Example
|
||||
|
||||
### 添加新规则
|
||||
### Add New Rule
|
||||
|
||||
**用户输入**:"以后遇到法律问题,先提醒我找专业律师"
|
||||
**User input**: "From now on, when there's a legal issue, remind me to consult a professional lawyer"
|
||||
|
||||
**生成的 Diff**:
|
||||
**Generated diff**:
|
||||
|
||||
```diff
|
||||
# principles.md
|
||||
@@ -308,11 +330,11 @@ cat ~/.desirecore/agents/legal-assistant/persona.md
|
||||
...
|
||||
```
|
||||
|
||||
### 修改现有规则
|
||||
### Modify Existing Rule
|
||||
|
||||
**用户输入**:"不要每次都提醒我,太啰嗦了"
|
||||
**User input**: "Don't remind me every time, it's too verbose"
|
||||
|
||||
**生成的 Diff**:
|
||||
**Generated diff**:
|
||||
|
||||
```diff
|
||||
# principles.md
|
||||
|
||||
286
skills/update-agent/SKILL.zh-CN.md
Normal file
286
skills/update-agent/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,286 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# update-agent 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
通过自然语言对话,安全地修改 Agent 的配置、人格、规则和技能。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
update-agent 是一个**元技能(Meta-Skill)**,允许用户通过对话方式修改 Agent 的各项配置。所有修改都会生成可审阅的 diff 补丁,经用户确认后才会应用,并支持版本回滚。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想要调整 Agent 的沟通风格("说话再正式一点")
|
||||
- 需要添加新的行为规则("以后遇到敏感话题要先提醒我")
|
||||
- 安装或卸载技能包("学会写合同吧")
|
||||
- 批量更新多项配置("全面升级一下你的能力")
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **安全可控**:所有变更需用户确认,支持回滚
|
||||
- **透明可见**:变更以 diff 形式展示,清晰明了
|
||||
- **版本管理**:通过 Git 管理版本,可追溯历史
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 支持的更新类型
|
||||
|
||||
| 更新类型 | 目标文件 | 风险等级 | 示例 |
|
||||
| --------------- | --------------- | -------- | -------------------- |
|
||||
| Persona 更新 | `persona.md` | 中 | 修改沟通风格、价值观 |
|
||||
| Principles 更新 | `principles.md` | 高 | 添加/修改行为规则 |
|
||||
| Skills 安装 | `skills/` | 中 | 添加新技能包 |
|
||||
| Skills 卸载 | `skills/` | 低 | 移除技能包 |
|
||||
| Memory 更新 | `memory/` | 低 | 添加知识条目 |
|
||||
| Tools 配置 | `tools/` | 高 | 修改工具权限 |
|
||||
|
||||
### 对话流程
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 意图识别 │ ──→ │ 变更分析 │ ──→ │ Diff 生成 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
│
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 回执生成 │ ←── │ 变更应用 │ ←── │ 用户确认 │
|
||||
└──────────────┘ └──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:意图识别
|
||||
|
||||
**触发条件**(任一满足):
|
||||
|
||||
- 用户说"修改你的..."、"更新你的..."、"调整一下..."
|
||||
- 用户说"你以后要..."、"记住这个规则..."
|
||||
- 用户说"安装/卸载这个技能..."
|
||||
- 用户描述对当前行为的不满并期望改变
|
||||
|
||||
**输出**:识别更新类型和目标范围。
|
||||
|
||||
### 阶段 2:变更分析
|
||||
|
||||
**分析维度**:
|
||||
|
||||
| 维度 | 说明 |
|
||||
| -------- | ------------------------ |
|
||||
| 影响范围 | 影响哪些文件、哪些行为 |
|
||||
| 风险等级 | 低/中/高(见风险分级表) |
|
||||
| 依赖检查 | 是否影响其他配置 |
|
||||
| 冲突检测 | 是否与现有规则冲突 |
|
||||
|
||||
**风险分级表**:
|
||||
|
||||
| 风险等级 | 条件 | 确认要求 |
|
||||
| -------- | ------------------------------ | ---------------------- |
|
||||
| 低 | 仅影响非核心配置(如记忆条目) | 简单确认 |
|
||||
| 中 | 影响 persona 或普通 principles | 展示 diff 后确认 |
|
||||
| 高 | 影响核心 principles 或工具权限 | 详细说明 + diff + 确认 |
|
||||
| 受保护 | 触及受保护路径 | 阻断,需 owner 权限 |
|
||||
|
||||
### 阶段 3:Diff 生成
|
||||
|
||||
**Diff 格式示例**:
|
||||
|
||||
```diff
|
||||
# persona.md
|
||||
|
||||
## 沟通风格
|
||||
|
||||
- 友好、随和、轻松幽默
|
||||
+ 专业、严谨、适度幽默
|
||||
|
||||
## 决策偏好
|
||||
|
||||
保持不变...
|
||||
```
|
||||
|
||||
**Diff 元数据**:
|
||||
|
||||
```yaml
|
||||
diff_metadata:
|
||||
files_affected: 1
|
||||
lines_added: 1
|
||||
lines_removed: 1
|
||||
risk_level: medium
|
||||
reversible: true
|
||||
estimated_impact: '沟通风格会变得更正式'
|
||||
```
|
||||
|
||||
### 阶段 4:用户确认
|
||||
|
||||
**确认界面**:
|
||||
|
||||
```
|
||||
变更预览
|
||||
|
||||
影响文件: persona.md
|
||||
风险等级: 中
|
||||
影响说明: 沟通风格会从"友好随和"变为"专业严谨"
|
||||
|
||||
--- 变更内容 ---
|
||||
[展示 diff]
|
||||
----------------
|
||||
|
||||
请确认是否应用此变更?
|
||||
[应用] [取消] [修改]
|
||||
```
|
||||
|
||||
**确认选项**:
|
||||
|
||||
- **应用**:执行变更
|
||||
- **取消**:放弃变更
|
||||
- **修改**:进入编辑模式微调
|
||||
|
||||
### 阶段 5:变更应用
|
||||
|
||||
通过 AgentFS 直接读写文件完成变更。**不要调用 HTTP API,不要直接操作 Git**(版本管理由后端自动处理)。
|
||||
|
||||
**AgentFS 根目录**:`~/.desirecore/agents/<agentId>/`
|
||||
|
||||
**读取文件**:使用 `cat` 命令读取目标文件当前内容。
|
||||
|
||||
**写入文件**:使用文本编辑工具直接写入目标文件。写入后重新读取文件确认内容正确。
|
||||
|
||||
**注意**:直接写入文件后,后端文件监控会自动检测变更并触发 Git 提交,无需手动执行 git 命令。
|
||||
|
||||
### 阶段 6:回执生成
|
||||
|
||||
创建成功后,以用户友好的方式呈现回执(不要暴露内部路径或技术细节):
|
||||
|
||||
> 已更新「法律顾问小助手」的沟通风格。
|
||||
>
|
||||
> **变更摘要**:沟通风格从"友好随和"调整为"专业严谨"
|
||||
>
|
||||
> 如果不满意,可以随时说"撤销刚才的修改"来回滚。
|
||||
|
||||
### 特殊操作:版本回滚
|
||||
|
||||
**触发条件**:用户说"撤销刚才的修改"、"回滚到之前的版本"、"恢复原来的设置"
|
||||
|
||||
**回滚流程**:
|
||||
|
||||
1. 在 Agent 目录下执行 `git log --oneline -10` 查看最近的版本历史
|
||||
2. 使用 `git show <commit>:<file>` 获取目标版本的文件内容,展示给用户确认
|
||||
3. 用户确认后,将目标版本内容写入对应文件
|
||||
4. 展示变更 diff,确认回滚成功
|
||||
|
||||
```bash
|
||||
# 查看版本历史
|
||||
cd ~/.desirecore/agents/<agentId>
|
||||
git log --oneline -10
|
||||
|
||||
# 查看某个版本的文件内容
|
||||
git show <commit>:persona.md
|
||||
```
|
||||
|
||||
### 背景知识
|
||||
|
||||
> AgentFS 仓库结构与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
|
||||
**更新操作对照表**:
|
||||
|
||||
| 用户意图 | 目标文件 | AgentFS 路径 |
|
||||
| -------------- | --------------- | ---------------------------------------------- |
|
||||
| 修改性格/风格 | `persona.md` | `~/.desirecore/agents/<agentId>/persona.md` |
|
||||
| 修改行为规则 | `principles.md` | `~/.desirecore/agents/<agentId>/principles.md` |
|
||||
| 安装/卸载技能 | `skills/` | `~/.desirecore/agents/<agentId>/skills/` |
|
||||
| 修改工具配置 | `tools/` | `~/.desirecore/agents/<agentId>/tools/` |
|
||||
| 添加记忆 | `memory/` | `~/.desirecore/agents/<agentId>/memory/` |
|
||||
| 修改运行时配置 | `agent.json` | `~/.desirecore/agents/<agentId>/agent.json` |
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
| ------------------ | -------------------------------------- |
|
||||
| 尝试修改受保护路径 | 阻断操作,提示需要 owner 权限 |
|
||||
| 文件不存在 | Agent 或目标文件不存在,提示用户检查 |
|
||||
| 权限不足 | 文件系统权限错误,提示用户检查目录权限 |
|
||||
| 回滚版本不存在 | 列出可用版本,请用户重新选择 |
|
||||
|
||||
### 权限要求
|
||||
|
||||
| 操作 | 所需角色 |
|
||||
| --------------------------- | ------------- |
|
||||
| 更新 persona | owner, member |
|
||||
| 更新 principles(普通规则) | owner, member |
|
||||
| 更新 principles(安全红线) | owner |
|
||||
| 安装/卸载 skills | owner, member |
|
||||
| 修改 tools 权限 | owner |
|
||||
| 版本回滚 | owner |
|
||||
|
||||
---
|
||||
|
||||
## 附录:更新示例
|
||||
|
||||
### Persona 修改示例
|
||||
|
||||
**用户输入**:"说话再正式一点,不要太随意"
|
||||
|
||||
**操作流程**:
|
||||
|
||||
```bash
|
||||
# 1. 读取当前 persona.md
|
||||
cat ~/.desirecore/agents/legal-assistant/persona.md
|
||||
|
||||
# 输出示例:
|
||||
# # 法律顾问小助手
|
||||
# ## L0
|
||||
# 专业的法律咨询助手
|
||||
# ## L1
|
||||
# ### Role
|
||||
# 法律顾问
|
||||
# ### Personality
|
||||
# 友好、随和
|
||||
# ### Communication Style
|
||||
# 轻松幽默
|
||||
|
||||
# 2. 分析需要修改的部分,生成 diff 展示给用户确认
|
||||
|
||||
# 3. 用户确认后,直接编辑文件,将 Personality 和 Communication Style 修改为目标值
|
||||
|
||||
# 4. 验证写入结果
|
||||
cat ~/.desirecore/agents/legal-assistant/persona.md
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### Principles 更新示例
|
||||
|
||||
### 添加新规则
|
||||
|
||||
**用户输入**:"以后遇到法律问题,先提醒我找专业律师"
|
||||
|
||||
**生成的 Diff**:
|
||||
|
||||
```diff
|
||||
# principles.md
|
||||
|
||||
## 必须做
|
||||
|
||||
- 始终保持礼貌和尊重
|
||||
- 不确定时主动询问
|
||||
+ - 遇到法律相关问题时,提醒用户咨询专业律师
|
||||
|
||||
## 绝不做
|
||||
...
|
||||
```
|
||||
|
||||
### 修改现有规则
|
||||
|
||||
**用户输入**:"不要每次都提醒我,太啰嗦了"
|
||||
|
||||
**生成的 Diff**:
|
||||
|
||||
```diff
|
||||
# principles.md
|
||||
|
||||
## 必须做
|
||||
|
||||
- - 每次回答后都提醒用户检查内容
|
||||
+ - 仅在重要决策时提醒用户检查内容
|
||||
```
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 联网访问
|
||||
name: web-access
|
||||
description: >-
|
||||
Use this skill whenever the user needs to access information from the internet
|
||||
— searching for current information, fetching public web pages, browsing
|
||||
@@ -29,7 +29,28 @@ tags:
|
||||
- playwright
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-04-13'
|
||||
updated_at: '2026-05-03'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 联网访问
|
||||
short_desc: 联网搜索、网页抓取、登录态浏览器访问(CDP)、研究调研工作流
|
||||
description: 三层联网访问工具包——搜索公开页面、Jina 优化抓取、CDP 登录态浏览器访问。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:0ba170b3126a0823
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Web Access
|
||||
short_desc: Web search, page fetching, logged-in browser access via CDP, research workflows
|
||||
description: A three-layer web-access toolkit — search public pages, fetch heavy pages via Jina Reader, and reach logged-in sites via Chrome CDP.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:0ba170b3126a0823
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -46,7 +67,6 @@ market:
|
||||
stroke="#34C759" stroke-width="1.5" fill="#34C759"
|
||||
fill-opacity="0.12"/><path d="M20.5 20.5l2 2" stroke="#34C759"
|
||||
stroke-width="1.8" stroke-linecap="round"/></svg>
|
||||
short_desc: 联网搜索、网页抓取、登录态浏览器访问(CDP)、研究调研工作流
|
||||
category: research
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -54,38 +74,38 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# web-access 技能
|
||||
# web-access skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
三层联网访问工具包——搜索公开页面、Jina 优化抓取、CDP 登录态浏览器访问。
|
||||
A three-layer web-access toolkit — search public pages, optimize fetches via Jina Reader, and reach login-gated sites via Chrome CDP.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview & Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
web-access 是一个**流程型技能(Procedural Skill)**,提供三层互补的联网访问能力:Layer 1(WebSearch + WebFetch)用于公开页面;Layer 2(Jina Reader)用于 JS 渲染的重页面,默认节省 Token;Layer 3(Chrome CDP)用于需要登录态的站点(小红书/B站/微博/飞书/Twitter)。
|
||||
web-access is a **procedural skill** that provides three complementary layers of web access: Layer 1 (WebSearch + WebFetch) for public pages; Layer 2 (Jina Reader) for JS-rendered heavy pages, saving tokens by default; Layer 3 (Chrome CDP) for sites requiring a logged-in session (Xiaohongshu / Bilibili / Weibo / Feishu / Twitter).
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要搜索当前信息或研究特定主题
|
||||
- 用户需要抓取公开网页内容或技术文档
|
||||
- 用户需要访问登录态站点(小红书、B站、微博、飞书、Twitter 等)
|
||||
- 用户需要对比产品、聚合新闻或调查 API/库版本
|
||||
- The user needs to search for current information or research a specific topic
|
||||
- The user needs to fetch public web content or technical documentation
|
||||
- The user needs to access logged-in sites (Xiaohongshu, Bilibili, Weibo, Feishu, Twitter, etc.)
|
||||
- The user needs to compare products, aggregate news, or investigate API/library versions
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **三层递进**:从轻量搜索到重度 JS 渲染到登录态访问,按需选择
|
||||
- **Token 优化**:Jina Reader 默认减少 50-80% Token 消耗
|
||||
- **登录态复用**:通过 CDP 连接用户已登录的 Chrome,无需重复登录
|
||||
- **Three-layer progression**: from lightweight search to heavy JS rendering to logged-in access — pick on demand
|
||||
- **Token optimization**: Jina Reader cuts token usage by 50–80% by default
|
||||
- **Logged-in session reuse**: connect to the user's already-logged-in Chrome via CDP — no re-login required
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you complete a research task, you **MUST** cite all source URLs in your response. Distinguish between:
|
||||
- **Quoted facts**: directly from a fetched page → cite the URL
|
||||
- **Inferences**: your synthesis or analysis → mark as "(分析/推断)"
|
||||
- **Inferences**: your synthesis or analysis → mark as "(analysis/inference)"
|
||||
|
||||
If any fetch fails, explicitly tell the user which URL failed and which fallback you used.
|
||||
|
||||
@@ -93,7 +113,7 @@ If any fetch fails, explicitly tell the user which URL failed and which fallback
|
||||
|
||||
## Prerequisites: Chrome CDP Setup (for login-gated sites)
|
||||
|
||||
**Only required when accessing sites that need the user's login session** (小红书/B站/微博/飞书/Twitter/知乎/公众号).
|
||||
**Only required when accessing sites that need the user's login session** (Xiaohongshu / Bilibili / Weibo / Feishu / Twitter / Zhihu / WeChat Official Accounts).
|
||||
|
||||
### One-time setup
|
||||
|
||||
@@ -121,7 +141,7 @@ google-chrome \
|
||||
```
|
||||
|
||||
After launch:
|
||||
1. Manually log in to the sites you need (小红书、B站、微博、飞书 …)
|
||||
1. Manually log in to the sites you need (Xiaohongshu, Bilibili, Weibo, Feishu, …)
|
||||
2. Leave this Chrome window open in the background
|
||||
3. Verify the debug endpoint: `curl -s http://localhost:9222/json/version` should return JSON
|
||||
|
||||
@@ -132,7 +152,7 @@ Before any CDP operation, always run:
|
||||
curl -s http://localhost:9222/json/version | python3 -c "import sys,json; d=json.load(sys.stdin); print('CDP ready:', d.get('Browser'))"
|
||||
```
|
||||
|
||||
If the command fails, tell the user: "请先启动 Chrome 并开启远程调试端口(见 web-access 技能的 Prerequisites 部分)。"
|
||||
If the command fails, tell the user: "Please launch Chrome with the remote debugging port enabled (see the Prerequisites section of the web-access skill)."
|
||||
|
||||
---
|
||||
|
||||
@@ -151,7 +171,7 @@ User intent
|
||||
│ └─→ Bash: curl -sL "https://r.jina.ai/<original-url>"
|
||||
│ (Jina Reader = default for JS-rendered content, saves tokens)
|
||||
│
|
||||
├─ "Read this login-gated page" (小红书/B站/微博/飞书/Twitter/知乎/公众号)
|
||||
├─ "Read this login-gated page" (Xiaohongshu/Bilibili/Weibo/Feishu/Twitter/Zhihu/WeChat)
|
||||
│ └─→ 1. Verify CDP ready (curl http://localhost:9222/json/version)
|
||||
│ 2. Bash: python3 script with playwright.connect_over_cdp()
|
||||
│ 3. Extract content → feed to Jina Reader for clean Markdown
|
||||
@@ -188,13 +208,13 @@ User intent
|
||||
| Hacker News, Reddit | L1 WebFetch | Public content |
|
||||
| Medium, Dev.to | L2 Jina Reader | JS-rendered, member gates |
|
||||
| Twitter/X | L3 CDP (or L2 Jina with `x.com`) | Login required for full thread |
|
||||
| 小红书 (xiaohongshu.com) | L3 CDP | 强制登录 |
|
||||
| B站 (bilibili.com) | L3 CDP | 视频描述/评论需登录 |
|
||||
| 微博 (weibo.com) | L3 CDP | 长微博需登录 |
|
||||
| 知乎 (zhihu.com) | L3 CDP | 长文+评论需登录 |
|
||||
| 飞书文档 (feishu.cn) | L3 CDP | 必须登录 |
|
||||
| 公众号 (mp.weixin.qq.com) | L2 Jina Reader | 通常公开,Jina 处理更干净 |
|
||||
| LinkedIn | L3 CDP | 登录墙 |
|
||||
| Xiaohongshu (xiaohongshu.com) | L3 CDP | Login required |
|
||||
| Bilibili (bilibili.com) | L3 CDP | Login needed for video desc/comments |
|
||||
| Weibo (weibo.com) | L3 CDP | Long posts require login |
|
||||
| Zhihu (zhihu.com) | L3 CDP | Long articles + comments require login |
|
||||
| Feishu Docs (feishu.cn) | L3 CDP | Login required |
|
||||
| WeChat Official Accounts (mp.weixin.qq.com) | L2 Jina Reader | Usually public, Jina cleans better |
|
||||
| LinkedIn | L3 CDP | Login wall |
|
||||
|
||||
---
|
||||
|
||||
@@ -284,7 +304,7 @@ PY
|
||||
```
|
||||
|
||||
See [references/cdp-browser.md](references/cdp-browser.md) for:
|
||||
- Per-site selectors (小红书/B站/微博/知乎/飞书)
|
||||
- Per-site selectors (Xiaohongshu / Bilibili / Weibo / Zhihu / Feishu)
|
||||
- Scrolling & lazy-load patterns
|
||||
- Screenshot & form-fill recipes
|
||||
- Troubleshooting connection issues
|
||||
@@ -294,12 +314,12 @@ See [references/cdp-browser.md](references/cdp-browser.md) for:
|
||||
## Common Workflows
|
||||
|
||||
Read [references/workflows.md](references/workflows.md) for detailed templates:
|
||||
- 技术文档查询 (Tech docs lookup)
|
||||
- 竞品对比研究 (Competitor research)
|
||||
- 新闻聚合与时间线 (News aggregation)
|
||||
- API/库版本调查 (Library version investigation)
|
||||
- Tech docs lookup
|
||||
- Competitor research
|
||||
- News aggregation & timelines
|
||||
- API/library version investigation
|
||||
|
||||
Read [references/cdp-browser.md](references/cdp-browser.md) for login-gated site recipes (小红书/B站/微博/知乎/飞书).
|
||||
Read [references/cdp-browser.md](references/cdp-browser.md) for login-gated site recipes (Xiaohongshu / Bilibili / Weibo / Zhihu / Feishu).
|
||||
|
||||
Read [references/jina-reader.md](references/jina-reader.md) for Jina Reader positioning, rate limits, and advanced endpoints.
|
||||
|
||||
@@ -321,7 +341,7 @@ Read [references/jina-reader.md](references/jina-reader.md) for Jina Reader posi
|
||||
|
||||
## Anti-Patterns (Avoid)
|
||||
|
||||
- ❌ **Using WebFetch on obviously heavy sites** — Medium, Twitter, 小红书 will waste tokens or fail. Jump straight to L2/L3.
|
||||
- ❌ **Using WebFetch on obviously heavy sites** — Medium, Twitter, Xiaohongshu will waste tokens or fail. Jump straight to L2/L3.
|
||||
- ❌ **Launching headless Chrome instead of CDP attach** — loses user's login state, triggers anti-bot, slow cold start. Always use `connect_over_cdp()` to attach to the user's existing session.
|
||||
- ❌ **Fetching one URL at a time when you need 5** — batch in a single message.
|
||||
- ❌ **Trusting a single source** — cross-check ≥ 2 sources for non-trivial claims.
|
||||
@@ -336,20 +356,20 @@ Read [references/jina-reader.md](references/jina-reader.md) for Jina Reader posi
|
||||
|
||||
## Example Interaction
|
||||
|
||||
**User**: "帮我抓一下这条小红书笔记的内容:https://www.xiaohongshu.com/explore/abc123"
|
||||
**User**: "Grab the contents of this Xiaohongshu note for me: https://www.xiaohongshu.com/explore/abc123"
|
||||
|
||||
**Agent workflow**:
|
||||
```
|
||||
1. 识别 → 小红书是 L3 登录态站点
|
||||
2. 检查 CDP:curl -s http://localhost:9222/json/version
|
||||
├─ 失败 → 提示用户启动 Chrome 调试模式,终止
|
||||
└─ 成功 → 继续
|
||||
3. Bash: python3 connect_over_cdp 脚本 → page.goto(url) → page.content()
|
||||
4. BeautifulSoup 提取 h1 title、.note-content、.comments
|
||||
5. 返回给用户时:
|
||||
- 引用原 URL
|
||||
- 若内容很长,用 Jina 清洗一遍节省 token
|
||||
6. 告知用户:「已通过你的登录态抓取,原链接:[xhs](url)」
|
||||
1. Recognize → Xiaohongshu is an L3 logged-in site
|
||||
2. Check CDP: curl -s http://localhost:9222/json/version
|
||||
├─ Failure → prompt the user to launch Chrome in debug mode, abort
|
||||
└─ Success → continue
|
||||
3. Bash: python3 connect_over_cdp script → page.goto(url) → page.content()
|
||||
4. BeautifulSoup extract h1 title, .note-content, .comments
|
||||
5. When returning to the user:
|
||||
- Cite the original URL
|
||||
- If content is long, run it through Jina to save tokens
|
||||
6. Tell the user: "Fetched via your logged-in session, original link: [xhs](url)"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
312
skills/web-access/SKILL.zh-CN.md
Normal file
312
skills/web-access/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,312 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# web-access 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
三层联网访问工具包——搜索公开页面、Jina 优化抓取、CDP 登录态浏览器访问。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
web-access 是一个**流程型技能(Procedural Skill)**,提供三层互补的联网访问能力:Layer 1(WebSearch + WebFetch)用于公开页面;Layer 2(Jina Reader)用于 JS 渲染的重页面,默认节省 Token;Layer 3(Chrome CDP)用于需要登录态的站点(小红书/B站/微博/飞书/Twitter)。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要搜索当前信息或研究特定主题
|
||||
- 用户需要抓取公开网页内容或技术文档
|
||||
- 用户需要访问登录态站点(小红书、B站、微博、飞书、Twitter 等)
|
||||
- 用户需要对比产品、聚合新闻或调查 API/库版本
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **三层递进**:从轻量搜索到重度 JS 渲染到登录态访问,按需选择
|
||||
- **Token 优化**:Jina Reader 默认减少 50-80% Token 消耗
|
||||
- **登录态复用**:通过 CDP 连接用户已登录的 Chrome,无需重复登录
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you complete a research task, you **MUST** cite all source URLs in your response. Distinguish between:
|
||||
- **Quoted facts**: directly from a fetched page → cite the URL
|
||||
- **Inferences**: your synthesis or analysis → mark as "(分析/推断)"
|
||||
|
||||
If any fetch fails, explicitly tell the user which URL failed and which fallback you used.
|
||||
|
||||
---
|
||||
|
||||
## Prerequisites: Chrome CDP Setup (for login-gated sites)
|
||||
|
||||
**Only required when accessing sites that need the user's login session** (小红书/B站/微博/飞书/Twitter/知乎/公众号).
|
||||
|
||||
### One-time setup
|
||||
|
||||
Launch a dedicated Chrome instance with remote debugging enabled:
|
||||
|
||||
**macOS**:
|
||||
```bash
|
||||
/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome \
|
||||
--remote-debugging-port=9222 \
|
||||
--user-data-dir="$HOME/.desirecore/chrome-profile"
|
||||
```
|
||||
|
||||
**Linux**:
|
||||
```bash
|
||||
google-chrome \
|
||||
--remote-debugging-port=9222 \
|
||||
--user-data-dir="$HOME/.desirecore/chrome-profile"
|
||||
```
|
||||
|
||||
**Windows (PowerShell)**:
|
||||
```powershell
|
||||
& "C:\Program Files\Google\Chrome\Application\chrome.exe" `
|
||||
--remote-debugging-port=9222 `
|
||||
--user-data-dir="$env:USERPROFILE\.desirecore\chrome-profile"
|
||||
```
|
||||
|
||||
After launch:
|
||||
1. Manually log in to the sites you need (小红书、B站、微博、飞书 …)
|
||||
2. Leave this Chrome window open in the background
|
||||
3. Verify the debug endpoint: `curl -s http://localhost:9222/json/version` should return JSON
|
||||
|
||||
### Verify CDP is ready
|
||||
|
||||
Before any CDP operation, always run:
|
||||
```bash
|
||||
curl -s http://localhost:9222/json/version | python3 -c "import sys,json; d=json.load(sys.stdin); print('CDP ready:', d.get('Browser'))"
|
||||
```
|
||||
|
||||
If the command fails, tell the user: "请先启动 Chrome 并开启远程调试端口(见 web-access 技能的 Prerequisites 部分)。"
|
||||
|
||||
---
|
||||
|
||||
## Tool Selection Decision Tree
|
||||
|
||||
```
|
||||
User intent
|
||||
│
|
||||
├─ "Search for information about X" (no specific URL)
|
||||
│ └─→ WebSearch → pick top 3-5 results → fetch each (see next branches)
|
||||
│
|
||||
├─ "Read this public page" (static HTML, docs, news)
|
||||
│ └─→ WebFetch(url) directly
|
||||
│
|
||||
├─ "Read this heavy-JS page" (SPA, React/Vue sites, Medium, etc.)
|
||||
│ └─→ Bash: curl -sL "https://r.jina.ai/<original-url>"
|
||||
│ (Jina Reader = default for JS-rendered content, saves tokens)
|
||||
│
|
||||
├─ "Read this login-gated page" (小红书/B站/微博/飞书/Twitter/知乎/公众号)
|
||||
│ └─→ 1. Verify CDP ready (curl http://localhost:9222/json/version)
|
||||
│ 2. Bash: python3 script with playwright.connect_over_cdp()
|
||||
│ 3. Extract content → feed to Jina Reader for clean Markdown
|
||||
│ (or use BeautifulSoup directly on the raw HTML)
|
||||
│
|
||||
├─ "API documentation / GitHub / npm package info"
|
||||
│ └─→ Prefer official API endpoints over scraping HTML:
|
||||
│ - GitHub: gh api repos/owner/name
|
||||
│ - npm: curl https://registry.npmjs.org/<pkg>
|
||||
│ - PyPI: curl https://pypi.org/pypi/<pkg>/json
|
||||
│
|
||||
└─ "Real-time interactive task" (click, fill form, scroll, screenshot)
|
||||
└─→ CDP + Playwright (see references/cdp-browser.md)
|
||||
```
|
||||
|
||||
### Three-layer strategy summary
|
||||
|
||||
| Layer | Use case | Primary tool | Token cost |
|
||||
|-------|----------|--------------|------------|
|
||||
| L1 | Public, static | `WebFetch` | Low |
|
||||
| L2 | JS-heavy, long articles, token savings | `Bash curl r.jina.ai` | **Lowest** (Markdown pre-cleaned) |
|
||||
| L3 | Login-gated, interactive | `Bash + Python Playwright CDP` | Medium (raw HTML, then clean via Jina or BS4) |
|
||||
|
||||
**Default priority**: L1 for simple public pages → L2 for anything heavy → L3 only when login is required.
|
||||
|
||||
---
|
||||
|
||||
## Supported Sites Matrix
|
||||
|
||||
| Site | Recommended Layer | Notes |
|
||||
|------|-------------------|-------|
|
||||
| Wikipedia, MDN, official docs | L1 WebFetch | Static, clean HTML |
|
||||
| GitHub README, issues, PRs | `gh api` (best) → L1 WebFetch | Prefer API |
|
||||
| Hacker News, Reddit | L1 WebFetch | Public content |
|
||||
| Medium, Dev.to | L2 Jina Reader | JS-rendered, member gates |
|
||||
| Twitter/X | L3 CDP (or L2 Jina with `x.com`) | Login required for full thread |
|
||||
| 小红书 (xiaohongshu.com) | L3 CDP | 强制登录 |
|
||||
| B站 (bilibili.com) | L3 CDP | 视频描述/评论需登录 |
|
||||
| 微博 (weibo.com) | L3 CDP | 长微博需登录 |
|
||||
| 知乎 (zhihu.com) | L3 CDP | 长文+评论需登录 |
|
||||
| 飞书文档 (feishu.cn) | L3 CDP | 必须登录 |
|
||||
| 公众号 (mp.weixin.qq.com) | L2 Jina Reader | 通常公开,Jina 处理更干净 |
|
||||
| LinkedIn | L3 CDP | 登录墙 |
|
||||
|
||||
---
|
||||
|
||||
## Tool Reference
|
||||
|
||||
### Layer 1: WebSearch + WebFetch
|
||||
|
||||
**WebSearch** — discover URLs for an unknown topic:
|
||||
```
|
||||
WebSearch(query="latest typescript 5.5 features 2026", max_results=5)
|
||||
```
|
||||
|
||||
Tips:
|
||||
- Include the year for time-sensitive topics
|
||||
- Use `allowed_domains` / `blocked_domains` to constrain
|
||||
|
||||
**WebFetch** — extract clean Markdown from a known URL:
|
||||
```
|
||||
WebFetch(url="https://example.com/article")
|
||||
```
|
||||
|
||||
Tips:
|
||||
- Results cached for 15 min
|
||||
- Returns cleaned Markdown with title + URL + body
|
||||
- If body < 200 chars or looks garbled → escalate to Layer 2 (Jina) or Layer 3 (CDP)
|
||||
|
||||
### Layer 2: Jina Reader (default for heavy pages)
|
||||
|
||||
Jina Reader (`r.jina.ai`) is a free public proxy that renders pages server-side and returns clean Markdown. Use it as the **default** for any page where WebFetch produces garbled or truncated output, and as the **preferred** extractor for JS-heavy SPAs.
|
||||
|
||||
```bash
|
||||
curl -sL "https://r.jina.ai/https://example.com/article"
|
||||
```
|
||||
|
||||
Why Jina is the default token-saver:
|
||||
- Strips nav/footer/ads automatically
|
||||
- Handles JS-rendered SPAs
|
||||
- Returns 50-80% fewer tokens than raw HTML
|
||||
- No API key needed for basic use (~20 req/min)
|
||||
|
||||
See [references/jina-reader.md](references/jina-reader.md) for advanced endpoints and rate limits.
|
||||
|
||||
### Layer 3: CDP Browser (login-gated access)
|
||||
|
||||
Use Python Playwright's `connect_over_cdp()` to attach to the user's running Chrome (which already has login cookies). **No re-login needed.**
|
||||
|
||||
**Minimal template**:
|
||||
```bash
|
||||
python3 << 'PY'
|
||||
from playwright.sync_api import sync_playwright
|
||||
|
||||
TARGET_URL = "https://www.xiaohongshu.com/explore/..."
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.connect_over_cdp("http://localhost:9222")
|
||||
context = browser.contexts[0] # reuse user's default context (has cookies)
|
||||
page = context.new_page()
|
||||
page.goto(TARGET_URL, wait_until="domcontentloaded")
|
||||
page.wait_for_timeout(2000) # let lazy content load
|
||||
html = page.content()
|
||||
page.close()
|
||||
|
||||
# Print first 500 chars to verify
|
||||
print(html[:500])
|
||||
PY
|
||||
```
|
||||
|
||||
**Extract text via BeautifulSoup** (no Jina round-trip):
|
||||
```bash
|
||||
python3 << 'PY'
|
||||
from playwright.sync_api import sync_playwright
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
with sync_playwright() as p:
|
||||
browser = p.chromium.connect_over_cdp("http://localhost:9222")
|
||||
page = browser.contexts[0].new_page()
|
||||
page.goto("https://www.bilibili.com/video/BV...", wait_until="networkidle")
|
||||
html = page.content()
|
||||
page.close()
|
||||
|
||||
soup = BeautifulSoup(html, "html.parser")
|
||||
title = soup.select_one("h1.video-title")
|
||||
desc = soup.select_one(".video-desc")
|
||||
print("Title:", title.get_text(strip=True) if title else "N/A")
|
||||
print("Desc:", desc.get_text(strip=True) if desc else "N/A")
|
||||
PY
|
||||
```
|
||||
|
||||
See [references/cdp-browser.md](references/cdp-browser.md) for:
|
||||
- Per-site selectors (小红书/B站/微博/知乎/飞书)
|
||||
- Scrolling & lazy-load patterns
|
||||
- Screenshot & form-fill recipes
|
||||
- Troubleshooting connection issues
|
||||
|
||||
---
|
||||
|
||||
## Common Workflows
|
||||
|
||||
Read [references/workflows.md](references/workflows.md) for detailed templates:
|
||||
- 技术文档查询 (Tech docs lookup)
|
||||
- 竞品对比研究 (Competitor research)
|
||||
- 新闻聚合与时间线 (News aggregation)
|
||||
- API/库版本调查 (Library version investigation)
|
||||
|
||||
Read [references/cdp-browser.md](references/cdp-browser.md) for login-gated site recipes (小红书/B站/微博/知乎/飞书).
|
||||
|
||||
Read [references/jina-reader.md](references/jina-reader.md) for Jina Reader positioning, rate limits, and advanced endpoints.
|
||||
|
||||
---
|
||||
|
||||
## Quick Workflow: Multi-Source Research
|
||||
|
||||
```
|
||||
1. WebSearch(query) → 5 candidate URLs
|
||||
2. Skim titles + snippets → pick 3 most relevant
|
||||
3. Classify each URL by layer (L1 / L2 / L3)
|
||||
4. Fetch all in parallel (single message, multiple tool calls)
|
||||
5. If any fetch returns < 200 chars or garbled → retry via next layer
|
||||
6. Synthesize: contradictions? consensus? outliers?
|
||||
7. Report with inline [source](url) citations + a Sources list at the end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Anti-Patterns (Avoid)
|
||||
|
||||
- ❌ **Using WebFetch on obviously heavy sites** — Medium, Twitter, 小红书 will waste tokens or fail. Jump straight to L2/L3.
|
||||
- ❌ **Launching headless Chrome instead of CDP attach** — loses user's login state, triggers anti-bot, slow cold start. Always use `connect_over_cdp()` to attach to the user's existing session.
|
||||
- ❌ **Fetching one URL at a time when you need 5** — batch in a single message.
|
||||
- ❌ **Trusting a single source** — cross-check ≥ 2 sources for non-trivial claims.
|
||||
- ❌ **Fetching the search result page itself** — WebSearch already returns snippets; fetch the actual articles.
|
||||
- ❌ **Ignoring the cache** — WebFetch caches 15 min, reuse freely.
|
||||
- ❌ **Scraping when an API exists** — GitHub, npm, PyPI, Wikipedia all have JSON APIs.
|
||||
- ❌ **Forgetting the year in time-sensitive queries** — "best AI models" returns 2023 results; "best AI models 2026" returns current.
|
||||
- ❌ **Hardcoding login credentials in scripts** — always rely on the user's pre-logged CDP session.
|
||||
- ❌ **Citing only after the fact** — collect URLs as you fetch, not from memory afterwards.
|
||||
|
||||
---
|
||||
|
||||
## Example Interaction
|
||||
|
||||
**User**: "帮我抓一下这条小红书笔记的内容:https://www.xiaohongshu.com/explore/abc123"
|
||||
|
||||
**Agent workflow**:
|
||||
```
|
||||
1. 识别 → 小红书是 L3 登录态站点
|
||||
2. 检查 CDP:curl -s http://localhost:9222/json/version
|
||||
├─ 失败 → 提示用户启动 Chrome 调试模式,终止
|
||||
└─ 成功 → 继续
|
||||
3. Bash: python3 connect_over_cdp 脚本 → page.goto(url) → page.content()
|
||||
4. BeautifulSoup 提取 h1 title、.note-content、.comments
|
||||
5. 返回给用户时:
|
||||
- 引用原 URL
|
||||
- 若内容很长,用 Jina 清洗一遍节省 token
|
||||
6. 告知用户:「已通过你的登录态抓取,原链接:[xhs](url)」
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Installation Note
|
||||
|
||||
CDP features require Python + Playwright installed:
|
||||
|
||||
```bash
|
||||
pip3 install playwright beautifulsoup4
|
||||
python3 -m playwright install chromium # only needed if user hasn't installed Chrome
|
||||
```
|
||||
|
||||
If `playwright` is not installed when the user requests a login-gated site, run the install commands in Bash and explain you're setting up the browser automation dependency.
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 工作流编排
|
||||
name: workflow
|
||||
description: >-
|
||||
引导 Agent 设计、编辑、测试和执行 Workflow 工作流。Use when
|
||||
用户要求创建工作流、编排多步骤自动化流程、设计审批流水线、
|
||||
@@ -17,6 +17,29 @@ tags:
|
||||
metadata:
|
||||
author: desirecore
|
||||
updated_at: '2026-05-04'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 工作流编排
|
||||
short_desc: 引导设计、编辑、测试和执行多节点自动化工作流
|
||||
description: >-
|
||||
引导 Agent 设计、编辑、测试和执行 Workflow 工作流。Use when 用户要求创建工作流、编排多步骤自动化流程、设计审批流水线、 或将重复性多节点任务编排成可复用的 DSL。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:aa197c62ae8a33d7
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Workflow Orchestration
|
||||
short_desc: Guide the design, editing, testing, and execution of multi-node automated workflows
|
||||
description: >-
|
||||
Guides the Agent to design, edit, test, and execute Workflow workflows. Use when the user asks to create a workflow, orchestrate multi-step automation, design an approval pipeline, or turn repetitive multi-node tasks into a reusable DSL.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:aa197c62ae8a33d7
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-04'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -35,7 +58,6 @@ market:
|
||||
stroke-width="1.5" stroke-linecap="round"/><line x1="12" y1="14.5"
|
||||
x2="12" y2="17.5" stroke="url(#wf-a)" stroke-width="1.5"
|
||||
stroke-linecap="round"/></svg>
|
||||
short_desc: 引导设计、编辑、测试和执行多节点自动化工作流
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -51,99 +73,101 @@ requires:
|
||||
- Bash
|
||||
---
|
||||
|
||||
# workflow 技能
|
||||
# workflow Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
引导 Agent 通过 DSL 设计、编辑、校验、测试和执行多节点自动化工作流。
|
||||
Guides the Agent to design, edit, validate, test, and execute multi-node automated workflows via a DSL.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability Description
|
||||
|
||||
workflow 是一个**流程型技能(Procedural Skill)**,赋予 Agent 编排多步骤自动化工作流的能力。工作流以 YAML DSL 文件描述,由引擎按拓扑顺序自动执行。
|
||||
workflow is a **Procedural Skill** that empowers the Agent to orchestrate multi-step automated workflows. Workflows are described by a YAML DSL file and are automatically executed by the engine in topological order.
|
||||
|
||||
**五种基座节点**:
|
||||
**Five base node types**:
|
||||
|
||||
| 基座 | 用途 | 典型场景 |
|
||||
|------|------|---------|
|
||||
| `trigger` | 工作流入口,声明输入参数 | 手动触发、webhook 触发 |
|
||||
| `code` | 执行代码(JS/Python) | 数据获取、API 调用 |
|
||||
| `llm` | 单次 LLM 调用(无状态) | 文本生成、数据分析、摘要 |
|
||||
| `agent` | 调用完整 Agent(有状态) | 需要 Agent 记忆、工具、技能的复杂任务 |
|
||||
| `human_gate` | 等待用户确认 | 敏感操作审批 |
|
||||
| Base | Purpose | Typical Scenario |
|
||||
|------|---------|------------------|
|
||||
| `trigger` | Workflow entry point, declares input parameters | Manual trigger, webhook trigger |
|
||||
| `code` | Executes code (JS/Python) | Data fetching, API calls |
|
||||
| `llm` | Single LLM call (stateless) | Text generation, data analysis, summarization |
|
||||
| `agent` | Invokes a full Agent (stateful) | Complex tasks requiring Agent memory, tools, and skills |
|
||||
| `human_gate` | Waits for user confirmation | Approval of sensitive operations |
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户想把重复性多步骤工作编排成自动化流程
|
||||
- 用户需要多个 Agent 协作完成一个复杂任务
|
||||
- 用户需要在自动化流程中插入人工审批环节
|
||||
- 用户想复用和分享已验证的工作流程
|
||||
- The user wants to orchestrate repetitive multi-step work into an automated process
|
||||
- The user needs multiple Agents to collaborate on a complex task
|
||||
- The user needs to insert manual approval steps into an automated process
|
||||
- The user wants to reuse and share validated workflows
|
||||
|
||||
### 核心价值
|
||||
### Core Value
|
||||
|
||||
- **可视化编排**:DSL 描述清晰直观,支持画布可视化
|
||||
- **渐进式构建**:先写骨架再逐步丰富,降低出错概率
|
||||
- **安全门控**:通过 human_gate 节点在关键环节保留人工决策权
|
||||
- **可复用**:DSL 文件可存档、版本管理、跨 Agent 共享
|
||||
- **Visual orchestration**: The DSL description is clear and intuitive, with canvas visualization support
|
||||
- **Progressive construction**: Write the skeleton first and gradually enrich it, reducing the chance of errors
|
||||
- **Safety gating**: Use human_gate nodes to retain human decision-making authority at critical steps
|
||||
- **Reusability**: DSL files can be archived, version-controlled, and shared across Agents
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
### 工作流程 SOP
|
||||
### Workflow SOP
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 1. 理解意图 │ ──→ │ 2a. 设计拓扑 │ ──→ │ 2b. 逐节点配置 │ ──→ │ 3. 校验 DSL │
|
||||
└──────────────┘ │ (节点骨架) │ │ (config/code)│ └──────────────┘
|
||||
│ 1. Understand│ ──→ │ 2a. Design │ ──→ │ 2b. Configure │ ──→ │ 3. Validate │
|
||||
│ intent │ │ topology │ │ each node │ │ DSL │
|
||||
└──────────────┘ │ (skeleton) │ │ (config/code) │ └──────────────┘
|
||||
└──────────────┘ └──────────────┘ │
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ 5. 正式执行 │ ←── │ 4. 干跑测试 │
|
||||
└──────────────┘ └──────────────┘
|
||||
│ 5. Real run │ ←── │ 4. Dry-run │
|
||||
└──────────────┘ │ testing │
|
||||
└──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:理解意图
|
||||
### Phase 1: Understand Intent
|
||||
|
||||
**触发条件**(任一满足):
|
||||
- 用户明确说"创建一个工作流"或"帮我编排一个流程"
|
||||
- 用户描述一个需要多步骤、多角色协作的任务
|
||||
- 用户想把手动重复的操作自动化
|
||||
**Trigger conditions** (any one is sufficient):
|
||||
- The user explicitly says "create a workflow" or "help me orchestrate a process"
|
||||
- The user describes a task that requires multi-step, multi-role collaboration
|
||||
- The user wants to automate manual repetitive operations
|
||||
|
||||
**收集信息**:
|
||||
**Information to collect**:
|
||||
|
||||
| 信息 | 说明 | 引导问题 |
|
||||
|------|------|---------|
|
||||
| 目标 | 工作流要完成什么 | "这个流程最终要产出什么?" |
|
||||
| 步骤 | 大致有哪些环节 | "你通常是怎么做的?分几步?" |
|
||||
| 审批 | 哪些环节需要人工确认 | "有哪些步骤需要你亲自过目确认?" |
|
||||
| Agent | 是否需要调用特定 Agent | "有没有已有的 Agent 可以参与?" |
|
||||
| Information | Description | Guiding Question |
|
||||
|-------------|-------------|------------------|
|
||||
| Goal | What the workflow should accomplish | "What is the final output of this process?" |
|
||||
| Steps | Roughly which stages are involved | "How do you usually do it? How many steps?" |
|
||||
| Approval | Which steps require manual confirmation | "Which steps require you to personally review and confirm?" |
|
||||
| Agent | Whether a specific Agent needs to be invoked | "Are there existing Agents that can participate?" |
|
||||
|
||||
### 阶段 2:渐进式构建 DSL
|
||||
### Phase 2: Progressive DSL Construction
|
||||
|
||||
**DSL 文件位置**:
|
||||
**DSL file location**:
|
||||
|
||||
```
|
||||
~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
其中 `wf_id` 使用 `wf_` 前缀 + snake_case,如 `wf_legal_review`、`wf_daily_report`。
|
||||
Where `wf_id` uses a `wf_` prefix + snake_case, e.g. `wf_legal_review`, `wf_daily_report`.
|
||||
|
||||
**构建策略**:严格分两步——先设计节点拓扑,再逐节点填充配置。**禁止在骨架阶段编写节点的 config 和 code 细节。**
|
||||
**Construction strategy**: Strictly two steps — first design the node topology, then fill in the configuration node by node. **Do not write node config or code details during the skeleton phase.**
|
||||
|
||||
#### 步骤 2a:设计节点拓扑(骨架)
|
||||
#### Step 2a: Design Node Topology (Skeleton)
|
||||
|
||||
先与用户对齐整体流程设计,确认后使用 Write 工具一次性创建骨架 DSL 文件。骨架用于对齐拓扑,不要求立即通过 `WorkflowValidate`;最终完整 DSL 写入时优先使用 `WorkflowCreate`。
|
||||
First align with the user on the overall process design. After confirmation, use the Write tool to create the skeleton DSL file in one shot. The skeleton is for aligning topology and is not required to immediately pass `WorkflowValidate`; when writing the final complete DSL, prefer using `WorkflowCreate`.
|
||||
|
||||
**骨架只包含**:
|
||||
- 根字段(version、id、name、description、creator)
|
||||
- 每个节点的 `id`、`base`、`display.name`
|
||||
- 每个节点的 `outputs`(声明变量名和描述)
|
||||
- `flow`(start、edges、end)
|
||||
**The skeleton contains only**:
|
||||
- Root fields (version, id, name, description, creator)
|
||||
- Each node's `id`, `base`, `display.name`
|
||||
- Each node's `outputs` (declaring variable names and descriptions)
|
||||
- `flow` (start, edges, end)
|
||||
|
||||
**骨架不包含**:config 内容(code / system_prompt / task / prompt 等)、inputs 引用。
|
||||
**The skeleton does not contain**: config content (code / system_prompt / task / prompt, etc.), inputs references.
|
||||
|
||||
```yaml
|
||||
# 骨架示例——只有结构,没有实现细节
|
||||
# Skeleton example — only structure, no implementation details
|
||||
version: "1.0"
|
||||
id: wf_daily_report
|
||||
name: 每日报告生成
|
||||
@@ -167,7 +191,7 @@ nodes:
|
||||
base: code
|
||||
display:
|
||||
name: 获取数据
|
||||
config: {} # 待步骤 2b 填充
|
||||
config: {} # To be filled in step 2b
|
||||
outputs:
|
||||
raw_data: "原始数据"
|
||||
|
||||
@@ -175,7 +199,7 @@ nodes:
|
||||
base: llm
|
||||
display:
|
||||
name: AI 分析
|
||||
config: {} # 待步骤 2b 填充
|
||||
config: {} # To be filled in step 2b
|
||||
outputs:
|
||||
report: "分析报告"
|
||||
|
||||
@@ -183,7 +207,7 @@ nodes:
|
||||
base: human_gate
|
||||
display:
|
||||
name: 人工审阅
|
||||
config: {} # 待步骤 2b 填充
|
||||
config: {} # To be filled in step 2b
|
||||
outputs:
|
||||
decision: "审批决定"
|
||||
comment: "审批备注"
|
||||
@@ -192,7 +216,7 @@ nodes:
|
||||
base: code
|
||||
display:
|
||||
name: 发送报告
|
||||
config: {} # 待步骤 2b 填充
|
||||
config: {} # To be filled in step 2b
|
||||
outputs:
|
||||
status: "发送状态"
|
||||
|
||||
@@ -206,57 +230,57 @@ flow:
|
||||
end: [send]
|
||||
```
|
||||
|
||||
骨架创建后,向用户确认节点设计和流程是否正确,再进入步骤 2b。
|
||||
After creating the skeleton, confirm with the user that the node design and process are correct, then proceed to step 2b.
|
||||
|
||||
#### 步骤 2b:逐节点填充配置
|
||||
#### Step 2b: Fill Node Configurations One by One
|
||||
|
||||
按拓扑顺序(从 trigger 开始,沿 edges 方向)逐个节点填充 config 和 inputs。每完成一个节点使用 Edit 工具写入,**不要一次性填充所有节点**。
|
||||
In topological order (starting from trigger and following the edges direction), fill in `config` and `inputs` for each node one at a time. Use the Edit tool to write each completed node — **do not fill in all nodes at once**.
|
||||
|
||||
**每个节点填充内容**:
|
||||
1. `inputs` — 引用上游节点的输出(`{{nodeId.outputKey}}`)
|
||||
2. `config` — 该基座类型的具体配置:
|
||||
- **code 节点**:编写 `runtime` 和 `code`(完整的可执行代码)
|
||||
- **llm 节点**:编写 `system_prompt`、选择 `model` / `provider`、设置 `temperature` 等参数
|
||||
- **agent 节点**:指定 `agent_id` 和编写 `task` 描述
|
||||
- **human_gate 节点**:编写审批 `prompt`(含 `{{}}` 插值)
|
||||
**Content to fill in for each node**:
|
||||
1. `inputs` — references to upstream node outputs (`{{nodeId.outputKey}}`)
|
||||
2. `config` — the specific configuration for that base type:
|
||||
- **code node**: write `runtime` and `code` (complete executable code)
|
||||
- **llm node**: write `system_prompt`, choose `model` / `provider`, set parameters such as `temperature`
|
||||
- **agent node**: specify `agent_id` and write the `task` description
|
||||
- **human_gate node**: write the approval `prompt` (with `{{}}` interpolation)
|
||||
|
||||
**逐节点填充顺序示例**(以上方骨架为例):
|
||||
**Example fill order, node by node** (using the skeleton above):
|
||||
|
||||
```
|
||||
1. fetch_data — 编写获取数据的 JS/Python 代码
|
||||
2. analyze — 编写 system_prompt,选择模型,配置 inputs 引用 fetch_data 输出
|
||||
3. review — 编写审批提示词,配置 inputs 引用 analyze 输出
|
||||
4. send — 编写发送逻辑的代码,配置 inputs 引用 review 输出
|
||||
1. fetch_data — write JS/Python code to fetch data
|
||||
2. analyze — write system_prompt, choose model, configure inputs to reference fetch_data outputs
|
||||
3. review — write the approval prompt, configure inputs to reference analyze outputs
|
||||
4. send — write the sending logic code, configure inputs to reference review outputs
|
||||
```
|
||||
|
||||
填充完所有节点后进入阶段 3 校验。
|
||||
After all nodes are filled in, proceed to phase 3 validation.
|
||||
|
||||
### DSL 编写规范
|
||||
### DSL Authoring Specification
|
||||
|
||||
#### 根结构
|
||||
#### Root Structure
|
||||
|
||||
```yaml
|
||||
version: "1.0" # 固定值
|
||||
id: wf_<snake_case_name> # 必须以 wf_ 前缀开头
|
||||
name: 工作流显示名称 # 人类可读名称
|
||||
description: 工作流用途描述 # 可选,说明适用场景
|
||||
creator: <agent_id> # 创建此工作流的 Agent ID
|
||||
version: "1.0" # Fixed value
|
||||
id: wf_<snake_case_name> # Must start with the wf_ prefix
|
||||
name: 工作流显示名称 # Human-readable name
|
||||
description: 工作流用途描述 # Optional, describing the applicable scenario
|
||||
creator: <agent_id> # ID of the Agent that created this workflow
|
||||
|
||||
nodes: # 节点列表(至少 1 个)
|
||||
nodes: # Node list (at least 1)
|
||||
- id: ...
|
||||
base: ...
|
||||
...
|
||||
|
||||
flow: # 流程控制
|
||||
start: <起始节点 id>
|
||||
flow: # Flow control
|
||||
start: <starting node id>
|
||||
edges:
|
||||
- { from: <节点 id>, to: <节点 id> }
|
||||
end: [<终止节点 id>]
|
||||
- { from: <node id>, to: <node id> }
|
||||
end: [<ending node id>]
|
||||
```
|
||||
|
||||
#### code 节点配置
|
||||
#### code Node Configuration
|
||||
|
||||
code 节点执行**内联代码**(JS 或 Python),通过 `inputs` 对象访问上游数据,通过 `return` 返回结果。
|
||||
A code node executes **inline code** (JS or Python), accesses upstream data via the `inputs` object, and returns results via `return`.
|
||||
|
||||
```yaml
|
||||
- id: format_data
|
||||
@@ -264,10 +288,10 @@ code 节点执行**内联代码**(JS 或 Python),通过 `inputs` 对象访
|
||||
display:
|
||||
name: 格式化数据
|
||||
config:
|
||||
runtime: nodejs # nodejs 或 python
|
||||
timeout_ms: 30000 # 超时毫秒数(可选,默认 30000)
|
||||
runtime: nodejs # nodejs or python
|
||||
timeout_ms: 30000 # Timeout in milliseconds (optional, default 30000)
|
||||
code: |
|
||||
// inputs 对象包含所有上游传入的数据
|
||||
// The inputs object contains all data passed in from upstream
|
||||
const data = JSON.parse(inputs.raw_data)
|
||||
const formatted = data.map(item => ({
|
||||
title: item.title.trim(),
|
||||
@@ -275,32 +299,32 @@ code 节点执行**内联代码**(JS 或 Python),通过 `inputs` 对象访
|
||||
}))
|
||||
return { formatted: JSON.stringify(formatted) }
|
||||
inputs:
|
||||
raw_data: "{{fetch_node.result}}" # 引用上游节点 fetch_node 的 result 输出
|
||||
raw_data: "{{fetch_node.result}}" # Reference the result output of the upstream fetch_node
|
||||
outputs:
|
||||
formatted: "格式化后的数据"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
**config field descriptions**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `runtime` | 是 | `nodejs` 或 `python` |
|
||||
| `code` | 是 | 内联代码。JS 通过 `inputs` 对象访问输入,`return` 返回输出对象。Python 同理。 |
|
||||
| `timeout_ms` | 否 | 执行超时(默认 30000ms) |
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `runtime` | Yes | `nodejs` or `python` |
|
||||
| `code` | Yes | Inline code. JS accesses inputs via the `inputs` object and returns the output object via `return`. Python is the same. |
|
||||
| `timeout_ms` | No | Execution timeout (default 30000ms) |
|
||||
|
||||
**JS 代码注意事项**:
|
||||
- 代码在 `new Function('inputs', ...)` 中执行,支持 `async/await` 和 `fetch`
|
||||
- **不支持 `require()`**,不能导入 Node.js 模块
|
||||
- 通过 `inputs.xxx` 访问输入数据
|
||||
- 必须 `return` 一个对象,其 key 对应 `outputs` 中声明的变量名
|
||||
**Notes for JS code**:
|
||||
- The code is executed inside `new Function('inputs', ...)`, supporting `async/await` and `fetch`
|
||||
- **`require()` is not supported**; you cannot import Node.js modules
|
||||
- Access input data via `inputs.xxx`
|
||||
- Must `return` an object whose keys match the variable names declared in `outputs`
|
||||
|
||||
**Python 代码注意事项**:
|
||||
- 通过 `inputs['xxx']` 访问输入数据
|
||||
- 必须 `return` 一个字典
|
||||
**Notes for Python code**:
|
||||
- Access input data via `inputs['xxx']`
|
||||
- Must `return` a dictionary
|
||||
|
||||
#### llm 节点配置
|
||||
#### llm Node Configuration
|
||||
|
||||
llm 节点执行**单次无状态 LLM 调用**,适用于文本生成、数据分析、摘要等场景。与 agent 节点的区别是不涉及 Agent 的记忆、工具和技能。
|
||||
An llm node performs a **single stateless LLM call**, suitable for text generation, data analysis, summarization, and similar scenarios. The difference from an agent node is that it does not involve the Agent's memory, tools, or skills.
|
||||
|
||||
```yaml
|
||||
- id: summarize
|
||||
@@ -308,33 +332,33 @@ llm 节点执行**单次无状态 LLM 调用**,适用于文本生成、数据
|
||||
display:
|
||||
name: AI 摘要
|
||||
config:
|
||||
provider: anthropic # 供应商名称(可选,精确匹配)
|
||||
model: claude-sonnet-4-6 # 模型(可选,不填使用默认)
|
||||
system_prompt: "你是摘要助手" # 系统提示词
|
||||
max_tokens: 2048 # 最大 token
|
||||
temperature: 0.3 # 温度(可选)
|
||||
reasoning: medium # 思维链级别(可选)
|
||||
provider: anthropic # Provider name (optional, exact match)
|
||||
model: claude-sonnet-4-6 # Model (optional, default is used if not set)
|
||||
system_prompt: "你是摘要助手" # System prompt
|
||||
max_tokens: 2048 # Max tokens
|
||||
temperature: 0.3 # Temperature (optional)
|
||||
reasoning: medium # Reasoning level (optional)
|
||||
inputs:
|
||||
data: "{{fetch_data.result}}"
|
||||
outputs:
|
||||
summary: "摘要文本"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
**config field descriptions**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `system_prompt` | 是 | 系统提示词,定义 LLM 的角色和行为 |
|
||||
| `provider` | 否 | 供应商名称(如 `anthropic`、`openai`),精确匹配已配置的供应商。不填则由系统自动匹配 |
|
||||
| `model` | 否 | 指定模型,不填使用默认模型 |
|
||||
| `max_tokens` | 否 | 最大输出 token 数 |
|
||||
| `temperature` | 否 | 温度参数(0-2),控制输出随机性 |
|
||||
| `reasoning` | 否 | 思维链级别:`low` / `medium` / `high`。开启后模型先推理再回答,适合复杂分析任务 |
|
||||
| `output_schema` | 否 | JSON Schema 对象。设置后 LLM 将尝试返回符合 Schema 的结构化 JSON |
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `system_prompt` | Yes | System prompt that defines the LLM's role and behavior |
|
||||
| `provider` | No | Provider name (e.g. `anthropic`, `openai`), exact match against configured providers. If not set, the system matches automatically |
|
||||
| `model` | No | Specifies the model; defaults to the system default if not set |
|
||||
| `max_tokens` | No | Max number of output tokens |
|
||||
| `temperature` | No | Temperature parameter (0-2), controls output randomness |
|
||||
| `reasoning` | No | Reasoning level: `low` / `medium` / `high`. When enabled, the model reasons before answering, suitable for complex analytical tasks |
|
||||
| `output_schema` | No | A JSON Schema object. When set, the LLM tries to return structured JSON conforming to the schema |
|
||||
|
||||
#### agent 节点配置
|
||||
#### agent Node Configuration
|
||||
|
||||
agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的专业知识、记忆、工具或技能的复杂任务。
|
||||
An agent node invokes a **full Agent** (stateful), suitable for complex tasks that require the Agent's domain knowledge, memory, tools, or skills.
|
||||
|
||||
```yaml
|
||||
- id: legal_review
|
||||
@@ -342,22 +366,22 @@ agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的
|
||||
display:
|
||||
name: 法律审核
|
||||
config:
|
||||
agent_id: legal-advisor # 必填:目标 Agent ID
|
||||
task: "审核以下内容:{{summarize.summary}}" # 任务描述
|
||||
agent_id: legal-advisor # Required: target Agent ID
|
||||
task: "审核以下内容:{{summarize.summary}}" # Task description
|
||||
inputs:
|
||||
content: "{{summarize.summary}}"
|
||||
outputs:
|
||||
review: "审核意见"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
**config field descriptions**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `agent_id` | 是 | 目标 Agent 的 ID |
|
||||
| `task` | 是 | 交给 Agent 的任务描述,支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}` 插值 |
|
||||
| Field | Required | Description |
|
||||
|-------|----------|-------------|
|
||||
| `agent_id` | Yes | ID of the target Agent |
|
||||
| `task` | Yes | Task description handed to the Agent. Supports `{{nodeId.outputKey}}`, `{{trigger.key}}`, and `{{secrets.keyName}}` interpolation |
|
||||
|
||||
#### human_gate 节点配置
|
||||
#### human_gate Node Configuration
|
||||
|
||||
```yaml
|
||||
- id: approval
|
||||
@@ -381,26 +405,26 @@ agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的
|
||||
comment: "审批备注"
|
||||
```
|
||||
|
||||
#### llm vs agent 选择指南
|
||||
#### llm vs agent Selection Guide
|
||||
|
||||
| 场景 | 推荐基座 | 理由 |
|
||||
|------|---------|------|
|
||||
| 文本摘要、翻译、格式转换 | `llm` | 单次调用,不需要 Agent 上下文 |
|
||||
| 数据分析、信息提取 | `llm` | 无状态处理即可完成 |
|
||||
| 需要专业知识的审核 | `agent` | 需要 Agent 的领域知识和记忆 |
|
||||
| 需要调用外部工具 | `agent` | 需要 Agent 的工具能力 |
|
||||
| 多轮推理、复杂决策 | `agent` | 需要 Agent 的完整推理链 |
|
||||
| Scenario | Recommended Base | Reason |
|
||||
|----------|------------------|--------|
|
||||
| Text summarization, translation, format conversion | `llm` | Single call, no Agent context required |
|
||||
| Data analysis, information extraction | `llm` | Stateless processing is sufficient |
|
||||
| Review requiring domain expertise | `agent` | Requires the Agent's domain knowledge and memory |
|
||||
| Calling external tools | `agent` | Requires the Agent's tool capability |
|
||||
| Multi-turn reasoning, complex decisions | `agent` | Requires the Agent's full reasoning chain |
|
||||
|
||||
**简单判断**:如果任务可以用一段 system prompt + 一次输入完成,用 `llm`;如果任务需要 Agent 的记忆、工具或技能,用 `agent`。
|
||||
**Quick rule**: If the task can be completed with a single system prompt + one input, use `llm`; if the task requires the Agent's memory, tools, or skills, use `agent`.
|
||||
|
||||
#### trigger 节点
|
||||
#### trigger Node
|
||||
|
||||
每个工作流**必须有且仅有一个** trigger 节点,作为工作流入口。`flow.start` 必须指向 trigger 节点。
|
||||
Each workflow **must have exactly one** trigger node, serving as the workflow entry point. `flow.start` must point to the trigger node.
|
||||
|
||||
**规则**:
|
||||
- trigger 节点**无 inputs**
|
||||
- trigger 节点的 outputs 使用结构化格式(`type` / `description` / `required` / `default`),声明工作流接受的输入参数
|
||||
- `config.type` 指定触发方式:`manual`(手动触发)或 `webhook`(外部触发)
|
||||
**Rules**:
|
||||
- A trigger node **has no inputs**
|
||||
- A trigger node's outputs use the structured format (`type` / `description` / `required` / `default`) to declare the input parameters the workflow accepts
|
||||
- `config.type` specifies the trigger method: `manual` (manual trigger) or `webhook` (external trigger)
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
@@ -412,13 +436,13 @@ agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的
|
||||
type: manual # manual | webhook
|
||||
outputs:
|
||||
param_name:
|
||||
type: string # 参数类型:string / number / boolean / object / array
|
||||
type: string # Parameter type: string / number / boolean / object / array
|
||||
description: "参数描述"
|
||||
required: true # 是否必填
|
||||
default: "默认值" # 可选,未传入时的默认值
|
||||
required: true # Whether required
|
||||
default: "默认值" # Optional, default value when not provided
|
||||
```
|
||||
|
||||
**示例**——带多个参数的 trigger:
|
||||
**Example** — a trigger with multiple parameters:
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
@@ -440,44 +464,44 @@ agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的
|
||||
default: "zh-CN"
|
||||
```
|
||||
|
||||
下游节点通过 `{{trigger.paramName}}` 引用 trigger 输出的参数值。
|
||||
Downstream nodes reference the parameter values output by the trigger via `{{trigger.paramName}}`.
|
||||
|
||||
#### inputs 格式规范
|
||||
#### inputs Format Specification
|
||||
|
||||
inputs 使用**对象映射格式**——key 为本节点的变量名,value 为数据来源引用:
|
||||
inputs uses an **object map format** — keys are the variable names within this node, and values are references to data sources:
|
||||
|
||||
```yaml
|
||||
# 引用其他节点的输出
|
||||
# Reference outputs of other nodes
|
||||
inputs:
|
||||
varName: "{{nodeId.outputKey}}"
|
||||
|
||||
# 引用触发参数
|
||||
# Reference trigger parameters
|
||||
inputs:
|
||||
query: "{{trigger.userQuery}}"
|
||||
|
||||
# 引用用户级 secret
|
||||
# Reference user-level secrets
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
|
||||
# 多个输入
|
||||
# Multiple inputs
|
||||
inputs:
|
||||
title: "{{extract.title}}"
|
||||
body: "{{extract.body}}"
|
||||
metadata: "{{trigger.metadata}}"
|
||||
```
|
||||
|
||||
**禁止使用数组格式**:
|
||||
**Array format is forbidden**:
|
||||
|
||||
```yaml
|
||||
# 错误!不要用数组
|
||||
# Wrong! Do not use arrays
|
||||
inputs:
|
||||
- name: varName
|
||||
source: nodeId.outputKey
|
||||
```
|
||||
|
||||
#### outputs 格式规范
|
||||
#### outputs Format Specification
|
||||
|
||||
outputs 使用**对象映射格式**——key 为输出变量名,value 为描述文本:
|
||||
outputs uses an **object map format** — keys are output variable names, and values are description text:
|
||||
|
||||
```yaml
|
||||
outputs:
|
||||
@@ -485,151 +509,151 @@ outputs:
|
||||
summary: "结果摘要"
|
||||
```
|
||||
|
||||
#### flow 定义
|
||||
#### flow Definition
|
||||
|
||||
```yaml
|
||||
flow:
|
||||
start: first_node # 起始节点 ID
|
||||
edges: # 边列表(定义执行顺序)
|
||||
start: first_node # Starting node ID
|
||||
edges: # Edge list (defines execution order)
|
||||
- { from: first_node, to: second_node }
|
||||
- { from: second_node, to: third_node }
|
||||
- from: third_node # 条件分支(可选)
|
||||
- from: third_node # Conditional branch (optional)
|
||||
to: branch_a
|
||||
condition: "risk_level == 'high'"
|
||||
end: [final_node] # 终止节点列表
|
||||
end: [final_node] # List of terminal nodes
|
||||
```
|
||||
|
||||
#### 变量引用体系
|
||||
#### Variable Reference System
|
||||
|
||||
DSL 中所有动态值统一使用 `{{}}` 模板语法引用:
|
||||
All dynamic values in the DSL are uniformly referenced using the `{{}}` template syntax:
|
||||
|
||||
| 语法 | 来源 | 示例 |
|
||||
|------|------|------|
|
||||
| `{{nodeId.outputKey}}` | 前置节点输出 | `{{summarize.summary}}` |
|
||||
| `{{trigger.key}}` | 触发时传入的参数 | `{{trigger.filePath}}` |
|
||||
| `{{secrets.keyName}}` | 用户级 secret | `{{secrets.dingtalk_token}}` |
|
||||
| Syntax | Source | Example |
|
||||
|--------|--------|---------|
|
||||
| `{{nodeId.outputKey}}` | Output of a preceding node | `{{summarize.summary}}` |
|
||||
| `{{trigger.key}}` | Parameters passed in at trigger time | `{{trigger.filePath}}` |
|
||||
| `{{secrets.keyName}}` | User-level secret | `{{secrets.dingtalk_token}}` |
|
||||
|
||||
**适用位置**:`inputs` 的值、`config.prompt` 中的插值均使用此语法。
|
||||
**Applicable locations**: This syntax is used both in `inputs` values and in interpolations within `config.prompt`.
|
||||
|
||||
#### Secrets 引用
|
||||
#### Secrets References
|
||||
|
||||
工作流可通过 `{{secrets.keyName}}` 引用用户预配置的密钥,用于 API 调用等场景。
|
||||
A workflow can reference user-preconfigured secrets via `{{secrets.keyName}}` for scenarios such as API calls.
|
||||
|
||||
- Secrets 由用户在 `~/.desirecore/config/secrets.json` 中预配置
|
||||
- 引擎在运行时自动解析 `{{secrets.*}}`,将其替换为实际值
|
||||
- Secrets 仅在执行阶段解析,校验和干跑阶段不会暴露实际值
|
||||
- Secrets are preconfigured by the user in `~/.desirecore/config/secrets.json`
|
||||
- The engine automatically resolves `{{secrets.*}}` at runtime, replacing them with the actual values
|
||||
- Secrets are resolved only during the execution phase; their actual values are not exposed during validation or dry-run
|
||||
|
||||
```yaml
|
||||
# 在 inputs 中引用 secret
|
||||
# Reference a secret in inputs
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
webhook_url: "{{secrets.dingtalk_webhook}}"
|
||||
|
||||
# 在 config.prompt 中引用 secret(不推荐,仅特殊场景)
|
||||
# Reference a secret in config.prompt (not recommended, only for special cases)
|
||||
config:
|
||||
prompt: "使用 token {{secrets.github_token}} 访问仓库"
|
||||
```
|
||||
|
||||
### 阶段 3:校验 DSL
|
||||
### Phase 3: Validate the DSL
|
||||
|
||||
使用 `WorkflowValidate` 工具校验 DSL 文件的结构和引用完整性。
|
||||
Use the `WorkflowValidate` tool to validate the structure and reference integrity of the DSL file.
|
||||
|
||||
**调用方式**:
|
||||
**How to call**:
|
||||
|
||||
```
|
||||
工具:WorkflowValidate
|
||||
参数:
|
||||
Tool: WorkflowValidate
|
||||
Parameters:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
**校验内容**:
|
||||
- YAML 语法正确性
|
||||
- JSON Schema 合规性(必填字段、类型、格式)
|
||||
- 节点 ID 唯一性
|
||||
- 边的引用有效性(from/to 均指向已存在的节点)
|
||||
- 起始节点和终止节点存在
|
||||
- 无环检测(DAG 校验)
|
||||
- inputs 引用的上游节点和输出字段存在
|
||||
**What is validated**:
|
||||
- YAML syntax correctness
|
||||
- JSON Schema compliance (required fields, types, formats)
|
||||
- Uniqueness of node IDs
|
||||
- Validity of edge references (from/to both point to existing nodes)
|
||||
- The starting and terminal nodes exist
|
||||
- Cycle detection (DAG validation)
|
||||
- The upstream nodes and output fields referenced by inputs exist
|
||||
|
||||
**校验通过** → 进入阶段 4
|
||||
**校验失败** → 根据错误信息用 Edit 工具修复,重新校验
|
||||
**Validation passes** → Proceed to phase 4
|
||||
**Validation fails** → Fix using the Edit tool based on the error information, then re-validate
|
||||
|
||||
### 阶段 4:干跑测试
|
||||
### Phase 4: Dry-run Testing
|
||||
|
||||
使用 `WorkflowTest` 工具进行模拟执行(dry-run),不实际调用 Agent 或执行代码。
|
||||
Use the `WorkflowTest` tool to perform a simulated execution (dry-run) without actually invoking Agents or executing code.
|
||||
|
||||
**调用方式**:
|
||||
**How to call**:
|
||||
|
||||
```
|
||||
工具:WorkflowTest
|
||||
参数:
|
||||
Tool: WorkflowTest
|
||||
Parameters:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,用于模拟 trigger 参数
|
||||
params: # Optional, used to simulate trigger parameters
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**测试内容**:
|
||||
- 验证拓扑排序是否成功
|
||||
- 模拟数据在节点间的流转路径
|
||||
- 检查所有 inputs 引用在运行时是否可解析
|
||||
- 输出执行计划预览(节点执行顺序)
|
||||
**What is tested**:
|
||||
- Verifies whether topological sorting succeeds
|
||||
- Simulates the data flow path between nodes
|
||||
- Checks whether all inputs references can be resolved at runtime
|
||||
- Outputs an execution plan preview (node execution order)
|
||||
|
||||
**测试通过** → 向用户确认是否正式执行
|
||||
**测试失败** → 根据错误信息修复,重新测试
|
||||
**Test passes** → Confirm with the user whether to perform a real run
|
||||
**Test fails** → Fix based on the error information, then retest
|
||||
|
||||
### 阶段 5:正式执行
|
||||
### Phase 5: Real Execution
|
||||
|
||||
使用 `WorkflowRun` 工具启动工作流。
|
||||
Use the `WorkflowRun` tool to start the workflow.
|
||||
|
||||
**调用方式**:
|
||||
**How to call**:
|
||||
|
||||
```
|
||||
工具:WorkflowRun
|
||||
参数:
|
||||
Tool: WorkflowRun
|
||||
Parameters:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,作为 {{trigger.key}} 上下文传入
|
||||
params: # Optional, passed in as the {{trigger.key}} context
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**执行过程**:
|
||||
- 引擎按拓扑顺序逐节点执行
|
||||
- 实时通过 SSE 推送节点状态变更事件
|
||||
- 遇到 human_gate 节点时暂停,等待用户审批
|
||||
- 所有终止节点完成后,返回最终结果
|
||||
**Execution process**:
|
||||
- The engine executes nodes one by one in topological order
|
||||
- Node status change events are pushed in real time via SSE
|
||||
- When a human_gate node is encountered, execution pauses and waits for user approval
|
||||
- After all terminal nodes complete, the final result is returned
|
||||
|
||||
**执行完成后**:
|
||||
- 向用户展示执行结果摘要
|
||||
- 如有失败节点,说明失败原因和建议修复方式
|
||||
**After execution completes**:
|
||||
- Show the user a summary of the execution result
|
||||
- If there are failed nodes, explain the cause of failure and recommended fixes
|
||||
|
||||
### 注意事项
|
||||
### Notes
|
||||
|
||||
1. **workflow_id 命名**:必须以 `wf_` 前缀开头,使用 snake_case,如 `wf_contract_review`
|
||||
2. **严格分步构建**:步骤 2a 只写节点拓扑骨架(不含 config/code),确认后步骤 2b 按拓扑顺序逐节点填充配置,禁止一次性写完所有细节
|
||||
3. **输入输出格式**:inputs 和 outputs 必须使用对象映射格式(`{ key: value }`),不要用数组
|
||||
4. **变量插值**:inputs、llm/agent/human_gate 的 prompt / system_prompt / task 支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}`
|
||||
5. **校验先行**:正式执行前务必先校验再干跑测试,减少运行时错误
|
||||
6. **人工门控**:涉及重要决策(如发布、付款、删除)的步骤,建议使用 human_gate 节点
|
||||
1. **workflow_id naming**: Must start with the `wf_` prefix and use snake_case, e.g. `wf_contract_review`
|
||||
2. **Strict step-by-step construction**: Step 2a writes only the node topology skeleton (without config/code); after confirmation, step 2b fills in configurations node by node in topological order. Do not write all details in one go
|
||||
3. **Input/output format**: inputs and outputs must use the object map format (`{ key: value }`); do not use arrays
|
||||
4. **Variable interpolation**: inputs and the prompt / system_prompt / task fields of llm/agent/human_gate support `{{nodeId.outputKey}}`, `{{trigger.key}}`, and `{{secrets.keyName}}`
|
||||
5. **Validate first**: Always validate before performing a real run, then dry-run, to reduce runtime errors
|
||||
6. **Human gating**: For steps involving important decisions (such as release, payment, or deletion), it is recommended to use a human_gate node
|
||||
|
||||
### 错误处理
|
||||
### Error Handling
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
|---------|---------|
|
||||
| YAML 语法错误 | 检查缩进和格式,用 Edit 工具修正 |
|
||||
| 校验失败 | 根据 WorkflowValidate 的错误详情逐项修复 |
|
||||
| 节点引用不存在 | 检查 inputs 中引用的 nodeId.outputKey 是否拼写正确 |
|
||||
| 干跑测试失败 | 检查拓扑排序和数据流转路径 |
|
||||
| 执行超时 | 检查是否有 agent 节点 prompt 过于复杂 |
|
||||
| human_gate 被拒绝 | 工作流中止,向用户说明中止原因和已完成的步骤 |
|
||||
| Error Scenario | Handling |
|
||||
|----------------|----------|
|
||||
| YAML syntax error | Check indentation and format, fix using the Edit tool |
|
||||
| Validation failure | Fix item by item based on WorkflowValidate's error details |
|
||||
| Referenced node does not exist | Check whether nodeId.outputKey referenced in inputs is spelled correctly |
|
||||
| Dry-run failure | Check topological sorting and the data flow path |
|
||||
| Execution timeout | Check whether any agent node prompt is overly complex |
|
||||
| human_gate rejected | The workflow aborts; explain to the user the reason for the abort and the steps already completed |
|
||||
|
||||
### 背景知识
|
||||
### Background Knowledge
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
> For the AgentFS repository structure, troubleshooting points, and protected paths, see `_agentfs-background.md` and `_protected-paths.yaml`.
|
||||
|
||||
### 依赖
|
||||
### Dependencies
|
||||
|
||||
- `WorkflowValidate` 内置工具 — 校验 DSL 结构
|
||||
- `WorkflowTest` 内置工具 — 干跑测试
|
||||
- `WorkflowCreate` 内置工具 — 校验并写入全局工作流目录
|
||||
- `WorkflowRun` 内置工具 — 正式执行工作流
|
||||
- Write / Edit / Read 工具 — 创建和编辑 DSL 文件
|
||||
- Agent Service Workflow 引擎(`lib/workflow-service/`)
|
||||
- `WorkflowValidate` built-in tool — validates DSL structure
|
||||
- `WorkflowTest` built-in tool — dry-run testing
|
||||
- `WorkflowCreate` built-in tool — validates and writes to the global workflow directory
|
||||
- `WorkflowRun` built-in tool — performs real workflow execution
|
||||
- Write / Edit / Read tools — create and edit DSL files
|
||||
- Agent Service Workflow engine (`lib/workflow-service/`)
|
||||
|
||||
584
skills/workflow/SKILL.zh-CN.md
Normal file
584
skills/workflow/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,584 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# workflow 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
引导 Agent 通过 DSL 设计、编辑、校验、测试和执行多节点自动化工作流。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
workflow 是一个**流程型技能(Procedural Skill)**,赋予 Agent 编排多步骤自动化工作流的能力。工作流以 YAML DSL 文件描述,由引擎按拓扑顺序自动执行。
|
||||
|
||||
**五种基座节点**:
|
||||
|
||||
| 基座 | 用途 | 典型场景 |
|
||||
|------|------|---------|
|
||||
| `trigger` | 工作流入口,声明输入参数 | 手动触发、webhook 触发 |
|
||||
| `code` | 执行代码(JS/Python) | 数据获取、API 调用 |
|
||||
| `llm` | 单次 LLM 调用(无状态) | 文本生成、数据分析、摘要 |
|
||||
| `agent` | 调用完整 Agent(有状态) | 需要 Agent 记忆、工具、技能的复杂任务 |
|
||||
| `human_gate` | 等待用户确认 | 敏感操作审批 |
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户想把重复性多步骤工作编排成自动化流程
|
||||
- 用户需要多个 Agent 协作完成一个复杂任务
|
||||
- 用户需要在自动化流程中插入人工审批环节
|
||||
- 用户想复用和分享已验证的工作流程
|
||||
|
||||
### 核心价值
|
||||
|
||||
- **可视化编排**:DSL 描述清晰直观,支持画布可视化
|
||||
- **渐进式构建**:先写骨架再逐步丰富,降低出错概率
|
||||
- **安全门控**:通过 human_gate 节点在关键环节保留人工决策权
|
||||
- **可复用**:DSL 文件可存档、版本管理、跨 Agent 共享
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
### 工作流程 SOP
|
||||
|
||||
```
|
||||
┌──────────────┐ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐
|
||||
│ 1. 理解意图 │ ──→ │ 2a. 设计拓扑 │ ──→ │ 2b. 逐节点配置 │ ──→ │ 3. 校验 DSL │
|
||||
└──────────────┘ │ (节点骨架) │ │ (config/code)│ └──────────────┘
|
||||
└──────────────┘ └──────────────┘ │
|
||||
↓
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ 5. 正式执行 │ ←── │ 4. 干跑测试 │
|
||||
└──────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
### 阶段 1:理解意图
|
||||
|
||||
**触发条件**(任一满足):
|
||||
- 用户明确说"创建一个工作流"或"帮我编排一个流程"
|
||||
- 用户描述一个需要多步骤、多角色协作的任务
|
||||
- 用户想把手动重复的操作自动化
|
||||
|
||||
**收集信息**:
|
||||
|
||||
| 信息 | 说明 | 引导问题 |
|
||||
|------|------|---------|
|
||||
| 目标 | 工作流要完成什么 | "这个流程最终要产出什么?" |
|
||||
| 步骤 | 大致有哪些环节 | "你通常是怎么做的?分几步?" |
|
||||
| 审批 | 哪些环节需要人工确认 | "有哪些步骤需要你亲自过目确认?" |
|
||||
| Agent | 是否需要调用特定 Agent | "有没有已有的 Agent 可以参与?" |
|
||||
|
||||
### 阶段 2:渐进式构建 DSL
|
||||
|
||||
**DSL 文件位置**:
|
||||
|
||||
```
|
||||
~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
其中 `wf_id` 使用 `wf_` 前缀 + snake_case,如 `wf_legal_review`、`wf_daily_report`。
|
||||
|
||||
**构建策略**:严格分两步——先设计节点拓扑,再逐节点填充配置。**禁止在骨架阶段编写节点的 config 和 code 细节。**
|
||||
|
||||
#### 步骤 2a:设计节点拓扑(骨架)
|
||||
|
||||
先与用户对齐整体流程设计,确认后使用 Write 工具一次性创建骨架 DSL 文件。骨架用于对齐拓扑,不要求立即通过 `WorkflowValidate`;最终完整 DSL 写入时优先使用 `WorkflowCreate`。
|
||||
|
||||
**骨架只包含**:
|
||||
- 根字段(version、id、name、description、creator)
|
||||
- 每个节点的 `id`、`base`、`display.name`
|
||||
- 每个节点的 `outputs`(声明变量名和描述)
|
||||
- `flow`(start、edges、end)
|
||||
|
||||
**骨架不包含**:config 内容(code / system_prompt / task / prompt 等)、inputs 引用。
|
||||
|
||||
```yaml
|
||||
# 骨架示例——只有结构,没有实现细节
|
||||
version: "1.0"
|
||||
id: wf_daily_report
|
||||
name: 每日报告生成
|
||||
description: 从多个数据源获取数据,生成日报并审批发送
|
||||
creator: desirecore
|
||||
|
||||
nodes:
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 手动触发
|
||||
config:
|
||||
type: manual
|
||||
outputs:
|
||||
date:
|
||||
type: string
|
||||
description: "报告日期"
|
||||
required: true
|
||||
|
||||
- id: fetch_data
|
||||
base: code
|
||||
display:
|
||||
name: 获取数据
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
raw_data: "原始数据"
|
||||
|
||||
- id: analyze
|
||||
base: llm
|
||||
display:
|
||||
name: AI 分析
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
report: "分析报告"
|
||||
|
||||
- id: review
|
||||
base: human_gate
|
||||
display:
|
||||
name: 人工审阅
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
decision: "审批决定"
|
||||
comment: "审批备注"
|
||||
|
||||
- id: send
|
||||
base: code
|
||||
display:
|
||||
name: 发送报告
|
||||
config: {} # 待步骤 2b 填充
|
||||
outputs:
|
||||
status: "发送状态"
|
||||
|
||||
flow:
|
||||
start: trigger
|
||||
edges:
|
||||
- { from: trigger, to: fetch_data }
|
||||
- { from: fetch_data, to: analyze }
|
||||
- { from: analyze, to: review }
|
||||
- { from: review, to: send }
|
||||
end: [send]
|
||||
```
|
||||
|
||||
骨架创建后,向用户确认节点设计和流程是否正确,再进入步骤 2b。
|
||||
|
||||
#### 步骤 2b:逐节点填充配置
|
||||
|
||||
按拓扑顺序(从 trigger 开始,沿 edges 方向)逐个节点填充 config 和 inputs。每完成一个节点使用 Edit 工具写入,**不要一次性填充所有节点**。
|
||||
|
||||
**每个节点填充内容**:
|
||||
1. `inputs` — 引用上游节点的输出(`{{nodeId.outputKey}}`)
|
||||
2. `config` — 该基座类型的具体配置:
|
||||
- **code 节点**:编写 `runtime` 和 `code`(完整的可执行代码)
|
||||
- **llm 节点**:编写 `system_prompt`、选择 `model` / `provider`、设置 `temperature` 等参数
|
||||
- **agent 节点**:指定 `agent_id` 和编写 `task` 描述
|
||||
- **human_gate 节点**:编写审批 `prompt`(含 `{{}}` 插值)
|
||||
|
||||
**逐节点填充顺序示例**(以上方骨架为例):
|
||||
|
||||
```
|
||||
1. fetch_data — 编写获取数据的 JS/Python 代码
|
||||
2. analyze — 编写 system_prompt,选择模型,配置 inputs 引用 fetch_data 输出
|
||||
3. review — 编写审批提示词,配置 inputs 引用 analyze 输出
|
||||
4. send — 编写发送逻辑的代码,配置 inputs 引用 review 输出
|
||||
```
|
||||
|
||||
填充完所有节点后进入阶段 3 校验。
|
||||
|
||||
### DSL 编写规范
|
||||
|
||||
#### 根结构
|
||||
|
||||
```yaml
|
||||
version: "1.0" # 固定值
|
||||
id: wf_<snake_case_name> # 必须以 wf_ 前缀开头
|
||||
name: 工作流显示名称 # 人类可读名称
|
||||
description: 工作流用途描述 # 可选,说明适用场景
|
||||
creator: <agent_id> # 创建此工作流的 Agent ID
|
||||
|
||||
nodes: # 节点列表(至少 1 个)
|
||||
- id: ...
|
||||
base: ...
|
||||
...
|
||||
|
||||
flow: # 流程控制
|
||||
start: <起始节点 id>
|
||||
edges:
|
||||
- { from: <节点 id>, to: <节点 id> }
|
||||
end: [<终止节点 id>]
|
||||
```
|
||||
|
||||
#### code 节点配置
|
||||
|
||||
code 节点执行**内联代码**(JS 或 Python),通过 `inputs` 对象访问上游数据,通过 `return` 返回结果。
|
||||
|
||||
```yaml
|
||||
- id: format_data
|
||||
base: code
|
||||
display:
|
||||
name: 格式化数据
|
||||
config:
|
||||
runtime: nodejs # nodejs 或 python
|
||||
timeout_ms: 30000 # 超时毫秒数(可选,默认 30000)
|
||||
code: |
|
||||
// inputs 对象包含所有上游传入的数据
|
||||
const data = JSON.parse(inputs.raw_data)
|
||||
const formatted = data.map(item => ({
|
||||
title: item.title.trim(),
|
||||
date: new Date(item.pubDate).toISOString().slice(0, 10),
|
||||
}))
|
||||
return { formatted: JSON.stringify(formatted) }
|
||||
inputs:
|
||||
raw_data: "{{fetch_node.result}}" # 引用上游节点 fetch_node 的 result 输出
|
||||
outputs:
|
||||
formatted: "格式化后的数据"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `runtime` | 是 | `nodejs` 或 `python` |
|
||||
| `code` | 是 | 内联代码。JS 通过 `inputs` 对象访问输入,`return` 返回输出对象。Python 同理。 |
|
||||
| `timeout_ms` | 否 | 执行超时(默认 30000ms) |
|
||||
|
||||
**JS 代码注意事项**:
|
||||
- 代码在 `new Function('inputs', ...)` 中执行,支持 `async/await` 和 `fetch`
|
||||
- **不支持 `require()`**,不能导入 Node.js 模块
|
||||
- 通过 `inputs.xxx` 访问输入数据
|
||||
- 必须 `return` 一个对象,其 key 对应 `outputs` 中声明的变量名
|
||||
|
||||
**Python 代码注意事项**:
|
||||
- 通过 `inputs['xxx']` 访问输入数据
|
||||
- 必须 `return` 一个字典
|
||||
|
||||
#### llm 节点配置
|
||||
|
||||
llm 节点执行**单次无状态 LLM 调用**,适用于文本生成、数据分析、摘要等场景。与 agent 节点的区别是不涉及 Agent 的记忆、工具和技能。
|
||||
|
||||
```yaml
|
||||
- id: summarize
|
||||
base: llm
|
||||
display:
|
||||
name: AI 摘要
|
||||
config:
|
||||
provider: anthropic # 供应商名称(可选,精确匹配)
|
||||
model: claude-sonnet-4-6 # 模型(可选,不填使用默认)
|
||||
system_prompt: "你是摘要助手" # 系统提示词
|
||||
max_tokens: 2048 # 最大 token
|
||||
temperature: 0.3 # 温度(可选)
|
||||
reasoning: medium # 思维链级别(可选)
|
||||
inputs:
|
||||
data: "{{fetch_data.result}}"
|
||||
outputs:
|
||||
summary: "摘要文本"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `system_prompt` | 是 | 系统提示词,定义 LLM 的角色和行为 |
|
||||
| `provider` | 否 | 供应商名称(如 `anthropic`、`openai`),精确匹配已配置的供应商。不填则由系统自动匹配 |
|
||||
| `model` | 否 | 指定模型,不填使用默认模型 |
|
||||
| `max_tokens` | 否 | 最大输出 token 数 |
|
||||
| `temperature` | 否 | 温度参数(0-2),控制输出随机性 |
|
||||
| `reasoning` | 否 | 思维链级别:`low` / `medium` / `high`。开启后模型先推理再回答,适合复杂分析任务 |
|
||||
| `output_schema` | 否 | JSON Schema 对象。设置后 LLM 将尝试返回符合 Schema 的结构化 JSON |
|
||||
|
||||
#### agent 节点配置
|
||||
|
||||
agent 节点调用**完整的 Agent**(有状态),适用于需要 Agent 的专业知识、记忆、工具或技能的复杂任务。
|
||||
|
||||
```yaml
|
||||
- id: legal_review
|
||||
base: agent
|
||||
display:
|
||||
name: 法律审核
|
||||
config:
|
||||
agent_id: legal-advisor # 必填:目标 Agent ID
|
||||
task: "审核以下内容:{{summarize.summary}}" # 任务描述
|
||||
inputs:
|
||||
content: "{{summarize.summary}}"
|
||||
outputs:
|
||||
review: "审核意见"
|
||||
```
|
||||
|
||||
**config 字段说明**:
|
||||
|
||||
| 字段 | 必填 | 说明 |
|
||||
|------|------|------|
|
||||
| `agent_id` | 是 | 目标 Agent 的 ID |
|
||||
| `task` | 是 | 交给 Agent 的任务描述,支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}` 插值 |
|
||||
|
||||
#### human_gate 节点配置
|
||||
|
||||
```yaml
|
||||
- id: approval
|
||||
base: human_gate
|
||||
display:
|
||||
name: 人工审批
|
||||
config:
|
||||
prompt: |
|
||||
请审阅以下内容并决定是否通过:
|
||||
审阅意见:{{draft_review.review_result}}
|
||||
风险等级:{{draft_review.risk_level}}
|
||||
options:
|
||||
- { label: "批准", value: approve }
|
||||
- { label: "拒绝", value: reject }
|
||||
- { label: "修改后通过", value: modify }
|
||||
inputs:
|
||||
review_result: "{{draft_review.review_result}}"
|
||||
risk_level: "{{draft_review.risk_level}}"
|
||||
outputs:
|
||||
decision: "审批决定(approve/reject/modify)"
|
||||
comment: "审批备注"
|
||||
```
|
||||
|
||||
#### llm vs agent 选择指南
|
||||
|
||||
| 场景 | 推荐基座 | 理由 |
|
||||
|------|---------|------|
|
||||
| 文本摘要、翻译、格式转换 | `llm` | 单次调用,不需要 Agent 上下文 |
|
||||
| 数据分析、信息提取 | `llm` | 无状态处理即可完成 |
|
||||
| 需要专业知识的审核 | `agent` | 需要 Agent 的领域知识和记忆 |
|
||||
| 需要调用外部工具 | `agent` | 需要 Agent 的工具能力 |
|
||||
| 多轮推理、复杂决策 | `agent` | 需要 Agent 的完整推理链 |
|
||||
|
||||
**简单判断**:如果任务可以用一段 system prompt + 一次输入完成,用 `llm`;如果任务需要 Agent 的记忆、工具或技能,用 `agent`。
|
||||
|
||||
#### trigger 节点
|
||||
|
||||
每个工作流**必须有且仅有一个** trigger 节点,作为工作流入口。`flow.start` 必须指向 trigger 节点。
|
||||
|
||||
**规则**:
|
||||
- trigger 节点**无 inputs**
|
||||
- trigger 节点的 outputs 使用结构化格式(`type` / `description` / `required` / `default`),声明工作流接受的输入参数
|
||||
- `config.type` 指定触发方式:`manual`(手动触发)或 `webhook`(外部触发)
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 手动触发
|
||||
icon: ▶️
|
||||
config:
|
||||
type: manual # manual | webhook
|
||||
outputs:
|
||||
param_name:
|
||||
type: string # 参数类型:string / number / boolean / object / array
|
||||
description: "参数描述"
|
||||
required: true # 是否必填
|
||||
default: "默认值" # 可选,未传入时的默认值
|
||||
```
|
||||
|
||||
**示例**——带多个参数的 trigger:
|
||||
|
||||
```yaml
|
||||
- id: trigger
|
||||
base: trigger
|
||||
display:
|
||||
name: 文档摘要触发
|
||||
icon: ▶️
|
||||
config:
|
||||
type: manual
|
||||
outputs:
|
||||
filePath:
|
||||
type: string
|
||||
description: "要摘要的文档路径"
|
||||
required: true
|
||||
language:
|
||||
type: string
|
||||
description: "摘要输出语言"
|
||||
required: false
|
||||
default: "zh-CN"
|
||||
```
|
||||
|
||||
下游节点通过 `{{trigger.paramName}}` 引用 trigger 输出的参数值。
|
||||
|
||||
#### inputs 格式规范
|
||||
|
||||
inputs 使用**对象映射格式**——key 为本节点的变量名,value 为数据来源引用:
|
||||
|
||||
```yaml
|
||||
# 引用其他节点的输出
|
||||
inputs:
|
||||
varName: "{{nodeId.outputKey}}"
|
||||
|
||||
# 引用触发参数
|
||||
inputs:
|
||||
query: "{{trigger.userQuery}}"
|
||||
|
||||
# 引用用户级 secret
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
|
||||
# 多个输入
|
||||
inputs:
|
||||
title: "{{extract.title}}"
|
||||
body: "{{extract.body}}"
|
||||
metadata: "{{trigger.metadata}}"
|
||||
```
|
||||
|
||||
**禁止使用数组格式**:
|
||||
|
||||
```yaml
|
||||
# 错误!不要用数组
|
||||
inputs:
|
||||
- name: varName
|
||||
source: nodeId.outputKey
|
||||
```
|
||||
|
||||
#### outputs 格式规范
|
||||
|
||||
outputs 使用**对象映射格式**——key 为输出变量名,value 为描述文本:
|
||||
|
||||
```yaml
|
||||
outputs:
|
||||
result: "处理后的结果数据"
|
||||
summary: "结果摘要"
|
||||
```
|
||||
|
||||
#### flow 定义
|
||||
|
||||
```yaml
|
||||
flow:
|
||||
start: first_node # 起始节点 ID
|
||||
edges: # 边列表(定义执行顺序)
|
||||
- { from: first_node, to: second_node }
|
||||
- { from: second_node, to: third_node }
|
||||
- from: third_node # 条件分支(可选)
|
||||
to: branch_a
|
||||
condition: "risk_level == 'high'"
|
||||
end: [final_node] # 终止节点列表
|
||||
```
|
||||
|
||||
#### 变量引用体系
|
||||
|
||||
DSL 中所有动态值统一使用 `{{}}` 模板语法引用:
|
||||
|
||||
| 语法 | 来源 | 示例 |
|
||||
|------|------|------|
|
||||
| `{{nodeId.outputKey}}` | 前置节点输出 | `{{summarize.summary}}` |
|
||||
| `{{trigger.key}}` | 触发时传入的参数 | `{{trigger.filePath}}` |
|
||||
| `{{secrets.keyName}}` | 用户级 secret | `{{secrets.dingtalk_token}}` |
|
||||
|
||||
**适用位置**:`inputs` 的值、`config.prompt` 中的插值均使用此语法。
|
||||
|
||||
#### Secrets 引用
|
||||
|
||||
工作流可通过 `{{secrets.keyName}}` 引用用户预配置的密钥,用于 API 调用等场景。
|
||||
|
||||
- Secrets 由用户在 `~/.desirecore/config/secrets.json` 中预配置
|
||||
- 引擎在运行时自动解析 `{{secrets.*}}`,将其替换为实际值
|
||||
- Secrets 仅在执行阶段解析,校验和干跑阶段不会暴露实际值
|
||||
|
||||
```yaml
|
||||
# 在 inputs 中引用 secret
|
||||
inputs:
|
||||
api_key: "{{secrets.email_api_key}}"
|
||||
webhook_url: "{{secrets.dingtalk_webhook}}"
|
||||
|
||||
# 在 config.prompt 中引用 secret(不推荐,仅特殊场景)
|
||||
config:
|
||||
prompt: "使用 token {{secrets.github_token}} 访问仓库"
|
||||
```
|
||||
|
||||
### 阶段 3:校验 DSL
|
||||
|
||||
使用 `WorkflowValidate` 工具校验 DSL 文件的结构和引用完整性。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowValidate
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
```
|
||||
|
||||
**校验内容**:
|
||||
- YAML 语法正确性
|
||||
- JSON Schema 合规性(必填字段、类型、格式)
|
||||
- 节点 ID 唯一性
|
||||
- 边的引用有效性(from/to 均指向已存在的节点)
|
||||
- 起始节点和终止节点存在
|
||||
- 无环检测(DAG 校验)
|
||||
- inputs 引用的上游节点和输出字段存在
|
||||
|
||||
**校验通过** → 进入阶段 4
|
||||
**校验失败** → 根据错误信息用 Edit 工具修复,重新校验
|
||||
|
||||
### 阶段 4:干跑测试
|
||||
|
||||
使用 `WorkflowTest` 工具进行模拟执行(dry-run),不实际调用 Agent 或执行代码。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowTest
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,用于模拟 trigger 参数
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**测试内容**:
|
||||
- 验证拓扑排序是否成功
|
||||
- 模拟数据在节点间的流转路径
|
||||
- 检查所有 inputs 引用在运行时是否可解析
|
||||
- 输出执行计划预览(节点执行顺序)
|
||||
|
||||
**测试通过** → 向用户确认是否正式执行
|
||||
**测试失败** → 根据错误信息修复,重新测试
|
||||
|
||||
### 阶段 5:正式执行
|
||||
|
||||
使用 `WorkflowRun` 工具启动工作流。
|
||||
|
||||
**调用方式**:
|
||||
|
||||
```
|
||||
工具:WorkflowRun
|
||||
参数:
|
||||
path: ~/.desirecore/workflows/<wf_id>/workflow.dsl.yaml
|
||||
params: # 可选,作为 {{trigger.key}} 上下文传入
|
||||
filePath: /path/to/input.md
|
||||
```
|
||||
|
||||
**执行过程**:
|
||||
- 引擎按拓扑顺序逐节点执行
|
||||
- 实时通过 SSE 推送节点状态变更事件
|
||||
- 遇到 human_gate 节点时暂停,等待用户审批
|
||||
- 所有终止节点完成后,返回最终结果
|
||||
|
||||
**执行完成后**:
|
||||
- 向用户展示执行结果摘要
|
||||
- 如有失败节点,说明失败原因和建议修复方式
|
||||
|
||||
### 注意事项
|
||||
|
||||
1. **workflow_id 命名**:必须以 `wf_` 前缀开头,使用 snake_case,如 `wf_contract_review`
|
||||
2. **严格分步构建**:步骤 2a 只写节点拓扑骨架(不含 config/code),确认后步骤 2b 按拓扑顺序逐节点填充配置,禁止一次性写完所有细节
|
||||
3. **输入输出格式**:inputs 和 outputs 必须使用对象映射格式(`{ key: value }`),不要用数组
|
||||
4. **变量插值**:inputs、llm/agent/human_gate 的 prompt / system_prompt / task 支持 `{{nodeId.outputKey}}`、`{{trigger.key}}`、`{{secrets.keyName}}`
|
||||
5. **校验先行**:正式执行前务必先校验再干跑测试,减少运行时错误
|
||||
6. **人工门控**:涉及重要决策(如发布、付款、删除)的步骤,建议使用 human_gate 节点
|
||||
|
||||
### 错误处理
|
||||
|
||||
| 错误场景 | 处理方式 |
|
||||
|---------|---------|
|
||||
| YAML 语法错误 | 检查缩进和格式,用 Edit 工具修正 |
|
||||
| 校验失败 | 根据 WorkflowValidate 的错误详情逐项修复 |
|
||||
| 节点引用不存在 | 检查 inputs 中引用的 nodeId.outputKey 是否拼写正确 |
|
||||
| 干跑测试失败 | 检查拓扑排序和数据流转路径 |
|
||||
| 执行超时 | 检查是否有 agent 节点 prompt 过于复杂 |
|
||||
| human_gate 被拒绝 | 工作流中止,向用户说明中止原因和已完成的步骤 |
|
||||
|
||||
### 背景知识
|
||||
|
||||
> AgentFS 仓库结构、排查要点与受保护路径详见 `_agentfs-background.md` 和 `_protected-paths.yaml`。
|
||||
|
||||
### 依赖
|
||||
|
||||
- `WorkflowValidate` 内置工具 — 校验 DSL 结构
|
||||
- `WorkflowTest` 内置工具 — 干跑测试
|
||||
- `WorkflowCreate` 内置工具 — 校验并写入全局工作流目录
|
||||
- `WorkflowRun` 内置工具 — 正式执行工作流
|
||||
- Write / Edit / Read 工具 — 创建和编辑 DSL 文件
|
||||
- Agent Service Workflow 引擎(`lib/workflow-service/`)
|
||||
@@ -1,5 +1,5 @@
|
||||
---
|
||||
name: 电子表格处理
|
||||
name: xlsx
|
||||
description: >-
|
||||
Use this skill any time a spreadsheet file is the primary input or output.
|
||||
This means any task where the user wants to: open, read, edit, or fix an
|
||||
@@ -28,6 +28,29 @@ tags:
|
||||
metadata:
|
||||
author: anthropic
|
||||
updated_at: '2026-04-13'
|
||||
i18n:
|
||||
default_locale: en-US
|
||||
source_locale: zh-CN
|
||||
locales:
|
||||
- zh-CN
|
||||
- en-US
|
||||
zh-CN:
|
||||
name: 电子表格处理
|
||||
short_desc: 创建、编辑和处理 Excel 电子表格(.xlsx)
|
||||
description: >-
|
||||
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved. Use when 用户提到 Excel、 电子表格、xlsx、表格处理、公式计算、数据清洗、图表、CSV导入导出。
|
||||
body: ./SKILL.zh-CN.md
|
||||
source_hash: sha256:de1660781d23798b
|
||||
translated_by: human
|
||||
en-US:
|
||||
name: Spreadsheet Processing
|
||||
short_desc: Create, edit, and process Excel spreadsheets (.xlsx)
|
||||
description: >-
|
||||
Use this skill any time a spreadsheet file is the primary input or output. This means any task where the user wants to: open, read, edit, or fix an existing .xlsx, .xlsm, .csv, or .tsv file (e.g., adding columns, computing formulas, formatting, charting, cleaning messy data); create a new spreadsheet from scratch or from other data sources; or convert between tabular file formats. Trigger especially when the user references a spreadsheet file by name or path — even casually (like "the xlsx in my downloads") — and wants something done to it or produced from it. Also trigger for cleaning or restructuring messy tabular data files (malformed rows, misplaced headers, junk data) into proper spreadsheets. The deliverable must be a spreadsheet file. Do NOT trigger when the primary deliverable is a Word document, HTML report, standalone Python script, database pipeline, or Google Sheets API integration, even if tabular data is involved. Use when the user mentions Excel, spreadsheets, xlsx, table processing, formula computation, data cleaning, charts, or CSV import/export.
|
||||
body: ./SKILL.md
|
||||
source_hash: sha256:de1660781d23798b
|
||||
translated_by: ai:claude-opus-4-7
|
||||
translated_at: '2026-05-03'
|
||||
market:
|
||||
icon: >-
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0
|
||||
@@ -42,7 +65,6 @@ market:
|
||||
r="3" fill="#34C759" fill-opacity="0.9"/><path d="M18 18.5l1 1.5 2-2.5"
|
||||
stroke="white" stroke-width="1.2" stroke-linecap="round"
|
||||
stroke-linejoin="round"/></svg>
|
||||
short_desc: 创建、编辑和处理 Excel 电子表格(.xlsx)
|
||||
category: productivity
|
||||
maintainer:
|
||||
name: DesireCore Official
|
||||
@@ -50,66 +72,66 @@ market:
|
||||
channel: latest
|
||||
---
|
||||
|
||||
# xlsx 技能
|
||||
# xlsx Skill
|
||||
|
||||
## L0:一句话摘要
|
||||
## L0: One-line Summary
|
||||
|
||||
创建、编辑和分析 Excel 电子表格(.xlsx),支持公式、格式、数据分析和可视化。
|
||||
Create, edit, and analyze Excel spreadsheets (.xlsx), with support for formulas, formatting, data analysis, and visualization.
|
||||
|
||||
## L1:概述与使用场景
|
||||
## L1: Overview and Use Cases
|
||||
|
||||
### 能力描述
|
||||
### Capability
|
||||
|
||||
xlsx 是一个**流程型技能(Procedural Skill)**,提供 Excel 电子表格的完整处理能力。基于 Python 库(openpyxl、pandas),支持创建新表格、编辑现有文件、数据分析、公式计算、格式设置和图表生成,并通过 LibreOffice 实现公式重算和错误检测。
|
||||
xlsx is a **Procedural Skill** that provides full processing capabilities for Excel spreadsheets. Built on Python libraries (openpyxl, pandas), it supports creating new spreadsheets, editing existing files, data analysis, formula calculation, formatting, and chart generation, and uses LibreOffice for formula recalculation and error detection.
|
||||
|
||||
### 使用场景
|
||||
### Use Cases
|
||||
|
||||
- 用户需要创建新的 Excel 电子表格(财务模型、数据报告等)
|
||||
- 用户需要编辑或修改现有 .xlsx 文件
|
||||
- 用户需要进行数据分析、清洗或格式转换(CSV/TSV → XLSX)
|
||||
- 用户需要添加公式、图表或格式化现有表格
|
||||
- The user needs to create a new Excel spreadsheet (financial models, data reports, etc.)
|
||||
- The user needs to edit or modify an existing .xlsx file
|
||||
- The user needs to perform data analysis, cleaning, or format conversion (CSV/TSV → XLSX)
|
||||
- The user needs to add formulas, charts, or formatting to an existing spreadsheet
|
||||
|
||||
## L2:详细规范
|
||||
## L2: Detailed Specification
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
### Python 3 (required)
|
||||
|
||||
在执行任何 Python 操作之前,先检测 Python 是否可用:
|
||||
Before performing any Python operation, first check whether Python is available:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
If the command fails (Python is unavailable), **you must stop and instruct the user to install Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **macOS**: `brew install python3` or download from https://www.python.org/downloads/
|
||||
- **Windows**: `winget install Python.Python.3` or download from python.org (check "Add Python to PATH" during installation)
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(LibreOffice / 容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
For more detailed environment setup help: for Python-related issues load the `python-runtime` Skill;
|
||||
for everything else (LibreOffice / containers / WSL), load the `dev-environment-setup` Skill.
|
||||
|
||||
### Python 包依赖
|
||||
### Python Package Dependencies
|
||||
|
||||
本技能依赖以下 Python 包(按需检测):
|
||||
This Skill depends on the following Python packages (checked on demand):
|
||||
|
||||
- `openpyxl` — Excel 文件创建和编辑(公式、格式)
|
||||
- `pandas` — 数据分析和读写
|
||||
- `openpyxl` — Excel file creation and editing (formulas, formatting)
|
||||
- `pandas` — data analysis and read/write
|
||||
|
||||
检测方法:
|
||||
Detection method:
|
||||
```bash
|
||||
python3 -c "import openpyxl; import pandas" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install openpyxl pandas`
|
||||
If missing, instruct the user to install: `pip install openpyxl pandas`
|
||||
|
||||
# Requirements for Outputs
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .xlsx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.xlsx`"
|
||||
When you create or modify a .xlsx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "File saved to: `/path/to/output.xlsx`"
|
||||
|
||||
## All Excel files
|
||||
|
||||
|
||||
347
skills/xlsx/SKILL.zh-CN.md
Normal file
347
skills/xlsx/SKILL.zh-CN.md
Normal file
@@ -0,0 +1,347 @@
|
||||
<!-- locale: zh-CN -->
|
||||
|
||||
# xlsx 技能
|
||||
|
||||
## L0:一句话摘要
|
||||
|
||||
创建、编辑和分析 Excel 电子表格(.xlsx),支持公式、格式、数据分析和可视化。
|
||||
|
||||
## L1:概述与使用场景
|
||||
|
||||
### 能力描述
|
||||
|
||||
xlsx 是一个**流程型技能(Procedural Skill)**,提供 Excel 电子表格的完整处理能力。基于 Python 库(openpyxl、pandas),支持创建新表格、编辑现有文件、数据分析、公式计算、格式设置和图表生成,并通过 LibreOffice 实现公式重算和错误检测。
|
||||
|
||||
### 使用场景
|
||||
|
||||
- 用户需要创建新的 Excel 电子表格(财务模型、数据报告等)
|
||||
- 用户需要编辑或修改现有 .xlsx 文件
|
||||
- 用户需要进行数据分析、清洗或格式转换(CSV/TSV → XLSX)
|
||||
- 用户需要添加公式、图表或格式化现有表格
|
||||
|
||||
## L2:详细规范
|
||||
|
||||
## Prerequisites
|
||||
|
||||
### Python 3(必需)
|
||||
|
||||
在执行任何 Python 操作之前,先检测 Python 是否可用:
|
||||
|
||||
```bash
|
||||
python3 --version 2>/dev/null || python --version 2>/dev/null
|
||||
```
|
||||
|
||||
如果命令失败(Python 不可用),**必须停止并告知用户安装 Python 3**:
|
||||
|
||||
- **macOS**: `brew install python3` 或从 https://www.python.org/downloads/ 下载
|
||||
- **Windows**: `winget install Python.Python.3` 或从 python.org 下载(安装时勾选 "Add Python to PATH")
|
||||
- **Linux (Debian/Ubuntu)**: `sudo apt install python3 python3-pip`
|
||||
- **Linux (Fedora/RHEL)**: `sudo dnf install python3 python3-pip`
|
||||
|
||||
如需更详细的环境配置帮助:Python 相关问题加载 `python-runtime` 技能;
|
||||
其他(LibreOffice / 容器 / WSL)加载 `dev-environment-setup` 技能。
|
||||
|
||||
### Python 包依赖
|
||||
|
||||
本技能依赖以下 Python 包(按需检测):
|
||||
|
||||
- `openpyxl` — Excel 文件创建和编辑(公式、格式)
|
||||
- `pandas` — 数据分析和读写
|
||||
|
||||
检测方法:
|
||||
```bash
|
||||
python3 -c "import openpyxl; import pandas" 2>/dev/null || echo "MISSING"
|
||||
```
|
||||
|
||||
缺失时告知用户安装:`pip install openpyxl pandas`
|
||||
|
||||
# Requirements for Outputs
|
||||
|
||||
## Output Rule
|
||||
|
||||
When you create or modify a .xlsx file, you **MUST** tell the user the absolute path of the output file in your response. Example: "文件已保存到:`/path/to/output.xlsx`"
|
||||
|
||||
## All Excel files
|
||||
|
||||
### Professional Font
|
||||
- Use a consistent, professional font (e.g., Arial, Times New Roman) for all deliverables unless otherwise instructed by the user
|
||||
|
||||
### Zero Formula Errors
|
||||
- Every Excel model MUST be delivered with ZERO formula errors (#REF!, #DIV/0!, #VALUE!, #N/A, #NAME?)
|
||||
|
||||
### Preserve Existing Templates (when updating templates)
|
||||
- Study and EXACTLY match existing format, style, and conventions when modifying files
|
||||
- Never impose standardized formatting on files with established patterns
|
||||
- Existing template conventions ALWAYS override these guidelines
|
||||
|
||||
## Financial models
|
||||
|
||||
### Color Coding Standards
|
||||
Unless otherwise stated by the user or existing template
|
||||
|
||||
#### Industry-Standard Color Conventions
|
||||
- **Blue text (RGB: 0,0,255)**: Hardcoded inputs, and numbers users will change for scenarios
|
||||
- **Black text (RGB: 0,0,0)**: ALL formulas and calculations
|
||||
- **Green text (RGB: 0,128,0)**: Links pulling from other worksheets within same workbook
|
||||
- **Red text (RGB: 255,0,0)**: External links to other files
|
||||
- **Yellow background (RGB: 255,255,0)**: Key assumptions needing attention or cells that need to be updated
|
||||
|
||||
### Number Formatting Standards
|
||||
|
||||
#### Required Format Rules
|
||||
- **Years**: Format as text strings (e.g., "2024" not "2,024")
|
||||
- **Currency**: Use $#,##0 format; ALWAYS specify units in headers ("Revenue ($mm)")
|
||||
- **Zeros**: Use number formatting to make all zeros "-", including percentages (e.g., "$#,##0;($#,##0);-")
|
||||
- **Percentages**: Default to 0.0% format (one decimal)
|
||||
- **Multiples**: Format as 0.0x for valuation multiples (EV/EBITDA, P/E)
|
||||
- **Negative numbers**: Use parentheses (123) not minus -123
|
||||
|
||||
### Formula Construction Rules
|
||||
|
||||
#### Assumptions Placement
|
||||
- Place ALL assumptions (growth rates, margins, multiples, etc.) in separate assumption cells
|
||||
- Use cell references instead of hardcoded values in formulas
|
||||
- Example: Use =B5*(1+$B$6) instead of =B5*1.05
|
||||
|
||||
#### Formula Error Prevention
|
||||
- Verify all cell references are correct
|
||||
- Check for off-by-one errors in ranges
|
||||
- Ensure consistent formulas across all projection periods
|
||||
- Test with edge cases (zero values, negative numbers)
|
||||
- Verify no unintended circular references
|
||||
|
||||
#### Documentation Requirements for Hardcodes
|
||||
- Comment or in cells beside (if end of table). Format: "Source: [System/Document], [Date], [Specific Reference], [URL if applicable]"
|
||||
- Examples:
|
||||
- "Source: Company 10-K, FY2024, Page 45, Revenue Note, [SEC EDGAR URL]"
|
||||
- "Source: Company 10-Q, Q2 2025, Exhibit 99.1, [SEC EDGAR URL]"
|
||||
- "Source: Bloomberg Terminal, 8/15/2025, AAPL US Equity"
|
||||
- "Source: FactSet, 8/20/2025, Consensus Estimates Screen"
|
||||
|
||||
# XLSX creation, editing, and analysis
|
||||
|
||||
## Overview
|
||||
|
||||
A user may ask you to create, edit, or analyze the contents of an .xlsx file. You have different tools and workflows available for different tasks.
|
||||
|
||||
## Important Requirements
|
||||
|
||||
**LibreOffice Required for Formula Recalculation**: You can assume LibreOffice is installed for recalculating formula values using the `scripts/recalc.py` script. The script automatically configures LibreOffice on first run, including in sandboxed environments where Unix sockets are restricted (handled by `scripts/office/soffice.py`)
|
||||
|
||||
## Reading and analyzing data
|
||||
|
||||
### Data analysis with pandas
|
||||
For data analysis, visualization, and basic operations, use **pandas** which provides powerful data manipulation capabilities:
|
||||
|
||||
```python
|
||||
import pandas as pd
|
||||
|
||||
# Read Excel
|
||||
df = pd.read_excel('file.xlsx') # Default: first sheet
|
||||
all_sheets = pd.read_excel('file.xlsx', sheet_name=None) # All sheets as dict
|
||||
|
||||
# Analyze
|
||||
df.head() # Preview data
|
||||
df.info() # Column info
|
||||
df.describe() # Statistics
|
||||
|
||||
# Write Excel
|
||||
df.to_excel('output.xlsx', index=False)
|
||||
```
|
||||
|
||||
## Excel File Workflows
|
||||
|
||||
## CRITICAL: Use Formulas, Not Hardcoded Values
|
||||
|
||||
**Always use Excel formulas instead of calculating values in Python and hardcoding them.** This ensures the spreadsheet remains dynamic and updateable.
|
||||
|
||||
### ❌ WRONG - Hardcoding Calculated Values
|
||||
```python
|
||||
# Bad: Calculating in Python and hardcoding result
|
||||
total = df['Sales'].sum()
|
||||
sheet['B10'] = total # Hardcodes 5000
|
||||
|
||||
# Bad: Computing growth rate in Python
|
||||
growth = (df.iloc[-1]['Revenue'] - df.iloc[0]['Revenue']) / df.iloc[0]['Revenue']
|
||||
sheet['C5'] = growth # Hardcodes 0.15
|
||||
|
||||
# Bad: Python calculation for average
|
||||
avg = sum(values) / len(values)
|
||||
sheet['D20'] = avg # Hardcodes 42.5
|
||||
```
|
||||
|
||||
### ✅ CORRECT - Using Excel Formulas
|
||||
```python
|
||||
# Good: Let Excel calculate the sum
|
||||
sheet['B10'] = '=SUM(B2:B9)'
|
||||
|
||||
# Good: Growth rate as Excel formula
|
||||
sheet['C5'] = '=(C4-C2)/C2'
|
||||
|
||||
# Good: Average using Excel function
|
||||
sheet['D20'] = '=AVERAGE(D2:D19)'
|
||||
```
|
||||
|
||||
This applies to ALL calculations - totals, percentages, ratios, differences, etc. The spreadsheet should be able to recalculate when source data changes.
|
||||
|
||||
## Common Workflow
|
||||
1. **Choose tool**: pandas for data, openpyxl for formulas/formatting
|
||||
2. **Create/Load**: Create new workbook or load existing file
|
||||
3. **Modify**: Add/edit data, formulas, and formatting
|
||||
4. **Save**: Write to file
|
||||
5. **Recalculate formulas (MANDATORY IF USING FORMULAS)**: Use the scripts/recalc.py script
|
||||
```bash
|
||||
python scripts/recalc.py output.xlsx
|
||||
```
|
||||
6. **Verify and fix any errors**:
|
||||
- The script returns JSON with error details
|
||||
- If `status` is `errors_found`, check `error_summary` for specific error types and locations
|
||||
- Fix the identified errors and recalculate again
|
||||
- Common errors to fix:
|
||||
- `#REF!`: Invalid cell references
|
||||
- `#DIV/0!`: Division by zero
|
||||
- `#VALUE!`: Wrong data type in formula
|
||||
- `#NAME?`: Unrecognized formula name
|
||||
|
||||
### Creating new Excel files
|
||||
|
||||
```python
|
||||
# Using openpyxl for formulas and formatting
|
||||
from openpyxl import Workbook
|
||||
from openpyxl.styles import Font, PatternFill, Alignment
|
||||
|
||||
wb = Workbook()
|
||||
sheet = wb.active
|
||||
|
||||
# Add data
|
||||
sheet['A1'] = 'Hello'
|
||||
sheet['B1'] = 'World'
|
||||
sheet.append(['Row', 'of', 'data'])
|
||||
|
||||
# Add formula
|
||||
sheet['B2'] = '=SUM(A1:A10)'
|
||||
|
||||
# Formatting
|
||||
sheet['A1'].font = Font(bold=True, color='FF0000')
|
||||
sheet['A1'].fill = PatternFill('solid', start_color='FFFF00')
|
||||
sheet['A1'].alignment = Alignment(horizontal='center')
|
||||
|
||||
# Column width
|
||||
sheet.column_dimensions['A'].width = 20
|
||||
|
||||
wb.save('output.xlsx')
|
||||
```
|
||||
|
||||
### Editing existing Excel files
|
||||
|
||||
```python
|
||||
# Using openpyxl to preserve formulas and formatting
|
||||
from openpyxl import load_workbook
|
||||
|
||||
# Load existing file
|
||||
wb = load_workbook('existing.xlsx')
|
||||
sheet = wb.active # or wb['SheetName'] for specific sheet
|
||||
|
||||
# Working with multiple sheets
|
||||
for sheet_name in wb.sheetnames:
|
||||
sheet = wb[sheet_name]
|
||||
print(f"Sheet: {sheet_name}")
|
||||
|
||||
# Modify cells
|
||||
sheet['A1'] = 'New Value'
|
||||
sheet.insert_rows(2) # Insert row at position 2
|
||||
sheet.delete_cols(3) # Delete column 3
|
||||
|
||||
# Add new sheet
|
||||
new_sheet = wb.create_sheet('NewSheet')
|
||||
new_sheet['A1'] = 'Data'
|
||||
|
||||
wb.save('modified.xlsx')
|
||||
```
|
||||
|
||||
## Recalculating formulas
|
||||
|
||||
Excel files created or modified by openpyxl contain formulas as strings but not calculated values. Use the provided `scripts/recalc.py` script to recalculate formulas:
|
||||
|
||||
```bash
|
||||
python scripts/recalc.py <excel_file> [timeout_seconds]
|
||||
```
|
||||
|
||||
Example:
|
||||
```bash
|
||||
python scripts/recalc.py output.xlsx 30
|
||||
```
|
||||
|
||||
The script:
|
||||
- Automatically sets up LibreOffice macro on first run
|
||||
- Recalculates all formulas in all sheets
|
||||
- Scans ALL cells for Excel errors (#REF!, #DIV/0!, etc.)
|
||||
- Returns JSON with detailed error locations and counts
|
||||
- Works on both Linux and macOS
|
||||
|
||||
## Formula Verification Checklist
|
||||
|
||||
Quick checks to ensure formulas work correctly:
|
||||
|
||||
### Essential Verification
|
||||
- [ ] **Test 2-3 sample references**: Verify they pull correct values before building full model
|
||||
- [ ] **Column mapping**: Confirm Excel columns match (e.g., column 64 = BL, not BK)
|
||||
- [ ] **Row offset**: Remember Excel rows are 1-indexed (DataFrame row 5 = Excel row 6)
|
||||
|
||||
### Common Pitfalls
|
||||
- [ ] **NaN handling**: Check for null values with `pd.notna()`
|
||||
- [ ] **Far-right columns**: FY data often in columns 50+
|
||||
- [ ] **Multiple matches**: Search all occurrences, not just first
|
||||
- [ ] **Division by zero**: Check denominators before using `/` in formulas (#DIV/0!)
|
||||
- [ ] **Wrong references**: Verify all cell references point to intended cells (#REF!)
|
||||
- [ ] **Cross-sheet references**: Use correct format (Sheet1!A1) for linking sheets
|
||||
|
||||
### Formula Testing Strategy
|
||||
- [ ] **Start small**: Test formulas on 2-3 cells before applying broadly
|
||||
- [ ] **Verify dependencies**: Check all cells referenced in formulas exist
|
||||
- [ ] **Test edge cases**: Include zero, negative, and very large values
|
||||
|
||||
### Interpreting scripts/recalc.py Output
|
||||
The script returns JSON with error details:
|
||||
```json
|
||||
{
|
||||
"status": "success", // or "errors_found"
|
||||
"total_errors": 0, // Total error count
|
||||
"total_formulas": 42, // Number of formulas in file
|
||||
"error_summary": { // Only present if errors found
|
||||
"#REF!": {
|
||||
"count": 2,
|
||||
"locations": ["Sheet1!B5", "Sheet1!C10"]
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## Best Practices
|
||||
|
||||
### Library Selection
|
||||
- **pandas**: Best for data analysis, bulk operations, and simple data export
|
||||
- **openpyxl**: Best for complex formatting, formulas, and Excel-specific features
|
||||
|
||||
### Working with openpyxl
|
||||
- Cell indices are 1-based (row=1, column=1 refers to cell A1)
|
||||
- Use `data_only=True` to read calculated values: `load_workbook('file.xlsx', data_only=True)`
|
||||
- **Warning**: If opened with `data_only=True` and saved, formulas are replaced with values and permanently lost
|
||||
- For large files: Use `read_only=True` for reading or `write_only=True` for writing
|
||||
- Formulas are preserved but not evaluated - use scripts/recalc.py to update values
|
||||
|
||||
### Working with pandas
|
||||
- Specify data types to avoid inference issues: `pd.read_excel('file.xlsx', dtype={'id': str})`
|
||||
- For large files, read specific columns: `pd.read_excel('file.xlsx', usecols=['A', 'C', 'E'])`
|
||||
- Handle dates properly: `pd.read_excel('file.xlsx', parse_dates=['date_column'])`
|
||||
|
||||
## Code Style Guidelines
|
||||
**IMPORTANT**: When generating Python code for Excel operations:
|
||||
- Write minimal, concise Python code without unnecessary comments
|
||||
- Avoid verbose variable names and redundant operations
|
||||
- Avoid unnecessary print statements
|
||||
|
||||
**For Excel files themselves**:
|
||||
- Add comments to cells with complex formulas or important assumptions
|
||||
- Document data sources for hardcoded values
|
||||
- Include notes for key calculations and model sections
|
||||
Reference in New Issue
Block a user