mockpit 2.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 +59 -223
- package/bin/demoData.js +2 -2
- package/bin/initDesign.js +17 -22
- package/bin/mockpit.js +626 -216
- package/bin/poster.js +434 -0
- package/dist/mcp/server.js +127 -29
- package/dist/server/answerAdditions.d.ts +7 -0
- package/dist/server/answerAdditions.js +76 -0
- package/dist/server/apiViews.d.ts +627 -385
- package/dist/server/apiViews.js +198 -81
- package/dist/server/app.d.ts +7 -2
- package/dist/server/app.js +3514 -984
- package/dist/server/appIcon.js +15 -5
- package/dist/server/appIconPng.js +3 -3
- package/dist/server/askNudges.js +1 -1
- package/dist/server/cdnInline.d.ts +8 -0
- package/dist/server/cdnInline.js +640 -0
- 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 +48 -0
- package/dist/server/decisionList.js +340 -0
- package/dist/server/decisions.d.ts +4 -4
- package/dist/server/decisions.js +9 -9
- package/dist/server/designGuide.d.ts +14 -7
- package/dist/server/designGuide.js +314 -88
- package/dist/server/embeds.d.ts +3 -1
- package/dist/server/embeds.js +31 -6
- package/dist/server/eventLog.d.ts +2 -2
- package/dist/server/eventLog.js +11 -11
- package/dist/server/events.d.ts +15 -6
- package/dist/server/feedbackBatch.d.ts +39 -13
- package/dist/server/feedbackBatch.js +129 -47
- package/dist/server/fills.d.ts +4 -0
- package/dist/server/fills.js +55 -1
- package/dist/server/guidance.d.ts +1 -1
- package/dist/server/guidance.js +2 -2
- package/dist/server/handoff.d.ts +4 -1
- package/dist/server/handoff.js +8 -2
- package/dist/server/icons.js +1 -1
- package/dist/server/index.js +39 -10
- package/dist/server/jump.d.ts +21 -0
- package/dist/server/jump.js +175 -0
- package/dist/server/kits.d.ts +2 -2
- package/dist/server/kits.js +54 -1
- package/dist/server/knobs.d.ts +3 -3
- package/dist/server/knobs.js +6 -6
- package/dist/server/mcpHttp.d.ts +7 -1
- package/dist/server/mcpHttp.js +29 -12
- package/dist/server/mcpSpec.d.ts +27 -27
- package/dist/server/mcpSpec.js +196 -56
- package/dist/server/parts.js +9 -1
- package/dist/server/run.d.ts +1 -1
- package/dist/server/run.js +47 -17
- package/dist/server/runApi.d.ts +3 -3
- package/dist/server/runApi.js +34 -21
- package/dist/server/sqlStore.d.ts +148 -103
- package/dist/server/sqlStore.js +1052 -181
- package/dist/server/standings.d.ts +25 -0
- package/dist/server/standings.js +113 -0
- package/dist/server/surfacePage.d.ts +8 -9
- package/dist/server/surfacePage.js +423 -100
- 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 +266 -93
- package/dist/server/types.js +76 -79
- package/extensions/mockpit.js +89 -72
- package/guide/AGENT_SETUP.md +15 -1
- package/guide/packs/design-craft.md +2 -3
- package/guide/packs/foundations.md +35 -0
- package/guide/topics/asks.md +108 -63
- package/guide/topics/feedback.md +129 -120
- package/guide/topics/html.md +18 -25
- package/guide/topics/http.md +43 -41
- package/guide/topics/knobs.md +7 -10
- package/guide/topics/scripts.md +22 -33
- package/guide/topics/surfaces.md +39 -48
- package/guide/topics/system.md +157 -0
- package/opencode/mockpit.js +120 -0
- package/opencode/package.json +8 -0
- package/package.json +15 -14
- package/skills/launch-video/SKILL.md +11 -11
- package/skills/mockpit/SKILL.md +33 -26
- package/viewer/dist/index.html +10 -9
package/dist/server/parts.js
CHANGED
|
@@ -48,8 +48,16 @@ export function partsInHtml(html) {
|
|
|
48
48
|
}
|
|
49
49
|
return [...byName.values()];
|
|
50
50
|
}
|
|
51
|
+
// Cached per surfaces array, which a stored post never mutates: a design's view
|
|
52
|
+
// asks for every variant's parts on every read. Callers must not change the result.
|
|
53
|
+
const bySurfaces = new WeakMap();
|
|
51
54
|
export function partsInSurfaces(surfaces) {
|
|
52
|
-
|
|
55
|
+
const hit = bySurfaces.get(surfaces);
|
|
56
|
+
if (hit)
|
|
57
|
+
return hit;
|
|
58
|
+
const parts = mergeParts(surfaces.flatMap((s) => (s.kind === "html" ? [partsInHtml(s.html)] : [])));
|
|
59
|
+
bySurfaces.set(surfaces, parts);
|
|
60
|
+
return parts;
|
|
53
61
|
}
|
|
54
62
|
// Union several part lists by name, first occurrence first.
|
|
55
63
|
export function mergeParts(lists) {
|
package/dist/server/run.d.ts
CHANGED
|
@@ -77,6 +77,6 @@ export interface RunDeps {
|
|
|
77
77
|
status: number;
|
|
78
78
|
}>;
|
|
79
79
|
}
|
|
80
|
-
export declare const RUN_UNAVAILABLE = "run is not available on this deployment: it has no script sandbox. Use the
|
|
80
|
+
export declare const RUN_UNAVAILABLE = "run is not available on this deployment: it has no script sandbox. Use the design tools (or REST) instead";
|
|
81
81
|
export declare function cut(s: string, max: number): string;
|
|
82
82
|
export declare function createRunFlow(deps: RunDeps): (body: any, ctx: FlowContext) => Promise<FlowResult>;
|
package/dist/server/run.js
CHANGED
|
@@ -26,7 +26,7 @@ export const DEFAULT_RUN_LIMITS = {
|
|
|
26
26
|
maxInflight: 4,
|
|
27
27
|
maxRuns: 4,
|
|
28
28
|
};
|
|
29
|
-
export const RUN_UNAVAILABLE = "run is not available on this deployment: it has no script sandbox. Use the
|
|
29
|
+
export const RUN_UNAVAILABLE = "run is not available on this deployment: it has no script sandbox. Use the design tools (or REST) instead";
|
|
30
30
|
const text = (v, max) => typeof v === "string" && v.trim() ? v.trim().slice(0, max) : undefined;
|
|
31
31
|
const plain = (v) => v && typeof v === "object" && !Array.isArray(v) ? v : {};
|
|
32
32
|
// Keep the head and the tail: the start says what a value is, the end is where
|
|
@@ -40,7 +40,7 @@ export function cut(s, max) {
|
|
|
40
40
|
}
|
|
41
41
|
function writeSummary(body) {
|
|
42
42
|
const post = body?.post;
|
|
43
|
-
const slug = body?.
|
|
43
|
+
const slug = body?.design?.slug ?? "?";
|
|
44
44
|
if (!post)
|
|
45
45
|
return slug;
|
|
46
46
|
return `${slug}/${post.state ? `${post.state}/` : ""}${post.variant} v${post.version}`;
|
|
@@ -150,28 +150,35 @@ export function createRunFlow(deps) {
|
|
|
150
150
|
return [await deps.guide(await projectOf()), "brief"];
|
|
151
151
|
if (!isGuideTopic(topic))
|
|
152
152
|
throw new Error(unknownTopicMessage(String(topic)));
|
|
153
|
-
return [
|
|
153
|
+
return [
|
|
154
|
+
await deps.guide(topic === "system" ? await projectOf() : "", topic),
|
|
155
|
+
String(topic),
|
|
156
|
+
];
|
|
154
157
|
},
|
|
155
|
-
async read([
|
|
156
|
-
if (
|
|
158
|
+
async read([design, opts]) {
|
|
159
|
+
if (plain(opts).decisions === true) {
|
|
160
|
+
const value = await take(flows.decisions({ project: await projectOf() }));
|
|
161
|
+
return [value, `${value.total} decisions`];
|
|
162
|
+
}
|
|
163
|
+
if ((design === undefined || design === null) && plain(opts).tree === true) {
|
|
157
164
|
const value = await take(flows.tree({ project: await projectOf() }));
|
|
158
|
-
return [value, `${value.tree.length}
|
|
165
|
+
return [value, `${value.tree.length} designs`];
|
|
159
166
|
}
|
|
160
|
-
if (
|
|
167
|
+
if (design === undefined || design === null) {
|
|
161
168
|
const value = await take(flows.list({ project: await projectOf() }));
|
|
162
|
-
return [value, `${value.
|
|
169
|
+
return [value, `${value.designs.length} designs`];
|
|
163
170
|
}
|
|
164
171
|
const o = plain(opts);
|
|
165
|
-
const value = await take(flows.get(
|
|
166
|
-
return [value, String(value?.slug ??
|
|
172
|
+
const value = await take(flows.get(design, { project, body: o.body === true, history: o.history === true }));
|
|
173
|
+
return [value, String(value?.slug ?? design)];
|
|
167
174
|
},
|
|
168
175
|
async publish([v]) {
|
|
169
176
|
const value = await take(flows.publish({ ...(await mine(plain(v))), agent }, flowCtx));
|
|
170
177
|
return [value, writeSummary(value)];
|
|
171
178
|
},
|
|
172
|
-
async ask([
|
|
173
|
-
const value = await take(flows.ask(
|
|
174
|
-
return [value, `${value.
|
|
179
|
+
async ask([design, asks]) {
|
|
180
|
+
const value = await take(flows.ask(design, await mine({ asks }), flowCtx));
|
|
181
|
+
return [value, `${value.design} ${value.asks.length} ask(s)`];
|
|
175
182
|
},
|
|
176
183
|
async feedback() {
|
|
177
184
|
const value = await take(flows.feedback(await mine({}), flowCtx));
|
|
@@ -180,8 +187,27 @@ export function createRunFlow(deps) {
|
|
|
180
187
|
},
|
|
181
188
|
async say([v, message]) {
|
|
182
189
|
const r = plain(v);
|
|
183
|
-
await take(flows.say(r.
|
|
184
|
-
return [null, String(r.
|
|
190
|
+
await take(flows.say(r.design, { ...(await mine(r)), message }, flowCtx));
|
|
191
|
+
return [null, String(r.design ?? "?")];
|
|
192
|
+
},
|
|
193
|
+
async move([v]) {
|
|
194
|
+
const r = plain(v);
|
|
195
|
+
const value = await take(flows.move(r.design, await mine(r), flowCtx));
|
|
196
|
+
return [value, `${value.variants.length} moved`];
|
|
197
|
+
},
|
|
198
|
+
async system([v]) {
|
|
199
|
+
const given = plain(v ?? {});
|
|
200
|
+
const named = project ?? (typeof given.project === "string" ? given.project : undefined);
|
|
201
|
+
const writing = Object.keys(given).some((k) => !["session", "project", "agent"].includes(k));
|
|
202
|
+
// A write lands on a project the script names, never on whichever is first.
|
|
203
|
+
if (writing && !named)
|
|
204
|
+
throw new Error("system writes need a project: pass {project} to run, or run in a session that has one");
|
|
205
|
+
const r = await mine(given);
|
|
206
|
+
const value = await take(flows.system(named ?? (await projectOf()), r, flowCtx));
|
|
207
|
+
return [
|
|
208
|
+
value,
|
|
209
|
+
value.changed?.length ? `r${value.rev}: ${value.changed.join("; ")}` : `r${value.rev}`,
|
|
210
|
+
];
|
|
185
211
|
},
|
|
186
212
|
async edit([v]) {
|
|
187
213
|
const r = await mine(plain(v));
|
|
@@ -206,8 +232,12 @@ export function createRunFlow(deps) {
|
|
|
206
232
|
},
|
|
207
233
|
async export([v]) {
|
|
208
234
|
const r = plain(v);
|
|
209
|
-
|
|
210
|
-
|
|
235
|
+
if (r.design === undefined) {
|
|
236
|
+
const value = await take(flows.exportSystem(r.project ?? project ?? (await projectOf())));
|
|
237
|
+
return [value, `${value.project} system r${value.rev}`];
|
|
238
|
+
}
|
|
239
|
+
const value = await take(flows.exportDesign(r.design, { ...r, project }, flowCtx));
|
|
240
|
+
return [value, `${value.design} ${value.states.length} state(s)`];
|
|
211
241
|
},
|
|
212
242
|
};
|
|
213
243
|
const call = (name, argsJson) => {
|
package/dist/server/runApi.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export declare const RUN_API = "// The body of an async function, in plain JavaScript (no TypeScript syntax).\n// `await mockpit.*`, `return` a JSON value, print() adds an output line.\n// No network, timers, imports or process. Session, project and agent are fixed\n// for the run; pass the returned session to the next run.\ntype Ref = {
|
|
2
|
-
export declare const RUN_FUNCTIONS: readonly ["guide", "read", "publish", "ask", "feedback", "say", "edit", "export", "upload"];
|
|
1
|
+
export declare const RUN_API = "// The body of an async function, in plain JavaScript (no TypeScript syntax).\n// `await mockpit.*`, `return` a JSON value, print() adds an output line.\n// No network, timers, imports or process. Session, project and agent are fixed\n// for the run; pass the returned session to the next run.\ntype Ref = { design: string; state?: string; variant?: string };\ntype Knobs = Record<string, unknown>; // path \u2192 [default,min,max,step] | boolean | {type:\"select\",options} | \"#hex\"\ntype Surface =\n | { kind: \"html\"; html: string; kits?: string[] }\n | { kind: \"markdown\"; markdown: string }\n | { kind: \"diff\"; patch?: string; files?: { filename: string; before: string; after: string }[]; layout?: \"unified\" | \"split\" }\n | { kind: \"image\"; assetId: string; alt?: string; caption?: string }\n | { kind: \"terminal\"; text: string; cols?: number; title?: string }\n | { kind: \"mermaid\"; mermaid: string }\n | { kind: \"json\"; data: unknown; title?: string }\n | { kind: \"code\"; code: string; language?: string; lineStart?: number };\ntype Ask = {\n id?: string; text: string; scope?: \"design\" | \"state\" | \"part\"; state?: string; part?: string; multi?: boolean;\n options: { id?: string; label: string; variant?: string; set?: Knobs; palette?: string; recommended?: boolean }[];\n};\ntype Written = {\n post?: { state: string | null; variant: string; version: number }; planned?: true; url: string;\n parts?: { state: string | null; parts: { name: string }[] }[];\n partChanges?: { vanished: string[]; renamed: { from: string; to: string }[] };\n nudges?: string[]; suggestedAsk?: Ask; suggestedFillAsks?: Ask[]; // send with ask when nudged\n};\ntype Feedback = {\n design: string | null;\n reply: null | { asks: { ask: string; chosen: { id: string; label: string; other?: true }[]; comment?: string }[]; borrowed: Record<string, string>; tuned: Knobs; comments: { part: string | null; text: string }[]; verdict?: { kind: \"use\" | \"revise\"; state: string | null; variant: string; version?: number } };\n messages: { text: string; state: string | null; variant: string | null }[];\n inUse: { state: string | null; variant: string; version: number }[]; archived: { state: string | null; variant: string }[];\n system?: { rev: number; changes: string[] };\n};\ntype Pending = { design: string; archived?: true; viewerOpen: boolean; draft: null | { answered: number; of: number; comments: number; touchedAt: string } };\ndeclare const mockpit: {\n guide(topic?: \"system\" | \"knobs\" | \"asks\" | \"surfaces\" | \"html\" | \"feedback\" | \"http\" | \"scripts\"): Promise<string>;\n /** Read first: decisionList is what the user already settled; it stands unless they say otherwise.\n * No design: every design, the flows, plus pending. With one: its states, variants, asks, parts, knobs.\n * opts.decisions: only the whole list, when a read cut it. */\n read(design?: string, opts?: { body?: boolean; history?: boolean; decisions?: boolean }): Promise<unknown>;\n /** Creates or versions (design, state, variant). One of: html; surfaces, the full ordered list\n * ({id} alone keeps that surface, a missing id is removed); parts {\"name\"|\"name#key\": outer html};\n * fills {\"part#fill\": outer html}, replacing or adding one fill of a part.\n * None of them, with kind screen or component: plans it, for a later publish to draw. */\n publish(v: Ref & { title?: string; kind?: \"screen\" | \"component\" | \"idea\"; area?: string; source?: string; html?: string; poster?: string; surfaces?: (Surface | { id: string })[]; parts?: Record<string, string>; fills?: Record<string, string>; knobs?: Knobs; variantKnobs?: Knobs; from?: number; prompt?: string; description?: string; widths?: number[]; flow?: string; step?: number }): Promise<Written>;\n ask(design: string, asks: Ask[]): Promise<{ asks: { id: string; text: string }[]; url: string; nudges?: string[] }>;\n /** Never waits: what the user sent since you last heard, and what they are doing now. */\n feedback(): Promise<{ feedback: Feedback[]; pending: Pending[] }>;\n say(v: Ref, message: string): Promise<void>;\n /** to or toState moves variants there; archive hides them; restore brings them back. */\n move(v: Ref & { variants: string[]; to?: string; toState?: string; archive?: boolean; restore?: boolean }): Promise<{ variants: { state: string | null; variant: string; status: string }[]; skipped: { variant: string; why: string }[]; url: string }>;\n /** No new version; \"\" clears. { rename } or { areaOrder } without design edits the project.\n * notes: a short plain-text spec; not applied over the user's own edit (notes.applied says). */\n edit(v: { design?: string; slug?: string; title?: string; kind?: string; area?: string; source?: string; firstState?: string; notes?: string; rename?: string; areaOrder?: string[] }): Promise<{ url: string; notes?: { applied: boolean; text?: string } }>;\n /** The project's system: sheet, tokens, scales, palettes, project knobs. No argument reads it;\n * each key replaces its part (tokens, scales, palettes upsert by name). Applies to every design at once. */\n system(v?: { sheet?: string; classes?: { name: string; note: string }[]; fonts?: { family: string; href?: string }[]; tokens?: unknown[]; scales?: unknown[]; roles?: { name: string; note: string }[]; palettes?: unknown[]; pairs?: [string, string, number][]; as?: Record<string, string>; knobs?: Knobs; remove?: { tokens?: string[]; palettes?: string[]; scales?: string[] }; restore?: number }): Promise<{ rev: number; changed?: string[]; kept?: string[]; checks: string[]; url: string }>;\n export(v: Ref): Promise<{ states: { state: string | null; variant: string; version: number; html: string; allFills?: string }[]; reply: unknown }>;\n /** Without design: the project's system for code. css holds the default palette on :root and kept ones by [data-palette]. */\n export(v: {}): Promise<{ rev: number; sheet: string; css: string; tokens: unknown; knobs: Record<string, unknown>; additions: { knob: string; value: string; style: string }[]; components: { slug: string; purpose: string; source: string | null }[] }>;\n /** data: base64 bytes. Use id as an image surface's assetId. */\n upload(data: string, opts: { contentType: string; filename?: string; kind?: \"image\" | \"file\" }): Promise<{ id: string; url: string }>;\n};\ndeclare function print(...values: unknown[]): void;";
|
|
2
|
+
export declare const RUN_FUNCTIONS: readonly ["guide", "read", "publish", "ask", "feedback", "say", "move", "edit", "system", "export", "upload"];
|
|
3
3
|
export type RunFunction = (typeof RUN_FUNCTIONS)[number];
|
|
4
|
-
export declare const RUN_EXAMPLE = "const html = (tone) => `<section data-part=\"hero\" class=\"${tone}\"><h1>Writer</h1></section>`;\nawait mockpit.publish({
|
|
4
|
+
export declare const RUN_EXAMPLE = "const html = (tone) => `<section data-part=\"hero\" class=\"${tone}\"><h1>Writer</h1></section>`;\nawait mockpit.publish({ design: \"writer\", variant: \"calm\", html: html(\"calm\") });\nawait mockpit.publish({ design: \"writer\", variant: \"bold\", html: html(\"bold\") });\nconst { url } = await mockpit.ask(\"writer\", [{ id: \"tone\", text: \"Calm or bold?\",\n options: [{ label: \"Calm\", variant: \"calm\" }, { label: \"Bold\", variant: \"bold\" }] }]);\n// Tell the user where to look and end the turn; a later run reads mockpit.feedback().\nreturn url;";
|
|
5
5
|
export declare const RUN_DESCRIPTION: string;
|
|
6
6
|
export declare const RUN_INSTRUCTIONS: string;
|
package/dist/server/runApi.js
CHANGED
|
@@ -8,7 +8,7 @@ export const RUN_API = `// The body of an async function, in plain JavaScript (n
|
|
|
8
8
|
// \`await mockpit.*\`, \`return\` a JSON value, print() adds an output line.
|
|
9
9
|
// No network, timers, imports or process. Session, project and agent are fixed
|
|
10
10
|
// for the run; pass the returned session to the next run.
|
|
11
|
-
type Ref = {
|
|
11
|
+
type Ref = { design: string; state?: string; variant?: string };
|
|
12
12
|
type Knobs = Record<string, unknown>; // path → [default,min,max,step] | boolean | {type:"select",options} | "#hex"
|
|
13
13
|
type Surface =
|
|
14
14
|
| { kind: "html"; html: string; kits?: string[] }
|
|
@@ -20,38 +20,49 @@ type Surface =
|
|
|
20
20
|
| { kind: "json"; data: unknown; title?: string }
|
|
21
21
|
| { kind: "code"; code: string; language?: string; lineStart?: number };
|
|
22
22
|
type Ask = {
|
|
23
|
-
id?: string; text: string; scope?: "
|
|
24
|
-
options: { id?: string; label: string; variant?: string; set?: Knobs; recommended?: boolean }[];
|
|
23
|
+
id?: string; text: string; scope?: "design" | "state" | "part"; state?: string; part?: string; multi?: boolean;
|
|
24
|
+
options: { id?: string; label: string; variant?: string; set?: Knobs; palette?: string; recommended?: boolean }[];
|
|
25
25
|
};
|
|
26
26
|
type Written = {
|
|
27
|
-
post
|
|
28
|
-
parts
|
|
27
|
+
post?: { state: string | null; variant: string; version: number }; planned?: true; url: string;
|
|
28
|
+
parts?: { state: string | null; parts: { name: string }[] }[];
|
|
29
29
|
partChanges?: { vanished: string[]; renamed: { from: string; to: string }[] };
|
|
30
30
|
nudges?: string[]; suggestedAsk?: Ask; suggestedFillAsks?: Ask[]; // send with ask when nudged
|
|
31
31
|
};
|
|
32
32
|
type Feedback = {
|
|
33
|
-
|
|
34
|
-
reply: null | { asks: { ask: string; chosen: { id: string; label: string; other?: true }[];
|
|
33
|
+
design: string | null;
|
|
34
|
+
reply: null | { asks: { ask: string; chosen: { id: string; label: string; other?: true }[]; comment?: string }[]; borrowed: Record<string, string>; tuned: Knobs; comments: { part: string | null; text: string }[]; verdict?: { kind: "use" | "revise"; state: string | null; variant: string; version?: number } };
|
|
35
35
|
messages: { text: string; state: string | null; variant: string | null }[];
|
|
36
36
|
inUse: { state: string | null; variant: string; version: number }[]; archived: { state: string | null; variant: string }[];
|
|
37
|
-
|
|
37
|
+
system?: { rev: number; changes: string[] };
|
|
38
38
|
};
|
|
39
|
-
type Pending = {
|
|
39
|
+
type Pending = { design: string; archived?: true; viewerOpen: boolean; draft: null | { answered: number; of: number; comments: number; touchedAt: string } };
|
|
40
40
|
declare const mockpit: {
|
|
41
|
-
guide(topic?: "knobs" | "asks" | "surfaces" | "html" | "feedback" | "http" | "scripts"): Promise<string>;
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
guide(topic?: "system" | "knobs" | "asks" | "surfaces" | "html" | "feedback" | "http" | "scripts"): Promise<string>;
|
|
42
|
+
/** Read first: decisionList is what the user already settled; it stands unless they say otherwise.
|
|
43
|
+
* No design: every design, the flows, plus pending. With one: its states, variants, asks, parts, knobs.
|
|
44
|
+
* opts.decisions: only the whole list, when a read cut it. */
|
|
45
|
+
read(design?: string, opts?: { body?: boolean; history?: boolean; decisions?: boolean }): Promise<unknown>;
|
|
46
|
+
/** Creates or versions (design, state, variant). One of: html; surfaces, the full ordered list
|
|
45
47
|
* ({id} alone keeps that surface, a missing id is removed); parts {"name"|"name#key": outer html};
|
|
46
|
-
* fills {"part#fill": outer html}, replacing or adding one fill of a part.
|
|
47
|
-
|
|
48
|
-
|
|
48
|
+
* fills {"part#fill": outer html}, replacing or adding one fill of a part.
|
|
49
|
+
* None of them, with kind screen or component: plans it, for a later publish to draw. */
|
|
50
|
+
publish(v: Ref & { title?: string; kind?: "screen" | "component" | "idea"; area?: string; source?: string; html?: string; poster?: string; surfaces?: (Surface | { id: string })[]; parts?: Record<string, string>; fills?: Record<string, string>; knobs?: Knobs; variantKnobs?: Knobs; from?: number; prompt?: string; description?: string; widths?: number[]; flow?: string; step?: number }): Promise<Written>;
|
|
51
|
+
ask(design: string, asks: Ask[]): Promise<{ asks: { id: string; text: string }[]; url: string; nudges?: string[] }>;
|
|
49
52
|
/** Never waits: what the user sent since you last heard, and what they are doing now. */
|
|
50
53
|
feedback(): Promise<{ feedback: Feedback[]; pending: Pending[] }>;
|
|
51
54
|
say(v: Ref, message: string): Promise<void>;
|
|
52
|
-
/**
|
|
53
|
-
|
|
55
|
+
/** to or toState moves variants there; archive hides them; restore brings them back. */
|
|
56
|
+
move(v: Ref & { variants: string[]; to?: string; toState?: string; archive?: boolean; restore?: boolean }): Promise<{ variants: { state: string | null; variant: string; status: string }[]; skipped: { variant: string; why: string }[]; url: string }>;
|
|
57
|
+
/** No new version; "" clears. { rename } or { areaOrder } without design edits the project.
|
|
58
|
+
* notes: a short plain-text spec; not applied over the user's own edit (notes.applied says). */
|
|
59
|
+
edit(v: { design?: string; slug?: string; title?: string; kind?: string; area?: string; source?: string; firstState?: string; notes?: string; rename?: string; areaOrder?: string[] }): Promise<{ url: string; notes?: { applied: boolean; text?: string } }>;
|
|
60
|
+
/** The project's system: sheet, tokens, scales, palettes, project knobs. No argument reads it;
|
|
61
|
+
* each key replaces its part (tokens, scales, palettes upsert by name). Applies to every design at once. */
|
|
62
|
+
system(v?: { sheet?: string; classes?: { name: string; note: string }[]; fonts?: { family: string; href?: string }[]; tokens?: unknown[]; scales?: unknown[]; roles?: { name: string; note: string }[]; palettes?: unknown[]; pairs?: [string, string, number][]; as?: Record<string, string>; knobs?: Knobs; remove?: { tokens?: string[]; palettes?: string[]; scales?: string[] }; restore?: number }): Promise<{ rev: number; changed?: string[]; kept?: string[]; checks: string[]; url: string }>;
|
|
54
63
|
export(v: Ref): Promise<{ states: { state: string | null; variant: string; version: number; html: string; allFills?: string }[]; reply: unknown }>;
|
|
64
|
+
/** Without design: the project's system for code. css holds the default palette on :root and kept ones by [data-palette]. */
|
|
65
|
+
export(v: {}): Promise<{ rev: number; sheet: string; css: string; tokens: unknown; knobs: Record<string, unknown>; additions: { knob: string; value: string; style: string }[]; components: { slug: string; purpose: string; source: string | null }[] }>;
|
|
55
66
|
/** data: base64 bytes. Use id as an image surface's assetId. */
|
|
56
67
|
upload(data: string, opts: { contentType: string; filename?: string; kind?: "image" | "file" }): Promise<{ id: string; url: string }>;
|
|
57
68
|
};
|
|
@@ -64,18 +75,20 @@ export const RUN_FUNCTIONS = [
|
|
|
64
75
|
"ask",
|
|
65
76
|
"feedback",
|
|
66
77
|
"say",
|
|
78
|
+
"move",
|
|
67
79
|
"edit",
|
|
80
|
+
"system",
|
|
68
81
|
"export",
|
|
69
82
|
"upload",
|
|
70
83
|
];
|
|
71
84
|
export const RUN_EXAMPLE = `const html = (tone) => \`<section data-part="hero" class="\${tone}"><h1>Writer</h1></section>\`;
|
|
72
|
-
await mockpit.publish({
|
|
73
|
-
await mockpit.publish({
|
|
85
|
+
await mockpit.publish({ design: "writer", variant: "calm", html: html("calm") });
|
|
86
|
+
await mockpit.publish({ design: "writer", variant: "bold", html: html("bold") });
|
|
74
87
|
const { url } = await mockpit.ask("writer", [{ id: "tone", text: "Calm or bold?",
|
|
75
88
|
options: [{ label: "Calm", variant: "calm" }, { label: "Bold", variant: "bold" }] }]);
|
|
76
89
|
// Tell the user where to look and end the turn; a later run reads mockpit.feedback().
|
|
77
90
|
return url;`;
|
|
78
|
-
export const RUN_DESCRIPTION = "Run a script against mockpit, which shows design work to the user (project >
|
|
91
|
+
export const RUN_DESCRIPTION = "Run a script against mockpit, which shows design work to the user (project > design > state > " +
|
|
79
92
|
"variant > version). Publish variants and ask in one call; nothing waits for the user. Returns " +
|
|
80
93
|
"value, prints, calls (every host call in order: which writes landed), error {kind, message, " +
|
|
81
94
|
"line} and feedback (every batch received, even if the script failed). Read mockpit.guide() " +
|
|
@@ -1,13 +1,26 @@
|
|
|
1
|
-
import { type Ask, type Asset, type Comment, type CommentQuery, type CommitReplyInput, type CreateAssetInput, type CreateCommentInput, type
|
|
1
|
+
import { type Ask, type JumpRows, type DesignKind, type Asset, type Comment, type CommentQuery, type CommitReplyInput, type CreateAssetInput, type CreateCommentInput, type CreateDesignInput, type CreatePostInput, type CreateSessionInput, type Draft, type Knobs, type Design, type DesignNotes, type AnswerAddition, type AnswerSet, type AnswerStanding, type StateOutline, type Post, type CopyRef, type LiveCopy, type PostHead, type PostQuery, type PostStatus, type PostVersion, type Reply, type Session, type Embed, type Flow, type FlowStep, type ForkRef, type SqlStorage, type Store, type Surface, type UpdateDesignInput, type UpdatePostInput, type AmendPostInput, type DecisionVariant } from "./types.ts";
|
|
2
|
+
import { type System } from "./system.ts";
|
|
3
|
+
import type { Mode } from "./themes.ts";
|
|
2
4
|
export declare class SqlStore implements Store {
|
|
3
5
|
private sql;
|
|
4
6
|
private assetRefCache;
|
|
5
|
-
|
|
7
|
+
private postCache;
|
|
8
|
+
private postCacheBytes;
|
|
9
|
+
private postCacheLimit;
|
|
10
|
+
private raw;
|
|
11
|
+
private holdPostDrop;
|
|
12
|
+
constructor(sql: SqlStorage, opts?: {
|
|
13
|
+
postCacheBytes?: number;
|
|
14
|
+
});
|
|
6
15
|
private atomic;
|
|
7
16
|
private tables;
|
|
8
17
|
private columns;
|
|
9
18
|
private addMissing;
|
|
19
|
+
private migrateToDesignWords;
|
|
20
|
+
private migrateAskScopeWord;
|
|
21
|
+
private renameMocksToDesigns;
|
|
10
22
|
private migrate;
|
|
23
|
+
private migrateSituations;
|
|
11
24
|
private migrateToContractTerms;
|
|
12
25
|
private createIndexes;
|
|
13
26
|
private migrateLegacy;
|
|
@@ -16,7 +29,7 @@ export declare class SqlStore implements Store {
|
|
|
16
29
|
private migrateSurfaceIds;
|
|
17
30
|
private migrateToItems;
|
|
18
31
|
private migrateToVersions;
|
|
19
|
-
private
|
|
32
|
+
private migrateToDesigns;
|
|
20
33
|
private migrateToSketches;
|
|
21
34
|
private settingSync;
|
|
22
35
|
private insertVersion;
|
|
@@ -24,7 +37,7 @@ export declare class SqlStore implements Store {
|
|
|
24
37
|
private historiesFor;
|
|
25
38
|
private rowsToPosts;
|
|
26
39
|
private rowToSession;
|
|
27
|
-
private
|
|
40
|
+
private rowToDesign;
|
|
28
41
|
private rowToPost;
|
|
29
42
|
private rowToAsset;
|
|
30
43
|
private rowToComment;
|
|
@@ -41,165 +54,197 @@ export declare class SqlStore implements Store {
|
|
|
41
54
|
getSetting(key: string): Promise<string | null>;
|
|
42
55
|
setSetting(key: string, value: string): Promise<void>;
|
|
43
56
|
listProjects(): Promise<import("./types.ts").ProjectSummary[]>;
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
57
|
+
listJumpRows(): Promise<JumpRows>;
|
|
58
|
+
listDesigns(project?: string): Promise<Design[]>;
|
|
59
|
+
getDesign(id: string): Promise<Design | null>;
|
|
60
|
+
findDesign(project: string, slug: string): Promise<Design | null>;
|
|
61
|
+
createDesign(input: CreateDesignInput): Promise<Design>;
|
|
62
|
+
updateDesign(id: string, patch: UpdateDesignInput): Promise<Design | null>;
|
|
63
|
+
removeDesign(id: string): Promise<boolean>;
|
|
64
|
+
nameFirstState(id: string, state: string): Promise<Design | null>;
|
|
65
|
+
renameDesign(id: string, slug: string): Promise<Design | null>;
|
|
51
66
|
renameProject(from: string, to: string): Promise<boolean>;
|
|
67
|
+
getSystem(project: string): Promise<System | null>;
|
|
68
|
+
putSystem(system: System, meta: {
|
|
69
|
+
sessionId: string | null;
|
|
70
|
+
summary: string;
|
|
71
|
+
}): Promise<System>;
|
|
72
|
+
commitSystemDecision(input: {
|
|
73
|
+
system: System;
|
|
74
|
+
summary: string;
|
|
75
|
+
tell: {
|
|
76
|
+
sessionId: string;
|
|
77
|
+
payload: Reply;
|
|
78
|
+
} | null;
|
|
79
|
+
}): Promise<Comment | null>;
|
|
80
|
+
private writeSystem;
|
|
81
|
+
listSystemRevisions(project: string): Promise<{
|
|
82
|
+
rev: number;
|
|
83
|
+
at: string;
|
|
84
|
+
sessionId: string | null;
|
|
85
|
+
summary: string;
|
|
86
|
+
}[]>;
|
|
87
|
+
getSystemRevision(project: string, rev: number): Promise<System | null>;
|
|
88
|
+
private migrateSystems;
|
|
52
89
|
private flowsOf;
|
|
53
90
|
private writeFlow;
|
|
54
91
|
listFlows(project: string): Promise<Flow[]>;
|
|
55
92
|
placeFlowStep(project: string, name: string, screen: FlowStep, step: number): Promise<Flow | null>;
|
|
56
|
-
putDraft(
|
|
57
|
-
draft: Draft | null;
|
|
93
|
+
putDraft(designId: string, draft: Draft | null): Promise<{
|
|
58
94
|
id: string;
|
|
59
95
|
project: string;
|
|
60
96
|
slug: string;
|
|
61
97
|
title: string;
|
|
62
|
-
kind:
|
|
98
|
+
kind: DesignKind;
|
|
63
99
|
area: string | null;
|
|
64
100
|
source: string | null;
|
|
65
101
|
states: string[];
|
|
66
|
-
situations: Record<string, string[]>;
|
|
67
102
|
asks: Ask[];
|
|
68
103
|
knobs: Knobs;
|
|
69
104
|
widths: number[];
|
|
70
105
|
sessionId: string | null;
|
|
71
|
-
|
|
106
|
+
shortlist: boolean;
|
|
107
|
+
archivedAt: string | null;
|
|
108
|
+
archiveReason: string | null;
|
|
109
|
+
notes: DesignNotes | null;
|
|
110
|
+
stateOutlines: Record<string, StateOutline>;
|
|
111
|
+
answerAdditions: AnswerAddition[];
|
|
112
|
+
standings: Record<string, AnswerStanding>;
|
|
113
|
+
sets: AnswerSet[];
|
|
72
114
|
createdAt: string;
|
|
73
115
|
updatedAt: string;
|
|
116
|
+
draft: Draft | null;
|
|
74
117
|
} | null>;
|
|
75
|
-
private
|
|
118
|
+
private touchDesign;
|
|
76
119
|
listPosts(query?: PostQuery): Promise<Post[]>;
|
|
120
|
+
listPostHeads(project?: string): Promise<PostHead[]>;
|
|
121
|
+
listCopies(project: string): Promise<LiveCopy[]>;
|
|
122
|
+
private postsOfDesign;
|
|
123
|
+
private trimPostCache;
|
|
124
|
+
private writingPosts;
|
|
125
|
+
private cachedPost;
|
|
126
|
+
private recache;
|
|
77
127
|
countPostsBySession(): Promise<Map<string, number>>;
|
|
78
128
|
getPost(id: string): Promise<Post | null>;
|
|
79
|
-
findPost(
|
|
129
|
+
findPost(designId: string, state: string | null, variant: string): Promise<Post | null>;
|
|
80
130
|
createPost(input: CreatePostInput): Promise<Post | null>;
|
|
81
131
|
updatePost(id: string, patch: UpdatePostInput): Promise<{
|
|
82
|
-
author?: string | undefined;
|
|
83
|
-
embeds: Embed[];
|
|
84
|
-
state: string | null;
|
|
85
|
-
version: number;
|
|
86
|
-
updatedAt: string;
|
|
87
|
-
history: PostVersion[];
|
|
88
|
-
from: number;
|
|
89
|
-
prompt: string;
|
|
90
|
-
note?: string | undefined;
|
|
91
|
-
knobs?: Knobs | undefined;
|
|
92
|
-
title: string;
|
|
93
|
-
surfaces: Surface[];
|
|
94
132
|
id: string;
|
|
95
133
|
sessionId: string;
|
|
96
|
-
|
|
134
|
+
design: string;
|
|
97
135
|
variant: string;
|
|
98
136
|
status: PostStatus;
|
|
99
137
|
createdAt: string;
|
|
100
138
|
forkedFrom?: ForkRef;
|
|
101
|
-
|
|
139
|
+
copiedFrom?: CopyRef;
|
|
102
140
|
acceptedVersion?: number;
|
|
103
141
|
hiddenVersions?: number[];
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
mock: string;
|
|
111
|
-
state: string | null;
|
|
112
|
-
variant: string;
|
|
142
|
+
archiveReason?: string;
|
|
143
|
+
archivedAt?: string;
|
|
144
|
+
stayedVersion?: number;
|
|
145
|
+
rewrites?: number;
|
|
146
|
+
contract: number;
|
|
147
|
+
system?: number | undefined;
|
|
113
148
|
title: string;
|
|
114
149
|
surfaces: Surface[];
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
version: number;
|
|
118
|
-
history: PostVersion[];
|
|
119
|
-
knobs?: Knobs;
|
|
120
|
-
note?: string;
|
|
150
|
+
knobs?: Knobs | undefined;
|
|
151
|
+
description?: string | undefined;
|
|
121
152
|
embeds: Embed[];
|
|
122
|
-
forkedFrom?: ForkRef;
|
|
123
|
-
starred?: true;
|
|
124
|
-
hiddenVersions?: number[];
|
|
125
|
-
from?: number;
|
|
126
|
-
prompt?: string;
|
|
127
|
-
author?: string;
|
|
128
|
-
} | {
|
|
129
|
-
status: PostStatus;
|
|
130
|
-
acceptedVersion: number;
|
|
131
|
-
id: string;
|
|
132
|
-
sessionId: string;
|
|
133
|
-
mock: string;
|
|
134
153
|
state: string | null;
|
|
135
|
-
variant: string;
|
|
136
|
-
title: string;
|
|
137
|
-
surfaces: Surface[];
|
|
138
|
-
createdAt: string;
|
|
139
|
-
updatedAt: string;
|
|
140
154
|
version: number;
|
|
155
|
+
updatedAt: string;
|
|
141
156
|
history: PostVersion[];
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
starred?: true;
|
|
147
|
-
hiddenVersions?: number[];
|
|
148
|
-
from?: number;
|
|
149
|
-
prompt?: string;
|
|
150
|
-
author?: string;
|
|
157
|
+
from: number;
|
|
158
|
+
prompt: string;
|
|
159
|
+
author?: string | undefined;
|
|
160
|
+
publishedBy?: string | undefined;
|
|
151
161
|
} | null>;
|
|
152
|
-
|
|
162
|
+
amendPost(id: string, version: number, patch: AmendPostInput): Promise<{
|
|
153
163
|
id: string;
|
|
154
164
|
sessionId: string;
|
|
155
|
-
|
|
165
|
+
design: string;
|
|
156
166
|
state: string | null;
|
|
157
167
|
variant: string;
|
|
158
168
|
status: PostStatus;
|
|
159
|
-
title: string;
|
|
160
|
-
surfaces: Surface[];
|
|
161
169
|
createdAt: string;
|
|
162
170
|
updatedAt: string;
|
|
163
171
|
version: number;
|
|
164
172
|
history: PostVersion[];
|
|
165
|
-
knobs?: Knobs;
|
|
166
|
-
note?: string;
|
|
167
|
-
embeds: Embed[];
|
|
168
173
|
forkedFrom?: ForkRef;
|
|
174
|
+
copiedFrom?: CopyRef;
|
|
169
175
|
acceptedVersion?: number;
|
|
170
176
|
hiddenVersions?: number[];
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
id: string;
|
|
177
|
-
sessionId: string;
|
|
178
|
-
mock: string;
|
|
179
|
-
state: string | null;
|
|
180
|
-
variant: string;
|
|
181
|
-
status: PostStatus;
|
|
177
|
+
archiveReason?: string;
|
|
178
|
+
archivedAt?: string;
|
|
179
|
+
stayedVersion?: number;
|
|
180
|
+
publishedBy?: string;
|
|
181
|
+
system?: number;
|
|
182
182
|
title: string;
|
|
183
183
|
surfaces: Surface[];
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
version: number;
|
|
187
|
-
history: PostVersion[];
|
|
188
|
-
knobs?: Knobs;
|
|
189
|
-
note?: string;
|
|
184
|
+
knobs?: Knobs | undefined;
|
|
185
|
+
description?: string | undefined;
|
|
190
186
|
embeds: Embed[];
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
187
|
+
from?: number | undefined;
|
|
188
|
+
prompt?: string | undefined;
|
|
189
|
+
author?: string | undefined;
|
|
190
|
+
amendedAt: string;
|
|
191
|
+
rewrites: number;
|
|
192
|
+
contract: number;
|
|
193
|
+
} | null>;
|
|
194
|
+
setPosterOnce(id: string, version: number, poster: string, mode?: Mode, system?: number): Promise<boolean>;
|
|
195
|
+
withdrawVersion(id: string, version: number, embeds: Embed[]): Promise<{
|
|
196
|
+
post: null;
|
|
197
|
+
} | {
|
|
198
|
+
post: {
|
|
199
|
+
id: string;
|
|
200
|
+
sessionId: string;
|
|
201
|
+
design: string;
|
|
202
|
+
state: string | null;
|
|
203
|
+
variant: string;
|
|
204
|
+
status: PostStatus;
|
|
205
|
+
createdAt: string;
|
|
206
|
+
knobs?: Knobs;
|
|
207
|
+
description?: string;
|
|
208
|
+
forkedFrom?: ForkRef;
|
|
209
|
+
copiedFrom?: CopyRef;
|
|
210
|
+
acceptedVersion?: number;
|
|
211
|
+
archiveReason?: string;
|
|
212
|
+
archivedAt?: string;
|
|
213
|
+
stayedVersion?: number;
|
|
214
|
+
title: string;
|
|
215
|
+
surfaces: Surface[];
|
|
216
|
+
embeds: Embed[];
|
|
217
|
+
updatedAt: string;
|
|
218
|
+
version: number;
|
|
219
|
+
history: PostVersion[];
|
|
220
|
+
from?: number | undefined;
|
|
221
|
+
prompt?: string | undefined;
|
|
222
|
+
author?: string | undefined;
|
|
223
|
+
publishedBy?: string | undefined;
|
|
224
|
+
amendedAt?: string | undefined;
|
|
225
|
+
hiddenVersions?: number[] | undefined;
|
|
226
|
+
contract?: number | undefined;
|
|
227
|
+
system?: number | undefined;
|
|
228
|
+
rewrites: number;
|
|
229
|
+
};
|
|
197
230
|
} | null>;
|
|
231
|
+
removePost(id: string): Promise<boolean>;
|
|
232
|
+
setPostStatus(id: string, status: PostStatus, acceptedVersion?: number): Promise<Post | null>;
|
|
233
|
+
setPostArchived(id: string, archivedAt: string, reason: string | null): Promise<Post | null>;
|
|
234
|
+
setForkedFrom(id: string, from: ForkRef | null): Promise<Post | null>;
|
|
235
|
+
bumpRewrites(designId: string): Promise<void>;
|
|
198
236
|
setVersionHidden(id: string, version: number, hidden: boolean): Promise<Post | null>;
|
|
237
|
+
deleteOldVersions(id: string, versions: number[]): Promise<Post | null>;
|
|
238
|
+
setPostReason(id: string, reason: string | null): Promise<Post | null>;
|
|
239
|
+
setPostStayed(id: string, version: number): Promise<Post | null>;
|
|
199
240
|
listComments(query: CommentQuery): Promise<Comment[]>;
|
|
200
241
|
private insertComment;
|
|
201
242
|
createComment(input: CreateCommentInput): Promise<Comment | null>;
|
|
202
243
|
removeComment(id: string): Promise<Comment | null>;
|
|
244
|
+
listDecisionSources(project: string): Promise<{
|
|
245
|
+
variants: DecisionVariant[];
|
|
246
|
+
decidedAt: Record<string, string>;
|
|
247
|
+
}>;
|
|
203
248
|
commitReply(input: CommitReplyInput): Promise<Comment | null>;
|
|
204
249
|
private referencedAssetIds;
|
|
205
250
|
private addAssetRefs;
|