@d5render/cli 0.1.16 → 0.1.22
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/.skills/review/SKILL.md +2 -3
- package/.skills/review/version +1 -1
- package/bin/copilot.js +52 -63
- package/bin/d5cli +64 -27
- package/package.json +3 -3
package/.skills/review/SKILL.md
CHANGED
|
@@ -6,6 +6,5 @@ description: When the task is code-review, please follow this document to procee
|
|
|
6
6
|
1. read file [review.instructions.md](./review.instructions.md).
|
|
7
7
|
2. find all Markdown resumes within the project and their basic understanding of the project.
|
|
8
8
|
3. integrate your understanding of code-review to process task.
|
|
9
|
-
4.
|
|
10
|
-
5.
|
|
11
|
-
6. output all the context read, especially the introductory document.
|
|
9
|
+
4. the merge request is only for change reference and is not the main objective of the review; therefore, it does not require in-depth analysis.
|
|
10
|
+
5. pay attention to the issue tracking description in the context, and try to use relevant tools to obtain more context.
|
package/.skills/review/version
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
0.0.
|
|
1
|
+
0.0.2
|
package/bin/copilot.js
CHANGED
|
@@ -18918,10 +18918,6 @@ const getCommits = () => {
|
|
|
18918
18918
|
text: `latest commit`
|
|
18919
18919
|
}] };
|
|
18920
18920
|
};
|
|
18921
|
-
const canIReview = ({ B }) => ({ content: [{
|
|
18922
|
-
type: "text",
|
|
18923
|
-
text: B.startsWith("Merge") ? "no" : "yes"
|
|
18924
|
-
}] });
|
|
18925
18921
|
const getMergeInfomation = () => {
|
|
18926
18922
|
const { CI_MERGE_REQUEST_DESCRIPTION, CI_MERGE_REQUEST_TITLE } = envUsed;
|
|
18927
18923
|
if (CI_MERGE_REQUEST_DESCRIPTION || CI_MERGE_REQUEST_TITLE) return { content: [{
|
|
@@ -18937,22 +18933,10 @@ const getMergeInfomation = () => {
|
|
|
18937
18933
|
};
|
|
18938
18934
|
};
|
|
18939
18935
|
|
|
18940
|
-
//#endregion
|
|
18941
|
-
//#region packages/gitlab/schema.ts
|
|
18942
|
-
const canireview = "can-i-review";
|
|
18943
|
-
const canireviewSchema = {
|
|
18944
|
-
hash: string().describe("commit hash"),
|
|
18945
|
-
B: string().describe("the commit directions logged by `git log --format=%B -n 1 <hash>`")
|
|
18946
|
-
};
|
|
18947
|
-
|
|
18948
18936
|
//#endregion
|
|
18949
18937
|
//#region packages/gitlab/index.ts
|
|
18950
18938
|
function install$2(server$1) {
|
|
18951
18939
|
server$1.registerTool(getHash, { description: noMandatory }, getCommits);
|
|
18952
|
-
server$1.registerTool(canireview, {
|
|
18953
|
-
inputSchema: canireviewSchema,
|
|
18954
|
-
description: "Determine whether the commit with the given hash needs to be reviewed based on its commit message."
|
|
18955
|
-
}, canIReview);
|
|
18956
18940
|
server$1.registerTool("getMergeDescription", {
|
|
18957
18941
|
title: "merge pipeline description",
|
|
18958
18942
|
description: "When review task from `merge pipeline`, get the merge request description."
|
|
@@ -19043,9 +19027,9 @@ const reportSchema = {
|
|
|
19043
19027
|
summary: array(string().describe(one)).optional().describe("Regarding the description of the current review, please summarize the main logic of the submission as concisely as possible."),
|
|
19044
19028
|
issues: array(object({
|
|
19045
19029
|
severity: string().optional().describe("Bug severity levels, such as CRITICAL, HIGH, MEDIUM, LOW."),
|
|
19046
|
-
|
|
19030
|
+
commitTitle: string().describe("The commit title associated with the issue"),
|
|
19031
|
+
commitAuthor: string().describe("The commit latest author associated with the issue"),
|
|
19047
19032
|
commitSha: string().optional().describe("The commit SHA associated with the issue"),
|
|
19048
|
-
commitTitle: string().optional().describe("The commit title associated with the issue"),
|
|
19049
19033
|
title: string().optional().describe("A short title for the issue"),
|
|
19050
19034
|
details: array(string()).optional().describe("Details about the issue"),
|
|
19051
19035
|
suggestions: array(string()).optional().describe("Improvement suggestion"),
|
|
@@ -19062,6 +19046,29 @@ const reportSchema = {
|
|
|
19062
19046
|
})).optional().describe("After gaining a comprehensive understanding of the files involved in the commits, propose suggestions for code corrections beyond the diff.")
|
|
19063
19047
|
};
|
|
19064
19048
|
|
|
19049
|
+
//#endregion
|
|
19050
|
+
//#region packages/message/sendding.ts
|
|
19051
|
+
async function sendding(title, text) {
|
|
19052
|
+
if (!envUsed.DINGTALK_WEBHOOK) throw new Error("non DINGTALK_WEBHOOK");
|
|
19053
|
+
let res = new Response();
|
|
19054
|
+
for (const url of envUsed.DINGTALK_WEBHOOK.split(",")) res = await fetch(url, {
|
|
19055
|
+
method: "POST",
|
|
19056
|
+
headers: { "Content-Type": "application/json" },
|
|
19057
|
+
body: JSON.stringify({
|
|
19058
|
+
msgtype: "markdown",
|
|
19059
|
+
markdown: {
|
|
19060
|
+
title,
|
|
19061
|
+
text
|
|
19062
|
+
},
|
|
19063
|
+
at: {
|
|
19064
|
+
atMobiles: ["17856104313"],
|
|
19065
|
+
isAtAll: false
|
|
19066
|
+
}
|
|
19067
|
+
})
|
|
19068
|
+
});
|
|
19069
|
+
return res;
|
|
19070
|
+
}
|
|
19071
|
+
|
|
19065
19072
|
//#endregion
|
|
19066
19073
|
//#region packages/message/report.ts
|
|
19067
19074
|
const lastComment = { value: {} };
|
|
@@ -19102,23 +19109,6 @@ function distReports(input) {
|
|
|
19102
19109
|
const mergeURL = pipelineMerge();
|
|
19103
19110
|
const linkBase = visitCommit();
|
|
19104
19111
|
const commitsURL = commits();
|
|
19105
|
-
for (const issue$1 of issues) {
|
|
19106
|
-
const { file: file$1 = "NON", commitSha = "", severity = "NON", commitSha: NCommitSha = "NON" } = issue$1;
|
|
19107
|
-
const fileList = fileMap.get(file$1) || [], issueList = severityMap.get(severity) || [];
|
|
19108
|
-
fileList.push(issue$1);
|
|
19109
|
-
fileMap.set(file$1, fileList);
|
|
19110
|
-
issueList.push(issue$1);
|
|
19111
|
-
severityMap.set(severity, issueList);
|
|
19112
|
-
if (commitSha) commitsSet.add(commitSha);
|
|
19113
|
-
commitsMap.set(NCommitSha, issue$1);
|
|
19114
|
-
distCommitComments(issue$1);
|
|
19115
|
-
}
|
|
19116
|
-
let gitlabReportMessage = `## 📖 ${title}\n`;
|
|
19117
|
-
if (summary && summary.length > 0) gitlabReportMessage += `> ${summary.join(" \n> ")}\n\n`;
|
|
19118
|
-
if (risks.length > 0) gitlabReportMessage += "\n**📋 主要风险**\n - " + risks.join("\n - ");
|
|
19119
|
-
gitlabReportMessage += `\n### 🐛 问题列表`;
|
|
19120
|
-
const cms = [...commitsSet].map((v) => `[${v.slice(0, 8)}](${linkBase}/${v})`);
|
|
19121
|
-
if (cms.length > 0) gitlabReportMessage += `\n-----\n> 含问题的commits:${cms.join(",")}\n\n`;
|
|
19122
19112
|
function distCommitComments({ file: file$1, commitSha, severity = "NON", line = "", details = [], suggestions: suggestions$1 = [], codeExample = "" }) {
|
|
19123
19113
|
if (commitSha && file$1) {
|
|
19124
19114
|
const lines = line.split(",").map((line$1) => {
|
|
@@ -19134,14 +19124,33 @@ function distReports(input) {
|
|
|
19134
19124
|
});
|
|
19135
19125
|
}
|
|
19136
19126
|
}
|
|
19137
|
-
for (const
|
|
19138
|
-
|
|
19139
|
-
|
|
19140
|
-
|
|
19141
|
-
|
|
19142
|
-
|
|
19143
|
-
|
|
19144
|
-
|
|
19127
|
+
for (const issue$1 of issues) {
|
|
19128
|
+
const { file: file$1 = "NON", commitSha = "", severity = "NON", commitSha: NCommitSha = "NON" } = issue$1;
|
|
19129
|
+
const fileList = fileMap.get(file$1) || [], issueList = severityMap.get(severity) || [];
|
|
19130
|
+
fileList.push(issue$1);
|
|
19131
|
+
fileMap.set(file$1, fileList);
|
|
19132
|
+
issueList.push(issue$1);
|
|
19133
|
+
severityMap.set(severity, issueList);
|
|
19134
|
+
if (commitSha) commitsSet.add(commitSha);
|
|
19135
|
+
commitsMap.set(NCommitSha, issue$1);
|
|
19136
|
+
distCommitComments(issue$1);
|
|
19137
|
+
}
|
|
19138
|
+
let gitlabReportMessage = `## 📖 ${title}\n`;
|
|
19139
|
+
if (summary && summary.length > 0) gitlabReportMessage += `> ${summary.join(" \n> ")}\n\n`;
|
|
19140
|
+
if (risks.length > 0) gitlabReportMessage += "\n**📋 主要风险**\n - " + risks.join("\n - ");
|
|
19141
|
+
if (fileMap.size > 0 || commitsSet.size > 0) {
|
|
19142
|
+
gitlabReportMessage += `\n### 🐛 问题列表`;
|
|
19143
|
+
const cms = [...commitsSet].map((v) => `[${v.slice(0, 8)}](${linkBase}/${v})`);
|
|
19144
|
+
if (cms.length > 0) gitlabReportMessage += `\n-----\n> 含问题的commits:${cms.join(",")}\n\n`;
|
|
19145
|
+
for (const [file$1, fileIssues] of fileMap) {
|
|
19146
|
+
gitlabReportMessage += `\n-----\n\n#### 文件: ${file$1}`;
|
|
19147
|
+
for (const issue$1 of fileIssues) {
|
|
19148
|
+
const { severity = "NON", line = "NON", title: issueTitle = "NON", details = [], suggestions: issueSuggestions = [], codeExample = "" } = issue$1;
|
|
19149
|
+
gitlabReportMessage += `\n\n**${severity}** | ${line} | ${issueTitle}`;
|
|
19150
|
+
gitlabReportMessage += `\n- 详情:\n - ${details.join("\n - ")}`;
|
|
19151
|
+
gitlabReportMessage += `\n- 建议:\n - ${issueSuggestions.join("\n - ")}`;
|
|
19152
|
+
if (codeExample) gitlabReportMessage += `\n${toCode(codeExample)}\n`;
|
|
19153
|
+
}
|
|
19145
19154
|
}
|
|
19146
19155
|
}
|
|
19147
19156
|
if (suggestions.length > 0) {
|
|
@@ -19243,26 +19252,6 @@ function toCode(code$1) {
|
|
|
19243
19252
|
const ct = code$1.trim();
|
|
19244
19253
|
return ct.startsWith("```") && ct.endsWith("```") ? code$1 : `\`\`\`\n${code$1}\n\`\`\``;
|
|
19245
19254
|
}
|
|
19246
|
-
async function sendding(title, text) {
|
|
19247
|
-
if (!envUsed.DINGTALK_WEBHOOK) throw new Error("non DINGTALK_WEBHOOK");
|
|
19248
|
-
let res = new Response();
|
|
19249
|
-
for (const url of envUsed.DINGTALK_WEBHOOK.split(",")) res = await fetch(url, {
|
|
19250
|
-
method: "POST",
|
|
19251
|
-
headers: { "Content-Type": "application/json" },
|
|
19252
|
-
body: JSON.stringify({
|
|
19253
|
-
msgtype: "markdown",
|
|
19254
|
-
markdown: {
|
|
19255
|
-
title,
|
|
19256
|
-
text
|
|
19257
|
-
},
|
|
19258
|
-
at: {
|
|
19259
|
-
atMobiles: ["17856104313"],
|
|
19260
|
-
isAtAll: false
|
|
19261
|
-
}
|
|
19262
|
-
})
|
|
19263
|
-
});
|
|
19264
|
-
return res;
|
|
19265
|
-
}
|
|
19266
19255
|
|
|
19267
19256
|
//#endregion
|
|
19268
19257
|
//#region packages/message/index.ts
|
package/bin/d5cli
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { execSync, spawn } from "node:child_process";
|
|
3
|
-
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
3
|
+
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from "node:fs";
|
|
4
4
|
import { dirname, join } from "node:path";
|
|
5
5
|
import { argv, env, exit, platform } from "node:process";
|
|
6
6
|
import { fileURLToPath } from "node:url";
|
|
7
7
|
|
|
8
8
|
//#region package.json
|
|
9
9
|
var name$1 = "@d5render/cli";
|
|
10
|
-
var version = "0.1.
|
|
10
|
+
var version = "0.1.22";
|
|
11
11
|
|
|
12
12
|
//#endregion
|
|
13
13
|
//#region copilot/server/config.ts
|
|
@@ -60,6 +60,29 @@ function buildEnv() {
|
|
|
60
60
|
return envJson$1;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
+
//#endregion
|
|
64
|
+
//#region packages/message/sendding.ts
|
|
65
|
+
async function sendding(title, text) {
|
|
66
|
+
if (!envUsed.DINGTALK_WEBHOOK) throw new Error("non DINGTALK_WEBHOOK");
|
|
67
|
+
let res = new Response();
|
|
68
|
+
for (const url of envUsed.DINGTALK_WEBHOOK.split(",")) res = await fetch(url, {
|
|
69
|
+
method: "POST",
|
|
70
|
+
headers: { "Content-Type": "application/json" },
|
|
71
|
+
body: JSON.stringify({
|
|
72
|
+
msgtype: "markdown",
|
|
73
|
+
markdown: {
|
|
74
|
+
title,
|
|
75
|
+
text
|
|
76
|
+
},
|
|
77
|
+
at: {
|
|
78
|
+
atMobiles: ["17856104313"],
|
|
79
|
+
isAtAll: false
|
|
80
|
+
}
|
|
81
|
+
})
|
|
82
|
+
});
|
|
83
|
+
return res;
|
|
84
|
+
}
|
|
85
|
+
|
|
63
86
|
//#endregion
|
|
64
87
|
//#region copilot/bin/install.ts
|
|
65
88
|
function install() {
|
|
@@ -142,10 +165,13 @@ const commits = () => {
|
|
|
142
165
|
|
|
143
166
|
//#endregion
|
|
144
167
|
//#region copilot/bin/utils.ts
|
|
145
|
-
const
|
|
168
|
+
const HOME = env.HOME ?? env.HOMEPATH;
|
|
169
|
+
const root = HOME ?? env.LOCALAPPDATA;
|
|
146
170
|
if (!root) throw new Error("cannot find home directory");
|
|
147
171
|
const cwd = join(dirname(fileURLToPath(import.meta.url)), "../");
|
|
148
172
|
function deploy() {
|
|
173
|
+
const config = join(HOME, ".copilot/config.json");
|
|
174
|
+
if (existsSync(config)) rmSync(config);
|
|
149
175
|
const dir = join(root, ".copilot/skills/codereview");
|
|
150
176
|
if (!existsSync(dir)) mkdirSync(dir, { recursive: true });
|
|
151
177
|
const skillRoot = join(cwd, ".skills/review");
|
|
@@ -194,31 +220,42 @@ function need() {
|
|
|
194
220
|
|
|
195
221
|
//#endregion
|
|
196
222
|
//#region copilot/bin/index.ts
|
|
197
|
-
|
|
223
|
+
try {
|
|
224
|
+
main();
|
|
225
|
+
} catch (error) {
|
|
226
|
+
sendding("CRITICAL", "未知错误,请自行检查日志");
|
|
227
|
+
throw error;
|
|
228
|
+
}
|
|
229
|
+
function main() {
|
|
230
|
+
const prompt = `Load skills, then call the mcp tool '${name}-${getHash}' to load code-review commits, if the task encounters an error, throw that.
|
|
198
231
|
Otherwise, use chinese as default language to call the mcp tool '${name}-${report}'`;
|
|
199
|
-
deploy();
|
|
200
|
-
if (need()) {
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
232
|
+
deploy();
|
|
233
|
+
if (need()) {
|
|
234
|
+
install();
|
|
235
|
+
const copilot = spawn("node", [
|
|
236
|
+
findCopilopt(),
|
|
237
|
+
...tools,
|
|
238
|
+
"--stream",
|
|
239
|
+
"off",
|
|
240
|
+
"-p",
|
|
241
|
+
prompt
|
|
242
|
+
], {
|
|
243
|
+
cwd: env.CI_PROJECT_DIR,
|
|
244
|
+
stdio: [
|
|
245
|
+
"inherit",
|
|
246
|
+
"pipe",
|
|
247
|
+
"pipe"
|
|
248
|
+
],
|
|
249
|
+
...platform === "win32" && { windowsHide: true }
|
|
250
|
+
});
|
|
251
|
+
copilot.stdout.on("data", (chunk) => console.log(String(chunk)));
|
|
252
|
+
copilot.stderr.on("data", (chunk) => console.error(String(chunk)));
|
|
253
|
+
copilot.on("close", (code) => {
|
|
254
|
+
sendding("CRITICAL", "Copilot 运行过程发生错误,请自行检查日志");
|
|
255
|
+
exit(code);
|
|
256
|
+
});
|
|
257
|
+
} else console.log("重复提交,进程跳过");
|
|
258
|
+
}
|
|
222
259
|
function findCopilopt() {
|
|
223
260
|
let copilot = execSync("npm list @github/copilot -g -p").toString().trim();
|
|
224
261
|
if (!copilot) {
|
package/package.json
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "jasirou",
|
|
6
6
|
"main": "./bin/d5cli",
|
|
7
|
-
"version": "0.1.
|
|
7
|
+
"version": "0.1.22",
|
|
8
8
|
"devDependencies": {
|
|
9
9
|
"@modelcontextprotocol/sdk": "^1.25.1",
|
|
10
10
|
"@types/node": "^25.0.3",
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
},
|
|
28
28
|
"scripts": {
|
|
29
29
|
"build:copilot": "node ./setup.js build",
|
|
30
|
-
"
|
|
31
|
-
"
|
|
30
|
+
"release": "node ./setup.js publish",
|
|
31
|
+
"setup": "node ./setup.js"
|
|
32
32
|
}
|
|
33
33
|
}
|