@lmzhen/dsh-evolution-skill-history 0.14.0 → 0.15.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/lib/index.js CHANGED
@@ -1,4 +1,4 @@
1
- import { contentHash, elapsedSince, errorText, latestVersionAt, partitionVersions, textDiffFacts, versionActionKind } from "@lmzhen/dsh-evolution-core";
1
+ import { contentHash, displayBodyOf, elapsedSince, errorText, latestVersionAt, partitionVersions, skillRowCells, textDiffFacts, versionActionKind, versionRowCells } from "@lmzhen/dsh-evolution-core";
2
2
  //#region lib/types/routes.js
3
3
  /**
4
4
  * The skill-history HTTP surface: six loopback routes over the curator's read/write seam (five reads plus the one write).
@@ -150,7 +150,7 @@ function makeSkillHistoryRoutes(services) {
150
150
  const versions = await curator.skills.listVersions(skill.name);
151
151
  if (versions.length === 0) continue;
152
152
  const lastAt = latestVersionAt(versions);
153
- withHistory.push({
153
+ const row = {
154
154
  name: skill.name,
155
155
  versions: versions.length,
156
156
  description: skill.description,
@@ -159,6 +159,10 @@ function makeSkillHistoryRoutes(services) {
159
159
  protectionUnknown: skill.protectionUnknown,
160
160
  lastAt,
161
161
  age: lastAt === null ? null : elapsedSince(lastAt, now)
162
+ };
163
+ withHistory.push({
164
+ ...row,
165
+ cells: skillRowCells(row)
162
166
  });
163
167
  }
164
168
  writeJson(res, 200, {
@@ -199,11 +203,23 @@ function makeSkillHistoryRoutes(services) {
199
203
  writeJson(res, 200, {
200
204
  ok: true,
201
205
  data: {
202
- content: groups.content.map((entry, index) => ({
203
- ...decorate(entry, index, groups.content, true),
204
- undoable: entry.hash !== liveHash
205
- })),
206
- support: groups.support.map((entry, index) => decorate(entry, index, groups.support, false)),
206
+ content: groups.content.map((entry, index) => {
207
+ const row = {
208
+ ...decorate(entry, index, groups.content, true),
209
+ undoable: entry.hash !== liveHash
210
+ };
211
+ return {
212
+ ...row,
213
+ cells: versionRowCells(row)
214
+ };
215
+ }),
216
+ support: groups.support.map((entry, index) => {
217
+ const row = decorate(entry, index, groups.support, false);
218
+ return {
219
+ ...row,
220
+ cells: versionRowCells(row)
221
+ };
222
+ }),
207
223
  liveHash
208
224
  }
209
225
  });
@@ -294,7 +310,7 @@ function makeSkillHistoryRoutes(services) {
294
310
  ok: true,
295
311
  data: {
296
312
  v,
297
- text: truncated ? text.slice(0, MAX_BODY_CHARS) : text,
313
+ display: displayBodyOf(truncated ? text.slice(0, MAX_BODY_CHARS) : text),
298
314
  chars: text.length,
299
315
  truncated
300
316
  }
@@ -1,33 +1,27 @@
1
1
  /**
2
- * The skill-history panel: the skills that recorded versions, the two chains of the selected skill,
3
- * and one action per body version (restore, behind an inline confirmation).
2
+ * The panel: one read, one open skill, one open row — and the faces that draw them.
4
3
  *
5
- * The panel owns no rule and no arithmetic: the host reports each row with its whole verdict
6
- * (`undoable`, the vocabulary key `actionKind`, the `age` bucket, `charsDelta`, `summary`) and this
7
- * file substitutes WORDS through the locale dictionary and renders. It never subscribes to anything
8
- * and never sees the context.
9
- *
10
- * State rules, each pinned by a live pass or a component spec: a restore's result sentence stays on
11
- * screen while the rows are read again; nothing is read on a poll (mount, opening a skill, the
12
- * refresh button, after a restore); a late reply for a skill the operator has already left is
13
- * discarded by its ticket; and the diff is fetched only when a row is expanded.
4
+ * Everything a PERSON reads is decided elsewhere: what a row says is core's (`skill-row-cells.ts`,
5
+ * shipped with the row), the words are the dictionary's, the tool face is `chrome.ts` and the reading
6
+ * face is `document.ts`. What is left here is the STATE — which skill is open, which row is expanded,
7
+ * which reads are in flight — and the two rules that only a state machine can hold: a read takes a
8
+ * ticket so a slow reply cannot land on another skill, and a write reports its own result instead of
9
+ * being erased by the read that follows it.
14
10
  * @module @lmzhen/dsh-evolution-skill-history/client
15
11
  */
