@maxenlin/mcp-zentao-11-3 1.0.0-patch.1
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/LICENSE +22 -0
- package/README.md +254 -0
- package/dist/config.d.ts +9 -0
- package/dist/config.js +54 -0
- package/dist/errors.d.ts +36 -0
- package/dist/errors.js +56 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +1338 -0
- package/dist/types.d.ts +122 -0
- package/dist/types.js +2 -0
- package/dist/utils/analyzer.d.ts +45 -0
- package/dist/utils/analyzer.js +183 -0
- package/dist/utils/formatter.d.ts +25 -0
- package/dist/utils/formatter.js +157 -0
- package/dist/utils/imageDownloader.d.ts +25 -0
- package/dist/utils/imageDownloader.js +104 -0
- package/dist/utils/suggestions.d.ts +28 -0
- package/dist/utils/suggestions.js +200 -0
- package/dist/zentaoLegacyApi.d.ts +152 -0
- package/dist/zentaoLegacyApi.js +815 -0
- package/package.json +52 -0
|
@@ -0,0 +1,200 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 操作建议工具
|
|
3
|
+
* 根据当前上下文,建议下一步操作
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* 根据需求上下文生成下一步建议
|
|
7
|
+
*/
|
|
8
|
+
export function suggestNextActionsForStory(story, hasRelatedBugs, hasTestCases) {
|
|
9
|
+
const suggestions = [];
|
|
10
|
+
// 如果需求是激活状态,建议创建任务
|
|
11
|
+
if (story.status === 'active' || story.status === 'draft') {
|
|
12
|
+
suggestions.push({
|
|
13
|
+
action: '创建开发任务',
|
|
14
|
+
description: `为需求 #${story.id} 创建开发任务`,
|
|
15
|
+
tool: 'createTaskFromStory',
|
|
16
|
+
toolArgs: { storyId: story.id },
|
|
17
|
+
priority: 'high'
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
// 如果有关联 Bug,建议查看
|
|
21
|
+
if (hasRelatedBugs) {
|
|
22
|
+
suggestions.push({
|
|
23
|
+
action: '查看关联 Bug',
|
|
24
|
+
description: `查看需求 #${story.id} 关联的所有 Bug`,
|
|
25
|
+
tool: 'getStoryRelatedBugs',
|
|
26
|
+
toolArgs: { storyId: story.id },
|
|
27
|
+
priority: 'medium'
|
|
28
|
+
});
|
|
29
|
+
}
|
|
30
|
+
// 如果没有测试用例,建议创建
|
|
31
|
+
if (!hasTestCases) {
|
|
32
|
+
suggestions.push({
|
|
33
|
+
action: '创建测试用例',
|
|
34
|
+
description: `为需求 #${story.id} 创建测试用例`,
|
|
35
|
+
tool: 'createTestCase',
|
|
36
|
+
toolArgs: { story: story.id },
|
|
37
|
+
priority: 'medium'
|
|
38
|
+
});
|
|
39
|
+
}
|
|
40
|
+
// 建议生成代码框架
|
|
41
|
+
suggestions.push({
|
|
42
|
+
action: '生成代码框架提示',
|
|
43
|
+
description: `根据需求 #${story.id} 生成代码框架提示`,
|
|
44
|
+
tool: 'generateCodePromptFromStory',
|
|
45
|
+
toolArgs: { storyId: story.id },
|
|
46
|
+
priority: 'medium'
|
|
47
|
+
});
|
|
48
|
+
// 建议分析复杂度
|
|
49
|
+
suggestions.push({
|
|
50
|
+
action: '分析需求复杂度',
|
|
51
|
+
description: `分析需求 #${story.id} 的开发复杂度`,
|
|
52
|
+
tool: 'analyzeStoryComplexity',
|
|
53
|
+
toolArgs: { storyId: story.id },
|
|
54
|
+
priority: 'low'
|
|
55
|
+
});
|
|
56
|
+
return suggestions;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* 根据 Bug 上下文生成下一步建议
|
|
60
|
+
*/
|
|
61
|
+
export function suggestNextActionsForBug(bug, hasRelatedStory, isActive) {
|
|
62
|
+
const suggestions = [];
|
|
63
|
+
// 如果是激活状态的 Bug,建议创建修复任务
|
|
64
|
+
if (isActive) {
|
|
65
|
+
suggestions.push({
|
|
66
|
+
action: '创建修复任务',
|
|
67
|
+
description: `为 Bug #${bug.id} 创建修复任务`,
|
|
68
|
+
tool: 'createTaskFromBug',
|
|
69
|
+
toolArgs: { bugId: bug.id },
|
|
70
|
+
priority: 'high'
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
// 建议生成测试用例
|
|
74
|
+
suggestions.push({
|
|
75
|
+
action: '生成测试用例提示',
|
|
76
|
+
description: `根据 Bug #${bug.id} 生成测试用例提示`,
|
|
77
|
+
tool: 'generateTestPromptFromBug',
|
|
78
|
+
toolArgs: { bugId: bug.id },
|
|
79
|
+
priority: 'high'
|
|
80
|
+
});
|
|
81
|
+
// 如果有关联需求,建议查看
|
|
82
|
+
if (hasRelatedStory) {
|
|
83
|
+
suggestions.push({
|
|
84
|
+
action: '查看关联需求',
|
|
85
|
+
description: `查看 Bug #${bug.id} 关联的需求`,
|
|
86
|
+
tool: 'getBugRelatedStory',
|
|
87
|
+
toolArgs: { bugId: bug.id },
|
|
88
|
+
priority: 'medium'
|
|
89
|
+
});
|
|
90
|
+
}
|
|
91
|
+
// 建议分析优先级
|
|
92
|
+
suggestions.push({
|
|
93
|
+
action: '分析 Bug 优先级',
|
|
94
|
+
description: `分析 Bug #${bug.id} 的处理优先级`,
|
|
95
|
+
tool: 'analyzeBugPriority',
|
|
96
|
+
toolArgs: { bugId: bug.id },
|
|
97
|
+
priority: 'medium'
|
|
98
|
+
});
|
|
99
|
+
// 如果 Bug 已解决,建议标记为已解决
|
|
100
|
+
if (bug.status === 'resolved') {
|
|
101
|
+
suggestions.push({
|
|
102
|
+
action: '标记 Bug 为已关闭',
|
|
103
|
+
description: `将 Bug #${bug.id} 标记为已关闭`,
|
|
104
|
+
tool: 'resolveBug',
|
|
105
|
+
toolArgs: {
|
|
106
|
+
bugId: bug.id,
|
|
107
|
+
resolution: { resolution: 'fixed', comment: 'Bug 已修复并验证' }
|
|
108
|
+
},
|
|
109
|
+
priority: 'low'
|
|
110
|
+
});
|
|
111
|
+
}
|
|
112
|
+
return suggestions;
|
|
113
|
+
}
|
|
114
|
+
/**
|
|
115
|
+
* 根据任务上下文生成下一步建议
|
|
116
|
+
*/
|
|
117
|
+
export function suggestNextActionsForTask(task, isCompleted = false) {
|
|
118
|
+
const suggestions = [];
|
|
119
|
+
// 如果任务是待办状态,建议开始
|
|
120
|
+
if (task.status === 'wait') {
|
|
121
|
+
suggestions.push({
|
|
122
|
+
action: '开始任务',
|
|
123
|
+
description: `将任务 #${task.id} 状态更新为进行中`,
|
|
124
|
+
tool: 'updateTask',
|
|
125
|
+
toolArgs: {
|
|
126
|
+
taskId: task.id,
|
|
127
|
+
update: { status: 'doing' }
|
|
128
|
+
},
|
|
129
|
+
priority: 'high'
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// 如果任务是进行中状态,建议完成
|
|
133
|
+
if (task.status === 'doing') {
|
|
134
|
+
suggestions.push({
|
|
135
|
+
action: '完成任务',
|
|
136
|
+
description: `将任务 #${task.id} 标记为已完成`,
|
|
137
|
+
tool: 'finishTask',
|
|
138
|
+
toolArgs: { taskId: task.id },
|
|
139
|
+
priority: 'high'
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
// 建议分析工作量
|
|
143
|
+
suggestions.push({
|
|
144
|
+
action: '分析任务工作量',
|
|
145
|
+
description: `分析任务 #${task.id} 的工作量`,
|
|
146
|
+
tool: 'analyzeTaskWorkload',
|
|
147
|
+
toolArgs: { taskId: task.id },
|
|
148
|
+
priority: 'low'
|
|
149
|
+
});
|
|
150
|
+
// 如果有关联需求,建议查看
|
|
151
|
+
if (task.story) {
|
|
152
|
+
suggestions.push({
|
|
153
|
+
action: '查看关联需求',
|
|
154
|
+
description: `查看任务 #${task.id} 关联的需求`,
|
|
155
|
+
tool: 'getStoryDetail',
|
|
156
|
+
toolArgs: { storyId: typeof task.story === 'string' ? parseInt(task.story) : task.story },
|
|
157
|
+
priority: 'medium'
|
|
158
|
+
});
|
|
159
|
+
}
|
|
160
|
+
return suggestions;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* 格式化建议为 Markdown
|
|
164
|
+
*/
|
|
165
|
+
export function formatSuggestionsAsMarkdown(suggestions) {
|
|
166
|
+
if (suggestions.length === 0) {
|
|
167
|
+
return '暂无建议操作。';
|
|
168
|
+
}
|
|
169
|
+
const lines = [];
|
|
170
|
+
lines.push('## 💡 建议下一步操作\n');
|
|
171
|
+
// 按优先级分组
|
|
172
|
+
const highPriority = suggestions.filter(s => s.priority === 'high');
|
|
173
|
+
const mediumPriority = suggestions.filter(s => s.priority === 'medium');
|
|
174
|
+
const lowPriority = suggestions.filter(s => s.priority === 'low');
|
|
175
|
+
const formatGroup = (group, title) => {
|
|
176
|
+
if (group.length === 0)
|
|
177
|
+
return;
|
|
178
|
+
lines.push(`### ${title}\n`);
|
|
179
|
+
group.forEach((suggestion, index) => {
|
|
180
|
+
lines.push(`${index + 1}. **${suggestion.action}**`);
|
|
181
|
+
lines.push(` - ${suggestion.description}`);
|
|
182
|
+
if (suggestion.tool) {
|
|
183
|
+
lines.push(` - 工具: \`${suggestion.tool}\``);
|
|
184
|
+
}
|
|
185
|
+
lines.push('');
|
|
186
|
+
});
|
|
187
|
+
};
|
|
188
|
+
if (highPriority.length > 0) {
|
|
189
|
+
formatGroup(highPriority, '🔴 高优先级');
|
|
190
|
+
}
|
|
191
|
+
if (mediumPriority.length > 0) {
|
|
192
|
+
formatGroup(mediumPriority, '🟡 中优先级');
|
|
193
|
+
}
|
|
194
|
+
if (lowPriority.length > 0) {
|
|
195
|
+
formatGroup(lowPriority, '🟢 低优先级');
|
|
196
|
+
}
|
|
197
|
+
lines.push('---\n');
|
|
198
|
+
lines.push('💬 **提示**: 你可以直接告诉我你想执行哪个操作,例如:"执行第1个操作"、"创建开发任务"等。\n');
|
|
199
|
+
return lines.join('\n');
|
|
200
|
+
}
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 禅道旧版API (11.x版本)
|
|
3
|
+
* 使用Session认证方式
|
|
4
|
+
*/
|
|
5
|
+
import { Bug, Task, Story, StoryStatus, TestCase, TestCaseStatus, TestResult, TestTask, CreateTestCaseRequest, TestRunRequest, Product, TaskUpdate, BugResolution } from './types.js';
|
|
6
|
+
import { ZentaoConfig } from './config.js';
|
|
7
|
+
export declare class ZentaoLegacyAPI {
|
|
8
|
+
private config;
|
|
9
|
+
private client;
|
|
10
|
+
private sessionId;
|
|
11
|
+
constructor(config: ZentaoConfig);
|
|
12
|
+
/**
|
|
13
|
+
* 获取SessionID
|
|
14
|
+
*/
|
|
15
|
+
private getSessionId;
|
|
16
|
+
/**
|
|
17
|
+
* 登录
|
|
18
|
+
*/
|
|
19
|
+
private login;
|
|
20
|
+
/**
|
|
21
|
+
* 确保已登录
|
|
22
|
+
*/
|
|
23
|
+
private ensureLoggedIn;
|
|
24
|
+
/**
|
|
25
|
+
* 发起请求
|
|
26
|
+
*/
|
|
27
|
+
private request;
|
|
28
|
+
/**
|
|
29
|
+
* POST请求
|
|
30
|
+
*/
|
|
31
|
+
private postRequest;
|
|
32
|
+
/**
|
|
33
|
+
* 获取产品列表
|
|
34
|
+
*/
|
|
35
|
+
getProducts(): Promise<Product[]>;
|
|
36
|
+
/**
|
|
37
|
+
* 获取产品的模块树
|
|
38
|
+
* @param productId 产品ID
|
|
39
|
+
* @returns 模块树对象,key是模块ID,value是模块名称
|
|
40
|
+
*/
|
|
41
|
+
getProductModules(productId: number): Promise<Record<string, string>>;
|
|
42
|
+
/**
|
|
43
|
+
* 获取我的任务列表
|
|
44
|
+
*/
|
|
45
|
+
getMyTasks(): Promise<Task[]>;
|
|
46
|
+
/**
|
|
47
|
+
* 获取任务详情
|
|
48
|
+
*/
|
|
49
|
+
getTaskDetail(taskId: number): Promise<Task>;
|
|
50
|
+
/**
|
|
51
|
+
* 获取我的Bug列表
|
|
52
|
+
*/
|
|
53
|
+
getMyBugs(): Promise<Bug[]>;
|
|
54
|
+
/**
|
|
55
|
+
* 获取Bug详情
|
|
56
|
+
*/
|
|
57
|
+
getBugDetail(bugId: number): Promise<Bug>;
|
|
58
|
+
/**
|
|
59
|
+
* 更新任务
|
|
60
|
+
*/
|
|
61
|
+
updateTask(taskId: number, update: TaskUpdate): Promise<Task>;
|
|
62
|
+
/**
|
|
63
|
+
* 完成任务
|
|
64
|
+
*/
|
|
65
|
+
finishTask(taskId: number, update: TaskUpdate): Promise<void>;
|
|
66
|
+
/**
|
|
67
|
+
* 解决Bug
|
|
68
|
+
*/
|
|
69
|
+
resolveBug(bugId: number, resolution: BugResolution): Promise<void>;
|
|
70
|
+
/**
|
|
71
|
+
* 获取产品的需求列表(支持分页,自动获取所有需求)
|
|
72
|
+
*/
|
|
73
|
+
getProductStories(productId: number, status?: StoryStatus): Promise<Story[]>;
|
|
74
|
+
/**
|
|
75
|
+
* 获取需求详情
|
|
76
|
+
*/
|
|
77
|
+
getStoryDetail(storyId: number): Promise<Story>;
|
|
78
|
+
/**
|
|
79
|
+
* 下载需求中的图片文件
|
|
80
|
+
*/
|
|
81
|
+
downloadStoryImage(imageUrl: string): Promise<Buffer>;
|
|
82
|
+
/**
|
|
83
|
+
* 提取需求描述中的所有图片URL
|
|
84
|
+
*/
|
|
85
|
+
extractImageUrls(spec: string): string[];
|
|
86
|
+
/**
|
|
87
|
+
* 提取需求描述中的文件ID
|
|
88
|
+
*/
|
|
89
|
+
extractFileIds(spec: string): string[];
|
|
90
|
+
/**
|
|
91
|
+
* 搜索需求(通过关键字)
|
|
92
|
+
* 由于禅道11.3的搜索API权限限制,我们通过获取所有产品的需求然后本地过滤
|
|
93
|
+
*/
|
|
94
|
+
searchStories(keyword: string, options?: {
|
|
95
|
+
productId?: number;
|
|
96
|
+
status?: StoryStatus;
|
|
97
|
+
limit?: number;
|
|
98
|
+
}): Promise<Story[]>;
|
|
99
|
+
/**
|
|
100
|
+
* 按产品名称搜索需求
|
|
101
|
+
*/
|
|
102
|
+
searchStoriesByProductName(productName: string, keyword: string, options?: {
|
|
103
|
+
status?: StoryStatus;
|
|
104
|
+
limit?: number;
|
|
105
|
+
}): Promise<{
|
|
106
|
+
product: Product;
|
|
107
|
+
stories: Story[];
|
|
108
|
+
}[]>;
|
|
109
|
+
/**
|
|
110
|
+
* 获取产品的测试用例列表
|
|
111
|
+
* @param productId 产品ID
|
|
112
|
+
* @param status 用例状态
|
|
113
|
+
* @param moduleId 模块ID(可选)
|
|
114
|
+
*/
|
|
115
|
+
getProductTestCases(productId: number, status?: TestCaseStatus, moduleId?: number): Promise<TestCase[]>;
|
|
116
|
+
/**
|
|
117
|
+
* 获取测试用例详情
|
|
118
|
+
*/
|
|
119
|
+
getTestCaseDetail(caseId: number): Promise<TestCase>;
|
|
120
|
+
/**
|
|
121
|
+
* 创建测试用例
|
|
122
|
+
*/
|
|
123
|
+
createTestCase(testCase: CreateTestCaseRequest): Promise<number>;
|
|
124
|
+
/**
|
|
125
|
+
* 获取需求的测试用例
|
|
126
|
+
*/
|
|
127
|
+
getStoryTestCases(storyId: number): Promise<TestCase[]>;
|
|
128
|
+
/**
|
|
129
|
+
* 获取测试单列表
|
|
130
|
+
*/
|
|
131
|
+
getTestTasks(productId?: number): Promise<TestTask[]>;
|
|
132
|
+
/**
|
|
133
|
+
* 获取测试单详情
|
|
134
|
+
*/
|
|
135
|
+
getTestTaskDetail(taskId: number): Promise<TestTask>;
|
|
136
|
+
/**
|
|
137
|
+
* 获取测试单的测试结果
|
|
138
|
+
*/
|
|
139
|
+
getTestTaskResults(taskId: number): Promise<TestResult[]>;
|
|
140
|
+
/**
|
|
141
|
+
* 执行测试用例
|
|
142
|
+
*/
|
|
143
|
+
runTestCase(taskId: number, testRun: TestRunRequest): Promise<void>;
|
|
144
|
+
/**
|
|
145
|
+
* 获取需求关联的 Bug 列表
|
|
146
|
+
*/
|
|
147
|
+
getStoryRelatedBugs(storyId: number): Promise<Bug[]>;
|
|
148
|
+
/**
|
|
149
|
+
* 获取 Bug 关联的需求
|
|
150
|
+
*/
|
|
151
|
+
getBugRelatedStory(bugId: number): Promise<Story | null>;
|
|
152
|
+
}
|