ai-worktool 1.0.12 → 1.0.13
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 +2 -1
- package/dist/program.js +40 -1
- package/dist/tools/git.js +2 -2
- package/dist/tools/index.js +1 -1
- package/dist/tools/project.js +19 -10
- package/dist/user.js +24 -5
- package/package.json +2 -1
package/CHANGELOG.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
## 1.0.
|
1
|
+
## 1.0.13 (2025-08-04)
|
2
2
|
|
3
3
|
|
4
4
|
### Bug Fixes
|
@@ -152,6 +152,7 @@
|
|
152
152
|
* **toolbox:** 重构并增强项目配置检测功能 ([6cc4e33](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/6cc4e33a58c7ebb622d27bc643c1e65d1e8af577))
|
153
153
|
* **tools:** 为简咕客插件生成 zod 工具 ([42dfcd9](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/42dfcd9eb337603ecb0c5fa381ad89784345c9dc))
|
154
154
|
* **tools:** 优化工具插件支持连续多行操作并添加新功能 ([734ca52](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/734ca5287785d84be0f8fc98b074476a3cc643f2))
|
155
|
+
* **user:** 实现登录、登出功能并优化 token 存储 ([1514408](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/151440887e90d90d0522303009f6940f0507258e))
|
155
156
|
* **user:** 实现登录取消功能并优化登录流程 ([50d124e](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/50d124e720c778e537488ca436855af21dcbcdeb))
|
156
157
|
* **user:** 为认证回调页面添加立即关闭按钮 ([4328b48](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/4328b48e06002fa9d70427b21992f1022ffa73a0))
|
157
158
|
* **views:** 优化代码覆盖率显示 ([ef98b11](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/ef98b115e57650483fae65ddec5ded085839ddd0))
|
package/dist/program.js
CHANGED
@@ -6,15 +6,54 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
6
6
|
Object.defineProperty(exports, "__esModule", { value: true });
|
7
7
|
const commander_1 = require("commander");
|
8
8
|
const path_1 = __importDefault(require("path"));
|
9
|
+
const promises_1 = __importDefault(require("fs/promises"));
|
10
|
+
const os_1 = __importDefault(require("os"));
|
9
11
|
const testAgent_1 = require("./testAgent");
|
10
12
|
const tools_1 = require("./tools");
|
11
13
|
const view_1 = require("./view");
|
14
|
+
const user_1 = require("./user");
|
12
15
|
// import { showCoverageView } from './view';
|
13
16
|
const program = new commander_1.Command();
|
14
17
|
program.name('testAgent').description('吃豆豆:单测智能体').version('1.0.1');
|
15
18
|
// 屏蔽调试日志
|
16
19
|
const logHandler = console.log;
|
17
20
|
console.log = () => { };
|
21
|
+
const tokenFile = path_1.default.join(os_1.default.homedir(), '.aiworktools');
|
22
|
+
// token存储在系统用户文件夹的.ai-worktools
|
23
|
+
(0, user_1.setTokenStorage)({
|
24
|
+
get: async () => {
|
25
|
+
let exists = false;
|
26
|
+
try {
|
27
|
+
await promises_1.default.access(tokenFile);
|
28
|
+
exists = true;
|
29
|
+
}
|
30
|
+
catch (err) {
|
31
|
+
return false;
|
32
|
+
}
|
33
|
+
if (exists) {
|
34
|
+
return JSON.parse(await promises_1.default.readFile(tokenFile, 'utf-8')).token;
|
35
|
+
}
|
36
|
+
return null;
|
37
|
+
},
|
38
|
+
set: async (token) => {
|
39
|
+
await promises_1.default.writeFile(tokenFile, JSON.stringify({ token }), 'utf-8');
|
40
|
+
},
|
41
|
+
clear: async () => {
|
42
|
+
await promises_1.default.unlink(tokenFile);
|
43
|
+
}
|
44
|
+
});
|
45
|
+
program
|
46
|
+
.command('login')
|
47
|
+
.description('登录')
|
48
|
+
.action(async () => {
|
49
|
+
await (0, user_1.login)('ai-worktools-cli');
|
50
|
+
});
|
51
|
+
program
|
52
|
+
.command('logout')
|
53
|
+
.description('登出')
|
54
|
+
.action(async () => {
|
55
|
+
await (0, user_1.logout)();
|
56
|
+
});
|
18
57
|
program
|
19
58
|
.command('start [projectRoot]')
|
20
59
|
.description('启动单测智能体,根据源代码文件开始补全单测代码,直到覆盖率100%')
|
@@ -27,7 +66,7 @@ program
|
|
27
66
|
.option('--fullCoverageEnd <boolean>', '是否在达到100%覆盖率后结束', (txt) => txt === 'true', true)
|
28
67
|
.action(async (projectRoot, options) => {
|
29
68
|
let projectConfig;
|
30
|
-
(0, testAgent_1.startTestAgent)({
|
69
|
+
await (0, testAgent_1.startTestAgent)({
|
31
70
|
...options,
|
32
71
|
projectRoot: projectRoot || options.projectRoot,
|
33
72
|
onReady: async (project) => {
|
package/dist/tools/git.js
CHANGED
@@ -73,7 +73,7 @@ async function commit(repoPath, message, files) {
|
|
73
73
|
const git = createGitInstance(repoPath);
|
74
74
|
try {
|
75
75
|
const result = files ? await git.commit(message, files) : await git.commit(message);
|
76
|
-
console.log(`提交成功: ${result
|
76
|
+
console.log(`提交成功: ${result?.summary}`);
|
77
77
|
}
|
78
78
|
catch (error) {
|
79
79
|
console.error(`提交失败: ${error}`);
|
@@ -91,7 +91,7 @@ async function pull(repoPath, remote = 'origin', branch) {
|
|
91
91
|
try {
|
92
92
|
const currentBranch = branch || (await git.branchLocal()).current;
|
93
93
|
const result = await git.pull(remote, currentBranch);
|
94
|
-
console.log(`拉取成功: ${result
|
94
|
+
console.log(`拉取成功: ${result?.summary}`);
|
95
95
|
}
|
96
96
|
catch (error) {
|
97
97
|
console.error(`拉取失败: ${error}`);
|
package/dist/tools/index.js
CHANGED
@@ -54,7 +54,7 @@ async function wait(timerout = 1000) {
|
|
54
54
|
}, timerout);
|
55
55
|
});
|
56
56
|
}
|
57
|
-
function runTests(projectRoot, testFramework, coverageDir, configPath) {
|
57
|
+
async function runTests(projectRoot, testFramework, coverageDir, configPath) {
|
58
58
|
if (testFramework === 'jest') {
|
59
59
|
return (0, jest_1.runJestTests)(projectRoot, coverageDir, configPath);
|
60
60
|
}
|
package/dist/tools/project.js
CHANGED
@@ -4,6 +4,15 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
4
4
|
};
|
5
5
|
Object.defineProperty(exports, "__esModule", { value: true });
|
6
6
|
exports.detectProjectConfig = detectProjectConfig;
|
7
|
+
exports.checkProjectInstalled = checkProjectInstalled;
|
8
|
+
exports.detectPackageManager = detectPackageManager;
|
9
|
+
exports.detectLanguages = detectLanguages;
|
10
|
+
exports.detectSrcDir = detectSrcDir;
|
11
|
+
exports.detectTestConfig = detectTestConfig;
|
12
|
+
exports.detectExistingTestPatterns = detectExistingTestPatterns;
|
13
|
+
exports.getDependencies = getDependencies;
|
14
|
+
exports.detectProjectType = detectProjectType;
|
15
|
+
exports.detectFramework = detectFramework;
|
7
16
|
const promises_1 = __importDefault(require("fs/promises"));
|
8
17
|
const path_1 = __importDefault(require("path"));
|
9
18
|
/**
|
@@ -207,13 +216,13 @@ async function detectTestConfig(projectRoot, config) {
|
|
207
216
|
];
|
208
217
|
// 根据项目语言生成对应扩展名的模式
|
209
218
|
const extensions = new Set();
|
210
|
-
if (config.languages
|
219
|
+
if (config.languages?.includes('javascript')) {
|
211
220
|
extensions.add('js');
|
212
221
|
}
|
213
|
-
if (config.languages
|
222
|
+
if (config.languages?.includes('typescript')) {
|
214
223
|
extensions.add('ts');
|
215
224
|
}
|
216
|
-
if (config.languages
|
225
|
+
if (config.languages?.includes('coffeescript')) {
|
217
226
|
extensions.add('coffee');
|
218
227
|
}
|
219
228
|
// 默认为js(如果没有检测到语言)
|
@@ -404,11 +413,11 @@ async function calculateScore(projectRoot, type) {
|
|
404
413
|
}
|
405
414
|
});
|
406
415
|
// 检查配置文件匹配(并行处理)
|
407
|
-
const configFileChecks = features.configFiles.map((file) => fileExists(path_1.default.join(
|
416
|
+
const configFileChecks = features.configFiles.map((file) => fileExists(path_1.default.join(projectRoot, file)));
|
408
417
|
const configFileResults = await Promise.all(configFileChecks);
|
409
418
|
score += configFileResults.filter(Boolean).length * 2; // 配置文件权重中等
|
410
419
|
// 检查目录结构匹配(并行处理)
|
411
|
-
const directoryChecks = features.directories.map((dir) => directoryExists(path_1.default.join(
|
420
|
+
const directoryChecks = features.directories.map((dir) => directoryExists(path_1.default.join(projectRoot, dir)));
|
412
421
|
const directoryResults = await Promise.all(directoryChecks);
|
413
422
|
score += directoryResults.filter(Boolean).length * 1; // 目录权重较低
|
414
423
|
return score;
|
@@ -430,11 +439,6 @@ async function detectProjectType(projectRoot, config) {
|
|
430
439
|
backend: backendScore,
|
431
440
|
cli: cliScore
|
432
441
|
};
|
433
|
-
// 判断是否为全栈项目
|
434
|
-
const isFullstack = frontendScore > 0 && backendScore > 0 && Math.abs(frontendScore - backendScore) < frontendScore * 0.5;
|
435
|
-
if (isFullstack) {
|
436
|
-
config.projectType = 'fullstack';
|
437
|
-
}
|
438
442
|
// 确定最高分数的项目类型
|
439
443
|
const maxScore = Math.max(frontendScore, backendScore, cliScore);
|
440
444
|
if (maxScore === 0) {
|
@@ -449,6 +453,11 @@ async function detectProjectType(projectRoot, config) {
|
|
449
453
|
else {
|
450
454
|
config.projectType = 'cli';
|
451
455
|
}
|
456
|
+
// 判断是否为全栈项目
|
457
|
+
const isFullstack = frontendScore > 0 && backendScore > 0 && Math.abs(frontendScore - backendScore) < frontendScore * 0.5;
|
458
|
+
if (isFullstack) {
|
459
|
+
config.projectType = 'fullstack';
|
460
|
+
}
|
452
461
|
}
|
453
462
|
/**
|
454
463
|
* 检测框架信息
|
package/dist/user.js
CHANGED
@@ -56,8 +56,25 @@ const util_1 = __importDefault(require("util"));
|
|
56
56
|
const child_process_1 = require("child_process");
|
57
57
|
// 转换exec为Promise形式,便于async/await使用
|
58
58
|
const execAsync = util_1.default.promisify(child_process_1.exec);
|
59
|
-
let tokenStorage
|
60
|
-
|
59
|
+
let tokenStorage = {
|
60
|
+
get: async () => {
|
61
|
+
return localStorage.getItem('token');
|
62
|
+
},
|
63
|
+
set: async (token) => {
|
64
|
+
localStorage.setItem('token', token);
|
65
|
+
},
|
66
|
+
clear: async () => {
|
67
|
+
localStorage.removeItem('token');
|
68
|
+
}
|
69
|
+
};
|
70
|
+
let environment = {
|
71
|
+
showInfoMessage: async (message) => {
|
72
|
+
console.log(message);
|
73
|
+
},
|
74
|
+
showErrorMessage: async (message) => {
|
75
|
+
console.error(message);
|
76
|
+
}
|
77
|
+
};
|
61
78
|
function setEnvironment(env) {
|
62
79
|
environment = env;
|
63
80
|
}
|
@@ -335,6 +352,7 @@ async function openExternalUrl(url) {
|
|
335
352
|
return false;
|
336
353
|
}
|
337
354
|
}
|
355
|
+
const AUTH_SERVER_URL = 'https://login.jianguoke.cn/login';
|
338
356
|
/**
|
339
357
|
* 执行登录流程
|
340
358
|
* @param env 环境接口
|
@@ -343,7 +361,8 @@ async function openExternalUrl(url) {
|
|
343
361
|
* @param clientId 客户端ID
|
344
362
|
* @returns 登录成功后的token
|
345
363
|
*/
|
346
|
-
async function login(
|
364
|
+
async function login(clientId) {
|
365
|
+
const authServerUrl = AUTH_SERVER_URL;
|
347
366
|
const env = getEnvironment();
|
348
367
|
const tokenStorage = getTokenStorage();
|
349
368
|
const state = generateState();
|
@@ -407,8 +426,8 @@ function isLoggedIn() {
|
|
407
426
|
}
|
408
427
|
return true;
|
409
428
|
}
|
410
|
-
function getUserData() {
|
411
|
-
const token = getTokenStorage().get();
|
429
|
+
async function getUserData() {
|
430
|
+
const token = await getTokenStorage().get();
|
412
431
|
if (!token) {
|
413
432
|
return null;
|
414
433
|
}
|
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.13",
|
5
5
|
"description": "单元测试智能体,帮你开发单元测试用例代码直到100%单测覆盖通过。",
|
6
6
|
"author": "jianguoke.cn",
|
7
7
|
"license": "MIT",
|
@@ -13,6 +13,7 @@
|
|
13
13
|
"watch": "tsc -w",
|
14
14
|
"build": "tsc",
|
15
15
|
"test": "jest test/tools",
|
16
|
+
"coverage": "jest --coverage test/tools",
|
16
17
|
"plugin": "ts-node ./tools.ts && dify plugin package plugins/dify-plugin",
|
17
18
|
"package": "cross-env PKG_CACHE_PATH=./binaries pkg . --targets node20-win-x64 --out-path aicoder ",
|
18
19
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
|