mirror of
https://github.com/catlog22/Claude-Code-Workflow.git
synced 2026-02-14 02:42:04 +08:00
feat(discovery): enhance discovery index reading and issue exporting
- Improved the reading of the discovery index by adding a fallback mechanism to scan directories for discovery folders if the index.json is invalid or missing. - Added sorting of discoveries by creation time in descending order. - Enhanced the `appendToIssuesJsonl` function to include deduplication logic for issues based on ID and source finding ID. - Updated the discovery route handler to reflect the number of issues added and skipped during export. - Introduced UI elements for selecting and deselecting findings in the dashboard. - Added CSS styles for exported findings and action buttons. - Implemented search functionality for filtering findings based on title, file, and description. - Added internationalization support for new UI elements. - Created scripts for automated API extraction from various project types, including FastAPI and TypeScript. - Documented the API extraction process and library bundling instructions.
This commit is contained in:
161
.claude/skills/software-manual/phases/02.5-api-extraction.md
Normal file
161
.claude/skills/software-manual/phases/02.5-api-extraction.md
Normal file
@@ -0,0 +1,161 @@
|
||||
# Phase 2.5: API Extraction
|
||||
|
||||
在项目探索后、并行分析前,自动提取 API 文档。
|
||||
|
||||
## 核心原则
|
||||
|
||||
**使用成熟工具提取,确保输出格式与 wiki 模板兼容。**
|
||||
|
||||
## 执行流程
|
||||
|
||||
```javascript
|
||||
const config = JSON.parse(Read(`${workDir}/manual-config.json`));
|
||||
|
||||
// 检查项目路径配置
|
||||
const apiSources = config.api_sources || detectApiSources(config.project_path);
|
||||
|
||||
// 执行 API 提取
|
||||
Bash({
|
||||
command: `python .claude/skills/software-manual/scripts/extract_apis.py -o "${workDir}" -p ${apiSources.join(' ')}`
|
||||
});
|
||||
|
||||
// 验证输出
|
||||
const apiDocsDir = `${workDir}/api-docs`;
|
||||
const extractedFiles = Glob(`${apiDocsDir}/**/*.{json,md}`);
|
||||
console.log(`Extracted ${extractedFiles.length} API documentation files`);
|
||||
```
|
||||
|
||||
## 支持的项目类型
|
||||
|
||||
| 类型 | 检测方式 | 提取工具 | 输出格式 |
|
||||
|------|----------|----------|----------|
|
||||
| FastAPI | `app/main.py` + FastAPI import | OpenAPI JSON | `openapi.json` + `API_SUMMARY.md` |
|
||||
| Next.js | `package.json` + next | TypeDoc | `*.md` (Markdown) |
|
||||
| Python Module | `__init__.py` + setup.py/pyproject.toml | pdoc | `*.md` (Markdown) |
|
||||
| Express | `package.json` + express | swagger-jsdoc | `openapi.json` |
|
||||
| NestJS | `package.json` + @nestjs | @nestjs/swagger | `openapi.json` |
|
||||
|
||||
## 输出格式规范
|
||||
|
||||
### Markdown 兼容性要求
|
||||
|
||||
确保输出 Markdown 与 wiki CSS 样式兼容:
|
||||
|
||||
```markdown
|
||||
# API Reference → <h1> (wiki-base.css)
|
||||
|
||||
## Endpoints → <h2>
|
||||
|
||||
| Method | Path | Summary | → <table> 蓝色表头
|
||||
|--------|------|---------|
|
||||
| `GET` | `/api/...` | ... | → <code> 红色高亮
|
||||
|
||||
### GET /api/users → <h3>
|
||||
|
||||
\`\`\`json → <pre><code> 深色背景
|
||||
{
|
||||
"id": 1,
|
||||
"name": "example"
|
||||
}
|
||||
\`\`\`
|
||||
|
||||
- Parameter: `id` (required) → <ul><li> + <code>
|
||||
```
|
||||
|
||||
### 格式验证检查
|
||||
|
||||
```javascript
|
||||
function validateApiDocsFormat(apiDocsDir) {
|
||||
const issues = [];
|
||||
const mdFiles = Glob(`${apiDocsDir}/**/*.md`);
|
||||
|
||||
for (const file of mdFiles) {
|
||||
const content = Read(file);
|
||||
|
||||
// 检查表格格式
|
||||
if (content.includes('|') && !content.match(/\|.*\|.*\|/)) {
|
||||
issues.push(`${file}: 表格格式不完整`);
|
||||
}
|
||||
|
||||
// 检查代码块语言标注
|
||||
const codeBlocks = content.match(/```(\w*)\n/g) || [];
|
||||
const unlabeled = codeBlocks.filter(b => b === '```\n');
|
||||
if (unlabeled.length > 0) {
|
||||
issues.push(`${file}: ${unlabeled.length} 个代码块缺少语言标注`);
|
||||
}
|
||||
|
||||
// 检查标题层级
|
||||
if (!content.match(/^# /m)) {
|
||||
issues.push(`${file}: 缺少一级标题`);
|
||||
}
|
||||
}
|
||||
|
||||
return issues;
|
||||
}
|
||||
```
|
||||
|
||||
## 项目配置示例
|
||||
|
||||
在 `manual-config.json` 中配置 API 源:
|
||||
|
||||
```json
|
||||
{
|
||||
"software": {
|
||||
"name": "Hydro Generator Workbench",
|
||||
"type": "web"
|
||||
},
|
||||
"api_sources": {
|
||||
"backend": {
|
||||
"path": "D:/dongdiankaifa9/backend",
|
||||
"type": "fastapi",
|
||||
"entry": "app.main:app"
|
||||
},
|
||||
"frontend": {
|
||||
"path": "D:/dongdiankaifa9/frontend",
|
||||
"type": "typescript",
|
||||
"entries": ["lib", "hooks", "components"]
|
||||
},
|
||||
"hydro_generator_module": {
|
||||
"path": "D:/dongdiankaifa9/hydro_generator_module",
|
||||
"type": "python"
|
||||
},
|
||||
"multiphysics_network": {
|
||||
"path": "D:/dongdiankaifa9/multiphysics_network",
|
||||
"type": "python"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
## 输出结构
|
||||
|
||||
```
|
||||
{workDir}/api-docs/
|
||||
├── backend/
|
||||
│ ├── openapi.json # OpenAPI 3.0 规范
|
||||
│ └── API_SUMMARY.md # Markdown 摘要(wiki 兼容)
|
||||
├── frontend/
|
||||
│ ├── modules.md # TypeDoc 模块文档
|
||||
│ ├── classes/ # 类文档
|
||||
│ └── functions/ # 函数文档
|
||||
├── hydro_generator/
|
||||
│ ├── assembler.md # pdoc 模块文档
|
||||
│ ├── blueprint.md
|
||||
│ └── builders/
|
||||
└── multiphysics/
|
||||
├── analysis_domain.md
|
||||
├── builders.md
|
||||
└── compilers.md
|
||||
```
|
||||
|
||||
## 质量门禁
|
||||
|
||||
- [ ] 所有配置的 API 源已提取
|
||||
- [ ] Markdown 格式与 wiki CSS 兼容
|
||||
- [ ] 表格正确渲染(蓝色表头)
|
||||
- [ ] 代码块有语言标注
|
||||
- [ ] 无空文件或错误文件
|
||||
|
||||
## 下一阶段
|
||||
|
||||
→ [Phase 3: Parallel Analysis](03-parallel-analysis.md)
|
||||
@@ -11,51 +11,66 @@ const AGENT_CONFIGS = {
|
||||
output: 'section-overview.md',
|
||||
task: '撰写产品概览、核心功能、快速入门指南',
|
||||
focus: '产品定位、目标用户、5步快速入门、系统要求',
|
||||
input: ['exploration-architecture.json', 'README.md', 'package.json']
|
||||
input: ['exploration-architecture.json', 'README.md', 'package.json'],
|
||||
tag: 'getting-started'
|
||||
},
|
||||
'ui-guide': {
|
||||
role: 'UX Expert',
|
||||
output: 'section-ui-guide.md',
|
||||
task: '撰写界面操作指南,标注所有需要截图的 UI 元素',
|
||||
focus: '界面布局、导航流程、功能操作、快捷键',
|
||||
input: ['exploration-ui-routes.json', 'pages/**', 'views/**'],
|
||||
'interface-guide': {
|
||||
role: 'Product Designer',
|
||||
output: 'section-interface.md',
|
||||
task: '撰写界面或交互指南(Web 截图、CLI 命令交互、桌面应用操作)',
|
||||
focus: '视觉布局、交互流程、命令行参数、输入/输出示例',
|
||||
input: ['exploration-ui-routes.json', 'src/**', 'pages/**', 'views/**', 'components/**', 'src/commands/**'],
|
||||
tag: 'interface',
|
||||
screenshot_rules: `
|
||||
每个关键 UI 交互点必须插入截图标记:
|
||||
<!-- SCREENSHOT: id="ss-{功能}-{状态}" url="{路由}" selector="{CSS选择器}" wait_for="{等待元素}" description="{描述}" -->
|
||||
根据项目类型标注交互点:
|
||||
|
||||
示例:
|
||||
- 页面全貌: <!-- SCREENSHOT: id="ss-dashboard-overview" url="/dashboard" description="仪表盘主界面" -->
|
||||
- 特定组件: <!-- SCREENSHOT: id="ss-login-form" url="/login" selector=".login-form" description="登录表单" -->
|
||||
- 交互状态: <!-- SCREENSHOT: id="ss-modal-open" url="/settings" selector=".modal" wait_for=".modal.show" description="设置弹窗" -->
|
||||
[Web] <!-- SCREENSHOT: id="ss-{功能}" url="{路由}" selector="{CSS选择器}" description="{描述}" -->
|
||||
[CLI] 使用代码块展示命令交互:
|
||||
\`\`\`bash
|
||||
$ command --flag value
|
||||
Expected output here
|
||||
\`\`\`
|
||||
[Desktop] <!-- SCREENSHOT: id="ss-{功能}" description="{描述}" -->
|
||||
`
|
||||
},
|
||||
'api-docs': {
|
||||
role: 'API Architect',
|
||||
output: 'section-api-reference.md',
|
||||
task: '撰写 REST API 和前端 API 参考文档',
|
||||
focus: 'API 概览、端点分类、请求/响应示例、错误码',
|
||||
input: ['exploration-api-endpoints.json', 'controllers/**', 'routes/**']
|
||||
'api-reference': {
|
||||
role: 'Technical Architect',
|
||||
output: 'section-reference.md',
|
||||
task: '撰写接口参考文档(REST API / 函数库 / CLI 命令)',
|
||||
focus: '函数签名、端点定义、参数说明、返回值、错误代码',
|
||||
pre_extract: 'python .claude/skills/software-manual/scripts/extract_apis.py -o ${workDir}',
|
||||
input: [
|
||||
'${workDir}/api-docs/backend/openapi.json', // FastAPI OpenAPI
|
||||
'${workDir}/api-docs/backend/API_SUMMARY.md', // Backend summary
|
||||
'${workDir}/api-docs/frontend/**/*.md', // TypeDoc output
|
||||
'${workDir}/api-docs/hydro_generator/**/*.md', // Python module
|
||||
'${workDir}/api-docs/multiphysics/**/*.md' // Python module
|
||||
],
|
||||
tag: 'api'
|
||||
},
|
||||
config: {
|
||||
role: 'DevOps Engineer',
|
||||
output: 'section-configuration.md',
|
||||
task: '撰写配置指南,涵盖环境变量、配置文件、部署设置',
|
||||
focus: '环境变量表格、配置文件格式、部署选项、安全设置',
|
||||
input: ['exploration-config.json', '.env.example', 'config/**']
|
||||
input: ['exploration-config.json', '.env.example', 'config/**', '*.config.*'],
|
||||
tag: 'config'
|
||||
},
|
||||
troubleshooting: {
|
||||
role: 'Support Engineer',
|
||||
output: 'section-troubleshooting.md',
|
||||
task: '撰写故障排查指南,涵盖常见问题、错误码、FAQ',
|
||||
focus: '常见问题与解决方案、错误码参考、FAQ、获取帮助',
|
||||
input: ['all exploration files', 'error handling code']
|
||||
input: ['docs/troubleshooting.md', 'src/**/errors.*', 'src/**/exceptions.*', 'TROUBLESHOOTING.md'],
|
||||
tag: 'troubleshooting'
|
||||
},
|
||||
'code-examples': {
|
||||
role: 'Developer Advocate',
|
||||
output: 'section-examples.md',
|
||||
task: '撰写多难度级别代码示例(入门40%/进阶40%/高级20%)',
|
||||
focus: '完整可运行代码、分步解释、预期输出、最佳实践',
|
||||
input: ['all exploration files', 'examples/**', 'tests/**']
|
||||
input: ['examples/**', 'tests/**', 'demo/**', 'samples/**'],
|
||||
tag: 'examples'
|
||||
}
|
||||
};
|
||||
```
|
||||
@@ -65,7 +80,16 @@ const AGENT_CONFIGS = {
|
||||
```javascript
|
||||
const config = JSON.parse(Read(`${workDir}/manual-config.json`));
|
||||
|
||||
// 并行启动 6 个 universal-executor
|
||||
// 1. 预提取 API 文档(如有 pre_extract 配置)
|
||||
for (const [name, cfg] of Object.entries(AGENT_CONFIGS)) {
|
||||
if (cfg.pre_extract) {
|
||||
const cmd = cfg.pre_extract.replace(/\$\{workDir\}/g, workDir);
|
||||
console.log(`[Pre-extract] ${name}: ${cmd}`);
|
||||
Bash({ command: cmd });
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 并行启动 6 个 universal-executor
|
||||
const tasks = Object.entries(AGENT_CONFIGS).map(([name, cfg]) =>
|
||||
Task({
|
||||
subagent_type: 'universal-executor',
|
||||
@@ -83,35 +107,51 @@ const results = await Promise.all(tasks);
|
||||
function buildAgentPrompt(name, cfg, config, workDir) {
|
||||
const screenshotSection = cfg.screenshot_rules
|
||||
? `\n[SCREENSHOT RULES]\n${cfg.screenshot_rules}`
|
||||
: '\n[SCREENSHOT]\n截图标记: <!-- SCREENSHOT: id="ss-xxx" url="/path" description="xxx" -->';
|
||||
: '';
|
||||
|
||||
return `
|
||||
[ROLE] ${cfg.role}
|
||||
|
||||
[PROJECT CONTEXT]
|
||||
项目类型: ${config.software.type} (web/cli/sdk/desktop)
|
||||
语言: ${config.software.language || 'auto-detect'}
|
||||
名称: ${config.software.name}
|
||||
|
||||
[TASK]
|
||||
${cfg.task}
|
||||
输出: ${workDir}/sections/${cfg.output}
|
||||
|
||||
[INPUT]
|
||||
- Read: ${workDir}/manual-config.json
|
||||
- Read: ${cfg.input.map(f => `${workDir}/exploration/${f}`).join(', ')}
|
||||
- 配置: ${workDir}/manual-config.json
|
||||
- 探索结果: ${workDir}/exploration/
|
||||
- 扫描路径: ${cfg.input.join(', ')}
|
||||
|
||||
[STYLE]
|
||||
- 用户友好语言,避免技术术语
|
||||
- 步骤编号清晰
|
||||
- 代码块标注语言
|
||||
[CONTENT REQUIREMENTS]
|
||||
- 标题层级: # ## ### (最多3级)
|
||||
- 代码块: \`\`\`language ... \`\`\` (必须标注语言)
|
||||
- 表格: | col1 | col2 | 格式
|
||||
- 列表: 有序 1. 2. 3. / 无序 - - -
|
||||
- 内联代码: \`code\`
|
||||
- 链接: [text](url)
|
||||
${screenshotSection}
|
||||
|
||||
[FOCUS]
|
||||
${cfg.focus}
|
||||
|
||||
[OUTPUT FORMAT]
|
||||
Markdown 文件,包含:
|
||||
- 清晰的章节结构
|
||||
- 具体的代码示例
|
||||
- 参数/配置表格
|
||||
- 常见用例说明
|
||||
|
||||
[RETURN JSON]
|
||||
{
|
||||
"status": "completed",
|
||||
"output_file": "sections/${cfg.output}",
|
||||
"summary": "<50字>",
|
||||
"screenshots_needed": [{ "id": "ss-xxx", "url": "/path", "selector": ".class", "description": "..." }],
|
||||
"cross_references": []
|
||||
"tag": "${cfg.tag}",
|
||||
"screenshots_needed": []
|
||||
}
|
||||
`;
|
||||
}
|
||||
|
||||
@@ -29,29 +29,40 @@ function buildAssemblyPrompt(config, workDir) {
|
||||
[ROLE] HTML Assembler
|
||||
|
||||
[TASK]
|
||||
生成 TiddlyWiki 风格的交互式 HTML 手册
|
||||
生成 TiddlyWiki 风格的交互式 HTML 手册(使用成熟库,无外部 CDN 依赖)
|
||||
|
||||
[INPUT]
|
||||
- 模板: .claude/skills/software-manual/templates/tiddlywiki-shell.html
|
||||
- CSS: .claude/skills/software-manual/templates/css/wiki-base.css, wiki-dark.css
|
||||
- 配置: ${workDir}/manual-config.json
|
||||
- 章节: ${workDir}/sections/section-*.md
|
||||
- Agent 结果: ${workDir}/agent-results.json (含 tag 信息)
|
||||
- 截图: ${workDir}/screenshots/
|
||||
|
||||
[LIBRARIES TO EMBED]
|
||||
1. marked.js (v14+) - Markdown 转 HTML
|
||||
- 从 https://unpkg.com/marked/marked.min.js 获取内容内嵌
|
||||
2. highlight.js (v11+) - 代码语法高亮
|
||||
- 核心 + 常用语言包 (js, ts, python, bash, json, yaml, html, css)
|
||||
- 使用 github-dark 主题
|
||||
|
||||
[STEPS]
|
||||
1. 读取 HTML 模板和 CSS
|
||||
2. 逐个读取 section-*.md,转换为 HTML tiddlers
|
||||
3. 处理 <!-- SCREENSHOT: id="..." --> 标记,嵌入 Base64 图片
|
||||
4. 生成目录、搜索索引
|
||||
5. 组装最终 HTML,写入 ${workDir}/${config.software.name}-使用手册.html
|
||||
6. 生成构建报告 ${workDir}/build-report.json
|
||||
2. 内嵌 marked.js 和 highlight.js 代码
|
||||
3. 读取 agent-results.json 提取各章节 tag
|
||||
4. 动态生成 {{TAG_BUTTONS_HTML}} (基于实际使用的 tags)
|
||||
5. 逐个读取 section-*.md,使用 marked 转换为 HTML
|
||||
6. 为代码块添加 data-language 属性和语法高亮
|
||||
7. 处理 <!-- SCREENSHOT: id="..." --> 标记,嵌入 Base64 图片
|
||||
8. 生成目录、搜索索引
|
||||
9. 组装最终 HTML,写入 ${workDir}/${config.software.name}-使用手册.html
|
||||
|
||||
[HTML FEATURES]
|
||||
- 搜索: 全文检索 + 高亮
|
||||
- 折叠: 章节可展开/收起
|
||||
- 标签: 分类过滤
|
||||
- 主题: 亮/暗模式切换
|
||||
- 离线: 所有资源内嵌
|
||||
[CONTENT FORMATTING]
|
||||
- 代码块: 深色背景 + 语言标签 + 语法高亮
|
||||
- 表格: 蓝色表头 + 边框 + 悬停效果
|
||||
- 内联代码: 红色高亮
|
||||
- 列表: 有序/无序样式增强
|
||||
- 左侧导航: 固定侧边栏 + TOC
|
||||
|
||||
[RETURN JSON]
|
||||
{
|
||||
@@ -59,6 +70,7 @@ function buildAssemblyPrompt(config, workDir) {
|
||||
"output_file": "${config.software.name}-使用手册.html",
|
||||
"file_size": "<size>",
|
||||
"sections_count": <n>,
|
||||
"tags_generated": [],
|
||||
"screenshots_embedded": <n>
|
||||
}
|
||||
`;
|
||||
|
||||
Reference in New Issue
Block a user