@book.dev/sdk 3.8.0 → 3.9.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 (53) hide show
  1. package/dist/ai.d.ts +12 -2
  2. package/dist/ai.js.map +1 -1
  3. package/dist/blockCatalogue.d.ts +560 -0
  4. package/dist/blockCatalogue.js +336 -0
  5. package/dist/blockCatalogue.js.map +1 -0
  6. package/dist/bookFolder.d.ts +9 -1
  7. package/dist/bookFolder.js +64 -2
  8. package/dist/bookFolder.js.map +1 -1
  9. package/dist/client.d.ts +22 -2
  10. package/dist/client.js +6 -2
  11. package/dist/client.js.map +1 -1
  12. package/dist/content.d.ts +40 -1
  13. package/dist/content.js +29 -7
  14. package/dist/content.js.map +1 -1
  15. package/dist/forwarding/forwardingClient.d.ts +68 -2
  16. package/dist/forwarding/forwardingClient.js +126 -12
  17. package/dist/forwarding/forwardingClient.js.map +1 -1
  18. package/dist/forwarding/index.d.ts +2 -1
  19. package/dist/forwarding/index.js +2 -1
  20. package/dist/forwarding/index.js.map +1 -1
  21. package/dist/forwarding/namespacedKeyStore.d.ts +52 -0
  22. package/dist/forwarding/namespacedKeyStore.js +99 -0
  23. package/dist/forwarding/namespacedKeyStore.js.map +1 -0
  24. package/dist/index.d.ts +10 -5
  25. package/dist/index.js +10 -5
  26. package/dist/index.js.map +1 -1
  27. package/dist/ledger.d.ts +29 -0
  28. package/dist/ledger.js +43 -0
  29. package/dist/ledger.js.map +1 -1
  30. package/dist/ledgerExportSection.d.ts +160 -0
  31. package/dist/ledgerExportSection.js +594 -0
  32. package/dist/ledgerExportSection.js.map +1 -0
  33. package/dist/orderKeys.d.ts +36 -0
  34. package/dist/orderKeys.js +88 -0
  35. package/dist/orderKeys.js.map +1 -0
  36. package/dist/plugins.d.ts +76 -4
  37. package/dist/plugins.js +95 -12
  38. package/dist/plugins.js.map +1 -1
  39. package/dist/provenance.d.ts +13 -0
  40. package/dist/registryClient.d.ts +227 -0
  41. package/dist/registryClient.js +397 -0
  42. package/dist/registryClient.js.map +1 -0
  43. package/dist/routes.d.ts +9 -0
  44. package/dist/routes.js +9 -0
  45. package/dist/routes.js.map +1 -1
  46. package/dist/suggestions.d.ts +12 -2
  47. package/dist/tableSnapshot.d.ts +233 -0
  48. package/dist/tableSnapshot.js +680 -0
  49. package/dist/tableSnapshot.js.map +1 -0
  50. package/dist/templates.d.ts +8 -0
  51. package/dist/templates.js +7 -2
  52. package/dist/templates.js.map +1 -1
  53. package/package.json +1 -1
