@comate/zulu 0.7.1 → 0.7.2
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/comate-engine/node_modules/@comate/plugin-shared-internals/dist/index.d.ts +1 -0
- package/comate-engine/server.js +3 -3
- package/dist/bundle/index.js +2 -2
- package/package.json +1 -1
- package/comate-engine/plugins/aiscan/assets/icon.svg +0 -12
- package/comate-engine/plugins/aiscan/dist/index.js +0 -54426
- package/comate-engine/plugins/aiscan/package.json +0 -67
- package/comate-engine/plugins/appdev/assets/icon.png +0 -0
- package/comate-engine/plugins/appdev/dist/help.md +0 -12
- package/comate-engine/plugins/appdev/dist/index.d.ts +0 -2
- package/comate-engine/plugins/appdev/dist/index.js +0 -194
- package/comate-engine/plugins/appdev/dist/providers/err.d.ts +0 -8
- package/comate-engine/plugins/appdev/dist/providers/err.js +0 -37
- package/comate-engine/plugins/appdev/dist/providers/fallback.d.ts +0 -5
- package/comate-engine/plugins/appdev/dist/providers/fallback.js +0 -28
- package/comate-engine/plugins/appdev/dist/providers/help.d.ts +0 -8
- package/comate-engine/plugins/appdev/dist/providers/help.js +0 -19
- package/comate-engine/plugins/appdev/dist/providers/medusa.d.ts +0 -8
- package/comate-engine/plugins/appdev/dist/providers/medusa.js +0 -39
- package/comate-engine/plugins/appdev/dist/providers/qa.d.ts +0 -8
- package/comate-engine/plugins/appdev/dist/providers/qa.js +0 -33
- package/comate-engine/plugins/appdev/package.json +0 -67
- package/comate-engine/plugins/bfc/assets/bfc-icon.png +0 -0
- package/comate-engine/plugins/bfc/dist/config/config.d.ts +0 -4
- package/comate-engine/plugins/bfc/dist/config/config.js +0 -4
- package/comate-engine/plugins/bfc/dist/help.md +0 -11
- package/comate-engine/plugins/bfc/dist/index.d.ts +0 -2
- package/comate-engine/plugins/bfc/dist/index.js +0 -452
- package/comate-engine/plugins/bfc/dist/providers/bfcInstructMode.d.ts +0 -8
- package/comate-engine/plugins/bfc/dist/providers/bfcInstructMode.js +0 -77
- package/comate-engine/plugins/bfc/dist/providers/genAbnormalCode.d.ts +0 -8
- package/comate-engine/plugins/bfc/dist/providers/genAbnormalCode.js +0 -71
- package/comate-engine/plugins/bfc/dist/providers/genBfcCode.d.ts +0 -8
- package/comate-engine/plugins/bfc/dist/providers/genBfcCode.js +0 -74
- package/comate-engine/plugins/bfc/dist/providers/getBatchCases.d.ts +0 -10
- package/comate-engine/plugins/bfc/dist/providers/getBatchCases.js +0 -71
- package/comate-engine/plugins/bfc/dist/providers/help.d.ts +0 -8
- package/comate-engine/plugins/bfc/dist/providers/help.js +0 -19
- package/comate-engine/plugins/bfc/dist/service/generateService.d.ts +0 -14
- package/comate-engine/plugins/bfc/dist/service/generateService.js +0 -27
- package/comate-engine/plugins/bfc/package.json +0 -85
- package/comate-engine/plugins/bpm/assets/bpm.png +0 -0
- package/comate-engine/plugins/bpm/dist/index.js +0 -313
- package/comate-engine/plugins/bpm/package.json +0 -65
- package/comate-engine/plugins/casebuilder/assets/icon.svg +0 -1
- package/comate-engine/plugins/casebuilder/dist/help.md +0 -33
- package/comate-engine/plugins/casebuilder/dist/index.js +0 -837
- package/comate-engine/plugins/casebuilder/package.json +0 -80
- package/comate-engine/plugins/centrino/assets/icon.png +0 -0
- package/comate-engine/plugins/centrino/dist/help.md +0 -30
- package/comate-engine/plugins/centrino/dist/index.js +0 -1046
- package/comate-engine/plugins/centrino/package.json +0 -68
- package/comate-engine/plugins/cnap/assets/cnap.png +0 -0
- package/comate-engine/plugins/cnap/dist/help.md +0 -11
- package/comate-engine/plugins/cnap/dist/index.js +0 -171
- package/comate-engine/plugins/cnap/package.json +0 -65
- package/comate-engine/plugins/demo-timer/assets/icon.svg +0 -2
- package/comate-engine/plugins/demo-timer/dist/index.js +0 -463
- package/comate-engine/plugins/demo-timer/package.json +0 -73
- package/comate-engine/plugins/dev-tools/assets/icon.png +0 -0
- package/comate-engine/plugins/dev-tools/dist/help.md +0 -18
- package/comate-engine/plugins/dev-tools/dist/index.js +0 -166160
- package/comate-engine/plugins/dev-tools/package.json +0 -95
- package/comate-engine/plugins/devaux/assets/icon.svg +0 -1
- package/comate-engine/plugins/devaux/dist/help.md +0 -41
- package/comate-engine/plugins/devaux/dist/index.js +0 -75551
- package/comate-engine/plugins/devaux/dist/static/tree-sitter-cpp.wasm +0 -0
- package/comate-engine/plugins/devaux/dist/static/tree-sitter-go.wasm +0 -0
- package/comate-engine/plugins/devaux/dist/static/tree-sitter.wasm +0 -0
- package/comate-engine/plugins/devaux/dist/tree-sitter.wasm +0 -0
- package/comate-engine/plugins/devaux/package.json +0 -82
- package/comate-engine/plugins/f2c/assets/icon.svg +0 -11
- package/comate-engine/plugins/f2c/dist/help.md +0 -13
- package/comate-engine/plugins/f2c/dist/index.js +0 -101649
- package/comate-engine/plugins/f2c/package.json +0 -56
- package/comate-engine/plugins/fcnap/assets/icon.png +0 -0
- package/comate-engine/plugins/fcnap/dist/help.md +0 -9
- package/comate-engine/plugins/fcnap/dist/index.js +0 -105
- package/comate-engine/plugins/fcnap/package.json +0 -50
- package/comate-engine/plugins/front-end-skills/assets/icon.svg +0 -1
- package/comate-engine/plugins/front-end-skills/dist/help.md +0 -17
- package/comate-engine/plugins/front-end-skills/dist/index.js +0 -8172
- package/comate-engine/plugins/front-end-skills/package.json +0 -79
- package/comate-engine/plugins/gdp/assets/icon.png +0 -0
- package/comate-engine/plugins/gdp/dist/help.md +0 -11
- package/comate-engine/plugins/gdp/dist/index.js +0 -70806
- package/comate-engine/plugins/gdp/package.json +0 -80
- package/comate-engine/plugins/git/assets/git.svg +0 -1
- package/comate-engine/plugins/git/assets/icon.svg +0 -1
- package/comate-engine/plugins/git/dist/help.md +0 -7
- package/comate-engine/plugins/git/dist/index.js +0 -32765
- package/comate-engine/plugins/git/package.json +0 -91
- package/comate-engine/plugins/harmonyos/assets/harmonyos.png +0 -0
- package/comate-engine/plugins/harmonyos/dist/index.js +0 -78
- package/comate-engine/plugins/harmonyos/package.json +0 -37
- package/comate-engine/plugins/iapi/assets/icon.png +0 -0
- package/comate-engine/plugins/iapi/dist/help.md +0 -13
- package/comate-engine/plugins/iapi/dist/index.js +0 -458
- package/comate-engine/plugins/iapi/dist/static/lang/tree-sitter-go.wasm +0 -0
- package/comate-engine/plugins/iapi/dist/static/lang/tree-sitter-java.wasm +0 -0
- package/comate-engine/plugins/iapi/dist/static/tree-sitter-go.wasm +0 -0
- package/comate-engine/plugins/iapi/dist/static/tree-sitter-java.wasm +0 -0
- package/comate-engine/plugins/iapi/dist/tree-sitter.wasm +0 -0
- package/comate-engine/plugins/iapi/package.json +0 -102
- package/comate-engine/plugins/icafe/assets/icafe.svg +0 -1
- package/comate-engine/plugins/icafe/dist/help.md +0 -5
- package/comate-engine/plugins/icafe/dist/index.js +0 -885
- package/comate-engine/plugins/icafe/package.json +0 -74
- package/comate-engine/plugins/ievalue/assets/iEValue.svg +0 -10
- package/comate-engine/plugins/ievalue/dist/index.js +0 -2920
- package/comate-engine/plugins/ievalue/package.json +0 -88
- package/comate-engine/plugins/ipipe/assets/iPipePlugin.png +0 -0
- package/comate-engine/plugins/ipipe/dist/help.md +0 -15
- package/comate-engine/plugins/ipipe/dist/index.js +0 -7268
- package/comate-engine/plugins/ipipe/package.json +0 -62
- package/comate-engine/plugins/jarvis/assets/icon.svg +0 -1
- package/comate-engine/plugins/jarvis/dist/help.md +0 -17
- package/comate-engine/plugins/jarvis/dist/index.js +0 -140473
- package/comate-engine/plugins/jarvis/package.json +0 -93
- package/comate-engine/plugins/mapsearch/assets/mapsearchicon.png +0 -0
- package/comate-engine/plugins/mapsearch/dist/help.md +0 -4
- package/comate-engine/plugins/mapsearch/dist/index.js +0 -145
- package/comate-engine/plugins/mapsearch/package.json +0 -53
- package/comate-engine/plugins/paddle/assets/icon.png +0 -0
- package/comate-engine/plugins/paddle/assets/paconvert-3.0.1-py3-none-any.whl +0 -0
- package/comate-engine/plugins/paddle/dist/help.md +0 -31
- package/comate-engine/plugins/paddle/dist/index.js +0 -1011
- package/comate-engine/plugins/paddle/package.json +0 -129
- package/comate-engine/plugins/robot/assets/Robot.png +0 -0
- package/comate-engine/plugins/robot/dist/index.js +0 -476
- package/comate-engine/plugins/robot/package.json +0 -91
- package/comate-engine/plugins/security/assets/comate.png +0 -0
- package/comate-engine/plugins/security/dist/index.js +0 -18434
- package/comate-engine/plugins/security/package.json +0 -82
- package/comate-engine/plugins/smartapp/assets/icon.png +0 -0
- package/comate-engine/plugins/smartapp/dist/help.md +0 -4
- package/comate-engine/plugins/smartapp/dist/index.js +0 -113
- package/comate-engine/plugins/smartapp/package.json +0 -54
- package/comate-engine/plugins/testmate/assets/icon.svg +0 -1
- package/comate-engine/plugins/testmate/dist/help.md +0 -62
- package/comate-engine/plugins/testmate/dist/index.js +0 -21483
- package/comate-engine/plugins/testmate/package.json +0 -85
- package/comate-engine/plugins/tor/assets/TorPlugin.png +0 -0
- package/comate-engine/plugins/tor/dist/help.md +0 -22
- package/comate-engine/plugins/tor/dist/index.js +0 -807
- package/comate-engine/plugins/tor/package.json +0 -99
- package/comate-engine/plugins/weiyun/assets/icon.png +0 -0
- package/comate-engine/plugins/weiyun/dist/help.md +0 -11
- package/comate-engine/plugins/weiyun/dist/index.js +0 -100495
- package/comate-engine/plugins/weiyun/package.json +0 -55
- package/comate-engine/plugins/workcard/assets/favicon.png +0 -0
- package/comate-engine/plugins/workcard/dist/help.md +0 -30
- package/comate-engine/plugins/workcard/dist/index.js +0 -547
- package/comate-engine/plugins/workcard/package.json +0 -102
|
@@ -1,837 +0,0 @@
|
|
|
1
|
-
import { SkillProvider, StringChunkStream } from '@comate/plugin-host';
|
|
2
|
-
import { readFileSync } from 'fs';
|
|
3
|
-
import { fileURLToPath } from 'node:url';
|
|
4
|
-
import path, { dirname } from 'path';
|
|
5
|
-
|
|
6
|
-
class HelpSkillProvider extends SkillProvider {
|
|
7
|
-
static{
|
|
8
|
-
this.skillName = 'help';
|
|
9
|
-
}
|
|
10
|
-
static{
|
|
11
|
-
this.description = '插件介绍';
|
|
12
|
-
}
|
|
13
|
-
static{
|
|
14
|
-
this.parameters = {
|
|
15
|
-
type: 'object',
|
|
16
|
-
properties: {}
|
|
17
|
-
};
|
|
18
|
-
}
|
|
19
|
-
async *execute() {
|
|
20
|
-
const stream = new StringChunkStream();
|
|
21
|
-
try {
|
|
22
|
-
const filename = fileURLToPath(import.meta.url);
|
|
23
|
-
const content = readFileSync(`${dirname(filename)}/help.md`, 'utf8');
|
|
24
|
-
yield stream.flush(content);
|
|
25
|
-
} catch (error) {
|
|
26
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
27
|
-
yield stream.flushReplaceLast(`抱歉\n\n插件发生出错,${error}。`);
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
const API_SERVER_HOST = 'http://10.169.27.242:8089/comate';
|
|
33
|
-
// export const API_SERVER_HOST = 'http://localhost:8080/comate';
|
|
34
|
-
const WEB_LINK = 'https://casebuilder.n.baidu-int.com';
|
|
35
|
-
const MAX_DEMO_CONTENT_LENGTH = 5000;
|
|
36
|
-
|
|
37
|
-
function createParser(onParse) {
|
|
38
|
-
let isFirstChunk, buffer, startingPosition, startingFieldLength, eventId, eventName, data;
|
|
39
|
-
return reset(), { feed, reset };
|
|
40
|
-
function reset() {
|
|
41
|
-
isFirstChunk = !0, buffer = "", startingPosition = 0, startingFieldLength = -1, eventId = void 0, eventName = void 0, data = "";
|
|
42
|
-
}
|
|
43
|
-
function feed(chunk) {
|
|
44
|
-
buffer = buffer ? buffer + chunk : chunk, isFirstChunk && hasBom(buffer) && (buffer = buffer.slice(BOM.length)), isFirstChunk = !1;
|
|
45
|
-
const length = buffer.length;
|
|
46
|
-
let position = 0, discardTrailingNewline = !1;
|
|
47
|
-
for (; position < length; ) {
|
|
48
|
-
discardTrailingNewline && (buffer[position] === `
|
|
49
|
-
` && ++position, discardTrailingNewline = !1);
|
|
50
|
-
let lineLength = -1, fieldLength = startingFieldLength, character;
|
|
51
|
-
for (let index = startingPosition; lineLength < 0 && index < length; ++index)
|
|
52
|
-
character = buffer[index], character === ":" && fieldLength < 0 ? fieldLength = index - position : character === "\r" ? (discardTrailingNewline = !0, lineLength = index - position) : character === `
|
|
53
|
-
` && (lineLength = index - position);
|
|
54
|
-
if (lineLength < 0) {
|
|
55
|
-
startingPosition = length - position, startingFieldLength = fieldLength;
|
|
56
|
-
break;
|
|
57
|
-
} else
|
|
58
|
-
startingPosition = 0, startingFieldLength = -1;
|
|
59
|
-
parseEventStreamLine(buffer, position, fieldLength, lineLength), position += lineLength + 1;
|
|
60
|
-
}
|
|
61
|
-
position === length ? buffer = "" : position > 0 && (buffer = buffer.slice(position));
|
|
62
|
-
}
|
|
63
|
-
function parseEventStreamLine(lineBuffer, index, fieldLength, lineLength) {
|
|
64
|
-
if (lineLength === 0) {
|
|
65
|
-
data.length > 0 && (onParse({
|
|
66
|
-
type: "event",
|
|
67
|
-
id: eventId,
|
|
68
|
-
event: eventName || void 0,
|
|
69
|
-
data: data.slice(0, -1)
|
|
70
|
-
// remove trailing newline
|
|
71
|
-
}), data = "", eventId = void 0), eventName = void 0;
|
|
72
|
-
return;
|
|
73
|
-
}
|
|
74
|
-
const noValue = fieldLength < 0, field = lineBuffer.slice(index, index + (noValue ? lineLength : fieldLength));
|
|
75
|
-
let step = 0;
|
|
76
|
-
noValue ? step = lineLength : lineBuffer[index + fieldLength + 1] === " " ? step = fieldLength + 2 : step = fieldLength + 1;
|
|
77
|
-
const position = index + step, valueLength = lineLength - step, value = lineBuffer.slice(position, position + valueLength).toString();
|
|
78
|
-
if (field === "data")
|
|
79
|
-
data += value ? `${value}
|
|
80
|
-
` : `
|
|
81
|
-
`;
|
|
82
|
-
else if (field === "event")
|
|
83
|
-
eventName = value;
|
|
84
|
-
else if (field === "id" && !value.includes("\0"))
|
|
85
|
-
eventId = value;
|
|
86
|
-
else if (field === "retry") {
|
|
87
|
-
const retry = parseInt(value, 10);
|
|
88
|
-
Number.isNaN(retry) || onParse({ type: "reconnect-interval", value: retry });
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
const BOM = [239, 187, 191];
|
|
93
|
-
function hasBom(buffer) {
|
|
94
|
-
return BOM.every((charCode, index) => buffer.charCodeAt(index) === charCode);
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
class EventSourceParserStream extends TransformStream {
|
|
98
|
-
constructor() {
|
|
99
|
-
let parser;
|
|
100
|
-
super({
|
|
101
|
-
start(controller) {
|
|
102
|
-
parser = createParser((event) => {
|
|
103
|
-
event.type === "event" && controller.enqueue(event);
|
|
104
|
-
});
|
|
105
|
-
},
|
|
106
|
-
transform(chunk) {
|
|
107
|
-
parser.feed(chunk);
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
}
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
const apiRequest = async (method, path, options = {}, timeout = 5000)=>{
|
|
114
|
-
try {
|
|
115
|
-
const response = await fetch(`${API_SERVER_HOST}${path}`, {
|
|
116
|
-
method,
|
|
117
|
-
...options,
|
|
118
|
-
signal: AbortSignal.timeout(timeout)
|
|
119
|
-
});
|
|
120
|
-
if (!response.ok) {
|
|
121
|
-
throw new Error(`[${response.status}] 请求错误。请求参数:${JSON.stringify({
|
|
122
|
-
method,
|
|
123
|
-
path,
|
|
124
|
-
...options
|
|
125
|
-
})}`);
|
|
126
|
-
}
|
|
127
|
-
const jsonRes = response.json();
|
|
128
|
-
return jsonRes.then((res)=>{
|
|
129
|
-
if (res.code !== 'OK') {
|
|
130
|
-
throw new Error(`[${res.code}] ${res.message}`);
|
|
131
|
-
} else {
|
|
132
|
-
return res.data;
|
|
133
|
-
}
|
|
134
|
-
});
|
|
135
|
-
} catch (err) {
|
|
136
|
-
throw err;
|
|
137
|
-
}
|
|
138
|
-
};
|
|
139
|
-
async function* sseRequest(method, path, options = {}) {
|
|
140
|
-
try {
|
|
141
|
-
const response = await fetch(`${API_SERVER_HOST}${path}`, {
|
|
142
|
-
method,
|
|
143
|
-
headers: {
|
|
144
|
-
'Content-Type': 'application/json'
|
|
145
|
-
},
|
|
146
|
-
...options
|
|
147
|
-
});
|
|
148
|
-
if (!response.ok) {
|
|
149
|
-
throw new Error(`[${response.status}] 请求错误。请求参数:${JSON.stringify({
|
|
150
|
-
method,
|
|
151
|
-
path,
|
|
152
|
-
...options
|
|
153
|
-
})}`);
|
|
154
|
-
}
|
|
155
|
-
if (!response.body) {
|
|
156
|
-
throw new Error(`[${response.status}] 响应体错误。请求参数:${JSON.stringify({
|
|
157
|
-
method,
|
|
158
|
-
path,
|
|
159
|
-
...options
|
|
160
|
-
})}`);
|
|
161
|
-
}
|
|
162
|
-
// 兼容非流式返回的处理逻辑
|
|
163
|
-
const contentType = response.headers.get('Content-Type');
|
|
164
|
-
if (contentType?.indexOf('application/json') !== -1) {
|
|
165
|
-
const jsonRes = response.json();
|
|
166
|
-
yield jsonRes.then((res)=>{
|
|
167
|
-
if (res.code !== 'OK') {
|
|
168
|
-
throw new Error(`[${res.code}] ${res.message}`);
|
|
169
|
-
} else {
|
|
170
|
-
return res.data;
|
|
171
|
-
}
|
|
172
|
-
});
|
|
173
|
-
}
|
|
174
|
-
const resBody = await response.body.pipeThrough(new TextDecoderStream()).pipeThrough(new EventSourceParserStream());
|
|
175
|
-
const reader = resBody.getReader();
|
|
176
|
-
try {
|
|
177
|
-
while(true){
|
|
178
|
-
const { value, done } = await reader.read();
|
|
179
|
-
if (done) {
|
|
180
|
-
break;
|
|
181
|
-
}
|
|
182
|
-
const { event, data } = value;
|
|
183
|
-
if (event && [
|
|
184
|
-
'FatalError',
|
|
185
|
-
'BadRequest'
|
|
186
|
-
].includes(event)) {
|
|
187
|
-
throw new Error(data);
|
|
188
|
-
}
|
|
189
|
-
if (event !== 'Msg' || !data.length) {
|
|
190
|
-
continue;
|
|
191
|
-
}
|
|
192
|
-
yield data.replaceAll('\\x0A', '\n');
|
|
193
|
-
}
|
|
194
|
-
} catch (e) {
|
|
195
|
-
throw e;
|
|
196
|
-
} finally{
|
|
197
|
-
reader.releaseLock();
|
|
198
|
-
}
|
|
199
|
-
} catch (err) {
|
|
200
|
-
throw err;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
|
-
const queryRepo = (username, repo)=>{
|
|
204
|
-
return apiRequest('GET', `/query/repo?repo=${repo}`, {
|
|
205
|
-
headers: {
|
|
206
|
-
'X-COMATE-USER': username
|
|
207
|
-
}
|
|
208
|
-
});
|
|
209
|
-
};
|
|
210
|
-
const setRepoProject = (username, repo, projectId)=>{
|
|
211
|
-
return apiRequest('POST', `/set/repo/project?repo=${repo}`, {
|
|
212
|
-
headers: {
|
|
213
|
-
'X-COMATE-USER': username,
|
|
214
|
-
'Content-Type': 'application/json'
|
|
215
|
-
},
|
|
216
|
-
body: JSON.stringify({
|
|
217
|
-
projectId
|
|
218
|
-
})
|
|
219
|
-
});
|
|
220
|
-
};
|
|
221
|
-
const setProjectCaseDemoContent = (username, repo, content)=>{
|
|
222
|
-
return apiRequest('POST', `/set/project/case-demo-content?repo=${repo}`, {
|
|
223
|
-
headers: {
|
|
224
|
-
'X-COMATE-USER': username,
|
|
225
|
-
'Content-Type': 'application/json'
|
|
226
|
-
},
|
|
227
|
-
body: JSON.stringify({
|
|
228
|
-
caseDemoContent: content
|
|
229
|
-
})
|
|
230
|
-
});
|
|
231
|
-
};
|
|
232
|
-
const analyzeRepo = (username, repo, fileRelPath, content)=>{
|
|
233
|
-
return apiRequest('POST', `/analyze/repo?repo=${repo}`, {
|
|
234
|
-
headers: {
|
|
235
|
-
'X-COMATE-USER': username,
|
|
236
|
-
'Content-Type': 'application/json'
|
|
237
|
-
},
|
|
238
|
-
body: JSON.stringify({
|
|
239
|
-
fileRelPath,
|
|
240
|
-
fileContent: content
|
|
241
|
-
})
|
|
242
|
-
}, 10000);
|
|
243
|
-
};
|
|
244
|
-
// 创建AppBuilder会话id
|
|
245
|
-
const newChat = (username, repo, sessionId, ide)=>{
|
|
246
|
-
return apiRequest('POST', `/chat/new?repo=${repo}`, {
|
|
247
|
-
headers: {
|
|
248
|
-
'X-COMATE-USER': username,
|
|
249
|
-
'Content-Type': 'application/json'
|
|
250
|
-
},
|
|
251
|
-
body: JSON.stringify({
|
|
252
|
-
sessionId,
|
|
253
|
-
ide
|
|
254
|
-
})
|
|
255
|
-
});
|
|
256
|
-
};
|
|
257
|
-
// 函数检索测试
|
|
258
|
-
const ragRepoFunc = (username, repo, query)=>{
|
|
259
|
-
return apiRequest('POST', `/rag/repo-func?repo=${repo}`, {
|
|
260
|
-
headers: {
|
|
261
|
-
'X-COMATE-USER': username,
|
|
262
|
-
'Content-Type': 'application/json'
|
|
263
|
-
},
|
|
264
|
-
body: JSON.stringify({
|
|
265
|
-
query
|
|
266
|
-
})
|
|
267
|
-
}, 20000);
|
|
268
|
-
};
|
|
269
|
-
// AppBuilder多轮对话生成代码
|
|
270
|
-
async function genCaseCodeByAB(username, repo, cid, query, caseDemoContent, isFirstRound) {
|
|
271
|
-
const res = await sseRequest('POST', `/gen/case-code-by-ab?repo=${repo}`, {
|
|
272
|
-
body: JSON.stringify({
|
|
273
|
-
cid,
|
|
274
|
-
query,
|
|
275
|
-
caseDemoContent,
|
|
276
|
-
isFirstRound
|
|
277
|
-
}),
|
|
278
|
-
headers: {
|
|
279
|
-
'X-COMATE-USER': username,
|
|
280
|
-
'Content-Type': 'application/json'
|
|
281
|
-
}
|
|
282
|
-
});
|
|
283
|
-
return res;
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
const pickICodeNameRepository = (repository)=>{
|
|
287
|
-
if (repository.versionControl === 'git') {
|
|
288
|
-
const repositoryUrl = repository.repositoryUrl;
|
|
289
|
-
const matched = repositoryUrl?.match(/ssh:\/\/[^/]+\/(.+)/);
|
|
290
|
-
if (matched && matched.length > 1) {
|
|
291
|
-
return matched[1];
|
|
292
|
-
}
|
|
293
|
-
}
|
|
294
|
-
return null;
|
|
295
|
-
};
|
|
296
|
-
|
|
297
|
-
class InfoSkillProvider extends SkillProvider {
|
|
298
|
-
static{
|
|
299
|
-
this.skillName = 'info';
|
|
300
|
-
}
|
|
301
|
-
static{
|
|
302
|
-
this.displayName = '查看当前代码库信息';
|
|
303
|
-
}
|
|
304
|
-
static{
|
|
305
|
-
this.description = '查看当前代码库在平台的信息和iAPI绑定关系';
|
|
306
|
-
}
|
|
307
|
-
static{
|
|
308
|
-
this.parameters = {
|
|
309
|
-
type: 'object',
|
|
310
|
-
properties: {}
|
|
311
|
-
};
|
|
312
|
-
}
|
|
313
|
-
async *execute() {
|
|
314
|
-
const stream = new StringChunkStream();
|
|
315
|
-
try {
|
|
316
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
317
|
-
if (!userDetail) {
|
|
318
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
319
|
-
return;
|
|
320
|
-
}
|
|
321
|
-
const repository = await this.retriever.repositoryInfo();
|
|
322
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
323
|
-
if (!repositoryUrl) {
|
|
324
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
325
|
-
return;
|
|
326
|
-
}
|
|
327
|
-
yield stream.flush('-> 正在获取当前仓库在平台的配置...\n\n');
|
|
328
|
-
const teamRepo = await queryRepo(userDetail.name, repositoryUrl);
|
|
329
|
-
yield stream.flush('-> 获取仓库配置成功,信息如下:\n\n');
|
|
330
|
-
const activeProject = teamRepo?.repoProjects.find((item)=>item.projectId === teamRepo.activeProjectId);
|
|
331
|
-
stream.append(`仓库名称:${teamRepo.name}\n\n`);
|
|
332
|
-
stream.append(`默认iAPI项目:${activeProject ? activeProject.name : '未设置'}\n\n`);
|
|
333
|
-
stream.append(`描述:${teamRepo.description}\n\n`);
|
|
334
|
-
stream.append('关联的iAPI项目:\n\n');
|
|
335
|
-
const projectTable = this.render.table(teamRepo?.repoProjects || [], {
|
|
336
|
-
columns: [
|
|
337
|
-
{
|
|
338
|
-
field: 'projectId',
|
|
339
|
-
title: '项目ID'
|
|
340
|
-
},
|
|
341
|
-
{
|
|
342
|
-
field: 'name',
|
|
343
|
-
title: '名称'
|
|
344
|
-
}
|
|
345
|
-
]
|
|
346
|
-
});
|
|
347
|
-
yield stream.flush(projectTable);
|
|
348
|
-
yield stream.flush('\n\n');
|
|
349
|
-
} catch (error) {
|
|
350
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
351
|
-
yield stream.flushReplaceLast(`${error}`);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
|
|
356
|
-
class SetRepoProjectSkillProvider extends SkillProvider {
|
|
357
|
-
static{
|
|
358
|
-
this.skillName = 'setRepoProject';
|
|
359
|
-
}
|
|
360
|
-
static{
|
|
361
|
-
this.displayName = '设置默认IAPI项目';
|
|
362
|
-
}
|
|
363
|
-
static{
|
|
364
|
-
this.description = '代码库必须要和IAPI项目做绑定,同时只能使用一个IAPI项目做接口生成';
|
|
365
|
-
}
|
|
366
|
-
static{
|
|
367
|
-
this.parameters = {
|
|
368
|
-
type: 'object',
|
|
369
|
-
properties: {}
|
|
370
|
-
};
|
|
371
|
-
}
|
|
372
|
-
async *execute() {
|
|
373
|
-
const stream = new StringChunkStream();
|
|
374
|
-
try {
|
|
375
|
-
const { query } = this.currentContext;
|
|
376
|
-
const projectId = query.trim();
|
|
377
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
378
|
-
if (!userDetail) {
|
|
379
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
380
|
-
return;
|
|
381
|
-
}
|
|
382
|
-
const fs = await this.requestWorkspaceFileSystem();
|
|
383
|
-
if (!fs) {
|
|
384
|
-
yield stream.flush('请先完成授权,CaseBuilder 插件需在用户授权工作区的文件读取权限后才能使用。');
|
|
385
|
-
return;
|
|
386
|
-
}
|
|
387
|
-
const repository = await this.retriever.repositoryInfo();
|
|
388
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
389
|
-
if (!repositoryUrl) {
|
|
390
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
391
|
-
return;
|
|
392
|
-
}
|
|
393
|
-
if (projectId == '') {
|
|
394
|
-
yield stream.flushReplaceLast('请输入需要设置的默认iAPI项目ID。');
|
|
395
|
-
return;
|
|
396
|
-
}
|
|
397
|
-
const repoProject = await setRepoProject(userDetail.name, repositoryUrl, projectId);
|
|
398
|
-
if (repoProject.name == '') {
|
|
399
|
-
yield stream.flushReplaceLast('设置默认iAPI项目失败,iAPI项目不存在,请检查输入的iAPI项目ID是否正确。');
|
|
400
|
-
return;
|
|
401
|
-
}
|
|
402
|
-
yield stream.flush('-> 设置默认iAPI项目成功。\n\n');
|
|
403
|
-
yield stream.flush('-> 当前默认iAPI项目:\n\n');
|
|
404
|
-
const projectTable = this.render.table([
|
|
405
|
-
repoProject
|
|
406
|
-
], {
|
|
407
|
-
columns: [
|
|
408
|
-
{
|
|
409
|
-
field: 'projectId',
|
|
410
|
-
title: '项目ID'
|
|
411
|
-
},
|
|
412
|
-
{
|
|
413
|
-
field: 'name',
|
|
414
|
-
title: '名称'
|
|
415
|
-
}
|
|
416
|
-
]
|
|
417
|
-
});
|
|
418
|
-
yield stream.flush(projectTable);
|
|
419
|
-
yield stream.flush('\n\n');
|
|
420
|
-
} catch (error) {
|
|
421
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
422
|
-
yield stream.flushReplaceLast(`${error}`);
|
|
423
|
-
}
|
|
424
|
-
}
|
|
425
|
-
}
|
|
426
|
-
|
|
427
|
-
class SetCaseDemoContentSkillProvider extends SkillProvider {
|
|
428
|
-
static{
|
|
429
|
-
this.skillName = 'setCaseDemoContent';
|
|
430
|
-
}
|
|
431
|
-
static{
|
|
432
|
-
this.displayName = '设置【用例样例】代码';
|
|
433
|
-
}
|
|
434
|
-
static{
|
|
435
|
-
this.description = '用例样例代码可用于用例生成的参考代码';
|
|
436
|
-
}
|
|
437
|
-
static{
|
|
438
|
-
this.parameters = {
|
|
439
|
-
type: 'object',
|
|
440
|
-
properties: {}
|
|
441
|
-
};
|
|
442
|
-
}
|
|
443
|
-
async *execute() {
|
|
444
|
-
const stream = new StringChunkStream();
|
|
445
|
-
try {
|
|
446
|
-
const { activeFilePath, activeFileContent, selectedCode } = this.currentContext;
|
|
447
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
448
|
-
if (!userDetail) {
|
|
449
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
450
|
-
return;
|
|
451
|
-
}
|
|
452
|
-
const fs = await this.requestWorkspaceFileSystem();
|
|
453
|
-
if (!fs) {
|
|
454
|
-
yield stream.flush('请先完成授权,CaseBuilder 插件需在用户授权工作区的文件读取权限后才能使用。');
|
|
455
|
-
return;
|
|
456
|
-
}
|
|
457
|
-
const repository = await this.retriever.repositoryInfo();
|
|
458
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
459
|
-
if (!repositoryUrl) {
|
|
460
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
461
|
-
return;
|
|
462
|
-
}
|
|
463
|
-
if (activeFilePath == '') {
|
|
464
|
-
yield stream.flushReplaceLast('未打开任何文件,请先打开需要设置的用例样例文件。');
|
|
465
|
-
return;
|
|
466
|
-
}
|
|
467
|
-
if (activeFileContent == '') {
|
|
468
|
-
yield stream.flushReplaceLast('当前文件内容为空,请先编辑需要设置的用例样例文件。');
|
|
469
|
-
return;
|
|
470
|
-
}
|
|
471
|
-
let fileContent = activeFileContent;
|
|
472
|
-
yield stream.flush('-> 使用当前编辑器中打开的文件作为用例样例文件。\n\n');
|
|
473
|
-
yield stream.flush(`-> 用例样例文件为:${activeFilePath}\n\n`);
|
|
474
|
-
if (selectedCode.length) {
|
|
475
|
-
fileContent = selectedCode;
|
|
476
|
-
yield stream.flush('-> 使用当前编辑器中选中的代码作为用例样例文件。\n\n');
|
|
477
|
-
}
|
|
478
|
-
const fileContentLength = fileContent.length;
|
|
479
|
-
yield stream.flush(`-> 当前样例文件长度: ${fileContentLength}。\n\n`);
|
|
480
|
-
if (fileContentLength > MAX_DEMO_CONTENT_LENGTH) {
|
|
481
|
-
yield stream.flush(`-> 样例文件超过 ${MAX_DEMO_CONTENT_LENGTH} 字符限制,请编辑更短的样例文件。\n\n`);
|
|
482
|
-
return;
|
|
483
|
-
}
|
|
484
|
-
await setProjectCaseDemoContent(userDetail.name, repositoryUrl, fileContent);
|
|
485
|
-
yield stream.flush('-> 设置用例样例文件成功。\n\n');
|
|
486
|
-
} catch (error) {
|
|
487
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
488
|
-
yield stream.flushReplaceLast(`${error}`);
|
|
489
|
-
}
|
|
490
|
-
}
|
|
491
|
-
}
|
|
492
|
-
|
|
493
|
-
const blackFileList = [
|
|
494
|
-
'__init__.py',
|
|
495
|
-
'.DS_Store'
|
|
496
|
-
];
|
|
497
|
-
const getFilesFromDirectory = async (files, rootDir, fs)=>{
|
|
498
|
-
rootDir = rootDir.replace(/\/$/, '');
|
|
499
|
-
const dirs = await fs.readDirectory(rootDir);
|
|
500
|
-
for (const item of dirs){
|
|
501
|
-
if (item.type === 'directory') {
|
|
502
|
-
await getFilesFromDirectory(files, path.join(rootDir, item.name), fs);
|
|
503
|
-
}
|
|
504
|
-
if (item.type === 'file') {
|
|
505
|
-
if (blackFileList.includes(item.name)) {
|
|
506
|
-
continue;
|
|
507
|
-
}
|
|
508
|
-
files.push({
|
|
509
|
-
name: item.name,
|
|
510
|
-
path: path.normalize(rootDir),
|
|
511
|
-
status: 'pending'
|
|
512
|
-
});
|
|
513
|
-
}
|
|
514
|
-
}
|
|
515
|
-
return files;
|
|
516
|
-
};
|
|
517
|
-
|
|
518
|
-
class RepoAnalyzeSkillProvider extends SkillProvider {
|
|
519
|
-
static{
|
|
520
|
-
this.skillName = 'repoAnalyze';
|
|
521
|
-
}
|
|
522
|
-
static{
|
|
523
|
-
this.displayName = '分析代码库';
|
|
524
|
-
}
|
|
525
|
-
static{
|
|
526
|
-
this.description = '指定目录或文件进行分析代码。';
|
|
527
|
-
}
|
|
528
|
-
static{
|
|
529
|
-
this.parameters = {
|
|
530
|
-
type: 'object',
|
|
531
|
-
properties: {}
|
|
532
|
-
};
|
|
533
|
-
}
|
|
534
|
-
renderFileTableString(files) {
|
|
535
|
-
return this.render.table(files, {
|
|
536
|
-
columns: [
|
|
537
|
-
{
|
|
538
|
-
field: 'path',
|
|
539
|
-
title: '目录'
|
|
540
|
-
},
|
|
541
|
-
{
|
|
542
|
-
field: 'name',
|
|
543
|
-
title: '文件名'
|
|
544
|
-
},
|
|
545
|
-
{
|
|
546
|
-
field: 'status',
|
|
547
|
-
title: '状态',
|
|
548
|
-
format: (v)=>{
|
|
549
|
-
switch(v){
|
|
550
|
-
case 'pending':
|
|
551
|
-
return '待提交';
|
|
552
|
-
case 'processing':
|
|
553
|
-
return '提交中';
|
|
554
|
-
case 'success':
|
|
555
|
-
return '已提交';
|
|
556
|
-
case 'failed':
|
|
557
|
-
return '提交失败';
|
|
558
|
-
case 'ignore':
|
|
559
|
-
return '忽略';
|
|
560
|
-
case 'empty':
|
|
561
|
-
return '空文件';
|
|
562
|
-
case 'exists':
|
|
563
|
-
return '任务已存在';
|
|
564
|
-
default:
|
|
565
|
-
return v;
|
|
566
|
-
}
|
|
567
|
-
}
|
|
568
|
-
},
|
|
569
|
-
{
|
|
570
|
-
field: 'err',
|
|
571
|
-
title: '失败原因',
|
|
572
|
-
format: (v)=>v || ''
|
|
573
|
-
}
|
|
574
|
-
]
|
|
575
|
-
});
|
|
576
|
-
}
|
|
577
|
-
async *execute() {
|
|
578
|
-
const stream = new StringChunkStream();
|
|
579
|
-
try {
|
|
580
|
-
const { query, selectedCode, activeFilePath } = this.currentContext;
|
|
581
|
-
let keyword = path.normalize(query.trim());
|
|
582
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
583
|
-
if (!userDetail) {
|
|
584
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
585
|
-
return;
|
|
586
|
-
}
|
|
587
|
-
const fs = await this.requestWorkspaceFileSystem();
|
|
588
|
-
if (!fs) {
|
|
589
|
-
yield stream.flush('请先完成授权,CaseBuilder 插件需在用户授权工作区的文件读取权限后才能使用。');
|
|
590
|
-
return;
|
|
591
|
-
}
|
|
592
|
-
const repository = await this.retriever.repositoryInfo();
|
|
593
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
594
|
-
if (!repositoryUrl) {
|
|
595
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
596
|
-
return;
|
|
597
|
-
}
|
|
598
|
-
const isSelectedCode = activeFilePath.length && selectedCode.length;
|
|
599
|
-
let fileMode = 'openFile';
|
|
600
|
-
if ([
|
|
601
|
-
'',
|
|
602
|
-
'.',
|
|
603
|
-
'./'
|
|
604
|
-
].includes(keyword)) {
|
|
605
|
-
if ((keyword === '.' || keyword === '') && isSelectedCode) {
|
|
606
|
-
keyword = activeFilePath;
|
|
607
|
-
fileMode = 'selectedCode';
|
|
608
|
-
} else {
|
|
609
|
-
yield stream.flushReplaceLast('请输入需要分析的目录、文件或者选中代码段,不允许输入根目录。');
|
|
610
|
-
return;
|
|
611
|
-
}
|
|
612
|
-
}
|
|
613
|
-
let files = [];
|
|
614
|
-
let fileOrDir;
|
|
615
|
-
try {
|
|
616
|
-
fileOrDir = await fs.stat(keyword);
|
|
617
|
-
} catch (error) {
|
|
618
|
-
yield stream.flushReplaceLast('目录或文件不存在。');
|
|
619
|
-
return;
|
|
620
|
-
}
|
|
621
|
-
if (fileOrDir.type === 'file') {
|
|
622
|
-
files.push({
|
|
623
|
-
name: path.basename(keyword),
|
|
624
|
-
path: path.dirname(keyword),
|
|
625
|
-
status: 'pending'
|
|
626
|
-
});
|
|
627
|
-
} else if (fileOrDir.type === 'directory') {
|
|
628
|
-
// 遍历目录
|
|
629
|
-
files = await getFilesFromDirectory([], keyword, fs);
|
|
630
|
-
if (files.length === 0) {
|
|
631
|
-
yield stream.flushReplaceLast('目录下没有文件,请选择其他目录');
|
|
632
|
-
return;
|
|
633
|
-
}
|
|
634
|
-
files.sort((a, b)=>a.path.length - b.path.length);
|
|
635
|
-
} else {
|
|
636
|
-
yield stream.flushReplaceLast('请输入正确的目录或文件');
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
639
|
-
yield stream.flushReplaceLast(this.renderFileTableString(files));
|
|
640
|
-
for(const fileIdx in files){
|
|
641
|
-
const file = files[fileIdx];
|
|
642
|
-
const fileRelPath = file.path + '/' + file.name;
|
|
643
|
-
let fileContent;
|
|
644
|
-
if (fileMode === 'openFile') {
|
|
645
|
-
const buf = await fs.readFile(fileRelPath);
|
|
646
|
-
fileContent = buf.toString();
|
|
647
|
-
}
|
|
648
|
-
if (fileMode === 'selectedCode') {
|
|
649
|
-
fileContent = selectedCode;
|
|
650
|
-
}
|
|
651
|
-
if (!fileContent) {
|
|
652
|
-
files[fileIdx].status = 'ignore';
|
|
653
|
-
yield stream.flushReplaceLast(this.renderFileTableString(files));
|
|
654
|
-
continue;
|
|
655
|
-
}
|
|
656
|
-
files[fileIdx].status = 'processing';
|
|
657
|
-
yield stream.flushReplaceLast(this.renderFileTableString(files));
|
|
658
|
-
try {
|
|
659
|
-
const status = await analyzeRepo(userDetail.name, repositoryUrl, fileRelPath, fileContent);
|
|
660
|
-
if (status) {
|
|
661
|
-
files[fileIdx].status = status;
|
|
662
|
-
}
|
|
663
|
-
} catch (error) {
|
|
664
|
-
files[fileIdx].status = 'failed';
|
|
665
|
-
files[fileIdx].err = error;
|
|
666
|
-
}
|
|
667
|
-
yield stream.flushReplaceLast(this.renderFileTableString(files));
|
|
668
|
-
}
|
|
669
|
-
yield stream.flushReplaceLast(this.renderFileTableString(files) + `\n\n分析任务是异步操作,前往 [CaseBuilder-团队-管理函数](${WEB_LINK}/team/repo) 查看任务进度。`);
|
|
670
|
-
} catch (error) {
|
|
671
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
672
|
-
yield stream.flushReplaceLast(`${error}`);
|
|
673
|
-
}
|
|
674
|
-
}
|
|
675
|
-
}
|
|
676
|
-
|
|
677
|
-
class GenCaseV2SkillProvider extends SkillProvider {
|
|
678
|
-
static{
|
|
679
|
-
this.skillName = 'genCaseV2';
|
|
680
|
-
}
|
|
681
|
-
static{
|
|
682
|
-
this.displayName = '用例用例生成V2';
|
|
683
|
-
}
|
|
684
|
-
static{
|
|
685
|
-
this.description = '基于代码库现有函数进行用例生成';
|
|
686
|
-
}
|
|
687
|
-
static{
|
|
688
|
-
this.parameters = {
|
|
689
|
-
type: 'object',
|
|
690
|
-
properties: {}
|
|
691
|
-
};
|
|
692
|
-
}
|
|
693
|
-
async *execute() {
|
|
694
|
-
const stream = new StringChunkStream();
|
|
695
|
-
try {
|
|
696
|
-
const { query, selectedCode } = this.currentContext;
|
|
697
|
-
const trimQuery = query.trim();
|
|
698
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
699
|
-
if (!userDetail) {
|
|
700
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
701
|
-
return;
|
|
702
|
-
}
|
|
703
|
-
const fs = await this.requestWorkspaceFileSystem();
|
|
704
|
-
if (!fs) {
|
|
705
|
-
yield stream.flush('请先完成授权,CaseBuilder 插件需在用户授权工作区的文件读取权限后才能使用。');
|
|
706
|
-
return;
|
|
707
|
-
}
|
|
708
|
-
const repository = await this.retriever.repositoryInfo();
|
|
709
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
710
|
-
if (!repositoryUrl) {
|
|
711
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
712
|
-
return;
|
|
713
|
-
}
|
|
714
|
-
if (trimQuery.length == 0) {
|
|
715
|
-
yield stream.flushReplaceLast('请以自然语言输入用例描述或用例实现步骤。');
|
|
716
|
-
return;
|
|
717
|
-
}
|
|
718
|
-
// 获取当前IDE的sessionId
|
|
719
|
-
const sessionId = this.sessionUuid;
|
|
720
|
-
if (!sessionId) {
|
|
721
|
-
yield stream.flushReplaceLast('IDE sessionId获取失败,请稍后重试。');
|
|
722
|
-
return;
|
|
723
|
-
}
|
|
724
|
-
// 获取当前IDE的名称
|
|
725
|
-
const host = await this.retriever.hostInfo();
|
|
726
|
-
const ideName = host.appName.replaceAll(" ", "_").toLowerCase();
|
|
727
|
-
yield stream.flush('-> 正在获取当前仓库在平台的配置...\n\n');
|
|
728
|
-
const teamRepo = await queryRepo(userDetail.name, repositoryUrl);
|
|
729
|
-
if (teamRepo.activeProjectId == '') {
|
|
730
|
-
yield stream.flush('团队仓库没有激活默认iAPI项目,你可以通过功能【设置默认iAPI项目】快速设置。\n\n');
|
|
731
|
-
return;
|
|
732
|
-
}
|
|
733
|
-
const activeProject = teamRepo?.repoProjects.find((item)=>item.projectId === teamRepo.activeProjectId);
|
|
734
|
-
if (!activeProject) {
|
|
735
|
-
yield stream.flush('团队仓库默认iAPI项目不存在。\n\n');
|
|
736
|
-
return;
|
|
737
|
-
}
|
|
738
|
-
yield stream.flush('-> 获取仓库配置成功,信息如下:\n\n');
|
|
739
|
-
stream.append(`仓库名称:${teamRepo.name}\n\n`);
|
|
740
|
-
stream.append(`默认iAPI项目:${activeProject.name}\n\n`);
|
|
741
|
-
stream.append(`描述:${teamRepo.description}\n\n`);
|
|
742
|
-
stream.append('关联的iAPI项目:\n\n');
|
|
743
|
-
const projectTable = this.render.table(teamRepo?.repoProjects || [], {
|
|
744
|
-
columns: [
|
|
745
|
-
{
|
|
746
|
-
field: 'projectId',
|
|
747
|
-
title: '项目ID'
|
|
748
|
-
},
|
|
749
|
-
{
|
|
750
|
-
field: 'name',
|
|
751
|
-
title: '名称'
|
|
752
|
-
}
|
|
753
|
-
]
|
|
754
|
-
});
|
|
755
|
-
yield stream.flush(projectTable);
|
|
756
|
-
yield stream.flush('\n\n');
|
|
757
|
-
const newChatRes = await newChat(userDetail.name, repositoryUrl, sessionId, ideName);
|
|
758
|
-
if (!newChatRes || !newChatRes.cid) {
|
|
759
|
-
yield stream.flush('生成会话失败,请稍后重试。\n\n');
|
|
760
|
-
return;
|
|
761
|
-
}
|
|
762
|
-
const cid = newChatRes.cid;
|
|
763
|
-
const isFirstRound = newChatRes.isFirstRound;
|
|
764
|
-
yield stream.flush('-> 根据您的需求,开始为您生成接口用例代码...\n\n');
|
|
765
|
-
const codeChunks = await genCaseCodeByAB(userDetail.name, repositoryUrl, cid, trimQuery, selectedCode, isFirstRound);
|
|
766
|
-
for await (const chunk of codeChunks){
|
|
767
|
-
yield stream.flush(chunk);
|
|
768
|
-
}
|
|
769
|
-
yield stream.flush('\n\n');
|
|
770
|
-
} catch (error) {
|
|
771
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
772
|
-
yield stream.flush(`${error}。`);
|
|
773
|
-
}
|
|
774
|
-
}
|
|
775
|
-
}
|
|
776
|
-
|
|
777
|
-
class RagRepoFuncSkillProvider extends SkillProvider {
|
|
778
|
-
static{
|
|
779
|
-
this.skillName = 'ragRepoFunc';
|
|
780
|
-
}
|
|
781
|
-
static{
|
|
782
|
-
this.displayName = '代码库函数命中测试';
|
|
783
|
-
}
|
|
784
|
-
static{
|
|
785
|
-
this.description = '根据关键字检索已经上传AB知识库的函数知识。';
|
|
786
|
-
}
|
|
787
|
-
static{
|
|
788
|
-
this.parameters = {
|
|
789
|
-
type: 'object',
|
|
790
|
-
properties: {}
|
|
791
|
-
};
|
|
792
|
-
}
|
|
793
|
-
async *execute() {
|
|
794
|
-
const stream = new StringChunkStream();
|
|
795
|
-
try {
|
|
796
|
-
const { query } = this.currentContext;
|
|
797
|
-
const keyword = query.trim();
|
|
798
|
-
const userDetail = await this.currentUser.requestDetail();
|
|
799
|
-
if (!userDetail) {
|
|
800
|
-
yield stream.flushReplaceLast('请先完成授权,CaseBuilder 插件需在用户授权后才能使用。');
|
|
801
|
-
return;
|
|
802
|
-
}
|
|
803
|
-
const repository = await this.retriever.repositoryInfo();
|
|
804
|
-
let repositoryUrl = pickICodeNameRepository(repository);
|
|
805
|
-
if (!repositoryUrl) {
|
|
806
|
-
yield stream.flushReplaceLast('无法获取当前项目的仓库地址,可能不是一个icode仓库或者缺少.git配置目录。');
|
|
807
|
-
return;
|
|
808
|
-
}
|
|
809
|
-
if (keyword.length == 0) {
|
|
810
|
-
yield stream.flushReplaceLast('请输入检索关键字,可以是用例描述的某一个步骤。');
|
|
811
|
-
return;
|
|
812
|
-
}
|
|
813
|
-
yield stream.flush('-> 正在为你进行函数命中测试...\n\n');
|
|
814
|
-
const res = await ragRepoFunc(userDetail.name, repositoryUrl, keyword);
|
|
815
|
-
if (res?.length) {
|
|
816
|
-
yield stream.flushReplaceLast(res);
|
|
817
|
-
} else {
|
|
818
|
-
yield stream.flushReplaceLast('没有找到匹配的函数,请调整输入的关键字重新尝试。');
|
|
819
|
-
}
|
|
820
|
-
} catch (error) {
|
|
821
|
-
this.logger.error(`Plugin Error: ${error}`);
|
|
822
|
-
yield stream.flushReplaceLast(`${error}`);
|
|
823
|
-
}
|
|
824
|
-
}
|
|
825
|
-
}
|
|
826
|
-
|
|
827
|
-
function setup({ registry }) {
|
|
828
|
-
registry.registerSkillProvider('help', HelpSkillProvider);
|
|
829
|
-
registry.registerSkillProvider('info', InfoSkillProvider);
|
|
830
|
-
registry.registerSkillProvider('setRepoProject', SetRepoProjectSkillProvider);
|
|
831
|
-
registry.registerSkillProvider('setCaseDemoContent', SetCaseDemoContentSkillProvider);
|
|
832
|
-
registry.registerSkillProvider('repoAnalyze', RepoAnalyzeSkillProvider);
|
|
833
|
-
registry.registerSkillProvider('genCaseV2', GenCaseV2SkillProvider);
|
|
834
|
-
registry.registerSkillProvider('ragRepoFunc', RagRepoFuncSkillProvider);
|
|
835
|
-
}
|
|
836
|
-
|
|
837
|
-
export { setup };
|