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/apiViews.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
// Response shapes shared by every tier (REST, both MCP transports, the CLI), so
|
|
2
|
-
// one
|
|
2
|
+
// one design reads the same however an agent asks for it.
|
|
3
3
|
import { slotKnobs, slotsInSurfaces } from "./fills.js";
|
|
4
4
|
import { mergeParts, partsInSurfaces } from "./parts.js";
|
|
5
|
-
import {
|
|
5
|
+
import { isKeptVariant, keptVariants } from "./standings.js";
|
|
6
|
+
import { changedTo, currentVersion, draftedCount, inUseVersion, isPlanned, isSandboxedSurfaceKind, isLive, openCount, recommendedVariant, SURFACE_CONTENT_FIELDS, variantStatus, } from "./types.js";
|
|
6
7
|
export const surfaceRef = (surface, index) => ({
|
|
7
8
|
id: surface.id,
|
|
8
9
|
kind: surface.kind,
|
|
@@ -25,11 +26,43 @@ export const hydratedSurfaceView = (surface, index) => {
|
|
|
25
26
|
delete view[field];
|
|
26
27
|
return view;
|
|
27
28
|
};
|
|
28
|
-
//
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
// A still mockpit took shows the page in the mode it was taken in. In the other mode it
|
|
30
|
+
// would be the one picture in the wrong colours among live pages, so it is left out and the
|
|
31
|
+
// page runs as it did before posters. Applied to posts before any view reads them, so every
|
|
32
|
+
// view agrees. Posts come from the store's cache: copied where changed, never written to.
|
|
33
|
+
// The same goes for a still taken under another revision of the project's system.
|
|
34
|
+
const otherMode = (s, mode, rev) => {
|
|
35
|
+
const { posterMode: taken, posterSystem: under } = s;
|
|
36
|
+
if (s.kind !== "html" || taken === undefined)
|
|
37
|
+
return false;
|
|
38
|
+
if (taken !== mode)
|
|
39
|
+
return true;
|
|
40
|
+
if (rev === undefined)
|
|
41
|
+
return false;
|
|
42
|
+
return under === undefined ? rev > 1 : under !== rev;
|
|
32
43
|
};
|
|
44
|
+
const surfacesFor = (surfaces, mode, rev) => surfaces.some((s) => otherMode(s, mode, rev))
|
|
45
|
+
? surfaces.map((s) => {
|
|
46
|
+
if (!otherMode(s, mode, rev))
|
|
47
|
+
return s;
|
|
48
|
+
const { poster: _poster, posterMode: _mode, posterSystem: _system, ...rest } = s;
|
|
49
|
+
return rest;
|
|
50
|
+
})
|
|
51
|
+
: surfaces;
|
|
52
|
+
export const postersFor = (posts, mode,
|
|
53
|
+
// The project system's revision; undefined across projects, where it isn't one.
|
|
54
|
+
rev) => posts.map((p) => {
|
|
55
|
+
const surfaces = surfacesFor(p.surfaces, mode, rev);
|
|
56
|
+
const history = p.history.map((h) => {
|
|
57
|
+
const own = surfacesFor(h.surfaces, mode, rev);
|
|
58
|
+
return own === h.surfaces ? h : { ...h, surfaces: own };
|
|
59
|
+
});
|
|
60
|
+
return surfaces === p.surfaces && history.every((h, i) => h === p.history[i])
|
|
61
|
+
? p
|
|
62
|
+
: { ...p, surfaces, history };
|
|
63
|
+
});
|
|
64
|
+
// The still overviews show for a version: its html page's poster.
|
|
65
|
+
const pagePoster = (surfaces) => surfaces.find((s) => s.kind === "html")?.poster;
|
|
33
66
|
const posterOf = (surfaces) => {
|
|
34
67
|
const poster = pagePoster(surfaces);
|
|
35
68
|
return poster ? { poster } : {};
|
|
@@ -46,6 +79,28 @@ const inUsePoster = (p) => {
|
|
|
46
79
|
const poster = posterAt(p, p.acceptedVersion);
|
|
47
80
|
return poster ? { inUsePoster: poster } : {};
|
|
48
81
|
};
|
|
82
|
+
// The version Home shows when nothing is in use and the newest was hidden.
|
|
83
|
+
const coverVersion = (p) => {
|
|
84
|
+
const at = currentVersion(p);
|
|
85
|
+
if (p.status === "accepted" || at === p.version)
|
|
86
|
+
return {};
|
|
87
|
+
const poster = posterAt(p, at);
|
|
88
|
+
return { coverVersion: at, ...(poster ? { coverPoster: poster } : {}) };
|
|
89
|
+
};
|
|
90
|
+
// A page that draws on a canvas may hold a WebGL context, of which a browser
|
|
91
|
+
// keeps about 16 and drops the oldest past that, so overviews ration these
|
|
92
|
+
// frames and no others. Three.js and the like make their canvas from script.
|
|
93
|
+
// Asked once per version: a read lists every version, with bodies up to 1 MB.
|
|
94
|
+
const CANVAS_PAGE = /<canvas[\s>]|webgl|three(?:\.module|\.min|\.js|@)|['"]three['"]|pixi|babylon/i;
|
|
95
|
+
const canvasPages = new WeakMap();
|
|
96
|
+
const drawsOnCanvas = (surfaces) => {
|
|
97
|
+
let hit = canvasPages.get(surfaces);
|
|
98
|
+
if (hit === undefined) {
|
|
99
|
+
hit = surfaces.some((s) => s.kind === "html" && CANVAS_PAGE.test(s.html));
|
|
100
|
+
canvasPages.set(surfaces, hit);
|
|
101
|
+
}
|
|
102
|
+
return hit;
|
|
103
|
+
};
|
|
49
104
|
// One past version without its bodies: enough to list versions or pick one to
|
|
50
105
|
// fetch, at a bounded cost.
|
|
51
106
|
export const historyMetaView = (version) => ({
|
|
@@ -55,8 +110,10 @@ export const historyMetaView = (version) => ({
|
|
|
55
110
|
...(version.from === undefined ? {} : { from: version.from }),
|
|
56
111
|
...(version.prompt ? { prompt: version.prompt } : {}),
|
|
57
112
|
...(version.author === undefined ? {} : { author: version.author }),
|
|
113
|
+
...(version.amendedAt ? { amendedAt: version.amendedAt } : {}),
|
|
58
114
|
surfaceKinds: version.surfaces.map((s) => s.kind),
|
|
59
115
|
...posterOf(version.surfaces),
|
|
116
|
+
...(drawsOnCanvas(version.surfaces) ? { canvas: true } : {}),
|
|
60
117
|
});
|
|
61
118
|
export const variantView = (post, opts = {}) => ({
|
|
62
119
|
postId: post.id,
|
|
@@ -71,12 +128,15 @@ export const variantView = (post, opts = {}) => ({
|
|
|
71
128
|
...(post.from === undefined ? {} : { from: post.from }),
|
|
72
129
|
...(post.prompt ? { prompt: post.prompt } : {}),
|
|
73
130
|
...(post.author === undefined ? {} : { author: post.author }),
|
|
131
|
+
...(post.amendedAt ? { amendedAt: post.amendedAt } : {}),
|
|
132
|
+
// Frame URLs carry it (`w`): an amended version keeps its number.
|
|
133
|
+
...(post.rewrites ? { rewrites: post.rewrites } : {}),
|
|
74
134
|
// A part with fills is a select knob on its part (fills.ts); declared knobs win.
|
|
75
135
|
...(slotsInSurfaces(post.surfaces).length || post.knobs
|
|
76
136
|
? { knobs: { ...slotKnobs(slotsInSurfaces(post.surfaces)), ...post.knobs } }
|
|
77
137
|
: {}),
|
|
78
138
|
...(slotsInSurfaces(post.surfaces).length ? { fills: slotsInSurfaces(post.surfaces) } : {}),
|
|
79
|
-
...(post.
|
|
139
|
+
...(post.description ? { description: post.description } : {}),
|
|
80
140
|
// Embedded components as they render now (server/embeds.ts); `publishedWith`
|
|
81
141
|
// is what this version rendered with when it was published.
|
|
82
142
|
...(opts.embeds?.get(post.id)
|
|
@@ -84,8 +144,11 @@ export const variantView = (post, opts = {}) => ({
|
|
|
84
144
|
: {}),
|
|
85
145
|
...(post.embeds.length ? { publishedWith: post.embeds } : {}),
|
|
86
146
|
...(post.forkedFrom ? { forkedFrom: post.forkedFrom } : {}),
|
|
87
|
-
...(post.
|
|
147
|
+
...(post.copiedFrom ? { copiedFrom: post.copiedFrom } : {}),
|
|
148
|
+
...(opts.kept && isKeptVariant(opts.kept, post) ? { kept: true } : {}),
|
|
88
149
|
...(post.acceptedVersion === undefined ? {} : { inUseVersion: post.acceptedVersion }),
|
|
150
|
+
...(changedTo(post) === undefined ? {} : { changedTo: changedTo(post) }),
|
|
151
|
+
...(post.archiveReason ? { archiveReason: post.archiveReason } : {}),
|
|
89
152
|
// The part names this variant's own markup marks, so the viewer can tell
|
|
90
153
|
// which variants render a part (Borrow) without the html bodies.
|
|
91
154
|
parts: partsInSurfaces(post.surfaces).map((p) => p.name),
|
|
@@ -101,97 +164,124 @@ export const variantView = (post, opts = {}) => ({
|
|
|
101
164
|
...(post.from === undefined ? {} : { from: post.from }),
|
|
102
165
|
...(post.prompt === undefined ? {} : { prompt: post.prompt }),
|
|
103
166
|
...(post.author === undefined ? {} : { author: post.author }),
|
|
167
|
+
...(post.amendedAt ? { amendedAt: post.amendedAt } : {}),
|
|
104
168
|
}),
|
|
105
169
|
...[...post.history].sort((a, b) => b.version - a.version).map(historyMetaView),
|
|
106
170
|
].map((row) => post.hiddenVersions?.includes(row.version) ? { ...row, hidden: true } : row),
|
|
107
171
|
}
|
|
108
172
|
: {}),
|
|
109
173
|
});
|
|
110
|
-
const stateOrder = (
|
|
111
|
-
// What the user put in use, per state, in the
|
|
174
|
+
const stateOrder = (design) => (design.states.length ? design.states : [null]);
|
|
175
|
+
// What the user put in use, per state, in the design's order; a state with
|
|
112
176
|
// nothing accepted is absent. Export and embeds resolve to exactly these.
|
|
113
|
-
export const inUseByState = (
|
|
177
|
+
export const inUseByState = (design, posts) => stateOrder(design).flatMap((state) => {
|
|
114
178
|
const p = posts.find((x) => x.state === state && x.status === "accepted");
|
|
115
179
|
return p ? [{ state, variant: p.variant, version: inUseVersion(p) }] : [];
|
|
116
180
|
});
|
|
117
181
|
// The parts the agent marked, per state, across the variants still in play.
|
|
118
|
-
export function partsByState(
|
|
119
|
-
return stateOrder(
|
|
182
|
+
export function partsByState(design, posts) {
|
|
183
|
+
return stateOrder(design).map((state) => ({
|
|
120
184
|
state,
|
|
121
185
|
parts: mergeParts(posts
|
|
122
186
|
.filter((p) => p.state === state && isLive(p.status))
|
|
123
187
|
.map((p) => partsInSurfaces(p.surfaces))),
|
|
124
188
|
}));
|
|
125
189
|
}
|
|
126
|
-
// Where a
|
|
190
|
+
// Where a design sits in the product and the code that implements it, only once
|
|
127
191
|
// declared, so the views of a project that names neither cost nothing.
|
|
128
|
-
export const placeOf = (
|
|
129
|
-
...(
|
|
130
|
-
...(
|
|
192
|
+
export const placeOf = (design) => ({
|
|
193
|
+
...(design.area ? { area: design.area } : {}),
|
|
194
|
+
...(design.source ? { source: design.source } : {}),
|
|
131
195
|
});
|
|
132
|
-
// What
|
|
133
|
-
|
|
134
|
-
|
|
196
|
+
// What a design's first state looks like in a list: what's in use, else what the agent
|
|
197
|
+
// recommends, else its first. Same rule as viewer/src/logic.ts screenPicture.
|
|
198
|
+
function thumbnail(design, posts) {
|
|
199
|
+
const first = stateOrder(design)[0];
|
|
135
200
|
const inState = posts.filter((p) => p.state === first);
|
|
201
|
+
const recommended = recommendedVariant(design.asks, first);
|
|
136
202
|
const pick = inState.find((p) => p.status === "accepted") ??
|
|
203
|
+
inState.find((p) => p.variant === recommended && isLive(p.status)) ??
|
|
137
204
|
inState.find((p) => p.status === "open") ??
|
|
138
205
|
inState[0] ??
|
|
139
206
|
posts[0];
|
|
140
207
|
if (!pick)
|
|
141
208
|
return null;
|
|
142
209
|
const surface = pick.surfaces.findIndex((s) => isSandboxedSurfaceKind(s.kind));
|
|
143
|
-
const version =
|
|
210
|
+
const version = currentVersion(pick);
|
|
144
211
|
const poster = posterAt(pick, version);
|
|
145
|
-
return {
|
|
212
|
+
return {
|
|
213
|
+
postId: pick.id,
|
|
214
|
+
surface: Math.max(surface, 0),
|
|
215
|
+
version,
|
|
216
|
+
...(poster ? { poster } : {}),
|
|
217
|
+
...(pick.rewrites ? { rewrites: pick.rewrites } : {}),
|
|
218
|
+
};
|
|
146
219
|
}
|
|
147
|
-
//
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
220
|
+
// Only a plan says so, so the views of everything drawn are unchanged.
|
|
221
|
+
const plannedOf = (design, variants) => isPlanned(design, variants) ? { planned: true } : {};
|
|
222
|
+
// Anything the user has yet to send. A stored draft can be an emptied one, which
|
|
223
|
+
// waits on nobody.
|
|
224
|
+
export const draftHolds = (draft) => !!draft &&
|
|
225
|
+
(draft.comments.length > 0 ||
|
|
226
|
+
Object.values(draft.answers).some((a) => !Array.isArray(a) || a.length > 0) ||
|
|
227
|
+
[draft.borrowed, draft.tuned, draft.others ?? {}, draft.askComments ?? {}].some((rec) => Object.keys(rec).length > 0));
|
|
228
|
+
export const designSummaryView = (design, posts) => {
|
|
229
|
+
const drafted = draftedCount(design);
|
|
152
230
|
return {
|
|
153
|
-
id:
|
|
154
|
-
project:
|
|
155
|
-
slug:
|
|
156
|
-
title:
|
|
157
|
-
kind:
|
|
158
|
-
...placeOf(
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
231
|
+
id: design.id,
|
|
232
|
+
project: design.project,
|
|
233
|
+
slug: design.slug,
|
|
234
|
+
title: design.title,
|
|
235
|
+
kind: design.kind,
|
|
236
|
+
...placeOf(design),
|
|
237
|
+
...plannedOf(design, posts.length),
|
|
238
|
+
// Text comes with a read of the design; a list only says there is some to read.
|
|
239
|
+
...(design.notes ? { hasNotes: true } : {}),
|
|
240
|
+
states: design.states,
|
|
241
|
+
stateCount: Math.max(design.states.length, 1),
|
|
162
242
|
variants: posts.length,
|
|
163
|
-
open: openCount(
|
|
243
|
+
open: openCount(design),
|
|
164
244
|
// Only once the user has started one, so a list with no drafts costs nothing.
|
|
165
245
|
...(drafted === null ? {} : { drafted }),
|
|
166
|
-
sessionId:
|
|
167
|
-
|
|
168
|
-
createdAt:
|
|
169
|
-
updatedAt:
|
|
170
|
-
thumbnail: thumbnail(
|
|
246
|
+
sessionId: design.sessionId,
|
|
247
|
+
archivedAt: design.archivedAt,
|
|
248
|
+
createdAt: design.createdAt,
|
|
249
|
+
updatedAt: design.updatedAt,
|
|
250
|
+
thumbnail: thumbnail(design, posts),
|
|
171
251
|
};
|
|
172
252
|
};
|
|
173
|
-
// One
|
|
253
|
+
// One design as anyone outside the viewer's own draft sees it: the draft is the
|
|
174
254
|
// user's unsent work and never leaves through this view.
|
|
175
|
-
export const
|
|
176
|
-
id:
|
|
177
|
-
project:
|
|
178
|
-
slug:
|
|
179
|
-
title:
|
|
180
|
-
kind:
|
|
181
|
-
...placeOf(
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
255
|
+
export const designDetailView = (design, posts, opts = {}) => ({
|
|
256
|
+
id: design.id,
|
|
257
|
+
project: design.project,
|
|
258
|
+
slug: design.slug,
|
|
259
|
+
title: design.title,
|
|
260
|
+
kind: design.kind,
|
|
261
|
+
...placeOf(design),
|
|
262
|
+
...(design.shortlist ? { shortlist: true } : {}),
|
|
263
|
+
// No agent has written to this shortlist yet: who its replies reach for now.
|
|
264
|
+
...(opts.repliesGoTo ? { repliesGoTo: opts.repliesGoTo } : {}),
|
|
265
|
+
...plannedOf(design, posts.length),
|
|
266
|
+
states: design.states,
|
|
267
|
+
...(design.notes ? { notes: design.notes } : {}),
|
|
268
|
+
...(Object.keys(design.stateOutlines).length ? { stateOutlines: design.stateOutlines } : {}),
|
|
269
|
+
...(design.answerAdditions.length ? { answerAdditions: design.answerAdditions } : {}),
|
|
270
|
+
asks: design.asks,
|
|
271
|
+
// By question id: the answers the user kept for later and hid, with why.
|
|
272
|
+
...(Object.keys(design.standings).length ? { standings: design.standings } : {}),
|
|
273
|
+
...(design.sets.length ? { sets: design.sets } : {}),
|
|
274
|
+
open: openCount(design),
|
|
275
|
+
knobs: design.knobs,
|
|
276
|
+
widths: design.widths,
|
|
277
|
+
sessionId: design.sessionId,
|
|
278
|
+
archivedAt: design.archivedAt,
|
|
279
|
+
...(design.archiveReason ? { archiveReason: design.archiveReason } : {}),
|
|
280
|
+
createdAt: design.createdAt,
|
|
281
|
+
updatedAt: design.updatedAt,
|
|
282
|
+
variants: ((kept) => posts.map((p) => variantView(p, { ...opts, kept })))(keptVariants(design, posts)),
|
|
283
|
+
inUse: inUseByState(design, posts),
|
|
284
|
+
parts: partsByState(design, posts),
|
|
195
285
|
// Every knob value the user has sent (answers' sets and tuning, later replies
|
|
196
286
|
// winning), never drafts. Later questions render on top of it.
|
|
197
287
|
settled: opts.settled ?? {},
|
|
@@ -200,26 +290,50 @@ export const sessionRowView = (session, postCount) => ({
|
|
|
200
290
|
...session,
|
|
201
291
|
postCount,
|
|
202
292
|
});
|
|
203
|
-
// One
|
|
204
|
-
// variants per state with status and lineage, and the
|
|
293
|
+
// One design as a node of the project tree (GET /api/projects/:name/tree): its
|
|
294
|
+
// variants per state with status and lineage, and the designs it embeds (`embeds`);
|
|
205
295
|
// `embeddedIn` is filled in once every node is known.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
296
|
+
// When it left the shelf: archived by hand, or with the last of its variants archived.
|
|
297
|
+
// Designs archived before the date was kept fall back on the design's last change.
|
|
298
|
+
function leftOf(design, posts) {
|
|
299
|
+
if (design.archivedAt)
|
|
300
|
+
return { leftAt: design.archivedAt };
|
|
301
|
+
if (!posts.length || posts.some((p) => isLive(p.status)))
|
|
302
|
+
return {};
|
|
303
|
+
const last = posts.reduce((t, p) => (p.archivedAt && p.archivedAt > t ? p.archivedAt : t), "");
|
|
304
|
+
return { leftAt: last || design.updatedAt };
|
|
305
|
+
}
|
|
306
|
+
export const treeNodeView = (design, posts, extra) => ({
|
|
307
|
+
id: design.id,
|
|
308
|
+
slug: design.slug,
|
|
309
|
+
title: design.title,
|
|
310
|
+
kind: design.kind,
|
|
311
|
+
...placeOf(design),
|
|
312
|
+
...(design.shortlist ? { shortlist: true } : {}),
|
|
313
|
+
...plannedOf(design, posts.length),
|
|
314
|
+
open: openCount(design),
|
|
315
|
+
// Any question ever asked, answered or not: it tells an idea from a document.
|
|
316
|
+
...(design.asks.length ? { asked: design.asks.length } : {}),
|
|
317
|
+
// Later than every variant: the user has spoken and it is the agent's turn.
|
|
318
|
+
...(extra.lastReplyAt ? { lastReplyAt: extra.lastReplyAt } : {}),
|
|
319
|
+
...(extra.lastSend ? { lastSend: extra.lastSend } : {}),
|
|
320
|
+
...(extra.drafting ? { drafting: true } : {}),
|
|
321
|
+
states: stateOrder(design),
|
|
322
|
+
widths: design.widths,
|
|
323
|
+
createdAt: design.createdAt,
|
|
324
|
+
updatedAt: design.updatedAt,
|
|
325
|
+
archivedAt: design.archivedAt,
|
|
326
|
+
...leftOf(design, posts),
|
|
327
|
+
...(design.archiveReason ? { archiveReason: design.archiveReason } : {}),
|
|
219
328
|
settled: extra.settled,
|
|
220
329
|
embeds: extra.embeds,
|
|
221
330
|
embeddedIn: [],
|
|
222
|
-
inUse: inUseByState(
|
|
331
|
+
inUse: inUseByState(design, posts),
|
|
332
|
+
// What the agent recommends where nothing is in use: a cover shows it.
|
|
333
|
+
recommended: stateOrder(design).flatMap((state) => {
|
|
334
|
+
const variant = recommendedVariant(design.asks, state);
|
|
335
|
+
return variant ? [{ state, variant }] : [];
|
|
336
|
+
}),
|
|
223
337
|
variants: posts.map((p) => ({
|
|
224
338
|
postId: p.id,
|
|
225
339
|
state: p.state,
|
|
@@ -227,13 +341,16 @@ export const treeNodeView = (mock, posts, extra) => ({
|
|
|
227
341
|
status: variantStatus(p.status),
|
|
228
342
|
version: p.version,
|
|
229
343
|
updatedAt: p.updatedAt,
|
|
344
|
+
...(p.rewrites ? { rewrites: p.rewrites } : {}),
|
|
230
345
|
surface: p.surfaces.findIndex((x) => isSandboxedSurfaceKind(x.kind)),
|
|
231
346
|
...posterOf(p.surfaces),
|
|
232
347
|
...inUsePoster(p),
|
|
233
|
-
...(p
|
|
348
|
+
...coverVersion(p),
|
|
349
|
+
...(p.description && !extra.noDescriptions ? { description: p.description } : {}),
|
|
234
350
|
...(p.forkedFrom ? { forkedFrom: p.forkedFrom } : {}),
|
|
235
|
-
...(p.starred ? { starred: true } : {}),
|
|
236
351
|
...(p.acceptedVersion === undefined ? {} : { inUseVersion: p.acceptedVersion }),
|
|
352
|
+
...(changedTo(p) === undefined ? {} : { changedTo: changedTo(p) }),
|
|
353
|
+
...(p.archiveReason ? { archiveReason: p.archiveReason } : {}),
|
|
237
354
|
...(extra.embedViews.get(p.id) ? { embedsKey: extra.embedViews.get(p.id).key } : {}),
|
|
238
355
|
})),
|
|
239
356
|
});
|
package/dist/server/app.d.ts
CHANGED
|
@@ -30,6 +30,10 @@ export interface AppOptions {
|
|
|
30
30
|
maxHoldConnections?: number;
|
|
31
31
|
executor?: Executor;
|
|
32
32
|
runLimits?: Partial<RunLimits>;
|
|
33
|
+
networkHosts?: () => {
|
|
34
|
+
localOnly: boolean;
|
|
35
|
+
hosts: string[];
|
|
36
|
+
};
|
|
33
37
|
log?: LogSink;
|
|
34
38
|
}
|
|
35
39
|
export interface LatestRelease {
|
|
@@ -38,12 +42,13 @@ export interface LatestRelease {
|
|
|
38
42
|
}
|
|
39
43
|
export interface CommentWait {
|
|
40
44
|
sessionId?: string;
|
|
41
|
-
|
|
45
|
+
designId?: string;
|
|
42
46
|
postId?: string;
|
|
43
47
|
author?: string;
|
|
44
48
|
afterSeq?: number;
|
|
45
49
|
waitSeconds: number;
|
|
46
50
|
agent?: boolean;
|
|
51
|
+
peek?: boolean;
|
|
47
52
|
}
|
|
48
53
|
export interface FlowResult {
|
|
49
54
|
status: number;
|
|
@@ -56,4 +61,4 @@ export interface FlowContext {
|
|
|
56
61
|
request?: Request;
|
|
57
62
|
signal?: AbortSignal;
|
|
58
63
|
}
|
|
59
|
-
export declare function createApp({ store, viewerHtml, setupText, topics, packs, userRules, authenticate, authToken, basePath, publicRead, screenshots, version, upgradeCommand, renderRev, fetchLatestRelease, onEvent, maxHoldConnections, executor, runLimits, log, }: AppOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|
|
64
|
+
export declare function createApp({ store, viewerHtml, setupText, topics, packs, userRules, authenticate, authToken, basePath, publicRead, screenshots, version, upgradeCommand, renderRev, fetchLatestRelease, onEvent, maxHoldConnections, executor, runLimits, networkHosts, log, }: AppOptions): Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
|