mockpit 0.0.0-stage → 1.0.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 (82) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +232 -2
  3. package/bin/demoData.js +132 -0
  4. package/bin/initDesign.js +846 -0
  5. package/bin/mockpit.js +1830 -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 +230 -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 +53 -0
  13. package/dist/server/app.js +3112 -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/events.d.ts +53 -0
  25. package/dist/server/events.js +14 -0
  26. package/dist/server/feedbackBatch.d.ts +43 -0
  27. package/dist/server/feedbackBatch.js +98 -0
  28. package/dist/server/icons.d.ts +50 -0
  29. package/dist/server/icons.js +225 -0
  30. package/dist/server/index.d.ts +1 -0
  31. package/dist/server/index.js +64 -0
  32. package/dist/server/kits.d.ts +36 -0
  33. package/dist/server/kits.js +279 -0
  34. package/dist/server/knobs.d.ts +15 -0
  35. package/dist/server/knobs.js +333 -0
  36. package/dist/server/mcpHttp.d.ts +53 -0
  37. package/dist/server/mcpHttp.js +143 -0
  38. package/dist/server/mcpSpec.d.ts +191 -0
  39. package/dist/server/mcpSpec.js +402 -0
  40. package/dist/server/parts.d.ts +31 -0
  41. package/dist/server/parts.js +338 -0
  42. package/dist/server/postMarkdown.d.ts +10 -0
  43. package/dist/server/postMarkdown.js +271 -0
  44. package/dist/server/postSurfaces.d.ts +40 -0
  45. package/dist/server/postSurfaces.js +407 -0
  46. package/dist/server/public.d.ts +5 -0
  47. package/dist/server/public.js +5 -0
  48. package/dist/server/push.d.ts +45 -0
  49. package/dist/server/push.js +234 -0
  50. package/dist/server/richRender.d.ts +15 -0
  51. package/dist/server/richRender.js +392 -0
  52. package/dist/server/run.d.ts +82 -0
  53. package/dist/server/run.js +290 -0
  54. package/dist/server/runApi.d.ts +6 -0
  55. package/dist/server/runApi.js +82 -0
  56. package/dist/server/slots.d.ts +14 -0
  57. package/dist/server/slots.js +71 -0
  58. package/dist/server/sqlStore.d.ts +119 -0
  59. package/dist/server/sqlStore.js +954 -0
  60. package/dist/server/sqliteStorage.d.ts +2 -0
  61. package/dist/server/sqliteStorage.js +90 -0
  62. package/dist/server/surfacePage.d.ts +48 -0
  63. package/dist/server/surfacePage.js +1099 -0
  64. package/dist/server/themes.d.ts +48 -0
  65. package/dist/server/themes.js +305 -0
  66. package/dist/server/types.d.ts +599 -0
  67. package/dist/server/types.js +299 -0
  68. package/dist/workers/public.d.ts +1 -0
  69. package/dist/workers/public.js +3 -0
  70. package/extensions/mockpit.js +703 -0
  71. package/guide/AGENT_SETUP.md +23 -0
  72. package/guide/topics/asks.md +87 -0
  73. package/guide/topics/feedback.md +127 -0
  74. package/guide/topics/html.md +175 -0
  75. package/guide/topics/http.md +76 -0
  76. package/guide/topics/knobs.md +72 -0
  77. package/guide/topics/scripts.md +129 -0
  78. package/guide/topics/surfaces.md +100 -0
  79. package/package.json +165 -4
  80. package/skills/launch-video/SKILL.md +159 -0
  81. package/skills/mockpit/SKILL.md +40 -0
  82. package/viewer/dist/index.html +1922 -0
