sumulige-claude 1.0.11 → 1.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/todos.md +41 -6
- package/.claude/hooks/session-restore.cjs +102 -0
- package/.claude/hooks/session-save.cjs +164 -0
- package/.claude/hooks/todo-manager.cjs +262 -141
- package/.claude/settings.local.json +11 -1
- package/.claude/skills/api-tester/SKILL.md +52 -23
- package/.claude/skills/test-workflow/SKILL.md +191 -0
- package/.claude/templates/tasks/develop.md +69 -0
- package/.claude/templates/tasks/research.md +64 -0
- package/.claude/templates/tasks/test.md +96 -0
- package/.claude-plugin/marketplace.json +2 -2
- package/.versionrc +25 -0
- package/AGENTS.md +7 -1
- package/CHANGELOG.md +83 -4
- package/PROJECT_STRUCTURE.md +40 -3
- package/Q&A.md +184 -0
- package/README.md +52 -2
- package/cli.js +74 -5
- package/config/official-skills.json +183 -0
- package/development/todos/.state.json +4 -0
- package/development/todos/INDEX.md +64 -38
- package/docs/RELEASE.md +93 -0
- package/lib/commands.js +1657 -39
- package/lib/utils.js +102 -14
- package/lib/version-check.js +169 -0
- package/package.json +7 -2
- package/template/.claude/hooks/project-kickoff.cjs +190 -1
- package/template/.claude/hooks/session-restore.cjs +102 -0
- package/template/.claude/hooks/session-save.cjs +164 -0
|
@@ -1,20 +1,15 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
/**
|
|
3
|
-
* TODO Manager - AI 自动任务管理系统
|
|
3
|
+
* TODO Manager - AI 自动任务管理系统 (v2.0)
|
|
4
4
|
*
|
|
5
5
|
* 功能:
|
|
6
|
-
* -
|
|
7
|
-
* -
|
|
6
|
+
* - 支持 Research → Develop → Test 生命周期
|
|
7
|
+
* - 自动任务状态流转
|
|
8
|
+
* - 智能任务创建建议
|
|
8
9
|
* - 维护任务状态流转
|
|
9
|
-
* - 静默运行,不打扰工作流
|
|
10
10
|
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
* ├── INDEX.md # 任务总览
|
|
14
|
-
* ├── active/ # 进行中的任务
|
|
15
|
-
* ├── completed/ # 已完成的任务
|
|
16
|
-
* ├── backlog/ # 待办任务
|
|
17
|
-
* └── archived/ # 已归档任务
|
|
11
|
+
* 生命周期:
|
|
12
|
+
* Research (研究) → Develop (开发) → Test (测试) → Done (完成)
|
|
18
13
|
*/
|
|
19
14
|
|
|
20
15
|
const fs = require('fs');
|
|
@@ -25,55 +20,81 @@ const TODOS_DIR = path.join(PROJECT_DIR, 'development', 'todos');
|
|
|
25
20
|
const INDEX_FILE = path.join(TODOS_DIR, 'INDEX.md');
|
|
26
21
|
const STATE_FILE = path.join(TODOS_DIR, '.state.json');
|
|
27
22
|
|
|
28
|
-
//
|
|
29
|
-
const
|
|
23
|
+
// 任务类型和状态
|
|
24
|
+
const TASK_TYPES = {
|
|
25
|
+
RESEARCH: 'research',
|
|
26
|
+
DEVELOP: 'develop',
|
|
27
|
+
TEST: 'test'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const TASK_STAGES = {
|
|
30
31
|
ACTIVE: 'active',
|
|
31
32
|
COMPLETED: 'completed',
|
|
32
33
|
BACKLOG: 'backlog',
|
|
33
34
|
ARCHIVED: 'archived'
|
|
34
35
|
};
|
|
35
36
|
|
|
37
|
+
// 图标映射
|
|
38
|
+
const ICONS = {
|
|
39
|
+
research: '📊',
|
|
40
|
+
develop: '💻',
|
|
41
|
+
test: '🧪'
|
|
42
|
+
};
|
|
43
|
+
|
|
36
44
|
// 确保目录存在
|
|
37
45
|
function ensureDirectories() {
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
46
|
+
const dirs = [TODOS_DIR];
|
|
47
|
+
|
|
48
|
+
// 为每个阶段创建类型子目录
|
|
49
|
+
for (const stage of Object.values(TASK_STAGES)) {
|
|
50
|
+
dirs.push(path.join(TODOS_DIR, stage));
|
|
51
|
+
for (const type of Object.values(TASK_TYPES)) {
|
|
52
|
+
dirs.push(path.join(TODOS_DIR, stage, type));
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
dirs.forEach(dir => {
|
|
57
|
+
try { fs.mkdirSync(dir, { recursive: true }); } catch (e) {}
|
|
41
58
|
});
|
|
42
59
|
}
|
|
43
60
|
|
|
44
61
|
// 扫描任务文件
|
|
45
62
|
function scanTasks() {
|
|
46
63
|
const tasks = {
|
|
47
|
-
active: [],
|
|
48
|
-
completed: [],
|
|
49
|
-
backlog: [],
|
|
50
|
-
archived: []
|
|
64
|
+
active: { research: [], develop: [], test: [] },
|
|
65
|
+
completed: { research: [], develop: [], test: [] },
|
|
66
|
+
backlog: { research: [], develop: [], test: [] },
|
|
67
|
+
archived: { research: [], develop: [], test: [] }
|
|
51
68
|
};
|
|
52
69
|
|
|
53
|
-
for (const [
|
|
54
|
-
const
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
70
|
+
for (const [stage, types] of Object.entries(tasks)) {
|
|
71
|
+
for (const [type, _] of Object.entries(types)) {
|
|
72
|
+
const dir = path.join(TODOS_DIR, stage, type);
|
|
73
|
+
if (!fs.existsSync(dir)) continue;
|
|
74
|
+
|
|
75
|
+
const files = fs.readdirSync(dir)
|
|
76
|
+
.filter(f => f.endsWith('.md') && f !== '_README.md');
|
|
77
|
+
|
|
78
|
+
tasks[stage][type] = files.map(f => {
|
|
79
|
+
const filePath = path.join(dir, f);
|
|
80
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
81
|
+
const titleMatch = content.match(/^#\s+(.+)$/m);
|
|
82
|
+
const statusMatch = content.match(/\*\*状态\*\*:\s*([✅🚧📋])/);
|
|
83
|
+
const priorityMatch = content.match(/\*\*优先级\*\*:\s*(P[0-3])/);
|
|
84
|
+
const typeMatch = content.match(/\*\*类型\*\*:\s*([📊💻🧪])\s*(\w+)/);
|
|
85
|
+
|
|
86
|
+
return {
|
|
87
|
+
file: f,
|
|
88
|
+
title: titleMatch ? titleMatch[1] : path.basename(f, '.md'),
|
|
89
|
+
status: statusMatch ? statusMatch[1] : '🚧',
|
|
90
|
+
priority: priorityMatch ? priorityMatch[1] : 'P2',
|
|
91
|
+
taskType: typeMatch ? typeMatch[1] : type,
|
|
92
|
+
icon: typeMatch ? typeMatch[2] : ICONS[type] || '📄',
|
|
93
|
+
path: `${stage}/${type}/${f}`,
|
|
94
|
+
stage: stage
|
|
95
|
+
};
|
|
96
|
+
});
|
|
97
|
+
}
|
|
77
98
|
}
|
|
78
99
|
|
|
79
100
|
return tasks;
|
|
@@ -83,138 +104,211 @@ function scanTasks() {
|
|
|
83
104
|
function generateIndex(tasks) {
|
|
84
105
|
const now = new Date().toISOString().split('T')[0];
|
|
85
106
|
|
|
107
|
+
// 计算总数
|
|
108
|
+
const activeCount = tasks.active.research.length + tasks.active.develop.length + tasks.active.test.length;
|
|
109
|
+
const completedCount = tasks.completed.research.length + tasks.completed.develop.length + tasks.completed.test.length;
|
|
110
|
+
const backlogCount = tasks.backlog.research.length + tasks.backlog.develop.length + tasks.backlog.test.length;
|
|
111
|
+
|
|
86
112
|
let md = `# 项目任务追踪系统
|
|
87
113
|
|
|
88
|
-
>
|
|
114
|
+
> **统一管理**: 研究 → 开发 → 测试
|
|
115
|
+
> **最后更新**: ${now}
|
|
116
|
+
|
|
117
|
+
@version: 2.0.0
|
|
118
|
+
|
|
119
|
+
---
|
|
120
|
+
|
|
121
|
+
## 📊 项目进度
|
|
122
|
+
|
|
123
|
+
| 阶段 | 进度 | 状态 |
|
|
124
|
+
|------|------|------|
|
|
125
|
+
| Phase 1: MVP 智能监控 | 80% | 🚧 进行中 |
|
|
126
|
+
| Phase 2: V1.5 动态调整 | 0% | 📋 待规划 |
|
|
127
|
+
| Phase 3: V2.0 AI 教练 | 0% | 📋 待规划 |
|
|
128
|
+
|
|
129
|
+
---
|
|
89
130
|
|
|
90
|
-
|
|
131
|
+
## 🔄 任务生命周期
|
|
91
132
|
|
|
92
|
-
|
|
133
|
+
\`\`\`
|
|
134
|
+
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
|
|
135
|
+
│ RESEARCH │ → │ DEVELOP │ → │ TEST │
|
|
136
|
+
│ 📊 研究 │ │ 💻 开发 │ │ 🧪 测试 │
|
|
137
|
+
└─────────────┘ └─────────────┘ └─────────────┘
|
|
138
|
+
\`\`\`
|
|
93
139
|
|
|
94
|
-
|
|
140
|
+
---
|
|
141
|
+
|
|
142
|
+
## 📁 目录结构
|
|
95
143
|
|
|
96
144
|
\`\`\`
|
|
97
145
|
development/todos/
|
|
98
146
|
├── INDEX.md # 本文件 - 任务总览
|
|
99
|
-
├──
|
|
100
|
-
├──
|
|
101
|
-
├──
|
|
102
|
-
|
|
147
|
+
├── _templates/ # 任务模板
|
|
148
|
+
├── active/ # 进行中的任务 (${activeCount})
|
|
149
|
+
│ ├── research/ # 📊 研究中 (${tasks.active.research.length})
|
|
150
|
+
│ ├── develop/ # 💻 开发中 (${tasks.active.develop.length})
|
|
151
|
+
│ └── test/ # 🧪 测试中 (${tasks.active.test.length})
|
|
152
|
+
├── completed/ # 已完成的任务 (${completedCount})
|
|
153
|
+
│ ├── research/
|
|
154
|
+
│ ├── develop/
|
|
155
|
+
│ └── test/
|
|
156
|
+
├── backlog/ # 待规划的任务 (${backlogCount})
|
|
157
|
+
└── archived/ # 已归档的任务
|
|
103
158
|
\`\`\`
|
|
104
159
|
|
|
105
|
-
|
|
160
|
+
---
|
|
161
|
+
|
|
162
|
+
## 🚧 当前进行中的任务
|
|
106
163
|
|
|
164
|
+
### 📊 研究任务
|
|
107
165
|
`;
|
|
108
166
|
|
|
109
|
-
//
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}${t.branch ? ` \`branch: ${t.branch}\`` : ''}\n`;
|
|
167
|
+
// 研究任务
|
|
168
|
+
if (tasks.active.research.length > 0) {
|
|
169
|
+
tasks.active.research.forEach(t => {
|
|
170
|
+
md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
|
|
114
171
|
});
|
|
115
172
|
} else {
|
|
116
|
-
md +=
|
|
173
|
+
md += `暂无\n`;
|
|
117
174
|
}
|
|
118
|
-
md += `\n`;
|
|
119
|
-
|
|
120
|
-
//
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
recentCompleted.forEach(t => {
|
|
125
|
-
md += `- [${t.title}](./${t.path})\n`;
|
|
175
|
+
md += `\n### 💻 开发任务\n`;
|
|
176
|
+
|
|
177
|
+
// 开发任务
|
|
178
|
+
if (tasks.active.develop.length > 0) {
|
|
179
|
+
tasks.active.develop.forEach(t => {
|
|
180
|
+
md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
|
|
126
181
|
});
|
|
127
|
-
if (tasks.completed.length > 5) {
|
|
128
|
-
md += `- ...还有 ${tasks.completed.length - 5} 个已完成任务\n`;
|
|
129
|
-
}
|
|
130
182
|
} else {
|
|
131
|
-
md +=
|
|
183
|
+
md += `暂无\n`;
|
|
132
184
|
}
|
|
133
|
-
md += `\n`;
|
|
185
|
+
md += `\n### 🧪 测试任务\n`;
|
|
134
186
|
|
|
135
|
-
//
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
187
|
+
// 测试任务
|
|
188
|
+
if (tasks.active.test.length > 0) {
|
|
189
|
+
tasks.active.test.forEach(t => {
|
|
190
|
+
md += `- [${t.priority}] [${t.title}](./${t.path}) - ${t.status}\n`;
|
|
191
|
+
});
|
|
192
|
+
} else {
|
|
193
|
+
md += `暂无\n`;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
md += `\n---\n\n## ✅ 最近完成的任务\n\n### 💻 开发任务\n`;
|
|
197
|
+
|
|
198
|
+
// 最近完成的开发任务
|
|
199
|
+
if (tasks.completed.develop.length > 0) {
|
|
200
|
+
tasks.completed.develop.slice(0, 5).forEach(t => {
|
|
201
|
+
md += `- [${t.title}](./${t.path}) ${t.status}\n`;
|
|
140
202
|
});
|
|
141
|
-
if (tasks.backlog.length > 10) {
|
|
142
|
-
md += `- ...还有 ${tasks.backlog.length - 10} 个待办任务\n`;
|
|
143
|
-
}
|
|
144
203
|
} else {
|
|
145
|
-
md +=
|
|
204
|
+
md += `暂无\n`;
|
|
146
205
|
}
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
md +=
|
|
160
|
-
md +=
|
|
161
|
-
|
|
162
|
-
md +=
|
|
163
|
-
md +=
|
|
164
|
-
md += `#
|
|
165
|
-
md += `
|
|
206
|
+
|
|
207
|
+
md += `\n### 🧪 测试任务\n`;
|
|
208
|
+
|
|
209
|
+
// 最近完成的测试任务
|
|
210
|
+
if (tasks.completed.test.length > 0) {
|
|
211
|
+
tasks.completed.test.slice(0, 3).forEach(t => {
|
|
212
|
+
md += `- [${t.title}](./${t.path}) ${t.status}\n`;
|
|
213
|
+
});
|
|
214
|
+
} else {
|
|
215
|
+
md += `暂无\n`;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
md += `\n---\n\n## 📋 待办任务\n\n`;
|
|
219
|
+
md += `暂无\n`;
|
|
220
|
+
|
|
221
|
+
md += `\n---\n\n## 🎯 使用方式\n\n`;
|
|
222
|
+
md += `### 查看任务\n\`\`\`bash\n`;
|
|
223
|
+
md += `# 按类型查看\n`;
|
|
224
|
+
md += `ls development/todos/active/research/ # 研究任务\n`;
|
|
225
|
+
md += `ls development/todos/active/develop/ # 开发任务\n`;
|
|
226
|
+
md += `ls development/todos/active/test/ # 测试任务\n`;
|
|
166
227
|
md += `\`\`\`\n\n`;
|
|
228
|
+
|
|
167
229
|
md += `### 创建新任务\n`;
|
|
168
|
-
md += `在 Claude Code 中:\n`;
|
|
169
|
-
md +=
|
|
170
|
-
md +=
|
|
171
|
-
md +=
|
|
172
|
-
md += `AI 会自动在 \`active/\` 目录创建对应的任务文件。\n\n`;
|
|
173
|
-
md += `### 更新任务状态\n`;
|
|
174
|
-
md += `\`\`\`\n`;
|
|
175
|
-
md += `将 [任务名] 标记为完成\n`;
|
|
176
|
-
md += `\`\`\`\n\n`;
|
|
177
|
-
md += `AI 会自动将任务移动到 \`completed/\` 目录。\n\n`;
|
|
230
|
+
md += `在 Claude Code 中:\n\`\`\`\n`;
|
|
231
|
+
md += `创建一个新任务:\n`;
|
|
232
|
+
md += `- 类型:测试\n`;
|
|
233
|
+
md += `- 标题:Dashboard 功能测试\n\`\`\`\n\n`;
|
|
178
234
|
|
|
179
|
-
md +=
|
|
180
|
-
md +=
|
|
235
|
+
md += `### 更新任务状态\n\`\`\`\n`;
|
|
236
|
+
md += `将 [任务名] 标记为完成\n\`\`\`\n\n`;
|
|
237
|
+
|
|
238
|
+
md += `---\n\n> **维护说明**: 本系统由 AI 自动维护\n`;
|
|
181
239
|
|
|
182
240
|
return md;
|
|
183
241
|
}
|
|
184
242
|
|
|
243
|
+
// 加载和保存状态
|
|
244
|
+
function loadState() {
|
|
245
|
+
if (fs.existsSync(STATE_FILE)) {
|
|
246
|
+
try {
|
|
247
|
+
return JSON.parse(fs.readFileSync(STATE_FILE, 'utf-8'));
|
|
248
|
+
} catch (e) {
|
|
249
|
+
return { tasks: {}, transitions: [] };
|
|
250
|
+
}
|
|
251
|
+
}
|
|
252
|
+
return { tasks: {}, transitions: [] };
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
function saveState(state) {
|
|
256
|
+
fs.writeFileSync(STATE_FILE, JSON.stringify(state, null, 2));
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
// 检查是否需要自动流转
|
|
260
|
+
function checkAutoTransition(tasks, state) {
|
|
261
|
+
const suggestions = [];
|
|
262
|
+
|
|
263
|
+
// 检查刚完成的开发任务,建议创建测试任务
|
|
264
|
+
const completedDevelop = tasks.completed.develop.filter(t => {
|
|
265
|
+
const key = `completed_develop_${t.file}`;
|
|
266
|
+
return !state.tasks[key]; // 首次完成
|
|
267
|
+
});
|
|
268
|
+
|
|
269
|
+
completedDevelop.forEach(t => {
|
|
270
|
+
const testTaskName = t.file.replace('.md', '-test.md');
|
|
271
|
+
const testPath = path.join(TODOS_DIR, 'active', 'test', testTaskName);
|
|
272
|
+
|
|
273
|
+
if (!fs.existsSync(testPath)) {
|
|
274
|
+
suggestions.push({
|
|
275
|
+
type: 'create_test',
|
|
276
|
+
message: `💡 建议为 "${t.title}" 创建测试任务`,
|
|
277
|
+
developTask: t,
|
|
278
|
+
testTask: testTaskName,
|
|
279
|
+
template: `_templates/test.md`
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
// 标记已处理
|
|
284
|
+
const key = `completed_develop_${t.file}`;
|
|
285
|
+
state.tasks[key] = { completed: true, notified: true };
|
|
286
|
+
});
|
|
287
|
+
|
|
288
|
+
return { suggestions, state };
|
|
289
|
+
}
|
|
290
|
+
|
|
185
291
|
// 更新索引
|
|
186
292
|
function updateIndex() {
|
|
187
293
|
try {
|
|
188
294
|
ensureDirectories();
|
|
189
295
|
const tasks = scanTasks();
|
|
190
|
-
const
|
|
296
|
+
const state = loadState();
|
|
191
297
|
|
|
192
|
-
//
|
|
193
|
-
|
|
194
|
-
if (fs.existsSync(INDEX_FILE)) {
|
|
195
|
-
const existing = fs.readFileSync(INDEX_FILE, 'utf-8');
|
|
196
|
-
// 从现有索引中提取任务数量
|
|
197
|
-
const activeMatch = existing.match(/## 🚧 进行中的任务 \((\d+)\)/);
|
|
198
|
-
const completedMatch = existing.match(/## ✅ 最近完成的任务/);
|
|
199
|
-
const existingActive = activeMatch ? parseInt(activeMatch[1], 10) : 0;
|
|
200
|
-
const newActive = tasks.active.length;
|
|
201
|
-
|
|
202
|
-
// 如果活跃任务数量相同且没有完成任务内容变化,则不更新
|
|
203
|
-
if (existingActive === newActive && tasks.completed.length === 0) {
|
|
204
|
-
// 检查现有索引是否已有完成任务
|
|
205
|
-
const hasCompletedInExisting = existing.includes('[completed/') || existing.includes('./completed/');
|
|
206
|
-
const hasCompletedNow = tasks.completed.length > 0;
|
|
207
|
-
needsUpdate = hasCompletedInExisting !== hasCompletedNow;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
298
|
+
// 检查自动流转
|
|
299
|
+
const { suggestions, state: newState } = checkAutoTransition(tasks, state);
|
|
210
300
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
301
|
+
// 生成索引
|
|
302
|
+
const index = generateIndex(tasks);
|
|
303
|
+
fs.writeFileSync(INDEX_FILE, index);
|
|
214
304
|
|
|
215
|
-
|
|
305
|
+
// 保存状态
|
|
306
|
+
saveState(newState);
|
|
307
|
+
|
|
308
|
+
return { tasks, suggestions, updated: true };
|
|
216
309
|
} catch (e) {
|
|
217
|
-
|
|
310
|
+
console.error('[TODO Manager] Error:', e.message);
|
|
311
|
+
return { tasks: { active: { research: [], develop: [], test: [] }, completed: { research: [], develop: [], test: [] } }, suggestions: [], updated: false };
|
|
218
312
|
}
|
|
219
313
|
}
|
|
220
314
|
|
|
@@ -222,13 +316,28 @@ function updateIndex() {
|
|
|
222
316
|
function main() {
|
|
223
317
|
const result = updateIndex();
|
|
224
318
|
|
|
225
|
-
//
|
|
319
|
+
// 输出建议
|
|
320
|
+
if (result.suggestions && result.suggestions.length > 0) {
|
|
321
|
+
console.log('\n📋 [任务流转] 检测到 ' + result.suggestions.length + ' 个自动流转建议:\n');
|
|
322
|
+
result.suggestions.forEach((s, i) => {
|
|
323
|
+
console.log(` ${i + 1}. ${s.message}`);
|
|
324
|
+
});
|
|
325
|
+
console.log('');
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
// 在 AgentStop 时输出摘要
|
|
226
329
|
const eventType = process.env.CLAUDE_EVENT_TYPE || '';
|
|
227
330
|
if (eventType === 'AgentStop') {
|
|
228
|
-
const
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
331
|
+
const active = result.tasks.active;
|
|
332
|
+
const activeTotal = active.research.length + active.develop.length + active.test.length;
|
|
333
|
+
const completed = result.tasks.completed;
|
|
334
|
+
const completedTotal = completed.research.length + completed.develop.length + completed.test.length;
|
|
335
|
+
|
|
336
|
+
if (activeTotal > 0 || completedTotal > 0) {
|
|
337
|
+
console.log(`\n📋 [任务追踪]`);
|
|
338
|
+
console.log(` 进行中: ${activeTotal} 个 (📊 ${active.research.length} | 💻 ${active.develop.length} | 🧪 ${active.test.length})`);
|
|
339
|
+
console.log(` 已完成: ${completedTotal} 个`);
|
|
340
|
+
console.log(` 查看: ${path.relative(PROJECT_DIR, INDEX_FILE)}\n`);
|
|
232
341
|
}
|
|
233
342
|
}
|
|
234
343
|
|
|
@@ -240,6 +349,18 @@ if (require.main === module) {
|
|
|
240
349
|
if (process.argv[2] === '--force') {
|
|
241
350
|
updateIndex();
|
|
242
351
|
console.log('✅ Task index updated');
|
|
352
|
+
} else if (process.argv[2] === '--suggest') {
|
|
353
|
+
const result = updateIndex();
|
|
354
|
+
if (result.suggestions.length > 0) {
|
|
355
|
+
console.log('\n💡 自动流转建议:\n');
|
|
356
|
+
result.suggestions.forEach((s, i) => {
|
|
357
|
+
console.log(`${i + 1}. ${s.message}`);
|
|
358
|
+
console.log(` 开发任务: ${s.developTask.file}`);
|
|
359
|
+
console.log(` 测试任务: ${s.testTask}`);
|
|
360
|
+
});
|
|
361
|
+
} else {
|
|
362
|
+
console.log('✅ 无待处理的流转建议');
|
|
363
|
+
}
|
|
243
364
|
} else {
|
|
244
365
|
main();
|
|
245
366
|
}
|
|
@@ -77,7 +77,17 @@
|
|
|
77
77
|
"Bash(pkill:*)",
|
|
78
78
|
"Bash(pip install:*)",
|
|
79
79
|
"Bash(timeout:*)",
|
|
80
|
-
"Bash(python3:*)"
|
|
80
|
+
"Bash(python3:*)",
|
|
81
|
+
"Bash(npm test:*)",
|
|
82
|
+
"Bash(npx standard-version:*)",
|
|
83
|
+
"Bash(openskills list:*)",
|
|
84
|
+
"Bash(playwright install:*)",
|
|
85
|
+
"Bash(npm run release:minor:*)",
|
|
86
|
+
"Bash(npm init:*)",
|
|
87
|
+
"Bash(git init:*)",
|
|
88
|
+
"Bash(git branch:*)",
|
|
89
|
+
"Bash(gh repo create:*)",
|
|
90
|
+
"Bash(npm view:*)"
|
|
81
91
|
]
|
|
82
92
|
},
|
|
83
93
|
"hooks": {
|
|
@@ -1,28 +1,39 @@
|
|
|
1
|
-
|
|
1
|
+
---
|
|
2
|
+
name: api-tester
|
|
3
|
+
description: API testing and HTTP request validation tool for REST/GraphQL endpoints
|
|
4
|
+
see_also:
|
|
5
|
+
- mcp-builder
|
|
6
|
+
- webapp-testing
|
|
7
|
+
---
|
|
2
8
|
|
|
3
|
-
|
|
9
|
+
# API Tester
|
|
4
10
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
11
|
+
> Test and validate REST/GraphQL APIs with automated request/response checking
|
|
12
|
+
|
|
13
|
+
**Version**: 1.0.0
|
|
14
|
+
**Author**: sumulige
|
|
15
|
+
**Tags**: [api, testing, http, rest, graphql]
|
|
16
|
+
**Difficulty**: 中级
|
|
9
17
|
|
|
10
18
|
---
|
|
11
19
|
|
|
12
20
|
## 概述
|
|
13
21
|
|
|
14
|
-
|
|
22
|
+
API Tester 是一个用于测试和验证 API 接口的技能。支持 REST 和 GraphQL,可以自动检查响应状态码、数据结构和性能指标。
|
|
15
23
|
|
|
16
24
|
## 适用场景
|
|
17
25
|
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
-
|
|
26
|
+
- 测试 REST API 端点
|
|
27
|
+
- 验证 API 响应格式
|
|
28
|
+
- 检查 HTTP 状态码
|
|
29
|
+
- 测试 API 认证
|
|
30
|
+
- 性能基准测试
|
|
21
31
|
|
|
22
32
|
## 触发关键词
|
|
23
33
|
|
|
24
34
|
```
|
|
25
|
-
|
|
35
|
+
api test, "test the api", "check endpoint", http request, "validate api",
|
|
36
|
+
graphql query, rest api, postman, curl
|
|
26
37
|
```
|
|
27
38
|
|
|
28
39
|
## 使用方法
|
|
@@ -30,32 +41,50 @@ keyword1, keyword2, "exact phrase"
|
|
|
30
41
|
### 基础用法
|
|
31
42
|
|
|
32
43
|
```bash
|
|
33
|
-
#
|
|
34
|
-
|
|
44
|
+
# 测试 GET 请求
|
|
45
|
+
curl -X GET https://api.example.com/users
|
|
46
|
+
|
|
47
|
+
# 测试 POST 请求
|
|
48
|
+
curl -X POST https://api.example.com/users \
|
|
49
|
+
-H "Content-Type: application/json" \
|
|
50
|
+
-d '{"name": "John"}'
|
|
35
51
|
```
|
|
36
52
|
|
|
37
|
-
###
|
|
53
|
+
### 验证响应
|
|
38
54
|
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
|
|
55
|
+
```javascript
|
|
56
|
+
// 检查状态码
|
|
57
|
+
response.status === 200
|
|
58
|
+
|
|
59
|
+
// 验证数据结构
|
|
60
|
+
response.data.users.forEach(user => {
|
|
61
|
+
assert(user.id, 'User must have id');
|
|
62
|
+
assert(user.email, 'User must have email');
|
|
63
|
+
});
|
|
42
64
|
```
|
|
43
65
|
|
|
44
66
|
## 输出格式
|
|
45
67
|
|
|
46
|
-
|
|
68
|
+
```
|
|
69
|
+
✅ GET /api/users - 200 OK (142ms)
|
|
70
|
+
✅ POST /api/users - 201 Created (89ms)
|
|
71
|
+
❌ GET /api/users/999 - 404 Not Found (45ms)
|
|
72
|
+
```
|
|
47
73
|
|
|
48
74
|
## 注意事项
|
|
49
75
|
|
|
50
|
-
-
|
|
51
|
-
-
|
|
76
|
+
- 使用测试环境 API,避免生产数据修改
|
|
77
|
+
- 检查 API 速率限制
|
|
78
|
+
- 验证认证 Token 有效性
|
|
79
|
+
- 处理分页响应
|
|
52
80
|
|
|
53
81
|
## 相关技能
|
|
54
82
|
|
|
55
|
-
- [
|
|
56
|
-
- [
|
|
83
|
+
- [mcp-builder](../mcp-builder/) - MCP 服务器构建
|
|
84
|
+
- [webapp-testing](../webapp-testing/) - Web 应用测试
|
|
57
85
|
|
|
58
86
|
## 更新日志
|
|
59
87
|
|
|
60
|
-
### 1.0.0 (
|
|
88
|
+
### 1.0.0 (2026-01-15)
|
|
61
89
|
- 初始版本
|
|
90
|
+
- 添加 REST/GraphQL 支持
|