ai-worktool 1.0.7
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 +169 -0
- package/LICENSE.txt +1 -0
- package/README.md +67 -0
- package/dist/agents/chanjet.js +377 -0
- package/dist/agents/index.js +73 -0
- package/dist/agents/jianguoke.js +182 -0
- package/dist/agents/prompt.js +41 -0
- package/dist/agents/toolCall.js +135 -0
- package/dist/cli.js +9 -0
- package/dist/loging.js +110 -0
- package/dist/program.js +35 -0
- package/dist/testAgent.js +142 -0
- package/dist/tools/file.js +543 -0
- package/dist/tools/git.js +204 -0
- package/dist/tools/index.js +71 -0
- package/dist/tools/interface.js +3 -0
- package/dist/tools/javascript.js +180 -0
- package/dist/tools/jest.js +482 -0
- package/dist/tools/mocha.js +107 -0
- package/dist/tools/package.js +376 -0
- package/dist/tools/project.js +541 -0
- package/dist/tools/typescript.js +242 -0
- package/dist/tools/vitest.js +115 -0
- package/dist/user.js +472 -0
- package/dist/view.js +216 -0
- package/package.json +289 -0
@@ -0,0 +1,73 @@
|
|
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
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
36
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
37
|
+
};
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
39
|
+
exports.setConversationId = void 0;
|
40
|
+
exports.getPlatform = getPlatform;
|
41
|
+
exports.setPlatform = setPlatform;
|
42
|
+
exports.startAgent = startAgent;
|
43
|
+
const jianguoke = __importStar(require("./jianguoke"));
|
44
|
+
const chanjet = __importStar(require("./chanjet"));
|
45
|
+
__exportStar(require("./prompt"), exports);
|
46
|
+
const platforms = {
|
47
|
+
chanjet,
|
48
|
+
jianguoke
|
49
|
+
};
|
50
|
+
let currentPlatform;
|
51
|
+
function getPlatform() {
|
52
|
+
return platforms[currentPlatform || 'jianguoke'];
|
53
|
+
}
|
54
|
+
function setPlatform(target) {
|
55
|
+
currentPlatform = target;
|
56
|
+
}
|
57
|
+
const setConversationId = (id) => {
|
58
|
+
const platform = getPlatform();
|
59
|
+
if (!platform) {
|
60
|
+
throw new Error(`智能体 "${currentPlatform}" 不支持`);
|
61
|
+
}
|
62
|
+
platform.setConversationId(id);
|
63
|
+
};
|
64
|
+
exports.setConversationId = setConversationId;
|
65
|
+
async function startAgent(currentPlatform, name, question, vars, withConversation, ctrl, onMessage, onToolCall) {
|
66
|
+
const platform = platforms[currentPlatform] || getPlatform();
|
67
|
+
if (!platform) {
|
68
|
+
throw new Error(`智能体 "${currentPlatform}" 不支持`);
|
69
|
+
}
|
70
|
+
await platform.startAgent.apply(null, [name, question, vars, withConversation, ctrl, onMessage, onToolCall]);
|
71
|
+
console.log(`智能体 "${currentPlatform}" 调用完成`);
|
72
|
+
}
|
73
|
+
//# sourceMappingURL=index.js.map
|
@@ -0,0 +1,182 @@
|
|
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.setConversationId = void 0;
|
37
|
+
exports.toolCallback = toolCallback;
|
38
|
+
exports.startAgent = startAgent;
|
39
|
+
const fetch_sse_1 = require("fetch-sse");
|
40
|
+
const tools = __importStar(require("../tools"));
|
41
|
+
const toolCall_1 = require("./toolCall");
|
42
|
+
const user_1 = require("../user");
|
43
|
+
const DEFAULT_SERVER = 'https://ai.jianguoke.cn';
|
44
|
+
let conversationId = ''; // 会话ID
|
45
|
+
const setConversationId = (id) => {
|
46
|
+
conversationId = id;
|
47
|
+
};
|
48
|
+
exports.setConversationId = setConversationId;
|
49
|
+
async function postData(url, data) {
|
50
|
+
const token = (0, user_1.getTokenStorage)().get();
|
51
|
+
try {
|
52
|
+
// 发送POST请求
|
53
|
+
const response = await fetch(url, {
|
54
|
+
method: 'POST',
|
55
|
+
headers: {
|
56
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
57
|
+
'Content-Type': 'application/json',
|
58
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
59
|
+
Authorization: token ? `Bearer ${token}` : ''
|
60
|
+
},
|
61
|
+
body: JSON.stringify(data) // 将数据转换为JSON字符串
|
62
|
+
});
|
63
|
+
// 检查响应状态
|
64
|
+
if (!response.ok) {
|
65
|
+
throw new Error(`HTTP error! status: ${response.status}`);
|
66
|
+
}
|
67
|
+
// 解析响应数据(根据实际响应格式选择解析方式)
|
68
|
+
const result = await response.text();
|
69
|
+
return {
|
70
|
+
status: response.status,
|
71
|
+
statusText: response.statusText,
|
72
|
+
data: result,
|
73
|
+
headers: response.headers
|
74
|
+
};
|
75
|
+
}
|
76
|
+
catch (error) {
|
77
|
+
console.error('请求失败:', error);
|
78
|
+
throw error; // 重新抛出错误以便调用者处理
|
79
|
+
}
|
80
|
+
}
|
81
|
+
async function toolCallback(toolName, callId, data) {
|
82
|
+
const baseURL = process.env.AI_SERVER || DEFAULT_SERVER;
|
83
|
+
await postData(`${baseURL}/api/tool/${toolName}`, { callId, data });
|
84
|
+
}
|
85
|
+
async function handleToolCall(toolCall) {
|
86
|
+
let data = null;
|
87
|
+
let message;
|
88
|
+
let success;
|
89
|
+
try {
|
90
|
+
const tool = tools[toolCall.toolName];
|
91
|
+
if (!tool) {
|
92
|
+
throw new Error(`Tool ${toolCall.toolName} not found`);
|
93
|
+
}
|
94
|
+
data = (await (0, toolCall_1.callWithObject)(tool, toolCall.params)) || '执行成功';
|
95
|
+
if (toolCall.toolName === 'readFile') {
|
96
|
+
data = `\n\`\`\`${(0, toolCall_1.inferCodeTypeFromExtension)(toolCall.params.filePath)}\n${data}\n\`\`\``;
|
97
|
+
}
|
98
|
+
success = true;
|
99
|
+
}
|
100
|
+
catch (err) {
|
101
|
+
success = false;
|
102
|
+
message = err.message || '执行失败';
|
103
|
+
}
|
104
|
+
await toolCallback(toolCall.toolName, toolCall.callId, data || message).catch(console.error);
|
105
|
+
return { data, message, success };
|
106
|
+
}
|
107
|
+
async function startAgent(name, question, vars, withConversation, ctrl, onMessage, onToolCall) {
|
108
|
+
let err = null;
|
109
|
+
let msg = '';
|
110
|
+
let lastMsgNo = 0;
|
111
|
+
const baseURL = process.env.AI_SERVER || DEFAULT_SERVER;
|
112
|
+
const token = (0, user_1.getTokenStorage)().get();
|
113
|
+
console.log(`Starting agent: ${baseURL}, token: ${token}`);
|
114
|
+
await (0, fetch_sse_1.fetchEventData)(`${baseURL}/api/agent/exec/aicoder`, {
|
115
|
+
method: 'POST',
|
116
|
+
signal: ctrl?.signal,
|
117
|
+
headers: {
|
118
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
119
|
+
Authorization: token ? `Bearer ${token}` : '',
|
120
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
121
|
+
'Content-Type': 'application/json',
|
122
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
123
|
+
'Cache-Control': 'no-cache',
|
124
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
125
|
+
Pragma: 'no-cache',
|
126
|
+
// 添加一个唯一的自定义头部,包含当前时间戳
|
127
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
128
|
+
'X-Custom-No-Cache': new Date().getTime().toString()
|
129
|
+
},
|
130
|
+
data: {
|
131
|
+
name,
|
132
|
+
vars,
|
133
|
+
question,
|
134
|
+
sid: withConversation ? conversationId : undefined,
|
135
|
+
tagEnabled: false
|
136
|
+
},
|
137
|
+
onError(error) {
|
138
|
+
err = error;
|
139
|
+
},
|
140
|
+
async onMessage(ev) {
|
141
|
+
const data = JSON.parse(ev.data);
|
142
|
+
// console.log(ev?.event, data);
|
143
|
+
if (ev?.event === 'MESSAGE') {
|
144
|
+
if (data.no !== lastMsgNo) {
|
145
|
+
lastMsgNo = data.no;
|
146
|
+
msg = '';
|
147
|
+
}
|
148
|
+
msg += data.content;
|
149
|
+
await onMessage?.(msg, 'msg-' + data.id + data.no);
|
150
|
+
}
|
151
|
+
if (ev?.event === 'TOOLCALL') {
|
152
|
+
const id = 'tool-' + data.callId;
|
153
|
+
await onMessage?.((0, toolCall_1.formatToolCallInfo)({
|
154
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
155
|
+
function_name: data.toolName,
|
156
|
+
params: data.params
|
157
|
+
}, vars.projectRoot), id);
|
158
|
+
const result = await handleToolCall(data);
|
159
|
+
await onToolCall?.({
|
160
|
+
functionName: data.toolName,
|
161
|
+
params: data.params,
|
162
|
+
result
|
163
|
+
});
|
164
|
+
await onMessage?.((0, toolCall_1.formatToolCallInfo)({
|
165
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
166
|
+
function_name: data.toolName,
|
167
|
+
params: data.params
|
168
|
+
}, vars.projectRoot, result), id);
|
169
|
+
}
|
170
|
+
if (ev?.event === 'DONE') {
|
171
|
+
console.log(msg);
|
172
|
+
}
|
173
|
+
if (ev?.event === 'ERROR') {
|
174
|
+
err = data.message;
|
175
|
+
}
|
176
|
+
}
|
177
|
+
});
|
178
|
+
if (err) {
|
179
|
+
throw new Error(err);
|
180
|
+
}
|
181
|
+
}
|
182
|
+
//# sourceMappingURL=jianguoke.js.map
|
@@ -0,0 +1,41 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.fixErrorPrompt = fixErrorPrompt;
|
7
|
+
exports.fixCodePrompt = fixCodePrompt;
|
8
|
+
exports.addUncoveredLinePrompt = addUncoveredLinePrompt;
|
9
|
+
const path_1 = __importDefault(require("path"));
|
10
|
+
const tools_1 = require("../tools");
|
11
|
+
const MAXLEN = 10000;
|
12
|
+
function fixErrorPrompt(error) {
|
13
|
+
return `单测执行失败,日志如下:
|
14
|
+
\`\`\`
|
15
|
+
${error.slice(0, MAXLEN)}
|
16
|
+
\`\`\`
|
17
|
+
`;
|
18
|
+
}
|
19
|
+
// 提示词管理,根据任务合成特定提示词
|
20
|
+
async function fixCodePrompt(failedTest) {
|
21
|
+
return `测试文件"${path_1.default.resolve(failedTest.testFilePath)}"${failedTest.testName ? '里的"' + failedTest.testName + '"' : ''}执行失败.
|
22
|
+
|
23
|
+
错误信息为:
|
24
|
+
\`\`\`
|
25
|
+
${failedTest.errorMessages.join('\n')}
|
26
|
+
\`\`\`
|
27
|
+
|
28
|
+
测试文件内容如下:
|
29
|
+
\`\`\`
|
30
|
+
${await (0, tools_1.readFile)(failedTest.testFilePath, 'utf8', true)}
|
31
|
+
\`\`\``;
|
32
|
+
}
|
33
|
+
async function addUncoveredLinePrompt(srcPath, report) {
|
34
|
+
return `源文件"${path_1.default.resolve(srcPath)}"的单元测试覆盖率是${report.coverage.lines.pct}%, 还有"${report.uncoveredLines.join(',')}"行未覆盖单测。
|
35
|
+
|
36
|
+
源文件内容如下:
|
37
|
+
\`\`\`
|
38
|
+
${await (0, tools_1.readFile)(srcPath, 'utf8', true)}
|
39
|
+
\`\`\``;
|
40
|
+
}
|
41
|
+
//# sourceMappingURL=prompt.js.map
|
@@ -0,0 +1,135 @@
|
|
1
|
+
"use strict";
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
4
|
+
};
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
6
|
+
exports.inferCodeTypeFromExtension = inferCodeTypeFromExtension;
|
7
|
+
exports.callWithObject = callWithObject;
|
8
|
+
exports.getParamNames = getParamNames;
|
9
|
+
exports.formatToolCallInfo = formatToolCallInfo;
|
10
|
+
const path_1 = __importDefault(require("path"));
|
11
|
+
/**
|
12
|
+
* 根据文件路径的扩展名推断Markdown代码块应使用的类型名
|
13
|
+
* @param filePath - 文件路径
|
14
|
+
* @returns 代码块类型名,如果无法识别则返回空字符串
|
15
|
+
*/
|
16
|
+
function inferCodeTypeFromExtension(filePath) {
|
17
|
+
// 获取文件扩展名(包含点号)并转为小写
|
18
|
+
const extname = path_1.default.extname(filePath).toLowerCase();
|
19
|
+
// 移除点号,获取纯扩展名
|
20
|
+
const extension = extname.slice(1);
|
21
|
+
// 常见文件扩展名与Markdown代码块类型名的映射
|
22
|
+
const extensionMap = {
|
23
|
+
// 前端相关
|
24
|
+
html: 'html',
|
25
|
+
htm: 'html',
|
26
|
+
css: 'css',
|
27
|
+
scss: 'scss',
|
28
|
+
sass: 'sass',
|
29
|
+
less: 'less',
|
30
|
+
js: 'javascript',
|
31
|
+
jsx: 'jsx',
|
32
|
+
ts: 'typescript',
|
33
|
+
tsx: 'tsx',
|
34
|
+
// 后端相关
|
35
|
+
java: 'java',
|
36
|
+
py: 'python',
|
37
|
+
php: 'php',
|
38
|
+
rb: 'ruby',
|
39
|
+
go: 'go',
|
40
|
+
rs: 'rust',
|
41
|
+
c: 'c',
|
42
|
+
cpp: 'cpp',
|
43
|
+
cs: 'csharp',
|
44
|
+
swift: 'swift',
|
45
|
+
kt: 'kotlin',
|
46
|
+
// 脚本与配置
|
47
|
+
sh: 'bash',
|
48
|
+
bash: 'bash',
|
49
|
+
json: 'json',
|
50
|
+
yml: 'yaml',
|
51
|
+
yaml: 'yaml',
|
52
|
+
xml: 'xml',
|
53
|
+
md: 'markdown',
|
54
|
+
markdown: 'markdown',
|
55
|
+
// 数据库
|
56
|
+
sql: 'sql',
|
57
|
+
mysql: 'sql',
|
58
|
+
// 其他
|
59
|
+
txt: 'text',
|
60
|
+
diff: 'diff',
|
61
|
+
patch: 'diff'
|
62
|
+
};
|
63
|
+
// 返回对应的类型名,如果没有匹配则返回空字符串
|
64
|
+
return extensionMap[extension] || '';
|
65
|
+
}
|
66
|
+
/**
|
67
|
+
* 从对象中提取函数参数并调用函数
|
68
|
+
* @param fn 目标函数
|
69
|
+
* @param argsObj 包含参数的对象
|
70
|
+
* @returns 函数执行结果
|
71
|
+
*/
|
72
|
+
function callWithObject(fn, argsObj) {
|
73
|
+
// 获取函数参数名
|
74
|
+
const paramNames = getParamNames(fn);
|
75
|
+
// 从对象中提取参数值
|
76
|
+
const args = paramNames.map((name) => argsObj[name]);
|
77
|
+
// 调用函数
|
78
|
+
return fn(...args);
|
79
|
+
}
|
80
|
+
/**
|
81
|
+
* 获取函数参数名
|
82
|
+
* @param fn 目标函数
|
83
|
+
* @returns 参数名数组
|
84
|
+
*/
|
85
|
+
function getParamNames(fn) {
|
86
|
+
// 匹配函数参数列表的正则表达式
|
87
|
+
const paramRegex = /\(([^)]*)\)/;
|
88
|
+
// 匹配参数名的正则表达式(处理默认值等情况)
|
89
|
+
const nameRegex = /([^\s,=]+)/g;
|
90
|
+
// 获取函数源码
|
91
|
+
const fnStr = fn.toString();
|
92
|
+
// 提取参数列表字符串
|
93
|
+
const match = paramRegex.exec(fnStr);
|
94
|
+
if (!match) {
|
95
|
+
return [];
|
96
|
+
}
|
97
|
+
const params = match[1].trim();
|
98
|
+
if (!params) {
|
99
|
+
return [];
|
100
|
+
}
|
101
|
+
// 提取参数名(处理有默认值的情况)
|
102
|
+
const paramNames = [];
|
103
|
+
let nameMatch;
|
104
|
+
while ((nameMatch = nameRegex.exec(params)) !== null) {
|
105
|
+
paramNames.push(nameMatch[1]);
|
106
|
+
}
|
107
|
+
return paramNames;
|
108
|
+
}
|
109
|
+
function formatToolCallInfo(
|
110
|
+
// eslint-disable-next-line @typescript-eslint/naming-convention
|
111
|
+
toolCall, root, result) {
|
112
|
+
root = root || '/';
|
113
|
+
if (toolCall.function_name === 'readFile') {
|
114
|
+
const outputResult = result ? (result?.success ? ` ✅` : result?.message || '❌') : '';
|
115
|
+
return `读取文件:${path_1.default.relative(root, toolCall.params[0] || toolCall.params.filePath)}${outputResult}`;
|
116
|
+
}
|
117
|
+
if (toolCall.function_name === 'writeFile') {
|
118
|
+
const outputResult = result ? (result?.success ? ` ✅` : result?.message || '❌') : '';
|
119
|
+
return `修改文件:${path_1.default.relative(root, toolCall.params[0] || toolCall.params.filePath)}${outputResult}`;
|
120
|
+
}
|
121
|
+
if (toolCall.function_name === 'searchFilesByExtension') {
|
122
|
+
const outputResult = result
|
123
|
+
? result?.success
|
124
|
+
? ` => ${result.data
|
125
|
+
.map((filePath) => path_1.default.relative(root, filePath))
|
126
|
+
.join(', ')
|
127
|
+
.slice(0, 50)} ✅`
|
128
|
+
: result?.message || '❌'
|
129
|
+
: '';
|
130
|
+
return `检索文件:${path_1.default.relative(root, toolCall.params[0] || toolCall.params.directory)}/*${toolCall.params[1] || toolCall.params.extensions}${outputResult}`;
|
131
|
+
}
|
132
|
+
const outputResult = result ? (result?.success ? ` ✅` : result?.message || '❌') : '';
|
133
|
+
return toolCall.function_name + outputResult;
|
134
|
+
}
|
135
|
+
//# sourceMappingURL=toolCall.js.map
|
package/dist/cli.js
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
"use strict";
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
5
|
+
};
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
+
const program_1 = __importDefault(require("./program"));
|
8
|
+
program_1.default.parse(process.argv);
|
9
|
+
//# sourceMappingURL=cli.js.map
|
package/dist/loging.js
ADDED
@@ -0,0 +1,110 @@
|
|
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/program.js
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
#!/usr/bin/env node
|
2
|
+
"use strict";
|
3
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
4
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
5
|
+
};
|
6
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
7
|
+
const commander_1 = require("commander");
|
8
|
+
const path_1 = __importDefault(require("path"));
|
9
|
+
const testAgent_1 = require("./testAgent");
|
10
|
+
const tools_1 = require("./tools");
|
11
|
+
const view_1 = require("./view");
|
12
|
+
const program = new commander_1.Command();
|
13
|
+
program.name('aicoder').description('你的AI编程搭子').version('1.0.0');
|
14
|
+
program
|
15
|
+
.command('startTestAgent')
|
16
|
+
.description('启动单测智能体,根据源代码文件开始补全单测代码,直到覆盖率100%')
|
17
|
+
.option('-p, --platform <string>', '智能体平台', 'jianguoke')
|
18
|
+
.option('-r, --projectRoot <directory>', '源代码文件夹', (txt) => path_1.default.resolve(txt), process.cwd())
|
19
|
+
.option('-t, --testDir <string>', '测试用例文件夹', 'test')
|
20
|
+
.option('-s, --srcDir <string>', '测试用例文件夹', 'src')
|
21
|
+
.option('-c, --coverageDir <string>', '覆盖率报告文件夹', 'coverage')
|
22
|
+
.option('--autoCommit <boolean>', '覆盖率报告文件夹', (txt) => txt === 'true', true)
|
23
|
+
.option('--fullCoverageEnd <boolean>', '是否在达到100%覆盖率后结束', (txt) => txt === 'true', true)
|
24
|
+
.action((options) => (0, testAgent_1.startTestAgent)(options));
|
25
|
+
program
|
26
|
+
.command('showCoverage')
|
27
|
+
.description('监控代码覆盖率报告')
|
28
|
+
.option('-r, --projectRoot <directory>', '源代码文件夹', (txt) => path_1.default.resolve(txt), process.cwd())
|
29
|
+
.option('-c, --coverageDir <string>', '覆盖率报告文件夹', 'coverage')
|
30
|
+
.action(async (options) => {
|
31
|
+
await (0, tools_1.runJestTests)(options.projectRoot);
|
32
|
+
await (0, view_1.showCoverageView)(path_1.default.join(options.projectRoot, options.coverageDir));
|
33
|
+
});
|
34
|
+
exports.default = program;
|
35
|
+
//# sourceMappingURL=program.js.map
|