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.
Files changed (54) hide show
  1. package/README.md +11 -23
  2. package/bin/initDesign.js +11 -16
  3. package/bin/mockpit.js +242 -52
  4. package/bin/poster.js +64 -7
  5. package/dist/mcp/server.js +48 -6
  6. package/dist/server/apiViews.d.ts +562 -557
  7. package/dist/server/apiViews.js +18 -9
  8. package/dist/server/app.js +723 -206
  9. package/dist/server/cdnInline.js +6 -4
  10. package/dist/server/codeWorker.js +2 -2
  11. package/dist/server/contrast.d.ts +4 -0
  12. package/dist/server/contrast.js +157 -0
  13. package/dist/server/decisionList.d.ts +4 -1
  14. package/dist/server/decisionList.js +43 -5
  15. package/dist/server/designGuide.d.ts +13 -6
  16. package/dist/server/designGuide.js +206 -41
  17. package/dist/server/events.d.ts +6 -0
  18. package/dist/server/feedbackBatch.d.ts +4 -0
  19. package/dist/server/feedbackBatch.js +19 -1
  20. package/dist/server/guidance.d.ts +1 -1
  21. package/dist/server/guidance.js +2 -2
  22. package/dist/server/kits.d.ts +2 -2
  23. package/dist/server/kits.js +54 -1
  24. package/dist/server/mcpHttp.d.ts +2 -0
  25. package/dist/server/mcpHttp.js +13 -1
  26. package/dist/server/mcpSpec.d.ts +27 -27
  27. package/dist/server/mcpSpec.js +78 -10
  28. package/dist/server/run.js +22 -1
  29. package/dist/server/runApi.d.ts +2 -2
  30. package/dist/server/runApi.js +9 -2
  31. package/dist/server/sqlStore.d.ts +68 -39
  32. package/dist/server/sqlStore.js +163 -26
  33. package/dist/server/surfacePage.d.ts +4 -2
  34. package/dist/server/surfacePage.js +80 -32
  35. package/dist/server/system.d.ts +234 -0
  36. package/dist/server/system.js +1508 -0
  37. package/dist/server/systemChecks.d.ts +15 -0
  38. package/dist/server/systemChecks.js +224 -0
  39. package/dist/server/systemSpecimen.d.ts +2 -0
  40. package/dist/server/systemSpecimen.js +49 -0
  41. package/dist/server/themes.d.ts +9 -7
  42. package/dist/server/themes.js +43 -90
  43. package/dist/server/types.d.ts +43 -24
  44. package/dist/server/types.js +3 -1
  45. package/guide/AGENT_SETUP.md +3 -1
  46. package/guide/packs/foundations.md +35 -0
  47. package/guide/topics/asks.md +2 -1
  48. package/guide/topics/feedback.md +5 -3
  49. package/guide/topics/html.md +2 -2
  50. package/guide/topics/http.md +3 -1
  51. package/guide/topics/system.md +157 -0
  52. package/package.json +12 -12
  53. package/skills/mockpit/SKILL.md +7 -4
  54. package/viewer/dist/index.html +9 -8
