ai-worktool 1.0.69 → 1.0.70
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/CHANGELOG.md +1 -1
- package/dist/agents/prompt.js +4 -1
- package/dist/agents/toolCall.js +13 -8
- package/dist/tools/jest.js +2 -2
- package/dist/tools/project.js +18 -2
- package/package.json +3 -3
package/CHANGELOG.md
CHANGED
package/dist/agents/prompt.js
CHANGED
|
@@ -37,7 +37,10 @@ async function addUncoveredLinePrompt(srcPath, report) {
|
|
|
37
37
|
源文件内容如下:
|
|
38
38
|
\`\`\`
|
|
39
39
|
${await (0, tools_1.readFile)(srcPath, 'utf8', true)}
|
|
40
|
-
|
|
40
|
+
\`\`\`` + (report.coverage.branches.pct > 0 ? `
|
|
41
|
+
|
|
42
|
+
查找已有测试文件增加单测代码。
|
|
43
|
+
` : '');
|
|
41
44
|
}
|
|
42
45
|
async function addUncoveredFilePrompt(total, files) {
|
|
43
46
|
const testFileNames = files.map((it) => it.filePath);
|
package/dist/agents/toolCall.js
CHANGED
|
@@ -103,7 +103,7 @@ function inferCodeTypeFromExtension(filePath) {
|
|
|
103
103
|
* @param argsObj 包含参数的对象
|
|
104
104
|
* @returns 函数执行结果
|
|
105
105
|
*/
|
|
106
|
-
async function callWithObject(name, argsObj,
|
|
106
|
+
async function callWithObject(name, argsObj, projectDir) {
|
|
107
107
|
const fn = tools[name];
|
|
108
108
|
if (!fn) {
|
|
109
109
|
throw new Error(`Tool ${name} not found`);
|
|
@@ -113,8 +113,10 @@ async function callWithObject(name, argsObj, cwd) {
|
|
|
113
113
|
// 从对象中提取参数值
|
|
114
114
|
const args = paramNames.map((name) => {
|
|
115
115
|
// 转成决定路径
|
|
116
|
-
if (name === 'filePath'
|
|
117
|
-
|
|
116
|
+
if ((name === 'filePath' || name === 'oldPath' || name === 'newPath' || name === 'directory') &&
|
|
117
|
+
projectDir &&
|
|
118
|
+
!path_1.default.isAbsolute(argsObj[name])) {
|
|
119
|
+
return path_1.default.resolve(projectDir, argsObj[name]);
|
|
118
120
|
}
|
|
119
121
|
return argsObj[name];
|
|
120
122
|
});
|
|
@@ -172,7 +174,7 @@ toolCall, root, result) {
|
|
|
172
174
|
root = root || '/';
|
|
173
175
|
const params = toolCall.params || {};
|
|
174
176
|
if (toolCall.function_name === 'readFile') {
|
|
175
|
-
const outputResult = result ? (result?.success ? ` ✅` : result?.message
|
|
177
|
+
const outputResult = result ? (result?.success ? ` ✅` : ` ❌${result?.message}`) : '';
|
|
176
178
|
const filePath = params[0] || params.filePath;
|
|
177
179
|
return `读取文件:${formatDisplayText(filePath ? (path_1.default.isAbsolute(filePath) ? path_1.default.relative(root, filePath) : filePath) : '')}${outputResult}`;
|
|
178
180
|
}
|
|
@@ -181,21 +183,24 @@ toolCall, root, result) {
|
|
|
181
183
|
toolCall.function_name === 'modifyLine' ||
|
|
182
184
|
toolCall.function_name === 'deleteLine' ||
|
|
183
185
|
toolCall.function_name === 'batchModifyLines') {
|
|
184
|
-
const outputResult = result ? (result?.success ? ` ✅` : result?.message
|
|
186
|
+
const outputResult = result ? (result?.success ? ` ✅` : ` ❌${result?.message}`) : '';
|
|
185
187
|
const filePath = params[0] || params.filePath;
|
|
186
188
|
return `修改文件:${formatDisplayText(filePath ? (path_1.default.isAbsolute(filePath) ? path_1.default.relative(root, filePath) : filePath) : '')}${outputResult}`;
|
|
187
189
|
}
|
|
188
190
|
if (toolCall.function_name === 'searchFilesByExtension') {
|
|
189
191
|
const outputResult = result
|
|
190
192
|
? result?.success
|
|
191
|
-
? ` => ${formatDisplayText(result.data
|
|
192
|
-
|
|
193
|
+
? ` => ${formatDisplayText(result.data
|
|
194
|
+
.replaceAll(root + path_1.default.sep, '')
|
|
195
|
+
.replaceAll('- ', '')
|
|
196
|
+
.replaceAll('\n', ' '))} ✅`
|
|
197
|
+
: ` ❌${result?.message}`
|
|
193
198
|
: '';
|
|
194
199
|
const searchPath = params[0] || params.directory;
|
|
195
200
|
const exts = params[1] || params.extensions || '';
|
|
196
201
|
return `检索文件:${searchPath ? (path_1.default.isAbsolute(searchPath) ? path_1.default.relative(root, searchPath) : searchPath) : ''}${exts ? '/*' : ''}${exts}${outputResult}`;
|
|
197
202
|
}
|
|
198
|
-
const outputResult = result ? (result?.success ? ` ✅` : result?.message
|
|
203
|
+
const outputResult = result ? (result?.success ? ` ✅` : ` ❌${result?.message}`) : '';
|
|
199
204
|
return toolCall.function_name + outputResult;
|
|
200
205
|
}
|
|
201
206
|
//# sourceMappingURL=toolCall.js.map
|
package/dist/tools/jest.js
CHANGED
|
@@ -231,7 +231,7 @@ async function getFailedTests(projectRoot, coverageDir = 'coverage') {
|
|
|
231
231
|
function parseLcovForUncoveredLines(lcovContent, measureType = 'branches') {
|
|
232
232
|
const uncoveredLines = {};
|
|
233
233
|
let currentFile = null;
|
|
234
|
-
const DAKey = measureType === 'branches' ? 'BRDA' :
|
|
234
|
+
const DAKey = measureType === 'branches' ? 'BRDA' : 'DA';
|
|
235
235
|
lcovContent.split('\n').forEach((line) => {
|
|
236
236
|
if (line.startsWith('SF:')) {
|
|
237
237
|
// 记录当前文件路径
|
|
@@ -243,7 +243,7 @@ function parseLcovForUncoveredLines(lcovContent, measureType = 'branches') {
|
|
|
243
243
|
// BRDA:53,0,0,8 最后是执行次数
|
|
244
244
|
const [lineNumberStr, ...executionCountStr] = line.substring(DAKey.length + 1).split(',');
|
|
245
245
|
const lineNumber = parseInt(lineNumberStr, 10);
|
|
246
|
-
const executionCount = parseInt(executionCountStr[
|
|
246
|
+
const executionCount = parseInt(executionCountStr[DAKey === 'BRDA' ? 2 : 0], 10);
|
|
247
247
|
// 如果执行次数为0,表示该行未被覆盖
|
|
248
248
|
if (executionCount === 0) {
|
|
249
249
|
uncoveredLines[currentFile].push(lineNumber);
|
package/dist/tools/project.js
CHANGED
|
@@ -56,10 +56,10 @@ async function detectProjectConfig(projectRoot, defaultConfig) {
|
|
|
56
56
|
await detectLanguages(projectRoot, config);
|
|
57
57
|
// 检测源代码目录
|
|
58
58
|
await detectSrcDir(projectRoot, config);
|
|
59
|
-
// 检测测试相关配置
|
|
60
|
-
await detectTestConfig(projectRoot, config);
|
|
61
59
|
// 检测项目类型(前端/后端/全栈)
|
|
62
60
|
await detectProjectType(projectRoot, config);
|
|
61
|
+
// 检测测试相关配置
|
|
62
|
+
await detectTestConfig(projectRoot, config);
|
|
63
63
|
// 检测框架信息
|
|
64
64
|
await detectFramework(projectRoot, config);
|
|
65
65
|
// 检测Git配置
|
|
@@ -170,6 +170,10 @@ async function detectTestConfig(projectRoot, config) {
|
|
|
170
170
|
}
|
|
171
171
|
// 检测测试目录
|
|
172
172
|
const possibleTestDirs = ['test', 'tests', '__tests__', 'spec', 'specs'];
|
|
173
|
+
if (config.srcDir) {
|
|
174
|
+
// __tests__:这是前端项目(尤其是使用 Jest 作为测试框架的 React 项目)中比较有特色的放置方式。
|
|
175
|
+
possibleTestDirs.push(path_1.default.join(config.srcDir, '__tests__'));
|
|
176
|
+
}
|
|
173
177
|
for (const dir of possibleTestDirs) {
|
|
174
178
|
const dirPath = path_1.default.join(projectRoot, dir);
|
|
175
179
|
if (await directoryExists(dirPath)) {
|
|
@@ -238,16 +242,28 @@ async function detectTestConfig(projectRoot, config) {
|
|
|
238
242
|
const extensions = new Set();
|
|
239
243
|
if (config.languages?.includes('javascript')) {
|
|
240
244
|
extensions.add('js');
|
|
245
|
+
if (config.projectType === 'frontend') {
|
|
246
|
+
extensions.add('jsx');
|
|
247
|
+
}
|
|
241
248
|
}
|
|
242
249
|
if (config.languages?.includes('typescript')) {
|
|
243
250
|
extensions.add('ts');
|
|
251
|
+
if (config.projectType === 'frontend') {
|
|
252
|
+
extensions.add('tsx');
|
|
253
|
+
}
|
|
244
254
|
}
|
|
245
255
|
if (config.languages?.includes('coffeescript')) {
|
|
246
256
|
extensions.add('coffee');
|
|
257
|
+
if (config.projectType === 'frontend') {
|
|
258
|
+
extensions.add('cjsx');
|
|
259
|
+
}
|
|
247
260
|
}
|
|
248
261
|
// 默认为js(如果没有检测到语言)
|
|
249
262
|
if (extensions.size === 0) {
|
|
250
263
|
extensions.add('js');
|
|
264
|
+
if (config.projectType === 'frontend') {
|
|
265
|
+
extensions.add('jsx');
|
|
266
|
+
}
|
|
251
267
|
}
|
|
252
268
|
// 生成基础模式集合
|
|
253
269
|
const basePatterns = new Set();
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ai-worktool",
|
|
3
3
|
"displayName": "吃豆豆:单测智能体",
|
|
4
|
-
"version": "1.0.
|
|
4
|
+
"version": "1.0.70",
|
|
5
5
|
"description": "单元测试智能体,帮你开发单元测试用例代码直到100%单测覆盖通过。",
|
|
6
6
|
"author": "jianguoke.cn",
|
|
7
7
|
"license": "MIT",
|
|
@@ -28,11 +28,11 @@
|
|
|
28
28
|
"createup": "node ./uposs.js create-local-folder",
|
|
29
29
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
|
|
30
30
|
"puball": "yarn ver && yarn exepack && yarn vspack && yarn pubvs && yarn pubovsx && yarn puboss && yarn pubnpm",
|
|
31
|
-
"exepack": "yarn createup && cross-env PKG_CACHE_PATH=./binaries pkg -o packages/aicoder-1.0.
|
|
31
|
+
"exepack": "yarn createup && cross-env PKG_CACHE_PATH=./binaries pkg -o packages/aicoder-1.0.70 . && yarn upicon",
|
|
32
32
|
"pubvs": "yarn remove-deps && yarn changelog && vsce publish --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
33
33
|
"pubovsx": "yarn remove-deps && ovsx publish -p 47621ff6-be56-4814-865e-d2a8e8a76f86 --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
34
34
|
"patch": "yarn remove-deps && vsce publish patch --yarn && yarn restore-deps",
|
|
35
|
-
"vspack": "yarn createup && yarn remove-deps && vsce package -o packages/aicoder-1.0.
|
|
35
|
+
"vspack": "yarn createup && yarn remove-deps && vsce package -o packages/aicoder-1.0.70.vsix --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
36
36
|
"puboss": "node ./uposs.js upload",
|
|
37
37
|
"pubnpm": "npm publish --registry=https://registry.npmjs.org",
|
|
38
38
|
"prepare": "husky"
|