@@ -0,0 +1,336 @@
1
+ /**
2
+ * The block-type catalogue — the ONE types-only description of every block the
3
+ * editor can render, shared by every layer that must reason about block types
4
+ * without importing React:
5
+ *
6
+ * - the UI's block model derives `BlockType`, `TEXT_BLOCKS` and
7
+ * `CONTAINER_BLOCKS` FROM this file (packages/ui/src/blockeditor/model.ts),
8
+ * so the core union cannot drift from the catalogue by construction;
9
+ * - the UI's runtime registry (registry.tsx + kit) is pinned to the `kit`
10
+ * entries by a drift-guard test (packages/ui/src/blockeditor/
11
+ * registryCatalogue.test.tsx) that registers every built-in custom block and
12
+ * fails when the registry and the catalogue disagree in either direction;
13
+ * - the server agent and the MCP server validate `add_blocks` /
14
+ * `create_artifact_page` / `update_block_props` payloads against it and
15
+ * serve it via their `list_block_types` tools.
16
+ *
17
+ * History: before this file the agent kept a hand-written `KNOWN_BLOCK_TYPES`
18
+ * and the MCP server a hand-written `ARTIFACT_TYPES`; the two disagreed with
19
+ * each other AND with the real registry (table/row/cell, image, notes, and
20
+ * several kit blocks were missing from one or both). Those lists are gone —
21
+ * everything reads this catalogue.
22
+ *
23
+ * Plugin blocks are NOT enumerated here (they are installed per library, not
24
+ * compiled in). They are namespaced `<pluginId>/<type>` (plugins/api.ts), a
25
+ * plugin declares its block types in its manifest (`PluginManifest.blocks`),
26
+ * and validators accept them by pattern + an installed-plugin lookup where one
27
+ * is available — see {@link isPluginBlockType} and {@link findUnknownBlockType}.
28
+ */
29
+ const CATALOGUE_LITERAL = [
30
+ // ── Core text + structure ──────────────────────────────────────────────────
31
+ { type: 'paragraph', category: 'core', nature: 'text', hint: 'plain rich text' },
32
+ { type: 'heading', category: 'core', nature: 'text', props: { level: 'number' }, hint: '{level:1|2|3}' },
33
+ { type: 'list', category: 'core', nature: 'text', props: { kind: 'string' }, hint: '{kind:"bullet"|"number"} — one block per item' },
34
+ { type: 'todo', category: 'core', nature: 'text', props: { checked: 'boolean' }, hint: '{checked?}' },
35
+ { type: 'quote', category: 'core', nature: 'text' },
36
+ { type: 'callout', category: 'core', nature: 'text', props: { variant: 'string' }, hint: '{variant:"info"|"warn"|"success"}' },
37
+ { type: 'code', category: 'core', nature: 'text', props: { language: 'string', live: 'boolean', name: 'string', collapsed: 'boolean' }, hint: '{language?,live?,name?,collapsed?}' },
38
+ // A speaker note: editable on the page, shown only in the presenter view.
39
+ { type: 'notes', category: 'core', nature: 'text', hint: 'speaker note — presenter view only, never exported' },
40
+ { type: 'divider', category: 'core', nature: 'void' },
41
+ // ── Core media leaves ──────────────────────────────────────────────────────
42
+ // `width` is a CSS length STRING (the editor writes percentages: '30%',
43
+ // '60%', `${pct}%` — see ui/blockeditor/imageBlock.ts + ImageBlockView).
44
+ { type: 'image', category: 'core', nature: 'void', props: { assetId: 'string', src: 'string', alt: 'string', width: 'string' }, hint: '{assetId|src,alt?,width?:"60%"}' },
45
+ { type: 'htmlArtifact', category: 'core', nature: 'void', props: { assetId: 'string', name: 'string', height: 'number' }, hint: 'sandboxed HTML document {assetId,name?,height?}' },
46
+ // ── Core containers (children hold ordinary blocks) ────────────────────────
47
+ { type: 'columns', category: 'core', nature: 'container', hint: 'side-by-side layout → column children (spans sum to 12)' },
48
+ { type: 'column', category: 'core', nature: 'container', parent: 'columns', props: { span: 'number' }, hint: '{span:1-12}' },
49
+ { type: 'table', category: 'core', nature: 'container', hint: 'table → row → cell; give every row the same number of cells' },
50
+ { type: 'row', category: 'core', nature: 'container', parent: 'table', props: { header: 'boolean' }, hint: '{header?} for the header row' },
51
+ { type: 'cell', category: 'core', nature: 'text', parent: 'row', hint: 'one table cell (rich text)' },
52
+ { type: 'group', category: 'core', nature: 'container', props: { name: 'string', locked: 'boolean' }, hint: '{name?,locked?}' },
53
+ { type: 'tabs', category: 'core', nature: 'container', hint: 'tabs → tab children' },
54
+ { type: 'tab', category: 'core', nature: 'container', parent: 'tabs', props: { label: 'string' }, hint: '{label}' },
55
+ { type: 'accordion', category: 'core', nature: 'container', props: { name: 'string', gated: 'boolean' }, hint: '{name?,gated?} → accordionsection children' },
56
+ { type: 'accordionsection', category: 'core', nature: 'container', parent: 'accordion', props: { label: 'string', collapsed: 'boolean' }, hint: '{label,collapsed?}' },
57
+ // ── Kit inputs (publish a named value into the reactive scope) ─────────────
58
+ { type: 'slider', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', value: 'number', min: 'number', max: 'number', step: 'number' }, hint: '{name,label?,value,min,max,step?}' },
59
+ { type: 'number', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', value: 'number', min: 'number', max: 'number', step: 'number' }, hint: '{name,label?,value,min?,max?,step?}' },
60
+ { type: 'textfield', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', value: 'string', placeholder: 'string' }, hint: '{name,label?,value?,placeholder?}' },
61
+ { type: 'longtext', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', value: 'string', placeholder: 'string' }, hint: '{name,label?,value?,placeholder?}' },
62
+ { type: 'richtext', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', runs: 'array' }, hint: '{name,label?} — formatted long text' },
63
+ { type: 'toggle', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', value: 'boolean' }, hint: '{name,label?,value:boolean}' },
64
+ { type: 'radio', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', opts: 'array' }, hint: '{name,label?,value,opts:[{label,value}]}' },
65
+ { type: 'dropdown', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', opts: 'array' }, hint: '{name,label?,value,opts:[{label,value}]}' },
66
+ { type: 'checklist', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', selected: 'array', opts: 'array' }, hint: '{name,label?,selected:[],opts}' },
67
+ { type: 'choicecards', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', opts: 'array', multi: 'boolean' }, hint: '{name,label?,value,opts:[{label,value,icon?}],multi?}' },
68
+ { type: 'searchselect', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', opts: 'array', multi: 'boolean' }, hint: '{name,label?,value,opts,multi?}' },
69
+ { type: 'tagfield', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string', selected: 'array', freeEntry: 'boolean' }, hint: '{name,label?,selected:[],freeEntry?}' },
70
+ { type: 'location', category: 'kit', nature: 'void', kitValue: true, props: { name: 'string', label: 'string' }, hint: '{name,label?}' },
71
+ // ── Kit actions + reactive display (consume the scope via `source`) ────────
72
+ { type: 'actionbutton', category: 'kit', nature: 'void', props: { btnlabel: 'string', action: 'string', target: 'string', amount: 'number', url: 'string' }, hint: '{btnlabel,action:"increment"|"set"|"toggle"|"link",target?,amount?,url?}' },
73
+ { type: 'kitchart', category: 'kit', nature: 'void', props: { kind: 'string', title: 'string', labels: 'string', source: 'string' }, hint: '{kind:"line"|"area"|"bar"|"pie"|"donut"|"scatter"|"funnel",title?,labels?,source}' },
74
+ { type: 'statuslight', category: 'kit', nature: 'void', props: { label: 'string', source: 'string', okAt: 'number', warnAt: 'number' }, hint: '{label?,source,okAt,warnAt}' },
75
+ { type: 'progressbar', category: 'kit', nature: 'void', props: { label: 'string', source: 'string', max: 'number', format: 'string' }, hint: '{label?,source,max?,format?}' },
76
+ { type: 'formula', category: 'kit', nature: 'void', props: { source: 'string' }, hint: '{source} — a JS expression over input names' },
77
+ { type: 'linkcard', category: 'kit', nature: 'void', props: { title: 'string', url: 'string', description: 'string' }, hint: '{title,url,description?}' },
78
+ { type: 'tooltipcard', category: 'kit', nature: 'void', props: { term: 'string', tip: 'string' }, hint: '{term,tip}' },
79
+ { type: 'dbview', category: 'kit', nature: 'void', props: { pageId: 'string' }, hint: 'embedded live database view {pageId} — the page hosting the database' },
80
+ ];
81
+ /** The catalogue, widened to the interface type for consumers (the `as const`
82
+ * literal view above exists only for {@link CoreBlockType} extraction). */
83
+ export const BLOCK_TYPE_CATALOGUE = CATALOGUE_LITERAL;
84
+ const byType = new Map(BLOCK_TYPE_CATALOGUE.map((e) => [e.type, e]));
85
+ /** The catalogue entry for a type, or undefined (plugin/unknown types). */
86
+ export const blockTypeInfo = (type) => byType.get(type);
87
+ /** Every catalogued (core + kit) type id. */
88
+ export const KNOWN_BLOCK_TYPE_IDS = new Set(byType.keys());
89
+ /** Core types whose `children` hold ordinary blocks. */
90
+ export const CONTAINER_BLOCK_TYPES = new Set(BLOCK_TYPE_CATALOGUE.filter((e) => e.nature === 'container').map((e) => e.type));
91
+ /** Core types that carry editable rich text. */
92
+ export const TEXT_BLOCK_TYPES = new Set(BLOCK_TYPE_CATALOGUE.filter((e) => e.nature === 'text').map((e) => e.type));
93
+ /** Child-only types → the one container each must sit directly inside. */
94
+ export const CHILD_ONLY_PARENT = Object.fromEntries(BLOCK_TYPE_CATALOGUE.filter((e) => e.parent).map((e) => [e.type, e.parent]));
95
+ /** Props every block accepts regardless of type (block chrome, not content). */
96
+ const COMMON_PROPS = { bg: 'string' };
97
+ // ── Plugin block types ─────────────────────────────────────────────────────────
98
+ /**
99
+ * Whether `type` is plugin-NAMESPACED: `<pluginId>/<blockType>` (plugins/api.ts
100
+ * prefixes every registered plugin block with its manifest id). Pattern only —
101
+ * says nothing about whether such a plugin is installed.
102
+ */
103
+ export const isPluginBlockType = (type) => /^[^\s/]+\/[^\s/]/.test(type);
104
+ /** The `<pluginId>` prefix of a plugin-namespaced type, or null. */
105
+ export const pluginIdOfBlockType = (type) => isPluginBlockType(type) ? type.slice(0, type.indexOf('/')) : null;
106
+ /**
107
+ * The first block type (anywhere in the tree) that is neither catalogued nor an
108
+ * acceptable plugin type, or null when every type is fine.
109
+ *
110
+ * Plugin types (`<pluginId>/<type>`) validate by pattern, then — when the
111
+ * caller CAN enumerate installed plugins — by an installed-plugin lookup on the
112
+ * id prefix. Pass `installedPluginIds: undefined` when no plugin listing is
113
+ * available (older server, no client): pattern-valid plugin types are then
114
+ * accepted opaquely, as the apply layer always has (never crash on them).
115
+ */
116
+ export function findUnknownBlockType(blocks, opts = {}, depth = 1) {
117
+ for (const raw of blocks) {
118
+ if (!raw || typeof raw !== 'object')
119
+ return { type: '(not a block)', reason: 'unknown' };
120
+ const b = raw;
121
+ const type = String(b.type ?? '');
122
+ if (!byType.has(type)) {
123
+ if (!isPluginBlockType(type))
124
+ return { type: type || '(missing type)', reason: 'unknown' };
125
+ const pluginId = pluginIdOfBlockType(type);
126
+ if (opts.installedPluginIds && !opts.installedPluginIds.has(pluginId)) {
127
+ return { type, reason: 'plugin-not-installed' };
128
+ }
129
+ }
130
+ // Depth ceiling: never let a pathological payload exhaust the stack. Types
131
+ // below this are left to {@link blockTreeError}, which rejects any payload
132
+ // deeper than MAX_BLOCK_DEPTH anyway (callers run both checks).
133
+ if (Array.isArray(b.children) && depth < TYPE_WALK_MAX_DEPTH) {
134
+ const nested = findUnknownBlockType(b.children, opts, depth + 1);
135
+ if (nested)
136
+ return nested;
137
+ }
138
+ }
139
+ return null;
140
+ }
141
+ /** Recursion ceiling for {@link findUnknownBlockType} — generous headroom over
142
+ * {@link MAX_BLOCK_DEPTH}, purely a stack-exhaustion guard. */
143
+ const TYPE_WALK_MAX_DEPTH = 64;
144
+ /** A caller-facing message for an {@link UnknownBlockType}, or null. */
145
+ export function unknownBlockTypeMessage(bad) {
146
+ if (!bad)
147
+ return null;
148
+ return bad.reason === 'plugin-not-installed'
149
+ ? `Block type "${bad.type}" belongs to a plugin that is not installed in this library. Use list_block_types to see the installed plugins' blocks.`
150
+ : `Unsupported block type "${bad.type}". Use list_block_types for the full catalogue of core, kit, and installed plugin block types.`;
151
+ }
152
+ /**
153
+ * Max nesting depth for one write. Deep enough for every real layout —
154
+ * `columns → column → table → row → cell → group → tabs → tab → paragraph` is
155
+ * 9 with room to spare at 8 for the practical trees — and shallow enough that a
156
+ * runaway/recursive model response can't build a pathological tree the editor
157
+ * then has to render.
158
+ */
159
+ export const MAX_BLOCK_DEPTH = 8;
160
+ /**
161
+ * Max TOTAL blocks (all levels) in one write. A 20×8 table is 180 nodes, so
162
+ * this fits any sane single write while bounding one request's cost; a bigger
163
+ * document is several appends.
164
+ */
165
+ export const MAX_BLOCK_NODES = 400;
166
+ /**
167
+ * Validate a nested block payload's STRUCTURE against the catalogue: a
168
+ * `children` array only on a container-nature type (anything else silently
169
+ * drops the children at apply time), a child-only type only directly inside its
170
+ * matching container, every `table` square (each `row` holding the same number
171
+ * of `cell` children — a ragged table renders holes), and the depth/node caps.
172
+ * Returns an actionable message, or null when the payload is fine.
173
+ *
174
+ * Block TYPES are not this function's business ({@link findUnknownBlockType}
175
+ * covers those) — plugin/unknown leaf types walk through untouched.
176
+ */
177
+ export function blockTreeError(blocks, opts = {}) {
178
+ const maxDepth = opts.maxDepth ?? MAX_BLOCK_DEPTH;
179
+ const maxNodes = opts.maxNodes ?? MAX_BLOCK_NODES;
180
+ let count = 0;
181
+ let deepest = 0;
182
+ let deepestPath = '';
183
+ let structural = null;
184
+ const walk = (list, depth, path, parentType) => {
185
+ if (depth > deepest) {
186
+ deepest = depth;
187
+ deepestPath = path;
188
+ }
189
+ // Once past the cap the payload is already refused ("nested too deeply");
190
+ // stop descending so a pathologically deep tree (tens of thousands of
191
+ // levels) reports cleanly instead of exhausting the stack.
192
+ if (depth > maxDepth)
193
+ return;
194
+ for (const [i, raw] of list.entries()) {
195
+ count += 1;
196
+ if (!raw || typeof raw !== 'object')
197
+ continue; // findUnknownBlockType reports these
198
+ const b = raw;
199
+ const type = String(b.type ?? '');
200
+ const here = path ? `${path} > ${type}` : type;
201
+ const children = Array.isArray(b.children) ? b.children : null;
202
+ const hasChildren = children !== null && children.length > 0;
203
+ if (structural === null) {
204
+ const needs = CHILD_ONLY_PARENT[type];
205
+ if (needs && parentType !== needs) {
206
+ structural = parentType
207
+ ? `A "${type}" block must be a direct child of a "${needs}" block, not a "${parentType}" block (at "${here}").`
208
+ : `A "${type}" block can't be top-level — it belongs directly inside a "${needs}" block (at "${here}").`;
209
+ }
210
+ else if (hasChildren && !CONTAINER_BLOCK_TYPES.has(type)) {
211
+ structural = `A "${type}" block can't hold children — only container blocks (${[...CONTAINER_BLOCK_TYPES].join(', ')}) do (at "${here}"). The nested blocks would be dropped.`;
212
+ }
213
+ else if (type === 'table' && hasChildren) {
214
+ structural = raggedTableError(children, here);
215
+ }
216
+ }
217
+ if (hasChildren)
218
+ walk(children, depth + 1, `${here}[${i}]`, type);
219
+ }
220
+ };
221
+ walk(blocks, 1, '', null);
222
+ if (structural)
223
+ return structural;
224
+ if (deepest > maxDepth) {
225
+ return `Blocks are nested too deeply: ${deepest} levels (max ${maxDepth}) at "${deepestPath}". Flatten the payload or split it across calls.`;
226
+ }
227
+ if (count > maxNodes) {
228
+ return `Too many blocks in one call: ${count} (max ${maxNodes}, counting nested children). Split it into several calls.`;
229
+ }
230
+ return null;
231
+ }
232
+ /** Cell-count consistency for one table's rows: every `row` must hold the same
233
+ * number of `cell` children (the first row sets the width). Null when square. */
234
+ function raggedTableError(rows, path) {
235
+ let width = -1;
236
+ for (const [i, raw] of rows.entries()) {
237
+ if (!raw || typeof raw !== 'object')
238
+ continue;
239
+ const b = raw;
240
+ if (String(b.type ?? '') !== 'row')
241
+ continue;
242
+ const cells = (Array.isArray(b.children) ? b.children : []).filter((c) => c && typeof c === 'object' && String(c.type ?? '') === 'cell').length;
243
+ if (width === -1)
244
+ width = cells;
245
+ else if (cells !== width) {
246
+ return `Table rows must all have the same number of cells: row ${i + 1} has ${cells}, but the first row has ${width} (at "${path}"). Pad the short rows with empty cells.`;
247
+ }
248
+ }
249
+ return null;
250
+ }
251
+ /**
252
+ * Per-type prop VALUE validation for one block's props patch. Permissive but
253
+ * typed: only props the catalogue declares for `type` (plus the common block
254
+ * props) are checked; unknown props pass, `null` passes (it removes the key),
255
+ * and plugin/unknown types pass entirely. Returns a message, or null.
256
+ */
257
+ export function invalidBlockProps(type, props) {
258
+ const info = byType.get(type);
259
+ if (!info)
260
+ return null;
261
+ const declared = { ...COMMON_PROPS, ...info.props };
262
+ for (const [key, value] of Object.entries(props)) {
263
+ // Own-property gate: a prop named after an Object.prototype member
264
+ // (`toString`, `constructor`, …) must read as UNDECLARED, not as the
265
+ // inherited function. (hasOwnProperty.call — the SDK targets pre-ES2022.)
266
+ const expect = Object.prototype.hasOwnProperty.call(declared, key) ? declared[key] : undefined;
267
+ if (!expect || value === null || value === undefined)
268
+ continue;
269
+ const actual = Array.isArray(value) ? 'array' : typeof value;
270
+ if (actual !== expect) {
271
+ return `Prop "${key}" of a "${type}" block must be ${expect === 'array' ? 'an array' : `a ${expect}`} — got ${actual} (${clipJson(value)}).`;
272
+ }
273
+ }
274
+ return null;
275
+ }
276
+ const clipJson = (v) => {
277
+ const s = JSON.stringify(v) ?? String(v);
278
+ return s.length > 40 ? `${s.slice(0, 40)}…` : s;
279
+ };
280
+ /** One `list_block_types` line for a catalogue entry. */
281
+ function entryLine(e) {
282
+ const bits = [
283
+ `- ${e.type} (${e.category}, ${e.nature})`,
284
+ e.nature === 'container' ? `children: yes${CHILD_ONLY_PARENT[e.type] ? ` — only inside "${CHILD_ONLY_PARENT[e.type]}"` : ''}` : CHILD_ONLY_PARENT[e.type] ? `only inside "${CHILD_ONLY_PARENT[e.type]}"` : '',
285
+ e.kitValue ? 'publishes a kit value' : '',
286
+ e.props ? `props: ${Object.entries(e.props).map(([k, t]) => `${k}:${t}`).join(', ')}` : '',
287
+ e.hint ? `— ${e.hint}` : '',
288
+ ];
289
+ return bits.filter(Boolean).join(' · ');
290
+ }
291
+ /**
292
+ * The full catalogue as `list_block_types` text: every core + kit entry, then
293
+ * one `plugin` entry per block each installed plugin DECLARES in its manifest
294
+ * (`PluginManifest.blocks`). Pass the installed plugins where a listing is
295
+ * available; omit it and the plugin section says so instead of guessing.
296
+ */
297
+ export function blockCatalogueText(plugins) {
298
+ const lines = [
299
+ 'Block types (type · category, nature · children/kit-value · declared props):',
300
+ ...BLOCK_TYPE_CATALOGUE.map((e) => entryLine(e)),
301
+ ];
302
+ if (!plugins) {
303
+ lines.push('Plugin blocks: installed-plugin listing unavailable — plugin types (`<pluginId>/<type>`) are accepted as-is.');
304
+ return lines.join('\n');
305
+ }
306
+ const pluginLines = [];
307
+ for (const p of plugins) {
308
+ for (const b of p.manifest.blocks ?? []) {
309
+ pluginLines.push(`- ${p.manifest.id}/${b.type} (plugin: ${p.manifest.name ?? p.manifest.id}${p.enabled === false ? ', disabled' : ''}, void)${b.description ? ` — ${b.description}` : ''}`);
310
+ }
311
+ }
312
+ lines.push(pluginLines.length ? 'Installed plugin blocks:' : 'Installed plugin blocks: none.');
313
+ lines.push(...pluginLines);
314
+ return lines.join('\n');
315
+ }
316
+ /**
317
+ * The `add_blocks` tool description, generated from the catalogue so the type
318
+ * list in the model's guidance can never drift from what validation accepts
319
+ * (this replaces the old hand-written BLOCK_CATALOGUE prose in the agent).
320
+ */
321
+ export function addBlocksGuidance() {
322
+ const hinted = (e) => (e.hint ? `${e.type} ${e.hint}` : e.type);
323
+ const core = BLOCK_TYPE_CATALOGUE.filter((e) => e.category === 'core');
324
+ const kit = BLOCK_TYPE_CATALOGUE.filter((e) => e.category === 'kit');
325
+ return [
326
+ 'Append rich blocks to a page — text, layouts, tables, media, interactive inputs, and charts. User approves before they are added.',
327
+ 'Each block is {type, text?, props?, children?}. `text` is a plain string (or rich runs [{"t","a":{b,i,u,s,c,a}}]); `children` nests blocks inside containers. Call list_block_types for the full catalogue including installed plugin blocks.',
328
+ `TEXT: ${core.filter((e) => e.nature === 'text' && !e.parent).map(hinted).join('; ')}.`,
329
+ `CONTAINERS (use children): ${core.filter((e) => e.nature === 'container' || e.parent).map(hinted).join('; ')}. Give every table row the same number of cells.`,
330
+ `MEDIA/OTHER: ${core.filter((e) => e.nature === 'void').map(hinted).join('; ')}.`,
331
+ `INPUTS (each publishes props.name into the reactive scope): ${kit.filter((e) => e.kitValue).map(hinted).join('; ')}.`,
332
+ `REACTIVE DISPLAY/ACTIONS (props.source is a JS expression over input names): ${kit.filter((e) => !e.kitValue).map(hinted).join('; ')}.`,
333
+ 'Example: a budget widget → [{"type":"heading","text":"Budget","props":{"level":2}},{"type":"columns","children":[{"type":"column","props":{"span":5},"children":[{"type":"slider","props":{"name":"spent","label":"Spent","value":80,"min":0,"max":200}},{"type":"number","props":{"name":"budget","label":"Budget","value":120}}]},{"type":"column","props":{"span":7},"children":[{"type":"kitchart","props":{"kind":"bar","title":"Spent vs budget","labels":"Spent, Budget","source":"[spent, budget]"}},{"type":"statuslight","props":{"label":"On track","source":"budget - spent","okAt":0,"warnAt":-20}}]}]}].',
334
+ ].join('\n');
335
+ }
336
+ //# sourceMappingURL=blockCatalogue.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blockCatalogue.js","sourceRoot":"","sources":["../src/blockCatalogue.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import type { StoredPage } from './types';
2
2
  import type { StoredDatabase } from './database';
3
+ import type { LedgerExportSection } from './ledgerExportSection';
3
4
  /**
4
5
  * Whole-space → folder-of-files serialisation, shared by every "dump my books
5
6
  * to a folder" surface: the desktop's native folder export and the web app's
@@ -48,11 +49,18 @@ export interface LibraryIsland {
48
49
  version: 1;
49
50
  rootId: string;
50
51
  space: LibrarySnapshot;
52
+ /** LX-2: the embedded ledger records, when the export opted in (see
53
+ * {@link LedgerExportSection} for the shape + authorization contract). */
54
+ ledger?: LedgerExportSection;
51
55
  }
52
- /** Wrap a whole-space bundle as its source-island `<script>` (versioned, escaped). */
56
+ /** Wrap a whole-space bundle as its source-island `<script>` (versioned, escaped).
57
+ * `opts.ledger` additionally embeds the LX-2 ledger records — pass it ONLY with
58
+ * a section captured through the exporting principal's own read paths
59
+ * ({@link gatherLedgerExportSection}). */
53
60
  export declare function libraryIslandScript(rootId: string, space: LibrarySnapshot, opts?: {
54
61
  attrs?: string;
55
62
  indent?: string;
63
+ ledger?: LedgerExportSection;
56
64
  }): string;
57
65
  /**
58
66
  * Read a site export's space island back, or `null` when absent/corrupt.
@@ -14,10 +14,67 @@ export const SPACE_BUNDLE_FILE = 'openbook.library.json';
14
14
  * never emits it.
15
15
  */
16
16
  export const LEGACY_SPACE_BUNDLE_FILE = 'openbook.space.json';
17
- /** Wrap a whole-space bundle as its source-island `<script>` (versioned, escaped). */
17
+ /** Wrap a whole-space bundle as its source-island `<script>` (versioned, escaped).
18
+ * `opts.ledger` additionally embeds the LX-2 ledger records — pass it ONLY with
19
+ * a section captured through the exporting principal's own read paths
20
+ * ({@link gatherLedgerExportSection}). */
18
21
  export function libraryIslandScript(rootId, space, opts = {}) {
19
22
  // Writer emits ONLY the new `library` key; the reader dual-reads for back-compat.
20
- return islandScript({ version: 1, rootId, library: space }, opts);
23
+ return islandScript({ version: 1, rootId, library: space, ...(opts.ledger ? { ledger: opts.ledger } : {}) }, opts);
24
+ }
25
+ /** Keys that must never survive a parse of untrusted island JSON: an own
26
+ * `__proto__`/`constructor`/`prototype` data property (JSON.parse creates them
27
+ * as plain own properties) becomes a prototype-pollution gadget the moment a
28
+ * consumer deep-merges or `Object.assign`s the settings into a live object. */
29
+ const UNSAFE_KEYS = new Set(['__proto__', 'constructor', 'prototype']);
30
+ /** Deep-copy a JSON value, dropping every {@link UNSAFE_KEYS} property. */
31
+ function stripUnsafeKeys(value) {
32
+ if (Array.isArray(value))
33
+ return value.map((v) => stripUnsafeKeys(v));
34
+ if (value !== null && typeof value === 'object') {
35
+ const out = {};
36
+ for (const key of Object.keys(value)) {
37
+ if (UNSAFE_KEYS.has(key))
38
+ continue;
39
+ out[key] = stripUnsafeKeys(value[key]);
40
+ }
41
+ return out;
42
+ }
43
+ return value;
44
+ }
45
+ const isPlainObject = (v) => v !== null && typeof v === 'object' && !Array.isArray(v);
46
+ /**
47
+ * Deep-validate the LX-2 `ledger` island key (the parse boundary LX-4's import
48
+ * inherits — island text is UNTRUSTED input): `settings` a plain object (with
49
+ * `__proto__`/`constructor`/`prototype` keys stripped, recursively), `library`
50
+ * a real {@link LibrarySnapshot} (pages[] of records with a string `id`,
51
+ * databases[] of records with string `id` + `pageId`), and `auditHead` either
52
+ * `null` or `{seq: number, hash: string}`. Any mismatch drops the whole key
53
+ * (returns `null`) — never a throw, and never a section import code can't trust.
54
+ */
55
+ function readLedgerSection(raw) {
56
+ if (!isPlainObject(raw))
57
+ return null;
58
+ const { settings, library, auditHead } = raw;
59
+ if (!isPlainObject(settings))
60
+ return null;
61
+ if (!isPlainObject(library) || !Array.isArray(library.pages) || !Array.isArray(library.databases))
62
+ return null;
63
+ if (!library.pages.every((p) => isPlainObject(p) && typeof p.id === 'string'))
64
+ return null;
65
+ if (!library.databases.every((d) => isPlainObject(d) && typeof d.id === 'string' && typeof d.pageId === 'string'))
66
+ return null;
67
+ let head = null;
68
+ if (auditHead !== null && auditHead !== undefined) {
69
+ if (!isPlainObject(auditHead) || typeof auditHead.seq !== 'number' || !Number.isFinite(auditHead.seq) || typeof auditHead.hash !== 'string')
70
+ return null;
71
+ head = { seq: auditHead.seq, hash: auditHead.hash };
72
+ }
73
+ return {
74
+ settings: stripUnsafeKeys(settings),
75
+ library: { pages: library.pages, databases: library.databases },
76
+ auditHead: head,
77
+ };
21
78
  }
22
79
  /**
23
80
  * Read a site export's space island back, or `null` when absent/corrupt.
@@ -29,6 +86,10 @@ export function readLibraryIsland(html) {
29
86
  const bundle = parsed?.library ?? parsed?.space;
30
87
  if (!bundle || !Array.isArray(bundle.pages))
31
88
  return null;
89
+ // Deep-validate the LX-2 ledger key (island text is untrusted input): carry
90
+ // it only when it IS a real section, so import code can trust the type — a
91
+ // malformed/hostile key is dropped, never thrown on (see readLedgerSection).
92
+ const ledger = readLedgerSection(parsed?.ledger);
32
93
  return {
33
94
  version: 1,
34
95
  rootId: parsed?.rootId ?? '',
@@ -36,6 +97,7 @@ export function readLibraryIsland(html) {
36
97
  pages: bundle.pages,
37
98
  databases: Array.isArray(bundle.databases) ? bundle.databases : [],
38
99
  },
100
+ ...(ledger ? { ledger } : {}),
39
101
  };
40
102
  }
41
103
  const MAX_DEPTH = 64;
@@ -1 +1 @@
1
- {"version":3,"file":"bookFolder.js","sourceRoot":"","sources":["../src/bookFolder.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"bookFolder.js","sourceRoot":"","sources":["../src/bookFolder.ts"],"names":[],"mappings":"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"}
package/dist/client.d.ts CHANGED
@@ -5,6 +5,7 @@ import type { AclLevel, AgentEditsMode, AgentEditsPolicy, Member, MemberRole, Me
5
5
  import type { InstanceConfig, InstanceInfo, StoredEdit } from './provenance';
6
6
  import type { AgentTokenMeta, AgentTokenScope } from './identity';
7
7
  import type { BackupCadence, BackupConfig, BackupStatus, ImportRequest, ImportResult, LedgerBackupSection } from './backup';
8
+ import type { LedgerExportSection, LedgerSectionRestoreResult } from './ledgerExportSection';
8
9
  import type { DatabaseInput, DatabaseRow, DatabaseUpdate, RowInput, RowUpdate, StoredDatabase } from './database';
9
10
  import type { CommentInput, StoredComment, StoredSuggestion, SuggestionInput, SuggestionStatus, SuggestionUpdate } from './suggestions';
10
11
  import type { LedgerAccount, LedgerAccountInput, LedgerAccountPatch, LedgerAuditEvent, LedgerClearedState, LedgerDraftInput, LedgerDraftPatch, LedgerInfo, LedgerPeriod, LedgerPeriodCloseInput, LedgerPeriodCloseResult, LedgerPeriodReopenResult, LedgerPosting, LedgerReconciliation, LedgerReconciliationInput, LedgerReconciliationPatch, LedgerReconciliationStatus, LedgerReconciliationSummary, LedgerReverseOptions, LedgerTransaction, LedgerTransactionState, LedgerVerifyReport } from './ledger';
@@ -162,7 +163,14 @@ export interface DataClient {
162
163
  * returns secrets. */
163
164
  testMcpServer(server: McpServerConfig): Promise<McpTestResult>;
164
165
  listPlugins(): Promise<StoredPlugin[]>;
165
- installPlugin(pkg: PluginPackage): Promise<StoredPlugin>;
166
+ /**
167
+ * Install or upgrade a plugin. The server preserves the enabled state and
168
+ * install time of an existing plugin, and REJECTS a downgrade (an older
169
+ * semver than what's installed) unless `opts.allowDowngrade` is explicit.
170
+ */
171
+ installPlugin(pkg: PluginPackage, opts?: {
172
+ allowDowngrade?: boolean;
173
+ }): Promise<StoredPlugin>;
166
174
  setPluginEnabled(id: string, enabled: boolean): Promise<StoredPlugin>;
167
175
  removePlugin(id: string): Promise<boolean>;
168
176
  /**
@@ -296,6 +304,15 @@ export interface DataClient {
296
304
  ledgerInfo(): Promise<LedgerInfo>;
297
305
  /** Seed the four managed ledger databases + restricted host page (idempotent). */
298
306
  ledgerInit(): Promise<LedgerInfo>;
307
+ /**
308
+ * LX-4: restore an export's embedded ledger-records section into an EMPTY
309
+ * ledger — the section is deep-validated, then REPLAYED through the server's
310
+ * ledger writer (fresh audit entries carrying import provenance; no direct
311
+ * row writes). Refuses with `LedgerError('invalid-state')` when the target
312
+ * already keeps any ledger data (merge is out of scope). Instance-admin gated
313
+ * over HTTP, like `importLibrary`.
314
+ */
315
+ ledgerRestoreSection(section: LedgerExportSection): Promise<LedgerSectionRestoreResult>;
299
316
  /** List accounts (hierarchy is encoded in the colon-delimited names). */
300
317
  ledgerListAccounts(): Promise<LedgerAccount[]>;
301
318
  /** Create an account. `currency` defaults to `USD`. */
@@ -710,6 +727,7 @@ export declare class HttpDataClient implements DataClient {
710
727
  private ledgerRequest;
711
728
  /** Re-materialize a non-2xx ledger response into a typed {@link LedgerError}. */
712
729
  private throwLedgerError;
730
+ ledgerRestoreSection(section: LedgerExportSection): Promise<LedgerSectionRestoreResult>;
713
731
  ledgerInfo(): Promise<LedgerInfo>;
714
732
  ledgerInit(): Promise<LedgerInfo>;
715
733
  ledgerListAccounts(): Promise<LedgerAccount[]>;
@@ -842,7 +860,9 @@ export declare class HttpDataClient implements DataClient {
842
860
  signal?: AbortSignal;
843
861
  }): Promise<string>;
844
862
  listPlugins(): Promise<StoredPlugin[]>;
845
- installPlugin(pkg: PluginPackage): Promise<StoredPlugin>;
863
+ installPlugin(pkg: PluginPackage, opts?: {
864
+ allowDowngrade?: boolean;
865
+ }): Promise<StoredPlugin>;
846
866
  setPluginEnabled(id: string, enabled: boolean): Promise<StoredPlugin>;
847
867
  removePlugin(id: string): Promise<boolean>;
848
868
  aiSkills(): Promise<AiSkill[]>;
package/dist/client.js CHANGED
@@ -813,6 +813,9 @@ export class HttpDataClient {
813
813
  }
814
814
  throw new Error(`OpenBook request failed (${res.status} ${res.statusText})${data?.error ? `: ${data.error}` : ''}`);
815
815
  }
816
+ ledgerRestoreSection(section) {
817
+ return this.ledgerRequest('POST', API.ledgerRestoreSection, section);
818
+ }
816
819
  ledgerInfo() {
817
820
  return this.ledgerRequest('GET', API.ledger);
818
821
  }
@@ -1129,8 +1132,9 @@ export class HttpDataClient {
1129
1132
  async listPlugins() {
1130
1133
  return this.request('GET', API.plugins);
1131
1134
  }
1132
- async installPlugin(pkg) {
1133
- return this.request('POST', API.plugins, pkg);
1135
+ async installPlugin(pkg, opts = {}) {
1136
+ const path = opts.allowDowngrade ? `${API.plugins}?allowDowngrade=1` : API.plugins;
1137
+ return this.request('POST', path, pkg);
1134
1138
  }
1135
1139
  async setPluginEnabled(id, enabled) {
1136
1140
  return this.request('PATCH', API.plugin(id), { enabled });