@@ -8,14 +8,14 @@ export declare const MCP_INSTRUCTIONS: string;
8
8
  export declare const mcpSurfaceSchema: z.ZodObject<{
9
9
  id: z.ZodOptional<z.ZodString>;
10
10
  kind: z.ZodOptional<z.ZodEnum<{
11
- html: "html";
11
+ code: "code";
12
12
  diff: "diff";
13
+ html: "html";
13
14
  image: "image";
15
+ json: "json";
14
16
  markdown: "markdown";
15
- terminal: "terminal";
16
17
  mermaid: "mermaid";
17
- json: "json";
18
- code: "code";
18
+ terminal: "terminal";
19
19
  }>>;
20
20
  html: z.ZodOptional<z.ZodString>;
21
21
  kits: z.ZodOptional<z.ZodArray<z.ZodString>>;
@@ -30,8 +30,8 @@ export declare const mcpSurfaceSchema: z.ZodObject<{
30
30
  language: z.ZodOptional<z.ZodString>;
31
31
  }, z.core.$strip>>>;
32
32
  layout: z.ZodOptional<z.ZodEnum<{
33
- unified: "unified";
34
33
  split: "split";
34
+ unified: "unified";
35
35
  }>>;
36
36
  assetId: z.ZodOptional<z.ZodString>;
37
37
  alt: z.ZodOptional<z.ZodString>;
@@ -54,7 +54,7 @@ type Param = {
54
54
  d?: string;
55
55
  req?: boolean;
56
56
  } | {
57
- t: "surfaces" | "asks" | "object" | "integers" | "strings";
57
+ t: "surfaces" | "asks" | "object" | "objects" | "named" | "pairs" | "json" | "integers" | "strings";
58
58
  d?: string;
59
59
  req?: boolean;
60
60
  };
@@ -72,115 +72,115 @@ export declare const HTTP_MCP_TOOLS: ({
72
72
  _meta: {
73
73
  "anthropic/alwaysLoad": boolean;
74
74
  };
75
- outputSchema?: Json | undefined;
76
75
  name: string;
77
76
  description: string;
78
77
  inputSchema: Json;
78
+ outputSchema?: Json | undefined;
79
79
  } | {
80
80
  _meta?: undefined;
81
- outputSchema?: Json | undefined;
82
81
  name: string;
83
82
  description: string;
84
83
  inputSchema: Json;
84
+ outputSchema?: Json | undefined;
85
85
  })[];
86
86
  export declare const STDIO_MCP_CATALOG: ({
87
87
  _meta: {
88
88
  "anthropic/alwaysLoad": boolean;
89
89
  };
90
- outputSchema?: Json | undefined;
91
90
  name: string;
92
91
  description: string;
93
92
  inputSchema: Json;
93
+ outputSchema?: Json | undefined;
94
94
  } | {
95
95
  _meta?: undefined;
96
- outputSchema?: Json | undefined;
97
96
  name: string;
98
97
  description: string;
99
98
  inputSchema: Json;
99
+ outputSchema?: Json | undefined;
100
100
  })[];
101
101
  export declare const HTTP_RUN_TOOLS: ({
102
102
  _meta: {
103
103
  "anthropic/alwaysLoad": boolean;
104
104
  };
105
- outputSchema?: Json | undefined;
106
105
  name: string;
107
106
  description: string;
108
107
  inputSchema: Json;
108
+ outputSchema?: Json | undefined;
109
109
  } | {
110
110
  _meta?: undefined;
111
- outputSchema?: Json | undefined;
112
111
  name: string;
113
112
  description: string;
114
113
  inputSchema: Json;
114
+ outputSchema?: Json | undefined;
115
115
  })[];
116
116
  export declare const STDIO_RUN_CATALOG: ({
117
117
  _meta: {
118
118
  "anthropic/alwaysLoad": boolean;
119
119
  };
120
- outputSchema?: Json | undefined;
121
120
  name: string;
122
121
  description: string;
123
122
  inputSchema: Json;
123
+ outputSchema?: Json | undefined;
124
124
  } | {
125
125
  _meta?: undefined;
126
- outputSchema?: Json | undefined;
127
126
  name: string;
128
127
  description: string;
129
128
  inputSchema: Json;
129
+ outputSchema?: Json | undefined;
130
130
  })[];
131
131
  export declare const STDIO_MCP_TOOLS: ({
132
132
  _meta: {
133
133
  "anthropic/alwaysLoad": boolean;
134
134
  };
135
- outputSchema?: z.ZodObject<{
136
- [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
137
- }, z.core.$loose> | undefined;
138
135
  name: string;
139
136
  description: string;
140
137
  inputSchema: Readonly<{
141
138
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
142
139
  }>;
143
- } | {
144
- _meta?: undefined;
145
140
  outputSchema?: z.ZodObject<{
146
141
  [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
147
142
  }, z.core.$loose> | undefined;
143
+ } | {
144
+ _meta?: undefined;
148
145
  name: string;
149
146
  description: string;
150
147
  inputSchema: Readonly<{
151
148
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
152
149
  }>;
150
+ outputSchema?: z.ZodObject<{
151
+ [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
152
+ }, z.core.$loose> | undefined;
153
153
  })[];
154
154
  export declare const STDIO_RUN_TOOLS: ({
155
155
  _meta: {
156
156
  "anthropic/alwaysLoad": boolean;
157
157
  };
158
- outputSchema?: z.ZodObject<{
159
- [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
160
- }, z.core.$loose> | undefined;
161
158
  name: string;
162
159
  description: string;
163
160
  inputSchema: Readonly<{
164
161
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
165
162
  }>;
166
- } | {
167
- _meta?: undefined;
168
163
  outputSchema?: z.ZodObject<{
169
164
  [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
170
165
  }, z.core.$loose> | undefined;
166
+ } | {
167
+ _meta?: undefined;
171
168
  name: string;
172
169
  description: string;
173
170
  inputSchema: Readonly<{
174
171
  [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
175
172
  }>;
173
+ outputSchema?: z.ZodObject<{
174
+ [x: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
175
+ }, z.core.$loose> | undefined;
176
176
  })[];
177
177
  export declare const MCP_TOOL_NAMES: string[];
178
178
  export declare function toolResult(name: string, value: unknown): {
179
- structuredContent?: Record<string, unknown> | undefined;
180
179
  content: {
181
180
  type: "text";
182
181
  text: string;
183
182
  }[];
183
+ structuredContent?: Record<string, unknown> | undefined;
184
184
  };
185
185
  export declare const MAX_RESULT_IMAGES = 8;
186
186
  export declare function withFeedbackImages<T extends {
@@ -190,11 +190,11 @@ export declare function withFeedbackImages<T extends {
190
190
  mimeType: string;
191
191
  } | null>): Promise<T>;
192
192
  export declare function runToolResult(envelope: unknown): {
193
- isError?: boolean | undefined;
194
- structuredContent?: Record<string, unknown> | undefined;
195
193
  content: {
196
194
  type: "text";
197
195
  text: string;
198
196
  }[];
197
+ structuredContent?: Record<string, unknown> | undefined;
198
+ isError?: boolean | undefined;
199
199
  };
200
200
  export {};
@@ -103,6 +103,10 @@ const askSchema = z.object({
103
103
  set: z.record(z.string(), z.unknown()).optional().describe("Or to knob values {path: value}"),
104
104
  style: z.string().optional().describe("With a set of a new value: its CSS"),
105
105
  fill: z.string().optional().describe("With a set of {part: new fill}: its html"),
106
+ palette: z
107
+ .string()
108
+ .optional()
109
+ .describe("Or a palette id of the project's system; the answer makes it the default"),
106
110
  html: z.string().optional().describe("Or a whole page"),
107
111
  recommended: z.boolean().optional().describe("The one you would pick; one per ask"),
108
112
  })),
@@ -122,6 +126,23 @@ function zodParam(p) {
122
126
  case "object":
123
127
  s = z.record(z.string(), z.unknown());
124
128
  break;
129
+ case "objects":
130
+ s = z.array(z.record(z.string(), z.unknown()));
131
+ break;
132
+ // A list of objects where a bare name stands for {name}.
133
+ case "named":
134
+ s = z.array(z.union([z.string(), z.record(z.string(), z.unknown())]));
135
+ break;
136
+ // [foreground, background, minimum?]
137
+ case "pairs":
138
+ s = z.array(z
139
+ .array(z.union([z.string(), z.number()]))
140
+ .min(2)
141
+ .max(3));
142
+ break;
143
+ case "json":
144
+ s = z.unknown();
145
+ break;
125
146
  case "integer":
126
147
  s = z.number().int();
127
148
  break;
@@ -252,8 +273,8 @@ export const MCP_TOOL_DEFS = [
252
273
  },
253
274
  {
254
275
  name: "export",
255
- description: "The html in use (else current) per state, version history, screenshot URL, knobs, the settled values and the last reply.",
256
- params: VARIANT_REF,
276
+ description: "The html in use (else current) per state, version history, screenshot URL, knobs, the settled values and the last reply. Without design: the project's system for code (sheet, tokens as CSS and JSON, settled project knobs, components' sources).",
277
+ params: { ...VARIANT_REF, design: { t: "string", d: field.design } },
257
278
  },
258
279
  {
259
280
  name: "edit",
@@ -290,10 +311,34 @@ export const MCP_TOOL_DEFS = [
290
311
  httpOnly: ["session"],
291
312
  stdioExtra: { path: { t: "string", d: "Local file path; use instead of data" } },
292
313
  },
314
+ {
315
+ name: "system",
316
+ description: "Read or change the project's system (sheet, tokens, scales, palettes, project knobs), which every render wears at once. No arguments reads it; each argument replaces its part, tokens, scales and palettes upsert. Shapes: topic system.",
317
+ params: {
318
+ project: P.project,
319
+ sheet: { t: "string", d: "CSS; no @import" },
320
+ classes: { t: "named", d: "[{name, note}] or names" },
321
+ fonts: { t: "objects", d: "[{family, href?}]" },
322
+ tokens: { t: "objects", d: "[{name, type, value, note?}]" },
323
+ scales: {
324
+ t: "objects",
325
+ d: "[{id, family: type|space, prefix, steps, zero, base, ratio, fluid?}]",
326
+ },
327
+ roles: { t: "named", d: "[{name, note}] or names" },
328
+ palettes: { t: "objects", d: "[{id, label, note, light, dark}]" },
329
+ pairs: { t: "pairs", d: "[[fg, bg, min?]]" },
330
+ as: { t: "object" },
331
+ knobs: { t: "object", d: "Project knobs" },
332
+ remove: { t: "object", d: "{tokens?, palettes?, scales?}" },
333
+ restore: { t: "integer", d: "A revision, alone" },
334
+ session: P.session,
335
+ },
336
+ httpOnly: ["session"],
337
+ },
293
338
  {
294
339
  name: "guide",
295
340
  description: "Fetch the brief: the loop, parts, asks and knobs, feedback, the html contract, and this " +
296
- "project's palette, kit and icons. Read it before the first publish. Pass topic for one " +
341
+ "project's system, kit and icons. Read it before the first publish. Pass topic for one " +
297
342
  `reference section (${GUIDE_TOPICS.join(", ")}).`,
298
343
  params: {
299
344
  project: P.project,
@@ -441,6 +486,14 @@ const OUTPUT_SCHEMAS = {
441
486
  url: str,
442
487
  feedback: feedbackRide,
443
488
  },
489
+ system: {
490
+ rev: num,
491
+ changed: strs.optional().describe("What this write changed, as the Thread says it"),
492
+ checks: strs,
493
+ nudges: strs.optional(),
494
+ url: str,
495
+ feedback: feedbackRide.optional(),
496
+ },
444
497
  edit: {
445
498
  renamed: o({ from: str, to: str }).optional(),
446
499
  areaOrder: strs.optional(),
@@ -470,6 +523,9 @@ const OUTPUT_SCHEMAS = {
470
523
  .optional()
471
524
  .describe("Per state, the version the user put in use; export and embeds resolve to it"),
472
525
  knobs: bag.optional(),
526
+ system: str
527
+ .optional()
528
+ .describe("Without design: what the project's renders wear (rev, palettes, counts, failing checks)"),
473
529
  settled: bag.optional().describe("Every knob value the user has sent, later replies winning"),
474
530
  tree: z.array(bag).optional(),
475
531
  flows: z.array(flowSchema).optional(),
@@ -479,6 +535,7 @@ const OUTPUT_SCHEMAS = {
479
535
  design: str,
480
536
  text: str,
481
537
  here: z.boolean().optional().describe("From the design read"),
538
+ system: z.boolean().optional().describe("The project's own, on every design"),
482
539
  edited: z.boolean().optional(),
483
540
  archived: z.boolean().optional(),
484
541
  })),
@@ -489,7 +546,8 @@ const OUTPUT_SCHEMAS = {
489
546
  pending: z.union([z.array(pendingSchema), pendingSchema]).optional(),
490
547
  },
491
548
  export: {
492
- states: z.array(o({
549
+ states: z
550
+ .array(o({
493
551
  state: nullStr,
494
552
  variant: str,
495
553
  version: num,
@@ -497,9 +555,17 @@ const OUTPUT_SCHEMAS = {
497
555
  html: str.describe("With fills: only the chosen ones"),
498
556
  allFills: str.optional().describe("With fills: the html with every fill"),
499
557
  markdown: str,
500
- })),
501
- settled: bag,
502
- reply: bag.nullable(),
558
+ }))
559
+ .optional(),
560
+ settled: bag.optional(),
561
+ reply: bag.nullable().optional(),
562
+ sheet: str.optional().describe("Without design: the project's sheet"),
563
+ css: str
564
+ .optional()
565
+ .describe("Without design: tokens as CSS, the default palette on :root, kept ones by [data-palette]"),
566
+ tokens: bag.optional().describe("Without design: the same as data"),
567
+ knobs: bag.optional().describe("Without design: the project knobs' values"),
568
+ components: z.array(bag).optional(),
503
569
  },
504
570
  };
505
571
  // The core loop, loaded up front by harnesses that defer the rest of the
@@ -515,9 +581,11 @@ function shapeFor(tool, transport) {
515
581
  shape[key] =
516
582
  transport === "stdio" && key === "html" && tool.name === "publish"
517
583
  ? z.string().optional().describe(`${field.html}; or a file path`)
518
- : transport === "stdio" && key === "poster" && tool.name === "publish"
519
- ? z.string().optional().describe(`${p.d}; or an image file path`)
520
- : zodParam(p);
584
+ : transport === "stdio" && key === "sheet" && tool.name === "system"
585
+ ? z.string().optional().describe(`${p.d}; or a file path`)
586
+ : transport === "stdio" && key === "poster" && tool.name === "publish"
587
+ ? z.string().optional().describe(`${p.d}; or an image file path`)
588
+ : zodParam(p);
521
589
  }
522
590
  return shape;
523
591
  }
@@ -150,7 +150,10 @@ 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 [await deps.guide("", topic), String(topic)];
153
+ return [
154
+ await deps.guide(topic === "system" ? await projectOf() : "", topic),
155
+ String(topic),
156
+ ];
154
157
  },
155
158
  async read([design, opts]) {
156
159
  if (plain(opts).decisions === true) {
@@ -192,6 +195,20 @@ export function createRunFlow(deps) {
192
195
  const value = await take(flows.move(r.design, await mine(r), flowCtx));
193
196
  return [value, `${value.variants.length} moved`];
194
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
+ ];
211
+ },
195
212
  async edit([v]) {
196
213
  const r = await mine(plain(v));
197
214
  const value = await take(editCall(flows, r, flowCtx, project));
@@ -215,6 +232,10 @@ export function createRunFlow(deps) {
215
232
  },
216
233
  async export([v]) {
217
234
  const r = plain(v);
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
+ }
218
239
  const value = await take(flows.exportDesign(r.design, { ...r, project }, flowCtx));
219
240
  return [value, `${value.design} ${value.states.length} state(s)`];
220
241
  },
@@ -1,5 +1,5 @@
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; 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};\ntype Pending = { design: string; archived?: true; viewerOpen: boolean; draft: null | { answered: number; of: number; comments: number; touchedAt: string } };\ndeclare const mockpit: {\n guide(topic?: \"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 export(v: Ref): Promise<{ states: { state: string | null; variant: string; version: number; html: string; allFills?: string }[]; reply: unknown }>;\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", "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
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;
@@ -21,7 +21,7 @@ type Surface =
21
21
  | { kind: "code"; code: string; language?: string; lineStart?: number };
22
22
  type Ask = {
23
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; recommended?: boolean }[];
24
+ options: { id?: string; label: string; variant?: string; set?: Knobs; palette?: string; recommended?: boolean }[];
25
25
  };
26
26
  type Written = {
27
27
  post?: { state: string | null; variant: string; version: number }; planned?: true; url: string;
@@ -34,10 +34,11 @@ type Feedback = {
34
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
+ system?: { rev: number; changes: string[] };
37
38
  };
38
39
  type Pending = { design: string; archived?: true; viewerOpen: boolean; draft: null | { answered: number; of: number; comments: number; touchedAt: string } };
39
40
  declare const mockpit: {
40
- guide(topic?: "knobs" | "asks" | "surfaces" | "html" | "feedback" | "http" | "scripts"): Promise<string>;
41
+ guide(topic?: "system" | "knobs" | "asks" | "surfaces" | "html" | "feedback" | "http" | "scripts"): Promise<string>;
41
42
  /** Read first: decisionList is what the user already settled; it stands unless they say otherwise.
42
43
  * No design: every design, the flows, plus pending. With one: its states, variants, asks, parts, knobs.
43
44
  * opts.decisions: only the whole list, when a read cut it. */
@@ -56,7 +57,12 @@ declare const mockpit: {
56
57
  /** No new version; "" clears. { rename } or { areaOrder } without design edits the project.
57
58
  * notes: a short plain-text spec; not applied over the user's own edit (notes.applied says). */
58
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 }>;
59
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 }[] }>;
60
66
  /** data: base64 bytes. Use id as an image surface's assetId. */
61
67
  upload(data: string, opts: { contentType: string; filename?: string; kind?: "image" | "file" }): Promise<{ id: string; url: string }>;
62
68
  };
@@ -71,6 +77,7 @@ export const RUN_FUNCTIONS = [
71
77
  "say",
72
78
  "move",
73
79
  "edit",
80
+ "system",
74
81
  "export",
75
82
  "upload",
76
83
  ];
@@ -1,4 +1,5 @@
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 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";
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";
2
3
  import type { Mode } from "./themes.ts";
3
4
  export declare class SqlStore implements Store {
4
5
  private sql;
@@ -63,12 +64,33 @@ export declare class SqlStore implements Store {
63
64
  nameFirstState(id: string, state: string): Promise<Design | null>;
64
65
  renameDesign(id: string, slug: string): Promise<Design | null>;
65
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;
66
89
  private flowsOf;
67
90
  private writeFlow;
68
91
  listFlows(project: string): Promise<Flow[]>;
69
92
  placeFlowStep(project: string, name: string, screen: FlowStep, step: number): Promise<Flow | null>;
70
93
  putDraft(designId: string, draft: Draft | null): Promise<{
71
- draft: Draft | null;
72
94
  id: string;
73
95
  project: string;
74
96
  slug: string;
@@ -91,6 +113,7 @@ export declare class SqlStore implements Store {
91
113
  sets: AnswerSet[];
92
114
  createdAt: string;
93
115
  updatedAt: string;
116
+ draft: Draft | null;
94
117
  } | null>;
95
118
  private touchDesign;
96
119
  listPosts(query?: PostQuery): Promise<Post[]>;
@@ -106,19 +129,6 @@ export declare class SqlStore implements Store {
106
129
  findPost(designId: string, state: string | null, variant: string): Promise<Post | null>;
107
130
  createPost(input: CreatePostInput): Promise<Post | null>;
108
131
  updatePost(id: string, patch: UpdatePostInput): Promise<{
109
- publishedBy?: string | undefined;
110
- author?: string | undefined;
111
- embeds: Embed[];
112
- state: string | null;
113
- version: number;
114
- updatedAt: string;
115
- history: PostVersion[];
116
- from: number;
117
- prompt: string;
118
- description?: string | undefined;
119
- knobs?: Knobs | undefined;
120
- title: string;
121
- surfaces: Surface[];
122
132
  id: string;
123
133
  sessionId: string;
124
134
  design: string;
@@ -133,18 +143,23 @@ export declare class SqlStore implements Store {
133
143
  archivedAt?: string;
134
144
  stayedVersion?: number;
135
145
  rewrites?: number;
136
- } | null>;
137
- amendPost(id: string, version: number, patch: AmendPostInput): Promise<{
138
- amendedAt: string;
139
- rewrites: number;
140
- author?: string | undefined;
141
- prompt?: string | undefined;
142
- from?: number | undefined;
143
- embeds: Embed[];
144
- description?: string | undefined;
145
- knobs?: Knobs | undefined;
146
+ contract: number;
147
+ system?: number | undefined;
146
148
  title: string;
147
149
  surfaces: Surface[];
150
+ knobs?: Knobs | undefined;
151
+ description?: string | undefined;
152
+ embeds: Embed[];
153
+ state: string | null;
154
+ version: number;
155
+ updatedAt: string;
156
+ history: PostVersion[];
157
+ from: number;
158
+ prompt: string;
159
+ author?: string | undefined;
160
+ publishedBy?: string | undefined;
161
+ } | null>;
162
+ amendPost(id: string, version: number, patch: AmendPostInput): Promise<{
148
163
  id: string;
149
164
  sessionId: string;
150
165
  design: string;
@@ -163,25 +178,24 @@ export declare class SqlStore implements Store {
163
178
  archivedAt?: string;
164
179
  stayedVersion?: number;
165
180
  publishedBy?: string;
181
+ system?: number;
182
+ title: string;
183
+ surfaces: Surface[];
184
+ knobs?: Knobs | undefined;
185
+ description?: string | undefined;
186
+ embeds: Embed[];
187
+ from?: number | undefined;
188
+ prompt?: string | undefined;
189
+ author?: string | undefined;
190
+ amendedAt: string;
191
+ rewrites: number;
192
+ contract: number;
166
193
  } | null>;
167
- setPosterOnce(id: string, version: number, poster: string, mode?: Mode): Promise<boolean>;
194
+ setPosterOnce(id: string, version: number, poster: string, mode?: Mode, system?: number): Promise<boolean>;
168
195
  withdrawVersion(id: string, version: number, embeds: Embed[]): Promise<{
169
196
  post: null;
170
197
  } | {
171
198
  post: {
172
- rewrites: number;
173
- hiddenVersions?: number[] | undefined;
174
- amendedAt?: string | undefined;
175
- publishedBy?: string | undefined;
176
- author?: string | undefined;
177
- prompt?: string | undefined;
178
- from?: number | undefined;
179
- title: string;
180
- surfaces: Surface[];
181
- embeds: Embed[];
182
- updatedAt: string;
183
- version: number;
184
- history: PostVersion[];
185
199
  id: string;
186
200
  sessionId: string;
187
201
  design: string;
@@ -197,6 +211,21 @@ export declare class SqlStore implements Store {
197
211
  archiveReason?: string;
198
212
  archivedAt?: string;
199
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;
200
229
  };
201
230
  } | null>;
202
231
  removePost(id: string): Promise<boolean>;