@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.
@@ -0,0 +1,122 @@
1
+ export interface Task {
2
+ id: number;
3
+ name: string;
4
+ status: string;
5
+ pri: number;
6
+ deadline?: string;
7
+ desc?: string;
8
+ story?: number | string;
9
+ product?: number | string;
10
+ }
11
+ export interface Bug {
12
+ id: number;
13
+ title: string;
14
+ status: string;
15
+ severity: number;
16
+ steps?: string;
17
+ openedDate?: string;
18
+ story?: number | string;
19
+ product?: number | string;
20
+ productName?: string;
21
+ }
22
+ export interface Product {
23
+ id: number;
24
+ name: string;
25
+ code: string;
26
+ status: string;
27
+ desc: string;
28
+ }
29
+ export interface Story {
30
+ id: number;
31
+ title: string;
32
+ status: string;
33
+ pri: number;
34
+ stage?: string;
35
+ estimate?: number;
36
+ openedBy?: string;
37
+ openedDate?: string;
38
+ assignedTo?: string;
39
+ spec?: string;
40
+ module?: string | number;
41
+ moduleName?: string;
42
+ product?: string | number;
43
+ productName?: string;
44
+ }
45
+ export interface TaskUpdate {
46
+ consumed?: number;
47
+ left?: number;
48
+ status?: TaskStatus;
49
+ finishedDate?: string;
50
+ comment?: string;
51
+ }
52
+ export interface BugResolution {
53
+ resolution: 'fixed' | 'notrepro' | 'duplicate' | 'bydesign' | 'willnotfix' | 'tostory' | 'external';
54
+ resolvedBuild?: string;
55
+ duplicateBug?: number;
56
+ comment?: string;
57
+ }
58
+ export interface TestCase {
59
+ id: number;
60
+ product?: number;
61
+ productName?: string;
62
+ module?: number;
63
+ moduleName?: string;
64
+ story?: number;
65
+ title: string;
66
+ type: string;
67
+ pri: number;
68
+ status: string;
69
+ precondition?: string;
70
+ steps?: string;
71
+ openedBy?: string;
72
+ openedDate?: string;
73
+ lastEditedBy?: string;
74
+ lastEditedDate?: string;
75
+ }
76
+ export interface TestResult {
77
+ id: number;
78
+ run: number;
79
+ case: number;
80
+ caseTitle?: string;
81
+ version: number;
82
+ status: string;
83
+ lastRunner?: string;
84
+ lastRunDate?: string;
85
+ lastRunResult?: string;
86
+ }
87
+ export interface TestTask {
88
+ id: number;
89
+ name: string;
90
+ product: number;
91
+ productName?: string;
92
+ project?: number;
93
+ execution?: number;
94
+ build?: string;
95
+ owner?: string;
96
+ status: string;
97
+ begin?: string;
98
+ end?: string;
99
+ desc?: string;
100
+ }
101
+ export interface CreateTestCaseRequest {
102
+ product: number;
103
+ module?: number;
104
+ story?: number;
105
+ title: string;
106
+ type?: string;
107
+ pri?: number;
108
+ precondition?: string;
109
+ steps?: string;
110
+ status?: string;
111
+ }
112
+ export interface TestRunRequest {
113
+ caseId: number;
114
+ version?: number;
115
+ result: 'pass' | 'fail' | 'blocked' | 'skipped';
116
+ steps?: string;
117
+ comment?: string;
118
+ }
119
+ export type TaskStatus = 'wait' | 'doing' | 'done' | 'all';
120
+ export type BugStatus = 'active' | 'resolved' | 'closed' | 'all';
121
+ export type StoryStatus = 'draft' | 'active' | 'closed' | 'changed' | 'all';
122
+ export type TestCaseStatus = 'normal' | 'blocked' | 'investigate' | 'all';
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ // 只保留 legacy 11.3 需要的类型定义
2
+ export {};
@@ -0,0 +1,45 @@
1
+ /**
2
+ * 智能分析工具
3
+ * 用于分析需求复杂度、Bug 优先级等
4
+ */
5
+ import { Story, Bug, Task } from '../types.js';
6
+ export interface ComplexityAnalysis {
7
+ score: number;
8
+ factors: {
9
+ descriptionLength: number;
10
+ hasImages: boolean;
11
+ relatedBugsCount: number;
12
+ testCasesCount: number;
13
+ };
14
+ estimatedHours?: number;
15
+ prioritySuggestion: 'low' | 'medium' | 'high';
16
+ }
17
+ export interface PriorityAnalysis {
18
+ score: number;
19
+ factors: {
20
+ severity: number;
21
+ hasRelatedStory: boolean;
22
+ status: string;
23
+ };
24
+ suggestion: 'low' | 'medium' | 'high' | 'urgent';
25
+ }
26
+ /**
27
+ * 分析需求复杂度
28
+ */
29
+ export declare function analyzeStoryComplexity(story: Story, relatedBugsCount?: number, testCasesCount?: number): ComplexityAnalysis;
30
+ /**
31
+ * 分析 Bug 优先级
32
+ */
33
+ export declare function analyzeBugPriority(bug: Bug, hasRelatedStory?: boolean): PriorityAnalysis;
34
+ /**
35
+ * 分析任务工作量
36
+ */
37
+ export declare function analyzeTaskWorkload(task: Task): {
38
+ estimatedHours: number;
39
+ difficulty: 'easy' | 'medium' | 'hard';
40
+ factors: {
41
+ descriptionLength: number;
42
+ priority: number;
43
+ hasDeadline: boolean;
44
+ };
45
+ };
@@ -0,0 +1,183 @@
1
+ /**
2
+ * 智能分析工具
3
+ * 用于分析需求复杂度、Bug 优先级等
4
+ */
5
+ /**
6
+ * 分析需求复杂度
7
+ */
8
+ export function analyzeStoryComplexity(story, relatedBugsCount = 0, testCasesCount = 0) {
9
+ let score = 0;
10
+ const factors = {
11
+ descriptionLength: 0,
12
+ hasImages: false,
13
+ relatedBugsCount,
14
+ testCasesCount
15
+ };
16
+ // 描述长度分析
17
+ if (story.spec) {
18
+ factors.descriptionLength = story.spec.length;
19
+ if (story.spec.length > 1000) {
20
+ score += 3;
21
+ }
22
+ else if (story.spec.length > 500) {
23
+ score += 2;
24
+ }
25
+ else if (story.spec.length > 200) {
26
+ score += 1;
27
+ }
28
+ }
29
+ // 图片分析(有图片通常意味着更复杂的需求)
30
+ if (story.spec && story.spec.includes('<img')) {
31
+ factors.hasImages = true;
32
+ score += 1;
33
+ }
34
+ // 关联 Bug 数量(Bug 多可能意味着需求复杂)
35
+ factors.relatedBugsCount = relatedBugsCount;
36
+ if (relatedBugsCount > 5) {
37
+ score += 2;
38
+ }
39
+ else if (relatedBugsCount > 2) {
40
+ score += 1;
41
+ }
42
+ // 测试用例数量(测试用例多可能意味着功能复杂)
43
+ factors.testCasesCount = testCasesCount;
44
+ if (testCasesCount > 10) {
45
+ score += 2;
46
+ }
47
+ else if (testCasesCount > 5) {
48
+ score += 1;
49
+ }
50
+ // 优先级影响
51
+ if (story.pri === 1) {
52
+ score += 1; // 高优先级需求可能更复杂
53
+ }
54
+ // 确保分数在 1-10 范围内
55
+ score = Math.max(1, Math.min(10, score));
56
+ // 估算工时(基于复杂度)
57
+ let estimatedHours;
58
+ if (score <= 3) {
59
+ estimatedHours = 2; // 简单需求
60
+ }
61
+ else if (score <= 6) {
62
+ estimatedHours = 4; // 中等需求
63
+ }
64
+ else if (score <= 8) {
65
+ estimatedHours = 8; // 复杂需求
66
+ }
67
+ else {
68
+ estimatedHours = 16; // 非常复杂的需求
69
+ }
70
+ // 优先级建议
71
+ let prioritySuggestion;
72
+ if (score <= 3) {
73
+ prioritySuggestion = 'low';
74
+ }
75
+ else if (score <= 6) {
76
+ prioritySuggestion = 'medium';
77
+ }
78
+ else {
79
+ prioritySuggestion = 'high';
80
+ }
81
+ return {
82
+ score,
83
+ factors,
84
+ estimatedHours,
85
+ prioritySuggestion
86
+ };
87
+ }
88
+ /**
89
+ * 分析 Bug 优先级
90
+ */
91
+ export function analyzeBugPriority(bug, hasRelatedStory = false) {
92
+ let score = 0;
93
+ const factors = {
94
+ severity: bug.severity || 0,
95
+ hasRelatedStory,
96
+ status: bug.status || ''
97
+ };
98
+ // 严重程度分析
99
+ factors.severity = bug.severity || 0;
100
+ if (bug.severity === 1) {
101
+ score += 4; // 致命 Bug
102
+ }
103
+ else if (bug.severity === 2) {
104
+ score += 3; // 严重 Bug
105
+ }
106
+ else if (bug.severity === 3) {
107
+ score += 2; // 一般 Bug
108
+ }
109
+ else {
110
+ score += 1; // 轻微 Bug
111
+ }
112
+ // 状态分析
113
+ if (bug.status === 'active') {
114
+ score += 2; // 激活状态的 Bug 需要优先处理
115
+ }
116
+ else if (bug.status === 'resolved') {
117
+ score -= 1; // 已解决的 Bug 优先级降低
118
+ }
119
+ // 关联需求分析
120
+ factors.hasRelatedStory = hasRelatedStory;
121
+ if (hasRelatedStory) {
122
+ score += 1; // 有关联需求的 Bug 可能需要优先处理
123
+ }
124
+ // 确保分数在 1-10 范围内
125
+ score = Math.max(1, Math.min(10, score));
126
+ // 优先级建议
127
+ let suggestion;
128
+ if (score <= 3) {
129
+ suggestion = 'low';
130
+ }
131
+ else if (score <= 5) {
132
+ suggestion = 'medium';
133
+ }
134
+ else if (score <= 7) {
135
+ suggestion = 'high';
136
+ }
137
+ else {
138
+ suggestion = 'urgent';
139
+ }
140
+ return {
141
+ score,
142
+ factors,
143
+ suggestion
144
+ };
145
+ }
146
+ /**
147
+ * 分析任务工作量
148
+ */
149
+ export function analyzeTaskWorkload(task) {
150
+ const factors = {
151
+ descriptionLength: task.desc?.length || 0,
152
+ priority: task.pri || 0,
153
+ hasDeadline: !!task.deadline
154
+ };
155
+ let estimatedHours = 2; // 默认 2 小时
156
+ // 描述长度影响
157
+ if (factors.descriptionLength > 500) {
158
+ estimatedHours += 2;
159
+ }
160
+ else if (factors.descriptionLength > 200) {
161
+ estimatedHours += 1;
162
+ }
163
+ // 优先级影响(高优先级任务可能需要更多时间)
164
+ if (factors.priority === 1) {
165
+ estimatedHours += 1;
166
+ }
167
+ // 难度评估
168
+ let difficulty;
169
+ if (estimatedHours <= 2) {
170
+ difficulty = 'easy';
171
+ }
172
+ else if (estimatedHours <= 4) {
173
+ difficulty = 'medium';
174
+ }
175
+ else {
176
+ difficulty = 'hard';
177
+ }
178
+ return {
179
+ estimatedHours,
180
+ difficulty,
181
+ factors
182
+ };
183
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 格式化工具函数
3
+ * 用于将需求、Bug、任务等格式化为 Markdown 或其他格式
4
+ */
5
+ import { Story, Bug, Task } from '../types.js';
6
+ /**
7
+ * 格式化需求为 Markdown
8
+ */
9
+ export declare function formatStoryAsMarkdown(story: Story): string;
10
+ /**
11
+ * 格式化 Bug 为 Markdown
12
+ */
13
+ export declare function formatBugAsMarkdown(bug: Bug): string;
14
+ /**
15
+ * 格式化任务为 Markdown
16
+ */
17
+ export declare function formatTaskAsMarkdown(task: Task): string;
18
+ /**
19
+ * 生成需求摘要
20
+ */
21
+ export declare function generateStorySummary(story: Story): string;
22
+ /**
23
+ * 生成 Bug 摘要
24
+ */
25
+ export declare function generateBugSummary(bug: Bug): string;
@@ -0,0 +1,157 @@
1
+ /**
2
+ * 格式化工具函数
3
+ * 用于将需求、Bug、任务等格式化为 Markdown 或其他格式
4
+ */
5
+ /**
6
+ * 格式化需求为 Markdown
7
+ */
8
+ export function formatStoryAsMarkdown(story) {
9
+ const lines = [];
10
+ lines.push(`# 需求 #${story.id}: ${story.title}`);
11
+ lines.push('');
12
+ if (story.productName) {
13
+ lines.push(`**产品**: ${story.productName}`);
14
+ }
15
+ if (story.moduleName) {
16
+ lines.push(`**模块**: ${story.moduleName}`);
17
+ }
18
+ if (story.status) {
19
+ lines.push(`**状态**: ${story.status}`);
20
+ }
21
+ if (story.pri) {
22
+ lines.push(`**优先级**: ${story.pri}`);
23
+ }
24
+ if (story.stage) {
25
+ lines.push(`**阶段**: ${story.stage}`);
26
+ }
27
+ if (story.estimate) {
28
+ lines.push(`**预估工时**: ${story.estimate} 小时`);
29
+ }
30
+ if (story.assignedTo) {
31
+ lines.push(`**指派给**: ${story.assignedTo}`);
32
+ }
33
+ if (story.openedBy) {
34
+ lines.push(`**创建人**: ${story.openedBy}`);
35
+ }
36
+ if (story.openedDate) {
37
+ lines.push(`**创建时间**: ${story.openedDate}`);
38
+ }
39
+ lines.push('');
40
+ lines.push('## 需求描述');
41
+ lines.push('');
42
+ if (story.spec) {
43
+ lines.push(story.spec);
44
+ }
45
+ else {
46
+ lines.push('*暂无描述*');
47
+ }
48
+ return lines.join('\n');
49
+ }
50
+ /**
51
+ * 格式化 Bug 为 Markdown
52
+ */
53
+ export function formatBugAsMarkdown(bug) {
54
+ const lines = [];
55
+ lines.push(`# Bug #${bug.id}: ${bug.title}`);
56
+ lines.push('');
57
+ if (bug.productName) {
58
+ lines.push(`**产品**: ${bug.productName}`);
59
+ }
60
+ if (bug.status) {
61
+ lines.push(`**状态**: ${bug.status}`);
62
+ }
63
+ if (bug.severity) {
64
+ lines.push(`**严重程度**: ${bug.severity}`);
65
+ }
66
+ if (bug.openedDate) {
67
+ lines.push(`**创建时间**: ${bug.openedDate}`);
68
+ }
69
+ if (bug.story) {
70
+ lines.push(`**关联需求**: #${bug.story}`);
71
+ }
72
+ lines.push('');
73
+ lines.push('## 复现步骤');
74
+ lines.push('');
75
+ if (bug.steps) {
76
+ lines.push(bug.steps);
77
+ }
78
+ else {
79
+ lines.push('*暂无复现步骤*');
80
+ }
81
+ return lines.join('\n');
82
+ }
83
+ /**
84
+ * 格式化任务为 Markdown
85
+ */
86
+ export function formatTaskAsMarkdown(task) {
87
+ const lines = [];
88
+ lines.push(`# 任务 #${task.id}: ${task.name}`);
89
+ lines.push('');
90
+ lines.push(`**状态**: ${task.status}`);
91
+ lines.push(`**优先级**: ${task.pri}`);
92
+ if (task.deadline) {
93
+ lines.push(`**截止日期**: ${task.deadline}`);
94
+ }
95
+ if (task.story) {
96
+ lines.push(`**关联需求**: #${task.story}`);
97
+ }
98
+ if (task.product) {
99
+ lines.push(`**产品**: #${task.product}`);
100
+ }
101
+ lines.push('');
102
+ lines.push('## 任务描述');
103
+ lines.push('');
104
+ if (task.desc) {
105
+ lines.push(task.desc);
106
+ }
107
+ else {
108
+ lines.push('*暂无描述*');
109
+ }
110
+ return lines.join('\n');
111
+ }
112
+ /**
113
+ * 生成需求摘要
114
+ */
115
+ export function generateStorySummary(story) {
116
+ const parts = [];
117
+ parts.push(`需求 #${story.id}: ${story.title}`);
118
+ if (story.status) {
119
+ parts.push(`状态: ${story.status}`);
120
+ }
121
+ if (story.pri) {
122
+ parts.push(`优先级: ${story.pri}`);
123
+ }
124
+ if (story.productName) {
125
+ parts.push(`产品: ${story.productName}`);
126
+ }
127
+ if (story.spec) {
128
+ const specPreview = story.spec.length > 100
129
+ ? story.spec.substring(0, 100) + '...'
130
+ : story.spec;
131
+ parts.push(`描述: ${specPreview}`);
132
+ }
133
+ return parts.join(' | ');
134
+ }
135
+ /**
136
+ * 生成 Bug 摘要
137
+ */
138
+ export function generateBugSummary(bug) {
139
+ const parts = [];
140
+ parts.push(`Bug #${bug.id}: ${bug.title}`);
141
+ if (bug.status) {
142
+ parts.push(`状态: ${bug.status}`);
143
+ }
144
+ if (bug.severity) {
145
+ parts.push(`严重程度: ${bug.severity}`);
146
+ }
147
+ if (bug.productName) {
148
+ parts.push(`产品: ${bug.productName}`);
149
+ }
150
+ if (bug.steps) {
151
+ const stepsPreview = bug.steps.length > 100
152
+ ? bug.steps.substring(0, 100) + '...'
153
+ : bug.steps;
154
+ parts.push(`复现步骤: ${stepsPreview}`);
155
+ }
156
+ return parts.join(' | ');
157
+ }
@@ -0,0 +1,25 @@
1
+ /**
2
+ * 图片下载工具函数
3
+ * 统一处理 Bug 和需求的图片下载逻辑
4
+ */
5
+ import { ZentaoLegacyAPI } from '../zentaoLegacyApi.js';
6
+ export interface DownloadedImage {
7
+ url: string;
8
+ base64?: string;
9
+ mimeType?: string;
10
+ size?: number;
11
+ success: boolean;
12
+ error?: string;
13
+ }
14
+ /**
15
+ * 下载图片列表
16
+ * @param zentaoApi Zentao API 实例
17
+ * @param imageUrls 图片 URL 列表
18
+ * @param parallel 是否并行下载(默认 true)
19
+ * @returns 下载结果数组
20
+ */
21
+ export declare function downloadImages(zentaoApi: ZentaoLegacyAPI, imageUrls: string[], parallel?: boolean): Promise<DownloadedImage[]>;
22
+ /**
23
+ * 构建 MCP image 内容数组
24
+ */
25
+ export declare function buildImageContent(downloadedImages: DownloadedImage[], entityType: 'bug' | 'story', entityId: number): any[];
@@ -0,0 +1,104 @@
1
+ /**
2
+ * 图片下载工具函数
3
+ * 统一处理 Bug 和需求的图片下载逻辑
4
+ */
5
+ /**
6
+ * 检测图片 MIME 类型
7
+ */
8
+ function detectMimeType(buffer) {
9
+ if (buffer[0] === 0xFF && buffer[1] === 0xD8) {
10
+ return 'image/jpeg';
11
+ }
12
+ else if (buffer[0] === 0x47 && buffer[1] === 0x49) {
13
+ return 'image/gif';
14
+ }
15
+ else if (buffer[0] === 0x89 && buffer[1] === 0x50) {
16
+ return 'image/png';
17
+ }
18
+ return 'image/png'; // 默认
19
+ }
20
+ /**
21
+ * 下载图片列表
22
+ * @param zentaoApi Zentao API 实例
23
+ * @param imageUrls 图片 URL 列表
24
+ * @param parallel 是否并行下载(默认 true)
25
+ * @returns 下载结果数组
26
+ */
27
+ export async function downloadImages(zentaoApi, imageUrls, parallel = true) {
28
+ if (imageUrls.length === 0) {
29
+ return [];
30
+ }
31
+ if (parallel) {
32
+ // 并行下载
33
+ const downloadPromises = imageUrls.map(async (url) => {
34
+ try {
35
+ const imageBuffer = await zentaoApi.downloadStoryImage(url);
36
+ const base64Image = imageBuffer.toString('base64');
37
+ const mimeType = detectMimeType(imageBuffer);
38
+ return {
39
+ url,
40
+ base64: base64Image,
41
+ mimeType,
42
+ size: imageBuffer.length,
43
+ success: true
44
+ };
45
+ }
46
+ catch (error) {
47
+ return {
48
+ url,
49
+ success: false,
50
+ error: error instanceof Error ? error.message : String(error)
51
+ };
52
+ }
53
+ });
54
+ return Promise.all(downloadPromises);
55
+ }
56
+ else {
57
+ // 串行下载(兼容旧逻辑)
58
+ const results = [];
59
+ for (const url of imageUrls) {
60
+ try {
61
+ const imageBuffer = await zentaoApi.downloadStoryImage(url);
62
+ const base64Image = imageBuffer.toString('base64');
63
+ const mimeType = detectMimeType(imageBuffer);
64
+ results.push({
65
+ url,
66
+ base64: base64Image,
67
+ mimeType,
68
+ size: imageBuffer.length,
69
+ success: true
70
+ });
71
+ }
72
+ catch (error) {
73
+ results.push({
74
+ url,
75
+ success: false,
76
+ error: error instanceof Error ? error.message : String(error)
77
+ });
78
+ }
79
+ }
80
+ return results;
81
+ }
82
+ }
83
+ /**
84
+ * 构建 MCP image 内容数组
85
+ */
86
+ export function buildImageContent(downloadedImages, entityType, entityId) {
87
+ const content = [];
88
+ downloadedImages.forEach((img, index) => {
89
+ if (img.success && img.base64) {
90
+ content.push({
91
+ type: "image",
92
+ data: img.base64,
93
+ mimeType: img.mimeType || 'image/png',
94
+ annotations: {
95
+ audience: ["user"],
96
+ priority: 0.8,
97
+ title: `${entityType === 'bug' ? 'Bug' : '需求'} ${entityId} 的图片 ${index + 1}`,
98
+ description: `来源: ${img.url}`
99
+ }
100
+ });
101
+ }
102
+ });
103
+ return content;
104
+ }
@@ -0,0 +1,28 @@
1
+ /**
2
+ * 操作建议工具
3
+ * 根据当前上下文,建议下一步操作
4
+ */
5
+ import { Story, Bug, Task } from '../types.js';
6
+ export interface NextActionSuggestion {
7
+ action: string;
8
+ description: string;
9
+ tool?: string;
10
+ toolArgs?: Record<string, any>;
11
+ priority: 'high' | 'medium' | 'low';
12
+ }
13
+ /**
14
+ * 根据需求上下文生成下一步建议
15
+ */
16
+ export declare function suggestNextActionsForStory(story: Story, hasRelatedBugs: boolean, hasTestCases: boolean): NextActionSuggestion[];
17
+ /**
18
+ * 根据 Bug 上下文生成下一步建议
19
+ */
20
+ export declare function suggestNextActionsForBug(bug: Bug, hasRelatedStory: boolean, isActive: boolean): NextActionSuggestion[];
21
+ /**
22
+ * 根据任务上下文生成下一步建议
23
+ */
24
+ export declare function suggestNextActionsForTask(task: Task, isCompleted?: boolean): NextActionSuggestion[];
25
+ /**
26
+ * 格式化建议为 Markdown
27
+ */
28
+ export declare function formatSuggestionsAsMarkdown(suggestions: NextActionSuggestion[]): string;