hypercore-cli 1.1.2 → 1.4.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/LICENSE +92 -21
- package/README.md +8 -1
- package/dist/App-YMX7FSXR.js +1 -0
- package/dist/api-ELP6F4NC.js +1 -0
- package/dist/auth-SICBMA3P.js +1 -0
- package/dist/auth-X6CUT3DW.js +1 -0
- package/dist/background-ACODXSUG.js +1 -0
- package/dist/backlog-JD2IM336.js +1 -0
- package/dist/chunk-2QI2IU2V.js +1 -0
- package/dist/chunk-3KFRDIPQ.js +1 -0
- package/dist/chunk-42C5J7PN.js +1 -0
- package/dist/chunk-4D7XVJ7Q.js +1 -0
- package/dist/chunk-5KUSGQP2.js +1 -0
- package/dist/chunk-5OEFAGD5.js +1 -0
- package/dist/chunk-AUQ64BK2.js +1 -0
- package/dist/chunk-AV244H5C.js +1 -0
- package/dist/chunk-BQVBEFS4.js +1 -0
- package/dist/chunk-BYWQLFP2.js +1 -0
- package/dist/chunk-C6YL7UHE.js +1 -0
- package/dist/chunk-COITWWZJ.js +1 -0
- package/dist/chunk-CR7UUJVX.js +1 -0
- package/dist/chunk-E3MULLBX.js +1 -0
- package/dist/chunk-EZHYVJGQ.js +1 -0
- package/dist/chunk-FAMURNNH.js +1 -0
- package/dist/chunk-FGP56E4W.js +1 -0
- package/dist/chunk-FHGATV5B.js +1 -0
- package/dist/chunk-I2G27Y5P.js +1 -0
- package/dist/chunk-IKF43TX2.js +1 -0
- package/dist/chunk-INSPHCBN.js +1 -0
- package/dist/chunk-JHMV366T.js +1 -0
- package/dist/chunk-L52HX5SX.js +1 -0
- package/dist/chunk-LQMDUKIE.js +1 -0
- package/dist/chunk-M3MTKGA5.js +1 -0
- package/dist/chunk-MPO54FU3.js +1 -0
- package/dist/chunk-PVKCZI6A.js +1 -0
- package/dist/chunk-Q7KEPCYL.js +1 -0
- package/dist/chunk-ROBZ6PAL.js +1 -0
- package/dist/chunk-RXB5BS2N.js +1 -0
- package/dist/chunk-RZ3HNYMT.js +1 -0
- package/dist/chunk-UCGLRMTG.js +1 -0
- package/dist/chunk-UEHJVRKB.js +1 -0
- package/dist/chunk-UZYX5GGF.js +1 -0
- package/dist/chunk-XQJBB725.js +1 -0
- package/dist/chunk-YXCRL6K3.js +1 -0
- package/dist/claude-US2QPRBA.js +1 -0
- package/dist/commands-EKPWCB3T.js +1 -0
- package/dist/commands-GYNKP5WV.js +1 -0
- package/dist/commands-QHJLREPM.js +1 -0
- package/dist/config-2OUL5FLS.js +1 -0
- package/dist/config-loader-N7IBWN2P.js +1 -0
- package/dist/diagnose-NLHN4SAJ.js +1 -0
- package/dist/display-RYAW2GFB.js +1 -0
- package/dist/extractor-3KTM2IUL.js +1 -0
- package/dist/feature-flag-VVIF5FJG.js +1 -0
- package/dist/history-3R2UHRDQ.js +1 -0
- package/dist/index.js +1 -402
- package/dist/instance-registry-I5AIVJE2.js +1 -0
- package/dist/keybindings-RN3A7CRW.js +1 -0
- package/dist/loader-3IKPXP4R.js +1 -0
- package/dist/network-K5HRJE44.js +1 -0
- package/dist/notify-O6FNVHC4.js +1 -0
- package/dist/openai-compat-IPCMINVF.js +1 -0
- package/dist/panels-2R5YEFXH.js +1 -0
- package/dist/permissions-5O7KVAXU.js +1 -0
- package/dist/prompt-VWFPFM4N.js +1 -0
- package/dist/quality-GPQD25UL.js +1 -0
- package/dist/repl-CL4SYHU4.js +1 -0
- package/dist/roadmap-QRZODSNJ.js +1 -0
- package/dist/server-PKOHK5M2.js +1 -0
- package/dist/session-5HDDQQP6.js +1 -0
- package/dist/skills-DXWSVJSU.js +1 -0
- package/dist/store-WXXTKTTL.js +1 -0
- package/dist/team-N2GF4YYS.js +1 -0
- package/dist/telemetry-NT4UZLBS.js +1 -0
- package/dist/test-runner-F6B6RH3S.js +1 -0
- package/dist/theme-JJJ6ABR2.js +1 -0
- package/dist/upgrade-RUG3R7R5.js +1 -0
- package/dist/verify-6OGRY2PR.js +1 -0
- package/dist/version-4RHTDUNQ.js +1 -0
- package/dist/web/static/app.js +1 -562
- package/dist/web/static/index.html +114 -126
- package/dist/web/static/mirror.css +1 -1001
- package/dist/web/static/mirror.html +155 -178
- package/dist/web/static/mirror.js +1 -1125
- package/dist/web/static/onboard.css +1 -302
- package/dist/web/static/onboard.html +121 -145
- package/dist/web/static/onboard.js +1 -300
- package/dist/web/static/style.css +1 -602
- package/dist/web/static/utils.js +1 -0
- package/dist/web/static/workspace.css +1 -1568
- package/dist/web/static/workspace.html +369 -402
- package/dist/web/static/workspace.js +1 -1683
- package/dist/web-CIC7ZKBM.js +1 -0
- package/package.json +26 -4
- package/dist/api-JHHOZTL6.js +0 -162
- package/dist/auth-5QFJLW7J.js +0 -21
- package/dist/background-2EGCAAQH.js +0 -14
- package/dist/backlog-Q2NZCLNY.js +0 -24
- package/dist/chunk-2CMSCWQW.js +0 -162
- package/dist/chunk-4DVYJAJL.js +0 -57
- package/dist/chunk-5GDYH676.js +0 -271
- package/dist/chunk-5NLVGLD7.js +0 -66
- package/dist/chunk-6XTEAFZQ.js +0 -575
- package/dist/chunk-AQBSMYLT.js +0 -2025
- package/dist/chunk-BE46C7JW.js +0 -46
- package/dist/chunk-CLKIMCXZ.js +0 -139
- package/dist/chunk-DN4ASQ26.js +0 -167
- package/dist/chunk-DUWREZXK.js +0 -173
- package/dist/chunk-FCW3K6F2.js +0 -263
- package/dist/chunk-GFORWAMW.js +0 -251
- package/dist/chunk-GH7E2OJE.js +0 -223
- package/dist/chunk-GU2FZQ6A.js +0 -69
- package/dist/chunk-I7WI3BMB.js +0 -161
- package/dist/chunk-IOPKN5GD.js +0 -190
- package/dist/chunk-LBVHDGZE.js +0 -133
- package/dist/chunk-MGLJ53QN.js +0 -219
- package/dist/chunk-NETIY5UB.js +0 -134
- package/dist/chunk-NP47L7LG.js +0 -288
- package/dist/chunk-O6MG7TOH.js +0 -58
- package/dist/chunk-OPZYEVYR.js +0 -150
- package/dist/chunk-R3GPQC7I.js +0 -393
- package/dist/chunk-R5T3A2NQ.js +0 -166
- package/dist/chunk-RKB2JOV2.js +0 -43
- package/dist/chunk-RNG3K465.js +0 -80
- package/dist/chunk-TGTYKBGC.js +0 -86
- package/dist/chunk-UCX4VZCT.js +0 -681
- package/dist/chunk-WHLVZCQY.js +0 -245
- package/dist/chunk-Y6HMJZDJ.js +0 -1505
- package/dist/chunk-ZSBHUGWR.js +0 -262
- package/dist/claude-4BX3MJSK.js +0 -12
- package/dist/commands-2X4OB5RF.js +0 -128
- package/dist/commands-GLBCEVQK.js +0 -1044
- package/dist/commands-IINRNBYX.js +0 -232
- package/dist/config-RSNQJQPS.js +0 -8
- package/dist/config-loader-SXO674TF.js +0 -24
- package/dist/diagnose-7UPLS7I4.js +0 -12
- package/dist/display-IIUBEYWN.js +0 -58
- package/dist/extractor-D3XWOAXI.js +0 -129
- package/dist/history-6I6FADAU.js +0 -180
- package/dist/index.d.ts +0 -1
- package/dist/instance-registry-J7UJ7U4Z.js +0 -15
- package/dist/keybindings-PDXIOV3O.js +0 -15
- package/dist/loader-GKEYT6Y7.js +0 -58
- package/dist/network-JYGHQXAR.js +0 -279
- package/dist/notify-HPTALZDC.js +0 -14
- package/dist/openai-compat-R7EKWG6Z.js +0 -12
- package/dist/permissions-JUKXMNDH.js +0 -10
- package/dist/prompt-UWHSZU4P.js +0 -166
- package/dist/quality-ST7PPNFR.js +0 -16
- package/dist/repl-QHIZ2JGF.js +0 -3374
- package/dist/roadmap-5OBEKROY.js +0 -17
- package/dist/server-HCNIP7ZQ.js +0 -57
- package/dist/session-5EBECDUP.js +0 -21
- package/dist/skills-HBQQTYO4.js +0 -175
- package/dist/store-FKUTR7GW.js +0 -25
- package/dist/team-7BBBP5YQ.js +0 -385
- package/dist/telemetry-6R4EIE6O.js +0 -30
- package/dist/test-runner-AUAGIBNM.js +0 -619
- package/dist/theme-3SYJ3UQA.js +0 -14
- package/dist/upgrade-MZFH7OCN.js +0 -83
- package/dist/verify-JUDKTPKZ.js +0 -14
- package/dist/web-KS3FUGJA.js +0 -39
package/dist/chunk-GH7E2OJE.js
DELETED
|
@@ -1,223 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
displayWidth,
|
|
3
|
-
padToWidth,
|
|
4
|
-
truncateToWidth
|
|
5
|
-
} from "./chunk-BE46C7JW.js";
|
|
6
|
-
|
|
7
|
-
// src/ui/markdown.ts
|
|
8
|
-
import chalk from "chalk";
|
|
9
|
-
import { Marked } from "marked";
|
|
10
|
-
import { markedTerminal } from "marked-terminal";
|
|
11
|
-
var INDENT = " ";
|
|
12
|
-
function renderTable(token) {
|
|
13
|
-
const termWidth = process.stdout.columns || 120;
|
|
14
|
-
const headers = token.header.map((h) => h.text.trim());
|
|
15
|
-
const rows = token.rows.map((r) => r.map((c) => c.text.trim()));
|
|
16
|
-
const colCount = headers.length;
|
|
17
|
-
const colWidths = headers.map((h) => displayWidth(h));
|
|
18
|
-
for (const row of rows) {
|
|
19
|
-
for (let i = 0; i < colCount; i++) {
|
|
20
|
-
const cellText = row[i] || "";
|
|
21
|
-
const w = displayWidth(cellText);
|
|
22
|
-
if (w > colWidths[i]) colWidths[i] = w;
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
const paddedWidths = colWidths.map((w) => w + 2);
|
|
26
|
-
const borderOverhead = colCount + 1;
|
|
27
|
-
const totalWidth = paddedWidths.reduce((a, b) => a + b, 0) + borderOverhead;
|
|
28
|
-
if (totalWidth > termWidth) {
|
|
29
|
-
const available = termWidth - borderOverhead - 4;
|
|
30
|
-
const ratio = available / paddedWidths.reduce((a, b) => a + b, 0);
|
|
31
|
-
for (let i = 0; i < colCount; i++) {
|
|
32
|
-
paddedWidths[i] = Math.max(4, Math.floor(paddedWidths[i] * ratio));
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
const contentWidths = paddedWidths.map((w) => w - 2);
|
|
36
|
-
const topLine = INDENT + "\u250C" + paddedWidths.map((w) => "\u2500".repeat(w)).join("\u252C") + "\u2510";
|
|
37
|
-
const midLine = INDENT + "\u251C" + paddedWidths.map((w) => "\u2500".repeat(w)).join("\u253C") + "\u2524";
|
|
38
|
-
const bottomLine = INDENT + "\u2514" + paddedWidths.map((w) => "\u2500".repeat(w)).join("\u2534") + "\u2518";
|
|
39
|
-
const headerCells = headers.map((h, i) => {
|
|
40
|
-
const text = displayWidth(h) > contentWidths[i] ? truncateToWidth(h, contentWidths[i]) : h;
|
|
41
|
-
return " " + padToWidth(text, contentWidths[i]) + " ";
|
|
42
|
-
});
|
|
43
|
-
const headerRow = INDENT + "\u2502" + headerCells.map((c) => chalk.bold(c)).join("\u2502") + "\u2502";
|
|
44
|
-
const dataRows = rows.map((row) => {
|
|
45
|
-
const cells = row.map((cell, i) => {
|
|
46
|
-
const cellText = cell || "";
|
|
47
|
-
const text = displayWidth(cellText) > contentWidths[i] ? truncateToWidth(cellText, contentWidths[i]) : cellText;
|
|
48
|
-
return " " + padToWidth(text, contentWidths[i]) + " ";
|
|
49
|
-
});
|
|
50
|
-
return INDENT + "\u2502" + cells.join("\u2502") + "\u2502";
|
|
51
|
-
});
|
|
52
|
-
return ["", topLine, headerRow, midLine, ...dataRows, bottomLine, ""].join("\n") + "\n";
|
|
53
|
-
}
|
|
54
|
-
function highlightCode(code, lang) {
|
|
55
|
-
const l = lang.toLowerCase();
|
|
56
|
-
if (l === "json" || l === "jsonc") {
|
|
57
|
-
return code.replace(/"([^"]*)"(?=\s*:)/g, chalk.cyan('"$1"')).replace(/:\s*"([^"]*)"/g, ": " + chalk.green('"$1"')).replace(/:\s*(\d+\.?\d*)/g, ": " + chalk.yellow("$1")).replace(/:\s*(true|false|null)/g, ": " + chalk.magenta("$1"));
|
|
58
|
-
}
|
|
59
|
-
if (l === "bash" || l === "sh" || l === "shell" || l === "zsh") {
|
|
60
|
-
return code.replace(/(#.*)$/gm, chalk.gray("$1")).replace(/\b(if|then|else|fi|for|do|done|while|case|esac|function|return|export|source|alias|echo|cd|ls|rm|cp|mv|mkdir|chmod|grep|sed|awk|cat|git|npm|node|docker)\b/g, chalk.blue("$1")).replace(/"([^"]*)"/g, chalk.green('"$1"')).replace(/'([^']*)'/g, chalk.green("'$1'")).replace(/\$\w+/g, chalk.cyan("$&"));
|
|
61
|
-
}
|
|
62
|
-
if (l === "css" || l === "scss" || l === "less") {
|
|
63
|
-
return code.replace(/(\/\*[\s\S]*?\*\/)/g, chalk.gray("$1")).replace(/(#[0-9a-fA-F]{3,8})\b/g, chalk.yellow("$1")).replace(/(\d+\.?\d*)(px|em|rem|%|vh|vw|s|ms)/g, chalk.yellow("$1$2")).replace(/\b(var|calc|rgba?|hsla?)\b/g, chalk.blue("$1"));
|
|
64
|
-
}
|
|
65
|
-
const isJSTS = ["js", "javascript", "ts", "typescript", "jsx", "tsx"].includes(l);
|
|
66
|
-
const isPython = ["python", "py"].includes(l);
|
|
67
|
-
const isGo = l === "go";
|
|
68
|
-
const isRust = l === "rust" || l === "rs";
|
|
69
|
-
if (isJSTS || isPython || isGo || isRust || !l) {
|
|
70
|
-
let result = code;
|
|
71
|
-
result = result.replace(/(\/\/.*)$/gm, chalk.gray("$1"));
|
|
72
|
-
result = result.replace(/(#.*)$/gm, chalk.gray("$1"));
|
|
73
|
-
result = result.replace(/"([^"\\]*(\\.[^"\\]*)*)"/g, chalk.green('"$1"'));
|
|
74
|
-
result = result.replace(/'([^'\\]*(\\.[^'\\]*)*)'/g, chalk.green("'$1'"));
|
|
75
|
-
result = result.replace(/`([^`]*)`/g, chalk.green("`$1`"));
|
|
76
|
-
let keywords;
|
|
77
|
-
if (isJSTS) {
|
|
78
|
-
keywords = ["import", "export", "from", "const", "let", "var", "function", "class", "interface", "type", "enum", "return", "if", "else", "for", "while", "switch", "case", "break", "continue", "async", "await", "new", "this", "extends", "implements", "typeof", "instanceof", "default", "try", "catch", "finally", "throw"];
|
|
79
|
-
} else if (isPython) {
|
|
80
|
-
keywords = ["import", "from", "def", "class", "return", "if", "elif", "else", "for", "while", "try", "except", "finally", "with", "as", "in", "not", "and", "or", "is", "None", "True", "False", "lambda", "yield", "async", "await", "raise", "pass", "self"];
|
|
81
|
-
} else if (isGo) {
|
|
82
|
-
keywords = ["package", "import", "func", "return", "if", "else", "for", "range", "switch", "case", "default", "var", "const", "type", "struct", "interface", "map", "chan", "go", "defer", "select", "nil", "true", "false"];
|
|
83
|
-
} else if (isRust) {
|
|
84
|
-
keywords = ["use", "fn", "let", "mut", "const", "struct", "enum", "impl", "trait", "pub", "mod", "return", "if", "else", "for", "while", "loop", "match", "self", "Self", "true", "false", "None", "Some", "Ok", "Err", "async", "await", "move", "where"];
|
|
85
|
-
} else {
|
|
86
|
-
keywords = ["import", "export", "function", "class", "return", "if", "else", "for", "while", "const", "let", "var"];
|
|
87
|
-
}
|
|
88
|
-
const kwPattern = new RegExp(`\\b(${keywords.join("|")})\\b`, "g");
|
|
89
|
-
result = result.replace(kwPattern, chalk.blue("$1"));
|
|
90
|
-
result = result.replace(/\b(\d+\.?\d*)\b/g, chalk.yellow("$1"));
|
|
91
|
-
return result;
|
|
92
|
-
}
|
|
93
|
-
return code;
|
|
94
|
-
}
|
|
95
|
-
var cjkTableAndCodeExtension = {
|
|
96
|
-
renderer: {
|
|
97
|
-
// 标题渲染:去除 # 前缀,纯样式输出
|
|
98
|
-
heading(token) {
|
|
99
|
-
const text = token.text;
|
|
100
|
-
if (token.depth === 1) {
|
|
101
|
-
return "\n" + chalk.bold.underline(text) + "\n\n";
|
|
102
|
-
}
|
|
103
|
-
if (token.depth === 2) {
|
|
104
|
-
return "\n" + chalk.bold(text) + "\n\n";
|
|
105
|
-
}
|
|
106
|
-
return "\n" + chalk.bold(text) + "\n\n";
|
|
107
|
-
},
|
|
108
|
-
table(token) {
|
|
109
|
-
return renderTable(token);
|
|
110
|
-
},
|
|
111
|
-
code(token) {
|
|
112
|
-
const lang = token.lang || "";
|
|
113
|
-
const highlighted = highlightCode(token.text, lang);
|
|
114
|
-
const termW = process.stdout.columns || 80;
|
|
115
|
-
const codeW = Math.min(termW - 6, 76);
|
|
116
|
-
const langLabel = lang ? chalk.dim.italic(` ${lang}`) : "";
|
|
117
|
-
const topBorder = INDENT + chalk.dim("\u250C" + "\u2500".repeat(codeW) + "\u2510") + langLabel;
|
|
118
|
-
const botBorder = INDENT + chalk.dim("\u2514" + "\u2500".repeat(codeW) + "\u2518");
|
|
119
|
-
const codeLines = highlighted.split("\n").map((line) => {
|
|
120
|
-
return INDENT + chalk.dim("\u2502") + chalk.bgHex("#1a1a2e")(" " + line) + " ";
|
|
121
|
-
});
|
|
122
|
-
return "\n" + topBorder + "\n" + codeLines.join("\n") + "\n" + botBorder + "\n";
|
|
123
|
-
}
|
|
124
|
-
}
|
|
125
|
-
};
|
|
126
|
-
var marked = new Marked(
|
|
127
|
-
// 先注册 marked-terminal 基础渲染
|
|
128
|
-
markedTerminal({
|
|
129
|
-
code: chalk.yellow,
|
|
130
|
-
codespan: chalk.cyan,
|
|
131
|
-
strong: chalk.bold,
|
|
132
|
-
em: chalk.italic,
|
|
133
|
-
link: chalk.blue.underline,
|
|
134
|
-
// 标题:粗体 + 下划线(一级)/ 粗体(其他)
|
|
135
|
-
firstHeading: chalk.bold.underline,
|
|
136
|
-
heading: chalk.bold,
|
|
137
|
-
blockquote: chalk.gray.italic,
|
|
138
|
-
listitem: chalk.reset,
|
|
139
|
-
// 渲染宽度
|
|
140
|
-
width: (process.stdout.columns || 80) - 4
|
|
141
|
-
}),
|
|
142
|
-
// 后注册自定义扩展(优先级更高)
|
|
143
|
-
cjkTableAndCodeExtension
|
|
144
|
-
);
|
|
145
|
-
function preprocess(text) {
|
|
146
|
-
const normalized = normalizeSpacing(text);
|
|
147
|
-
return normalized.replace(/^(\s*)\* /gm, "$1- ");
|
|
148
|
-
}
|
|
149
|
-
function isListLine(line) {
|
|
150
|
-
const t = line.trim();
|
|
151
|
-
return /^[-+*]\s+/.test(t) || /^\d+\.\s+/.test(t);
|
|
152
|
-
}
|
|
153
|
-
function normalizeSpacing(text) {
|
|
154
|
-
const lines = text.replace(/\r\n/g, "\n").split("\n");
|
|
155
|
-
const out = [];
|
|
156
|
-
let inCodeFence = false;
|
|
157
|
-
let blankCount = 0;
|
|
158
|
-
for (let i = 0; i < lines.length; i++) {
|
|
159
|
-
const current = lines[i].replace(/\s+$/g, "");
|
|
160
|
-
const trimmed = current.trim();
|
|
161
|
-
if (/^```/.test(trimmed)) {
|
|
162
|
-
inCodeFence = !inCodeFence;
|
|
163
|
-
blankCount = 0;
|
|
164
|
-
out.push(current);
|
|
165
|
-
continue;
|
|
166
|
-
}
|
|
167
|
-
if (!inCodeFence && trimmed === "") {
|
|
168
|
-
const prev = out.length > 0 ? out[out.length - 1] : "";
|
|
169
|
-
const next = i + 1 < lines.length ? lines[i + 1].trim() : "";
|
|
170
|
-
if (isListLine(prev) && isListLine(next)) {
|
|
171
|
-
continue;
|
|
172
|
-
}
|
|
173
|
-
blankCount += 1;
|
|
174
|
-
if (blankCount > 1) continue;
|
|
175
|
-
out.push("");
|
|
176
|
-
continue;
|
|
177
|
-
}
|
|
178
|
-
blankCount = 0;
|
|
179
|
-
out.push(current);
|
|
180
|
-
}
|
|
181
|
-
return out.join("\n").trim();
|
|
182
|
-
}
|
|
183
|
-
function addIndent(rendered) {
|
|
184
|
-
const lines = rendered.split("\n");
|
|
185
|
-
const out = [];
|
|
186
|
-
let prevBlank = false;
|
|
187
|
-
for (const line of lines) {
|
|
188
|
-
const trimmed = line.trim();
|
|
189
|
-
const isBlank = trimmed === "";
|
|
190
|
-
if (isBlank) {
|
|
191
|
-
if (!prevBlank) out.push("");
|
|
192
|
-
prevBlank = true;
|
|
193
|
-
continue;
|
|
194
|
-
}
|
|
195
|
-
prevBlank = false;
|
|
196
|
-
if (/^ /.test(line)) {
|
|
197
|
-
out.push(line);
|
|
198
|
-
} else {
|
|
199
|
-
out.push(INDENT + line);
|
|
200
|
-
}
|
|
201
|
-
}
|
|
202
|
-
return out.join("\n");
|
|
203
|
-
}
|
|
204
|
-
function renderMarkdown(text) {
|
|
205
|
-
try {
|
|
206
|
-
let rendered = marked.parse(preprocess(text));
|
|
207
|
-
rendered = rendered.replace(/^(\s*)(\*) /gm, "$1- ");
|
|
208
|
-
rendered = rendered.replace(/\*\*(.+?)\*\*/g, (_m, content) => chalk.bold(content));
|
|
209
|
-
rendered = rendered.replace(/(?<!\*)\*([^*\s][^*]*?)\*(?!\*)/g, (_m, content) => chalk.italic(content));
|
|
210
|
-
rendered = rendered.replace(/^(\x1b\[0m)+/gm, "");
|
|
211
|
-
rendered = rendered.replace(/^\s*(\x1b\[[0-9;]*m\s*)+$/gm, "");
|
|
212
|
-
rendered = rendered.replace(/(\x1b\[0m){2,}/g, "\x1B[0m");
|
|
213
|
-
rendered = rendered.replace(/\n{3,}/g, "\n\n");
|
|
214
|
-
rendered = addIndent(rendered);
|
|
215
|
-
return rendered;
|
|
216
|
-
} catch {
|
|
217
|
-
return text;
|
|
218
|
-
}
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
export {
|
|
222
|
-
renderMarkdown
|
|
223
|
-
};
|
package/dist/chunk-GU2FZQ6A.js
DELETED
|
@@ -1,69 +0,0 @@
|
|
|
1
|
-
// src/core/permissions.ts
|
|
2
|
-
import chalk from "chalk";
|
|
3
|
-
import { confirm } from "@inquirer/prompts";
|
|
4
|
-
var TOOL_PERMISSIONS = {
|
|
5
|
-
// safe — 只读操作
|
|
6
|
-
file_read: "safe",
|
|
7
|
-
glob: "safe",
|
|
8
|
-
grep: "safe",
|
|
9
|
-
web_fetch: "safe",
|
|
10
|
-
web_search: "safe",
|
|
11
|
-
memory_search: "safe",
|
|
12
|
-
notebook_read: "safe",
|
|
13
|
-
task_output: "safe",
|
|
14
|
-
sub_agent: "safe",
|
|
15
|
-
// write — 文件修改操作
|
|
16
|
-
file_write: "write",
|
|
17
|
-
file_edit: "write",
|
|
18
|
-
memory_save: "write",
|
|
19
|
-
notebook_edit: "write",
|
|
20
|
-
// dangerous — 系统级操作
|
|
21
|
-
bash: "dangerous"
|
|
22
|
-
};
|
|
23
|
-
function getToolPermission(toolName) {
|
|
24
|
-
if (TOOL_PERMISSIONS[toolName]) return TOOL_PERMISSIONS[toolName];
|
|
25
|
-
if (toolName.startsWith("mcp_")) return "write";
|
|
26
|
-
return "write";
|
|
27
|
-
}
|
|
28
|
-
function wrapToolWithPermission(tool, config) {
|
|
29
|
-
const level = getToolPermission(tool.definition.name);
|
|
30
|
-
if (level === "safe") return tool;
|
|
31
|
-
const originalHandler = tool.handler;
|
|
32
|
-
return {
|
|
33
|
-
definition: tool.definition,
|
|
34
|
-
handler: async (input) => {
|
|
35
|
-
const mode = config.permissionMode || "full";
|
|
36
|
-
if (mode === "full") return originalHandler(input);
|
|
37
|
-
if (mode === "safe") {
|
|
38
|
-
return `\u26D4 \u6743\u9650\u62D2\u7EDD: \u5F53\u524D\u4E3A safe \u6A21\u5F0F\uFF0C\u5DE5\u5177 "${tool.definition.name}" (${level}) \u4E0D\u53EF\u7528\u3002\u4F7F\u7528 /permissions full \u5207\u6362\u6A21\u5F0F\u3002`;
|
|
39
|
-
}
|
|
40
|
-
if (mode === "ask") {
|
|
41
|
-
const inputPreview = JSON.stringify(input).slice(0, 200);
|
|
42
|
-
console.log(chalk.yellow(`
|
|
43
|
-
\u26A0\uFE0F \u6743\u9650\u786E\u8BA4: ${tool.definition.name} [${level}]`));
|
|
44
|
-
console.log(chalk.dim(` \u8F93\u5165: ${inputPreview}`));
|
|
45
|
-
try {
|
|
46
|
-
const yes = await confirm({
|
|
47
|
-
message: `\u5141\u8BB8\u6267\u884C ${tool.definition.name}?`,
|
|
48
|
-
default: true
|
|
49
|
-
});
|
|
50
|
-
if (!yes) {
|
|
51
|
-
return `\u26D4 \u7528\u6237\u62D2\u7EDD\u6267\u884C "${tool.definition.name}"`;
|
|
52
|
-
}
|
|
53
|
-
} catch {
|
|
54
|
-
return `\u26D4 \u7528\u6237\u53D6\u6D88\u6267\u884C "${tool.definition.name}"`;
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
return originalHandler(input);
|
|
58
|
-
}
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
|
-
function applyPermissions(tools, config) {
|
|
62
|
-
return tools.map((t) => wrapToolWithPermission(t, config));
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
export {
|
|
66
|
-
getToolPermission,
|
|
67
|
-
wrapToolWithPermission,
|
|
68
|
-
applyPermissions
|
|
69
|
-
};
|
package/dist/chunk-I7WI3BMB.js
DELETED
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
// src/core/config.ts
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { readFile } from "fs/promises";
|
|
4
|
-
import { existsSync } from "fs";
|
|
5
|
-
|
|
6
|
-
// src/core/types.ts
|
|
7
|
-
var MODEL_PROVIDERS = {
|
|
8
|
-
anthropic: {
|
|
9
|
-
defaultModel: "claude-sonnet-4-20250514",
|
|
10
|
-
name: "Anthropic (Claude)",
|
|
11
|
-
sdkType: "anthropic"
|
|
12
|
-
},
|
|
13
|
-
minimax: {
|
|
14
|
-
baseURL: "https://api.minimax.io/anthropic",
|
|
15
|
-
defaultModel: "MiniMax-M2.5",
|
|
16
|
-
name: "MiniMax (M2.5)",
|
|
17
|
-
sdkType: "anthropic"
|
|
18
|
-
},
|
|
19
|
-
gemini: {
|
|
20
|
-
baseURL: "https://generativelanguage.googleapis.com/v1beta/openai",
|
|
21
|
-
defaultModel: "gemini-2.5-flash",
|
|
22
|
-
name: "Google (Gemini)",
|
|
23
|
-
sdkType: "openai"
|
|
24
|
-
},
|
|
25
|
-
deepseek: {
|
|
26
|
-
baseURL: "https://api.deepseek.com/v1",
|
|
27
|
-
defaultModel: "deepseek-chat",
|
|
28
|
-
name: "DeepSeek",
|
|
29
|
-
sdkType: "openai"
|
|
30
|
-
},
|
|
31
|
-
"openai-compatible": {
|
|
32
|
-
defaultModel: "gpt-4o",
|
|
33
|
-
name: "OpenAI Compatible",
|
|
34
|
-
sdkType: "openai"
|
|
35
|
-
}
|
|
36
|
-
};
|
|
37
|
-
var MODEL_ALIASES = {
|
|
38
|
-
// Claude 系列
|
|
39
|
-
"sonnet": { provider: "anthropic", model: "claude-sonnet-4-20250514" },
|
|
40
|
-
"haiku": { provider: "anthropic", model: "claude-3-5-haiku-20241022" },
|
|
41
|
-
"opus": { provider: "anthropic", model: "claude-opus-4-20250514" },
|
|
42
|
-
// Gemini 系列
|
|
43
|
-
"flash": { provider: "gemini", model: "gemini-2.5-flash" },
|
|
44
|
-
"gemini": { provider: "gemini", model: "gemini-2.5-flash" },
|
|
45
|
-
"gemini-pro": { provider: "gemini", model: "gemini-2.5-pro-preview-05-06" },
|
|
46
|
-
// DeepSeek
|
|
47
|
-
"deepseek": { provider: "deepseek", model: "deepseek-chat" },
|
|
48
|
-
"ds": { provider: "deepseek", model: "deepseek-chat" },
|
|
49
|
-
"deepseek-coder": { provider: "deepseek", model: "deepseek-coder" },
|
|
50
|
-
"deepseek-r1": { provider: "deepseek", model: "deepseek-reasoner" },
|
|
51
|
-
// MiniMax
|
|
52
|
-
"minimax": { provider: "minimax", model: "MiniMax-M2.5" },
|
|
53
|
-
"mm": { provider: "minimax", model: "MiniMax-M2.5" }
|
|
54
|
-
};
|
|
55
|
-
|
|
56
|
-
// src/core/config.ts
|
|
57
|
-
var HYPERCORE_DIR = join(process.env.HOME || "~", ".hypercore");
|
|
58
|
-
function parseSectionValues(content, sectionName) {
|
|
59
|
-
const sectionRegex = new RegExp(`\\[${sectionName}\\]([\\s\\S]*?)(?=\\[|$)`);
|
|
60
|
-
const match = content.match(sectionRegex);
|
|
61
|
-
if (!match) return {};
|
|
62
|
-
const result = {};
|
|
63
|
-
const lines = match[1].split("\n");
|
|
64
|
-
for (const rawLine of lines) {
|
|
65
|
-
const kvMatch = rawLine.match(/^\s*([A-Za-z_]\w*)\s*=\s*(?:"((?:\\.|[^"])*)"|(\S+))(?:\s+#.*)?\s*$/);
|
|
66
|
-
if (kvMatch) {
|
|
67
|
-
const key = kvMatch[1];
|
|
68
|
-
const quoted = kvMatch[2];
|
|
69
|
-
const bare = kvMatch[3];
|
|
70
|
-
let value = quoted != null ? quoted : bare;
|
|
71
|
-
value = value.replace(/\\n/g, "\n").replace(/\\r/g, "\r").replace(/\\"/g, '"').replace(/\\\\/g, "\\");
|
|
72
|
-
result[key] = value;
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
return result;
|
|
76
|
-
}
|
|
77
|
-
async function loadConfig() {
|
|
78
|
-
const configPath = join(HYPERCORE_DIR, "config.toml");
|
|
79
|
-
if (!existsSync(configPath)) {
|
|
80
|
-
throw new Error("\u672A\u627E\u5230\u914D\u7F6E\u6587\u4EF6\u3002\u8BF7\u5148\u8FD0\u884C hypercore init");
|
|
81
|
-
}
|
|
82
|
-
const content = await readFile(configPath, "utf-8");
|
|
83
|
-
const modelSection = parseSectionValues(content, "model");
|
|
84
|
-
const rawProvider = (modelSection["provider"] || "anthropic").trim();
|
|
85
|
-
const providerAliasMap = {
|
|
86
|
-
openai: "openai-compatible",
|
|
87
|
-
"openai-compat": "openai-compatible",
|
|
88
|
-
"openai_compatible": "openai-compatible",
|
|
89
|
-
"openai-compatible": "openai-compatible",
|
|
90
|
-
"deepseek-coder": "deepseek",
|
|
91
|
-
"deepseek-reasoner": "deepseek"
|
|
92
|
-
};
|
|
93
|
-
let provider = providerAliasMap[rawProvider] || rawProvider;
|
|
94
|
-
const apiKey = modelSection["api_key"];
|
|
95
|
-
if (!apiKey) {
|
|
96
|
-
throw new Error("\u914D\u7F6E\u6587\u4EF6 [model] \u6BB5\u672A\u627E\u5230 api_key");
|
|
97
|
-
}
|
|
98
|
-
const modelName = modelSection["name"];
|
|
99
|
-
if (!MODEL_PROVIDERS[provider] && modelName) {
|
|
100
|
-
if (modelName.startsWith("deepseek-")) provider = "deepseek";
|
|
101
|
-
else if (modelName.startsWith("gemini-")) provider = "gemini";
|
|
102
|
-
else if (modelName.startsWith("claude-")) provider = "anthropic";
|
|
103
|
-
else if (modelName.startsWith("MiniMax") || modelName.startsWith("minimax")) provider = "minimax";
|
|
104
|
-
}
|
|
105
|
-
const providerConfig = MODEL_PROVIDERS[provider];
|
|
106
|
-
if (!providerConfig) {
|
|
107
|
-
throw new Error(`\u4E0D\u652F\u6301\u7684\u6A21\u578B\u63D0\u4F9B\u5546: ${provider}\u3002\u652F\u6301: ${Object.keys(MODEL_PROVIDERS).join(", ")}`);
|
|
108
|
-
}
|
|
109
|
-
const searchSection = parseSectionValues(content, "search");
|
|
110
|
-
const outputSection = parseSectionValues(content, "output");
|
|
111
|
-
const keysSection = parseSectionValues(content, "keys");
|
|
112
|
-
const providerKeys = {};
|
|
113
|
-
providerKeys[provider] = apiKey;
|
|
114
|
-
const keyMapping = {
|
|
115
|
-
anthropic: "anthropic",
|
|
116
|
-
gemini: "gemini",
|
|
117
|
-
deepseek: "deepseek",
|
|
118
|
-
minimax: "minimax",
|
|
119
|
-
openai: "openai-compatible"
|
|
120
|
-
};
|
|
121
|
-
for (const [name, value] of Object.entries(keysSection)) {
|
|
122
|
-
const mappedProvider = keyMapping[name];
|
|
123
|
-
if (mappedProvider && value) {
|
|
124
|
-
providerKeys[mappedProvider] = value;
|
|
125
|
-
}
|
|
126
|
-
}
|
|
127
|
-
const uiSection = parseSectionValues(content, "ui");
|
|
128
|
-
const uiConfig = {};
|
|
129
|
-
if (uiSection["theme"]) {
|
|
130
|
-
const t = uiSection["theme"];
|
|
131
|
-
if (t === "dark" || t === "light" || t === "high-contrast") {
|
|
132
|
-
uiConfig.theme = t;
|
|
133
|
-
}
|
|
134
|
-
}
|
|
135
|
-
if (uiSection["vim_mode"] === "true") uiConfig.vimMode = true;
|
|
136
|
-
if (uiSection["notifications"] === "false") {
|
|
137
|
-
uiConfig.notifications = false;
|
|
138
|
-
} else {
|
|
139
|
-
uiConfig.notifications = true;
|
|
140
|
-
}
|
|
141
|
-
return {
|
|
142
|
-
modelConfig: {
|
|
143
|
-
provider,
|
|
144
|
-
model: modelSection["name"] || (rawProvider === "deepseek-coder" ? "deepseek-coder" : providerConfig.defaultModel),
|
|
145
|
-
apiKey,
|
|
146
|
-
baseURL: modelSection["base_url"] || providerConfig.baseURL,
|
|
147
|
-
sdkType: providerConfig.sdkType
|
|
148
|
-
},
|
|
149
|
-
tavilyApiKey: searchSection["api_key"] || void 0,
|
|
150
|
-
outputDir: outputSection["dir"] || join(HYPERCORE_DIR, "outputs"),
|
|
151
|
-
providerKeys,
|
|
152
|
-
uiConfig
|
|
153
|
-
};
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
export {
|
|
157
|
-
MODEL_PROVIDERS,
|
|
158
|
-
MODEL_ALIASES,
|
|
159
|
-
HYPERCORE_DIR,
|
|
160
|
-
loadConfig
|
|
161
|
-
};
|
package/dist/chunk-IOPKN5GD.js
DELETED
|
@@ -1,190 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getEventsSummary
|
|
3
|
-
} from "./chunk-2CMSCWQW.js";
|
|
4
|
-
import {
|
|
5
|
-
getItem,
|
|
6
|
-
listItems,
|
|
7
|
-
updateItemMetrics
|
|
8
|
-
} from "./chunk-MGLJ53QN.js";
|
|
9
|
-
|
|
10
|
-
// src/admin/verify.ts
|
|
11
|
-
function inferBaselineKey(item) {
|
|
12
|
-
const titleLower = item.title.toLowerCase();
|
|
13
|
-
const descLower = item.description.toLowerCase();
|
|
14
|
-
const text = titleLower + " " + descLower;
|
|
15
|
-
if (text.includes("\u5931\u8D25\u7387") || text.includes("fail")) {
|
|
16
|
-
const cmdMatch = text.match(/(\/\w+)\s+失败/) || text.match(/(\/\w+).*fail/);
|
|
17
|
-
if (cmdMatch) return `cmd_fail_rate:${cmdMatch[1]}`;
|
|
18
|
-
return "cmd_fail_rate:all";
|
|
19
|
-
}
|
|
20
|
-
if (text.includes("\u9519\u8BEF") || text.includes("error")) {
|
|
21
|
-
return "error_count";
|
|
22
|
-
}
|
|
23
|
-
if (text.includes("\u8017\u65F6") || text.includes("\u6027\u80FD") || text.includes("perf") || text.includes("duration")) {
|
|
24
|
-
return "avg_session_rounds";
|
|
25
|
-
}
|
|
26
|
-
if (text.includes("\u4F1A\u8BDD") || text.includes("session") || text.includes("\u8F6E\u6B21")) {
|
|
27
|
-
return "avg_session_rounds";
|
|
28
|
-
}
|
|
29
|
-
if (text.includes("test") || text.includes("\u6D4B\u8BD5")) {
|
|
30
|
-
return "test_pass_rate";
|
|
31
|
-
}
|
|
32
|
-
if (text.includes("todo") || text.includes("fixme") || text.includes("\u6280\u672F\u503A")) {
|
|
33
|
-
return "todo_count";
|
|
34
|
-
}
|
|
35
|
-
if (text.includes("\u4F53\u79EF") || text.includes("size") || text.includes("bundle")) {
|
|
36
|
-
return "package_size";
|
|
37
|
-
}
|
|
38
|
-
if (item.type === "bugfix") return "error_count";
|
|
39
|
-
if (item.type === "improvement") return "avg_session_rounds";
|
|
40
|
-
return null;
|
|
41
|
-
}
|
|
42
|
-
async function getMetricValue(key, days = 7) {
|
|
43
|
-
if (key.startsWith("cmd_fail_rate:")) {
|
|
44
|
-
const cmd = key.replace("cmd_fail_rate:", "");
|
|
45
|
-
const summary = await getEventsSummary(days);
|
|
46
|
-
if (cmd === "all") {
|
|
47
|
-
let total = 0, fail = 0;
|
|
48
|
-
for (const stats2 of Object.values(summary.cmdCounts)) {
|
|
49
|
-
total += stats2.total;
|
|
50
|
-
fail += stats2.fail;
|
|
51
|
-
}
|
|
52
|
-
return total > 0 ? Math.round(fail / total * 1e3) / 10 : 0;
|
|
53
|
-
}
|
|
54
|
-
const stats = summary.cmdCounts[cmd];
|
|
55
|
-
if (!stats || stats.total === 0) return 0;
|
|
56
|
-
return Math.round(stats.fail / stats.total * 1e3) / 10;
|
|
57
|
-
}
|
|
58
|
-
if (key === "error_count") {
|
|
59
|
-
const summary = await getEventsSummary(days);
|
|
60
|
-
return summary.errors.reduce((s, e) => s + e.count, 0);
|
|
61
|
-
}
|
|
62
|
-
if (key === "avg_session_rounds") {
|
|
63
|
-
const summary = await getEventsSummary(days);
|
|
64
|
-
return summary.avgSessionRounds;
|
|
65
|
-
}
|
|
66
|
-
if (key === "test_pass_rate") {
|
|
67
|
-
const { checkTests } = await import("./quality-ST7PPNFR.js");
|
|
68
|
-
const result = await checkTests(process.cwd());
|
|
69
|
-
return result.value ?? null;
|
|
70
|
-
}
|
|
71
|
-
if (key === "todo_count") {
|
|
72
|
-
const { checkTodos } = await import("./quality-ST7PPNFR.js");
|
|
73
|
-
const result = await checkTodos(process.cwd());
|
|
74
|
-
return result.value ?? null;
|
|
75
|
-
}
|
|
76
|
-
if (key === "package_size") {
|
|
77
|
-
const { checkPackageSize } = await import("./quality-ST7PPNFR.js");
|
|
78
|
-
const result = await checkPackageSize(process.cwd());
|
|
79
|
-
return result.value ?? null;
|
|
80
|
-
}
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
async function recordBaseline(itemId) {
|
|
84
|
-
const item = await getItem(itemId);
|
|
85
|
-
if (!item) return null;
|
|
86
|
-
if (item.metrics.baselineKey && item.metrics.baselineValue !== null) {
|
|
87
|
-
return { key: item.metrics.baselineKey, value: item.metrics.baselineValue };
|
|
88
|
-
}
|
|
89
|
-
const key = inferBaselineKey(item);
|
|
90
|
-
if (!key) return null;
|
|
91
|
-
const value = await getMetricValue(key);
|
|
92
|
-
if (value === null) return null;
|
|
93
|
-
const metrics = {
|
|
94
|
-
...item.metrics,
|
|
95
|
-
baselineKey: key,
|
|
96
|
-
baselineValue: value,
|
|
97
|
-
baselineDate: (/* @__PURE__ */ new Date()).toISOString(),
|
|
98
|
-
verified: false
|
|
99
|
-
};
|
|
100
|
-
const updated = await updateItemMetrics(itemId, metrics);
|
|
101
|
-
if (!updated) return null;
|
|
102
|
-
return { key, value };
|
|
103
|
-
}
|
|
104
|
-
async function verifyCompletedItems() {
|
|
105
|
-
const items = await listItems({ status: "done" });
|
|
106
|
-
const results = [];
|
|
107
|
-
for (const item of items) {
|
|
108
|
-
if (!item.metrics.baselineKey || item.metrics.baselineValue === null) continue;
|
|
109
|
-
if (item.metrics.verified) continue;
|
|
110
|
-
const currentValue = await getMetricValue(item.metrics.baselineKey);
|
|
111
|
-
let changePercent = null;
|
|
112
|
-
let verdict = "no-data";
|
|
113
|
-
let detail = "";
|
|
114
|
-
if (currentValue === null) {
|
|
115
|
-
verdict = "no-data";
|
|
116
|
-
detail = `\u65E0\u6CD5\u83B7\u53D6 ${item.metrics.baselineKey} \u7684\u5F53\u524D\u503C`;
|
|
117
|
-
} else {
|
|
118
|
-
const baseline = item.metrics.baselineValue;
|
|
119
|
-
if (baseline === 0) {
|
|
120
|
-
changePercent = currentValue === 0 ? 0 : 100;
|
|
121
|
-
verdict = currentValue <= 0 ? "effective" : "pending";
|
|
122
|
-
detail = `\u57FA\u7EBF: 0 \u2192 \u5F53\u524D: ${currentValue}`;
|
|
123
|
-
} else {
|
|
124
|
-
changePercent = Math.round((currentValue - baseline) / Math.abs(baseline) * 1e3) / 10;
|
|
125
|
-
const lowerIsBetter = isLowerBetter(item.metrics.baselineKey);
|
|
126
|
-
if (lowerIsBetter) {
|
|
127
|
-
if (changePercent <= -50) {
|
|
128
|
-
verdict = "effective";
|
|
129
|
-
detail = `\u4E0B\u964D ${Math.abs(changePercent)}% (${baseline} \u2192 ${currentValue})`;
|
|
130
|
-
} else if (changePercent <= -20) {
|
|
131
|
-
verdict = "pending";
|
|
132
|
-
detail = `\u4E0B\u964D ${Math.abs(changePercent)}%\uFF0C\u5F85\u8FDB\u4E00\u6B65\u89C2\u5BDF (${baseline} \u2192 ${currentValue})`;
|
|
133
|
-
} else {
|
|
134
|
-
verdict = "ineffective";
|
|
135
|
-
detail = changePercent >= 0 ? `\u672A\u6539\u5584\uFF0C\u53CD\u5347 ${changePercent}% (${baseline} \u2192 ${currentValue})` : `\u4EC5\u4E0B\u964D ${Math.abs(changePercent)}% (${baseline} \u2192 ${currentValue})`;
|
|
136
|
-
}
|
|
137
|
-
} else {
|
|
138
|
-
if (changePercent >= 50) {
|
|
139
|
-
verdict = "effective";
|
|
140
|
-
detail = `\u4E0A\u5347 ${changePercent}% (${baseline} \u2192 ${currentValue})`;
|
|
141
|
-
} else if (changePercent >= 20) {
|
|
142
|
-
verdict = "pending";
|
|
143
|
-
detail = `\u4E0A\u5347 ${changePercent}%\uFF0C\u5F85\u8FDB\u4E00\u6B65\u89C2\u5BDF (${baseline} \u2192 ${currentValue})`;
|
|
144
|
-
} else {
|
|
145
|
-
verdict = "ineffective";
|
|
146
|
-
detail = changePercent <= 0 ? `\u672A\u6539\u5584\uFF0C\u53CD\u964D ${Math.abs(changePercent)}% (${baseline} \u2192 ${currentValue})` : `\u4EC5\u4E0A\u5347 ${changePercent}% (${baseline} \u2192 ${currentValue})`;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
}
|
|
150
|
-
item.metrics.afterValue = currentValue;
|
|
151
|
-
item.metrics.afterDate = (/* @__PURE__ */ new Date()).toISOString();
|
|
152
|
-
if (verdict === "effective" || verdict === "ineffective") {
|
|
153
|
-
item.metrics.verified = true;
|
|
154
|
-
}
|
|
155
|
-
await updateItemMetrics(item.id, item.metrics);
|
|
156
|
-
}
|
|
157
|
-
results.push({
|
|
158
|
-
itemId: item.id,
|
|
159
|
-
title: item.title,
|
|
160
|
-
baselineKey: item.metrics.baselineKey,
|
|
161
|
-
baselineValue: item.metrics.baselineValue,
|
|
162
|
-
afterValue: currentValue,
|
|
163
|
-
changePercent,
|
|
164
|
-
verdict,
|
|
165
|
-
detail
|
|
166
|
-
});
|
|
167
|
-
}
|
|
168
|
-
const summary = {
|
|
169
|
-
total: results.length,
|
|
170
|
-
effective: results.filter((r) => r.verdict === "effective").length,
|
|
171
|
-
ineffective: results.filter((r) => r.verdict === "ineffective").length,
|
|
172
|
-
pending: results.filter((r) => r.verdict === "pending").length,
|
|
173
|
-
noData: results.filter((r) => r.verdict === "no-data").length
|
|
174
|
-
};
|
|
175
|
-
return { timestamp: (/* @__PURE__ */ new Date()).toISOString(), results, summary };
|
|
176
|
-
}
|
|
177
|
-
function isLowerBetter(key) {
|
|
178
|
-
if (key.startsWith("cmd_fail_rate")) return true;
|
|
179
|
-
if (key === "error_count") return true;
|
|
180
|
-
if (key === "todo_count") return true;
|
|
181
|
-
if (key === "package_size") return true;
|
|
182
|
-
return false;
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
export {
|
|
186
|
-
inferBaselineKey,
|
|
187
|
-
getMetricValue,
|
|
188
|
-
recordBaseline,
|
|
189
|
-
verifyCompletedItems
|
|
190
|
-
};
|