@ai-matrx/content-ir-react 0.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/CHANGELOG.md +37 -0
- package/LICENSE +21 -0
- package/README.md +78 -0
- package/dist/index.cjs +769 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +782 -0
- package/dist/index.d.ts +782 -0
- package/dist/index.js +732 -0
- package/dist/index.js.map +1 -0
- package/package.json +73 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,782 @@
|
|
|
1
|
+
import * as react from 'react';
|
|
2
|
+
import react__default, { ReactNode } from 'react';
|
|
3
|
+
import { KindDefinition, CanonicalBlockIR, PartialKindEvent } from '@ai-matrx/content-ir';
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* THE SCREAM SEAM.
|
|
7
|
+
*
|
|
8
|
+
* Every recovery path in this package is loud: a defective component row, a
|
|
9
|
+
* failed resolver load, a kind whose component throws on a provisional value.
|
|
10
|
+
* The package refuses to own where those screams land — matrx-frontend routes
|
|
11
|
+
* them to the Error Inspector, the dashboard to its own log, the extension to
|
|
12
|
+
* its background page. Each host binds one function.
|
|
13
|
+
*
|
|
14
|
+
* A host that binds a no-op has chosen silence, which is a defect in itself;
|
|
15
|
+
* {@link consoleErrorReporter} is the honest default.
|
|
16
|
+
*/
|
|
17
|
+
interface ContentIrErrorReport {
|
|
18
|
+
/** Always `"content-ir"` — hosts key their capture stores on it. */
|
|
19
|
+
source: "content-ir";
|
|
20
|
+
message: string;
|
|
21
|
+
name?: string;
|
|
22
|
+
stack?: string;
|
|
23
|
+
/** Free-form grouping key (the host's `relation`), e.g. `"partial-kind"`. */
|
|
24
|
+
relation?: string;
|
|
25
|
+
raw?: unknown;
|
|
26
|
+
}
|
|
27
|
+
type ContentIrErrorReporter = (report: ContentIrErrorReport) => void;
|
|
28
|
+
/** The default when a host binds nothing: never silent. */
|
|
29
|
+
declare const consoleErrorReporter: ContentIrErrorReporter;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* The (kind, platform, role) → component vocabulary — the Shape System's
|
|
33
|
+
* resolver contract (rulings R1 + R6), stated once for every UI.
|
|
34
|
+
*
|
|
35
|
+
* Cross-repo system-of-record:
|
|
36
|
+
* `common-docs/systems/content-ir-twin/FEATURE.md` (package boundary) and
|
|
37
|
+
* `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md` (the semantics).
|
|
38
|
+
*
|
|
39
|
+
* Nothing here knows where a row comes from. A host supplies rows from
|
|
40
|
+
* `content_ir.kind_component` (Supabase, a REST call, a fixture); the resolver
|
|
41
|
+
* only knows the shape.
|
|
42
|
+
*/
|
|
43
|
+
/** JSON object, restated locally so this package depends on no host type. */
|
|
44
|
+
type JsonObject = Record<string, unknown>;
|
|
45
|
+
/** Which half of the shape a component draws. */
|
|
46
|
+
type ComponentRole = "output" | "input";
|
|
47
|
+
/**
|
|
48
|
+
* One `content_ir.kind_component` row, projected to exactly what rendering
|
|
49
|
+
* needs. Hosts map their own query result onto this.
|
|
50
|
+
*/
|
|
51
|
+
interface KindComponentRow {
|
|
52
|
+
kind: string;
|
|
53
|
+
platform: string;
|
|
54
|
+
role: ComponentRole;
|
|
55
|
+
componentKey: string;
|
|
56
|
+
/** `source` column vocabulary: "bundled" | "db" (db = web sandbox only). */
|
|
57
|
+
source: string;
|
|
58
|
+
config: JsonObject;
|
|
59
|
+
isActive: boolean;
|
|
60
|
+
componentSource: string | null;
|
|
61
|
+
propsTransform: string | null;
|
|
62
|
+
pinnedKindVersion: number | null;
|
|
63
|
+
updatedAt: string | null;
|
|
64
|
+
createdBy: string | null;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* One COMPILED bootstrap entry — the trusted-at-boot floor a host ships in its
|
|
68
|
+
* bundle, available synchronously from the first streamed byte.
|
|
69
|
+
*/
|
|
70
|
+
interface SystemComponentEntry {
|
|
71
|
+
kind: string;
|
|
72
|
+
platform: string;
|
|
73
|
+
role: ComponentRole;
|
|
74
|
+
componentKey: string;
|
|
75
|
+
source: string;
|
|
76
|
+
config: JsonObject;
|
|
77
|
+
}
|
|
78
|
+
/** The resolver's answer for one (kind, platform, role). */
|
|
79
|
+
interface ComponentResolution {
|
|
80
|
+
/** The component key the renderer routes on (e.g. "flashcards"). */
|
|
81
|
+
componentKey: string;
|
|
82
|
+
source: string;
|
|
83
|
+
config: JsonObject;
|
|
84
|
+
/**
|
|
85
|
+
* Render-trust verdict (R6). Compiled entries are always active (trusted at
|
|
86
|
+
* bootstrap); DB rows carry their own `is_active`.
|
|
87
|
+
*/
|
|
88
|
+
isActive: boolean;
|
|
89
|
+
/** Which tier produced this answer — the verification hook's `by`. */
|
|
90
|
+
resolvedBy: "compiled" | "db";
|
|
91
|
+
componentSource: string | null;
|
|
92
|
+
propsTransform: string | null;
|
|
93
|
+
pinnedKindVersion: number | null;
|
|
94
|
+
/** The db row's `updated_at` — the compile-cache staleness key. */
|
|
95
|
+
updatedAt: string | null;
|
|
96
|
+
createdBy: string | null;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* The read side of a component resolver, as the render layer consumes it.
|
|
100
|
+
* The package ships {@link ComponentResolver}; a host with its own resolver
|
|
101
|
+
* only has to satisfy this.
|
|
102
|
+
*/
|
|
103
|
+
interface ComponentResolutionSource {
|
|
104
|
+
/** Synchronous — the render seam's per-block call. */
|
|
105
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
106
|
+
/** Eager targeted fetch for one kind; fire-and-forget, never awaited on the hot path. */
|
|
107
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
108
|
+
/** One list fetch per session. */
|
|
109
|
+
ensureWarm(): Promise<void>;
|
|
110
|
+
/** Refresh-on-view; rate-limited and deduped by the implementation. */
|
|
111
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
112
|
+
/** Monotonic tier version — has anything at all changed? */
|
|
113
|
+
getVersion(): number;
|
|
114
|
+
/** Monotonic per-kind version (+ wholesale epoch) — the granular repaint key. */
|
|
115
|
+
getKindVersion(kind: string): number;
|
|
116
|
+
subscribe(listener: () => void): () => void;
|
|
117
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* THE HOST CONTRACT — everything this package refuses to decide.
|
|
122
|
+
*
|
|
123
|
+
* The kernel (`@ai-matrx/content-ir`) proved the shape: extract the portable
|
|
124
|
+
* part, let host capability enter through explicit named seams. The render
|
|
125
|
+
* layer needs four things it must never own:
|
|
126
|
+
*
|
|
127
|
+
* 1. WHERE KIND DEFINITIONS COME FROM (a bundled table, `content_ir`, a REST
|
|
128
|
+
* call). The route only asks "is this kind registered, and does it carry a
|
|
129
|
+
* legacy bridge / a partial-ready opt-in".
|
|
130
|
+
* 2. WHERE COMPONENT ROWS COME FROM — {@link ComponentResolutionSource}. The
|
|
131
|
+
* package ships `ComponentResolver`, which any host can construct with its
|
|
132
|
+
* own loaders; a host with its own resolver only has to satisfy the type.
|
|
133
|
+
* 3. HOW A ROUTED BLOCK ACTUALLY DRAWS. `applyIrKindRoute` decides a block's
|
|
134
|
+
* TYPE; turning that type into pixels is the host's dispatch table
|
|
135
|
+
* (matrx-frontend's `BlockRenderer`, the dashboard's small map). The
|
|
136
|
+
* package never imports a component library.
|
|
137
|
+
* 4. WHERE SCREAMS LAND — {@link ContentIrErrorReporter}.
|
|
138
|
+
*
|
|
139
|
+
* No Next.js, no Redux, no Supabase, no router, no host error capture. If a
|
|
140
|
+
* seam is missing, ADD A SEAM — never an import.
|
|
141
|
+
*/
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* The minimum a render block must expose for the kind route to work. Hosts
|
|
145
|
+
* pass their own richer block type through; the route is generic over `T` and
|
|
146
|
+
* preserves every extra field.
|
|
147
|
+
*/
|
|
148
|
+
interface IrRoutableBlock {
|
|
149
|
+
type: string;
|
|
150
|
+
serverData?: Record<string, unknown>;
|
|
151
|
+
metadata?: Record<string, unknown>;
|
|
152
|
+
}
|
|
153
|
+
/** A routable block that also carries its source text (the raw region). */
|
|
154
|
+
interface IrRenderBlock extends IrRoutableBlock {
|
|
155
|
+
content: string;
|
|
156
|
+
language?: string;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Where registered kinds come from. `getDefinition` is the only method the
|
|
160
|
+
* pure route needs; the rest drive the granular repaint and the warm-up tick
|
|
161
|
+
* that keeps a cold registry from being mistaken for "this kind has no
|
|
162
|
+
* component".
|
|
163
|
+
*/
|
|
164
|
+
interface KindDefinitionSource {
|
|
165
|
+
getDefinition(kind: string): KindDefinition | undefined;
|
|
166
|
+
/** Monotonic per-kind version — the repaint snapshot key. */
|
|
167
|
+
getKindVersion(kind: string): number;
|
|
168
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
169
|
+
/** One definition load per app session. */
|
|
170
|
+
ensureWarm(): Promise<void>;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* The rendering seams. Everything here returns host UI; the package supplies
|
|
174
|
+
* the DECISIONS and the chrome-free structure around them.
|
|
175
|
+
*/
|
|
176
|
+
interface ContentIrRenderSeams {
|
|
177
|
+
/**
|
|
178
|
+
* Draw a block the kind route has already typed. This is the host's dispatch
|
|
179
|
+
* table — the single place a component key becomes a component.
|
|
180
|
+
*/
|
|
181
|
+
renderBlock(block: IrRenderBlock): ReactNode;
|
|
182
|
+
/**
|
|
183
|
+
* THE FLOOR: render ANY JSON value as a human document. Reached when a kind
|
|
184
|
+
* has no render-trusted component, when the value is not an object at all,
|
|
185
|
+
* and by the generic structured view.
|
|
186
|
+
*
|
|
187
|
+
* This is deliberately a seam and not a bundled component. Rendering a value
|
|
188
|
+
* WELL means prose through the host's markdown renderer, media through the
|
|
189
|
+
* host's file handler, and uniform arrays through the host's data table —
|
|
190
|
+
* all of which are host property. A host that has none of those can pass a
|
|
191
|
+
* `<pre>`; it will be honest, just plain.
|
|
192
|
+
*/
|
|
193
|
+
renderValue(props: StructuredValueRenderProps): ReactNode;
|
|
194
|
+
/**
|
|
195
|
+
* The "still arriving" indicator used by the provisional frame. Optional —
|
|
196
|
+
* hosts without a shimmer get plain text.
|
|
197
|
+
*/
|
|
198
|
+
renderShimmer?(text: string): ReactNode;
|
|
199
|
+
/**
|
|
200
|
+
* The honest "this shape has no custom component yet" notice. Optional: the
|
|
201
|
+
* package draws a plain amber line when a host supplies nothing, and a host
|
|
202
|
+
* with an icon set or its own callout component supplies that instead. It is
|
|
203
|
+
* a seam and not a bundled component because this package depends on no icon
|
|
204
|
+
* library.
|
|
205
|
+
*/
|
|
206
|
+
renderNotice?(text: string): ReactNode;
|
|
207
|
+
}
|
|
208
|
+
interface StructuredValueRenderProps {
|
|
209
|
+
value: unknown;
|
|
210
|
+
/** The kind slug this value claims, when known. Honesty line only — never a renderer choice. */
|
|
211
|
+
kind?: string;
|
|
212
|
+
/** Why this shape has no custom view, in human words. */
|
|
213
|
+
note?: string;
|
|
214
|
+
/** Show the "what this is / raw data" footer. Default true. */
|
|
215
|
+
footer?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* One host, wired once, read by every component in this package through
|
|
219
|
+
* {@link ContentIrRenderProvider}.
|
|
220
|
+
*/
|
|
221
|
+
interface ContentIrHost extends ContentIrRenderSeams {
|
|
222
|
+
kinds: KindDefinitionSource;
|
|
223
|
+
components: ComponentResolutionSource;
|
|
224
|
+
reportError: ContentIrErrorReporter;
|
|
225
|
+
/**
|
|
226
|
+
* The `kind_component.platform` this host resolves as. "web" for every
|
|
227
|
+
* browser UI; the column already models "react-native" and friends, and a
|
|
228
|
+
* host that lies here renders the wrong component everywhere.
|
|
229
|
+
*/
|
|
230
|
+
platform: string;
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* The pure route's dependencies — a strict subset of {@link ContentIrHost},
|
|
234
|
+
* because `applyIrKindRoute` is called OUTSIDE React (reducers, stream
|
|
235
|
+
* accumulators, tests) where there is no provider to read.
|
|
236
|
+
*/
|
|
237
|
+
interface KindRouteEnv {
|
|
238
|
+
kinds: Pick<KindDefinitionSource, "getDefinition">;
|
|
239
|
+
components: Pick<ComponentResolutionSource, "resolve">;
|
|
240
|
+
reportError: ContentIrErrorReporter;
|
|
241
|
+
platform: string;
|
|
242
|
+
}
|
|
243
|
+
/** Narrow a host (or anything host-shaped) to what the pure route needs. */
|
|
244
|
+
declare function routeEnvOf(host: ContentIrHost): KindRouteEnv;
|
|
245
|
+
|
|
246
|
+
interface ContentIrRenderProviderProps {
|
|
247
|
+
host: ContentIrHost;
|
|
248
|
+
children: ReactNode;
|
|
249
|
+
}
|
|
250
|
+
declare function ContentIrRenderProvider({ host, children, }: ContentIrRenderProviderProps): react.JSX.Element;
|
|
251
|
+
/**
|
|
252
|
+
* The wired host, or null. For the rare consumer that can legitimately run
|
|
253
|
+
* without a provider because it was handed its sources explicitly (see
|
|
254
|
+
* `useContentIrKindVersion`). Everything else uses {@link useContentIrHost}.
|
|
255
|
+
*/
|
|
256
|
+
declare function useContentIrHostOrNull(): ContentIrHost | null;
|
|
257
|
+
/** The wired host. Throws outside a provider — see the module doc. */
|
|
258
|
+
declare function useContentIrHost(): ContentIrHost;
|
|
259
|
+
/** The wired host narrowed to what the pure route functions take. */
|
|
260
|
+
declare function useKindRouteEnv(): KindRouteEnv;
|
|
261
|
+
|
|
262
|
+
/**
|
|
263
|
+
* The Shape System component RESOLVER (rulings R1 + R6): (kind, platform,
|
|
264
|
+
* role) → component, with two tiers:
|
|
265
|
+
*
|
|
266
|
+
* - eager: a COMPILED bootstrap the host ships in its bundle — the
|
|
267
|
+
* trusted-at-boot floor, available at import so the render seam can gate
|
|
268
|
+
* synchronously from the first streamed byte.
|
|
269
|
+
* - warm: one `content_ir.kind_component` list fetch per app session
|
|
270
|
+
* (`ensureWarm`). A DB row for a (kind, platform, role) OVERRIDES the
|
|
271
|
+
* compiled entry once warm; the compiled floor keeps answering until then
|
|
272
|
+
* (and forever, on DB failure).
|
|
273
|
+
*
|
|
274
|
+
* Resolution is SYNCHRONOUS (the render seam calls it per block); the only
|
|
275
|
+
* async work is the loading, off the render path.
|
|
276
|
+
*
|
|
277
|
+
* WHAT MOVED AND WHY. This class was matrx-frontend's `ComponentRegistry`. It
|
|
278
|
+
* is a large part of why a second UI could not render a kind: every tier rule,
|
|
279
|
+
* every repaint counter, every dedupe latch lived in one app. Nothing about it
|
|
280
|
+
* is Next.js, Redux, or Supabase — the only host-specific parts were the two
|
|
281
|
+
* loaders and the error sink, which are now constructor arguments.
|
|
282
|
+
*/
|
|
283
|
+
|
|
284
|
+
interface ComponentResolverOptions {
|
|
285
|
+
/**
|
|
286
|
+
* The compiled bootstrap, as a THUNK resolved on first use: a host's system
|
|
287
|
+
* component table is often mid-initialization when this module evaluates
|
|
288
|
+
* (matrx-frontend's registry cluster has a deliberate import cycle).
|
|
289
|
+
*/
|
|
290
|
+
compiledEntries?: () => SystemComponentEntry[];
|
|
291
|
+
/** The warm/refresh list load — every `kind_component` row the user may see. */
|
|
292
|
+
loadAll?: () => Promise<KindComponentRow[]>;
|
|
293
|
+
/** The eager single-kind load fired the moment a kind is identified mid-stream. */
|
|
294
|
+
loadForKind?: (kind: string, platform: string) => Promise<KindComponentRow[]>;
|
|
295
|
+
/** Where recovery screams land. Defaults to `console.error`, never silence. */
|
|
296
|
+
reportError?: ContentIrErrorReporter;
|
|
297
|
+
/** Clock seam — the refresh rate limiter. Defaults to `Date.now`. */
|
|
298
|
+
now?: () => number;
|
|
299
|
+
}
|
|
300
|
+
declare class ComponentResolver implements ComponentResolutionSource {
|
|
301
|
+
private compiled;
|
|
302
|
+
private readonly db;
|
|
303
|
+
private warmPromise;
|
|
304
|
+
private warmFailureLogged;
|
|
305
|
+
/**
|
|
306
|
+
* When the last successful wholesale refresh landed, or null for "never".
|
|
307
|
+
* Explicitly nullable rather than 0: with a host-supplied clock that starts
|
|
308
|
+
* near zero, a `0` sentinel makes the FIRST refresh look rate-limited and
|
|
309
|
+
* silently skip.
|
|
310
|
+
*/
|
|
311
|
+
private lastRefreshAt;
|
|
312
|
+
private refreshPromise;
|
|
313
|
+
private readonly listeners;
|
|
314
|
+
/**
|
|
315
|
+
* Cold single-kind fetch dedupe (streaming eager path). In-flight is keyed
|
|
316
|
+
* by (kind, platform) — the fetch unit; misses are keyed by (kind, platform,
|
|
317
|
+
* role) so a miss on web/output never suppresses other roles, and CLEARED on
|
|
318
|
+
* every wholesale refresh (a component created mid-session becomes eagerly
|
|
319
|
+
* fetchable again — misses are cheap to re-verify).
|
|
320
|
+
*/
|
|
321
|
+
private readonly coldInFlight;
|
|
322
|
+
private readonly coldMisses;
|
|
323
|
+
/** Monotonic db-tier version — the repaint hook's snapshot key. */
|
|
324
|
+
private version;
|
|
325
|
+
/** Per-kind versions + listeners (granular repaint) + wholesale epoch. */
|
|
326
|
+
private readonly kindVersions;
|
|
327
|
+
private readonly kindListeners;
|
|
328
|
+
private epoch;
|
|
329
|
+
private readonly reportError;
|
|
330
|
+
private readonly now;
|
|
331
|
+
private readonly options;
|
|
332
|
+
constructor(options?: ComponentResolverOptions);
|
|
333
|
+
private compiledMap;
|
|
334
|
+
/**
|
|
335
|
+
* Synchronous resolve — the render seam's per-block call. DB override first
|
|
336
|
+
* (once warm), compiled floor second, null for unknown.
|
|
337
|
+
*/
|
|
338
|
+
resolve(kind: string, platform: string, role: ComponentRole): ComponentResolution | null;
|
|
339
|
+
/** R6 floor check: compiled-bootstrap membership = always render-trusted. */
|
|
340
|
+
hasCompiled(kind: string, platform: string, role: ComponentRole): boolean;
|
|
341
|
+
/**
|
|
342
|
+
* Pure ingest — the warm landing point and the unit-test seam. First row per
|
|
343
|
+
* key wins: rows arrive is_default-first / sort_order-asc from the source.
|
|
344
|
+
*/
|
|
345
|
+
ingestDbRows(rows: readonly KindComponentRow[]): void;
|
|
346
|
+
/**
|
|
347
|
+
* Refresh landing point: REPLACE the db tier wholesale (same
|
|
348
|
+
* first-row-per-key contract as {@link ingestDbRows}) so edits, deletions,
|
|
349
|
+
* and is_active flips all take effect. Always notifies.
|
|
350
|
+
*/
|
|
351
|
+
replaceDbRows(rows: readonly KindComponentRow[]): void;
|
|
352
|
+
getVersion(): number;
|
|
353
|
+
getKindVersion(kind: string): number;
|
|
354
|
+
subscribeKind(kind: string, listener: () => void): () => void;
|
|
355
|
+
subscribe(listener: () => void): () => void;
|
|
356
|
+
private bumpKind;
|
|
357
|
+
private notifyChanged;
|
|
358
|
+
/**
|
|
359
|
+
* The eager lightweight single-kind fetch (streaming path): the moment a
|
|
360
|
+
* cloud kind is identified mid-stream, pull ONLY that kind's resolver rows
|
|
361
|
+
* and ingest them so {@link resolve} can answer before — or shortly after —
|
|
362
|
+
* the region completes. Deduped in-flight and by known-miss. Fire-and-forget;
|
|
363
|
+
* failures are loud (the warm list remains the backstop).
|
|
364
|
+
*/
|
|
365
|
+
requestComponent(kind: string, platform: string, role: ComponentRole): void;
|
|
366
|
+
/**
|
|
367
|
+
* Refresh-on-view: re-fetch the warm list and REPLACE the db tier, so an
|
|
368
|
+
* edited `source='db'` component (its `updated_at` bump re-keys the host's
|
|
369
|
+
* compile cache) renders fresh on the next view. Deduped in-flight and
|
|
370
|
+
* rate-limited by `maxAgeMs` (default 10s) — mounting several previews costs
|
|
371
|
+
* one fetch. Server-side edits do NOT push to open clients; the contract is
|
|
372
|
+
* refresh-on-view via this call.
|
|
373
|
+
*/
|
|
374
|
+
refresh(maxAgeMs?: number): Promise<void>;
|
|
375
|
+
/** One list fetch per app session; failed loads retry on the next call. */
|
|
376
|
+
ensureWarm(): Promise<void>;
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
/**
|
|
380
|
+
* THE KIND ROUTE — the render flip, as a pure block transform.
|
|
381
|
+
*
|
|
382
|
+
* A block whose `metadata.__ir` envelope resolved a REGISTERED kind is routed
|
|
383
|
+
* to that kind's component: via the legacy-bridge facet (`legacyBlockType` +
|
|
384
|
+
* `toLegacyServerData`) when the kind has one, so the block enters the host's
|
|
385
|
+
* existing renderer as its real type with envelope-derived serverData;
|
|
386
|
+
* otherwise via the component resolver. Blocks with no envelope, an
|
|
387
|
+
* unregistered kind, or no bridge facet pass through UNTOUCHED — the strangler
|
|
388
|
+
* seam.
|
|
389
|
+
*
|
|
390
|
+
* This is where a bare/fenced JSON flashcard_set — which a text detector could
|
|
391
|
+
* only ever call "code" — becomes real flashcards, live while streaming.
|
|
392
|
+
*
|
|
393
|
+
* PORTABILITY. This function was matrx-frontend's `react/kind-route.ts` and is
|
|
394
|
+
* the single most-copied thing in the system: every UI that renders a kind has
|
|
395
|
+
* to make exactly these decisions in exactly this order, and a second
|
|
396
|
+
* implementation of them is a guaranteed divergence. It takes its registries,
|
|
397
|
+
* its platform, and its error sink as an {@link KindRouteEnv} argument rather
|
|
398
|
+
* than importing them, so it is callable from a reducer, a stream accumulator,
|
|
399
|
+
* a test, or a React render — in any app.
|
|
400
|
+
*
|
|
401
|
+
* Semantics: `matrx-frontend/features/content-ir/docs/SHAPE_SYSTEM.md`
|
|
402
|
+
* (registry, dual gate, `kind_component` resolution, rulings R1 + R6).
|
|
403
|
+
*/
|
|
404
|
+
|
|
405
|
+
/**
|
|
406
|
+
* Runtime routing marker (the Shape System's verification hook): stamped on
|
|
407
|
+
* `metadata.__ir_route` whenever a block routes AND the component resolver
|
|
408
|
+
* produced the decision. `by` says which resolver tier answered ("compiled"
|
|
409
|
+
* floor vs a warm `content_ir.kind_component` row) — the live proof of
|
|
410
|
+
* registry-resolution vs hard-coded fallback. Metadata-only, non-breaking.
|
|
411
|
+
*/
|
|
412
|
+
declare const IR_ROUTE_KEY: "__ir_route";
|
|
413
|
+
/**
|
|
414
|
+
* The component key the R6 generic fallback routes to — the official renderer
|
|
415
|
+
* for a KNOWN shape that nothing render-trusted claims. Hosts map this key to
|
|
416
|
+
* their generic structured view (the package ships one: `GenericStructuredView`).
|
|
417
|
+
*/
|
|
418
|
+
declare const GENERIC_STRUCTURED_COMPONENT_KEY: "generic_structured";
|
|
419
|
+
/**
|
|
420
|
+
* The block type a DB-sourced (user-authored) kind component renders as.
|
|
421
|
+
* FE-synthesized: produced ONLY here, never emitted upstream. A host that has
|
|
422
|
+
* no sandbox for user components simply does not map this key — the block then
|
|
423
|
+
* falls to that host's unknown-type handling, which is honest.
|
|
424
|
+
*/
|
|
425
|
+
declare const DB_KIND_COMPONENT_KEY: "db_kind_component";
|
|
426
|
+
/** Test-only reset of the once-per-kind console latch. */
|
|
427
|
+
declare function resetSourcelessDbRowReports(): void;
|
|
428
|
+
/** Why a block landed on the generic viewer instead of a real renderer. */
|
|
429
|
+
type GenericFallbackReason =
|
|
430
|
+
/** No compiled bridge and no `content_ir.kind_component` row at all. */
|
|
431
|
+
"no-component"
|
|
432
|
+
/** A component row exists but is held `is_active = false`. */
|
|
433
|
+
| "inactive";
|
|
434
|
+
interface IrRouteMarker {
|
|
435
|
+
by: ComponentResolution["resolvedBy"] | "generic";
|
|
436
|
+
key: string;
|
|
437
|
+
/**
|
|
438
|
+
* Only on the generic fallback: the shape is NOT render-trusted, so the
|
|
439
|
+
* viewer must say so out loud (R6 — never an error, never hidden content).
|
|
440
|
+
*/
|
|
441
|
+
unverified?: true;
|
|
442
|
+
reason?: GenericFallbackReason;
|
|
443
|
+
}
|
|
444
|
+
/** Read the routing marker a block picked up at the seam (or null). */
|
|
445
|
+
declare function readIrRouteMarker(metadata: Record<string, unknown> | null | undefined): IrRouteMarker | null;
|
|
446
|
+
interface KindRouteOptions {
|
|
447
|
+
/**
|
|
448
|
+
* Block types this host OWNS and the route must never re-type, however good
|
|
449
|
+
* the envelope on them looks.
|
|
450
|
+
*
|
|
451
|
+
* matrx-frontend passes `["artifact"]`: an artifact block has an identity, a
|
|
452
|
+
* version, and a Canvas to open in, and since 2026-08-18 it carries
|
|
453
|
+
* `metadata.__ir` so SELECTORS can read the envelope. That envelope is DATA
|
|
454
|
+
* there, not a route — re-typing it to the bare kind component would strip
|
|
455
|
+
* the artifact chrome and lose the door to the Canvas.
|
|
456
|
+
*/
|
|
457
|
+
ownedTypes?: readonly string[];
|
|
458
|
+
}
|
|
459
|
+
declare function applyIrKindRoute<T extends IrRoutableBlock>(block: T, env: KindRouteEnv, options?: KindRouteOptions): T;
|
|
460
|
+
/**
|
|
461
|
+
* Rehydration route for STRUCTURED persisted artifacts.
|
|
462
|
+
*
|
|
463
|
+
* A materialized kind artifact stores its zero-loss value object (carrying
|
|
464
|
+
* `__kind`) alongside its row. Given that stored value, derive the registered
|
|
465
|
+
* kind's legacy `serverData` WITHOUT re-parsing any text: the value wraps into
|
|
466
|
+
* a complete envelope and runs through the same `toLegacyServerData` bridge the
|
|
467
|
+
* live stream uses. Returns null for non-objects, unregistered kinds, or kinds
|
|
468
|
+
* without a legacy bridge — callers fall back to their string-payload path.
|
|
469
|
+
*/
|
|
470
|
+
declare function kindServerDataFromStoredValue(value: unknown, env: Pick<KindRouteEnv, "kinds">): Record<string, unknown> | null;
|
|
471
|
+
|
|
472
|
+
/**
|
|
473
|
+
* Routing the PROVISIONAL half of the streaming partial-kinds contract.
|
|
474
|
+
*
|
|
475
|
+
* Cross-repo system-of-record (read it before changing anything here):
|
|
476
|
+
* `common-docs/systems/content-ir-system/STREAMING_PARTIAL_KINDS.md` §8.
|
|
477
|
+
* The reader/validator half lives in `@ai-matrx/content-ir` (`wire/partial-kind`);
|
|
478
|
+
* the wire gate runs in each host's stream ingest.
|
|
479
|
+
*
|
|
480
|
+
* WHAT THIS DOES
|
|
481
|
+
* --------------
|
|
482
|
+
* While a structured region streams, the server announces what it thinks the
|
|
483
|
+
* region IS and what has arrived so far (`metadata.__ir_partial`). This module
|
|
484
|
+
* turns that provisional event into a routed block that renders through the
|
|
485
|
+
* EXACT SAME component the final value renders in — which is the entire point:
|
|
486
|
+
* a bespoke skeleton renderer would be a second render path and is banned.
|
|
487
|
+
*
|
|
488
|
+
* HOW, without touching the verified channel
|
|
489
|
+
* ------------------------------------------
|
|
490
|
+
* `root` is deliberately `IrStructuredNode`-shaped, so the event wraps into a
|
|
491
|
+
* `CanonicalBlockIR` and every existing reader — the compiled bridge, the
|
|
492
|
+
* component resolver, the db-component flip, the generic viewer — works
|
|
493
|
+
* unchanged. That provisional envelope is placed on a RENDER-LOCAL COPY of the
|
|
494
|
+
* block's metadata under `__ir`, never on the wire and never in host state. The
|
|
495
|
+
* block also carries `__ir_provisional: true` so any downstream reader can tell
|
|
496
|
+
* a provisional render from a verified one.
|
|
497
|
+
*
|
|
498
|
+
* THE POSTURE: WITHHOLD BY DEFAULT, OPT IN PER KIND
|
|
499
|
+
* -------------------------------------------------
|
|
500
|
+
* A provisional value MAY be missing required fields — that is what the
|
|
501
|
+
* `partial_unvalidated` notice declares — and §8 of the contract requires that
|
|
502
|
+
* a component which throws on an absent field is not routed one. Rather than
|
|
503
|
+
* audit every component, the default is WITHHOLD: nothing changes and the block
|
|
504
|
+
* keeps its loading skeleton. A kind opts in with `partialReady: true` on its
|
|
505
|
+
* registry definition. If an opted-in component throws anyway,
|
|
506
|
+
* `ProvisionalKindBoundary` screams and calls `markKindPartialUnsafe`, which
|
|
507
|
+
* drops that kind back to withhold for the rest of the session — loud recovery,
|
|
508
|
+
* never a broken surface.
|
|
509
|
+
*
|
|
510
|
+
* TERMINALS
|
|
511
|
+
* ---------
|
|
512
|
+
* `superseded` and `retracted` produce NO provisional render, so the swap to
|
|
513
|
+
* the final value happens in the same frame the terminal arrives — never a
|
|
514
|
+
* flicker through an empty state. Both are explicit EVENTS: the terminal is
|
|
515
|
+
* never inferred from the arrival of `__ir`, because a completed block often
|
|
516
|
+
* has no `__ir` at all (unregistered kind, schema drift, cold catalog) and
|
|
517
|
+
* inferring it would leave the skeleton up forever in exactly those cases.
|
|
518
|
+
*/
|
|
519
|
+
|
|
520
|
+
/**
|
|
521
|
+
* Marker stamped on a render-local block whose `__ir` is PROVISIONAL. Never
|
|
522
|
+
* emitted by a producer, never persisted, never on the wire.
|
|
523
|
+
*/
|
|
524
|
+
declare const IR_PROVISIONAL_KEY: "__ir_provisional";
|
|
525
|
+
/** True when this block's metadata carries a provisional (not verified) envelope. */
|
|
526
|
+
declare function isProvisionalBlock(metadata: Record<string, unknown> | null | undefined): boolean;
|
|
527
|
+
/** Wrap a validated `partial` event into the envelope shape every IR reader consumes. */
|
|
528
|
+
declare function envelopeFromPartialKind(event: PartialKindEvent): CanonicalBlockIR;
|
|
529
|
+
/** Loud recovery hook — called by ProvisionalKindBoundary when a render throws. */
|
|
530
|
+
declare function markKindPartialUnsafe(kind: string): void;
|
|
531
|
+
/** Test-only reset of the session latch. */
|
|
532
|
+
declare function resetPartialUnsafeKinds(): void;
|
|
533
|
+
/**
|
|
534
|
+
* Has this kind opted in to being handed a provisional value? Withhold is the
|
|
535
|
+
* default; see the module doc.
|
|
536
|
+
*/
|
|
537
|
+
declare function isPartialReadyKind(kind: string, env: Pick<KindRouteEnv, "kinds">): boolean;
|
|
538
|
+
interface PartialRenderOptions extends KindRouteOptions {
|
|
539
|
+
/**
|
|
540
|
+
* Is the STREAM still running? Message-wide, deliberately — not this block's
|
|
541
|
+
* own completion.
|
|
542
|
+
*
|
|
543
|
+
* 🚨 THE ANTI-STUCK-SKELETON BACKSTOP. Law 1 of the contract says every
|
|
544
|
+
* partial ends in exactly one terminal, and that law is the ONLY thing
|
|
545
|
+
* standing between a user and a "Still arriving" skeleton that never
|
|
546
|
+
* resolves. It is a producer guarantee with at least three ways to not fire:
|
|
547
|
+
* the drain skips a block missing from the final block list, the emitter
|
|
548
|
+
* early-returns once the stream ended or was cancelled (so a client abort
|
|
549
|
+
* drops every retraction), and a flush failure is swallowed so it never kills
|
|
550
|
+
* a run.
|
|
551
|
+
*
|
|
552
|
+
* Once the stream is over, no terminal can ever arrive, so a still-open
|
|
553
|
+
* provisional is stuck by definition — drop it and let the block's own
|
|
554
|
+
* content and `__ir` be the truth. Correct to be message-wide: a terminal for
|
|
555
|
+
* THIS block may still be in flight while the block itself looks finished.
|
|
556
|
+
*
|
|
557
|
+
* `undefined` reads as active, so a caller that does not thread stream state
|
|
558
|
+
* keeps live rendering rather than silently losing it.
|
|
559
|
+
*/
|
|
560
|
+
streamActive?: boolean;
|
|
561
|
+
}
|
|
562
|
+
/**
|
|
563
|
+
* The ANNOUNCED-but-not-yet-renderable state: the server has said what this
|
|
564
|
+
* region is, and the region cannot render its real component yet.
|
|
565
|
+
*
|
|
566
|
+
* WHY THIS EXISTS SEPARATELY FROM THE VERIFIED CHANNEL. On a chat stream the
|
|
567
|
+
* host's own accumulator fills `__ir` in as it parses. A WORKFLOW run's lane
|
|
568
|
+
* does not: when the server opens the block scope it marks the text channel
|
|
569
|
+
* `block_shadowed` and the lane stops feeding its accumulator, precisely so one
|
|
570
|
+
* region is never rendered twice under two sets of block ids
|
|
571
|
+
* (STREAMING_PARTIAL_KINDS.md §7b rule 4). So on a run page there is NO
|
|
572
|
+
* streaming `__ir` — the ONLY thing that knows what the region is, is the
|
|
573
|
+
* partial channel. Without this, a workflow node's structured answer fell
|
|
574
|
+
* through to the raw-text renderer: a generic loader, then raw JSON
|
|
575
|
+
* accumulating, then a swap at the end.
|
|
576
|
+
*
|
|
577
|
+
* Returns the provisional envelope to feed the kind's loading component, or
|
|
578
|
+
* null when there is nothing announced (no event, a terminal, a dead stream).
|
|
579
|
+
* Deliberately independent of `partialReady`: withholding a VALUE from a
|
|
580
|
+
* component that might throw on it is a real decision, but withholding the
|
|
581
|
+
* kind's own loading state is not — a skeleton cannot throw, and the reader
|
|
582
|
+
* seeing what is coming is the whole point.
|
|
583
|
+
*/
|
|
584
|
+
declare function resolveAnnouncedKindLoading(block: {
|
|
585
|
+
metadata?: Record<string, unknown>;
|
|
586
|
+
}, options?: Pick<PartialRenderOptions, "streamActive">): {
|
|
587
|
+
kind: string;
|
|
588
|
+
envelope: CanonicalBlockIR;
|
|
589
|
+
} | null;
|
|
590
|
+
interface ProvisionalKindRender<T> {
|
|
591
|
+
/** The routed block — same type/serverData shape the final value produces. */
|
|
592
|
+
block: T;
|
|
593
|
+
/** The announced (speculative) kind. */
|
|
594
|
+
kind: string;
|
|
595
|
+
/** Per-block ordering key, for diagnostics. */
|
|
596
|
+
seq: number;
|
|
597
|
+
/** The provisional envelope — feeds the loading skeleton used as the throw fallback. */
|
|
598
|
+
envelope: CanonicalBlockIR;
|
|
599
|
+
}
|
|
600
|
+
/**
|
|
601
|
+
* Resolve a block's provisional render, or null when there is nothing to show
|
|
602
|
+
* provisionally (no event, a terminal event, a withheld kind, a kind nothing
|
|
603
|
+
* can route, or a verified envelope that already won).
|
|
604
|
+
*
|
|
605
|
+
* Pure: no React, no host state, no side effects beyond the registry reads.
|
|
606
|
+
*/
|
|
607
|
+
declare function resolveProvisionalKindRender<T extends IrRoutableBlock & {
|
|
608
|
+
metadata?: Record<string, unknown>;
|
|
609
|
+
}>(block: T, env: KindRouteEnv, options?: PartialRenderOptions): ProvisionalKindRender<T> | null;
|
|
610
|
+
|
|
611
|
+
/**
|
|
612
|
+
* The two registries this hook watches. Passed explicitly by a host whose
|
|
613
|
+
* render path sits BELOW no provider — matrx-frontend's block renderer runs
|
|
614
|
+
* deep inside chat, workflow, and canvas trees that predate this package, and
|
|
615
|
+
* threading a provider through all of them to read two counters would be the
|
|
616
|
+
* tail wagging the dog.
|
|
617
|
+
*/
|
|
618
|
+
interface KindVersionSources {
|
|
619
|
+
kinds: Pick<KindDefinitionSource, "getKindVersion" | "subscribeKind">;
|
|
620
|
+
components: Pick<ComponentResolutionSource, "getKindVersion" | "subscribeKind">;
|
|
621
|
+
}
|
|
622
|
+
/**
|
|
623
|
+
* Subscribes the caller to registry changes FOR ONE KIND and returns that
|
|
624
|
+
* kind's combined version. Pass null for blocks with no envelope kind — they
|
|
625
|
+
* never repaint from registries (nothing to learn about them).
|
|
626
|
+
*
|
|
627
|
+
* `sources` defaults to the provider's host. Passing them explicitly is the
|
|
628
|
+
* supported way to use this hook outside a provider.
|
|
629
|
+
*/
|
|
630
|
+
declare function useContentIrKindVersion(kind: string | null, sources?: KindVersionSources): number;
|
|
631
|
+
|
|
632
|
+
declare function isRecordValue(value: unknown): value is Record<string, unknown>;
|
|
633
|
+
/**
|
|
634
|
+
* True when `applyIrKindRoute` has a registered render path for this kind — a
|
|
635
|
+
* compiled legacy bridge OR any ACTIVE resolver row (including db-sourced user
|
|
636
|
+
* components, which route to `db_kind_component`). Mirrors the route's own
|
|
637
|
+
* decision order; requires the resolver warm tier for db rows (see the warm
|
|
638
|
+
* tick in {@link KindInstanceRender}).
|
|
639
|
+
*/
|
|
640
|
+
declare function kindIsRoutable(kind: string, host: ContentIrHost): boolean;
|
|
641
|
+
interface KindInstanceRenderProps {
|
|
642
|
+
kind: string;
|
|
643
|
+
/** The canonical instance value (a `kind_example.data` row, a form-emitted instance, a node output). */
|
|
644
|
+
value: unknown;
|
|
645
|
+
/** Show the honest "no component registered" notice when unroutable. Default true. */
|
|
646
|
+
showRoutingNote?: boolean;
|
|
647
|
+
/**
|
|
648
|
+
* What to render when the routing decision lands on "no component exists for
|
|
649
|
+
* this kind". The universal document view is the right answer almost
|
|
650
|
+
* everywhere — it reads well and hides nothing. It is still the wrong answer
|
|
651
|
+
* when the raw value is an internal ENVELOPE rather than content: an
|
|
652
|
+
* `agent_result` dumped the verbatim prompt, the model id and the token bill
|
|
653
|
+
* into the box a learner was waiting on. Passing a fallback lets that caller
|
|
654
|
+
* show what the reader actually wants WITHOUT anyone second-guessing the
|
|
655
|
+
* routing decision — this component stays the ONE place that decides whether
|
|
656
|
+
* a kind has a component.
|
|
657
|
+
*
|
|
658
|
+
* Omitted → the host's floor, exactly as before.
|
|
659
|
+
*/
|
|
660
|
+
unroutableFallback?: ReactNode;
|
|
661
|
+
/**
|
|
662
|
+
* Chrome, per THE WRAPPER LAW: a host frame either IS the chrome or has none.
|
|
663
|
+
* "card" (default) keeps a bordered surface for preview surfaces. "bare"
|
|
664
|
+
* renders with NO border/background/pad — for a host that already draws a
|
|
665
|
+
* titled card, where the default produced a two-tone box-in-a-box with a dead
|
|
666
|
+
* band around it.
|
|
667
|
+
*/
|
|
668
|
+
variant?: "card" | "bare";
|
|
669
|
+
className?: string;
|
|
670
|
+
}
|
|
671
|
+
declare function KindInstanceRender({ kind, value, showRoutingNote, unroutableFallback, variant, className, }: KindInstanceRenderProps): react.JSX.Element;
|
|
672
|
+
|
|
673
|
+
/**
|
|
674
|
+
* The safety net + the "still arriving" affordance for a provisional kind
|
|
675
|
+
* render (streaming partial kinds — see `route/partial-kind-route.ts` and
|
|
676
|
+
* `common-docs/systems/content-ir-system/STREAMING_PARTIAL_KINDS.md`).
|
|
677
|
+
*
|
|
678
|
+
* TWO JOBS
|
|
679
|
+
* --------
|
|
680
|
+
* 1. **Never let a component throw mid-stream.** A provisional value may be
|
|
681
|
+
* missing required fields. The routed kind opted in to tolerating that
|
|
682
|
+
* (`partialReady`), but an opt-in is a claim, not a proof — so a throw is
|
|
683
|
+
* caught here, SCREAMS through the host's error reporter, drops the kind
|
|
684
|
+
* back to withhold for the session (`markKindPartialUnsafe`), and falls back
|
|
685
|
+
* to the kind's own loading skeleton. The user sees the pre-partial
|
|
686
|
+
* behavior, not a broken message.
|
|
687
|
+
* 2. **Say it is still arriving.** The user must be able to tell a live fill-in
|
|
688
|
+
* from a finished render, and it must not read as an error. A quiet chip
|
|
689
|
+
* rides the block's top edge — absolutely positioned and
|
|
690
|
+
* `pointer-events-none`, so it costs the content no layout and cannot shift
|
|
691
|
+
* the page when it disappears. It sits ON the border rather than inside the
|
|
692
|
+
* block: a routed kind often renders its own chrome, and a chip inside the
|
|
693
|
+
* box lands on top of those controls.
|
|
694
|
+
*
|
|
695
|
+
* No wrapper chrome: no border, no background, no padding. The kind component
|
|
696
|
+
* already carries its own (THE WRAPPER LAW).
|
|
697
|
+
*/
|
|
698
|
+
|
|
699
|
+
interface ProvisionalKindBoundaryOwnProps {
|
|
700
|
+
kind: string;
|
|
701
|
+
/** Rendered instead of the children when the provisional render throws. */
|
|
702
|
+
fallback: ReactNode;
|
|
703
|
+
children: ReactNode;
|
|
704
|
+
}
|
|
705
|
+
declare function ProvisionalKindBoundary(props: ProvisionalKindBoundaryOwnProps): react__default.JSX.Element;
|
|
706
|
+
/**
|
|
707
|
+
* The "still arriving" frame. `aria-busy` carries the same fact to assistive
|
|
708
|
+
* tech that the chip carries visually. The chip's own rendering is a host seam
|
|
709
|
+
* (`renderShimmer`) so an app with a shimmer primitive uses it and one without
|
|
710
|
+
* still says the true thing, plainly.
|
|
711
|
+
*/
|
|
712
|
+
declare function ProvisionalKindFrame({ children }: {
|
|
713
|
+
children: ReactNode;
|
|
714
|
+
}): react__default.JSX.Element;
|
|
715
|
+
|
|
716
|
+
interface GenericStructuredViewProps {
|
|
717
|
+
/** The raw region source — the zero-loss floor when no envelope survived. */
|
|
718
|
+
content: string;
|
|
719
|
+
/** Carries `__ir` (the parsed envelope) and `__ir_route` (the seam marker). */
|
|
720
|
+
metadata?: Record<string, unknown>;
|
|
721
|
+
/**
|
|
722
|
+
* What to show while the region is still streaming. Hosts with a shimmer or
|
|
723
|
+
* an icon set pass theirs; the default is the same sentence, plainly.
|
|
724
|
+
*/
|
|
725
|
+
streamingIndicator?: ReactNode;
|
|
726
|
+
className?: string;
|
|
727
|
+
}
|
|
728
|
+
declare function GenericStructuredView({ content, metadata, streamingIndicator, className, }: GenericStructuredViewProps): react.JSX.Element;
|
|
729
|
+
|
|
730
|
+
interface DelegatedOutputProps {
|
|
731
|
+
output: unknown;
|
|
732
|
+
/** The wrapper's `output_kind` — the node's DECLARATION, the fallback. */
|
|
733
|
+
declaredKind: string | null;
|
|
734
|
+
/**
|
|
735
|
+
* What to draw for a value with no kind at all, and as the unroutable
|
|
736
|
+
* fallback. Hosts with a settled-output body (the same one their readout
|
|
737
|
+
* uses — never a second reader) pass it; otherwise the floor draws it.
|
|
738
|
+
*
|
|
739
|
+
* A RENDER FUNCTION, not a node: the fallback needs the payload, and the only
|
|
740
|
+
* component that has read it is this one. Handing back a static node would
|
|
741
|
+
* force every host to re-read the wrapper itself — a second reader, which is
|
|
742
|
+
* exactly what this family exists to prevent.
|
|
743
|
+
*/
|
|
744
|
+
fallback?: (output: unknown) => ReactNode;
|
|
745
|
+
/** What to say when the step produced nothing. */
|
|
746
|
+
emptyLabel?: string;
|
|
747
|
+
}
|
|
748
|
+
/**
|
|
749
|
+
* The delegation seam — the ONLY thing these components do with a payload.
|
|
750
|
+
*
|
|
751
|
+
* In-band `__kind` wins over the node's DECLARATION, the same law a run reducer
|
|
752
|
+
* follows: the discriminator inside the value describes what we are actually
|
|
753
|
+
* holding, so it is what routes. With no kind at all there is nothing to route
|
|
754
|
+
* to, and the host's fallback (or the floor) shows what the step produced.
|
|
755
|
+
*/
|
|
756
|
+
declare function DelegatedOutput({ output, declaredKind, fallback, emptyLabel, }: DelegatedOutputProps): react.JSX.Element;
|
|
757
|
+
interface NodeOutcomeViewProps {
|
|
758
|
+
serverData?: unknown;
|
|
759
|
+
/** Passed through to {@link DelegatedOutput}. */
|
|
760
|
+
fallback?: (output: unknown) => ReactNode;
|
|
761
|
+
}
|
|
762
|
+
/** THE renderer for the `node_outcome` runtime wrapper kind. */
|
|
763
|
+
declare function NodeOutcomeView({ serverData, fallback }: NodeOutcomeViewProps): react.JSX.Element | null;
|
|
764
|
+
interface RunResultViewProps {
|
|
765
|
+
serverData?: unknown;
|
|
766
|
+
fallback?: (output: unknown) => ReactNode;
|
|
767
|
+
}
|
|
768
|
+
/**
|
|
769
|
+
* THE renderer for the `run_result` runtime wrapper kind.
|
|
770
|
+
*
|
|
771
|
+
* One finished run: one `node_outcome` per TERMINAL node — each delegated to
|
|
772
|
+
* {@link NodeOutcomeView}, which delegates the payload inside it to the data
|
|
773
|
+
* kind's own component. Recursion all the way down; no payload is rendered
|
|
774
|
+
* here, and no `final_text` is read here.
|
|
775
|
+
*
|
|
776
|
+
* The run's own `output` is rendered ONLY when the run declared no terminal
|
|
777
|
+
* outcomes — otherwise it is the same content the outcomes already carry, and
|
|
778
|
+
* showing both is the duplication the wrapper exists to prevent.
|
|
779
|
+
*/
|
|
780
|
+
declare function RunResultView({ serverData, fallback }: RunResultViewProps): react.JSX.Element | null;
|
|
781
|
+
|
|
782
|
+
export { type ComponentResolution, type ComponentResolutionSource, ComponentResolver, type ComponentResolverOptions, type ComponentRole, type ContentIrErrorReport, type ContentIrErrorReporter, type ContentIrHost, ContentIrRenderProvider, type ContentIrRenderProviderProps, type ContentIrRenderSeams, DB_KIND_COMPONENT_KEY, DelegatedOutput, type DelegatedOutputProps, GENERIC_STRUCTURED_COMPONENT_KEY, type GenericFallbackReason, GenericStructuredView, type GenericStructuredViewProps, IR_PROVISIONAL_KEY, IR_ROUTE_KEY, type IrRenderBlock, type IrRoutableBlock, type IrRouteMarker, type JsonObject, type KindComponentRow, type KindDefinitionSource, KindInstanceRender, type KindInstanceRenderProps, type KindRouteEnv, type KindRouteOptions, type KindVersionSources, NodeOutcomeView, type NodeOutcomeViewProps, type PartialRenderOptions, ProvisionalKindBoundary, ProvisionalKindFrame, type ProvisionalKindRender, RunResultView, type RunResultViewProps, type StructuredValueRenderProps, type SystemComponentEntry, applyIrKindRoute, consoleErrorReporter, envelopeFromPartialKind, isPartialReadyKind, isProvisionalBlock, isRecordValue, kindIsRoutable, kindServerDataFromStoredValue, markKindPartialUnsafe, readIrRouteMarker, resetPartialUnsafeKinds, resetSourcelessDbRowReports, resolveAnnouncedKindLoading, resolveProvisionalKindRender, routeEnvOf, useContentIrHost, useContentIrHostOrNull, useContentIrKindVersion, useKindRouteEnv };
|