mockpit 0.0.0-stage → 1.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 (86) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +239 -2
  3. package/bin/demoData.js +132 -0
  4. package/bin/initDesign.js +846 -0
  5. package/bin/mockpit.js +1835 -0
  6. package/bin/serveUrl.d.ts +1 -0
  7. package/bin/serveUrl.js +7 -0
  8. package/dist/mcp/server.d.ts +2 -0
  9. package/dist/mcp/server.js +252 -0
  10. package/dist/server/apiViews.d.ts +329 -0
  11. package/dist/server/apiViews.js +135 -0
  12. package/dist/server/app.d.ts +55 -0
  13. package/dist/server/app.js +3134 -0
  14. package/dist/server/base64.d.ts +1 -0
  15. package/dist/server/base64.js +16 -0
  16. package/dist/server/cdn.d.ts +6 -0
  17. package/dist/server/cdn.js +33 -0
  18. package/dist/server/codeRunner.d.ts +5 -0
  19. package/dist/server/codeRunner.js +89 -0
  20. package/dist/server/codeWorker.d.ts +1 -0
  21. package/dist/server/codeWorker.js +196 -0
  22. package/dist/server/designGuide.d.ts +16 -0
  23. package/dist/server/designGuide.js +311 -0
  24. package/dist/server/eventLog.d.ts +27 -0
  25. package/dist/server/eventLog.js +187 -0
  26. package/dist/server/events.d.ts +53 -0
  27. package/dist/server/events.js +14 -0
  28. package/dist/server/feedbackBatch.d.ts +43 -0
  29. package/dist/server/feedbackBatch.js +98 -0
  30. package/dist/server/icons.d.ts +50 -0
  31. package/dist/server/icons.js +225 -0
  32. package/dist/server/index.d.ts +1 -0
  33. package/dist/server/index.js +76 -0
  34. package/dist/server/kits.d.ts +36 -0
  35. package/dist/server/kits.js +279 -0
  36. package/dist/server/knobs.d.ts +15 -0
  37. package/dist/server/knobs.js +333 -0
  38. package/dist/server/logFile.d.ts +2 -0
  39. package/dist/server/logFile.js +27 -0
  40. package/dist/server/mcpHttp.d.ts +53 -0
  41. package/dist/server/mcpHttp.js +143 -0
  42. package/dist/server/mcpSpec.d.ts +191 -0
  43. package/dist/server/mcpSpec.js +402 -0
  44. package/dist/server/parts.d.ts +31 -0
  45. package/dist/server/parts.js +338 -0
  46. package/dist/server/postMarkdown.d.ts +10 -0
  47. package/dist/server/postMarkdown.js +271 -0
  48. package/dist/server/postSurfaces.d.ts +40 -0
  49. package/dist/server/postSurfaces.js +407 -0
  50. package/dist/server/public.d.ts +5 -0
  51. package/dist/server/public.js +5 -0
  52. package/dist/server/push.d.ts +45 -0
  53. package/dist/server/push.js +234 -0
  54. package/dist/server/richRender.d.ts +15 -0
  55. package/dist/server/richRender.js +392 -0
  56. package/dist/server/run.d.ts +82 -0
  57. package/dist/server/run.js +290 -0
  58. package/dist/server/runApi.d.ts +6 -0
  59. package/dist/server/runApi.js +82 -0
  60. package/dist/server/slots.d.ts +14 -0
  61. package/dist/server/slots.js +71 -0
  62. package/dist/server/sqlStore.d.ts +119 -0
  63. package/dist/server/sqlStore.js +954 -0
  64. package/dist/server/sqliteStorage.d.ts +2 -0
  65. package/dist/server/sqliteStorage.js +90 -0
  66. package/dist/server/surfacePage.d.ts +48 -0
  67. package/dist/server/surfacePage.js +1099 -0
  68. package/dist/server/themes.d.ts +48 -0
  69. package/dist/server/themes.js +305 -0
  70. package/dist/server/types.d.ts +599 -0
  71. package/dist/server/types.js +299 -0
  72. package/dist/workers/public.d.ts +1 -0
  73. package/dist/workers/public.js +3 -0
  74. package/extensions/mockpit.js +717 -0
  75. package/guide/AGENT_SETUP.md +23 -0
  76. package/guide/topics/asks.md +87 -0
  77. package/guide/topics/feedback.md +127 -0
  78. package/guide/topics/html.md +175 -0
  79. package/guide/topics/http.md +76 -0
  80. package/guide/topics/knobs.md +72 -0
  81. package/guide/topics/scripts.md +129 -0
  82. package/guide/topics/surfaces.md +100 -0
  83. package/package.json +165 -4
  84. package/skills/launch-video/SKILL.md +159 -0
  85. package/skills/mockpit/SKILL.md +40 -0
  86. package/viewer/dist/index.html +1922 -0