@@ -0,0 +1,135 @@
1
+ // Response shapes shared by every tier (REST, both MCP transports, the CLI), so
2
+ // one mock reads the same however an agent asks for it.
3
+ import { mergeParts, partsInSurfaces } from "./parts.js";
4
+ import { isSandboxedSurfaceKind, openCount, SURFACE_CONTENT_FIELDS, } from "./types.js";
5
+ export const surfaceRef = (surface, index) => ({
6
+ id: surface.id,
7
+ kind: surface.kind,
8
+ index,
9
+ });
10
+ export const fullSurfaceView = (surface, index) => ({ ...surface, index });
11
+ // A sandboxed surface renders as an opaque-origin iframe pointed at
12
+ // /s/:id?surface=N, which fetches the body itself — so a read that is not asking
13
+ // for bodies drops just the content field. Native kinds (image/json) render from
14
+ // inline data, so they keep everything.
15
+ export const hydratedSurfaceView = (surface, index) => {
16
+ const field = isSandboxedSurfaceKind(surface.kind)
17
+ ? SURFACE_CONTENT_FIELDS[surface.kind]
18
+ : undefined;
19
+ if (!field)
20
+ return fullSurfaceView(surface, index);
21
+ // Surface is a union of interfaces, so the content key can't be dropped through
22
+ // the union type. Widen to a bag, delete the one key; the value is only serialized.
23
+ const view = { ...surface, index };
24
+ delete view[field];
25
+ return view;
26
+ };
27
+ // One past version without its bodies: enough to list versions or pick one to
28
+ // fetch, at a bounded cost.
29
+ export const historyMetaView = (version) => ({
30
+ version: version.version,
31
+ title: version.title,
32
+ at: version.at,
33
+ ...(version.from === undefined ? {} : { from: version.from }),
34
+ ...(version.prompt ? { prompt: version.prompt } : {}),
35
+ ...(version.author === undefined ? {} : { author: version.author }),
36
+ surfaceKinds: version.surfaces.map((s) => s.kind),
37
+ });
38
+ export const variantView = (post, opts = {}) => ({
39
+ postId: post.id,
40
+ state: post.state,
41
+ variant: post.variant,
42
+ status: post.status,
43
+ version: post.version,
44
+ title: post.title,
45
+ sessionId: post.sessionId,
46
+ createdAt: post.createdAt,
47
+ updatedAt: post.updatedAt,
48
+ ...(post.from === undefined ? {} : { from: post.from }),
49
+ ...(post.prompt ? { prompt: post.prompt } : {}),
50
+ ...(post.author === undefined ? {} : { author: post.author }),
51
+ ...(post.knobs ? { knobs: post.knobs } : {}),
52
+ ...(post.slots.length ? { slots: post.slots } : {}),
53
+ // The part names this variant's own markup marks, so the viewer can tell
54
+ // which looks render a part (Mix) without the html bodies.
55
+ parts: partsInSurfaces(post.surfaces).map((p) => p.name),
56
+ surfaces: post.surfaces.map(opts.body ? fullSurfaceView : hydratedSurfaceView),
57
+ ...(opts.history
58
+ ? {
59
+ history: [
60
+ historyMetaView({
61
+ version: post.version,
62
+ title: post.title,
63
+ surfaces: post.surfaces,
64
+ at: post.updatedAt,
65
+ ...(post.from === undefined ? {} : { from: post.from }),
66
+ ...(post.prompt === undefined ? {} : { prompt: post.prompt }),
67
+ ...(post.author === undefined ? {} : { author: post.author }),
68
+ }),
69
+ ...[...post.history].sort((a, b) => b.version - a.version).map(historyMetaView),
70
+ ],
71
+ }
72
+ : {}),
73
+ });
74
+ const stateOrder = (mock) => (mock.states.length ? mock.states : [null]);
75
+ // The parts the agent marked, per state, across the variants still in play.
76
+ export function partsByState(mock, posts) {
77
+ return stateOrder(mock).map((state) => ({
78
+ state,
79
+ parts: mergeParts(posts
80
+ .filter((p) => p.state === state && p.status !== "archived")
81
+ .map((p) => partsInSurfaces(p.surfaces))),
82
+ }));
83
+ }
84
+ // What Home shows for a mock: the first state's chosen (else first) variant.
85
+ function thumbnail(mock, posts) {
86
+ const first = stateOrder(mock)[0];
87
+ const inState = posts.filter((p) => p.state === first);
88
+ const pick = inState.find((p) => p.status === "accepted") ??
89
+ inState.find((p) => p.status === "open") ??
90
+ inState[0] ??
91
+ posts[0];
92
+ if (!pick)
93
+ return null;
94
+ const surface = pick.surfaces.findIndex((s) => isSandboxedSurfaceKind(s.kind));
95
+ return { postId: pick.id, surface: Math.max(surface, 0), version: pick.version };
96
+ }
97
+ export const mockSummaryView = (mock, posts) => ({
98
+ id: mock.id,
99
+ project: mock.project,
100
+ slug: mock.slug,
101
+ title: mock.title,
102
+ kind: mock.kind,
103
+ states: mock.states,
104
+ stateCount: Math.max(mock.states.length, 1),
105
+ variants: posts.length,
106
+ open: openCount(mock, posts),
107
+ sessionId: mock.sessionId,
108
+ createdAt: mock.createdAt,
109
+ updatedAt: mock.updatedAt,
110
+ thumbnail: thumbnail(mock, posts),
111
+ });
112
+ // One mock as anyone outside the viewer's own draft sees it: the draft is the
113
+ // user's unsent work and never leaves through this view.
114
+ export const mockDetailView = (mock, posts, opts = {}) => ({
115
+ id: mock.id,
116
+ project: mock.project,
117
+ slug: mock.slug,
118
+ title: mock.title,
119
+ kind: mock.kind,
120
+ states: mock.states,
121
+ asks: mock.asks,
122
+ open: openCount(mock, posts),
123
+ knobs: mock.knobs,
124
+ sessionId: mock.sessionId,
125
+ createdAt: mock.createdAt,
126
+ updatedAt: mock.updatedAt,
127
+ variants: posts.map((p) => variantView(p, opts)),
128
+ parts: partsByState(mock, posts),
129
+ // The knob values of the latest reply — what the user last sent, not drafts.
130
+ tuned: opts.tuned ?? {},
131
+ });
132
+ export const sessionRowView = (session, postCount) => ({
133
+ ...session,
134
+ postCount,
135
+ });
@@ -0,0 +1,53 @@
1
+ import { Hono } from "hono";
2
+ import { type FeedEvent } from "./events.ts";
3
+ import { type GuideTopic } from "./designGuide.ts";
4
+ import { type Executor, type RunLimits } from "./run.ts";
5
+ import { type Store } from "./types.ts";
6
+ export type { FeedEvent } from "./events.ts";
7
+ export type { FeedbackBatch } from "./feedbackBatch.ts";
8
+ export type AuthenticateHook = (request: Request) => boolean | Response | Promise<boolean | Response>;
9
+ export type BasePathHook = string | ((request: Request) => string | null | undefined);
10
+ export type PublicReadMode = "session" | "full";
11
+ export interface AppOptions {
12
+ store: Store;
13
+ viewerHtml: string;
14
+ setupText: string;
15
+ topics?: Partial<Record<GuideTopic, string>>;
16
+ authenticate?: AuthenticateHook;
17
+ authToken?: string;
18
+ basePath?: BasePathHook;
19
+ publicRead?: PublicReadMode;
20
+ screenshots?: boolean;
21
+ version?: string;
22
+ upgradeCommand?: string;
23
+ fetchLatestRelease?: () => Promise<LatestRelease | null>;
24
+ onEvent?: (event: FeedEvent) => void;
25
+ maxHoldConnections?: number;
26
+ executor?: Executor;
27
+ runLimits?: Partial<RunLimits>;
28
+ }
29
+ export interface LatestRelease {
30
+ version: string;
31
+ notes?: string;
32
+ }
33
+ export interface CommentWait {
34
+ sessionId?: string;
35
+ mockId?: string;
36
+ postId?: string;
37
+ author?: string;
38
+ afterSeq?: number;
39
+ waitSeconds: number;
40
+ agent?: boolean;
41
+ }
42
+ export interface FlowResult {
43
+ status: number;
44
+ body: any;
45
+ }
46
+ export interface FlowContext {
47
+ base: string;
48
+ viewer: boolean;
49
+ strict: boolean;
50
+ request?: Request;
51
+ signal?: AbortSignal;
52
+ }
53
+ export declare function createApp({ store, viewerHtml, setupText, topics, authenticate, authToken, basePath, publicRead, screenshots, version, upgradeCommand, fetchLatestRelease, onEvent, maxHoldConnections, executor, runLimits, }: AppOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;