@lmzhen/dsh-evolution-skill-health 0.25.6 → 0.25.7
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/lib/client.js +87 -8
- package/lib/types/client/styles.d.ts +19 -1
- package/package.json +3 -3
package/lib/client.js
CHANGED
|
@@ -74,10 +74,12 @@ window.__ModuleLoader__.load({
|
|
|
74
74
|
"line": "位置:{path}",
|
|
75
75
|
"line.unknown": "位置:未知",
|
|
76
76
|
"unreadable.note": "读不到内容,因此无法判断(不是「通过」)。",
|
|
77
|
-
"loading.failed": "读取失败——现在判断不了;点「刷新」重试。"
|
|
77
|
+
"loading.failed": "读取失败——现在判断不了;点「刷新」重试。",
|
|
78
|
+
"read.failed": "这次没读到数据(下面一行是原始信息):"
|
|
78
79
|
};
|
|
79
80
|
/** English dictionary. */
|
|
80
81
|
const en = {
|
|
82
|
+
"read.failed": "This read failed (raw message below):",
|
|
81
83
|
"entry.label": "Skill Health",
|
|
82
84
|
"title": "Skill Health",
|
|
83
85
|
"hint": "What the health engine found, aggregated by rule. A rule whose threshold is not calibrated yet is named without a number; skills that cannot be read are listed as unreadable, never as fine.",
|
|
@@ -134,10 +136,40 @@ window.__ModuleLoader__.load({
|
|
|
134
136
|
}
|
|
135
137
|
return [...table.values()].sort((a, b) => b.skills.length - a.skills.length || a.rule.localeCompare(b.rule));
|
|
136
138
|
}
|
|
137
|
-
/** The rule
|
|
139
|
+
/** The verdict a rule's row speaks in: the worst one among the skills that carry it. */
|
|
140
|
+
function worstVerdict(face, skills) {
|
|
141
|
+
const order = [
|
|
142
|
+
"error",
|
|
143
|
+
"warn",
|
|
144
|
+
"unreadable",
|
|
145
|
+
"ok"
|
|
146
|
+
];
|
|
147
|
+
let worst = "ok";
|
|
148
|
+
for (const row of face.rows) {
|
|
149
|
+
if (!skills.includes(row.name)) continue;
|
|
150
|
+
if (order.indexOf(row.verdict) < order.indexOf(worst)) worst = row.verdict;
|
|
151
|
+
}
|
|
152
|
+
return worst;
|
|
153
|
+
}
|
|
154
|
+
/** The rule table: a grid so counts line up, with a tone bar per row and skill pills. */
|
|
138
155
|
function ruleTable(face, t) {
|
|
139
156
|
const rows = byRule(face.rows);
|
|
140
|
-
|
|
157
|
+
const cell = (role, children, key) => (0, react.createElement)("div", key === void 0 ? { "data-role": role } : {
|
|
158
|
+
"data-role": role,
|
|
159
|
+
key
|
|
160
|
+
}, children);
|
|
161
|
+
return (0, react.createElement)("div", { "data-role": "rule-table" }, (0, react.createElement)("div", {
|
|
162
|
+
"data-role": "rule-row",
|
|
163
|
+
"data-role-head": "true"
|
|
164
|
+
}, (0, react.createElement)("div", { "data-role": "rule-name" }, t("col.rule")), (0, react.createElement)("div", { "data-role": "skills" }, t("col.skills")), (0, react.createElement)("div", { "data-role": "rule-count" }, t("col.count"))), rows.map((entry) => (0, react.createElement)("div", {
|
|
165
|
+
key: entry.rule,
|
|
166
|
+
"data-role": "rule-row",
|
|
167
|
+
"data-tone": worstVerdict(face, entry.skills)
|
|
168
|
+
}, cell("rule-name", entry.rule), cell("skills", entry.skills.map((name, i) => (0, react.createElement)("span", {
|
|
169
|
+
"data-role": "skill-pill",
|
|
170
|
+
key: name + ":" + String(i),
|
|
171
|
+
title: name
|
|
172
|
+
}, name))), cell("rule-count", entry.count === 0 ? t("count.notCalibrated") : String(entry.count)))));
|
|
141
173
|
}
|
|
142
174
|
/**
|
|
143
175
|
* Render the panel.
|
|
@@ -168,7 +200,15 @@ window.__ModuleLoader__.load({
|
|
|
168
200
|
};
|
|
169
201
|
}, [face]);
|
|
170
202
|
const counts = new Map(KINDS.map((kind) => [kind, view.rows.filter((row) => row.verdict === kind).length]));
|
|
171
|
-
|
|
203
|
+
const stats = (0, react.createElement)("div", { "data-role": "stats" }, KINDS.map((kind) => (0, react.createElement)("div", {
|
|
204
|
+
key: kind,
|
|
205
|
+
"data-role": "stat",
|
|
206
|
+
"data-tone": kind
|
|
207
|
+
}, (0, react.createElement)("div", { "data-role": "stat-value" }, String(counts.get(kind) ?? 0)), (0, react.createElement)("div", { "data-role": "stat-label" }, t("verdict." + kind)))));
|
|
208
|
+
return (0, react.createElement)("section", null, (0, react.createElement)("p", { "data-role": "hint" }, t("hint")), stats, view.truncated ? (0, react.createElement)("p", { "data-role": "note" }, t("loading.failed")) : null, failed === void 0 ? null : (0, react.createElement)("p", { "data-role": "note" }, t("read.failed") + " " + failed), view.rows.length === 0 ? (0, react.createElement)("p", { "data-role": "note" }, t("empty.noneReported")) : null, (0, react.createElement)("h3", { "data-role": "group-title" }, t("group.byRule")), ruleTable(view, t), view.rows.filter((row) => row.verdict === "unreadable").map((row) => (0, react.createElement)("p", {
|
|
209
|
+
key: row.name + ":unreadable",
|
|
210
|
+
"data-role": "note"
|
|
211
|
+
}, row.name + " — " + t("unreadable.note"))));
|
|
172
212
|
}
|
|
173
213
|
//#endregion
|
|
174
214
|
//#region src/client/styles.ts
|
|
@@ -177,17 +217,56 @@ window.__ModuleLoader__.load({
|
|
|
177
217
|
* the text itself and injects one tagged <style> element; the tag id keeps a hot reload from stacking
|
|
178
218
|
* copies. Only the panel body is styled — the sidebar owns the row and its glyph slot.
|
|
179
219
|
*
|
|
180
|
-
*
|
|
220
|
+
* Token discipline (the family gate `verify-client-tokens --strict` enforces it): every `--evo-*` name
|
|
221
|
+
* below is DECLARED in `packages/scripts/client-tokens.json` — the family scale — and every `--dsw-*`
|
|
222
|
+
* name is a platform semantic alias (packages/client/ui-theme/src/styles). No type step, space, radius,
|
|
223
|
+
* hairline or colour is invented here, and no pixel geometry literal appears.
|
|
224
|
+
*
|
|
225
|
+
* Metrics are COPIED from the platform’s own components rather than invented, each cited here:
|
|
226
|
+
*
|
|
227
|
+
* - hover and current-row fills (`--dsw-alias-interactive-bg-hover`) follow the platform sidebar row
|
|
228
|
+
* (client/ui-sidebar/…/SidebarRoot.module.css), as the sibling panel does;
|
|
229
|
+
* - label steps (`--dsw-alias-label-primary/secondary/tertiary`) and the card hairline
|
|
230
|
+
* (`--evo-hairline-width`, the scale’s copy of the platform’s 0.5px card border) come from
|
|
231
|
+
* client/ui-chat/…/GenericCommandCard.module.css;
|
|
232
|
+
* - the control radius (`--evo-radius-control`, the scale’s copy of the platform field radius) comes
|
|
233
|
+
* from client/ui-primitives/Input.module.css; the capsule uses `--evo-radius-pill`;
|
|
234
|
+
* - verdict colours are the platform STATE aliases (state-success / state-warn / state-error) plus the
|
|
235
|
+
* scale’s `--evo-tone-quiet`; the validity bar is an inset shadow, not a border-width literal.
|
|
236
|
+
*
|
|
237
|
+
* Layout: four verdict cards, then the by-rule table as a grid (rule / skills / count) so numbers sit
|
|
238
|
+
* on tabular figures and long skill lists wrap into pills instead of ragged comma text.
|
|
181
239
|
* @module @lmzhen/dsh-evolution-skill-health/client
|
|
182
240
|
*/
|
|
183
241
|
/** Tag id for the injected <style>, so a hot reload replaces rather than stacks it. */
|
|
184
242
|
const CSS_TAG_ID = "dsh-evolution-skill-health";
|
|
185
243
|
/** The panel stylesheet text. */
|
|
186
244
|
const CSS = [
|
|
187
|
-
":where(.dsh-evolution-skill-health) { display: flex; flex-direction: column; gap: var(--evo-space-8); padding: var(--evo-space-12); }",
|
|
188
245
|
":where(.dsh-evolution-skill-health) { --evo-type-lg:calc(1em + 2px);--evo-type-body:1em;--evo-type-sm:calc(1em - 1px);--evo-type-xs:calc(1em - 2px);--evo-space-2:2px;--evo-space-4:4px;--evo-space-6:6px;--evo-space-8:8px;--evo-space-10:10px;--evo-space-12:12px;--evo-space-14:14px;--evo-space-16:16px;--evo-space-20:20px;--evo-radius-chip:4px;--evo-radius-control:8px;--evo-radius-surface:12px;--evo-radius-pill:999px;--evo-hairline-width:.5px;--evo-hairline-marker:2px;--evo-measure-read:80ch;--evo-leading-base:1.5;--evo-tone-quiet:var(--dsw-alias-label-secondary);--evo-tone-primary:var(--dsw-alias-brand-primary);--evo-tone-danger:var(--dsw-alias-state-error-primary);--evo-tone-success:var(--dsw-alias-state-success-primary);--evo-focus-ring:2px solid var(--dsw-alias-label-primary);--evo-focus-offset:-2px;--evo-cap-aside:280px;--evo-cap-block:260px }",
|
|
189
|
-
":where(.dsh-evolution-skill-health
|
|
190
|
-
":where(.dsh-evolution-skill-health [data-role=\"
|
|
246
|
+
":where(.dsh-evolution-skill-health) { display: flex; flex-direction: column; gap: var(--evo-space-12); padding: var(--evo-space-16); color: var(--dsw-alias-label-primary); font-size: var(--evo-type-sm); line-height: var(--evo-leading-base); }",
|
|
247
|
+
":where(.dsh-evolution-skill-health [data-role=\"hint\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }",
|
|
248
|
+
":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--evo-space-8); }",
|
|
249
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"]) { display: flex; flex-direction: column; gap: var(--evo-space-2); padding: var(--evo-space-8) var(--evo-space-10); border: var(--evo-hairline-width) solid var(--dsw-alias-border-l); border-radius: var(--evo-radius-control); }",
|
|
250
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"ok\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-success-primary); }",
|
|
251
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"warn\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-warn-primary); }",
|
|
252
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"error\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-error-primary); }",
|
|
253
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"unreadable\"]) { box-shadow: inset 2px 0 0 var(--evo-tone-quiet); }",
|
|
254
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-size: var(--evo-type-lg); font-variant-numeric: tabular-nums; line-height: 1; }",
|
|
255
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat-label\"]) { color: var(--dsw-alias-label-tertiary); }",
|
|
256
|
+
":where(.dsh-evolution-skill-health [data-role=\"group-title\"]) { margin: 0; font-weight: 500; }",
|
|
257
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-table\"]) { display: flex; flex-direction: column; border: var(--evo-hairline-width) solid var(--dsw-alias-border-l); border-radius: var(--evo-radius-control); overflow: hidden; }",
|
|
258
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]) { display: grid; grid-template-columns: minmax(9rem, 13rem) minmax(0, 1fr) 4rem; gap: var(--evo-space-10); align-items: center; padding: var(--evo-space-6) var(--evo-space-10); border-top: var(--evo-hairline-width) solid var(--dsw-alias-border-l); }",
|
|
259
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"warn\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--dsw-alias-state-warn-primary); }",
|
|
260
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"error\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--dsw-alias-state-error-primary); }",
|
|
261
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"][data-tone=\"unreadable\"]) { box-shadow: inset var(--evo-hairline-marker) 0 0 var(--evo-tone-quiet); }",
|
|
262
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]:hover) { background: var(--dsw-alias-interactive-bg-hover); }",
|
|
263
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]:focus-visible) { outline: var(--evo-focus-ring); outline-offset: var(--evo-focus-offset); }",
|
|
264
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-head\"]) { border-top: 0; color: var(--dsw-alias-label-tertiary); }",
|
|
265
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-name\"]) { overflow-wrap: anywhere; }",
|
|
266
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-count\"]) { text-align: right; font-variant-numeric: tabular-nums; color: var(--dsw-alias-label-secondary); }",
|
|
267
|
+
":where(.dsh-evolution-skill-health [data-role=\"skills\"]) { display: flex; flex-wrap: wrap; gap: var(--evo-space-4); }",
|
|
268
|
+
":where(.dsh-evolution-skill-health [data-role=\"skill-pill\"]) { padding: 0 var(--evo-space-6); border: var(--evo-hairline-width) solid var(--dsw-alias-border-l); border-radius: var(--evo-radius-pill); color: var(--dsw-alias-label-secondary); white-space: nowrap; }",
|
|
269
|
+
":where(.dsh-evolution-skill-health [data-role=\"note\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }"
|
|
191
270
|
].join(String.fromCharCode(10));
|
|
192
271
|
//#endregion
|
|
193
272
|
//#region src/client/index.ts
|
|
@@ -3,7 +3,25 @@
|
|
|
3
3
|
* the text itself and injects one tagged <style> element; the tag id keeps a hot reload from stacking
|
|
4
4
|
* copies. Only the panel body is styled — the sidebar owns the row and its glyph slot.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
6
|
+
* Token discipline (the family gate `verify-client-tokens --strict` enforces it): every `--evo-*` name
|
|
7
|
+
* below is DECLARED in `packages/scripts/client-tokens.json` — the family scale — and every `--dsw-*`
|
|
8
|
+
* name is a platform semantic alias (packages/client/ui-theme/src/styles). No type step, space, radius,
|
|
9
|
+
* hairline or colour is invented here, and no pixel geometry literal appears.
|
|
10
|
+
*
|
|
11
|
+
* Metrics are COPIED from the platform’s own components rather than invented, each cited here:
|
|
12
|
+
*
|
|
13
|
+
* - hover and current-row fills (`--dsw-alias-interactive-bg-hover`) follow the platform sidebar row
|
|
14
|
+
* (client/ui-sidebar/…/SidebarRoot.module.css), as the sibling panel does;
|
|
15
|
+
* - label steps (`--dsw-alias-label-primary/secondary/tertiary`) and the card hairline
|
|
16
|
+
* (`--evo-hairline-width`, the scale’s copy of the platform’s 0.5px card border) come from
|
|
17
|
+
* client/ui-chat/…/GenericCommandCard.module.css;
|
|
18
|
+
* - the control radius (`--evo-radius-control`, the scale’s copy of the platform field radius) comes
|
|
19
|
+
* from client/ui-primitives/Input.module.css; the capsule uses `--evo-radius-pill`;
|
|
20
|
+
* - verdict colours are the platform STATE aliases (state-success / state-warn / state-error) plus the
|
|
21
|
+
* scale’s `--evo-tone-quiet`; the validity bar is an inset shadow, not a border-width literal.
|
|
22
|
+
*
|
|
23
|
+
* Layout: four verdict cards, then the by-rule table as a grid (rule / skills / count) so numbers sit
|
|
24
|
+
* on tabular figures and long skill lists wrap into pills instead of ragged comma text.
|
|
7
25
|
* @module @lmzhen/dsh-evolution-skill-health/client
|
|
8
26
|
*/
|
|
9
27
|
/** Tag id for the injected <style>, so a hot reload replaces rather than stacks it. */
|
package/package.json
CHANGED
|
@@ -11,7 +11,7 @@
|
|
|
11
11
|
]
|
|
12
12
|
}
|
|
13
13
|
},
|
|
14
|
-
"version": "0.25.
|
|
14
|
+
"version": "0.25.7",
|
|
15
15
|
"publishConfig": {
|
|
16
16
|
"access": "public"
|
|
17
17
|
},
|
|
@@ -43,13 +43,13 @@
|
|
|
43
43
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
44
44
|
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
|
|
45
45
|
"react": "^18.2.0",
|
|
46
|
-
"@lmzhen/dsh-evolution-curator": "^0.25.
|
|
46
|
+
"@lmzhen/dsh-evolution-curator": "^0.25.7"
|
|
47
47
|
},
|
|
48
48
|
"devDependencies": {
|
|
49
49
|
"@deepseek-ai/cordis": "^4.0.1",
|
|
50
50
|
"@deepseek-ai/dsh-host-webserver": "^0.2.0-rc.1",
|
|
51
51
|
"@types/react": "~18.3.1",
|
|
52
52
|
"react": "^18.2.0",
|
|
53
|
-
"@lmzhen/dsh-evolution-curator": "^0.25.
|
|
53
|
+
"@lmzhen/dsh-evolution-curator": "^0.25.7"
|
|
54
54
|
}
|
|
55
55
|
}
|