@lmzhen/dsh-evolution-skill-health 0.30.24 → 0.30.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -3,11 +3,12 @@
3
3
  技能健康面板:把体检引擎(`evolution-core` 的 skill-lint/skill-health)的结论**按规则聚合**呈现,
4
4
  让"哪条规则在哪些技能上出现、本次改动新引入了什么"一眼可见。**只读**:不写任何技能、不改任何配置。
5
5
 
6
- ## 座位与注册(照 `evolution-skill-history` 的成例)
6
+ ## 座位与注册
7
7
 
8
- - 侧栏行:`ctx.slots.inject('sidebar.panellist', …)` + `slots.register({ name: 'sidebar.panellist', id, order, label: () => … })`;
9
- `label` 必须是 **thunk**(跟语言切换走 ✓),`order` 取 40 一带(与技能历史相邻 ✓);`sidebar.panellist` 是**列表座位** ⇒ 多个面板可并存 ✓。
10
- - 主区:`slots.register({ name: 'main', key: <同一个 id>, inject })` —— **同一个 id 注册两次**,这是本家族面板的既定契约 ✓。
8
+ - 侧栏行和主区由 `@lmzhen/dsh-evolution-client-kit` 的 `registerSidebarPanel` 一次注册:
9
+ 同一个 id 既是 `sidebar.panellist` 的行,也是 keyed `main` 的 key(家族面板契约);
10
+ `label` 由 Kit 以 thunk 提供,跟随语言切换;`order` 取 40 一带(与技能历史相邻)。
11
+ - 三个侧栏面板共用同一份客户端缝和生命周期;业务只提供 Panel/Store/api 和图标。
11
12
 
12
13
  ## 数据来源与边界
13
14
 
@@ -15,7 +16,7 @@
15
16
  - **呈现**:总览四态(ok/warn/error/不可读)+ **按规则聚合**的清单 + 与技能历史/技能目录的交叉跳转;
16
17
  `line: …`/`line: UNKNOWN` 两态要写清(未知就是未知 ✓)。
17
18
  - **不上屏**:**未标定**的阈值(如 `SUPPORT_SPRAWL_FILES`)**只报规则名、不报数字** ✓ —— 口径冻结之前不许把数字给读者 ✓。
18
- - 客户端半**不得** import 其它插件的值/类型 ⇒ 只声明自己消费的座位形状(见 `evolution-settings-ui/src/client/seam.ts` 的头注释 ✓)。
19
+ - 客户端半不直接 import 其它插件的值/类型;座位形状由 `client-kit` 的 seam 唯一定义 ✓。
19
20
 
20
21
  ## 当前状态
21
22
 
