ai-worktool 1.0.65 → 1.0.66
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 +3 -1
- package/dist/agents/jianguoke.js +2 -7
- package/dist/agents/toolCall.js +1 -1
- package/dist/program.js +21 -21
- package/dist/testAgent.js +16 -13
- package/dist/tools/file.js +24 -1
- package/dist/view.js +2 -1
- package/package.json +9 -3
- package/dist/loging.js +0 -110
- package/dist/statusBar.js +0 -121
package/CHANGELOG.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
## 1.0.
|
|
1
|
+
## 1.0.66 (2025-08-17)
|
|
2
2
|
|
|
3
3
|
|
|
4
4
|
### Bug Fixes
|
|
@@ -106,8 +106,10 @@
|
|
|
106
106
|
* **dify-plugin:** 新增重命名文件或目录的功能 ([9bb6961](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/9bb69613a28aba6859f72b14b2aa1a586ac9ca70))
|
|
107
107
|
* **extension:** 重构 Webview 并添加覆盖率报告功能 ([fd8a62b](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/fd8a62b79aff4c03af8b56779d607f01d65c175a))
|
|
108
108
|
* **jianguoke:** 优化工具调用信息格式化及消息 ID 生成 ([1b240e7](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/1b240e7fbcabb2112789c116b7f483308c184fce))
|
|
109
|
+
* **logger:** 实现日志记录功能并优化工具调用处理 ([84bbd9b](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/84bbd9be8338e80779eb9159ba62ffb9c59cdbd7))
|
|
109
110
|
* **log:** 增加日志容器拖动调整功能 ([cfdaf9d](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/cfdaf9d7bec56687a2d49ca92785463dc6713a77))
|
|
110
111
|
* **package:** 添加阿里云 OSS 发布脚本并更新版本号 ([572ef25](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/572ef25f36c949672c4d1c062015f970c9862e69))
|
|
112
|
+
* **package:** 添加项目关键词 ([d4707a1](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/d4707a12adbd510088d3fa7fdae78e8b6d858eb6))
|
|
111
113
|
* **plugin:** 更新插件版本和功能描述 ([f3773d6](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/f3773d675fcb274080339cd0274a1a7aff8415a9))
|
|
112
114
|
* **program:** 增加代码覆盖率报告展示功能 ([60da9b5](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/60da9b59e4b913695daa8697dd9aeec16cf78a5f))
|
|
113
115
|
* **program:** 增加代码覆盖率报告展示功能 ([f693e27](https://codeup.aliyun.com/666cf9ed29ecbe23053513a3/JianGuoKe/ai-worktools/commits/f693e272ef0fe7e58083d2589339af17e45cff95))
|
package/dist/agents/jianguoke.js
CHANGED
|
@@ -122,13 +122,8 @@ async function startAgent(name, question, vars, withConversation, ctrl, mode, on
|
|
|
122
122
|
lastMsgNo = data.no;
|
|
123
123
|
msg = '';
|
|
124
124
|
}
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
msg = data.content;
|
|
130
|
-
}
|
|
131
|
-
await onMessage?.(msg, 'msg-' + data.id + data.no);
|
|
125
|
+
msg += data.content;
|
|
126
|
+
await onMessage?.(mode === 'full' ? msg : data.content, 'msg-' + data.id + data.no);
|
|
132
127
|
}
|
|
133
128
|
if (ev?.event === 'TOOL' && lastToolId !== 'tool-' + data.id + data.no) {
|
|
134
129
|
lastToolId = 'tool-' + data.id + data.no;
|
package/dist/agents/toolCall.js
CHANGED
|
@@ -119,7 +119,7 @@ async function callWithObject(name, argsObj, cwd) {
|
|
|
119
119
|
return argsObj[name];
|
|
120
120
|
});
|
|
121
121
|
// 调用函数
|
|
122
|
-
let data =
|
|
122
|
+
let data = await fn(...args);
|
|
123
123
|
if (name === 'readFile') {
|
|
124
124
|
data = `\n\`\`\`${inferCodeTypeFromExtension(argsObj.filePath)}\n${data}\n\`\`\``;
|
|
125
125
|
}
|
package/dist/program.js
CHANGED
|
@@ -15,10 +15,23 @@ const user_1 = require("./user");
|
|
|
15
15
|
const program = new commander_1.Command();
|
|
16
16
|
program.name('testAgent').description('吃豆豆:单测智能体').version('1.0.1');
|
|
17
17
|
// 屏蔽调试日志
|
|
18
|
-
|
|
18
|
+
let lastLineNo;
|
|
19
|
+
const outputLine = (message, id) => {
|
|
20
|
+
if (id && lastLineNo !== id) {
|
|
21
|
+
process.stdout.write('\n');
|
|
22
|
+
}
|
|
23
|
+
process.stdout.write(message);
|
|
24
|
+
if (!id) {
|
|
25
|
+
process.stdout.write('\n');
|
|
26
|
+
}
|
|
27
|
+
lastLineNo = id;
|
|
28
|
+
};
|
|
19
29
|
if (process.env.NODE_ENV !== 'test') {
|
|
20
30
|
console.log = () => { };
|
|
21
31
|
}
|
|
32
|
+
else {
|
|
33
|
+
console.log = (...txt) => outputLine(txt.join(' '));
|
|
34
|
+
}
|
|
22
35
|
const tokenFile = path_1.default.join(os_1.default.homedir(), '.aiworktools');
|
|
23
36
|
// token存储在系统用户文件夹的.ai-worktools
|
|
24
37
|
(0, user_1.setTokenStorage)({
|
|
@@ -48,12 +61,12 @@ program
|
|
|
48
61
|
.description('登录')
|
|
49
62
|
.action(async () => {
|
|
50
63
|
try {
|
|
51
|
-
|
|
64
|
+
outputLine(`正在打开浏览器进行登录...`);
|
|
52
65
|
await (0, user_1.login)('ai-worktools-cli');
|
|
53
|
-
|
|
66
|
+
outputLine('登录成功!');
|
|
54
67
|
}
|
|
55
68
|
catch (err) {
|
|
56
|
-
|
|
69
|
+
outputLine('登录失败', err.message);
|
|
57
70
|
}
|
|
58
71
|
});
|
|
59
72
|
program
|
|
@@ -61,7 +74,7 @@ program
|
|
|
61
74
|
.description('登出')
|
|
62
75
|
.action(async () => {
|
|
63
76
|
await (0, user_1.logout)();
|
|
64
|
-
|
|
77
|
+
outputLine('已成功退出');
|
|
65
78
|
});
|
|
66
79
|
program
|
|
67
80
|
.command('start [projectRoot]')
|
|
@@ -87,26 +100,13 @@ program
|
|
|
87
100
|
onReady: async (project) => {
|
|
88
101
|
projectConfig = project;
|
|
89
102
|
},
|
|
90
|
-
onMessage:
|
|
91
|
-
logHandler(message);
|
|
92
|
-
if (message.includes('当前代码总覆盖率')) {
|
|
93
|
-
const task = (0, view_1.loadAndDisplayCoverage)(path_1.default.join(projectConfig.projectRoot, projectConfig.coverageDir, view_1.COVERAGE_FILE_PATH), 0);
|
|
94
|
-
tasks.push(task);
|
|
95
|
-
task
|
|
96
|
-
.then(() => {
|
|
97
|
-
tasks.splice(tasks.indexOf(task), 1);
|
|
98
|
-
})
|
|
99
|
-
.catch(() => {
|
|
100
|
-
tasks.splice(tasks.indexOf(task), 1);
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
103
|
+
onMessage: outputLine
|
|
104
104
|
});
|
|
105
105
|
await Promise.all(tasks);
|
|
106
106
|
if (result?.name === '') {
|
|
107
107
|
if (result?.name === 'ExpiredException') {
|
|
108
|
-
|
|
109
|
-
|
|
108
|
+
outputLine('您的Tokens已用完,请充值。执行下面命令打开使用面板:');
|
|
109
|
+
outputLine('testAgent usage');
|
|
110
110
|
}
|
|
111
111
|
}
|
|
112
112
|
});
|
package/dist/testAgent.js
CHANGED
|
@@ -9,9 +9,12 @@ const agents_1 = require("./agents");
|
|
|
9
9
|
const tools_1 = require("./tools");
|
|
10
10
|
async function startTestAgent(options) {
|
|
11
11
|
const ctrl = options.controller;
|
|
12
|
-
|
|
12
|
+
let no = 0;
|
|
13
|
+
const output = (txt, id) => {
|
|
14
|
+
options.onMessage?.(txt, id || '#' + ++no);
|
|
15
|
+
};
|
|
13
16
|
let isErrorEnd;
|
|
14
|
-
|
|
17
|
+
output(`开始干活... 😎`);
|
|
15
18
|
console.log(options.projectRoot);
|
|
16
19
|
try {
|
|
17
20
|
isErrorEnd = false;
|
|
@@ -19,7 +22,7 @@ async function startTestAgent(options) {
|
|
|
19
22
|
// 1、检查当前项目单元测试工具是否安装好,否则安装测试工具搭建测试环境
|
|
20
23
|
const projectConfig = await (0, tools_1.detectProjectConfig)(options.projectRoot, options);
|
|
21
24
|
if (!projectConfig.isInstalled) {
|
|
22
|
-
|
|
25
|
+
output('项目初始化...');
|
|
23
26
|
await (0, tools_1.initProject)(options.projectRoot, projectConfig.packageManager);
|
|
24
27
|
}
|
|
25
28
|
if (options.setupEnv !== false) {
|
|
@@ -34,7 +37,7 @@ async function startTestAgent(options) {
|
|
|
34
37
|
toolCalls = [];
|
|
35
38
|
}
|
|
36
39
|
// 2、先执行单测并生成单测覆盖报告
|
|
37
|
-
|
|
40
|
+
output('开始检查测试覆盖率...');
|
|
38
41
|
const result = await (0, tools_1.runTests)(projectConfig.projectRoot, projectConfig.testFramework, projectConfig.coverageDir, projectConfig.testConfigFile);
|
|
39
42
|
if (ctrl?.signal.aborted) {
|
|
40
43
|
break;
|
|
@@ -43,13 +46,13 @@ async function startTestAgent(options) {
|
|
|
43
46
|
// 上一次执行必须有写入类操作,否则不会有新的单测覆盖率变化
|
|
44
47
|
if (lastTestResult?.stderr === result.stderr &&
|
|
45
48
|
toolCalls.every((toolCall) => !tools_1.modifyTools.includes(toolCall.functionName))) {
|
|
46
|
-
|
|
49
|
+
output('没有新的代码修改,等待中...');
|
|
47
50
|
await (0, tools_1.wait)(options.idleTimeout || 5000);
|
|
48
51
|
continue;
|
|
49
52
|
}
|
|
50
53
|
lastTestResult = result;
|
|
51
54
|
// 单测执行失败,比如代码编译不通过
|
|
52
|
-
|
|
55
|
+
output('单测执行失败,开始修复...');
|
|
53
56
|
await (0, agents_1.startAgent)(options.platform, 'fixconfig', (0, agents_1.fixErrorPrompt)(result.stderr), projectConfig, options.withConversation, ctrl, options.mode, options.onMessage, async (tool) => {
|
|
54
57
|
toolCalls.push(tool);
|
|
55
58
|
});
|
|
@@ -69,13 +72,13 @@ async function startTestAgent(options) {
|
|
|
69
72
|
lastFailedTest.testFilePath === failedTest.testFilePath &&
|
|
70
73
|
lastFailedTest.testName === failedTest.testName &&
|
|
71
74
|
toolCalls.every((toolCall) => !tools_1.modifyTools.includes(toolCall.functionName))) {
|
|
72
|
-
|
|
75
|
+
output('没有新的单测失败,等待中...');
|
|
73
76
|
await (0, tools_1.wait)(options.idleTimeout || 5000);
|
|
74
77
|
continue;
|
|
75
78
|
}
|
|
76
79
|
lastFailedTest = failedTest;
|
|
77
80
|
// 不能并行修复,改完行号都会变,所以每次修复完需要重新执行单测
|
|
78
|
-
|
|
81
|
+
output(`发现有失败的单测${path_1.default.basename(failedTest.testFilePath)},开始修复...`);
|
|
79
82
|
await (0, agents_1.startAgent)(options.platform,
|
|
80
83
|
// 没有testName说明是修复单测代码本身问题
|
|
81
84
|
failedTest.testName ? 'fixbug' : 'fixconfig', await (0, agents_1.fixCodePrompt)(failedTest), projectConfig, options.withConversation, ctrl, options.mode, options.onMessage, async (tool) => {
|
|
@@ -94,12 +97,12 @@ async function startTestAgent(options) {
|
|
|
94
97
|
if (ctrl?.signal.aborted) {
|
|
95
98
|
break;
|
|
96
99
|
}
|
|
97
|
-
|
|
100
|
+
output(`当前代码总覆盖率为${parseFloat(total[options.measureType || 'branches'].pct.toString()) || 0}%`);
|
|
98
101
|
const finished = total[options.measureType || 'branches'].pct >= 100;
|
|
99
102
|
if (!finished) {
|
|
100
103
|
if (files.length) {
|
|
101
104
|
for (const uncoveredLineFile of files.sort((a, b) => a.lines.coverage.branches.pct - b.lines.coverage.branches.pct)) {
|
|
102
|
-
|
|
105
|
+
output(`发现有未覆盖行,开始补充...`, uncoveredLineFile.filePath);
|
|
103
106
|
await (0, agents_1.startAgent)(options.platform, 'addtest', await (0, agents_1.addUncoveredLinePrompt)(uncoveredLineFile.filePath, uncoveredLineFile.lines), projectConfig, options.withConversation, ctrl, options.mode, options.onMessage, async (tool) => {
|
|
104
107
|
toolCalls.push(tool);
|
|
105
108
|
});
|
|
@@ -110,7 +113,7 @@ async function startTestAgent(options) {
|
|
|
110
113
|
}
|
|
111
114
|
else {
|
|
112
115
|
// 如果没有测试文件,则尝试修复代码
|
|
113
|
-
|
|
116
|
+
output(`发现有未覆盖文件,开始补充...`);
|
|
114
117
|
await (0, agents_1.startAgent)(options.platform, 'addtest', await (0, agents_1.addUncoveredFilePrompt)(total, files), projectConfig, options.withConversation, ctrl, options.mode, options.onMessage, async (tool) => {
|
|
115
118
|
toolCalls.push(tool);
|
|
116
119
|
});
|
|
@@ -134,10 +137,10 @@ async function startTestAgent(options) {
|
|
|
134
137
|
else {
|
|
135
138
|
isErrorEnd = err;
|
|
136
139
|
console.error(err);
|
|
137
|
-
|
|
140
|
+
output('发生错误, ' + err.message);
|
|
138
141
|
}
|
|
139
142
|
}
|
|
140
|
-
|
|
143
|
+
output(isErrorEnd ? '被下班~ 👻' : '快乐的~下班下班 👋');
|
|
141
144
|
return isErrorEnd;
|
|
142
145
|
}
|
|
143
146
|
//# sourceMappingURL=testAgent.js.map
|
package/dist/tools/file.js
CHANGED
|
@@ -50,6 +50,16 @@ exports.batchModifyLines = batchModifyLines;
|
|
|
50
50
|
exports.deleteFolder = deleteFolder;
|
|
51
51
|
const fs = __importStar(require("fs/promises"));
|
|
52
52
|
const path_1 = __importDefault(require("path"));
|
|
53
|
+
const diff_1 = require("diff");
|
|
54
|
+
const cli_color_1 = __importDefault(require("cli-color"));
|
|
55
|
+
// 颜色配置
|
|
56
|
+
const colors = {
|
|
57
|
+
added: cli_color_1.default.green, // 新增内容 - 绿色
|
|
58
|
+
removed: cli_color_1.default.red, // 删除内容 - 红色
|
|
59
|
+
unchanged: cli_color_1.default.white, // 未变更内容 - 白色
|
|
60
|
+
header: cli_color_1.default.cyan.bold, // 标题 - 青色加粗
|
|
61
|
+
timestamp: cli_color_1.default.yellow // 时间戳 - 黄色
|
|
62
|
+
};
|
|
53
63
|
/**
|
|
54
64
|
* 解析操作字符串为内部操作对象
|
|
55
65
|
* @param operations 操作字符串,格式:操作类型:行号范围:内容(仅增/改需要),多操作用逗号分隔
|
|
@@ -286,7 +296,20 @@ async function writeFile(filePath, content, encoding = 'utf8', overwrite = true)
|
|
|
286
296
|
catch {
|
|
287
297
|
await fs.mkdir(dir, { recursive: true });
|
|
288
298
|
}
|
|
289
|
-
|
|
299
|
+
const data = content.replace(/\r\n/g, '\n');
|
|
300
|
+
const old = process.env.NODE_ENV === 'test' ? await fs.readFile(filePath, encoding) : '';
|
|
301
|
+
await fs.writeFile(filePath, data, encoding);
|
|
302
|
+
if (process.env.NODE_ENV === 'test') {
|
|
303
|
+
// 比较文件差异
|
|
304
|
+
let logContent = '';
|
|
305
|
+
const diff = (0, diff_1.diffLines)(old, data);
|
|
306
|
+
diff.forEach((part) => {
|
|
307
|
+
const prefix = part.added ? '+' : part.removed ? '-' : ' ';
|
|
308
|
+
const colorFn = part.added ? colors.added : part.removed ? colors.removed : colors.unchanged;
|
|
309
|
+
logContent += colorFn(`${prefix} ${part.value}`);
|
|
310
|
+
});
|
|
311
|
+
console.log(logContent);
|
|
312
|
+
}
|
|
290
313
|
}
|
|
291
314
|
catch (error) {
|
|
292
315
|
throw new Error(`写入文件失败: ${error.message}`);
|
package/dist/view.js
CHANGED
|
@@ -128,8 +128,9 @@ function generateTableData(coverage) {
|
|
|
128
128
|
}
|
|
129
129
|
// 格式化百分比并应用颜色
|
|
130
130
|
function formatPercentage(pct) {
|
|
131
|
-
if (pct === 'Unknown')
|
|
131
|
+
if (pct === 'Unknown') {
|
|
132
132
|
return cli_color_1.default.italic('Unknown');
|
|
133
|
+
}
|
|
133
134
|
let formatted = pct.toFixed(2) + '%';
|
|
134
135
|
// 根据覆盖率设置颜色
|
|
135
136
|
if (pct < 50) {
|
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.66",
|
|
5
5
|
"description": "单元测试智能体,帮你开发单元测试用例代码直到100%单测覆盖通过。",
|
|
6
6
|
"author": "jianguoke.cn",
|
|
7
7
|
"license": "MIT",
|
|
@@ -9,6 +9,11 @@
|
|
|
9
9
|
"bin": {
|
|
10
10
|
"testAgent": "dist/cli.js"
|
|
11
11
|
},
|
|
12
|
+
"keywords": [
|
|
13
|
+
"单元测试智能体",
|
|
14
|
+
"AI",
|
|
15
|
+
"CLI"
|
|
16
|
+
],
|
|
12
17
|
"scripts": {
|
|
13
18
|
"build": "tsc",
|
|
14
19
|
"watch": "tsc -w",
|
|
@@ -23,11 +28,11 @@
|
|
|
23
28
|
"createup": "node ./uposs.js create-local-folder",
|
|
24
29
|
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
|
|
25
30
|
"puball": "yarn ver && yarn exepack && yarn vspack && yarn pubvs && yarn pubovsx && yarn puboss && yarn pubnpm",
|
|
26
|
-
"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.66 . && yarn upicon",
|
|
27
32
|
"pubvs": "yarn remove-deps && yarn changelog && vsce publish --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
28
33
|
"pubovsx": "yarn remove-deps && ovsx publish -p 47621ff6-be56-4814-865e-d2a8e8a76f86 --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
29
34
|
"patch": "yarn remove-deps && vsce publish patch --yarn && yarn restore-deps",
|
|
30
|
-
"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.66.vsix --yarn --baseContentUrl https://aicoder.jianguoke.cn/assets && yarn restore-deps",
|
|
31
36
|
"puboss": "node ./uposs.js upload",
|
|
32
37
|
"pubnpm": "npm publish --registry=https://registry.npmjs.org",
|
|
33
38
|
"prepare": "husky"
|
|
@@ -255,6 +260,7 @@
|
|
|
255
260
|
}
|
|
256
261
|
},
|
|
257
262
|
"dependencies": {
|
|
263
|
+
"diff": "^8.0.2",
|
|
258
264
|
"fetch-sse": "^1.1.2",
|
|
259
265
|
"jsonwebtoken": "^9.0.2",
|
|
260
266
|
"simple-git": "^3.28.0",
|
package/dist/loging.js
DELETED
|
@@ -1,110 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.LogLevel = void 0;
|
|
4
|
-
exports.showLogs = showLogs;
|
|
5
|
-
exports.setSpy = setSpy;
|
|
6
|
-
exports.addLog = addLog;
|
|
7
|
-
exports.updateLog = updateLog;
|
|
8
|
-
exports.applyAspectToModule = applyAspectToModule;
|
|
9
|
-
exports.spyConsole = spyConsole;
|
|
10
|
-
const logs = [];
|
|
11
|
-
const output = console.log;
|
|
12
|
-
/**
|
|
13
|
-
* 日志级别枚举
|
|
14
|
-
*/
|
|
15
|
-
var LogLevel;
|
|
16
|
-
(function (LogLevel) {
|
|
17
|
-
LogLevel["DEBUG"] = "debug";
|
|
18
|
-
LogLevel["INFO"] = "info";
|
|
19
|
-
LogLevel["WARN"] = "warn";
|
|
20
|
-
LogLevel["ERROR"] = "error";
|
|
21
|
-
})(LogLevel || (exports.LogLevel = LogLevel = {}));
|
|
22
|
-
/**
|
|
23
|
-
* 默认配置
|
|
24
|
-
*/
|
|
25
|
-
const defaultConfig = {
|
|
26
|
-
level: LogLevel.INFO,
|
|
27
|
-
logArgs: true,
|
|
28
|
-
logResult: true,
|
|
29
|
-
logExecutionTime: true,
|
|
30
|
-
logger: (txt) => addLog(txt)
|
|
31
|
-
};
|
|
32
|
-
/**
|
|
33
|
-
* 合并配置
|
|
34
|
-
*/
|
|
35
|
-
function mergeConfig(customConfig) {
|
|
36
|
-
return { ...defaultConfig, ...customConfig };
|
|
37
|
-
}
|
|
38
|
-
function showLogs() {
|
|
39
|
-
console.log(logs.join('\n'));
|
|
40
|
-
logs.length = 0;
|
|
41
|
-
}
|
|
42
|
-
let logSpy = undefined;
|
|
43
|
-
function setSpy(fn) {
|
|
44
|
-
logSpy = fn;
|
|
45
|
-
}
|
|
46
|
-
function addLog(...logs) {
|
|
47
|
-
logs.push(...logs);
|
|
48
|
-
if (logs.length > 20) {
|
|
49
|
-
logs.splice(0, logs.length - 20);
|
|
50
|
-
}
|
|
51
|
-
for (const log of logs) {
|
|
52
|
-
logSpy?.(log, 'add');
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
function updateLog(log) {
|
|
56
|
-
logs[logs.length - 1] = log;
|
|
57
|
-
logSpy?.(log, 'update');
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* 为模块中的所有导出函数应用切面 - 用于普通函数模块
|
|
61
|
-
*/
|
|
62
|
-
function applyAspectToModule(moduleExports, config) {
|
|
63
|
-
const mergedConfig = mergeConfig(config);
|
|
64
|
-
for (const key in moduleExports) {
|
|
65
|
-
if (typeof moduleExports[key] === 'function') {
|
|
66
|
-
const originalFunction = moduleExports[key];
|
|
67
|
-
moduleExports[key] = async function (...args) {
|
|
68
|
-
const startTime = Date.now();
|
|
69
|
-
const functionName = key;
|
|
70
|
-
// 记录函数调用
|
|
71
|
-
if (mergedConfig.logArgs) {
|
|
72
|
-
mergedConfig.logger?.(`${functionName}, 参数: ${JSON.stringify(args)}`);
|
|
73
|
-
}
|
|
74
|
-
else {
|
|
75
|
-
mergedConfig.logger?.(`${functionName}`);
|
|
76
|
-
}
|
|
77
|
-
// 执行原函数
|
|
78
|
-
try {
|
|
79
|
-
const result = await originalFunction.apply(this, args);
|
|
80
|
-
// 处理同步返回
|
|
81
|
-
const endTime = Date.now();
|
|
82
|
-
const executionTime = endTime - startTime;
|
|
83
|
-
if (mergedConfig.logResult) {
|
|
84
|
-
mergedConfig.logger?.(`${functionName} 返回: ${JSON.stringify(result)} 执行时间: ${executionTime}ms`);
|
|
85
|
-
}
|
|
86
|
-
return result;
|
|
87
|
-
}
|
|
88
|
-
catch (error) {
|
|
89
|
-
// 处理异常
|
|
90
|
-
const endTime = Date.now();
|
|
91
|
-
const executionTime = endTime - startTime;
|
|
92
|
-
mergedConfig.logger?.(`${functionName} 抛出异常: ${error.message} 执行时间: ${executionTime}ms`);
|
|
93
|
-
throw error;
|
|
94
|
-
}
|
|
95
|
-
};
|
|
96
|
-
}
|
|
97
|
-
}
|
|
98
|
-
return moduleExports;
|
|
99
|
-
}
|
|
100
|
-
function spyConsole(logCount = 1, format = 'compact' // 紧凑还是宽松
|
|
101
|
-
) {
|
|
102
|
-
console.log = async (...txts) => {
|
|
103
|
-
addLog(...txts.map((txt) => (format === 'compact' && typeof txt === 'string' ? txt.replace(/\n/g, '\\n') : txt)));
|
|
104
|
-
if (logs.length > logCount) {
|
|
105
|
-
logs.shift();
|
|
106
|
-
}
|
|
107
|
-
logs.forEach((txts) => output(...txts));
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
//# sourceMappingURL=loging.js.map
|
package/dist/statusBar.js
DELETED
|
@@ -1,121 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
-
if (k2 === undefined) k2 = k;
|
|
4
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
-
}
|
|
8
|
-
Object.defineProperty(o, k2, desc);
|
|
9
|
-
}) : (function(o, m, k, k2) {
|
|
10
|
-
if (k2 === undefined) k2 = k;
|
|
11
|
-
o[k2] = m[k];
|
|
12
|
-
}));
|
|
13
|
-
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
-
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
-
}) : function(o, v) {
|
|
16
|
-
o["default"] = v;
|
|
17
|
-
});
|
|
18
|
-
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
-
var ownKeys = function(o) {
|
|
20
|
-
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
-
var ar = [];
|
|
22
|
-
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
-
return ar;
|
|
24
|
-
};
|
|
25
|
-
return ownKeys(o);
|
|
26
|
-
};
|
|
27
|
-
return function (mod) {
|
|
28
|
-
if (mod && mod.__esModule) return mod;
|
|
29
|
-
var result = {};
|
|
30
|
-
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
-
__setModuleDefault(result, mod);
|
|
32
|
-
return result;
|
|
33
|
-
};
|
|
34
|
-
})();
|
|
35
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
-
exports.getStatusBarItem = getStatusBarItem;
|
|
37
|
-
exports.createStatusBarItem = createStatusBarItem;
|
|
38
|
-
exports.showLoginStatus = showLoginStatus;
|
|
39
|
-
exports.showProgress = showProgress;
|
|
40
|
-
exports.showLogedStatus = showLogedStatus;
|
|
41
|
-
const vscode = __importStar(require("vscode"));
|
|
42
|
-
const user_1 = require("./user");
|
|
43
|
-
let statusBarItem;
|
|
44
|
-
function getStatusBarItem() {
|
|
45
|
-
return statusBarItem;
|
|
46
|
-
;
|
|
47
|
-
}
|
|
48
|
-
function createStatusBarItem(context) {
|
|
49
|
-
if (!statusBarItem) {
|
|
50
|
-
statusBarItem = vscode.window.createStatusBarItem(vscode.StatusBarAlignment.Right);
|
|
51
|
-
context.subscriptions.push(statusBarItem);
|
|
52
|
-
}
|
|
53
|
-
return statusBarItem;
|
|
54
|
-
}
|
|
55
|
-
function showLoginStatus() {
|
|
56
|
-
// 显示登录中状态
|
|
57
|
-
statusBarItem.text = '$(sync~spin) 点击取消登录...';
|
|
58
|
-
statusBarItem.command = 'ai-worktool.cancelLoginCommand';
|
|
59
|
-
statusBarItem.show();
|
|
60
|
-
}
|
|
61
|
-
let timer;
|
|
62
|
-
function showProgress(tasks) {
|
|
63
|
-
if (!tasks) {
|
|
64
|
-
showUserInfo();
|
|
65
|
-
return;
|
|
66
|
-
}
|
|
67
|
-
if (timer) {
|
|
68
|
-
clearTimeout(timer);
|
|
69
|
-
}
|
|
70
|
-
// 更新悬停面板内容
|
|
71
|
-
function updateTaskProgress() {
|
|
72
|
-
let progress = '';
|
|
73
|
-
progress = `$(sync~spin) ${tasks
|
|
74
|
-
.map((task) => {
|
|
75
|
-
return (tasks?.length === 1 ? task.name + ' ' : '') + Math.round((task.progress / task.total) * 100) + '%';
|
|
76
|
-
})
|
|
77
|
-
.join(' | ')}`;
|
|
78
|
-
statusBarItem.text = progress;
|
|
79
|
-
statusBarItem.tooltip = `${tasks
|
|
80
|
-
.map((task) => task.name + ' ' + Math.round((task.progress / task.total) * 100) + '%')
|
|
81
|
-
.join('\n')}`;
|
|
82
|
-
}
|
|
83
|
-
updateTaskProgress();
|
|
84
|
-
statusBarItem.show();
|
|
85
|
-
// 检查所有任务是否完成
|
|
86
|
-
if (tasks.every((t) => t.status === 'completed')) {
|
|
87
|
-
statusBarItem.text = '$(check) 所有任务完成';
|
|
88
|
-
// 5秒后隐藏状态栏项
|
|
89
|
-
timer = setTimeout(() => {
|
|
90
|
-
showUserInfo();
|
|
91
|
-
}, 5000);
|
|
92
|
-
}
|
|
93
|
-
else {
|
|
94
|
-
timer = setTimeout(() => {
|
|
95
|
-
showUserInfo();
|
|
96
|
-
}, 30000);
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
async function showUserInfo() {
|
|
100
|
-
const userInfo = await (0, user_1.getUserData)();
|
|
101
|
-
if (!userInfo) {
|
|
102
|
-
statusBarItem.hide();
|
|
103
|
-
return;
|
|
104
|
-
}
|
|
105
|
-
statusBarItem.command = 'ai-worktool.usageCommand';
|
|
106
|
-
statusBarItem.tooltip = '吃豆豆:查看使用量';
|
|
107
|
-
statusBarItem.text = '$(check) ' + userInfo.name;
|
|
108
|
-
statusBarItem.show();
|
|
109
|
-
}
|
|
110
|
-
function showLogedStatus() {
|
|
111
|
-
if (statusBarItem.command === 'ai-worktool.cancelLoginCommand') {
|
|
112
|
-
statusBarItem.text = '$(check) 登录成功';
|
|
113
|
-
setTimeout(() => {
|
|
114
|
-
showUserInfo();
|
|
115
|
-
}, 3000);
|
|
116
|
-
}
|
|
117
|
-
else {
|
|
118
|
-
showUserInfo();
|
|
119
|
-
}
|
|
120
|
-
}
|
|
121
|
-
//# sourceMappingURL=statusBar.js.map
|