@json-render/devtools 0.18.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/LICENSE +201 -0
- package/README.md +46 -0
- package/dist/index.d.mts +509 -0
- package/dist/index.d.ts +509 -0
- package/dist/index.js +3311 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +3261 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +52 -0
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,509 @@
|
|
|
1
|
+
import { Spec, JsonPatch, Catalog, StateStore, StreamChunk } from '@json-render/core';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Token usage metadata from an AI generation.
|
|
5
|
+
* Matches the shape used by renderers (e.g. `@json-render/react`).
|
|
6
|
+
*/
|
|
7
|
+
interface TokenUsage {
|
|
8
|
+
promptTokens: number;
|
|
9
|
+
completionTokens: number;
|
|
10
|
+
totalTokens: number;
|
|
11
|
+
cachedTokens?: number;
|
|
12
|
+
cacheWriteTokens?: number;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* A single devtools event. Events flow into the `EventStore` from framework
|
|
16
|
+
* adapters (state changes, action dispatches) and from stream taps.
|
|
17
|
+
*/
|
|
18
|
+
type DevtoolsEvent = {
|
|
19
|
+
kind: "spec-changed";
|
|
20
|
+
at: number;
|
|
21
|
+
spec: Spec;
|
|
22
|
+
} | {
|
|
23
|
+
kind: "state-set";
|
|
24
|
+
at: number;
|
|
25
|
+
path: string;
|
|
26
|
+
prev: unknown;
|
|
27
|
+
next: unknown;
|
|
28
|
+
} | {
|
|
29
|
+
kind: "action-dispatched";
|
|
30
|
+
at: number;
|
|
31
|
+
id: string;
|
|
32
|
+
name: string;
|
|
33
|
+
params?: unknown;
|
|
34
|
+
} | {
|
|
35
|
+
kind: "action-settled";
|
|
36
|
+
at: number;
|
|
37
|
+
id: string;
|
|
38
|
+
ok: boolean;
|
|
39
|
+
result?: unknown;
|
|
40
|
+
error?: string;
|
|
41
|
+
durationMs: number;
|
|
42
|
+
} | {
|
|
43
|
+
kind: "stream-patch";
|
|
44
|
+
at: number;
|
|
45
|
+
patch: JsonPatch;
|
|
46
|
+
source: "json" | "yaml";
|
|
47
|
+
} | {
|
|
48
|
+
kind: "stream-text";
|
|
49
|
+
at: number;
|
|
50
|
+
text: string;
|
|
51
|
+
} | {
|
|
52
|
+
kind: "stream-usage";
|
|
53
|
+
at: number;
|
|
54
|
+
usage: TokenUsage;
|
|
55
|
+
} | {
|
|
56
|
+
kind: "stream-lifecycle";
|
|
57
|
+
at: number;
|
|
58
|
+
phase: "start" | "end";
|
|
59
|
+
ok?: boolean;
|
|
60
|
+
};
|
|
61
|
+
type DevtoolsEventKind = DevtoolsEvent["kind"];
|
|
62
|
+
/**
|
|
63
|
+
* Options for creating a picker session. A picker session lets the user
|
|
64
|
+
* click an element in the host DOM to surface the matching element key
|
|
65
|
+
* in the Spec panel, and vice versa.
|
|
66
|
+
*/
|
|
67
|
+
interface PickerOptions {
|
|
68
|
+
/** Called when the user clicks an element with a `data-jr-key` attribute. */
|
|
69
|
+
onPick: (key: string) => void;
|
|
70
|
+
/** Called when the user exits picker mode without selecting. */
|
|
71
|
+
onCancel?: () => void;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Handle returned from {@link startPicker}. Call `.stop()` to tear down.
|
|
75
|
+
*/
|
|
76
|
+
interface PickerSession {
|
|
77
|
+
stop: () => void;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Options for {@link createEventStore}.
|
|
82
|
+
*/
|
|
83
|
+
interface EventStoreOptions {
|
|
84
|
+
/** Max events to retain. Older events are dropped. Default: 500. */
|
|
85
|
+
bufferSize?: number;
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* A capped, subscribable ring buffer of {@link DevtoolsEvent}s.
|
|
89
|
+
*
|
|
90
|
+
* Core to every devtools panel — all adapters push into the same store,
|
|
91
|
+
* and panel UIs subscribe for render updates.
|
|
92
|
+
*/
|
|
93
|
+
interface EventStore {
|
|
94
|
+
/** Append an event. May drop the oldest event if the buffer is full. */
|
|
95
|
+
push: (event: DevtoolsEvent) => void;
|
|
96
|
+
/**
|
|
97
|
+
* Current events in insertion order (oldest first). Returns a fresh
|
|
98
|
+
* array so callers can treat it as immutable.
|
|
99
|
+
*/
|
|
100
|
+
snapshot: () => DevtoolsEvent[];
|
|
101
|
+
/**
|
|
102
|
+
* Register a listener invoked after every push (or `clear`). Returns
|
|
103
|
+
* an unsubscribe function. Listeners are invoked synchronously.
|
|
104
|
+
*/
|
|
105
|
+
subscribe: (listener: () => void) => () => void;
|
|
106
|
+
/** Remove all events. Notifies listeners. */
|
|
107
|
+
clear: () => void;
|
|
108
|
+
/** Current event count. */
|
|
109
|
+
size: () => number;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Create an in-memory ring-buffered event store.
|
|
113
|
+
*
|
|
114
|
+
* @example
|
|
115
|
+
* ```ts
|
|
116
|
+
* const store = createEventStore({ bufferSize: 200 });
|
|
117
|
+
* const unsub = store.subscribe(() => render(store.snapshot()));
|
|
118
|
+
* store.push({ kind: "state-set", at: Date.now(), path: "/x", prev: 1, next: 2 });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
declare function createEventStore(options?: EventStoreOptions): EventStore;
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Production guard. Framework adapters short-circuit to a no-op when this
|
|
125
|
+
* returns true, so dropping `<JsonRenderDevtools />` into an app costs
|
|
126
|
+
* nothing in production builds.
|
|
127
|
+
*
|
|
128
|
+
* Tree-shaken bundlers will fold constant `process.env.NODE_ENV` checks.
|
|
129
|
+
* Consumers that run in browsers without `process` also work because the
|
|
130
|
+
* typeof check guards the access.
|
|
131
|
+
*/
|
|
132
|
+
declare function isProduction(): boolean;
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Where the devtools panel docks and where the floating toggle lives.
|
|
136
|
+
*
|
|
137
|
+
* - `bottom-right` (default) — panel docks to the bottom; toggle sits in the
|
|
138
|
+
* bottom-right corner.
|
|
139
|
+
* - `bottom-left` — panel docks to the bottom; toggle sits in the bottom-left
|
|
140
|
+
* corner. Useful when the host app already has something bottom-right.
|
|
141
|
+
* - `right` — panel docks to the right edge (full height); toggle sits in the
|
|
142
|
+
* top-right corner. Best for app-shell layouts that already use `100vh` /
|
|
143
|
+
* `position: fixed` at the bottom — right docking avoids the bottom edge
|
|
144
|
+
* entirely.
|
|
145
|
+
*/
|
|
146
|
+
type PanelPosition = "bottom-right" | "bottom-left" | "right";
|
|
147
|
+
/**
|
|
148
|
+
* A single spec available for inspection. When the host app renders one
|
|
149
|
+
* spec at a time (the common single-renderer case) this list has a single
|
|
150
|
+
* entry. Multi-renderer hosts (e.g. an AI chat where each assistant reply
|
|
151
|
+
* produces its own spec) surface every generation so the Spec tab can
|
|
152
|
+
* switch between them.
|
|
153
|
+
*/
|
|
154
|
+
interface SpecEntry {
|
|
155
|
+
/** Stable id, typically the message id that produced the spec. */
|
|
156
|
+
id: string;
|
|
157
|
+
/** Human-readable label shown in the generation switcher (e.g. "Generation 2"). */
|
|
158
|
+
label: string;
|
|
159
|
+
/** The spec itself. */
|
|
160
|
+
spec: Spec;
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Context shared with every tab. Tabs read live values via getters so they
|
|
164
|
+
* always see the latest spec/state/catalog without needing to re-mount.
|
|
165
|
+
*/
|
|
166
|
+
interface PanelContext {
|
|
167
|
+
/** Event log shared by all panels. */
|
|
168
|
+
events: EventStore;
|
|
169
|
+
/** Returns the current (usually latest) spec or `null`. */
|
|
170
|
+
getSpec: () => Spec | null;
|
|
171
|
+
/**
|
|
172
|
+
* Optional: returns every inspectable spec on the page.
|
|
173
|
+
* Hosts with multiple concurrent renderers (e.g. a chat with one spec
|
|
174
|
+
* per assistant message) provide this so the Spec tab can offer a
|
|
175
|
+
* generation switcher. When absent, the tab falls back to `getSpec()`
|
|
176
|
+
* alone.
|
|
177
|
+
*/
|
|
178
|
+
getSpecs?: () => SpecEntry[];
|
|
179
|
+
/** Returns the current catalog or `null`. */
|
|
180
|
+
getCatalog: () => Catalog | null;
|
|
181
|
+
/** Returns the live `StateStore` or `null` (only set when a provider is mounted). */
|
|
182
|
+
getStateStore: () => StateStore | null;
|
|
183
|
+
/** Start a picker session. Returns `null` if no DOM is available. */
|
|
184
|
+
startPicker?: (options: PickerOptions) => PickerSession | null;
|
|
185
|
+
/** Selection channel shared across tabs (picker <-> Spec tab). */
|
|
186
|
+
selection: SelectionBus;
|
|
187
|
+
/** Activate a specific tab by id. */
|
|
188
|
+
activateTab: (id: string) => void;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Bus for syncing the currently focused spec element key across tabs and the
|
|
192
|
+
* picker overlay. Tabs read the current value and subscribe to changes;
|
|
193
|
+
* anything that wants to focus an element (picker, tree click) calls `set`.
|
|
194
|
+
*/
|
|
195
|
+
interface SelectionBus {
|
|
196
|
+
get: () => string | null;
|
|
197
|
+
set: (key: string | null) => void;
|
|
198
|
+
subscribe: (listener: (key: string | null) => void) => () => void;
|
|
199
|
+
}
|
|
200
|
+
/** Create an in-memory {@link SelectionBus}. */
|
|
201
|
+
declare function createSelectionBus(): SelectionBus;
|
|
202
|
+
/**
|
|
203
|
+
* A tab registered with the panel. Tabs are rendered lazily — `mount` is
|
|
204
|
+
* called the first time the tab is activated, and `update` is called on
|
|
205
|
+
* every re-render request after that.
|
|
206
|
+
*/
|
|
207
|
+
interface TabDef {
|
|
208
|
+
/** Stable tab id used in URL hash / storage. */
|
|
209
|
+
id: string;
|
|
210
|
+
/** Short label shown in the tab strip. */
|
|
211
|
+
label: string;
|
|
212
|
+
/** Optional count badge, recomputed on every render. */
|
|
213
|
+
badge?: (ctx: PanelContext) => number | string | undefined;
|
|
214
|
+
/** Create the DOM for this tab. Called once per activation. */
|
|
215
|
+
mount: (root: HTMLElement, ctx: PanelContext) => TabInstance;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* A live tab. `update` is called whenever an event fires or the host
|
|
219
|
+
* refreshes; `destroy` is called when the tab is unmounted.
|
|
220
|
+
*/
|
|
221
|
+
interface TabInstance {
|
|
222
|
+
/** Re-render with latest data. */
|
|
223
|
+
update: () => void;
|
|
224
|
+
/** Clean up subscriptions / listeners. */
|
|
225
|
+
destroy?: () => void;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Options for {@link createPanel}.
|
|
229
|
+
*/
|
|
230
|
+
interface PanelOptions {
|
|
231
|
+
/** Shared panel context. */
|
|
232
|
+
context: PanelContext;
|
|
233
|
+
/** Tabs to register. Order is preserved in the tab strip. */
|
|
234
|
+
tabs: TabDef[];
|
|
235
|
+
/** Host-document node to mount under. Default: `document.body`. */
|
|
236
|
+
host?: HTMLElement;
|
|
237
|
+
/** Position of the floating toggle button. */
|
|
238
|
+
position?: PanelPosition;
|
|
239
|
+
/** Start open. Default: `false`. */
|
|
240
|
+
initialOpen?: boolean;
|
|
241
|
+
/**
|
|
242
|
+
* Keyboard shortcut to toggle the panel, or `false` to disable.
|
|
243
|
+
* Syntax: `"mod+shift+j"` (`mod` = meta on mac, ctrl elsewhere).
|
|
244
|
+
* Default: `"mod+shift+j"`.
|
|
245
|
+
*/
|
|
246
|
+
hotkey?: string | false;
|
|
247
|
+
/**
|
|
248
|
+
* Whether the panel should push the host app's content out of the way
|
|
249
|
+
* while open, by applying `padding` on `<body>` matching the panel's size.
|
|
250
|
+
*
|
|
251
|
+
* - `true` (default) — body padding is applied. Works for document-flow
|
|
252
|
+
* layouts and `height: 100%` app shells. Modern apps that use
|
|
253
|
+
* `height: 100vh`, `position: fixed; bottom: 0` etc. are effectively
|
|
254
|
+
* *overlaid* by the panel because CSS can't resize `100vh`. Pair this
|
|
255
|
+
* with `"right"` docking or opt those specific elements in via
|
|
256
|
+
* `bottom: var(--jr-devtools-offset-bottom, 0)` /
|
|
257
|
+
* `right: var(--jr-devtools-offset-right, 0)`.
|
|
258
|
+
* - `false` — the panel is a pure overlay. Nothing is pushed; the host
|
|
259
|
+
* app remains visually unchanged. The CSS custom properties
|
|
260
|
+
* `--jr-devtools-offset-bottom` / `--jr-devtools-offset-right` are
|
|
261
|
+
* still published on `:root` so apps can reserve their own space.
|
|
262
|
+
*/
|
|
263
|
+
reserveSpace?: boolean;
|
|
264
|
+
/**
|
|
265
|
+
* When `true` (default), show a toolbar button that lets the user flip
|
|
266
|
+
* the panel between bottom-dock and right-dock. The user's choice
|
|
267
|
+
* persists across reloads (localStorage key `__jr_devtools_dock`), and
|
|
268
|
+
* takes precedence over the initial `position` once set.
|
|
269
|
+
*
|
|
270
|
+
* When `false`, the dock follows `position` exactly and the toolbar
|
|
271
|
+
* button is not rendered — useful when the host app's layout only works
|
|
272
|
+
* with one dock.
|
|
273
|
+
*/
|
|
274
|
+
allowDockToggle?: boolean;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Returned from {@link createPanel}. Controls the panel lifecycle.
|
|
278
|
+
*/
|
|
279
|
+
interface PanelHandle {
|
|
280
|
+
/** Show the panel. */
|
|
281
|
+
open: () => void;
|
|
282
|
+
/** Hide the panel. */
|
|
283
|
+
close: () => void;
|
|
284
|
+
/** Toggle open/closed. */
|
|
285
|
+
toggle: () => void;
|
|
286
|
+
/** True if the panel is currently open. */
|
|
287
|
+
isOpen: () => boolean;
|
|
288
|
+
/** Request that all visible tabs re-render. */
|
|
289
|
+
refresh: () => void;
|
|
290
|
+
/** Remove the panel from the DOM and clean up. */
|
|
291
|
+
destroy: () => void;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Create a devtools panel and mount it to the host document.
|
|
296
|
+
*
|
|
297
|
+
* Idempotent per-host: if a panel is already mounted under the given host,
|
|
298
|
+
* this returns that panel's handle instead of creating a duplicate.
|
|
299
|
+
*/
|
|
300
|
+
declare function createPanel(options: PanelOptions): PanelHandle;
|
|
301
|
+
/**
|
|
302
|
+
* Mount a panel with a minimal placeholder for each tab. Useful for tests
|
|
303
|
+
* or environments where individual tab implementations aren't available.
|
|
304
|
+
*
|
|
305
|
+
* In production, consumers use {@link createPanel} with the full tab set.
|
|
306
|
+
*/
|
|
307
|
+
declare function createStubTab(id: string, label: string): TabDef;
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Tiny hyperscript-style helper for building DOM nodes without JSX.
|
|
311
|
+
*
|
|
312
|
+
* Keeps the vanilla-TS panel readable. Supports attributes starting with
|
|
313
|
+
* `on` as event listeners, `className`, inline `style` objects, and a mix
|
|
314
|
+
* of string / node / array children.
|
|
315
|
+
*/
|
|
316
|
+
type Child = Node | string | number | null | undefined | false | Child[];
|
|
317
|
+
type Attrs = {
|
|
318
|
+
[key: string]: unknown;
|
|
319
|
+
className?: string;
|
|
320
|
+
style?: Partial<CSSStyleDeclaration>;
|
|
321
|
+
};
|
|
322
|
+
declare function h<K extends keyof HTMLElementTagNameMap>(tag: K, attrs?: Attrs | null, ...children: Child[]): HTMLElementTagNameMap[K];
|
|
323
|
+
/** Replace the children of `parent` with `next`, clearing first. */
|
|
324
|
+
declare function replaceChildren(parent: Node, ...next: Child[]): void;
|
|
325
|
+
/** Render a short JSON preview that truncates long values. */
|
|
326
|
+
declare function jsonPreview(value: unknown, max?: number): string;
|
|
327
|
+
/** Format an absolute timestamp (ms) as `HH:MM:SS.mmm`. */
|
|
328
|
+
declare function formatTime(at: number): string;
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Spec Tree tab — renders the element tree with expand/collapse, shows a
|
|
332
|
+
* one-line summary per node, and highlights structural issues from
|
|
333
|
+
* `validateSpec`. Selecting a node fills the right-hand detail pane with
|
|
334
|
+
* full props + metadata.
|
|
335
|
+
*/
|
|
336
|
+
declare function specTab(): TabDef;
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* State Inspector tab — lists every leaf path in the state model with an
|
|
340
|
+
* inline editor. Editing a value re-parses it as JSON; if the input
|
|
341
|
+
* doesn't parse, the raw string is used. Reads a snapshot from the
|
|
342
|
+
* underlying StateStore on every render, plus on every state-set event.
|
|
343
|
+
*/
|
|
344
|
+
declare function stateTab(): TabDef;
|
|
345
|
+
|
|
346
|
+
/**
|
|
347
|
+
* Action Log tab — chronologically ordered list of dispatched actions.
|
|
348
|
+
* Each dispatch is paired with its settle event (by `id`) to show
|
|
349
|
+
* duration + success/failure.
|
|
350
|
+
*/
|
|
351
|
+
declare function actionsTab(): TabDef;
|
|
352
|
+
|
|
353
|
+
/**
|
|
354
|
+
* Stream Log tab — shows spec patches, text chunks, lifecycle markers,
|
|
355
|
+
* and token usage grouped by generation (lifecycle start -> end).
|
|
356
|
+
*/
|
|
357
|
+
declare function streamTab(): TabDef;
|
|
358
|
+
|
|
359
|
+
interface CatalogField {
|
|
360
|
+
name: string;
|
|
361
|
+
type: string;
|
|
362
|
+
}
|
|
363
|
+
interface CatalogComponentInfo {
|
|
364
|
+
name: string;
|
|
365
|
+
description: string;
|
|
366
|
+
props: CatalogField[];
|
|
367
|
+
slots: string[];
|
|
368
|
+
events: string[];
|
|
369
|
+
}
|
|
370
|
+
interface CatalogActionInfo {
|
|
371
|
+
name: string;
|
|
372
|
+
description: string;
|
|
373
|
+
params: CatalogField[];
|
|
374
|
+
}
|
|
375
|
+
/**
|
|
376
|
+
* Catalog Browser tab — lists the components and actions declared in the
|
|
377
|
+
* attached catalog with prop/param chips, so developers can see what the
|
|
378
|
+
* AI can use.
|
|
379
|
+
*/
|
|
380
|
+
declare function catalogTab(): TabDef;
|
|
381
|
+
/**
|
|
382
|
+
* Extract display data from a raw catalog definition. Handles both Zod v3
|
|
383
|
+
* (`_def.shape()`) and v4 (`shape` getter). Resilient to missing fields.
|
|
384
|
+
*
|
|
385
|
+
* Same logic as `apps/web/lib/render/catalog-display.ts` but lives here
|
|
386
|
+
* so framework adapters don't depend on the web app.
|
|
387
|
+
*/
|
|
388
|
+
declare function buildCatalogDisplayData(rawCatalogData: unknown): {
|
|
389
|
+
components: CatalogComponentInfo[];
|
|
390
|
+
actions: CatalogActionInfo[];
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
/**
|
|
394
|
+
* Picker tab — explains the DOM picker flow, starts / stops a picker
|
|
395
|
+
* session, and shows the currently selected element key. Selecting a key
|
|
396
|
+
* in the spec tab reflects here; selecting here (via click-to-pick)
|
|
397
|
+
* jumps back to the spec tab.
|
|
398
|
+
*/
|
|
399
|
+
declare function pickerTab(): TabDef;
|
|
400
|
+
|
|
401
|
+
/**
|
|
402
|
+
* Attribute the ElementRenderer (when devtools is active) sets on each
|
|
403
|
+
* rendered element's wrapper. The picker walks up from the hovered node
|
|
404
|
+
* to the nearest ancestor bearing this attribute.
|
|
405
|
+
*/
|
|
406
|
+
declare const DEVTOOLS_KEY_ATTR = "data-jr-key";
|
|
407
|
+
/**
|
|
408
|
+
* Start an interactive DOM picker. The user hovers or clicks any element
|
|
409
|
+
* in the page; when a click lands on (or inside) a node carrying
|
|
410
|
+
* {@link DEVTOOLS_KEY_ATTR}, `onPick` fires with that key.
|
|
411
|
+
*
|
|
412
|
+
* Returns `null` in environments without a DOM (SSR, tests).
|
|
413
|
+
*
|
|
414
|
+
* The picker paints a translucent overlay + border over the hovered
|
|
415
|
+
* element (Chrome-DevTools style). See {@link computeBounds} for the
|
|
416
|
+
* `display: contents` fallback.
|
|
417
|
+
*/
|
|
418
|
+
declare function startPicker(options: PickerOptions): PickerSession | null;
|
|
419
|
+
/**
|
|
420
|
+
* Show (or hide) a persistent bounding-box overlay over the element
|
|
421
|
+
* identified by `key`. Pass `null` to clear the overlay.
|
|
422
|
+
*
|
|
423
|
+
* Unlike {@link highlightElement}, this does not fade out — callers are
|
|
424
|
+
* expected to clear it explicitly (typically on `mouseleave`). Safe to
|
|
425
|
+
* call repeatedly; each call cheaply repositions the single overlay.
|
|
426
|
+
*/
|
|
427
|
+
declare function setHoverHighlight(key: string | null): void;
|
|
428
|
+
/**
|
|
429
|
+
* Look up the DOM element carrying `data-jr-key={key}`. Returns `null`
|
|
430
|
+
* when no match (spec exists but hasn't rendered, or the element is
|
|
431
|
+
* currently hidden by a visibility condition).
|
|
432
|
+
*
|
|
433
|
+
* Note: when an element appears inside a `repeat`, each repetition
|
|
434
|
+
* renders its own DOM instance with the same `data-jr-key`. Use
|
|
435
|
+
* {@link findAllElementsByKey} if you need all of them.
|
|
436
|
+
*/
|
|
437
|
+
declare function findElementByKey(key: string): Element | null;
|
|
438
|
+
/**
|
|
439
|
+
* Return every DOM element carrying `data-jr-key={key}`. Intended for
|
|
440
|
+
* repeated spec elements (list items, grid cells…) where a single spec
|
|
441
|
+
* key renders to N DOM instances.
|
|
442
|
+
*/
|
|
443
|
+
declare function findAllElementsByKey(key: string): Element[];
|
|
444
|
+
/**
|
|
445
|
+
* Briefly paint an outline around the DOM element for `key`, so clicking
|
|
446
|
+
* a spec-tree row in the panel flashes its position in the page.
|
|
447
|
+
*
|
|
448
|
+
* The target is often a `display: contents` wrapper, so we build the
|
|
449
|
+
* overlay from `computeBounds` (descendants' client rects) instead of
|
|
450
|
+
* using a CSS outline on the target directly.
|
|
451
|
+
*/
|
|
452
|
+
declare function highlightElement(key: string, durationMs?: number): void;
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* A minimal shape compatible with AI SDK `UIMessage.parts[i]`. Defined
|
|
456
|
+
* locally so the devtools package has no dependency on the `ai` package.
|
|
457
|
+
*/
|
|
458
|
+
interface DataPart {
|
|
459
|
+
type: string;
|
|
460
|
+
text?: string;
|
|
461
|
+
data?: unknown;
|
|
462
|
+
state?: string;
|
|
463
|
+
}
|
|
464
|
+
/**
|
|
465
|
+
* Wrap a `ReadableStream<StreamChunk>` (e.g. the output of `pipeJsonRender`
|
|
466
|
+
* or any `TransformStream<StreamChunk, StreamChunk>`) so spec patches are
|
|
467
|
+
* mirrored into a devtools `EventStore` as they fly past.
|
|
468
|
+
*
|
|
469
|
+
* Returns the original stream unchanged — the tap just forks a copy.
|
|
470
|
+
*
|
|
471
|
+
* @example
|
|
472
|
+
* ```ts
|
|
473
|
+
* writer.merge(
|
|
474
|
+
* tapJsonRenderStream(
|
|
475
|
+
* pipeJsonRender(result.toUIMessageStream()),
|
|
476
|
+
* devtoolsEventStore,
|
|
477
|
+
* ),
|
|
478
|
+
* );
|
|
479
|
+
* ```
|
|
480
|
+
*/
|
|
481
|
+
declare function tapJsonRenderStream(stream: ReadableStream<StreamChunk>, events: EventStore): ReadableStream<StreamChunk>;
|
|
482
|
+
/** YAML variant — identical behaviour with `source: "yaml"`. */
|
|
483
|
+
declare function tapYamlStream(stream: ReadableStream<StreamChunk>, events: EventStore): ReadableStream<StreamChunk>;
|
|
484
|
+
/**
|
|
485
|
+
* Client-side helper: scan a message's `parts` array for spec data parts
|
|
486
|
+
* and push matching events into the store. Use this when rendering chat
|
|
487
|
+
* UIs that use `@ai-sdk/react` `useChat` and pass in `messages`.
|
|
488
|
+
*
|
|
489
|
+
* Idempotent via `seenIds`: only parts not already recorded will emit.
|
|
490
|
+
* Returns the new `seenIds` set so callers can persist it between calls.
|
|
491
|
+
*/
|
|
492
|
+
declare function scanMessageParts(parts: readonly DataPart[] | undefined, events: EventStore, seen: WeakSet<object>): void;
|
|
493
|
+
/**
|
|
494
|
+
* Emit a token-usage event. Called by adapters with whatever usage
|
|
495
|
+
* object their framework surfaces (AI SDK `result.usage`).
|
|
496
|
+
*/
|
|
497
|
+
declare function recordUsage(events: EventStore, usage: TokenUsage): void;
|
|
498
|
+
/**
|
|
499
|
+
* Replay every `SPEC_DATA_PART` in `parts` and return the resulting spec,
|
|
500
|
+
* or `null` if the message has no UI. Mirrors the framework-side
|
|
501
|
+
* `buildSpecFromParts` helper but without a framework dependency — used by
|
|
502
|
+
* the devtools panel's generation switcher to reconstruct each prior
|
|
503
|
+
* assistant message's spec so the user can inspect any of them.
|
|
504
|
+
*/
|
|
505
|
+
declare function extractSpecFromParts(parts: readonly DataPart[] | undefined): Spec | null;
|
|
506
|
+
/** Emit a pre-built devtools event. Useful for manual instrumentation. */
|
|
507
|
+
declare function recordEvent(events: EventStore, event: DevtoolsEvent): void;
|
|
508
|
+
|
|
509
|
+
export { DEVTOOLS_KEY_ATTR, type DevtoolsEvent, type DevtoolsEventKind, type EventStore, type EventStoreOptions, type PanelContext, type PanelHandle, type PanelOptions, type PanelPosition, type PickerOptions, type PickerSession, type SelectionBus, type SpecEntry, type TabDef, type TabInstance, type TokenUsage, actionsTab, buildCatalogDisplayData, catalogTab, createEventStore, createPanel, createSelectionBus, createStubTab, extractSpecFromParts, findAllElementsByKey, findElementByKey, formatTime, h, highlightElement, isProduction, jsonPreview, pickerTab, recordEvent, recordUsage, replaceChildren, scanMessageParts, setHoverHighlight, specTab, startPicker, stateTab, streamTab, tapJsonRenderStream, tapYamlStream };
|