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-NP47L7LG.js
DELETED
|
@@ -1,288 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
getEventsSummary,
|
|
3
|
-
readEvents
|
|
4
|
-
} from "./chunk-2CMSCWQW.js";
|
|
5
|
-
import {
|
|
6
|
-
addItem,
|
|
7
|
-
listItems
|
|
8
|
-
} from "./chunk-MGLJ53QN.js";
|
|
9
|
-
|
|
10
|
-
// src/admin/diagnose.ts
|
|
11
|
-
async function runRuleDiagnosis(days = 7) {
|
|
12
|
-
const findings = [];
|
|
13
|
-
const events = await readEvents(days);
|
|
14
|
-
const summary = await getEventsSummary(days);
|
|
15
|
-
if (events.length === 0) {
|
|
16
|
-
return [{
|
|
17
|
-
severity: "warning",
|
|
18
|
-
title: "\u65E0\u4E8B\u4EF6\u6570\u636E",
|
|
19
|
-
detail: `\u8FD1 ${days} \u5929\u6CA1\u6709\u91C7\u96C6\u5230\u4EFB\u4F55\u4E8B\u4EF6`,
|
|
20
|
-
evidence: "\u4E8B\u4EF6\u6587\u4EF6\u4E3A\u7A7A\u6216\u4E0D\u5B58\u5728",
|
|
21
|
-
suggestion: "\u786E\u8BA4 telemetry \u5DF2\u542F\u7528\uFF0C\u6B63\u5E38\u4F7F\u7528 Hypercore \u540E\u4F1A\u81EA\u52A8\u91C7\u96C6",
|
|
22
|
-
suggestedType: "bugfix",
|
|
23
|
-
suggestedPriority: "A",
|
|
24
|
-
suggestedWuxing: "\u6728"
|
|
25
|
-
}];
|
|
26
|
-
}
|
|
27
|
-
for (const [cmd, stats] of Object.entries(summary.cmdCounts)) {
|
|
28
|
-
const failRate = stats.total >= 3 ? stats.fail / stats.total : 0;
|
|
29
|
-
if (failRate > 0.1) {
|
|
30
|
-
const failEvents = events.filter(
|
|
31
|
-
(e) => e.event === "cmd_exec" && e.cmd === cmd && !e.ok
|
|
32
|
-
);
|
|
33
|
-
const errorMessages = failEvents.map((e) => String(e.err || "")).filter(Boolean);
|
|
34
|
-
const topError = mostCommon(errorMessages) || "\u672A\u77E5";
|
|
35
|
-
findings.push({
|
|
36
|
-
severity: "high",
|
|
37
|
-
title: `${cmd} \u5931\u8D25\u7387 ${(failRate * 100).toFixed(0)}%`,
|
|
38
|
-
detail: `\u8FD1 ${days} \u5929\u5185 ${cmd} \u6267\u884C ${stats.total} \u6B21\uFF0C\u5931\u8D25 ${stats.fail} \u6B21`,
|
|
39
|
-
evidence: `\u5E38\u89C1\u9519\u8BEF: ${topError} (${stats.fail}/${stats.total})`,
|
|
40
|
-
suggestion: `\u6392\u67E5 ${cmd} \u547D\u4EE4\u7684\u9519\u8BEF\u5904\u7406\u903B\u8F91`,
|
|
41
|
-
suggestedType: "bugfix",
|
|
42
|
-
suggestedPriority: failRate > 0.2 ? "S" : "A",
|
|
43
|
-
suggestedWuxing: "\u6728"
|
|
44
|
-
});
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
for (const err of summary.errors) {
|
|
48
|
-
if (err.count >= 3) {
|
|
49
|
-
findings.push({
|
|
50
|
-
severity: "high",
|
|
51
|
-
title: `${err.type} \u9519\u8BEF\u9891\u53D1 (${err.count}\u6B21)`,
|
|
52
|
-
detail: `\u8FD1 ${days} \u5929\u5185 ${err.type} \u7C7B\u578B\u9519\u8BEF\u51FA\u73B0 ${err.count} \u6B21`,
|
|
53
|
-
evidence: `\u9519\u8BEF\u7C7B\u578B\u7EDF\u8BA1: ${err.type} = ${err.count}`,
|
|
54
|
-
suggestion: "\u68C0\u67E5\u9519\u8BEF\u6839\u56E0\u5E76\u4FEE\u590D",
|
|
55
|
-
suggestedType: "bugfix",
|
|
56
|
-
suggestedPriority: err.count >= 5 ? "S" : "A",
|
|
57
|
-
suggestedWuxing: "\u6728"
|
|
58
|
-
});
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
const lineEvents = events.filter((e) => e.event === "line_run");
|
|
62
|
-
const lineStats = {};
|
|
63
|
-
for (const e of lineEvents) {
|
|
64
|
-
const name = String(e.line || "unknown");
|
|
65
|
-
if (!lineStats[name]) lineStats[name] = { durations: [], fails: 0, total: 0 };
|
|
66
|
-
lineStats[name].total++;
|
|
67
|
-
if (e.duration_ms) lineStats[name].durations.push(e.duration_ms);
|
|
68
|
-
if (!e.ok) lineStats[name].fails++;
|
|
69
|
-
}
|
|
70
|
-
for (const [name, stats] of Object.entries(lineStats)) {
|
|
71
|
-
if (stats.durations.length >= 3) {
|
|
72
|
-
const avg = stats.durations.reduce((a, b) => a + b, 0) / stats.durations.length;
|
|
73
|
-
const p95 = stats.durations.sort((a, b) => a - b)[Math.floor(stats.durations.length * 0.95)];
|
|
74
|
-
if (p95 > 3e4) {
|
|
75
|
-
findings.push({
|
|
76
|
-
severity: "warning",
|
|
77
|
-
title: `\u751F\u4EA7\u7EBF "${name}" \u8017\u65F6\u504F\u9AD8`,
|
|
78
|
-
detail: `\u5E73\u5747 ${(avg / 1e3).toFixed(1)}s, p95 ${(p95 / 1e3).toFixed(1)}s (${stats.total}\u6B21\u8FD0\u884C)`,
|
|
79
|
-
evidence: `\u8017\u65F6\u6570\u636E: avg=${(avg / 1e3).toFixed(1)}s, p95=${(p95 / 1e3).toFixed(1)}s`,
|
|
80
|
-
suggestion: "\u68C0\u67E5 prompt \u957F\u5EA6\u6216\u8003\u8651\u5207\u6362\u66F4\u5FEB\u7684\u6A21\u578B",
|
|
81
|
-
suggestedType: "improvement",
|
|
82
|
-
suggestedPriority: "A",
|
|
83
|
-
suggestedWuxing: "\u6728"
|
|
84
|
-
});
|
|
85
|
-
}
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
const allCmds = events.filter((e) => e.event === "cmd_exec").map((e) => String(e.cmd));
|
|
89
|
-
const knownCmds = ["/model", "/team", "/memory", "/network", "/admin", "/run", "/git", "/session"];
|
|
90
|
-
for (const cmd of knownCmds) {
|
|
91
|
-
if (!allCmds.includes(cmd) && events.length > 20) {
|
|
92
|
-
findings.push({
|
|
93
|
-
severity: "opportunity",
|
|
94
|
-
title: `${cmd} \u8FD1 ${days} \u5929\u672A\u4F7F\u7528`,
|
|
95
|
-
detail: `\u5728 ${events.length} \u6761\u4E8B\u4EF6\u4E2D\u6CA1\u6709 ${cmd} \u7684\u4F7F\u7528\u8BB0\u5F55`,
|
|
96
|
-
evidence: `${cmd} \u8C03\u7528\u6B21\u6570: 0`,
|
|
97
|
-
suggestion: "\u8BC4\u4F30\u8BE5\u529F\u80FD\u662F\u5426\u9700\u8981\u6539\u8FDB\u5165\u53E3\u6216\u8003\u8651\u4E0B\u7EBF",
|
|
98
|
-
suggestedType: "idea",
|
|
99
|
-
suggestedPriority: "C",
|
|
100
|
-
suggestedWuxing: "\u91D1"
|
|
101
|
-
});
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
const sessionEnds = events.filter((e) => e.event === "session_end");
|
|
105
|
-
if (sessionEnds.length >= 4) {
|
|
106
|
-
const mid = Math.floor(sessionEnds.length / 2);
|
|
107
|
-
const firstHalf = sessionEnds.slice(0, mid);
|
|
108
|
-
const secondHalf = sessionEnds.slice(mid);
|
|
109
|
-
const avgFirst = firstHalf.reduce((s, e) => s + (e.rounds || 0), 0) / firstHalf.length;
|
|
110
|
-
const avgSecond = secondHalf.reduce((s, e) => s + (e.rounds || 0), 0) / secondHalf.length;
|
|
111
|
-
if (avgFirst > 0 && avgSecond / avgFirst < 0.6) {
|
|
112
|
-
findings.push({
|
|
113
|
-
severity: "warning",
|
|
114
|
-
title: `\u4F1A\u8BDD\u6DF1\u5EA6\u4E0B\u964D (${avgFirst.toFixed(1)} \u2192 ${avgSecond.toFixed(1)} \u8F6E)`,
|
|
115
|
-
detail: `\u524D\u534A\u671F\u5E73\u5747 ${avgFirst.toFixed(1)} \u8F6E\uFF0C\u540E\u534A\u671F ${avgSecond.toFixed(1)} \u8F6E`,
|
|
116
|
-
evidence: `\u4E0B\u964D\u5E45\u5EA6: ${((1 - avgSecond / avgFirst) * 100).toFixed(0)}%`,
|
|
117
|
-
suggestion: "\u5206\u6790\u7528\u6237\u662F\u5426\u63D0\u524D\u653E\u5F03\u8FD8\u662F\u9700\u6C42\u53D8\u7B80\u77ED",
|
|
118
|
-
suggestedType: "idea",
|
|
119
|
-
suggestedPriority: "B",
|
|
120
|
-
suggestedWuxing: "\u6C34"
|
|
121
|
-
});
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
return findings;
|
|
125
|
-
}
|
|
126
|
-
function buildDiagnosePrompt(summary, ruleFindings) {
|
|
127
|
-
const parts = [];
|
|
128
|
-
parts.push(`\u4F60\u662F\u8D85\u534F\u4F53 (Hypercore) \u9879\u76EE\u7684\u5185\u89C2\u8BCA\u65AD\u5F15\u64CE\u3002\u4EE5\u4E0B\u662F\u8FD1 ${summary.period.days} \u5929\u7684\u4F7F\u7528\u6570\u636E\u6458\u8981\u3002`);
|
|
129
|
-
parts.push(`\u8BF7\u5206\u6790\u5E76\u8865\u5145\u89C4\u5219\u5F15\u64CE\u53EF\u80FD\u9057\u6F0F\u7684\u6D1E\u5BDF\u3002
|
|
130
|
-
`);
|
|
131
|
-
parts.push(`## \u57FA\u7840\u7EDF\u8BA1`);
|
|
132
|
-
parts.push(`- \u4E8B\u4EF6\u603B\u6570: ${summary.totalEvents}`);
|
|
133
|
-
parts.push(`- \u4F1A\u8BDD\u6570: ${summary.totalSessions}`);
|
|
134
|
-
parts.push(`- \u5E73\u5747\u4F1A\u8BDD\u8F6E\u6B21: ${summary.avgSessionRounds}`);
|
|
135
|
-
parts.push(`- \u7EDF\u8BA1\u5468\u671F: ${summary.period.from} \u2192 ${summary.period.to}
|
|
136
|
-
`);
|
|
137
|
-
if (Object.keys(summary.cmdCounts).length > 0) {
|
|
138
|
-
parts.push(`## \u547D\u4EE4\u4F7F\u7528\u7EDF\u8BA1`);
|
|
139
|
-
for (const [cmd, stats] of Object.entries(summary.cmdCounts)) {
|
|
140
|
-
const failPart = stats.fail > 0 ? ` (\u5931\u8D25${stats.fail}\u6B21, \u7387${(stats.fail / stats.total * 100).toFixed(0)}%)` : "";
|
|
141
|
-
parts.push(`- ${cmd}: ${stats.total}\u6B21${failPart}`);
|
|
142
|
-
}
|
|
143
|
-
parts.push("");
|
|
144
|
-
}
|
|
145
|
-
if (summary.errors.length > 0) {
|
|
146
|
-
parts.push(`## \u9519\u8BEF\u7EDF\u8BA1`);
|
|
147
|
-
for (const e of summary.errors) {
|
|
148
|
-
parts.push(`- ${e.type}: ${e.count}\u6B21`);
|
|
149
|
-
}
|
|
150
|
-
parts.push("");
|
|
151
|
-
}
|
|
152
|
-
if (ruleFindings.length > 0) {
|
|
153
|
-
parts.push(`## \u89C4\u5219\u5F15\u64CE\u5DF2\u53D1\u73B0`);
|
|
154
|
-
for (const f of ruleFindings) {
|
|
155
|
-
parts.push(`- [${f.severity}] ${f.title}: ${f.detail}`);
|
|
156
|
-
}
|
|
157
|
-
parts.push("");
|
|
158
|
-
}
|
|
159
|
-
parts.push(`## \u4F60\u7684\u4EFB\u52A1`);
|
|
160
|
-
parts.push(`\u57FA\u4E8E\u4EE5\u4E0A\u6570\u636E\uFF0C\u8F93\u51FA\uFF1A`);
|
|
161
|
-
parts.push(`1. \u89C4\u5219\u5F15\u64CE\u53EF\u80FD\u9057\u6F0F\u7684\u95EE\u9898\u6216\u6A21\u5F0F`);
|
|
162
|
-
parts.push(`2. \u4F7F\u7528\u8D8B\u52BF\u7684\u6DF1\u5C42\u89E3\u8BFB`);
|
|
163
|
-
parts.push(`3. \u4EA7\u54C1\u6539\u8FDB\u673A\u4F1A`);
|
|
164
|
-
parts.push(`
|
|
165
|
-
\u6BCF\u6761\u53D1\u73B0\u8BF7\u7528\u4EE5\u4E0B\u683C\u5F0F\uFF1A`);
|
|
166
|
-
parts.push(`### [severity: high/warning/opportunity] \u6807\u9898`);
|
|
167
|
-
parts.push(`- \u8BE6\u60C5: ...`);
|
|
168
|
-
parts.push(`- \u8BC1\u636E: ...`);
|
|
169
|
-
parts.push(`- \u5EFA\u8BAE: ...`);
|
|
170
|
-
parts.push(`- \u7C7B\u578B: bugfix/feature/improvement/idea`);
|
|
171
|
-
parts.push(`- \u4F18\u5148\u7EA7: S/A/B/C`);
|
|
172
|
-
parts.push(`- \u4E94\u884C: \u6728/\u706B/\u6C34/\u91D1/\u571F`);
|
|
173
|
-
parts.push(`
|
|
174
|
-
\u5982\u679C\u6CA1\u6709\u989D\u5916\u53D1\u73B0\uFF0C\u76F4\u63A5\u8BF4"\u89C4\u5219\u5F15\u64CE\u5DF2\u8986\u76D6\u4E3B\u8981\u95EE\u9898"\u3002`);
|
|
175
|
-
return parts.join("\n");
|
|
176
|
-
}
|
|
177
|
-
function parseAIFindings(text) {
|
|
178
|
-
const findings = [];
|
|
179
|
-
const blocks = text.split(/###\s+\[/).filter(Boolean);
|
|
180
|
-
for (const block of blocks) {
|
|
181
|
-
const severityMatch = block.match(/^(high|warning|opportunity)\]\s*(.+)/);
|
|
182
|
-
if (!severityMatch) continue;
|
|
183
|
-
const severity = severityMatch[1];
|
|
184
|
-
const title = severityMatch[2].trim();
|
|
185
|
-
const detail = extractField(block, "\u8BE6\u60C5") || "";
|
|
186
|
-
const evidence = extractField(block, "\u8BC1\u636E") || "";
|
|
187
|
-
const suggestion = extractField(block, "\u5EFA\u8BAE") || "";
|
|
188
|
-
const typeStr = extractField(block, "\u7C7B\u578B") || "idea";
|
|
189
|
-
const priorityStr = extractField(block, "\u4F18\u5148\u7EA7") || "B";
|
|
190
|
-
const wuxingStr = extractField(block, "\u4E94\u884C") || "\u6728";
|
|
191
|
-
findings.push({
|
|
192
|
-
severity,
|
|
193
|
-
title,
|
|
194
|
-
detail,
|
|
195
|
-
evidence,
|
|
196
|
-
suggestion,
|
|
197
|
-
suggestedType: ["bugfix", "feature", "improvement", "idea"].includes(typeStr) ? typeStr : "idea",
|
|
198
|
-
suggestedPriority: ["S", "A", "B", "C"].includes(priorityStr) ? priorityStr : "B",
|
|
199
|
-
suggestedWuxing: ["\u6728", "\u706B", "\u6C34", "\u91D1", "\u571F"].includes(wuxingStr) ? wuxingStr : "\u6728"
|
|
200
|
-
});
|
|
201
|
-
}
|
|
202
|
-
return findings;
|
|
203
|
-
}
|
|
204
|
-
function extractField(block, fieldName) {
|
|
205
|
-
const regex = new RegExp(`-\\s*${fieldName}[\uFF1A:]\\s*(.+)`, "i");
|
|
206
|
-
const match = block.match(regex);
|
|
207
|
-
return match ? match[1].trim() : "";
|
|
208
|
-
}
|
|
209
|
-
async function runAIDiagnosis(ctx, days = 7) {
|
|
210
|
-
const summary = await getEventsSummary(days);
|
|
211
|
-
const ruleFindings = await runRuleDiagnosis(days);
|
|
212
|
-
const prompt = buildDiagnosePrompt(summary, ruleFindings);
|
|
213
|
-
let aiRawText = "";
|
|
214
|
-
const aiFindings = [];
|
|
215
|
-
try {
|
|
216
|
-
if (ctx.config.modelConfig.sdkType === "openai") {
|
|
217
|
-
const { streamOpenAIChat } = await import("./openai-compat-R7EKWG6Z.js");
|
|
218
|
-
const OpenAI = (await import("openai")).default;
|
|
219
|
-
const client = ctx.getClient();
|
|
220
|
-
const result = await streamOpenAIChat(client, [
|
|
221
|
-
{ role: "system", content: "\u4F60\u662F\u8D85\u534F\u4F53\u9879\u76EE\u7684\u5185\u89C2\u8BCA\u65AD\u5F15\u64CE\u3002\u5206\u6790\u6570\u636E\uFF0C\u8F93\u51FA\u7CBE\u51C6\u8BCA\u65AD\u3002\u7528\u4E2D\u6587\u56DE\u590D\u3002" },
|
|
222
|
-
{ role: "user", content: prompt }
|
|
223
|
-
], {
|
|
224
|
-
model: ctx.config.modelConfig.model,
|
|
225
|
-
tools: [],
|
|
226
|
-
onChunk: (text) => {
|
|
227
|
-
process.stdout.write(text);
|
|
228
|
-
},
|
|
229
|
-
onToolCall: () => {
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
aiRawText = result.content.trim();
|
|
233
|
-
} else {
|
|
234
|
-
const { streamCallLLM } = await import("./claude-4BX3MJSK.js");
|
|
235
|
-
const Anthropic = (await import("@anthropic-ai/sdk")).default;
|
|
236
|
-
const client = ctx.getClient();
|
|
237
|
-
const result = await streamCallLLM(client, {
|
|
238
|
-
systemPrompt: "\u4F60\u662F\u8D85\u534F\u4F53\u9879\u76EE\u7684\u5185\u89C2\u8BCA\u65AD\u5F15\u64CE\u3002\u5206\u6790\u6570\u636E\uFF0C\u8F93\u51FA\u7CBE\u51C6\u8BCA\u65AD\u3002\u7528\u4E2D\u6587\u56DE\u590D\u3002",
|
|
239
|
-
userPrompt: prompt,
|
|
240
|
-
history: [],
|
|
241
|
-
tools: [],
|
|
242
|
-
model: ctx.config.modelConfig.model,
|
|
243
|
-
onText: (text) => {
|
|
244
|
-
process.stdout.write(text);
|
|
245
|
-
},
|
|
246
|
-
onToolCall: () => {
|
|
247
|
-
}
|
|
248
|
-
});
|
|
249
|
-
aiRawText = result.output.trim();
|
|
250
|
-
}
|
|
251
|
-
aiFindings.push(...parseAIFindings(aiRawText));
|
|
252
|
-
} catch (err) {
|
|
253
|
-
aiRawText = `AI \u8BCA\u65AD\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`;
|
|
254
|
-
}
|
|
255
|
-
return { ruleFindings, aiFindings, aiRawText };
|
|
256
|
-
}
|
|
257
|
-
async function findingsToBacklog(findings, targetVersion) {
|
|
258
|
-
const existing = await listItems();
|
|
259
|
-
const existingTitles = new Set(existing.map((i) => i.title.toLowerCase()));
|
|
260
|
-
const createdIds = [];
|
|
261
|
-
for (const f of findings) {
|
|
262
|
-
if (existingTitles.has(f.title.toLowerCase())) continue;
|
|
263
|
-
const item = await addItem({
|
|
264
|
-
title: f.title,
|
|
265
|
-
description: f.detail,
|
|
266
|
-
type: f.suggestedType,
|
|
267
|
-
wuxing: f.suggestedWuxing,
|
|
268
|
-
priority: f.suggestedPriority,
|
|
269
|
-
targetVersion,
|
|
270
|
-
source: "auto-diagnose",
|
|
271
|
-
evidence: f.evidence
|
|
272
|
-
});
|
|
273
|
-
createdIds.push(item.id);
|
|
274
|
-
}
|
|
275
|
-
return createdIds;
|
|
276
|
-
}
|
|
277
|
-
function mostCommon(arr) {
|
|
278
|
-
if (arr.length === 0) return void 0;
|
|
279
|
-
const counts = {};
|
|
280
|
-
for (const s of arr) counts[s] = (counts[s] || 0) + 1;
|
|
281
|
-
return Object.entries(counts).sort((a, b) => b[1] - a[1])[0]?.[0];
|
|
282
|
-
}
|
|
283
|
-
|
|
284
|
-
export {
|
|
285
|
-
runRuleDiagnosis,
|
|
286
|
-
runAIDiagnosis,
|
|
287
|
-
findingsToBacklog
|
|
288
|
-
};
|
package/dist/chunk-O6MG7TOH.js
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
HYPERCORE_DIR
|
|
3
|
-
} from "./chunk-I7WI3BMB.js";
|
|
4
|
-
|
|
5
|
-
// src/ui/keybindings.ts
|
|
6
|
-
import { existsSync } from "fs";
|
|
7
|
-
import { readFile } from "fs/promises";
|
|
8
|
-
import { join } from "path";
|
|
9
|
-
var DEFAULT_BINDINGS = {
|
|
10
|
-
"ctrl+t": "todo",
|
|
11
|
-
"ctrl+n": "new",
|
|
12
|
-
"ctrl+k": "palette"
|
|
13
|
-
};
|
|
14
|
-
var loadedBindings = null;
|
|
15
|
-
async function loadKeyBindings() {
|
|
16
|
-
const merged = { ...DEFAULT_BINDINGS };
|
|
17
|
-
const filePath = join(HYPERCORE_DIR, "keybindings.json");
|
|
18
|
-
if (existsSync(filePath)) {
|
|
19
|
-
try {
|
|
20
|
-
const content = await readFile(filePath, "utf-8");
|
|
21
|
-
const userBindings = JSON.parse(content);
|
|
22
|
-
Object.assign(merged, userBindings);
|
|
23
|
-
} catch {
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
loadedBindings = merged;
|
|
27
|
-
return merged;
|
|
28
|
-
}
|
|
29
|
-
function getKeyBindings() {
|
|
30
|
-
return loadedBindings || DEFAULT_BINDINGS;
|
|
31
|
-
}
|
|
32
|
-
function keypressToCombo(key) {
|
|
33
|
-
if (!key.name) return null;
|
|
34
|
-
const parts = [];
|
|
35
|
-
if (key.ctrl) parts.push("ctrl");
|
|
36
|
-
if (key.meta) parts.push("alt");
|
|
37
|
-
if (key.shift) parts.push("shift");
|
|
38
|
-
parts.push(key.name);
|
|
39
|
-
return parts.join("+");
|
|
40
|
-
}
|
|
41
|
-
function matchKeyBinding(key) {
|
|
42
|
-
const combo = keypressToCombo(key);
|
|
43
|
-
if (!combo) return null;
|
|
44
|
-
const bindings = getKeyBindings();
|
|
45
|
-
return bindings[combo] || null;
|
|
46
|
-
}
|
|
47
|
-
function listKeyBindings() {
|
|
48
|
-
const bindings = getKeyBindings();
|
|
49
|
-
return Object.entries(bindings).map(([combo, command]) => ({ combo, command }));
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
export {
|
|
53
|
-
loadKeyBindings,
|
|
54
|
-
getKeyBindings,
|
|
55
|
-
keypressToCombo,
|
|
56
|
-
matchKeyBinding,
|
|
57
|
-
listKeyBindings
|
|
58
|
-
};
|
package/dist/chunk-OPZYEVYR.js
DELETED
|
@@ -1,150 +0,0 @@
|
|
|
1
|
-
import {
|
|
2
|
-
listItems
|
|
3
|
-
} from "./chunk-MGLJ53QN.js";
|
|
4
|
-
|
|
5
|
-
// src/admin/roadmap.ts
|
|
6
|
-
import { join } from "path";
|
|
7
|
-
import { readFile, writeFile, mkdir } from "fs/promises";
|
|
8
|
-
import { existsSync } from "fs";
|
|
9
|
-
var HYPERCORE_DIR = join(process.env.HOME || "~", ".hypercore");
|
|
10
|
-
var ADMIN_DIR = join(HYPERCORE_DIR, "admin");
|
|
11
|
-
var MILESTONES_FILE = join(ADMIN_DIR, "milestones.json");
|
|
12
|
-
async function ensureDir() {
|
|
13
|
-
if (!existsSync(ADMIN_DIR)) {
|
|
14
|
-
await mkdir(ADMIN_DIR, { recursive: true });
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
async function loadStore() {
|
|
18
|
-
await ensureDir();
|
|
19
|
-
if (!existsSync(MILESTONES_FILE)) {
|
|
20
|
-
return { milestones: [] };
|
|
21
|
-
}
|
|
22
|
-
try {
|
|
23
|
-
const raw = await readFile(MILESTONES_FILE, "utf-8");
|
|
24
|
-
return JSON.parse(raw);
|
|
25
|
-
} catch {
|
|
26
|
-
return { milestones: [] };
|
|
27
|
-
}
|
|
28
|
-
}
|
|
29
|
-
async function saveStore(store) {
|
|
30
|
-
await ensureDir();
|
|
31
|
-
await writeFile(MILESTONES_FILE, JSON.stringify(store, null, 2), "utf-8");
|
|
32
|
-
}
|
|
33
|
-
async function addMilestone(version, name, description) {
|
|
34
|
-
const store = await loadStore();
|
|
35
|
-
if (store.milestones.find((m) => m.version === version)) {
|
|
36
|
-
throw new Error(`\u91CC\u7A0B\u7891 ${version} \u5DF2\u5B58\u5728`);
|
|
37
|
-
}
|
|
38
|
-
const milestone = {
|
|
39
|
-
version,
|
|
40
|
-
name,
|
|
41
|
-
description: description || "",
|
|
42
|
-
status: "planning",
|
|
43
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
44
|
-
doneAt: null
|
|
45
|
-
};
|
|
46
|
-
store.milestones.push(milestone);
|
|
47
|
-
await saveStore(store);
|
|
48
|
-
return milestone;
|
|
49
|
-
}
|
|
50
|
-
async function doneMilestone(version) {
|
|
51
|
-
const store = await loadStore();
|
|
52
|
-
const ms = store.milestones.find((m) => m.version === version);
|
|
53
|
-
if (!ms) return null;
|
|
54
|
-
ms.status = "done";
|
|
55
|
-
ms.doneAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
56
|
-
await saveStore(store);
|
|
57
|
-
return ms;
|
|
58
|
-
}
|
|
59
|
-
async function activateMilestone(version) {
|
|
60
|
-
const store = await loadStore();
|
|
61
|
-
const ms = store.milestones.find((m) => m.version === version);
|
|
62
|
-
if (!ms) return null;
|
|
63
|
-
ms.status = "active";
|
|
64
|
-
await saveStore(store);
|
|
65
|
-
return ms;
|
|
66
|
-
}
|
|
67
|
-
async function listMilestones() {
|
|
68
|
-
const store = await loadStore();
|
|
69
|
-
return store.milestones;
|
|
70
|
-
}
|
|
71
|
-
async function getMilestone(version) {
|
|
72
|
-
const store = await loadStore();
|
|
73
|
-
return store.milestones.find((m) => m.version === version) || null;
|
|
74
|
-
}
|
|
75
|
-
async function getRoadmap() {
|
|
76
|
-
const allItems = await listItems();
|
|
77
|
-
const milestones = await listMilestones();
|
|
78
|
-
const grouped = {};
|
|
79
|
-
const unversioned = [];
|
|
80
|
-
for (const item of allItems) {
|
|
81
|
-
if (item.targetVersion) {
|
|
82
|
-
if (!grouped[item.targetVersion]) grouped[item.targetVersion] = [];
|
|
83
|
-
grouped[item.targetVersion].push(item);
|
|
84
|
-
} else {
|
|
85
|
-
unversioned.push(item);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
for (const ms of milestones) {
|
|
89
|
-
if (!grouped[ms.version]) grouped[ms.version] = [];
|
|
90
|
-
}
|
|
91
|
-
const versions = Object.keys(grouped).sort(compareVersions);
|
|
92
|
-
const roadmap = versions.map((ver) => {
|
|
93
|
-
const items = grouped[ver];
|
|
94
|
-
const milestone = milestones.find((m) => m.version === ver) || null;
|
|
95
|
-
const done = items.filter((i) => i.status === "done").length;
|
|
96
|
-
const developing = items.filter((i) => i.status === "developing").length;
|
|
97
|
-
const planned = items.filter((i) => i.status === "planned").length;
|
|
98
|
-
const idea = items.filter((i) => i.status === "idea").length;
|
|
99
|
-
const total = items.length;
|
|
100
|
-
return {
|
|
101
|
-
version: ver,
|
|
102
|
-
milestone,
|
|
103
|
-
items,
|
|
104
|
-
stats: {
|
|
105
|
-
total,
|
|
106
|
-
done,
|
|
107
|
-
developing,
|
|
108
|
-
planned,
|
|
109
|
-
idea,
|
|
110
|
-
progress: total > 0 ? Math.round(done / total * 100) : 0
|
|
111
|
-
}
|
|
112
|
-
};
|
|
113
|
-
});
|
|
114
|
-
if (unversioned.length > 0) {
|
|
115
|
-
const done = unversioned.filter((i) => i.status === "done").length;
|
|
116
|
-
roadmap.push({
|
|
117
|
-
version: "(\u672A\u5206\u914D)",
|
|
118
|
-
milestone: null,
|
|
119
|
-
items: unversioned,
|
|
120
|
-
stats: {
|
|
121
|
-
total: unversioned.length,
|
|
122
|
-
done,
|
|
123
|
-
developing: unversioned.filter((i) => i.status === "developing").length,
|
|
124
|
-
planned: unversioned.filter((i) => i.status === "planned").length,
|
|
125
|
-
idea: unversioned.filter((i) => i.status === "idea").length,
|
|
126
|
-
progress: unversioned.length > 0 ? Math.round(done / unversioned.length * 100) : 0
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
}
|
|
130
|
-
return roadmap;
|
|
131
|
-
}
|
|
132
|
-
function compareVersions(a, b) {
|
|
133
|
-
const normalize = (v) => v.replace(/^v/, "").split(".").map((n) => parseInt(n) || 0);
|
|
134
|
-
const aParts = normalize(a);
|
|
135
|
-
const bParts = normalize(b);
|
|
136
|
-
for (let i = 0; i < Math.max(aParts.length, bParts.length); i++) {
|
|
137
|
-
const diff = (aParts[i] || 0) - (bParts[i] || 0);
|
|
138
|
-
if (diff !== 0) return diff;
|
|
139
|
-
}
|
|
140
|
-
return 0;
|
|
141
|
-
}
|
|
142
|
-
|
|
143
|
-
export {
|
|
144
|
-
addMilestone,
|
|
145
|
-
doneMilestone,
|
|
146
|
-
activateMilestone,
|
|
147
|
-
listMilestones,
|
|
148
|
-
getMilestone,
|
|
149
|
-
getRoadmap
|
|
150
|
-
};
|