@d5render/cli 0.1.85 → 0.1.86
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 +35 -35
- package/bin/d5cli +28 -65
- package/bin/mcpServer.js +148 -148
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,35 +1,35 @@
|
|
|
1
|
-
> 参考 [.skills/devops](.skills/devops) 对项目进行初始化
|
|
2
|
-
|
|
3
|
-
> .github/\* 是相关技能的自定义的部分,建议自行放在项目文件夹内,review脚本会自动部署在~/.claude/skills(.claude适配的CLI比较多)内
|
|
4
|
-
|
|
5
|
-
# CHANGELOG
|
|
6
|
-
|
|
7
|
-
### 2026-3-18
|
|
8
|
-
|
|
9
|
-
🚩 cli
|
|
10
|
-
|
|
11
|
-
- 功能更新
|
|
12
|
-
- 报告添加回流功能
|
|
13
|
-
|
|
14
|
-
🚩 skills
|
|
15
|
-
|
|
16
|
-
- 多agent审查
|
|
17
|
-
- 启动LSP等辅助工具
|
|
18
|
-
|
|
19
|
-
### 2026-1-31
|
|
20
|
-
|
|
21
|
-
code-review skill 补充LSP相关语句
|
|
22
|
-
|
|
23
|
-
### 2026-1-16
|
|
24
|
-
|
|
25
|
-
补充安全相关检查
|
|
26
|
-
|
|
27
|
-
### 2026-1-7
|
|
28
|
-
|
|
29
|
-
代码评审 skills 更新
|
|
30
|
-
|
|
31
|
-
使用内置 skills
|
|
32
|
-
|
|
33
|
-
### 2025-12-31
|
|
34
|
-
|
|
35
|
-
基础评审能力上云
|
|
1
|
+
> 参考 [.skills/devops](.skills/devops) 对项目进行初始化
|
|
2
|
+
|
|
3
|
+
> .github/\* 是相关技能的自定义的部分,建议自行放在项目文件夹内,review脚本会自动部署在~/.claude/skills(.claude适配的CLI比较多)内
|
|
4
|
+
|
|
5
|
+
# CHANGELOG
|
|
6
|
+
|
|
7
|
+
### 2026-3-18
|
|
8
|
+
|
|
9
|
+
🚩 cli
|
|
10
|
+
|
|
11
|
+
- 功能更新
|
|
12
|
+
- 报告添加回流功能
|
|
13
|
+
|
|
14
|
+
🚩 skills
|
|
15
|
+
|
|
16
|
+
- 多agent审查
|
|
17
|
+
- 启动LSP等辅助工具
|
|
18
|
+
|
|
19
|
+
### 2026-1-31
|
|
20
|
+
|
|
21
|
+
code-review skill 补充LSP相关语句
|
|
22
|
+
|
|
23
|
+
### 2026-1-16
|
|
24
|
+
|
|
25
|
+
补充安全相关检查
|
|
26
|
+
|
|
27
|
+
### 2026-1-7
|
|
28
|
+
|
|
29
|
+
代码评审 skills 更新
|
|
30
|
+
|
|
31
|
+
使用内置 skills
|
|
32
|
+
|
|
33
|
+
### 2025-12-31
|
|
34
|
+
|
|
35
|
+
基础评审能力上云
|
package/bin/d5cli
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { argv, env, platform } from "node:process";
|
|
3
|
-
import { execSync, spawn
|
|
3
|
+
import { execSync, spawn } from "node:child_process";
|
|
4
4
|
import { createHash } from "node:crypto";
|
|
5
5
|
import { copyFileSync, existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
|
|
6
6
|
import { dirname, join } from "node:path";
|
|
@@ -8,7 +8,7 @@ import { fileURLToPath } from "node:url";
|
|
|
8
8
|
|
|
9
9
|
//#region package.json
|
|
10
10
|
var name$1 = "@d5render/cli";
|
|
11
|
-
var version = "0.1.
|
|
11
|
+
var version = "0.1.86";
|
|
12
12
|
|
|
13
13
|
//#endregion
|
|
14
14
|
//#region packages/env.ts
|
|
@@ -147,7 +147,7 @@ function deploySkills(SKILLS_DIR = ".copilot/skills") {
|
|
|
147
147
|
if (!HOME) throw new Error("cannot find `USERPROFILE` directory");
|
|
148
148
|
const dir = join(HOME, `${SKILLS_DIR}/code-review`);
|
|
149
149
|
mkdirSync(dir, { recursive: true });
|
|
150
|
-
console.log("deploy code-review skills..."
|
|
150
|
+
console.log("deploy code-review skills...");
|
|
151
151
|
const skillRoot = join(RUNTIME_CWD, ".skills/code-review");
|
|
152
152
|
readdirSync(skillRoot).forEach((file) => copyFileSync(join(skillRoot, file), join(dir, file)));
|
|
153
153
|
const instructionsRoot = join(RUNTIME_CWD, ".github/instructions");
|
|
@@ -208,9 +208,10 @@ const COPILOT_HEADERS = {
|
|
|
208
208
|
"Editor-Plugin-Version": "copilot-chat/0.35.0",
|
|
209
209
|
"Copilot-Integration-Id": "vscode-chat"
|
|
210
210
|
};
|
|
211
|
-
function getOAuthToken() {
|
|
211
|
+
function getOAuthToken(setKey) {
|
|
212
212
|
const token = env.GITHUB_COPILOT_TOKEN || env.COPILOT_TOKEN || env.GITHUB_TOKEN || env.GH_TOKEN;
|
|
213
213
|
if (!token) throw new Error("未找到 GitHub Token,请设置 GITHUB_COPILOT_TOKEN / GITHUB_TOKEN / GH_TOKEN 环境变量");
|
|
214
|
+
if (setKey) env[setKey] = token;
|
|
214
215
|
return token;
|
|
215
216
|
}
|
|
216
217
|
/**
|
|
@@ -230,8 +231,8 @@ async function exchangeForCopilotToken(oauthToken) {
|
|
|
230
231
|
return;
|
|
231
232
|
}
|
|
232
233
|
}
|
|
233
|
-
async function fetchInternalUsage() {
|
|
234
|
-
const oauthToken = getOAuthToken();
|
|
234
|
+
async function fetchInternalUsage(options = {}) {
|
|
235
|
+
const oauthToken = getOAuthToken(options.token);
|
|
235
236
|
const directRes = await fetch(`${GITHUB_API}/copilot_internal/user`, { headers: {
|
|
236
237
|
Accept: "application/json",
|
|
237
238
|
Authorization: `token ${oauthToken}`,
|
|
@@ -269,7 +270,7 @@ function formatInternalResult(data) {
|
|
|
269
270
|
*/
|
|
270
271
|
async function getCopilotUsage(options = {}) {
|
|
271
272
|
try {
|
|
272
|
-
return formatInternalResult(await fetchInternalUsage());
|
|
273
|
+
return formatInternalResult(await fetchInternalUsage(options));
|
|
273
274
|
} catch {
|
|
274
275
|
return null;
|
|
275
276
|
}
|
|
@@ -278,7 +279,6 @@ async function getCopilotUsage(options = {}) {
|
|
|
278
279
|
//#endregion
|
|
279
280
|
//#region review/copilot/deploy.ts
|
|
280
281
|
const config = join(dirname(fileURLToPath(import.meta.url)), "copilot-mcp.json");
|
|
281
|
-
console.log("config:", config);
|
|
282
282
|
const tools = [
|
|
283
283
|
"--additional-mcp-config",
|
|
284
284
|
platform === "win32" ? `"@${config}"` : `@${config}`,
|
|
@@ -295,9 +295,9 @@ const tools = [
|
|
|
295
295
|
async function deploy() {
|
|
296
296
|
if (!env.CI) return;
|
|
297
297
|
await changelog();
|
|
298
|
-
execSync("npm i -g @github/copilot@latest --registry=https://registry.npmmirror.com", { stdio: "inherit" });
|
|
299
298
|
deploySkills();
|
|
300
|
-
|
|
299
|
+
execSync("npm i -g @github/copilot@latest --registry=https://registry.npmmirror.com", { stdio: "inherit" });
|
|
300
|
+
const token = await getCopilotUsage({ token: "GH_TOKEN" });
|
|
301
301
|
env["TOKEN_USAGE"] = String(token);
|
|
302
302
|
console.log("deploy customized config...");
|
|
303
303
|
writeFileSync(config, JSON.stringify({ mcpServers: { [name]: {
|
|
@@ -310,84 +310,47 @@ async function deploy() {
|
|
|
310
310
|
|
|
311
311
|
//#endregion
|
|
312
312
|
//#region review/copilot/index.ts
|
|
313
|
-
const
|
|
314
|
-
const verifyPrompt = "Reply with OK only, no other text.";
|
|
315
|
-
/** 单引号包裹并转义,用于 shell 内联,避免子进程 env 被改写 */
|
|
316
|
-
function shellEscape(val) {
|
|
317
|
-
return `'${val.replace(/'/g, "'\\''")}'`;
|
|
318
|
-
}
|
|
319
|
-
/** 最简 copilot 调用(仅 -p),用于验证登录/env 是否可用 */
|
|
320
|
-
function runVerifySync() {
|
|
321
|
-
const verifyArgs = ["-p", verifyPrompt];
|
|
322
|
-
const opts = {
|
|
323
|
-
cwd: env.CI_PROJECT_DIR,
|
|
324
|
-
encoding: "utf8"
|
|
325
|
-
};
|
|
326
|
-
if (platform === "win32") {
|
|
327
|
-
const r = spawnSync(bind, verifyArgs, {
|
|
328
|
-
...opts,
|
|
329
|
-
shell: true
|
|
330
|
-
});
|
|
331
|
-
return {
|
|
332
|
-
code: r.status ?? -1,
|
|
333
|
-
out: r.stdout?.toString() ?? "",
|
|
334
|
-
err: r.stderr?.toString() ?? ""
|
|
335
|
-
};
|
|
336
|
-
}
|
|
337
|
-
const token = env.COPILOT_GITHUB_TOKEN || env.GH_TOKEN || env.GITHUB_TOKEN || env.GITHUB_COPILOT_TOKEN;
|
|
338
|
-
const r = spawnSync("sh", ["-c", `${token !== void 0 && token !== "" ? `export COPILOT_GITHUB_TOKEN=${shellEscape(token)} GH_TOKEN=${shellEscape(token)} GITHUB_TOKEN=${shellEscape(token)}; ` : ""}exec ${bind} ${verifyArgs.map((a) => shellEscape(a)).join(" ")}`], {
|
|
339
|
-
...opts,
|
|
340
|
-
env
|
|
341
|
-
});
|
|
342
|
-
return {
|
|
343
|
-
code: r.status ?? -1,
|
|
344
|
-
out: r.stdout?.toString() ?? "",
|
|
345
|
-
err: r.stderr?.toString() ?? ""
|
|
346
|
-
};
|
|
347
|
-
}
|
|
313
|
+
const bin = "copilot";
|
|
348
314
|
async function cli() {
|
|
349
315
|
await deploy();
|
|
316
|
+
console.log(NAME, "version:", VERSION);
|
|
350
317
|
const httpProxy = env.HTTP_PROXY || env.http_proxy || "";
|
|
351
318
|
const httpsProxy = env.HTTPS_PROXY || env.https_proxy || "";
|
|
352
319
|
if (httpProxy) env.HTTP_PROXY = httpProxy;
|
|
353
320
|
if (httpsProxy) env.HTTPS_PROXY = httpsProxy;
|
|
354
|
-
console.log("@d5render/cli version:", VERSION);
|
|
355
|
-
const verify = runVerifySync();
|
|
356
|
-
console.log("copilot verify:", verify.code === 0 ? "OK" : `failed (code ${verify.code})`);
|
|
357
|
-
if (verify.out) console.log(verify.out.trim());
|
|
358
|
-
if (verify.err) console.error(verify.err.trim());
|
|
359
321
|
const args = [
|
|
360
322
|
...tools,
|
|
361
323
|
"-p",
|
|
362
324
|
`"${common_review_prompt.replace(/"/g, "\\\"")}"`
|
|
363
325
|
];
|
|
364
|
-
|
|
326
|
+
let child;
|
|
327
|
+
if (platform === "win32") child = spawn(bin, args, {
|
|
365
328
|
cwd: env.CI_PROJECT_DIR,
|
|
366
329
|
stdio: [
|
|
367
330
|
"inherit",
|
|
368
331
|
"pipe",
|
|
369
332
|
"pipe"
|
|
370
|
-
]
|
|
371
|
-
};
|
|
372
|
-
let child;
|
|
373
|
-
if (platform === "win32") child = spawn(bind, args, {
|
|
374
|
-
...opts,
|
|
333
|
+
],
|
|
375
334
|
shell: true
|
|
376
335
|
});
|
|
377
|
-
else {
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
336
|
+
else child = spawn("sh", ["-c", `export GH_TOKEN=${shellEscape(env.GH_TOKEN)}; exec ${bin} ${args.map((a) => shellEscape(a)).join(" ")}`], {
|
|
337
|
+
cwd: env.CI_PROJECT_DIR,
|
|
338
|
+
stdio: [
|
|
339
|
+
"inherit",
|
|
340
|
+
"pipe",
|
|
341
|
+
"pipe"
|
|
342
|
+
]
|
|
343
|
+
});
|
|
384
344
|
child.stdout.on("data", (chunk) => console.log(String(chunk)));
|
|
385
345
|
child.stderr.on("data", (chunk) => console.error(String(chunk)));
|
|
386
|
-
return new Promise((res, rej) => child.on("close", (code) => getCopilotUsage().then((
|
|
346
|
+
return new Promise((res, rej) => child.on("close", (code) => getCopilotUsage().then((res) => console.log("本次Token积累使用量:", res)).catch(() => {}).finally(() => {
|
|
387
347
|
if (code === 0) res();
|
|
388
|
-
else rej(/* @__PURE__ */ new Error(`${
|
|
348
|
+
else rej(/* @__PURE__ */ new Error(`${bin} exited with code ${code}`));
|
|
389
349
|
})));
|
|
390
350
|
}
|
|
351
|
+
function shellEscape(val) {
|
|
352
|
+
return `'${(val || "").replace(/'/g, "'\\''")}'`;
|
|
353
|
+
}
|
|
391
354
|
|
|
392
355
|
//#endregion
|
|
393
356
|
//#region review/index.ts
|