@@ -0,0 +1,53 @@
1
+ import type { Hono } from "hono";
2
+ import type { FlowContext, FlowResult } from "./app.ts";
3
+ import { type GuideTopic } from "./designGuide.ts";
4
+ import type { Asset, AssetKind, Store } from "./types.ts";
5
+ type Flow<A extends unknown[]> = (...args: A) => Promise<FlowResult>;
6
+ export interface McpFlows {
7
+ publish: Flow<[body: any, ctx: FlowContext]>;
8
+ list: Flow<[query: {
9
+ project?: string;
10
+ }]>;
11
+ get: Flow<[ref: unknown, query: {
12
+ project?: unknown;
13
+ body?: boolean;
14
+ history?: boolean;
15
+ }]>;
16
+ ask: Flow<[ref: unknown, body: any, ctx: FlowContext]>;
17
+ exportMock: Flow<[
18
+ ref: unknown,
19
+ query: {
20
+ project?: unknown;
21
+ state?: unknown;
22
+ variant?: unknown;
23
+ },
24
+ ctx: FlowContext
25
+ ]>;
26
+ say: Flow<[ref: unknown, body: any]>;
27
+ feedback: Flow<[query: {
28
+ session?: unknown;
29
+ project?: unknown;
30
+ }]>;
31
+ }
32
+ export interface McpDeps {
33
+ store: Store;
34
+ basePath?: (request: Request) => string;
35
+ flows: McpFlows;
36
+ run: Flow<[body: any, ctx: FlowContext]>;
37
+ uploadAsset(input: {
38
+ data: Uint8Array;
39
+ contentType: string;
40
+ filename?: string;
41
+ kind?: AssetKind;
42
+ session?: string;
43
+ }): Promise<{
44
+ asset: Omit<Asset, "data">;
45
+ } | {
46
+ error: string;
47
+ status: number;
48
+ }>;
49
+ guide(project: string, topic?: GuideTopic): string | Promise<string>;
50
+ }
51
+ export declare function unwrap(result: FlowResult): unknown;
52
+ export declare function registerMcp(app: Hono, deps: McpDeps): void;
53
+ export {};
@@ -0,0 +1,143 @@
1
+ import { decodeBase64 } from "./base64.js";
2
+ import { isGuideTopic, unknownTopicMessage } from "./designGuide.js";
3
+ import { HTTP_MCP_TOOLS, HTTP_RUN_TOOLS, MCP_INSTRUCTIONS, MCP_SERVER_INFO, runToolResult, toolResult, } from "./mcpSpec.js";
4
+ import { RUN_INSTRUCTIONS } from "./runApi.js";
5
+ // A flow's error status becomes a tool error carrying the same JSON body the
6
+ // REST tier returns, so the agent sees the hint (states, variants) either way.
7
+ export function unwrap(result) {
8
+ if (result.status >= 400) {
9
+ const { error, ...extra } = result.body ?? {};
10
+ throw new Error(Object.keys(extra).length ? `${error} ${JSON.stringify(extra)}` : String(error));
11
+ }
12
+ return result.body;
13
+ }
14
+ export function registerMcp(app, deps) {
15
+ const { flows, store } = deps;
16
+ async function projectOf(args) {
17
+ if (typeof args.project === "string" && args.project)
18
+ return args.project;
19
+ if (typeof args.session === "string") {
20
+ const session = await store.getSession(args.session);
21
+ if (session?.project)
22
+ return session.project;
23
+ }
24
+ const projects = await store.listProjects();
25
+ return projects[0]?.name ?? "workspace";
26
+ }
27
+ async function callTool(name, args, ctx) {
28
+ switch (name) {
29
+ case "publish":
30
+ return unwrap(await flows.publish(args, ctx));
31
+ case "ask":
32
+ return unwrap(await flows.ask(args.mock, args, ctx));
33
+ case "read":
34
+ if (args.mock === undefined)
35
+ return unwrap(await flows.list({ project: args.project }));
36
+ return unwrap(await flows.get(args.mock, {
37
+ project: args.project,
38
+ body: args.body === true,
39
+ history: args.history === true,
40
+ }));
41
+ case "feedback":
42
+ return unwrap(await flows.feedback({ session: args.session, project: args.project }));
43
+ case "say":
44
+ return unwrap(await flows.say(args.mock, args));
45
+ case "export":
46
+ return unwrap(await flows.exportMock(args.mock, args, ctx));
47
+ case "upload": {
48
+ if (typeof args.data !== "string" || args.data.length === 0) {
49
+ throw new Error("upload needs base64 `data`");
50
+ }
51
+ const result = await deps.uploadAsset({
52
+ data: decodeBase64(args.data),
53
+ contentType: typeof args.contentType === "string" ? args.contentType : "",
54
+ filename: typeof args.filename === "string" ? args.filename : undefined,
55
+ kind: args.kind === "image" || args.kind === "file" ? args.kind : undefined,
56
+ session: typeof args.session === "string" ? args.session : undefined,
57
+ });
58
+ if ("error" in result)
59
+ throw new Error(result.error);
60
+ return {
61
+ id: result.asset.id,
62
+ sessionId: result.asset.sessionId,
63
+ url: `${ctx.base}/a/${result.asset.id}`,
64
+ contentType: result.asset.contentType,
65
+ byteLength: result.asset.byteLength,
66
+ kind: result.asset.kind,
67
+ };
68
+ }
69
+ case "guide": {
70
+ if (args.topic === undefined)
71
+ return await deps.guide(await projectOf(args));
72
+ if (!isGuideTopic(args.topic))
73
+ throw new Error(unknownTopicMessage(String(args.topic)));
74
+ return await deps.guide("", args.topic);
75
+ }
76
+ default:
77
+ throw new Error(`unknown tool: ${name}`);
78
+ }
79
+ }
80
+ app.post("/mcp", async (c) => {
81
+ const rpc = (id, result) => c.json({ jsonrpc: "2.0", id, result });
82
+ // `?mode=code` is the opt-in codemode catalog for clients without a
83
+ // harness of their own: one `run` tool instead of the mock tools.
84
+ const code = c.req.query("mode") === "code";
85
+ const rpcError = (id, code, message, status = 200) => c.json({ jsonrpc: "2.0", id, error: { code, message } }, status);
86
+ let msg;
87
+ try {
88
+ msg = await c.req.json();
89
+ }
90
+ catch {
91
+ return rpcError(null, -32700, "parse error", 400);
92
+ }
93
+ if (Array.isArray(msg)) {
94
+ return rpcError(null, -32600, "batch requests are not supported", 400);
95
+ }
96
+ if (msg.method === "initialize") {
97
+ return rpc(msg.id, {
98
+ protocolVersion: typeof msg.params?.protocolVersion === "string"
99
+ ? msg.params.protocolVersion
100
+ : "2025-03-26",
101
+ capabilities: { tools: { listChanged: false } },
102
+ serverInfo: MCP_SERVER_INFO,
103
+ instructions: code ? RUN_INSTRUCTIONS : MCP_INSTRUCTIONS,
104
+ });
105
+ }
106
+ if (msg.id === undefined)
107
+ return c.body(null, 202); // notifications
108
+ if (msg.method === "ping")
109
+ return rpc(msg.id, {});
110
+ if (msg.method === "tools/list") {
111
+ return rpc(msg.id, { tools: code ? HTTP_RUN_TOOLS : HTTP_MCP_TOOLS });
112
+ }
113
+ if (msg.method === "tools/call") {
114
+ const url = new URL(c.req.url);
115
+ const ctx = {
116
+ base: `${url.origin}${deps.basePath?.(c.req.raw) ?? ""}`,
117
+ // An MCP caller is an agent, never the viewer.
118
+ viewer: false,
119
+ strict: false,
120
+ request: c.req.raw,
121
+ signal: c.req.raw.signal,
122
+ };
123
+ try {
124
+ const name = msg.params?.name;
125
+ if (name === "run") {
126
+ const args = msg.params?.arguments ?? {};
127
+ return rpc(msg.id, runToolResult(unwrap(await deps.run(args, ctx))));
128
+ }
129
+ return rpc(msg.id, toolResult(name, await callTool(name, msg.params?.arguments ?? {}, ctx)));
130
+ }
131
+ catch (err) {
132
+ return rpc(msg.id, {
133
+ content: [{ type: "text", text: `error: ${err instanceof Error ? err.message : err}` }],
134
+ isError: true,
135
+ });
136
+ }
137
+ }
138
+ return rpcError(msg.id, -32601, `method not found: ${msg.method}`);
139
+ });
140
+ // Stateless server: no SSE stream to resume, no session to delete.
141
+ app.get("/mcp", (c) => c.text("mockpit MCP is stateless — POST JSON-RPC messages here", 405));
142
+ app.delete("/mcp", (c) => c.body(null, 405));
143
+ }
@@ -0,0 +1,191 @@
1
+ import * as z from "zod/v4";
2
+ export declare const MCP_SERVER_INFO: {
3
+ name: string;
4
+ version: string;
5
+ };
6
+ export declare const MCP_INSTRUCTIONS: string;
7
+ export declare const mcpSurfaceSchema: z.ZodObject<{
8
+ id: z.ZodOptional<z.ZodString>;
9
+ kind: z.ZodOptional<z.ZodEnum<{
10
+ html: "html";
11
+ diff: "diff";
12
+ image: "image";
13
+ markdown: "markdown";
14
+ terminal: "terminal";
15
+ mermaid: "mermaid";
16
+ json: "json";
17
+ code: "code";
18
+ }>>;
19
+ html: z.ZodOptional<z.ZodString>;
20
+ kits: z.ZodOptional<z.ZodArray<z.ZodString>>;
21
+ markdown: z.ZodOptional<z.ZodString>;
22
+ mermaid: z.ZodOptional<z.ZodString>;
23
+ patch: z.ZodOptional<z.ZodString>;
24
+ files: z.ZodOptional<z.ZodArray<z.ZodObject<{
25
+ filename: z.ZodString;
26
+ before: z.ZodString;
27
+ after: z.ZodString;
28
+ language: z.ZodOptional<z.ZodString>;
29
+ }, z.core.$strip>>>;
30
+ layout: z.ZodOptional<z.ZodEnum<{
31
+ unified: "unified";
32
+ split: "split";
33
+ }>>;
34
+ assetId: z.ZodOptional<z.ZodString>;
35
+ alt: z.ZodOptional<z.ZodString>;
36
+ caption: z.ZodOptional<z.ZodString>;
37
+ title: z.ZodOptional<z.ZodString>;
38
+ text: z.ZodOptional<z.ZodString>;
39
+ cols: z.ZodOptional<z.ZodNumber>;
40
+ data: z.ZodOptional<z.ZodUnknown>;
41
+ code: z.ZodOptional<z.ZodString>;
42
+ language: z.ZodOptional<z.ZodString>;
43
+ lineStart: z.ZodOptional<z.ZodNumber>;
44
+ }, z.core.$strip>;
45
+ type Param = {
46
+ t: "string" | "number" | "boolean" | "integer";
47
+ d?: string;
48
+ req?: boolean;
49
+ } | {
50
+ t: "enum";
51
+ values: readonly [string, ...string[]];
52
+ d?: string;
53
+ req?: boolean;
54
+ } | {
55
+ t: "surfaces" | "asks" | "object";
56
+ d?: string;
57
+ req?: boolean;
58
+ };
59
+ interface ToolDef {
60
+ name: string;
61
+ description: string;
62
+ params: Record<string, Param>;
63
+ httpOnly?: readonly string[];
64
+ stdioExtra?: Record<string, Param>;
65
+ }
66
+ export declare const MCP_TOOL_DEFS: ToolDef[];
67
+ export declare const RUN_TOOL_DEF: ToolDef;
68
+ type Json = Record<string, unknown>;
69
+ export declare const HTTP_MCP_TOOLS: ({
70
+ _meta: {
71
+ "anthropic/alwaysLoad": boolean;
72
+ };
73
+ outputSchema?: Json | undefined;
74
+ name: string;
75
+ description: string;
76
+ inputSchema: Json;
77
+ } | {
78
+ _meta?: undefined;
79
+ outputSchema?: Json | undefined;
80
+ name: string;
81
+ description: string;
82
+ inputSchema: Json;
83
+ })[];
84
+ export declare const STDIO_MCP_CATALOG: ({
85
+ _meta: {
86
+ "anthropic/alwaysLoad": boolean;
87
+ };
88
+ outputSchema?: Json | undefined;
89
+ name: string;
90
+ description: string;
91
+ inputSchema: Json;
92
+ } | {
93
+ _meta?: undefined;
94
+ outputSchema?: Json | undefined;
95
+ name: string;
96
+ description: string;
97
+ inputSchema: Json;
98
+ })[];
99
+ export declare const HTTP_RUN_TOOLS: ({
100
+ _meta: {
101
+ "anthropic/alwaysLoad": boolean;
102
+ };
103
+ outputSchema?: Json | undefined;
104
+ name: string;
105
+ description: string;
106
+ inputSchema: Json;
107
+ } | {
108
+ _meta?: undefined;
109
+ outputSchema?: Json | undefined;
110
+ name: string;
111
+ description: string;
112
+ inputSchema: Json;
113
+ })[];
114
+ export declare const STDIO_RUN_CATALOG: ({
115
+ _meta: {
116
+ "anthropic/alwaysLoad": boolean;
117
+ };
118
+ outputSchema?: Json | undefined;
119
+ name: string;
120
+ description: string;
121
+ inputSchema: Json;
122
+ } | {
123
+ _meta?: undefined;
124
+ outputSchema?: Json | undefined;
125
+ name: string;
126
+ description: string;
127
+ inputSchema: Json;
128
+ })[];
129
+ export declare const STDIO_MCP_TOOLS: ({
130
+ _meta: {
131
+ "anthropic/alwaysLoad": boolean;
132
+ };
133
+ outputSchema?: z.ZodObject<Readonly<{
134
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
135
+ }>, z.core.$loose> | undefined;
136
+ name: string;
137
+ description: string;
138
+ inputSchema: Readonly<{
139
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
140
+ }>;
141
+ } | {
142
+ _meta?: undefined;
143
+ outputSchema?: z.ZodObject<Readonly<{
144
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
145
+ }>, z.core.$loose> | undefined;
146
+ name: string;
147
+ description: string;
148
+ inputSchema: Readonly<{
149
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
150
+ }>;
151
+ })[];
152
+ export declare const STDIO_RUN_TOOLS: ({
153
+ _meta: {
154
+ "anthropic/alwaysLoad": boolean;
155
+ };
156
+ outputSchema?: z.ZodObject<Readonly<{
157
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
158
+ }>, z.core.$loose> | undefined;
159
+ name: string;
160
+ description: string;
161
+ inputSchema: Readonly<{
162
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
163
+ }>;
164
+ } | {
165
+ _meta?: undefined;
166
+ outputSchema?: z.ZodObject<Readonly<{
167
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
168
+ }>, z.core.$loose> | undefined;
169
+ name: string;
170
+ description: string;
171
+ inputSchema: Readonly<{
172
+ [k: string]: z.core.$ZodType<unknown, unknown, z.core.$ZodTypeInternals<unknown, unknown>>;
173
+ }>;
174
+ })[];
175
+ export declare const MCP_TOOL_NAMES: string[];
176
+ export declare function toolResult(name: string, value: unknown): {
177
+ structuredContent?: Record<string, unknown> | undefined;
178
+ content: {
179
+ type: "text";
180
+ text: string;
181
+ }[];
182
+ };
183
+ export declare function runToolResult(envelope: unknown): {
184
+ isError?: boolean | undefined;
185
+ structuredContent?: Record<string, unknown> | undefined;
186
+ content: {
187
+ type: "text";
188
+ text: string;
189
+ }[];
190
+ };
191
+ export {};