16
12
  import { type ReactNode } from 'react';
13
+ import { type Copy } from './chrome.ts';
17
14
  import type { SkillRow, VersionBodyRow, VersionDiffRow, VersionsPayload } from './api.ts';
18
- import { type MarkdownWords } from './markdown.ts';
19
- /** The face the plugin hands the component: copy plus callbacks, never a service handle. */
20
- export interface PanelFace {
21
- readonly t: (key: string) => string;
22
- /** Fill one copy key's `{n}` slots (the dictionaries own the sentences). */
23
- readonly format: (key: string, values: Record<string, string | number>) => string;
15
+ import type { MarkdownWords } from './markdown.ts';
16
+ /** What the panel is handed: the dictionary seat, the renderer's words, and the host's callbacks. */
17
+ export interface PanelFace extends Copy {
18
+ /** The two words the platform Markdown renderer needs; the dictionary owns them. */
19
+ readonly markdownWords: MarkdownWords;
24
20
  readonly loadSkills: () => Promise<readonly SkillRow[]>;
25
21
  readonly loadVersions: (name: string) => Promise<VersionsPayload>;
26
22
  readonly loadDiff: (name: string, v: number) => Promise<VersionDiffRow>;
27
23
  readonly loadBody: (name: string, v: number) => Promise<VersionBodyRow>;
28
24
  readonly undo: (name: string, v?: number) => Promise<string>;
29
- /** The two words the platform Markdown renderer needs; the dictionary owns them. */
30
- readonly markdownWords: MarkdownWords;
31
25
  }
32
26
  /**
33
27
  * The panel body.
@@ -30,6 +30,30 @@ export interface VersionDiffRow {
30
30
  readonly hunks: readonly DiffHunkRow[];
31
31
  readonly truncated: boolean;
32
32
  }
33
+ /** Where a cell sits in its row: `aside` is right-aligned and is never truncated. */
34
+ export type CellSlot = 'lead' | 'meta' | 'aside';
35
+ /** The visual register a cell speaks in; the stylesheet maps it to a scale token. */
36
+ export type CellTone = 'primary' | 'secondary' | 'tertiary';
37
+ /** One cell of a row: a locale key with the values its template needs, or a verbatim fact. */
38
+ export type RowCell = {
39
+ readonly key: string;
40
+ readonly slot: CellSlot;
41
+ readonly tone: CellTone;
42
+ readonly note?: string;
43
+ readonly copy: string;
44
+ readonly values?: Readonly<Record<string, string | number>>;
45
+ } | {
46
+ readonly key: string;
47
+ readonly slot: CellSlot;
48
+ readonly tone: CellTone;
49
+ readonly note?: string;
50
+ readonly literal: string;
51
+ };
52
+ /** The lines one row shows: a title line, and a meta line under it. */
53
+ export interface RowCells {
54
+ readonly title: readonly RowCell[];
55
+ readonly meta: readonly RowCell[];
56
+ }
33
57
  /** One recorded version, as the host reports it. */
34
58
  export interface VersionRow {
35
59
  readonly v: number;
@@ -48,6 +72,8 @@ export interface VersionRow {
48
72
  readonly unit: string;
49
73
  readonly n: number;
50
74
  };
75
+ /** What this row says and where each fact sits, decided in core (`skill-row-cells.ts`). */
76
+ readonly cells: RowCells;
51
77
  /** The one line the optional summarizer wrote, when the deployment turned it on. */
52
78
  readonly summary?: string;
53
79
  /**
@@ -71,12 +97,17 @@ export interface SkillRow {
71
97
  readonly unit: string;
72
98
  readonly n: number;
73
99
  } | null;
100
+ /** What this row says and where each fact sits, decided in core (`skill-row-cells.ts`). */
101
+ readonly cells: RowCells;
74
102
  }
75
103
  /** One version's whole body, as the read route hands it over. */
76
104
  export interface VersionBodyRow {
77
105
  readonly v: number;
78
- /** The body, or its head when `truncated` — the reader is told rather than silently cut. */
79
- readonly text: string;
106
+ /**
107
+ * The text a READER sees: the body without its frontmatter block, or its head when `truncated` —
108
+ * the reader is told rather than silently cut. The exact bytes are the diff route's answer.
109
+ */
110
+ readonly display: string;
80
111
  /** How long the stored body is, whatever came back. */
81
112
  readonly chars: number;
82
113
  readonly truncated: boolean;
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The four atoms the panel's tool face is built from (G3, §15.2 L2a atoms).
3
+ *
4
+ * Why atoms at all: the row used to be assembled from five different elements that each wrote their
5
+ * own classes, so "what a control looks like" was spread over the stylesheet and a click target, a
6
+ * state chip, a refusal and a glyph had no vocabulary at all (W7/W9/W13/W14). Every interactive
7
+ * element now says what it IS — a control that acts, a control that only reveals more, a state, a
8
+ * notice — and the stylesheet answers once per kind.
9
+ *
10
+ * No words live here: an atom takes the copy its caller already resolved.
11
+ * @module @lmzhen/dsh-evolution-skill-history/client
12
+ */
13
+ import { type ReactNode } from 'react';
14
+ /** The register one control speaks in. `primary` is reserved for the click that writes. */
15
+ export type Tone = 'quiet' | 'primary';
16
+ /**
17
+ * What a control DOES, which is what makes them distinguishable at a glance: one acts, one reveals
18
+ * more (and shows whether it is open), one chooses between two views of the same thing.
19
+ */
20
+ export type ControlKind = 'action' | 'toggle' | 'switch';
21
+ /** The glyphs the panel draws. The platform's own arrows are text characters, which render in the
22
+ * reader's fallback font at whatever weight it has (W7); a drawn path cannot. */
23
+ export type IconName = 'chevron-right' | 'chevron-down' | 'alert';
24
+ /**
25
+ * One drawn glyph.
26
+ * @param name - which glyph.
27
+ * @returns an inline SVG that takes the surrounding colour and type size.
28
+ */
29
+ export declare function icon(name: IconName): ReactNode;
30
+ /** What every atom takes. */
31
+ interface BaseProps {
32
+ /** React key, for the callers that build lists. */
33
+ readonly key?: string;
34
+ /** The copy, already resolved by the dictionary seat. */
35
+ readonly children: ReactNode;
36
+ }
37
+ /** One control. `kind` says whether it acts or only reveals; `tone` says whether it writes. */
38
+ export interface ButtonProps extends BaseProps {
39
+ readonly kind?: ControlKind;
40
+ readonly tone?: Tone;
41
+ /** Hover text, when the label alone is ambiguous. */
42
+ readonly title?: string;
43
+ /** Whether the thing this control reveals is currently open (`aria-expanded`). */
44
+ readonly expanded?: boolean;
45
+ /** Whether this control is the side of a two-way choice that is showing. */
46
+ readonly pressed?: boolean;
47
+ readonly onClick: () => void;
48
+ }
49
+ /**
50
+ * One control.
51
+ * @param props - what it is, how it speaks, and what it does.
52
+ * @returns the button element.
53
+ */
54
+ export declare function button(props: ButtonProps): ReactNode;
55
+ /**
56
+ * One state, spelled as a chip: never clickable, never in the primary colour (W9).
57
+ * @param props - the copy.
58
+ * @returns the chip element.
59
+ */
60
+ export declare function chip(props: BaseProps): ReactNode;
61
+ /** One notice: a sentence about what just happened, or why nothing did. */
62
+ export interface NoteProps extends BaseProps {
63
+ /** Whether this is a refusal or a failure, which colours it and adds the glyph (W13). */
64
+ readonly error?: boolean;
65
+ }
66
+ /**
67
+ * One notice.
68
+ * @param props - the copy, and whether it reports a failure.
69
+ * @returns the note element.
70
+ */
71
+ export declare function note(props: NoteProps): ReactNode;
72
+ export {};
73
+ //# sourceMappingURL=atoms.d.ts.map
@@ -0,0 +1,73 @@
1
+ /**
2
+ * The TOOL face: the skill list, the version list, and the controls that act on a version.
3
+ *
4
+ * This file renders FACTS. What a row says, in which order and in which slot is decided in core
5
+ * (`skill-row-cells.ts`) and travels with the row, because a browser half cannot import core at
6
+ * runtime; the words come from the locale dictionary through the `Copy` seat. The renderer's only
7
+ * judgements are layout: a cell's slot decides its alignment, and the `aside` slot is the one the
8
+ * browser's ellipsis may never eat (W1).
9
+ *
10
+ * The reading face — a version rendered as a document, and the rendered diff — lives in
11
+ * `document.ts`; the two faces share the scale in `tokens.ts` and nothing else (§15.2 L2b).
12
+ * @module @lmzhen/dsh-evolution-skill-history/client
13
+ */
14
+ import { type ReactNode } from 'react';
15
+ import type { SkillRow, VersionRow } from './api.ts';
16
+ /** What a chrome builder needs: the dictionary, and nothing else. */
17
+ export interface Copy {
18
+ readonly t: (key: string) => string;
19
+ readonly format: (key: string, values: Record<string, string | number>) => string;
20
+ }
21
+ /** One kind of expansion a row can show. */
22
+ export type OpenKind = 'diff' | 'preview';
23
+ /** The local time an ISO timestamp names, as the operator's own clock shows it. */
24
+ export declare function localTime(at: string): string;
25
+ /** The search field above the list. */
26
+ export declare function searchField(copy: Copy, query: string, onQuery: (value: string) => void): ReactNode;
27
+ /**
28
+ * One skill in the left column: its name and size, then what it is and when it last changed.
29
+ * @param copy - the dictionary seat.
30
+ * @param row - the skill's facts and cells.
31
+ * @param selected - whether this is the open skill.
32
+ * @param onOpen - what a click does.
33
+ * @returns the row.
34
+ */
35
+ export declare function skillLine(copy: Copy, row: SkillRow, selected: boolean, onOpen: () => void): ReactNode;
36
+ /** What one version row needs from the panel's state machine. */
37
+ export interface VersionRowProps {
38
+ readonly copy: Copy;
39
+ readonly row: VersionRow;
40
+ /** Whether this row is the one waiting for a confirmation click. */
41
+ readonly confirming: boolean;
42
+ /** Which expansion this row currently shows, if any. */
43
+ readonly open: OpenKind | undefined;
44
+ /** The expanded content, already built by the caller. */
45
+ readonly expanded: ReactNode;
46
+ readonly onRestore: () => void;
47
+ readonly onCancel: () => void;
48
+ readonly onToggle: (kind: OpenKind) => void;
49
+ }
50
+ /**
51
+ * One version row: what happened, when, how big — then the controls, then whatever is expanded.
52
+ *
53
+ * The write is the only control that can change anything, and it is the only one that ever takes the
54
+ * primary tone; a toggle that merely reveals more is borderless and carries a drawn chevron, so the
55
+ * two kinds cannot be mistaken for each other (W7/W14).
56
+ * @param props - the row, the copy, and the panel's callbacks.
57
+ * @returns the row.
58
+ */
59
+ export declare function versionRow(props: VersionRowProps): ReactNode;
60
+ /**
61
+ * One group's heading, and the note that explains the group.
62
+ * @param title - the group's name, already resolved.
63
+ * @param noteText - the group's note, when it has one.
64
+ * @returns the heading and the note, for the caller to place in its own section.
65
+ */
66
+ export declare function groupHeading(title: string, noteText: string | undefined): ReactNode[];
67
+ /** What the list shows when it has nothing to show. */
68
+ export declare function emptyState(text: string): ReactNode;
69
+ /** One notice about what just happened. */
70
+ export declare function notice(text: string | undefined, error: boolean): ReactNode;
71
+ /** The pane's heading and its one control. */
72
+ export declare function panelHead(copy: Copy, onRefresh: () => void): ReactNode;
73
+ //# sourceMappingURL=chrome.d.ts.map
@@ -0,0 +1,71 @@
1
+ /**
2
+ * The READING face: one version rendered as a document, and the rendered diff.
3
+ *
4
+ * This file is the only place that decides how a document reads (G4). The tool face (`chrome.ts`)
5
+ * picks versions and acts on them; here the rules are the reader's, and they follow the positioning
6
+ * ruling of §14.0: a document is read, not scanned — one measure, page-like spacing, no inner scroll
7
+ * (W18/W20/W21/W22). Nothing here is a control except the source/rendered choice, which belongs to
8
+ * the reader rather than to the panel's actions.
9
+ *
10
+ * The text arrives already prepared: the host strips the frontmatter block through core's
11
+ * `displayBodyOf`, because a browser half cannot import core. The RENDERED DIFF keeps the whole text
12
+ * on purpose — a diff is about what CHANGED, and a metadata change is a change.
13
+ *
14
+ * It degrades rather than blanking: when the platform's renderer cannot be reached, the exact text is
15
+ * shown instead, and the reader can still read the version.
16
+ * @module @lmzhen/dsh-evolution-skill-history/client
17
+ */
18
+ import { type ReactNode } from 'react';
19
+ import type { VersionBodyRow, VersionDiffRow } from './api.ts';
20
+ import type { Copy } from './chrome.ts';
21
+ import { type MarkdownWords } from './markdown.ts';
22
+ /** What one expanded diff holds: the change, still loading, or a refusal. */
23
+ export type DiffState = {
24
+ kind: 'loading';
25
+ } | {
26
+ kind: 'ready';
27
+ diff: VersionDiffRow;
28
+ } | {
29
+ kind: 'failed';
30
+ message: string;
31
+ };
32
+ /** What one expanded preview holds. */
33
+ export type BodyState = {
34
+ kind: 'loading';
35
+ } | {
36
+ kind: 'ready';
37
+ body: VersionBodyRow;
38
+ } | {
39
+ kind: 'failed';
40
+ message: string;
41
+ };
42
+ /** What the reading face needs: the dictionary seat, plus the two words the platform renderer takes. */
43
+ export interface DocumentFace extends Copy {
44
+ readonly markdownWords: MarkdownWords;
45
+ }
46
+ /**
47
+ * One version read as a document: the platform renderer when it is there, plain text when it is not.
48
+ *
49
+ * The document is the page, not a card inside it: no border, no surface of its own and no inner
50
+ * scroll, so the pane's own scrollbar is the only one a reader meets (W20/W21). A body the host
51
+ * bounded says how much it is not showing, with both numbers (W23).
52
+ * @param props - the face and the body state to draw.
53
+ * @returns the element.
54
+ */
55
+ export declare function PreviewBody(props: {
56
+ face: DocumentFace;
57
+ body: BodyState;
58
+ }): ReactNode;
59
+ /**
60
+ * The expanded body of one row: the diff, a loading line, or the refusal.
61
+ *
62
+ * The source/rendered choice is LOCAL to this view: which row is open is the panel's business, but
63
+ * how one open diff is displayed is not, so the state does not climb into the parent.
64
+ * @param props - the face and the diff state to draw.
65
+ * @returns the element.
66
+ */
67
+ export declare function DiffBody(props: {
68
+ face: DocumentFace;
69
+ diff: DiffState;
70
+ }): ReactNode;
71
+ //# sourceMappingURL=document.d.ts.map
@@ -5,6 +5,23 @@ export interface MarkdownWords {
5
5
  /** The heading of the generated footnote section. */
6
6
  readonly footnotes: string;
7
7
  }
8
+ /** Copy-button labels forwarded to fenced code blocks. */
9
+ interface MarkdownCodeLabels {
10
+ copyLabel: string;
11
+ copiedLabel: string;
12
+ }
13
+ /** Localized Markdown chrome: every field the platform component requires. */
14
+ interface MarkdownLabels {
15
+ code: MarkdownCodeLabels;
16
+ footnotes: string;
17
+ }
18
+ /** What the renderer reads; the streaming and mention knobs are not used by this panel. */
19
+ interface MarkdownTextProps {
20
+ text: string;
21
+ labels: MarkdownLabels;
22
+ }
23
+ /** The component as the module table hands it over. */
24
+ type MarkdownTextComponent = (props: MarkdownTextProps) => unknown;
8
25
  /** One render attempt: the element, or the news that this deployment has no renderer. */
9
26
  export type MarkdownRender = {
10
27
  readonly ok: true;
@@ -12,6 +29,21 @@ export type MarkdownRender = {
12
29
  } | {
13
30
  readonly ok: false;
14
31
  };
32
+ /**
33
+ * The renderer a module row carries, when it carries one.
34
+ *
35
+ * A React component type is NOT always a function: the platform's own `MarkdownText` is
36
+ * `memo(function MarkdownText …)`, and `memo` returns an OBJECT. A `typeof === 'function'` test
37
+ * therefore rejected the real renderer and silently degraded every view to its source — exactly
38
+ * what 0.14.0 shipped (measured on the installed panel 2026-09-28: `[预览]` and the rendered diff
39
+ * both fell back). The accepted domain is React's element-type domain: a function, or a non-null
40
+ * object it can mount. `tests/markdown.client.spec.ts` pins all four cases.
41
+ * @param row - what the client module table handed over.
42
+ * @returns the component, or undefined when the row carries none.
43
+ */
44
+ export declare function rendererOf(row: {
45
+ MarkdownText?: unknown;
46
+ }): MarkdownTextComponent | undefined;
15
47
  /**
16
48
  * Render one Markdown document to an element tree.
17
49
  * @param text - the Markdown source (already bounded by the caller).
@@ -20,4 +52,5 @@ export type MarkdownRender = {
20
52
  * then keeps its own source view: a missing renderer degrades the view, never the panel).
21
53
  */
22
54
  export declare function renderMarkdown(text: string, words: MarkdownWords): MarkdownRender;
55
+ export {};
23
56
  //# sourceMappingURL=markdown.d.ts.map
@@ -1,24 +1,3 @@
1
- /**
2
- * The panel’s stylesheet, injected once behind a `<style data-plugin-css=…>` tag.
3
- *
4
- * The bundle is built outside the platform’s CSS-Modules pipeline, so it carries its own string and
5
- * injects it the same way the family’s settings section does. Every rule reads the platform’s design
6
- * tokens, and the metrics are COPIED from the platform’s own components rather than invented:
7
- *
8
- * - the code block (`--dsw-font-markdown-code-block-small`, `.5px` border, `12px`, radius `12px`,
9
- * `max-height: 260px`) is the platform command card’s `<pre>` (client/ui-chat/…/GenericCommandCard.module.css);
10
- * - hover / focus (`--dsw-alias-interactive-bg-hover`, a 2px inset focus ring) follow the platform
11
- * sidebar row (client/ui-sidebar/…/SidebarRoot.module.css);
12
- * - the panel’s type scale is the platform TOKEN rather than a magic number, so it follows the
13
- * deployment’s content size the way the platform’s own panels do;
14
- * - the capsule and the field metrics follow the family’s settings card, which copied them from the
15
- * platform’s settings fields in the first place.
16
- *
17
- * Geometry (widths, paddings, radii, the 260px scroll cap) is a plain number here because the platform's
18
- * own components write geometry the same way; what must never be a literal is TYPE and COLOUR, and
19
- * every size and colour below is a token or a `calc()` over one.
20
- * @module @lmzhen/dsh-evolution-skill-history/client
21
- */
22
1
  /** Tag id that makes the injection idempotent. */
23
2
  export declare const CSS_TAG_ID = "@lmzhen/dsh-evolution-skill-history/panel.css";
24
3
  /** The stylesheet the panel injects once. */
@@ -0,0 +1,25 @@
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
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@lmzhen/dsh-evolution-skill-history",
3
3
  "description": "Web surface for skill content history: loopback host routes plus the sidebar panel (community build)",
4
- "version": "0.14.0",
4
+ "version": "0.15.0",
5
5
  "publishConfig": {
6
6
  "access": "public"
7
7
  },
@@ -30,23 +30,23 @@
30
30
  ],
31
31
  "license": "MIT",
32
32
  "dependencies": {
33
- "@lmzhen/dsh-evolution-core": "^0.14.0"
33
+ "@lmzhen/dsh-evolution-core": "^0.15.0"
34
34
  },
35
35
  "peerDependencies": {
36
36
  "@deepseek-ai/cordis": "^4.0.1",
37
37
  "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.2",
38
38
  "react": "^18.2.0",
39
- "@lmzhen/dsh-evolution-curator": "^0.14.0"
39
+ "@lmzhen/dsh-evolution-curator": "^0.15.0"
40
40
  },
41
41
  "devDependencies": {
42
42
  "@deepseek-ai/cordis": "^4.0.1",
43
43
  "@deepseek-ai/dsh-host-webserver": "^0.1.5-rc.2",
44
44
  "@types/react": "~18.3.1",
45
45
  "react": "^18.2.0",
46
- "@lmzhen/dsh-evolution-core": "^0.14.0",
47
- "@lmzhen/dsh-evolution-curator": "^0.14.0",
48
- "@lmzhen/dsh-evolution-io": "^0.14.0",
49
- "@lmzhen/dsh-evolution-io-node": "^0.14.0"
46
+ "@lmzhen/dsh-evolution-core": "^0.15.0",
47
+ "@lmzhen/dsh-evolution-curator": "^0.15.0",
48
+ "@lmzhen/dsh-evolution-io": "^0.15.0",
49
+ "@lmzhen/dsh-evolution-io-node": "^0.15.0"
50
50
  },
51
51
  "dsh": {
52
52
  "client": {