mockpit 3.0.0 → 3.1.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/README.md +11 -23
- package/bin/initDesign.js +11 -16
- package/bin/mockpit.js +242 -52
- package/bin/poster.js +64 -7
- package/dist/mcp/server.js +48 -6
- package/dist/server/apiViews.d.ts +562 -557
- package/dist/server/apiViews.js +18 -9
- package/dist/server/app.js +723 -206
- package/dist/server/cdnInline.js +6 -4
- package/dist/server/codeWorker.js +2 -2
- package/dist/server/contrast.d.ts +4 -0
- package/dist/server/contrast.js +157 -0
- package/dist/server/decisionList.d.ts +4 -1
- package/dist/server/decisionList.js +43 -5
- package/dist/server/designGuide.d.ts +13 -6
- package/dist/server/designGuide.js +206 -41
- package/dist/server/events.d.ts +6 -0
- package/dist/server/feedbackBatch.d.ts +4 -0
- package/dist/server/feedbackBatch.js +19 -1
- package/dist/server/guidance.d.ts +1 -1
- package/dist/server/guidance.js +2 -2
- package/dist/server/kits.d.ts +2 -2
- package/dist/server/kits.js +54 -1
- package/dist/server/mcpHttp.d.ts +2 -0
- package/dist/server/mcpHttp.js +13 -1
- package/dist/server/mcpSpec.d.ts +27 -27
- package/dist/server/mcpSpec.js +78 -10
- package/dist/server/run.js +22 -1
- package/dist/server/runApi.d.ts +2 -2
- package/dist/server/runApi.js +9 -2
- package/dist/server/sqlStore.d.ts +68 -39
- package/dist/server/sqlStore.js +163 -26
- package/dist/server/surfacePage.d.ts +4 -2
- package/dist/server/surfacePage.js +80 -32
- package/dist/server/system.d.ts +234 -0
- package/dist/server/system.js +1508 -0
- package/dist/server/systemChecks.d.ts +15 -0
- package/dist/server/systemChecks.js +224 -0
- package/dist/server/systemSpecimen.d.ts +2 -0
- package/dist/server/systemSpecimen.js +49 -0
- package/dist/server/themes.d.ts +9 -7
- package/dist/server/themes.js +43 -90
- package/dist/server/types.d.ts +43 -24
- package/dist/server/types.js +3 -1
- package/guide/AGENT_SETUP.md +3 -1
- package/guide/packs/foundations.md +35 -0
- package/guide/topics/asks.md +2 -1
- package/guide/topics/feedback.md +5 -3
- package/guide/topics/html.md +2 -2
- package/guide/topics/http.md +3 -1
- package/guide/topics/system.md +157 -0
- package/package.json +12 -12
- package/skills/mockpit/SKILL.md +7 -4
- package/viewer/dist/index.html +9 -8
package/dist/server/cdnInline.js
CHANGED
|
@@ -409,9 +409,11 @@ export function createCdnInliner() {
|
|
|
409
409
|
last = at + m[0].length;
|
|
410
410
|
const raw = m[1] ?? m[2] ?? m[3] ?? m[4] ?? m[5] ?? "";
|
|
411
411
|
const url = onCdn(raw, base);
|
|
412
|
-
// A
|
|
413
|
-
|
|
414
|
-
|
|
412
|
+
// A layer is wrapped as a block, which says the same; a media or
|
|
413
|
+
// supports qualifier would need more, so it keeps its link.
|
|
414
|
+
const qualifier = m[6]?.trim() ?? "";
|
|
415
|
+
const layer = /^layer\(\s*([A-Za-z_][\w.-]*)\s*\)$/.exec(qualifier)?.[1];
|
|
416
|
+
if (!url || (qualifier && !layer) || depth >= MAX_IMPORT_DEPTH) {
|
|
415
417
|
imports += `${m[0]}\n`;
|
|
416
418
|
continue;
|
|
417
419
|
}
|
|
@@ -421,7 +423,7 @@ export function createCdnInliner() {
|
|
|
421
423
|
continue;
|
|
422
424
|
}
|
|
423
425
|
imports += inlined.imports;
|
|
424
|
-
importedBody += `${inlined.body}\n`;
|
|
426
|
+
importedBody += layer ? `@layer ${layer}{${inlined.body}}\n` : `${inlined.body}\n`;
|
|
425
427
|
}
|
|
426
428
|
rest += absolute.slice(last);
|
|
427
429
|
return { imports, body: `${importedBody}${await rewriteFaces(rest, base)}` };
|
|
@@ -25,8 +25,8 @@ const PRELUDE = `(function (call, out) {
|
|
|
25
25
|
};
|
|
26
26
|
globalThis.mockpit = Object.freeze({
|
|
27
27
|
guide: fn("guide"), read: fn("read"), publish: fn("publish"), ask: fn("ask"),
|
|
28
|
-
feedback: fn("feedback"), say: fn("say"), move: fn("move"), edit: fn("edit"),
|
|
29
|
-
upload: fn("upload"),
|
|
28
|
+
feedback: fn("feedback"), say: fn("say"), move: fn("move"), edit: fn("edit"), system: fn("system"),
|
|
29
|
+
export: fn("export"), upload: fn("upload"),
|
|
30
30
|
});
|
|
31
31
|
globalThis.print = print;
|
|
32
32
|
globalThis.console = Object.freeze({ log: print, info: print, warn: print, error: print });
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
// WCAG 2.2 contrast between two CSS colours, for the system's declared pairs.
|
|
2
|
+
// Five notations resolve: hex, rgb(), hsl(), oklch() and oklab(). Anything else
|
|
3
|
+
// (a var(), color-mix(), a named colour past the few below) is unresolved, and
|
|
4
|
+
// the caller reports the pair as unchecked rather than passing it.
|
|
5
|
+
// Runtime-agnostic.
|
|
6
|
+
const NAMED = {
|
|
7
|
+
white: [1, 1, 1, 1],
|
|
8
|
+
black: [0, 0, 0, 1],
|
|
9
|
+
transparent: [0, 0, 0, 0],
|
|
10
|
+
};
|
|
11
|
+
const clamp01 = (n) => Math.min(1, Math.max(0, n));
|
|
12
|
+
// A number, a percentage of `full`, or `none` (0).
|
|
13
|
+
function channel(raw, full) {
|
|
14
|
+
const s = raw.trim();
|
|
15
|
+
if (s === "none")
|
|
16
|
+
return 0;
|
|
17
|
+
const pct = /^(-?\d*\.?\d+)%$/.exec(s);
|
|
18
|
+
if (pct)
|
|
19
|
+
return (Number(pct[1]) / 100) * full;
|
|
20
|
+
const n = /^(-?\d*\.?\d+(?:e-?\d+)?)$/.exec(s);
|
|
21
|
+
return n ? Number(n[1]) : null;
|
|
22
|
+
}
|
|
23
|
+
function hue(raw) {
|
|
24
|
+
const m = /^(-?\d*\.?\d+)(deg|turn|rad|grad)?$/.exec(raw.trim());
|
|
25
|
+
if (!m)
|
|
26
|
+
return raw.trim() === "none" ? 0 : null;
|
|
27
|
+
const n = Number(m[1]);
|
|
28
|
+
switch (m[2]) {
|
|
29
|
+
case "turn":
|
|
30
|
+
return n * 360;
|
|
31
|
+
case "rad":
|
|
32
|
+
return (n * 180) / Math.PI;
|
|
33
|
+
case "grad":
|
|
34
|
+
return n * 0.9;
|
|
35
|
+
default:
|
|
36
|
+
return n;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
// `fn(a b c / d)` or the legacy `fn(a, b, c, d)` into its parts.
|
|
40
|
+
function args(body) {
|
|
41
|
+
const [main, alpha] = body.includes("/") ? body.split("/") : [body, null];
|
|
42
|
+
const parts = main.includes(",")
|
|
43
|
+
? main.split(",").map((s) => s.trim())
|
|
44
|
+
: main.trim().split(/\s+/);
|
|
45
|
+
if (parts.length === 4 && alpha === null && main.includes(","))
|
|
46
|
+
return { parts: parts.slice(0, 3), alpha: parts[3] };
|
|
47
|
+
if (parts.length !== 3)
|
|
48
|
+
return null;
|
|
49
|
+
return { parts, alpha: alpha?.trim() ?? null };
|
|
50
|
+
}
|
|
51
|
+
const linearToSrgb = (c) => (c <= 0.0031308 ? 12.92 * c : 1.055 * c ** (1 / 2.4) - 0.055);
|
|
52
|
+
function oklabToRgb(L, a, b) {
|
|
53
|
+
const l_ = L + 0.3963377774 * a + 0.2158037573 * b;
|
|
54
|
+
const m_ = L - 0.1055613458 * a - 0.0638541728 * b;
|
|
55
|
+
const s_ = L - 0.0894841775 * a - 1.291485548 * b;
|
|
56
|
+
const l = l_ ** 3;
|
|
57
|
+
const m = m_ ** 3;
|
|
58
|
+
const s = s_ ** 3;
|
|
59
|
+
return [
|
|
60
|
+
clamp01(linearToSrgb(4.0767416621 * l - 3.3077115913 * m + 0.2309699292 * s)),
|
|
61
|
+
clamp01(linearToSrgb(-1.2684380046 * l + 2.6097574011 * m - 0.3413193965 * s)),
|
|
62
|
+
clamp01(linearToSrgb(-0.0041960863 * l - 0.7034186147 * m + 1.707614701 * s)),
|
|
63
|
+
];
|
|
64
|
+
}
|
|
65
|
+
function hslToRgb(h, s, l) {
|
|
66
|
+
const k = (n) => (n + h / 30) % 12;
|
|
67
|
+
const a = s * Math.min(l, 1 - l);
|
|
68
|
+
const f = (n) => l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)));
|
|
69
|
+
return [f(0), f(8), f(4)];
|
|
70
|
+
}
|
|
71
|
+
export function parseColor(input) {
|
|
72
|
+
const v = input.trim().toLowerCase();
|
|
73
|
+
if (NAMED[v])
|
|
74
|
+
return NAMED[v];
|
|
75
|
+
const hex = /^#([0-9a-f]{3,8})$/.exec(v);
|
|
76
|
+
if (hex) {
|
|
77
|
+
let h = hex[1];
|
|
78
|
+
if (h.length === 3 || h.length === 4)
|
|
79
|
+
h = [...h].map((c) => c + c).join("");
|
|
80
|
+
if (h.length !== 6 && h.length !== 8)
|
|
81
|
+
return null;
|
|
82
|
+
const n = (i) => parseInt(h.slice(i, i + 2), 16) / 255;
|
|
83
|
+
return [n(0), n(2), n(4), h.length === 8 ? n(6) : 1];
|
|
84
|
+
}
|
|
85
|
+
const fn = /^([a-z]+)\((.*)\)$/.exec(v);
|
|
86
|
+
if (!fn)
|
|
87
|
+
return null;
|
|
88
|
+
const parsed = args(fn[2]);
|
|
89
|
+
if (!parsed)
|
|
90
|
+
return null;
|
|
91
|
+
const alpha = parsed.alpha === null ? 1 : channel(parsed.alpha, 1);
|
|
92
|
+
if (alpha === null)
|
|
93
|
+
return null;
|
|
94
|
+
const [p0, p1, p2] = parsed.parts;
|
|
95
|
+
switch (fn[1]) {
|
|
96
|
+
case "rgb":
|
|
97
|
+
case "rgba": {
|
|
98
|
+
const c = [channel(p0, 255), channel(p1, 255), channel(p2, 255)];
|
|
99
|
+
if (c.some((x) => x === null))
|
|
100
|
+
return null;
|
|
101
|
+
return [clamp01(c[0] / 255), clamp01(c[1] / 255), clamp01(c[2] / 255), clamp01(alpha)];
|
|
102
|
+
}
|
|
103
|
+
case "hsl":
|
|
104
|
+
case "hsla": {
|
|
105
|
+
const h = hue(p0);
|
|
106
|
+
const s = channel(p1.endsWith("%") ? p1 : `${p1}%`, 1);
|
|
107
|
+
const l = channel(p2.endsWith("%") ? p2 : `${p2}%`, 1);
|
|
108
|
+
if (h === null || s === null || l === null)
|
|
109
|
+
return null;
|
|
110
|
+
return [...hslToRgb(((h % 360) + 360) % 360, clamp01(s), clamp01(l)), clamp01(alpha)];
|
|
111
|
+
}
|
|
112
|
+
case "oklab": {
|
|
113
|
+
const L = channel(p0, 1);
|
|
114
|
+
const a = channel(p1, 0.4);
|
|
115
|
+
const b = channel(p2, 0.4);
|
|
116
|
+
if (L === null || a === null || b === null)
|
|
117
|
+
return null;
|
|
118
|
+
return [...oklabToRgb(L, a, b), clamp01(alpha)];
|
|
119
|
+
}
|
|
120
|
+
case "oklch": {
|
|
121
|
+
const L = channel(p0, 1);
|
|
122
|
+
const C = channel(p1, 0.4);
|
|
123
|
+
const h = hue(p2);
|
|
124
|
+
if (L === null || C === null || h === null)
|
|
125
|
+
return null;
|
|
126
|
+
const r = (h * Math.PI) / 180;
|
|
127
|
+
return [...oklabToRgb(L, C * Math.cos(r), C * Math.sin(r)), clamp01(alpha)];
|
|
128
|
+
}
|
|
129
|
+
default:
|
|
130
|
+
return null;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
const luminance = ([r, g, b]) => {
|
|
134
|
+
const lin = (c) => (c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4);
|
|
135
|
+
return 0.2126 * lin(r) + 0.7152 * lin(g) + 0.0722 * lin(b);
|
|
136
|
+
};
|
|
137
|
+
// A translucent colour is what it shows over what's under it.
|
|
138
|
+
const over = (top, under) => [
|
|
139
|
+
top[0] * top[3] + under[0] * (1 - top[3]),
|
|
140
|
+
top[1] * top[3] + under[1] * (1 - top[3]),
|
|
141
|
+
top[2] * top[3] + under[2] * (1 - top[3]),
|
|
142
|
+
1,
|
|
143
|
+
];
|
|
144
|
+
// The ratio, rounded to two places, or null when either colour doesn't resolve.
|
|
145
|
+
// A translucent background sits on white, the frame's canvas.
|
|
146
|
+
export function contrastRatio(fg, bg) {
|
|
147
|
+
const f = parseColor(fg);
|
|
148
|
+
const b0 = parseColor(bg);
|
|
149
|
+
if (!f || !b0)
|
|
150
|
+
return null;
|
|
151
|
+
const b = b0[3] < 1 ? over(b0, [1, 1, 1, 1]) : b0;
|
|
152
|
+
const top = f[3] < 1 ? over(f, b) : f;
|
|
153
|
+
const l1 = luminance(top);
|
|
154
|
+
const l2 = luminance(b);
|
|
155
|
+
const ratio = (Math.max(l1, l2) + 0.05) / (Math.min(l1, l2) + 0.05);
|
|
156
|
+
return Math.round(ratio * 100) / 100;
|
|
157
|
+
}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { type DecisionSources, type Design } from "./types.ts";
|
|
2
|
+
import type { System } from "./system.ts";
|
|
2
3
|
export interface DecisionParts {
|
|
3
4
|
asked: string;
|
|
4
5
|
chose?: string;
|
|
@@ -15,6 +16,7 @@ export interface DecisionLine {
|
|
|
15
16
|
parts?: DecisionParts;
|
|
16
17
|
edited?: true;
|
|
17
18
|
archived?: true;
|
|
19
|
+
system?: true;
|
|
18
20
|
at?: string;
|
|
19
21
|
}
|
|
20
22
|
export type DecisionEdits = Record<string, {
|
|
@@ -23,7 +25,7 @@ export type DecisionEdits = Record<string, {
|
|
|
23
25
|
removed?: true;
|
|
24
26
|
}>;
|
|
25
27
|
export declare function parseDecisionEdits(raw: string | null): DecisionEdits;
|
|
26
|
-
export declare function deriveDecisionLines(designs: Design[], sources: DecisionSources): (DecisionLine & {
|
|
28
|
+
export declare function deriveDecisionLines(designs: Design[], sources: DecisionSources, system?: System | null): (DecisionLine & {
|
|
27
29
|
basis: string;
|
|
28
30
|
})[];
|
|
29
31
|
export declare function applyDecisionEdits(lines: (DecisionLine & {
|
|
@@ -32,6 +34,7 @@ export declare function applyDecisionEdits(lines: (DecisionLine & {
|
|
|
32
34
|
export interface AgentDecisionLine {
|
|
33
35
|
design: string;
|
|
34
36
|
text: string;
|
|
37
|
+
system?: true;
|
|
35
38
|
here?: true;
|
|
36
39
|
edited?: true;
|
|
37
40
|
archived?: true;
|
|
@@ -177,7 +177,7 @@ function standingBasis(design, ask) {
|
|
|
177
177
|
// Every line the project's replies add up to, as derived: newest decided design
|
|
178
178
|
// first, an archived design after every live one, each design's lines as it asked them
|
|
179
179
|
// with what it put in use first.
|
|
180
|
-
export function deriveDecisionLines(designs, sources) {
|
|
180
|
+
export function deriveDecisionLines(designs, sources, system = null) {
|
|
181
181
|
const byDesign = new Map();
|
|
182
182
|
for (const v of sources.variants) {
|
|
183
183
|
const list = byDesign.get(v.designId);
|
|
@@ -188,7 +188,7 @@ export function deriveDecisionLines(designs, sources) {
|
|
|
188
188
|
}
|
|
189
189
|
const order = [...designs].sort((a, b) => Number(!!a.archivedAt) - Number(!!b.archivedAt) ||
|
|
190
190
|
(sources.decidedAt[b.id] ?? "").localeCompare(sources.decidedAt[a.id] ?? ""));
|
|
191
|
-
const out =
|
|
191
|
+
const out = systemLines(system);
|
|
192
192
|
for (const design of order) {
|
|
193
193
|
const variants = byDesign.get(design.id) ?? [];
|
|
194
194
|
const base = {
|
|
@@ -234,6 +234,39 @@ export function deriveDecisionLines(designs, sources) {
|
|
|
234
234
|
}
|
|
235
235
|
return out;
|
|
236
236
|
}
|
|
237
|
+
// The project's own decisions, first: they hold on every design. A palette line
|
|
238
|
+
// only once there are palettes to choose between.
|
|
239
|
+
function systemLines(system) {
|
|
240
|
+
if (!system)
|
|
241
|
+
return [];
|
|
242
|
+
const base = { design: "", title: "System", system: true };
|
|
243
|
+
const out = [];
|
|
244
|
+
const palettes = system.color.palettes;
|
|
245
|
+
const def = palettes.find((p) => p.status === "default");
|
|
246
|
+
if (def && palettes.length > 1) {
|
|
247
|
+
const named = (status) => palettes.filter((p) => p.status === status).map((p) => p.label || p.id);
|
|
248
|
+
const kept = named("kept");
|
|
249
|
+
const hidden = named("hidden");
|
|
250
|
+
const text = [
|
|
251
|
+
`Palette: ${def.label || def.id} by default.`,
|
|
252
|
+
kept.length ? ` Kept: ${kept.join(", ")}.` : "",
|
|
253
|
+
hidden.length ? ` Not: ${hidden.join(", ")}.` : "",
|
|
254
|
+
].join("");
|
|
255
|
+
out.push({
|
|
256
|
+
...base,
|
|
257
|
+
id: "system:palette",
|
|
258
|
+
text,
|
|
259
|
+
basis: JSON.stringify(palettes.map((p) => [p.id, p.status])),
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
for (const [path, value] of Object.entries(system.settled)) {
|
|
263
|
+
if (!Object.hasOwn(system.knobs, path))
|
|
264
|
+
continue;
|
|
265
|
+
const text = `Project knob ${path}: ${typeof value === "string" ? value : JSON.stringify(value)}.`;
|
|
266
|
+
out.push({ ...base, id: `system:knob:${path}`, text, basis: JSON.stringify(value) });
|
|
267
|
+
}
|
|
268
|
+
return out;
|
|
269
|
+
}
|
|
237
270
|
// The hand edits laid over the derived lines. An edit made on an older answer
|
|
238
271
|
// no longer applies: the user has decided again since.
|
|
239
272
|
export function applyDecisionEdits(lines, edits) {
|
|
@@ -256,9 +289,12 @@ export function applyDecisionEdits(lines, edits) {
|
|
|
256
289
|
const AGENT_LINE_CHARS = 280;
|
|
257
290
|
const AGENT_LIST_CHARS = 6000;
|
|
258
291
|
export function agentDecisionList(lines, here) {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
292
|
+
// The project's own come first wherever the read is: they hold on every design.
|
|
293
|
+
const ordered = [
|
|
294
|
+
...lines.filter((l) => l.system),
|
|
295
|
+
...lines.filter((l) => !l.system && here && l.design === here),
|
|
296
|
+
...lines.filter((l) => !l.system && !(here && l.design === here)),
|
|
297
|
+
];
|
|
262
298
|
const kept = [];
|
|
263
299
|
let used = 0;
|
|
264
300
|
let clipped = false;
|
|
@@ -272,6 +308,7 @@ export function agentDecisionList(lines, here) {
|
|
|
272
308
|
kept.push({
|
|
273
309
|
design: l.design,
|
|
274
310
|
text,
|
|
311
|
+
...(l.system ? { system: true } : {}),
|
|
275
312
|
...(l.design === here ? { here: true } : {}),
|
|
276
313
|
...(l.edited ? { edited: true } : {}),
|
|
277
314
|
...(l.archived ? { archived: true } : {}),
|
|
@@ -295,6 +332,7 @@ export function fullAgentDecisionList(lines) {
|
|
|
295
332
|
lines: lines.map((l) => ({
|
|
296
333
|
design: l.design,
|
|
297
334
|
text: l.text,
|
|
335
|
+
...(l.system ? { system: true } : {}),
|
|
298
336
|
...(l.edited ? { edited: true } : {}),
|
|
299
337
|
...(l.archived ? { archived: true } : {}),
|
|
300
338
|
})),
|
|
@@ -1,20 +1,27 @@
|
|
|
1
|
-
import type
|
|
2
|
-
export declare const GUIDE_TOPICS: readonly ["knobs", "asks", "surfaces", "html", "feedback", "http", "scripts"];
|
|
1
|
+
import { type System } from "./system.ts";
|
|
2
|
+
export declare const GUIDE_TOPICS: readonly ["system", "knobs", "asks", "surfaces", "html", "feedback", "http", "scripts"];
|
|
3
3
|
export type GuideTopic = (typeof GUIDE_TOPICS)[number];
|
|
4
4
|
export declare const isGuideTopic: (id: unknown) => id is GuideTopic;
|
|
5
5
|
export declare const unknownTopicMessage: (topic: string) => string;
|
|
6
|
-
export declare function iconsLine(
|
|
6
|
+
export declare function iconsLine(system: System | null): string;
|
|
7
7
|
/**
|
|
8
8
|
* What the repo's DESIGN.md, DTCG tokens and shadcn components.json say, as
|
|
9
9
|
* init stored them. Empty when the repo has none.
|
|
10
10
|
*/
|
|
11
|
-
export declare function designFilesSection(
|
|
11
|
+
export declare function designFilesSection(system: System | null): string;
|
|
12
|
+
export interface ComponentLine {
|
|
13
|
+
slug: string;
|
|
14
|
+
purpose: string;
|
|
15
|
+
screens: number;
|
|
16
|
+
}
|
|
17
|
+
export declare function systemSection(system: System | null, components?: ComponentLine[]): string;
|
|
18
|
+
export declare function renderSystemTopic(contract: string, system: System | null, components?: ComponentLine[]): string;
|
|
12
19
|
/**
|
|
13
20
|
* The project-aware brief. `designSystem` is the stored `design:<project>` settings,
|
|
14
21
|
* or null for a project that never ran `mockpit init`; `guidance` is the
|
|
15
22
|
* layers above core (server/guidance.ts), absent when none is on.
|
|
16
23
|
*/
|
|
17
|
-
export declare function renderBriefGuide(
|
|
24
|
+
export declare function renderBriefGuide(system: System | null, guidance?: {
|
|
18
25
|
line: string;
|
|
19
26
|
body: string;
|
|
20
|
-
}): string;
|
|
27
|
+
}, components?: ComponentLine[]): string;
|