@lmzhen/dsh-evolution-skill-health 0.25.6 → 0.25.8
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 +102 -23
- 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.",
|
|
@@ -102,6 +104,64 @@ window.__ModuleLoader__.load({
|
|
|
102
104
|
"loading.failed": "Reading failed — this cannot be judged right now; press Refresh to retry."
|
|
103
105
|
};
|
|
104
106
|
//#endregion
|
|
107
|
+
//#region src/client/styles.ts
|
|
108
|
+
/**
|
|
109
|
+
* The panel stylesheet. The bundle is built outside the platform CSS-Modules pipeline, so it carries
|
|
110
|
+
* the text itself and injects one tagged <style> element; the tag id keeps a hot reload from stacking
|
|
111
|
+
* copies. Only the panel body is styled — the sidebar owns the row and its glyph slot.
|
|
112
|
+
*
|
|
113
|
+
* Token discipline (the family gate `verify-client-tokens --strict` enforces it): every `--evo-*` name
|
|
114
|
+
* below is DECLARED in `packages/scripts/client-tokens.json` — the family scale — and every `--dsw-*`
|
|
115
|
+
* name is a platform semantic alias (packages/client/ui-theme/src/styles). No type step, space, radius,
|
|
116
|
+
* hairline or colour is invented here, and no pixel geometry literal appears.
|
|
117
|
+
*
|
|
118
|
+
* Metrics are COPIED from the platform’s own components rather than invented, each cited here:
|
|
119
|
+
*
|
|
120
|
+
* - hover and current-row fills (`--dsw-alias-interactive-bg-hover`) follow the platform sidebar row
|
|
121
|
+
* (client/ui-sidebar/…/SidebarRoot.module.css), as the sibling panel does;
|
|
122
|
+
* - label steps (`--dsw-alias-label-primary/secondary/tertiary`) and the card hairline
|
|
123
|
+
* (`--evo-hairline-width`, the scale’s copy of the platform’s 0.5px card border) come from
|
|
124
|
+
* client/ui-chat/…/GenericCommandCard.module.css;
|
|
125
|
+
* - the control radius (`--evo-radius-control`, the scale’s copy of the platform field radius) comes
|
|
126
|
+
* from client/ui-primitives/Input.module.css; the capsule uses `--evo-radius-pill`;
|
|
127
|
+
* - verdict colours are the platform STATE aliases (state-success / state-warn / state-error) plus the
|
|
128
|
+
* scale’s `--evo-tone-quiet`; the validity bar is an inset shadow, not a border-width literal.
|
|
129
|
+
*
|
|
130
|
+
* Layout: four verdict cards, then the by-rule table as a grid (rule / skills / count) so numbers sit
|
|
131
|
+
* on tabular figures and long skill lists wrap into pills instead of ragged comma text.
|
|
132
|
+
* @module @lmzhen/dsh-evolution-skill-health/client
|
|
133
|
+
*/
|
|
134
|
+
/** Tag id for the injected <style>, so a hot reload replaces rather than stacks it. */
|
|
135
|
+
const CSS_TAG_ID = "dsh-evolution-skill-health";
|
|
136
|
+
/** The panel stylesheet text. */
|
|
137
|
+
const CSS = [
|
|
138
|
+
":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 }",
|
|
139
|
+
":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); }",
|
|
140
|
+
":where(.dsh-evolution-skill-health [data-role=\"hint\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }",
|
|
141
|
+
":where(.dsh-evolution-skill-health [data-role=\"stats\"]) { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: var(--evo-space-8); }",
|
|
142
|
+
":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); }",
|
|
143
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"ok\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-success-primary); }",
|
|
144
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"warn\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-warn-primary); }",
|
|
145
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"error\"]) { box-shadow: inset 2px 0 0 var(--dsw-alias-state-error-primary); }",
|
|
146
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat\"][data-tone=\"unreadable\"]) { box-shadow: inset 2px 0 0 var(--evo-tone-quiet); }",
|
|
147
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat-value\"]) { font-size: var(--evo-type-lg); font-variant-numeric: tabular-nums; line-height: 1; }",
|
|
148
|
+
":where(.dsh-evolution-skill-health [data-role=\"stat-label\"]) { color: var(--dsw-alias-label-tertiary); }",
|
|
149
|
+
":where(.dsh-evolution-skill-health [data-role=\"group-title\"]) { margin: 0; font-weight: 500; }",
|
|
150
|
+
":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; }",
|
|
151
|
+
":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); }",
|
|
152
|
+
":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); }",
|
|
153
|
+
":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); }",
|
|
154
|
+
":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); }",
|
|
155
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]:hover) { background: var(--dsw-alias-interactive-bg-hover); }",
|
|
156
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-row\"]:focus-visible) { outline: var(--evo-focus-ring); outline-offset: var(--evo-focus-offset); }",
|
|
157
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-head\"]) { border-top: 0; color: var(--dsw-alias-label-tertiary); }",
|
|
158
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-name\"]) { overflow-wrap: anywhere; }",
|
|
159
|
+
":where(.dsh-evolution-skill-health [data-role=\"rule-count\"]) { text-align: right; font-variant-numeric: tabular-nums; color: var(--dsw-alias-label-secondary); }",
|
|
160
|
+
":where(.dsh-evolution-skill-health [data-role=\"skills\"]) { display: flex; flex-wrap: wrap; gap: var(--evo-space-4); }",
|
|
161
|
+
":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; }",
|
|
162
|
+
":where(.dsh-evolution-skill-health [data-role=\"note\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }"
|
|
163
|
+
].join(String.fromCharCode(10));
|
|
164
|
+
//#endregion
|
|
105
165
|
//#region src/client/Panel.ts
|
|
106
166
|
/**
|
|
107
167
|
* The panel body: a four-state summary plus the list aggregated BY RULE.
|
|
@@ -134,10 +194,40 @@ window.__ModuleLoader__.load({
|
|
|
134
194
|
}
|
|
135
195
|
return [...table.values()].sort((a, b) => b.skills.length - a.skills.length || a.rule.localeCompare(b.rule));
|
|
136
196
|
}
|
|
137
|
-
/** The rule
|
|
197
|
+
/** The verdict a rule's row speaks in: the worst one among the skills that carry it. */
|
|
198
|
+
function worstVerdict(face, skills) {
|
|
199
|
+
const order = [
|
|
200
|
+
"error",
|
|
201
|
+
"warn",
|
|
202
|
+
"unreadable",
|
|
203
|
+
"ok"
|
|
204
|
+
];
|
|
205
|
+
let worst = "ok";
|
|
206
|
+
for (const row of face.rows) {
|
|
207
|
+
if (!skills.includes(row.name)) continue;
|
|
208
|
+
if (order.indexOf(row.verdict) < order.indexOf(worst)) worst = row.verdict;
|
|
209
|
+
}
|
|
210
|
+
return worst;
|
|
211
|
+
}
|
|
212
|
+
/** The rule table: a grid so counts line up, with a tone bar per row and skill pills. */
|
|
138
213
|
function ruleTable(face, t) {
|
|
139
214
|
const rows = byRule(face.rows);
|
|
140
|
-
|
|
215
|
+
const cell = (role, children, key) => (0, react.createElement)("div", key === void 0 ? { "data-role": role } : {
|
|
216
|
+
"data-role": role,
|
|
217
|
+
key
|
|
218
|
+
}, children);
|
|
219
|
+
return (0, react.createElement)("div", { "data-role": "rule-table" }, (0, react.createElement)("div", {
|
|
220
|
+
"data-role": "rule-row",
|
|
221
|
+
"data-role-head": "true"
|
|
222
|
+
}, (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", {
|
|
223
|
+
key: entry.rule,
|
|
224
|
+
"data-role": "rule-row",
|
|
225
|
+
"data-tone": worstVerdict(face, entry.skills)
|
|
226
|
+
}, cell("rule-name", entry.rule), cell("skills", entry.skills.map((name, i) => (0, react.createElement)("span", {
|
|
227
|
+
"data-role": "skill-pill",
|
|
228
|
+
key: name + ":" + String(i),
|
|
229
|
+
title: name
|
|
230
|
+
}, name))), cell("rule-count", entry.count === 0 ? t("count.notCalibrated") : String(entry.count)))));
|
|
141
231
|
}
|
|
142
232
|
/**
|
|
143
233
|
* Render the panel.
|
|
@@ -168,28 +258,17 @@ window.__ModuleLoader__.load({
|
|
|
168
258
|
};
|
|
169
259
|
}, [face]);
|
|
170
260
|
const counts = new Map(KINDS.map((kind) => [kind, view.rows.filter((row) => row.verdict === kind).length]));
|
|
171
|
-
|
|
261
|
+
const stats = (0, react.createElement)("div", { "data-role": "stats" }, KINDS.map((kind) => (0, react.createElement)("div", {
|
|
262
|
+
key: kind,
|
|
263
|
+
"data-role": "stat",
|
|
264
|
+
"data-tone": kind
|
|
265
|
+
}, (0, react.createElement)("div", { "data-role": "stat-value" }, String(counts.get(kind) ?? 0)), (0, react.createElement)("div", { "data-role": "stat-label" }, t("verdict." + kind)))));
|
|
266
|
+
return (0, react.createElement)("section", { className: CSS_TAG_ID }, (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", {
|
|
267
|
+
key: row.name + ":unreadable",
|
|
268
|
+
"data-role": "note"
|
|
269
|
+
}, row.name + " — " + t("unreadable.note"))));
|
|
172
270
|
}
|
|
173
271
|
//#endregion
|
|
174
|
-
//#region src/client/styles.ts
|
|
175
|
-
/**
|
|
176
|
-
* The panel stylesheet. The bundle is built outside the platform CSS-Modules pipeline, so it carries
|
|
177
|
-
* the text itself and injects one tagged <style> element; the tag id keeps a hot reload from stacking
|
|
178
|
-
* copies. Only the panel body is styled — the sidebar owns the row and its glyph slot.
|
|
179
|
-
*
|
|
180
|
-
* Every value comes from the generated family scale (`./tokens.ts`), so this file carries no literal.
|
|
181
|
-
* @module @lmzhen/dsh-evolution-skill-health/client
|
|
182
|
-
*/
|
|
183
|
-
/** Tag id for the injected <style>, so a hot reload replaces rather than stacks it. */
|
|
184
|
-
const CSS_TAG_ID = "dsh-evolution-skill-health";
|
|
185
|
-
/** The panel stylesheet text. */
|
|
186
|
-
const CSS = [
|
|
187
|
-
":where(.dsh-evolution-skill-health) { display: flex; flex-direction: column; gap: var(--evo-space-8); padding: var(--evo-space-12); }",
|
|
188
|
-
":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 [data-role=\"row\"]) { display: flex; align-items: baseline; justify-content: space-between; gap: var(--evo-space-8); border-bottom: var(--evo-hairline-width) solid var(--evo-tone-quiet); }",
|
|
190
|
-
":where(.dsh-evolution-skill-health [data-role=\"note\"]) { color: var(--evo-tone-quiet); }"
|
|
191
|
-
].join(String.fromCharCode(10));
|
|
192
|
-
//#endregion
|
|
193
272
|
//#region src/client/index.ts
|
|
194
273
|
/** Required client services: the slot registry and the locale seat. */
|
|
195
274
|
const inject = ["slots", "locale"];
|
|
@@ -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.8",
|
|
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.8"
|
|
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.8"
|
|
54
54
|
}
|
|
55
55
|
}
|