package/lib/client.js CHANGED
@@ -5,7 +5,69 @@ window.__ModuleLoader__.load({
5
5
  var exports = module.exports;
6
6
  Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
7
7
  let react = require("react");
8
- //#region src/client/routes.generated.ts
8
+ //#region ../evolution-client-kit/src/panel.ts
9
+ function interpolate(text, values) {
10
+ if (values === void 0) return text;
11
+ return text.replace(/\{(\w+)\}/g, (_match, key) => String(values[key] ?? ""));
12
+ }
13
+ function injectStyles(doc, css, tagId) {
14
+ if (doc === void 0) return () => {};
15
+ if (doc.querySelector("style[data-plugin-css=\"" + tagId + "\"]") !== null) return () => {};
16
+ const tag = doc.createElement("style");
17
+ tag.setAttribute("data-plugin-css", tagId);
18
+ tag.textContent = css;
19
+ doc.head.append(tag);
20
+ return () => {
21
+ tag.remove();
22
+ };
23
+ }
24
+ /**
25
+ * Register one sidebar row and its main body under one lifecycle.
26
+ * @param ctx - the client context carrying the slots and locale seats.
27
+ * @param spec - the feature-specific row/body descriptor.
28
+ */
29
+ function registerSidebarPanel(ctx, spec) {
30
+ const seam = ctx;
31
+ let registered = false;
32
+ ctx.effect(() => {
33
+ try {
34
+ const dispose = seam.locale.register(spec.namespace, spec.dictionaries);
35
+ registered = true;
36
+ return dispose;
37
+ } catch (error) {
38
+ ctx.logger.warn(spec.namespace + ": the locale seat refused the dictionary (" + String(error) + "); the panel falls back to the bundle copy");
39
+ return () => {};
40
+ }
41
+ }, spec.namespace + ": locale");
42
+ ctx.effect(() => injectStyles(typeof document === "undefined" ? void 0 : document, spec.styles.css, spec.styles.tagId), spec.namespace + ": styles");
43
+ const fallback = spec.dictionaries[spec.fallback ?? "zh"];
44
+ const lookup = (key) => {
45
+ const own = fallback[key] ?? key;
46
+ if (!registered) return own;
47
+ try {
48
+ return seam.locale.bind(spec.namespace)(key);
49
+ } catch {
50
+ return own;
51
+ }
52
+ };
53
+ const t = (key, values) => interpolate(lookup(key), values);
54
+ const label = () => lookup("entry.label");
55
+ seam.slots.inject("sidebar.panellist", function* () {
56
+ yield seam.slots.register({
57
+ name: "sidebar.panellist",
58
+ id: spec.id,
59
+ order: spec.order,
60
+ label
61
+ }, spec.icon);
62
+ yield seam.slots.register({
63
+ name: "main",
64
+ key: spec.id,
65
+ inject: () => spec.body(t)
66
+ }, spec.component);
67
+ });
68
+ }
69
+ //#endregion
70
+ //#region ../evolution-client-kit/src/generated/routes.generated.ts
9
71
  /**
10
72
  * Every family host path, generated from evolution-core's HOST_ROUTES (the ONE declaration).
11
73
  * A browser half cannot import the host package at runtime (client bundles keep @deepseek-ai/*
@@ -39,7 +101,53 @@ window.__ModuleLoader__.load({
39
101
  diagnostics: { view: "/api/dsh-evolution/diagnostics" }
40
102
  };
41
103
  //#endregion
42
- //#region src/client/route-client.generated.ts
104
+ //#region ../evolution-client-kit/src/generated/fallbacks.generated.ts
105
+ /**
106
+ * The command-face fallback for every Host surface, generated from evolution-commands'
107
+ * COMMAND_FALLBACKS (the ONE home). When the platform's connection carrier is absent (E-325) the
108
+ * panels render this hint instead of a bare HTTP failure — same use case, command face.
109
+ */
110
+ const FALLBACKS = {
111
+ approval: { command: "/evolution pending … /evolution approve <id> … /evolution reject <id> … /evolution release <id>" },
112
+ "skill-history": { command: "/evolution restore <name> [v](查看:/evolution skills history <name>)" },
113
+ "skill-health": { command: "/evolution skills refresh(健康行:/evolution doctor)" },
114
+ merge: { command: "/evolution merge status / pending / approve <id> / report" },
115
+ diagnostics: {
116
+ command: "/evolution doctor",
117
+ platformCli: "dsh --json /evolution doctor"
118
+ }
119
+ };
120
+ //#endregion
121
+ //#region ../evolution-client-kit/src/generated/states.generated.ts
122
+ /** A neutral/ warn/ fail block; a fail block is role=alert so assistive tech announces it. */
123
+ function Block(props) {
124
+ const tone = props.tone ?? "neutral";
125
+ return (0, react.createElement)("div", {
126
+ "data-tone": tone,
127
+ ...tone === "fail" ? { role: "alert" } : {}
128
+ }, props.title === void 0 ? null : (0, react.createElement)("div", { "data-tone-title": tone }, props.title), props.children);
129
+ }
130
+ /** One classified failure as a reader-facing sentence. */
131
+ function failureText(failure, t) {
132
+ switch (failure.kind) {
133
+ case "unauthenticated": return t("failureUnauthorized");
134
+ case "forbidden": return t("failureForbidden");
135
+ case "unmounted": return t("failureUnmounted");
136
+ case "server": return failure.status === 0 ? t("failureServer") : t("failureServer") + " (HTTP " + String(failure.status) + ")";
137
+ case "refused": return failure.message;
138
+ }
139
+ }
140
+ /** The failed-state block: sentence + (when the surface exists but is unreachable) the command fallback. */
141
+ function FailureBlock(props) {
142
+ const hint = props.fallback === void 0 ? null : (0, react.createElement)("div", { "data-tone-hint": "true" }, props.t("fallbackHint", { command: props.fallback.command }));
143
+ return Block({
144
+ tone: "fail",
145
+ title: failureText(props.failure, props.t),
146
+ children: hint
147
+ });
148
+ }
149
+ //#endregion
150
+ //#region ../evolution-client-kit/src/generated/route-client.generated.ts
43
151
  /** Classify a non-2xx status: 401/403/404 keep their own kind, everything else is a server answer. */
44
152
  function classify(status) {
45
153
  if (status === 401) return {
@@ -154,9 +262,9 @@ window.__ModuleLoader__.load({
154
262
  };
155
263
  }
156
264
  //#endregion
157
- //#region src/client/seam.ts
158
- /** The panel id. The row and the `main` body MUST share it: the sidebar resolves the body by it. */
265
+ //#region src/client/ids.ts
159
266
  const PANEL_ID = "skill-health";
267
+ const PANEL_ORDER = 40;
160
268
  //#endregion
161
269
  //#region src/client/messages.ts
162
270
  /**
@@ -291,52 +399,6 @@ window.__ModuleLoader__.load({
291
399
  ":where(.dsh-evolution-skill-health [data-role=\"note\"]) { margin: 0; color: var(--dsw-alias-label-secondary); }"
292
400
  ].join(String.fromCharCode(10));
293
401
  //#endregion
294
- //#region src/client/states.generated.ts
295
- /** A neutral/ warn/ fail block; a fail block is role=alert so assistive tech announces it. */
296
- function Block(props) {
297
- const tone = props.tone ?? "neutral";
298
- return (0, react.createElement)("div", {
299
- "data-tone": tone,
300
- ...tone === "fail" ? { role: "alert" } : {}
301
- }, props.title === void 0 ? null : (0, react.createElement)("div", { "data-tone-title": tone }, props.title), props.children);
302
- }
303
- /** One classified failure as a reader-facing sentence. */
304
- function failureText(failure, t) {
305
- switch (failure.kind) {
306
- case "unauthenticated": return t("failureUnauthorized");
307
- case "forbidden": return t("failureForbidden");
308
- case "unmounted": return t("failureUnmounted");
309
- case "server": return failure.status === 0 ? t("failureServer") : t("failureServer") + " (HTTP " + String(failure.status) + ")";
310
- case "refused": return failure.message;
311
- }
312
- }
313
- /** The failed-state block: sentence + (when the surface exists but is unreachable) the command fallback. */
314
- function FailureBlock(props) {
315
- const hint = props.fallback === void 0 ? null : (0, react.createElement)("div", { "data-tone-hint": "true" }, props.t("fallbackHint", { command: props.fallback.command }));
316
- return Block({
317
- tone: "fail",
318
- title: failureText(props.failure, props.t),
319
- children: hint
320
- });
321
- }
322
- //#endregion
323
- //#region src/client/fallbacks.generated.ts
324
- /**
325
- * The command-face fallback for every Host surface, generated from evolution-commands'
326
- * COMMAND_FALLBACKS (the ONE home). When the platform's connection carrier is absent (E-325) the
327
- * panels render this hint instead of a bare HTTP failure — same use case, command face.
328
- */
329
- const FALLBACKS = {
330
- approval: { command: "/evolution pending … /evolution approve <id> … /evolution reject <id> … /evolution release <id>" },
331
- "skill-history": { command: "/evolution restore <name> [v](查看:/evolution skills history <name>)" },
332
- "skill-health": { command: "/evolution skills refresh(健康行:/evolution doctor)" },
333
- merge: { command: "/evolution merge status / pending / approve <id> / report" },
334
- diagnostics: {
335
- command: "/evolution doctor",
336
- platformCli: "dsh --json /evolution doctor"
337
- }
338
- };
339
- //#endregion
340
402
  //#region src/client/Panel.ts
341
403
  /**
342
404
  * The panel body: a four-state summary plus the list aggregated BY RULE.
@@ -469,16 +531,6 @@ window.__ModuleLoader__.load({
469
531
  //#region src/client/index.ts
470
532
  /** Required client services: the slot registry and the locale seat. */
471
533
  const inject = ["slots", "locale"];
472
- /**
473
- * Register the row and the body.
474
- * @param ctx - the client context; it must carry the two seats above.
475
- */
476
- /**
477
- * The row glyph. The sidebar hands every `sidebar.panellist` occupant `{ size, active }` and owns the
478
- * slot around it, so this is a plain line glyph drawn in `currentColor`.
479
- * @param props - the seat-provided size and active flag.
480
- * @returns the glyph element.
481
- */
482
534
  function PanelIcon(props = {}) {
483
535
  const size = typeof props.size === "number" && props.size > 0 ? props.size : 16;
484
536
  return (0, react.createElement)("svg", {
@@ -493,72 +545,36 @@ window.__ModuleLoader__.load({
493
545
  strokeLinejoin: "round"
494
546
  }, (0, react.createElement)("path", { d: "M2 8h3l1.5-3.5L9 11.5 10.5 8H14" }));
495
547
  }
548
+ /**
549
+ * Register the row and the body through the shared panel lifecycle.
550
+ * @param ctx - the client context; it must carry the two seats above.
551
+ */
496
552
  function apply(ctx) {
497
- const seam = ctx;
498
- let registered = false;
499
- ctx.effect(() => {
500
- try {
501
- const dispose = seam.locale.register(NS, {
502
- zh,
503
- en
504
- });
505
- registered = true;
506
- return dispose;
507
- } catch (error) {
508
- ctx.logger.warn(`evolution-skill-health: the locale seat refused the "${NS}" dictionary (${String(error)}); the row falls back to the bundle copy.`);
509
- return () => {};
510
- }
511
- }, "evolution-skill-health: locale");
512
- ctx.effect(() => {
513
- if (document.querySelector("style[data-plugin-css=\"dsh-evolution-skill-health\"]") === null) {
514
- const tag = document.createElement("style");
515
- tag.setAttribute("data-plugin-css", CSS_TAG_ID);
516
- tag.textContent = CSS;
517
- document.head.append(tag);
518
- return () => {
519
- tag.remove();
520
- };
521
- }
522
- return () => {};
523
- }, "evolution-skill-health: styles");
524
- const label = () => {
525
- const fallback = zh["entry.label"] ?? "技能健康";
526
- if (!registered) return fallback;
527
- try {
528
- return seam.locale.bind(NS)("entry.label");
529
- } catch {
530
- return fallback;
531
- }
532
- };
533
- const t = (key) => {
534
- const fallback = zh[key] ?? key;
535
- if (!registered) return fallback;
536
- try {
537
- return seam.locale.bind(NS)(key);
538
- } catch {
539
- return fallback;
540
- }
541
- };
542
- seam.slots.inject("sidebar.panellist", function* () {
543
- yield seam.slots.register({
544
- name: "sidebar.panellist",
545
- id: PANEL_ID,
546
- order: 40,
547
- label
548
- }, PanelIcon);
549
- yield seam.slots.register({
550
- name: "main",
551
- key: PANEL_ID,
552
- inject: () => ({
553
- rows: [],
554
- truncated: false,
555
- loadRows: rows,
556
- t
557
- })
558
- }, SkillHealthPanel);
553
+ registerSidebarPanel(ctx, {
554
+ id: PANEL_ID,
555
+ order: 40,
556
+ namespace: NS,
557
+ dictionaries: {
558
+ zh,
559
+ en
560
+ },
561
+ styles: {
562
+ css: CSS,
563
+ tagId: CSS_TAG_ID
564
+ },
565
+ icon: PanelIcon,
566
+ component: SkillHealthPanel,
567
+ body: (t) => ({
568
+ rows: [],
569
+ truncated: false,
570
+ loadRows: rows,
571
+ t
572
+ })
559
573
  });
560
574
  }
561
575
  //#endregion
576
+ exports.PANEL_ID = PANEL_ID;
577
+ exports.PANEL_ORDER = PANEL_ORDER;
562
578
  exports.apply = apply;
563
579
  exports.inject = inject;
564
580
 
@@ -1,4 +1,4 @@
1
- import type { RouteFailure } from './route-client.generated.ts';
1
+ import type { RouteFailure } from '@lmzhen/dsh-evolution-client-kit/generated/route-client';
2
2
  import type { HealthRow } from './Panel.ts';
3
3
  /** Route paths: the generated mirror of the host's HOST_ROUTES (one declaration in core). */
4
4
  export declare const HOST_ROUTES: {
@@ -0,0 +1,3 @@
1
+ export declare const PANEL_ID = "skill-health";
2
+ export declare const PANEL_ORDER = 40;
3
+ //# sourceMappingURL=ids.d.ts.map
@@ -1,16 +1,18 @@
1
1
  /**
2
- * Browser half: one left-sidebar row (`技能健康`) and the main-column body it opens.
3
- *
4
- * Two places, one id: `sidebar.panellist` owns the row and the layout's keyed `main` slot owns the
5
- * body, dispatched by that same id. Facts arrive through a loader the HOST half supplies, so this
6
- * bundle keeps no state of its own and touches no service.
2
+ * Browser half: one left-sidebar row (技能健康) and the main-column body it opens.
7
3
  * @module @lmzhen/dsh-evolution-skill-health/client
8
4
  */
9
5
  import type { Context as ClientContext } from '@deepseek-ai/cordis';
6
+ import { PANEL_ID, PANEL_ORDER } from './ids.ts';
10
7
  import { type HealthFace } from './Panel.ts';
11
8
  /** Required client services: the slot registry and the locale seat. */
12
9
  export declare const inject: string[];
13
10
  /** The host half hands the panel a way to read its rows (a read-only route on the host side). */
14
11
  export type HealthFaceLoader = () => Promise<HealthFace>;
12
+ export { PANEL_ID, PANEL_ORDER };
13
+ /**
14
+ * Register the row and the body through the shared panel lifecycle.
15
+ * @param ctx - the client context; it must carry the two seats above.
16
+ */
15
17
  export declare function apply(ctx: ClientContext): void;
16
18
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -11,7 +11,7 @@
11
11
  ]
12
12
  }
13
13
  },
14
- "version": "0.30.24",
14
+ "version": "0.30.27",
15
15
  "publishConfig": {
16
16
  "access": "public"
17
17
  },
@@ -42,17 +42,20 @@
42
42
  "peerDependencies": {
43
43
  "@deepseek-ai/cordis": "^4.0.5",
44
44
  "react": "^18.2.0",
45
- "@lmzhen/dsh-evolution-core": "^0.30.24",
46
- "@lmzhen/dsh-evolution-curator": "^0.30.24"
45
+ "@lmzhen/dsh-evolution-core": "^0.30.27",
46
+ "@lmzhen/dsh-evolution-curator": "^0.30.27"
47
47
  },
48
48
  "devDependencies": {
49
49
  "@deepseek-ai/cordis": "^4.0.5",
50
50
  "@types/react": "~18.3.1",
51
51
  "react": "^18.2.0",
52
- "@lmzhen/dsh-evolution-core": "^0.30.24",
53
- "@lmzhen/dsh-evolution-curator": "^0.30.24"
52
+ "@lmzhen/dsh-evolution-core": "^0.30.27",
53
+ "@lmzhen/dsh-evolution-curator": "^0.30.27"
54
+ },
55
+ "dependencies": {
56
+ "@lmzhen/dsh-evolution-client-kit": "^0.30.27"
54
57
  },
55
58
  "engines": {
56
- "dsh": ">=0.2.1-rc.1 <0.2.2-0"
59
+ "dsh": ">=0.2.1-rc.2 <0.2.2-0"
57
60
  }
58
61
  }
@@ -1,37 +0,0 @@
1
- /**
2
- * Literal mirror of the frozen Host diagnostics contract (W1 §2.8 / core diagnostics.ts). The browser
3
- * build keeps every @deepseek-ai/* specifier external, so the client CANNOT import the host type — the
4
- * shape is mirrored mechanically here instead. The key unions are rendered from core diagnostics.ts by
5
- * the generator, so a key change regenerates all three copies (a stale copy fails --check).
6
- */
7
- export type DiagnosticsSchemaVersion = 2;
8
- export type DiagnosticsFactKey = 'platform-line' | 'family-version' | 'install-form' | 'preset-ids' | 'readonly-contract' | 'upgrade-order' | 'fallback-map';
9
- export type DiagnosticsRuntimeKey = 'subagent-channel' | 'restricted-preset' | 'host-surface' | 'session-fold' | 'platform-services' | 'runs' | 'platform-pairing' | 'install-form-detected';
10
- export type DiagnosticStatus = 'ok' | 'warn' | 'fail' | 'unknown';
11
- export interface DocFactRow {
12
- readonly key: DiagnosticsFactKey;
13
- readonly label: string;
14
- readonly value: string;
15
- readonly home: string;
16
- }
17
- export interface DiagnosticRow {
18
- readonly key: DiagnosticsRuntimeKey;
19
- readonly label: string;
20
- readonly status: DiagnosticStatus;
21
- readonly detail?: string;
22
- readonly remedy?: string;
23
- }
24
- export interface DiagnosticsView {
25
- readonly schemaVersion: DiagnosticsSchemaVersion;
26
- readonly generatedAt: string;
27
- readonly facts: readonly DocFactRow[];
28
- readonly runtime: readonly DiagnosticRow[];
29
- }
30
- /** The installation form the doctor reports (W8 install-form-detected row). */
31
- export type InstallFormId = 'M1' | 'M2' | 'M3' | 'M4';
32
- /** One surface's command-face path(s) — the client `fallbacks.generated.ts` table's row type. */
33
- export interface FallbackHint {
34
- readonly command: string;
35
- readonly platformCli?: string;
36
- }
37
- //# sourceMappingURL=contracts.generated.d.ts.map
@@ -1,8 +0,0 @@
1
- import type { FallbackHint } from './contracts.generated.ts';
2
- /**
3
- * The command-face fallback for every Host surface, generated from evolution-commands'
4
- * COMMAND_FALLBACKS (the ONE home). When the platform's connection carrier is absent (E-325) the
5
- * panels render this hint instead of a bare HTTP failure — same use case, command face.
6
- */
7
- export declare const FALLBACKS: Readonly<Record<'approval' | 'skill-history' | 'skill-health' | 'merge' | 'diagnostics', FallbackHint>>;
8
- //# sourceMappingURL=fallbacks.generated.d.ts.map
@@ -1,45 +0,0 @@
1
- /**
2
- * The four-state transport classifier every family client shares (W7 §2). The platform owns
3
- * admission (401/403/404 are its answers, not ours), so the client reads the STATUS only for those
4
- * three and never tries to interpret a platform body. Everything the family route itself answers
5
- * keeps its business envelope: 2xx + {ok:true,data} or 2xx + {ok:false,code,message}.
6
- */
7
- export type RouteFailure = {
8
- readonly kind: 'unauthenticated';
9
- readonly status: 401;
10
- } | {
11
- readonly kind: 'forbidden';
12
- readonly status: 403;
13
- } | {
14
- readonly kind: 'unmounted';
15
- readonly status: 404;
16
- } | {
17
- readonly kind: 'server';
18
- readonly status: number;
19
- readonly detail?: string;
20
- } | {
21
- readonly kind: 'refused';
22
- readonly code: string;
23
- readonly message: string;
24
- };
25
- /** One route answer: the data, or the classified failure. */
26
- export type RouteAnswer<T> = {
27
- readonly ok: true;
28
- readonly data: T;
29
- } | {
30
- readonly ok: false;
31
- readonly failure: RouteFailure;
32
- };
33
- /** Classify a non-2xx status: 401/403/404 keep their own kind, everything else is a server answer. */
34
- export declare function classify(status: number): RouteFailure;
35
- /**
36
- * One request, no retries and no body parsing for the platform's admission answers.
37
- * @param doFetch - the fetch in use (the browser's, or a spec's stub).
38
- * @param path - the exact route path from the generated ROUTES table.
39
- * @param init - standard RequestInit.
40
- * @returns the data, or the classified failure (network/parse failures read as 'server').
41
- */
42
- export declare function requestJson<T>(doFetch: typeof fetch, path: string, init?: RequestInit): Promise<RouteAnswer<T>>;
43
- /** The one-sentence rendering legacy callers attach to a classified failure. */
44
- export declare function failureMessage(failure: RouteFailure): string;
45
- //# sourceMappingURL=route-client.generated.d.ts.map
@@ -1,39 +0,0 @@
1
- /** One host data-plane surface the browser half can call. */
2
- export type SurfaceId = 'approval' | 'skill-history' | 'skill-health' | 'merge' | 'diagnostics';
3
- /**
4
- * Every family host path, generated from evolution-core's HOST_ROUTES (the ONE declaration).
5
- * A browser half cannot import the host package at runtime (client bundles keep @deepseek-ai/*
6
- * external), so the table is mirrored here mechanically; a rename in core regenerates all three
7
- * client copies, and the generator's --check makes a stale copy red.
8
- */
9
- export declare const ROUTES: {
10
- readonly approval: {
11
- readonly pending: "/api/dsh-evolution/approval/pending";
12
- readonly preview: "/api/dsh-evolution/approval/preview";
13
- readonly approve: "/api/dsh-evolution/approval/approve";
14
- readonly reject: "/api/dsh-evolution/approval/reject";
15
- };
16
- readonly 'skill-history': {
17
- readonly skills: "/api/dsh-evolution/skill-history/skills";
18
- readonly versions: "/api/dsh-evolution/skill-history/versions";
19
- readonly diff: "/api/dsh-evolution/skill-history/versions/diff";
20
- readonly body: "/api/dsh-evolution/skill-history/versions/body";
21
- readonly undo: "/api/dsh-evolution/skill-history/undo";
22
- readonly health: "/api/dsh-evolution/skill-history/health";
23
- };
24
- readonly 'skill-health': {
25
- readonly rows: "/api/dsh-evolution/skill-health/rows";
26
- };
27
- readonly merge: {
28
- readonly view: "/api/dsh-evolution/merge/view";
29
- readonly rows: "/api/dsh-evolution/merge/rows";
30
- readonly run: "/api/dsh-evolution/merge/run";
31
- readonly runs: "/api/dsh-evolution/merge/runs";
32
- readonly body: "/api/dsh-evolution/merge/body";
33
- readonly history: "/api/dsh-evolution/merge/history";
34
- };
35
- readonly diagnostics: {
36
- readonly view: "/api/dsh-evolution/diagnostics";
37
- };
38
- };
39
- //# sourceMappingURL=routes.generated.d.ts.map
@@ -1,50 +0,0 @@
1
- /**
2
- * Structural view of the client seams this bundle consumes: the sidebar's global panel row, the
3
- * main-column body it addresses, the slot registry and the locale seat.
4
- *
5
- * The package ships outside the platform repository, so it DECLARES the seams it uses instead of
6
- * importing another plugin's values (forbidden by the client bundle purity rule) or its types
7
- * (which would drag platform client sources in). The shapes below are the shell's contract:
8
- * `sidebar.panellist` takes `id`/`order`/`label` and owns the button and the layout, while the body
9
- * is the root layout's keyed `main` slot dispatched by that SAME id.
10
- * @module @lmzhen/dsh-evolution-skill-health/client
11
- */
12
- import type { ReactNode } from 'react';
13
- /** The panel id. The row and the `main` body MUST share it: the sidebar resolves the body by it. */
14
- export declare const PANEL_ID = "skill-health";
15
- /** Row order inside the global panel list: beside the skill-history row (35), after it. */
16
- export declare const PANEL_ORDER = 40;
17
- /** Registration options for the global panel row (the sidebar's own shape). */
18
- export interface PanelRowOptions {
19
- name: 'sidebar.panellist';
20
- id: string;
21
- order: number;
22
- /** Lazy label: the sidebar re-reads it on every projection, so the locale can change underneath. */
23
- label: () => string;
24
- }
25
- /** Registration options for the main-column body: a keyed slot dispatched by sidebar entry id. */
26
- export interface PanelBodyOptions {
27
- name: 'main';
28
- key: string;
29
- /** The face handed to the component: plain data and callbacks, never a service. */
30
- inject: () => unknown;
31
- }
32
- /** The locale seat: register this bundle's namespace, bind a translator. */
33
- export interface LocaleSeat {
34
- register(namespace: string, dictionaries: {
35
- zh: Record<string, string>;
36
- en: Record<string, string>;
37
- }): () => void;
38
- bind(namespace: string): (key: string) => string;
39
- }
40
- /** The slot registry: a generator body may register (and is disposed when it unmounts). */
41
- export interface SlotsSeat {
42
- inject(name: string, body: () => Generator<() => void, void, void>): void;
43
- register(options: PanelRowOptions | PanelBodyOptions, component: (props: never) => ReactNode): () => void;
44
- }
45
- /** Everything this bundle asks the shell for. */
46
- export interface ClientSeam {
47
- slots: SlotsSeat;
48
- locale: LocaleSeat;
49
- }
50
- //# sourceMappingURL=seam.d.ts.map
@@ -1,43 +0,0 @@
1
- import { type ReactNode } from 'react';
2
- import type { RouteAnswer, RouteFailure } from './route-client.generated.ts';
3
- import type { FallbackHint } from './contracts.generated.ts';
4
- /**
5
- * The four-state base of every family card (W7 §2). Load states are read from the generated
6
- * route-client's answer — a card owns no HTTP vocabulary and no second state machine.
7
- */
8
- export type LoadState<T> = {
9
- readonly phase: 'loading';
10
- } | {
11
- readonly phase: 'ready';
12
- readonly data: T;
13
- } | {
14
- readonly phase: 'empty';
15
- } | {
16
- readonly phase: 'failed';
17
- readonly failure: RouteFailure;
18
- };
19
- /** Map one classified answer onto the card's four states. */
20
- export declare function loadStateOf<T>(answer: RouteAnswer<T>, isEmpty: (data: T) => boolean): LoadState<T>;
21
- /** The locale lookup every block calls (the platform's own `t`). */
22
- export interface Translate {
23
- (key: string, values?: Readonly<Record<string, string | number>>): string;
24
- }
25
- export type BlockTone = 'neutral' | 'warn' | 'fail';
26
- export interface BlockProps {
27
- readonly tone?: BlockTone;
28
- readonly title?: string;
29
- readonly children?: ReactNode;
30
- }
31
- /** A neutral/ warn/ fail block; a fail block is role=alert so assistive tech announces it. */
32
- export declare function Block(props: BlockProps): ReactNode;
33
- export interface FailureBlockProps {
34
- readonly failure: RouteFailure;
35
- readonly t: Translate;
36
- /** The command-face fallback for this surface (rendered on unmounted/failed answers). */
37
- readonly fallback?: FallbackHint | undefined;
38
- }
39
- /** One classified failure as a reader-facing sentence. */
40
- export declare function failureText(failure: RouteFailure, t: Translate): string;
41
- /** The failed-state block: sentence + (when the surface exists but is unreachable) the command fallback. */
42
- export declare function FailureBlock(props: FailureBlockProps): ReactNode;
43
- //# sourceMappingURL=states.generated.d.ts.map
@@ -1,25 +0,0 @@
1
- /**
2
- * The family client scale - GENERATED from packages/scripts/client-tokens.json. Do not edit.
3
- *
4
- * Both browser halves of the family carry this file with identical bytes, because the scale is one
5
- * fact: `verify-client-tokens.mjs` (a gate step) fails when either copy drifts from the source. The
6
- * scale cannot be shared at runtime - a browser half may not import evolution-core, since every
7
- * `@deepseek-ai/*` specifier stays external in the client build and the platform module table has no
8
- * row for it - so the values are generated into each package instead.
9
- *
10
- * Usage: put `tokenVars(...)` for your root class in the package stylesheet, then read
11
- * `var(--evo-group-name)` in its rules.
12
- * Regenerate with: node packages/scripts/gen-client-tokens.mjs packages
13
- * @module @deepseek-ai/dsh-evolution-client-scale
14
- */
15
- /** Every custom property of the scale, in the source order. */
16
- export declare const TOKENS: Readonly<Record<string, string>>;
17
- /** The declarations, without a selector. */
18
- export declare const TOKEN_CSS: string;
19
- /**
20
- * The scale, declared on one element so it never leaks into the host shell.
21
- * @param scope - the selector the custom properties are declared on.
22
- * @returns the declaration block to put in the stylesheet.
23
- */
24
- export declare function tokenVars(scope: string): string;
25
- //# sourceMappingURL=tokens.d.ts.map