job51-gitlab-cr-node-skill-prompt-optimize 1.0.0
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/README.md +58 -0
- package/analyze_filepath.js +66 -0
- package/analyze_issue.js +68 -0
- package/debug_test.js +89 -0
- package/env_check.js +32 -0
- package/example.js +29 -0
- package/index.js +532 -0
- package/log.txt +519 -0
- package/mr-review-template.md +65 -0
- package/package.json +23 -0
- package/simulate_ci.js +57 -0
- package/simulate_no_claude.js +61 -0
- package/temp-diff-block-1772527822359-0.diff +10 -0
- package/temp-diff-block-1772527823803-2.diff +9 -0
- package/temp-diff-block-1772527949844-0.diff +10 -0
- package/temp-diff-block-1772527949860-2.diff +9 -0
- package/temp-diff-block-1772528045156-0.diff +10 -0
- package/temp-diff-block-1772528045169-1.diff +8 -0
- package/temp-diff-block-1772528045180-2.diff +9 -0
- package/temp-diff-block-1772528185915-0.diff +10 -0
- package/temp-diff-block-1772528185952-2.diff +9 -0
- package/test_claude_file_access.js +125 -0
- package/test_filepath.js +98 -0
- package/test_no_nested_session.js +117 -0
- package/test_path_recognition.js +119 -0
- package/utils.js +67 -0
package/package.json
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "job51-gitlab-cr-node-skill-prompt-optimize",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "GitLab merge request code review tool with AI-powered analysis",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"gitlab-cr": "./index.js"
|
|
8
|
+
},
|
|
9
|
+
"scripts": {
|
|
10
|
+
"start": "node index.js",
|
|
11
|
+
"dev": "nodemon index.js",
|
|
12
|
+
"example": "node example.js"
|
|
13
|
+
},
|
|
14
|
+
"keywords": [],
|
|
15
|
+
"author": "Linton Cao",
|
|
16
|
+
"license": "MIT",
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"axios": "^1.6.0"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"nodemon": "^3.0.1"
|
|
22
|
+
}
|
|
23
|
+
}
|
package/simulate_ci.js
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// 模拟在GitLab CI环境中的情况
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
|
|
4
|
+
console.log('=== 模拟GitLab CI环境下的Claude调用 ===');
|
|
5
|
+
|
|
6
|
+
function runClaudeCommandSimulation(promptContent) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
console.log('尝试启动Claude命令...');
|
|
9
|
+
|
|
10
|
+
// 模拟Claude命令执行(在GitLab CI中可能不存在或不可用)
|
|
11
|
+
const claudeProcess = spawn('claude', ['-p', promptContent], {
|
|
12
|
+
shell: true,
|
|
13
|
+
cwd: process.cwd(),
|
|
14
|
+
// 在GitLab CI中,可能没有Claude CLI或命令不可用
|
|
15
|
+
env: { ...process.env }, // 这里可能没有Claude相关的环境配置
|
|
16
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
let stdout = '';
|
|
20
|
+
let stderr = '';
|
|
21
|
+
|
|
22
|
+
claudeProcess.stdout.on('data', (data) => {
|
|
23
|
+
stdout += data.toString();
|
|
24
|
+
console.log('STDOUT接收数据:', data.toString().substring(0, 100) + '...');
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
claudeProcess.stderr.on('data', (data) => {
|
|
28
|
+
stderr += data.toString();
|
|
29
|
+
console.log('STDERR接收数据:', data.toString());
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
claudeProcess.on('close', (code) => {
|
|
33
|
+
console.log(`Claude进程关闭,退出码: ${code}`);
|
|
34
|
+
console.log(`最终输出: "${stdout}"`);
|
|
35
|
+
console.log(`错误输出: "${stderr}"`);
|
|
36
|
+
|
|
37
|
+
if (code !== 0) {
|
|
38
|
+
console.log('命令执行失败!');
|
|
39
|
+
resolve(''); // 返回空字符串,就像在GitLab CI中一样
|
|
40
|
+
} else {
|
|
41
|
+
resolve(stdout.trim());
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
claudeProcess.on('error', (error) => {
|
|
46
|
+
console.log(`进程启动错误: ${error.message}`);
|
|
47
|
+
// 这种情况下,Claude命令根本没启动,所以返回空
|
|
48
|
+
resolve('');
|
|
49
|
+
});
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// 测试调用
|
|
54
|
+
runClaudeCommandSimulation('/simple-code-review console.log("test");')
|
|
55
|
+
.then(result => {
|
|
56
|
+
console.log('最终结果:', result || '(空结果)');
|
|
57
|
+
});
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// 模拟在GitLab CI环境中的情况(移除了CLAUDECODE环境变量,但系统仍没有Claude CLI)
|
|
2
|
+
const { spawn } = require('child_process');
|
|
3
|
+
|
|
4
|
+
console.log('=== 模拟移除CLAUDECODE后的GitLab CI环境 ===');
|
|
5
|
+
|
|
6
|
+
function runClaudeCommandSimulationWithoutClaudeCodeEnv(promptContent) {
|
|
7
|
+
return new Promise((resolve, reject) => {
|
|
8
|
+
console.log('尝试启动Claude命令(模拟GitLab CI环境)...');
|
|
9
|
+
|
|
10
|
+
// 复制环境变量并移除CLAUDECODE
|
|
11
|
+
const envVars = { ...process.env };
|
|
12
|
+
delete envVars.CLAUDECODE;
|
|
13
|
+
delete envVars.CLAUDE_CODE_ENTRYPOINT;
|
|
14
|
+
|
|
15
|
+
const claudeProcess = spawn('claude', ['-p', promptContent], {
|
|
16
|
+
shell: true,
|
|
17
|
+
cwd: process.cwd(),
|
|
18
|
+
env: envVars, // 没有CLAUDECODE环境变量
|
|
19
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
let stdout = '';
|
|
23
|
+
let stderr = '';
|
|
24
|
+
|
|
25
|
+
claudeProcess.stdout.on('data', (data) => {
|
|
26
|
+
stdout += data.toString();
|
|
27
|
+
console.log('STDOUT接收数据:', data.toString().substring(0, 100) + '...');
|
|
28
|
+
});
|
|
29
|
+
|
|
30
|
+
claudeProcess.stderr.on('data', (data) => {
|
|
31
|
+
stderr += data.toString();
|
|
32
|
+
console.log('STDERR接收数据:', data.toString());
|
|
33
|
+
});
|
|
34
|
+
|
|
35
|
+
claudeProcess.on('close', (code) => {
|
|
36
|
+
console.log(`Claude进程关闭,退出码: ${code}`);
|
|
37
|
+
console.log(`最终输出: "${stdout}"`);
|
|
38
|
+
console.log(`错误输出: "${stderr}"`);
|
|
39
|
+
|
|
40
|
+
if (code !== 0) {
|
|
41
|
+
console.log('命令执行失败或命令不存在!');
|
|
42
|
+
resolve(''); // 返回空字符串,就像在GitLab CI中找不到命令一样
|
|
43
|
+
} else {
|
|
44
|
+
resolve(stdout.trim());
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
claudeProcess.on('error', (error) => {
|
|
49
|
+
console.log(`进程启动错误: ${error.message}`);
|
|
50
|
+
console.log('这通常表示命令不存在或权限不足');
|
|
51
|
+
// 这种情况下,Claude命令根本没启动,所以返回空
|
|
52
|
+
resolve('');
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 测试调用
|
|
58
|
+
runClaudeCommandSimulationWithoutClaudeCodeEnv('/simple-code-review console.log("test");')
|
|
59
|
+
.then(result => {
|
|
60
|
+
console.log('最终结果:', result || '(空结果)');
|
|
61
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@@ -85,7 +85,8 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
}
|
|
3
|
+
|
|
4
|
+
private void extracted(StringBuilder result, String pushTag, List<ApplyPushDataDTO> applyPushDataList, Set<Long> accountIdSet) {
|
|
5
|
+
- if (CollectionUtils.isNotEmpty(applyPushDataList)){
|
|
6
|
+
+ if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
7
|
+
+ result = null;
|
|
8
|
+
applyPushDataList = applyPushDataList.stream().filter(a -> !accountIdSet.contains(a.getAccountId())).collect(Collectors.toList());
|
|
9
|
+
String format = MessageFormat.format("投递反馈push推送结束,size:{0}, pushtag:{1}", applyPushDataList.size(), pushTag);
|
|
10
|
+
if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@@ -142,7 +144,7 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
|
|
3
|
+
ApplyScrollSearchDTO resultBody = applyScrollSearchDTOResult.getResultbody();
|
|
4
|
+
|
|
5
|
+
- if (!applyScrollSearchDTOResult.requestSucceeded() || CollectionUtils.isEmpty(resultBody.getApplyStatusList())){
|
|
6
|
+
+ if (!applyScrollSearchDTOResult.requestSucceeded() && CollectionUtils.isEmpty(resultBody.getApplyStatusList())) {
|
|
7
|
+
return applyPushDataDTOList;
|
|
8
|
+
}
|
|
9
|
+
Long totalHit = resultBody.getTotalHit();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@@ -85,7 +85,8 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
}
|
|
3
|
+
|
|
4
|
+
private void extracted(StringBuilder result, String pushTag, List<ApplyPushDataDTO> applyPushDataList, Set<Long> accountIdSet) {
|
|
5
|
+
- if (CollectionUtils.isNotEmpty(applyPushDataList)){
|
|
6
|
+
+ if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
7
|
+
+ result = null;
|
|
8
|
+
applyPushDataList = applyPushDataList.stream().filter(a -> !accountIdSet.contains(a.getAccountId())).collect(Collectors.toList());
|
|
9
|
+
String format = MessageFormat.format("投递反馈push推送结束,size:{0}, pushtag:{1}", applyPushDataList.size(), pushTag);
|
|
10
|
+
if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@@ -142,7 +144,7 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
|
|
3
|
+
ApplyScrollSearchDTO resultBody = applyScrollSearchDTOResult.getResultbody();
|
|
4
|
+
|
|
5
|
+
- if (!applyScrollSearchDTOResult.requestSucceeded() || CollectionUtils.isEmpty(resultBody.getApplyStatusList())){
|
|
6
|
+
+ if (!applyScrollSearchDTOResult.requestSucceeded() && CollectionUtils.isEmpty(resultBody.getApplyStatusList())) {
|
|
7
|
+
return applyPushDataDTOList;
|
|
8
|
+
}
|
|
9
|
+
Long totalHit = resultBody.getTotalHit();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@@ -85,7 +85,8 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
}
|
|
3
|
+
|
|
4
|
+
private void extracted(StringBuilder result, String pushTag, List<ApplyPushDataDTO> applyPushDataList, Set<Long> accountIdSet) {
|
|
5
|
+
- if (CollectionUtils.isNotEmpty(applyPushDataList)){
|
|
6
|
+
+ if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
7
|
+
+ result = null;
|
|
8
|
+
applyPushDataList = applyPushDataList.stream().filter(a -> !accountIdSet.contains(a.getAccountId())).collect(Collectors.toList());
|
|
9
|
+
String format = MessageFormat.format("投递反馈push推送结束,size:{0}, pushtag:{1}", applyPushDataList.size(), pushTag);
|
|
10
|
+
if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@@ -142,7 +144,7 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
|
|
3
|
+
ApplyScrollSearchDTO resultBody = applyScrollSearchDTOResult.getResultbody();
|
|
4
|
+
|
|
5
|
+
- if (!applyScrollSearchDTOResult.requestSucceeded() || CollectionUtils.isEmpty(resultBody.getApplyStatusList())){
|
|
6
|
+
+ if (!applyScrollSearchDTOResult.requestSucceeded() && CollectionUtils.isEmpty(resultBody.getApplyStatusList())) {
|
|
7
|
+
return applyPushDataDTOList;
|
|
8
|
+
}
|
|
9
|
+
Long totalHit = resultBody.getTotalHit();
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
@@ -85,7 +85,8 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
}
|
|
3
|
+
|
|
4
|
+
private void extracted(StringBuilder result, String pushTag, List<ApplyPushDataDTO> applyPushDataList, Set<Long> accountIdSet) {
|
|
5
|
+
- if (CollectionUtils.isNotEmpty(applyPushDataList)){
|
|
6
|
+
+ if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
7
|
+
+ result = null;
|
|
8
|
+
applyPushDataList = applyPushDataList.stream().filter(a -> !accountIdSet.contains(a.getAccountId())).collect(Collectors.toList());
|
|
9
|
+
String format = MessageFormat.format("投递反馈push推送结束,size:{0}, pushtag:{1}", applyPushDataList.size(), pushTag);
|
|
10
|
+
if (CollectionUtils.isNotEmpty(applyPushDataList)) {
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
@@ -142,7 +144,7 @@ public class ApplyPushServiceImpl implements ApplyPushService {
|
|
2
|
+
|
|
3
|
+
ApplyScrollSearchDTO resultBody = applyScrollSearchDTOResult.getResultbody();
|
|
4
|
+
|
|
5
|
+
- if (!applyScrollSearchDTOResult.requestSucceeded() || CollectionUtils.isEmpty(resultBody.getApplyStatusList())){
|
|
6
|
+
+ if (!applyScrollSearchDTOResult.requestSucceeded() && CollectionUtils.isEmpty(resultBody.getApplyStatusList())) {
|
|
7
|
+
return applyPushDataDTOList;
|
|
8
|
+
}
|
|
9
|
+
Long totalHit = resultBody.getTotalHit();
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
// 测试在GitLab CI环境中Claude是否能正常处理文件
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawn } = require('child_process');
|
|
5
|
+
|
|
6
|
+
console.log('=== 测试GitLab CI环境中Claude处理文件的能力 ===\n');
|
|
7
|
+
|
|
8
|
+
async function testClaudeWithFile() {
|
|
9
|
+
// 1. 创建一个测试文件
|
|
10
|
+
const testFile = `./test-claude-file-${Date.now()}.js`;
|
|
11
|
+
const testContent = `// 测试文件
|
|
12
|
+
function testFunction() {
|
|
13
|
+
console.log("This is a test function");
|
|
14
|
+
// 有问题的代码:未处理异常
|
|
15
|
+
JSON.parse("{ invalid json }");
|
|
16
|
+
}`;
|
|
17
|
+
|
|
18
|
+
console.log(`1. 创建测试文件: ${testFile}`);
|
|
19
|
+
fs.writeFileSync(testFile, testContent);
|
|
20
|
+
|
|
21
|
+
// 2. 验证文件创建
|
|
22
|
+
const exists = fs.existsSync(testFile);
|
|
23
|
+
console.log(`2. 文件创建成功: ${exists}`);
|
|
24
|
+
|
|
25
|
+
if (!exists) {
|
|
26
|
+
console.error(' 文件创建失败,终止测试');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log('3. 文件内容:');
|
|
31
|
+
console.log(' ' + testContent.replace(/\n/g, '\n '));
|
|
32
|
+
|
|
33
|
+
// 3. 模拟index.js中的runClaudeCommand调用
|
|
34
|
+
console.log('\n4. 模拟Claude命令调用...');
|
|
35
|
+
const prompt = '/simple-code-review ' + testFile;
|
|
36
|
+
console.log(` Prompt: ${prompt}`);
|
|
37
|
+
|
|
38
|
+
// 模拟runClaudeCommand函数
|
|
39
|
+
const claudeResult = await runClaudeCommandSim(prompt);
|
|
40
|
+
console.log(`\n5. Claude返回结果长度: ${claudeResult.length}`);
|
|
41
|
+
console.log(` 结果预览: ${claudeResult.substring(0, 200)}...`);
|
|
42
|
+
|
|
43
|
+
// 6. 检查结果是否包含预期的标记
|
|
44
|
+
const hasReportMarker = claudeResult.includes('🤖 AI代码审查报告');
|
|
45
|
+
const hasReportTags = claudeResult.includes('<REPORT>') && claudeResult.includes('</REPORT>');
|
|
46
|
+
|
|
47
|
+
console.log(`\n6. 检查结果内容:`);
|
|
48
|
+
console.log(` 包含"🤖 AI代码审查报告": ${hasReportMarker}`);
|
|
49
|
+
console.log(` 包含REPORT标签: ${hasReportTags}`);
|
|
50
|
+
|
|
51
|
+
// 7. 模拟extractReportContent函数
|
|
52
|
+
const extractedContent = extractReportContent(claudeResult);
|
|
53
|
+
console.log(`\n7. 提取的内容长度: ${extractedContent.length}`);
|
|
54
|
+
console.log(` 提取内容预览: ${extractedContent.substring(0, 200)}...`);
|
|
55
|
+
|
|
56
|
+
// 8. 清理文件
|
|
57
|
+
try {
|
|
58
|
+
fs.unlinkSync(testFile);
|
|
59
|
+
console.log(`\n8. 清理测试文件: ${testFile}`);
|
|
60
|
+
} catch (error) {
|
|
61
|
+
console.error(` 清理文件失败: ${error.message}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
console.log('\n=== 测试完成 ===');
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// 模拟runClaudeCommand函数(在GitLab CI环境中)
|
|
68
|
+
function runClaudeCommandSim(promptContent) {
|
|
69
|
+
return new Promise((resolve, reject) => {
|
|
70
|
+
console.log(` 启动Claude命令: claude -p "${promptContent}"`);
|
|
71
|
+
|
|
72
|
+
// 注意:在这里cwd设置为__dirname,正如index.js中所做的
|
|
73
|
+
const claudeProcess = spawn('claude', ['-p', promptContent], {
|
|
74
|
+
shell: true,
|
|
75
|
+
cwd: __dirname, // 与index.js中相同
|
|
76
|
+
env: process.env,
|
|
77
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
let stdout = '';
|
|
81
|
+
let stderr = '';
|
|
82
|
+
|
|
83
|
+
claudeProcess.stdout.on('data', (data) => {
|
|
84
|
+
const str = data.toString();
|
|
85
|
+
stdout += str;
|
|
86
|
+
console.log(` [STDOUT] 接收 ${str.length} 字符`);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
claudeProcess.stderr.on('data', (data) => {
|
|
90
|
+
const str = data.toString();
|
|
91
|
+
stderr += str;
|
|
92
|
+
console.log(` [STDERR] 接收 ${str.length} 字符: ${str.substring(0, 100)}...`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
claudeProcess.on('close', (code) => {
|
|
96
|
+
console.log(` Claude进程退出,代码: ${code}`);
|
|
97
|
+
console.log(` 总输出长度: ${stdout.length}`);
|
|
98
|
+
|
|
99
|
+
// 根据退出码判断是否成功
|
|
100
|
+
if (code !== 0) {
|
|
101
|
+
console.log(` Claude命令执行失败,退出码: ${code}`);
|
|
102
|
+
console.log(` 错误输出: ${stderr || '(无错误输出)'}`);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
resolve(stdout.trim());
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
claudeProcess.on('error', (error) => {
|
|
109
|
+
console.log(` Claude进程启动失败: ${error.message}`);
|
|
110
|
+
resolve(''); // 即使错误也返回空字符串
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
// 提取REPORT标签内容的函数(来自utils.js)
|
|
116
|
+
function extractReportContent(text) {
|
|
117
|
+
const reportRegex = /<REPORT>([\s\S]*?)<\/REPORT>/;
|
|
118
|
+
const match = text.match(reportRegex);
|
|
119
|
+
return match ? match[1].trim() : text;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// 运行测试
|
|
123
|
+
testClaudeWithFile().catch(err => {
|
|
124
|
+
console.error('测试过程中发生错误:', err);
|
|
125
|
+
});
|
package/test_filepath.js
ADDED
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// 测试文件路径拼接和Claude命令处理
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawn } = require('child_process');
|
|
5
|
+
|
|
6
|
+
// 模拟创建临时文件并测试路径
|
|
7
|
+
function testFilePathHandling() {
|
|
8
|
+
console.log('=== 测试文件路径拼接和Claude命令处理 ===\n');
|
|
9
|
+
|
|
10
|
+
// 模拟临时文件创建
|
|
11
|
+
const timestamp = Date.now();
|
|
12
|
+
const blockIndex = 0;
|
|
13
|
+
const tmpFileName = `./temp-diff-block-${timestamp}-${blockIndex}.diff`;
|
|
14
|
+
|
|
15
|
+
console.log(`1. 生成的临时文件名: ${tmpFileName}`);
|
|
16
|
+
|
|
17
|
+
// 检查相对路径是否相对于当前工作目录
|
|
18
|
+
const fullPath = path.resolve(tmpFileName);
|
|
19
|
+
console.log(`2. 完整路径: ${fullPath}`);
|
|
20
|
+
|
|
21
|
+
// 写入一些示例内容
|
|
22
|
+
const sampleDiff = `diff --git a/test.js b/test.js
|
|
23
|
+
index 1234567..8901234 100644
|
|
24
|
+
--- a/test.js
|
|
25
|
+
+++ b/test.js
|
|
26
|
+
@@ -1,3 +1,4 @@
|
|
27
|
+
console.log('hello');
|
|
28
|
+
+console.log('world');
|
|
29
|
+
console.log('test');`;
|
|
30
|
+
|
|
31
|
+
try {
|
|
32
|
+
fs.writeFileSync(tmpFileName, sampleDiff);
|
|
33
|
+
console.log(`3. 临时文件创建成功: ${tmpFileName}`);
|
|
34
|
+
|
|
35
|
+
// 检查文件是否存在
|
|
36
|
+
const exists = fs.existsSync(tmpFileName);
|
|
37
|
+
console.log(`4. 文件存在验证: ${exists}`);
|
|
38
|
+
|
|
39
|
+
// 构建prompt (模拟第198行的代码)
|
|
40
|
+
const prompt = '/simple-code-review' + ' ' + tmpFileName;
|
|
41
|
+
console.log(`5. 构建的prompt: ${prompt}`);
|
|
42
|
+
|
|
43
|
+
// 测试在当前工作目录下是否能找到该文件
|
|
44
|
+
const relativeExists = fs.existsSync(tmpFileName);
|
|
45
|
+
console.log(`6. 相对路径文件存在: ${relativeExists}`);
|
|
46
|
+
|
|
47
|
+
// 清理临时文件
|
|
48
|
+
if(fs.existsSync(tmpFileName)) {
|
|
49
|
+
fs.unlinkSync(tmpFileName);
|
|
50
|
+
console.log(`7. 临时文件已清理`);
|
|
51
|
+
}
|
|
52
|
+
} catch (error) {
|
|
53
|
+
console.error(`错误: ${error.message}`);
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// 测试Claude命令处理文件路径的方式
|
|
58
|
+
function testClaudeFileHandling() {
|
|
59
|
+
console.log('\n=== 测试Claude命令如何处理文件路径 ===\n');
|
|
60
|
+
|
|
61
|
+
// 创建一个真实的临时文件用于测试
|
|
62
|
+
const testFileName = './test_temp_file_for_claude.diff';
|
|
63
|
+
const testContent = 'console.log("test file for claude");';
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
fs.writeFileSync(testFileName, testContent);
|
|
67
|
+
console.log(`1. 创建测试文件: ${testFileName}`);
|
|
68
|
+
|
|
69
|
+
// 检查Claude是否能识别相对路径文件
|
|
70
|
+
console.log(`2. 当前工作目录: ${process.cwd()}`);
|
|
71
|
+
console.log(`3. 文件绝对路径: ${path.resolve(testFileName)}`);
|
|
72
|
+
|
|
73
|
+
// 模拟Claude命令的参数传递
|
|
74
|
+
const prompt = '/simple-code-review ' + testFileName;
|
|
75
|
+
console.log(`4. 模拟的Claude命令参数: ${prompt}`);
|
|
76
|
+
|
|
77
|
+
// 实际上我们不能真正调用Claude命令,但可以检查文件路径的正确性
|
|
78
|
+
|
|
79
|
+
// 清理测试文件
|
|
80
|
+
if(fs.existsSync(testFileName)) {
|
|
81
|
+
fs.unlinkSync(testFileName);
|
|
82
|
+
console.log(`5. 测试文件已清理`);
|
|
83
|
+
}
|
|
84
|
+
} catch (error) {
|
|
85
|
+
console.error(`错误: ${error.message}`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// 运行测试
|
|
90
|
+
testFilePathHandling();
|
|
91
|
+
testClaudeFileHandling();
|
|
92
|
+
|
|
93
|
+
console.log('\n=== 关键发现 ===');
|
|
94
|
+
console.log('1. 代码中使用相对路径 "./temp-diff-block-xxx.diff" 创建临时文件');
|
|
95
|
+
console.log('2. 这些文件在当前工作目录 (index.js所在目录) 中创建');
|
|
96
|
+
console.log('3. 然后将此相对路径传递给Claude命令: "/simple-code-review ./temp-diff-block-xxx.diff"');
|
|
97
|
+
console.log('4. 问题在于Claude CLI是否能在其运行环境中找到这些相对路径的文件');
|
|
98
|
+
console.log('5. 在CI环境中,工作目录、权限和文件访问可能有所不同');
|
|
@@ -0,0 +1,117 @@
|
|
|
1
|
+
// 测试移除CLAUDECODE环境变量后Claude是否能正常工作
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const { spawn } = require('child_process');
|
|
5
|
+
|
|
6
|
+
console.log('=== 测试移除CLAUDECODE环境变量后的Claude命令 ===\n');
|
|
7
|
+
|
|
8
|
+
async function testClaudeWithoutClaudeCodeEnv() {
|
|
9
|
+
// 1. 创建一个测试文件
|
|
10
|
+
const testFile = `./test-no-nested-session-${Date.now()}.js`;
|
|
11
|
+
const testContent = `// 测试文件
|
|
12
|
+
function sampleFunction() {
|
|
13
|
+
console.log("This is a sample function for testing");
|
|
14
|
+
return true;
|
|
15
|
+
}`;
|
|
16
|
+
|
|
17
|
+
console.log(`1. 创建测试文件: ${testFile}`);
|
|
18
|
+
fs.writeFileSync(testFile, testContent);
|
|
19
|
+
|
|
20
|
+
// 2. 验证文件创建
|
|
21
|
+
const exists = fs.existsSync(testFile);
|
|
22
|
+
console.log(`2. 文件创建成功: ${exists}`);
|
|
23
|
+
|
|
24
|
+
if (!exists) {
|
|
25
|
+
console.error(' 文件创建失败,终止测试');
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
// 3. 构造Claude命令,但移除CLAUDECODE环境变量
|
|
30
|
+
console.log('\n3. 模拟移除CLAUDECODE环境变量的Claude命令调用...');
|
|
31
|
+
const prompt = '/simple-code-review ' + testFile;
|
|
32
|
+
console.log(` Prompt: ${prompt}`);
|
|
33
|
+
|
|
34
|
+
// 测试修改后的runClaudeCommand,移除了CLAUDECODE环境变量
|
|
35
|
+
const claudeResult = await runClaudeCommandWithoutClaudeCode(prompt);
|
|
36
|
+
console.log(`\n4. Claude返回结果长度: ${claudeResult.length}`);
|
|
37
|
+
|
|
38
|
+
if (claudeResult.length > 0) {
|
|
39
|
+
console.log(` 结果预览: ${claudeResult.substring(0, 200)}...`);
|
|
40
|
+
} else {
|
|
41
|
+
console.log(' 结果为空');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
// 5. 检查结果内容
|
|
45
|
+
const hasReportMarker = claudeResult.includes('🤖 AI代码审查报告');
|
|
46
|
+
const hasReportTags = claudeResult.includes('<REPORT>') && claudeResult.includes('</REPORT>');
|
|
47
|
+
|
|
48
|
+
console.log(`\n5. 检查结果内容:`);
|
|
49
|
+
console.log(` 包含"🤖 AI代码审查报告": ${hasReportMarker}`);
|
|
50
|
+
console.log(` 包含REPORT标签: ${hasReportTags}`);
|
|
51
|
+
|
|
52
|
+
// 6. 清理文件
|
|
53
|
+
try {
|
|
54
|
+
fs.unlinkSync(testFile);
|
|
55
|
+
console.log(`\n6. 清理测试文件: ${testFile}`);
|
|
56
|
+
} catch (error) {
|
|
57
|
+
console.error(` 清理文件失败: ${error.message}`);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
console.log('\n=== 测试完成 ===');
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
// 修改版runClaudeCommand函数,移除CLAUDECODE环境变量
|
|
64
|
+
function runClaudeCommandWithoutClaudeCode(promptContent) {
|
|
65
|
+
return new Promise((resolve, reject) => {
|
|
66
|
+
console.log(` 启动Claude命令 (移除CLAUDECODE环境变量): claude -p "${promptContent}"`);
|
|
67
|
+
|
|
68
|
+
// 创建一个新的环境变量副本,移除CLAUDECODE
|
|
69
|
+
const modifiedEnv = { ...process.env };
|
|
70
|
+
delete modifiedEnv.CLAUDECODE;
|
|
71
|
+
delete modifiedEnv.CLAUDE_CODE_ENTRYPOINT;
|
|
72
|
+
|
|
73
|
+
const claudeProcess = spawn('claude', ['-p', promptContent], {
|
|
74
|
+
shell: true,
|
|
75
|
+
cwd: __dirname, // 与index.js中相同
|
|
76
|
+
env: modifiedEnv, // 关键:移除了CLAUDECODE的环境变量
|
|
77
|
+
stdio: ['ignore', 'pipe', 'pipe']
|
|
78
|
+
});
|
|
79
|
+
|
|
80
|
+
let stdout = '';
|
|
81
|
+
let stderr = '';
|
|
82
|
+
|
|
83
|
+
claudeProcess.stdout.on('data', (data) => {
|
|
84
|
+
const str = data.toString();
|
|
85
|
+
stdout += str;
|
|
86
|
+
console.log(` [STDOUT] 接收 ${str.length} 字符`);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
claudeProcess.stderr.on('data', (data) => {
|
|
90
|
+
const str = data.toString();
|
|
91
|
+
stderr += str;
|
|
92
|
+
console.log(` [STDERR] 接收 ${str.length} 字符: ${str.substring(0, 100)}...`);
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
claudeProcess.on('close', (code) => {
|
|
96
|
+
console.log(` Claude进程退出,代码: ${code}`);
|
|
97
|
+
console.log(` 总输出长度: ${stdout.length}`);
|
|
98
|
+
|
|
99
|
+
if (code !== 0) {
|
|
100
|
+
console.log(` Claude命令执行失败,退出码: ${code}`);
|
|
101
|
+
console.log(` 错误输出: ${stderr || '(无错误输出)'}`);
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
resolve(stdout.trim());
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
claudeProcess.on('error', (error) => {
|
|
108
|
+
console.log(` Claude进程启动失败: ${error.message}`);
|
|
109
|
+
resolve(''); // 即使错误也返回空字符串
|
|
110
|
+
});
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// 运行测试
|
|
115
|
+
testClaudeWithoutClaudeCodeEnv().catch(err => {
|
|
116
|
+
console.error('测试过程中发生错误:', err);
|
|
117
|
+
});
|