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