@copilotkit/web-inspector 1.79.2-canary.1792172552 → 1.81.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 (36) hide show
  1. package/dist/components/generative-ui-view.cjs +939 -0
  2. package/dist/components/generative-ui-view.cjs.map +1 -0
  3. package/dist/components/generative-ui-view.d.mts +3 -0
  4. package/dist/components/generative-ui-view.mjs +940 -0
  5. package/dist/components/generative-ui-view.mjs.map +1 -0
  6. package/dist/components/learning-view.cjs +145 -10
  7. package/dist/components/learning-view.cjs.map +1 -1
  8. package/dist/components/learning-view.mjs +145 -10
  9. package/dist/components/learning-view.mjs.map +1 -1
  10. package/dist/index.cjs +79 -155
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +6 -23
  13. package/dist/index.d.cts.map +1 -1
  14. package/dist/index.d.mts +7 -23
  15. package/dist/index.d.mts.map +1 -1
  16. package/dist/index.mjs +63 -139
  17. package/dist/index.mjs.map +1 -1
  18. package/dist/index.umd.js +1427 -289
  19. package/dist/index.umd.js.map +1 -1
  20. package/dist/lib/inspector-nav.cjs +2 -1
  21. package/dist/lib/inspector-nav.cjs.map +1 -1
  22. package/dist/lib/inspector-nav.mjs +2 -1
  23. package/dist/lib/inspector-nav.mjs.map +1 -1
  24. package/dist/lib/json-block.cjs +139 -0
  25. package/dist/lib/json-block.cjs.map +1 -0
  26. package/dist/lib/json-block.d.cts +26 -0
  27. package/dist/lib/json-block.d.cts.map +1 -0
  28. package/dist/lib/json-block.d.mts +28 -0
  29. package/dist/lib/json-block.d.mts.map +1 -0
  30. package/dist/lib/json-block.mjs +134 -0
  31. package/dist/lib/json-block.mjs.map +1 -0
  32. package/dist/lib/telemetry.cjs.map +1 -1
  33. package/dist/lib/telemetry.mjs.map +1 -1
  34. package/dist/package.cjs +1 -1
  35. package/dist/package.mjs +1 -1
  36. package/package.json +5 -5
@@ -0,0 +1,939 @@
1
+ const require_json_block = require('../lib/json-block.cjs');
2
+ let lit = require("lit");
3
+ let _copilotkit_shared = require("@copilotkit/shared");
4
+
5
+ //#region src/components/generative-ui-view.ts
6
+ const TABS = [
7
+ {
8
+ key: "surfaces",
9
+ label: "Surfaces"
10
+ },
11
+ {
12
+ key: "catalog",
13
+ label: "Catalog"
14
+ },
15
+ {
16
+ key: "prompt",
17
+ label: "Prompt"
18
+ }
19
+ ];
20
+ const PROMPT_SOURCE_NOTES = {
21
+ runtime: "The runtime adds this text as a context entry, with the render_ui tool.",
22
+ context: "The provider sends this text as a context entry.",
23
+ backend: "sendContext is false. Your backend builds the prompt, usually from this text."
24
+ };
25
+ /** A rough token count: about 4 characters for each token. */
26
+ function estimateTokens(text) {
27
+ return Math.ceil(text.length / 4);
28
+ }
29
+ function formatTokens(text) {
30
+ return `~${estimateTokens(text).toLocaleString()} tokens`;
31
+ }
32
+ function json(value) {
33
+ return JSON.stringify(value, null, 2) ?? "undefined";
34
+ }
35
+ /** The kind of an A2UI operation, for example `updateComponents`. */
36
+ function operationKind(operation) {
37
+ if (typeof operation !== "object" || operation === null) return "unknown";
38
+ return Object.keys(operation).find((key) => key !== "version") ?? "unknown";
39
+ }
40
+ /**
41
+ * The component tree of a surface, from its root. Later operations replace
42
+ * components with the same id. Skipped operations (rejected by the browser)
43
+ * are left out. A slot id with no component yet is left out too.
44
+ */
45
+ function componentTree(operations, skip, catalog) {
46
+ const byId = /* @__PURE__ */ new Map();
47
+ operations.forEach((operation, index) => {
48
+ if (skip.has(index)) return;
49
+ const components = "createSurface" in operation ? operation.createSurface.components : "updateComponents" in operation ? operation.updateComponents.components : void 0;
50
+ for (const node of components ?? []) byId.set(node.id, node);
51
+ });
52
+ const seen = /* @__PURE__ */ new Set();
53
+ const build = (id, repeat) => {
54
+ const node = typeof id === "string" ? byId.get(id) : void 0;
55
+ if (!node || seen.has(node.id)) return [];
56
+ seen.add(node.id);
57
+ const { id: _id, component, ...rest } = node;
58
+ const manifest = catalog[component];
59
+ const refs = manifest ? (0, _copilotkit_shared.collectChildRefs)(manifest.props) : [];
60
+ const childKeys = new Set([...Object.keys(manifest?.slots ?? {}), ...refs.filter((ref) => ref.path.length === 1).map((ref) => ref.path[0])]);
61
+ const nested = refs.filter((ref) => ref.path.length > 1);
62
+ const props = {};
63
+ const children = [];
64
+ for (const [name, value] of Object.entries(rest)) if (!childKeys.has(name)) props[name] = value;
65
+ else if (Array.isArray(value)) for (const child of value) children.push(...build(child));
66
+ else if (typeof value === "object" && value !== null) {
67
+ const template = value;
68
+ children.push(...build(template.componentId, template.path));
69
+ } else children.push(...build(value));
70
+ for (const child of (0, _copilotkit_shared.childIdsAtRefs)(rest, nested)) children.push(...build(child));
71
+ return [{
72
+ id: node.id,
73
+ component,
74
+ props,
75
+ ...repeat ? { repeat } : {},
76
+ children
77
+ }];
78
+ };
79
+ return build(_copilotkit_shared.GENERATIVE_UI_ROOT_ID)[0];
80
+ }
81
+ /** The first element of the page whose `attribute` is `value`. */
82
+ function findOnPage(attribute, value) {
83
+ return [...document.querySelectorAll(`[${attribute}]`)].find((element) => element.getAttribute(attribute) === value);
84
+ }
85
+ /**
86
+ * The function problem that the inspector shows. A function goes to the
87
+ * model only with exactly one mounted handler.
88
+ */
89
+ /**
90
+ * Splits components by the catalog that declared them: the catalog of the
91
+ * provider first, then each base in the order of `extends`.
92
+ */
93
+ function groupByCatalog(components, snapshot) {
94
+ const groups = new Map([[snapshot.catalogId, []]]);
95
+ for (const entry of components) {
96
+ const id = snapshot.componentCatalogs[entry[0]] ?? snapshot.catalogId;
97
+ groups.set(id, [...groups.get(id) ?? [], entry]);
98
+ }
99
+ return [...groups].filter(([, group]) => group.length > 0);
100
+ }
101
+ function functionHandlerProblem(handlers) {
102
+ if (handlers === 1) return void 0;
103
+ if (handlers === 0) return "No useGenerativeUIFunction handler is mounted, so the model does not get this function.";
104
+ return `${handlers} handlers are mounted. Mount exactly one, or the model does not get this function.`;
105
+ }
106
+ /**
107
+ * The Generative UI pane: the catalog, the targets and surfaces on the page,
108
+ * and what a run adds to the prompt of the model.
109
+ */
110
+ var CpkGenerativeUIView = class extends lit.LitElement {
111
+ constructor(..._args) {
112
+ super(..._args);
113
+ this.tab = "surfaces";
114
+ this.run = "last";
115
+ this.filter = "";
116
+ this.expanded = /* @__PURE__ */ new Set();
117
+ this.copied = null;
118
+ this.unsubscribe = null;
119
+ this.outlined = null;
120
+ }
121
+ static {
122
+ this.properties = { source: { attribute: false } };
123
+ }
124
+ disconnectedCallback() {
125
+ super.disconnectedCallback();
126
+ this.unhighlight();
127
+ this.unsubscribe?.();
128
+ this.unsubscribe = null;
129
+ this.subscribedSource = void 0;
130
+ }
131
+ willUpdate() {
132
+ if (this.source === this.subscribedSource && this.unsubscribe) return;
133
+ this.unsubscribe?.();
134
+ this.subscribedSource = this.source;
135
+ this.unsubscribe = this.source?.subscribe(() => this.requestUpdate()) ?? null;
136
+ }
137
+ toggle(key) {
138
+ if (this.expanded.has(key)) this.expanded.delete(key);
139
+ else this.expanded.add(key);
140
+ this.requestUpdate();
141
+ }
142
+ async copy(key, text) {
143
+ try {
144
+ await navigator.clipboard.writeText(text);
145
+ this.copied = key;
146
+ } catch {
147
+ this.copied = null;
148
+ }
149
+ this.requestUpdate();
150
+ setTimeout(() => {
151
+ if (this.copied !== key) return;
152
+ this.copied = null;
153
+ this.requestUpdate();
154
+ }, 1500);
155
+ }
156
+ /**
157
+ * Outlines an element of the page and scrolls it into view, until
158
+ * `unhighlight`. Hover and keyboard focus call these two.
159
+ */
160
+ highlight(element) {
161
+ this.unhighlight();
162
+ if (!element) return;
163
+ const { outline, outlineOffset } = element.style;
164
+ this.outlined = {
165
+ element,
166
+ outline,
167
+ outlineOffset
168
+ };
169
+ element.style.outline = "2px solid #7567ff";
170
+ element.style.outlineOffset = "4px";
171
+ element.scrollIntoView({
172
+ behavior: "smooth",
173
+ block: "nearest"
174
+ });
175
+ }
176
+ unhighlight() {
177
+ if (!this.outlined) return;
178
+ const { element, outline, outlineOffset } = this.outlined;
179
+ element.style.outline = outline;
180
+ element.style.outlineOffset = outlineOffset;
181
+ this.outlined = null;
182
+ }
183
+ render() {
184
+ if (!this.source) return lit.html`
185
+ <div class="empty">
186
+ <p class="strong">No generative UI</p>
187
+ <p>
188
+ Pass <code>generativeUI</code> to <code>CopilotKitProvider</code>, and this
189
+ pane shows its catalog, surfaces, and prompt.
190
+ </p>
191
+ </div>
192
+ `;
193
+ const snapshot = this.source.getSnapshot();
194
+ return lit.html`
195
+ <header class="header">
196
+ <div class="title-row">
197
+ <h2>Generative UI</h2>
198
+ <span class="chip">${snapshot.transport} transport</span>
199
+ <code class="muted">${snapshot.catalogId}</code>
200
+ </div>
201
+ <p class="muted small">
202
+ ${snapshot.agentIds ? `For agents: ${snapshot.agentIds.join(", ")}` : "For every agent"}
203
+ · ${Object.keys(snapshot.components).length} components ·
204
+ ${Object.keys(snapshot.functions).length} functions ·
205
+ ${snapshot.surfaces.length} surfaces
206
+ </p>
207
+ <nav class="tabs" role="tablist">
208
+ ${TABS.map((tab) => lit.html`<button
209
+ type="button"
210
+ role="tab"
211
+ aria-selected=${this.tab === tab.key}
212
+ class="tab ${this.tab === tab.key ? "active" : ""}"
213
+ @click=${() => {
214
+ this.tab = tab.key;
215
+ this.requestUpdate();
216
+ }}
217
+ >
218
+ ${tab.label}
219
+ </button>`)}
220
+ </nav>
221
+ </header>
222
+ <div class="body">
223
+ ${this.tab === "surfaces" ? this.renderSurfaces(snapshot) : this.tab === "catalog" ? this.renderCatalog(snapshot) : this.renderPrompt(snapshot)}
224
+ </div>
225
+ `;
226
+ }
227
+ renderSurfaces(snapshot) {
228
+ const stateKeys = Object.keys(snapshot.state);
229
+ const active = snapshot.surfaces.filter((surface) => surface.threadId === snapshot.activeThreadId);
230
+ const other = snapshot.surfaces.filter((surface) => surface.threadId !== snapshot.activeThreadId);
231
+ return lit.html`
232
+ <section>
233
+ <h3>Targets</h3>
234
+ <p class="muted small">
235
+ Where the model can render. The model sees each description.
236
+ </p>
237
+ ${snapshot.targets.map((target) => {
238
+ const show = () => this.highlight(findOnPage("data-generative-ui-surface", target.id));
239
+ return lit.html`<div
240
+ class="row"
241
+ @mouseenter=${show}
242
+ @mouseleave=${this.unhighlight}
243
+ >
244
+ <div class="row-main">
245
+ <div class="row-title">
246
+ <code>${target.id}</code>
247
+ <span class="chip">${target.kind}</span>
248
+ ${target.components ? lit.html`<span class="chip"
249
+ >${target.components.length} components only</span
250
+ >` : lit.nothing}
251
+ </div>
252
+ ${target.description ? lit.html`<p class="small">${target.description}</p>` : target.kind === "inline" ? lit.html`
253
+ <p class="small warn">
254
+ No description. Give the surface a description, so the model knows what to put
255
+ in it.
256
+ </p>
257
+ ` : lit.nothing}
258
+ ${target.components ? lit.html`<p class="muted small">
259
+ ${target.components.join(", ") || "No components"}
260
+ </p>` : lit.nothing}
261
+ </div>
262
+ </div>`;
263
+ })}
264
+ </section>
265
+ <section>
266
+ <h3>Surfaces in this thread</h3>
267
+ ${active.length === 0 ? lit.html`
268
+ <p class="muted small">No surfaces yet. Ask the chat for something visual.</p>
269
+ ` : active.map((surface) => this.renderSurface(surface, snapshot.components))}
270
+ ${other.length > 0 ? lit.html`<h4>Other threads</h4>
271
+ ${other.map((surface) => this.renderSurface(surface, snapshot.components))}` : lit.nothing}
272
+ </section>
273
+ <section>
274
+ <h3>App state</h3>
275
+ <p class="muted small">
276
+ Bound props read these values. The model does not see them.
277
+ </p>
278
+ ${stateKeys.length === 0 ? lit.html`
279
+ <p class="muted small">No state is set.</p>
280
+ ` : require_json_block.renderHighlightedJsonBlock(snapshot.state)}
281
+ </section>
282
+ `;
283
+ }
284
+ renderComponent(node, key) {
285
+ const nodeKey = `${key}:component:${node.id}`;
286
+ const propCount = Object.keys(node.props).length;
287
+ return lit.html`<li>
288
+ <button
289
+ type="button"
290
+ class="op-toggle"
291
+ aria-expanded=${this.expanded.has(nodeKey)}
292
+ @click=${() => this.toggle(nodeKey)}
293
+ >
294
+ <code>${node.component}</code>
295
+ <span class="muted small">${node.id}</span>
296
+ ${node.repeat ? lit.html`<span class="chip">each item of ${node.repeat}</span>` : lit.nothing}
297
+ <span class="muted small">${propCount} props</span>
298
+ </button>
299
+ ${this.expanded.has(nodeKey) ? require_json_block.renderHighlightedJsonBlock(node.props) : lit.nothing}
300
+ ${node.children.length > 0 ? lit.html`<ul class="tree">
301
+ ${node.children.map((child) => this.renderComponent(child, key))}
302
+ </ul>` : lit.nothing}
303
+ </li>`;
304
+ }
305
+ renderSurface(surface, catalog) {
306
+ const key = `surface:${surface.threadId}:${surface.surfaceId}`;
307
+ const isOpen = this.expanded.has(key);
308
+ const userPaths = Object.keys(surface.userValues);
309
+ const browserRejected = new Set(surface.rejected.filter((rejection) => rejection.source === "browser").map((rejection) => rejection.index));
310
+ const tree = isOpen ? componentTree(surface.operations, browserRejected, catalog) : void 0;
311
+ const show = () => this.highlight(findOnPage("data-generative-ui-root", surface.surfaceId)?.closest("[data-generative-ui-surface]"));
312
+ return lit.html`<div
313
+ class="card"
314
+ @mouseenter=${show}
315
+ @mouseleave=${this.unhighlight}
316
+ @focusin=${show}
317
+ @focusout=${this.unhighlight}
318
+ >
319
+ <div class="card-head">
320
+ <button
321
+ type="button"
322
+ class="card-toggle"
323
+ aria-expanded=${isOpen}
324
+ @click=${() => this.toggle(key)}
325
+ >
326
+ <span class="row-title">
327
+ <code>${surface.surfaceId}</code>
328
+ <span class="chip status-${surface.status}">${surface.status}</span>
329
+ <span class="muted small">in ${surface.target}</span>
330
+ </span>
331
+ <span class="muted small">
332
+ ${surface.operations.length} operations
333
+ ${surface.rejected.length > 0 ? lit.html`·
334
+ <span class="danger"
335
+ >${surface.rejected.length} rejected</span
336
+ >` : lit.nothing}
337
+ ${userPaths.length > 0 ? lit.html`· ${userPaths.length} user values` : lit.nothing}
338
+ </span>
339
+ </button>
340
+ </div>
341
+ ${isOpen ? lit.html`<div class="card-body">
342
+ ${surface.rejected.length > 0 ? lit.html`<h4>Rejected operations</h4>
343
+ <p class="muted small">
344
+ These were dropped. The model gets them on its next run, so
345
+ it can fix them.
346
+ </p>
347
+ <ul class="list">
348
+ ${surface.rejected.map((rejection) => lit.html`<li class="danger">
349
+ <span class="chip">${rejection.source}</span>
350
+ operation ${rejection.index}: ${rejection.reason}
351
+ </li>`)}
352
+ </ul>` : lit.nothing}
353
+ ${userPaths.length > 0 ? lit.html`<h4>User values</h4>
354
+ <p class="muted small">
355
+ The user wrote these paths. Agent writes to them are
356
+ ignored.
357
+ </p>
358
+ ${require_json_block.renderHighlightedJsonBlock(surface.userValues)}` : lit.nothing}
359
+ <h4>Components</h4>
360
+ ${tree ? lit.html`<ul class="tree root">
361
+ ${this.renderComponent(tree, key)}
362
+ </ul>` : lit.html`
363
+ <p class="muted small">No root component yet.</p>
364
+ `}
365
+ <h4>Data model</h4>
366
+ ${require_json_block.renderHighlightedJsonBlock(surface.dataModel)}
367
+ <h4>Operations</h4>
368
+ <ol class="ops">
369
+ ${surface.operations.map((operation, index) => {
370
+ const opKey = `${key}:op:${index}`;
371
+ const rejected = browserRejected.has(index);
372
+ return lit.html`<li class=${rejected ? "danger" : ""}>
373
+ <button
374
+ type="button"
375
+ class="op-toggle"
376
+ aria-expanded=${this.expanded.has(opKey)}
377
+ @click=${() => this.toggle(opKey)}
378
+ >
379
+ <span class="muted">${index}</span>
380
+ <code>${operationKind(operation)}</code>
381
+ ${rejected ? lit.html`
382
+ <span class="chip">rejected</span>
383
+ ` : lit.nothing}
384
+ </button>
385
+ ${this.expanded.has(opKey) ? require_json_block.renderHighlightedJsonBlock(operation) : lit.nothing}
386
+ </li>`;
387
+ })}
388
+ </ol>
389
+ <p class="muted small">Thread <code>${surface.threadId}</code></p>
390
+ </div>` : lit.nothing}
391
+ </div>`;
392
+ }
393
+ renderCatalogComponent(name, component) {
394
+ const key = `component:${name}`;
395
+ const isOpen = this.expanded.has(key);
396
+ const events = Object.keys(component.events ?? {});
397
+ return lit.html`<div class="card">
398
+ <button
399
+ type="button"
400
+ class="card-toggle"
401
+ aria-expanded=${isOpen}
402
+ @click=${() => this.toggle(key)}
403
+ >
404
+ <span class="row-title">
405
+ <code>${name}</code>
406
+ ${[...Object.entries(component.slots ?? {}), ...(0, _copilotkit_shared.collectChildRefs)(component.props).map((ref) => [ref.path.join("."), ref.kind])].map(([slot, kind]) => lit.html`<span class="chip">${slot}: ${kind}</span>`)}
407
+ ${events.map((event) => lit.html`<span class="chip event">${event}</span>`)}
408
+ </span>
409
+ ${component.description ? lit.html`<span class="small">${component.description}</span>` : lit.html`
410
+ <span class="small warn">No description</span>
411
+ `}
412
+ </button>
413
+ ${isOpen ? lit.html`<div class="card-body">
414
+ <h4>Props (JSON Schema)</h4>
415
+ ${require_json_block.renderHighlightedJsonBlock(component.props)}
416
+ ${component.events ? lit.html`<h4>Events</h4>
417
+ ${require_json_block.renderHighlightedJsonBlock(component.events)}` : lit.nothing}
418
+ </div>` : lit.nothing}
419
+ </div>`;
420
+ }
421
+ renderCatalog(snapshot) {
422
+ const query = this.filter.trim().toLowerCase();
423
+ const matches = ([name, entry]) => !query || name.toLowerCase().includes(query) || entry.description?.toLowerCase().includes(query);
424
+ const components = Object.entries(snapshot.components).filter(matches);
425
+ const functions = Object.entries(snapshot.functions).filter(matches);
426
+ return lit.html`
427
+ <section>
428
+ <div class="section-head">
429
+ <h3>Components</h3>
430
+ <input
431
+ class="filter"
432
+ type="search"
433
+ placeholder="Search"
434
+ aria-label="Search components and functions"
435
+ .value=${this.filter}
436
+ @input=${(event) => {
437
+ this.filter = event.target.value;
438
+ this.requestUpdate();
439
+ }}
440
+ />
441
+ </div>
442
+ <p class="muted small">
443
+ ${Object.keys(snapshot.components).length} components ·
444
+ ${formatTokens(JSON.stringify(snapshot.components))} in the envelope
445
+ </p>
446
+ ${groupByCatalog(components, snapshot).map(([catalogId, group]) => {
447
+ const key = `catalog:${catalogId}`;
448
+ const isOwn = catalogId === snapshot.catalogId;
449
+ const toggled = this.expanded.has(key);
450
+ const isOpen = query !== "" || (isOwn ? !toggled : toggled);
451
+ return lit.html`<h4>
452
+ <button
453
+ type="button"
454
+ class="op-toggle catalog-toggle"
455
+ aria-expanded=${isOpen}
456
+ @click=${() => this.toggle(key)}
457
+ >
458
+ <code>${catalogId}</code>
459
+ ${isOwn ? lit.nothing : lit.html`
460
+ <span class="chip">extended</span>
461
+ `}
462
+ <span class="muted small">${group.length} components</span>
463
+ </button>
464
+ </h4>
465
+ ${isOpen ? group.map(([name, component]) => this.renderCatalogComponent(name, component)) : lit.nothing}`;
466
+ })}
467
+ ${query && components.length === 0 ? lit.html`
468
+ <p class="muted small">No component matches.</p>
469
+ ` : lit.nothing}
470
+ </section>
471
+ <section>
472
+ <h3>Functions</h3>
473
+ ${functions.length === 0 ? lit.html`<p class="muted small">
474
+ ${query ? "No function matches." : "No functions are declared."}
475
+ </p>` : functions.map(([name, fn]) => {
476
+ const problem = functionHandlerProblem(fn.handlers);
477
+ return lit.html`<div class="card">
478
+ <div class="card-body">
479
+ <div class="row-title">
480
+ <code>${name}</code>
481
+ <span
482
+ class="chip ${problem ? "status-error" : "status-ready"}"
483
+ >${fn.handlers}
484
+ handler${fn.handlers === 1 ? "" : "s"}</span
485
+ >
486
+ </div>
487
+ ${fn.description ? lit.html`<p class="small">${fn.description}</p>` : lit.nothing}
488
+ ${problem ? lit.html`<p class="small warn">${problem}</p>` : lit.nothing}
489
+ ${require_json_block.renderHighlightedJsonBlock(fn.parameters)}
490
+ </div>
491
+ </div>`;
492
+ })}
493
+ </section>
494
+ `;
495
+ }
496
+ /**
497
+ * The prompt text and the envelope are large (about 90,000 characters
498
+ * each in the shop), and the next run changes with each surface change.
499
+ * So they are drawn only when open.
500
+ */
501
+ renderShowButton(key) {
502
+ const open = this.expanded.has(key);
503
+ return lit.html`<button
504
+ type="button"
505
+ class="button"
506
+ aria-expanded=${open}
507
+ @click=${() => this.toggle(key)}
508
+ >
509
+ ${open ? "Hide" : "Show"}
510
+ </button>`;
511
+ }
512
+ renderPrompt(snapshot) {
513
+ const showing = this.run === "last" && snapshot.lastRun ? "last" : "next";
514
+ const run = showing === "last" && snapshot.lastRun ? snapshot.lastRun : snapshot.nextRun;
515
+ const isLast = showing === "last";
516
+ const envelope = json(run.envelope);
517
+ return lit.html`
518
+ <div class="segmented" role="radiogroup">
519
+ ${["last", "next"].map((option) => lit.html`<button
520
+ type="button"
521
+ role="radio"
522
+ aria-checked=${showing === option}
523
+ class="tab ${showing === option ? "active" : ""}"
524
+ ?disabled=${option === "last" && !snapshot.lastRun}
525
+ @click=${() => {
526
+ this.run = option;
527
+ this.requestUpdate();
528
+ }}
529
+ >
530
+ ${option === "last" ? "Last run" : "Next run"}
531
+ </button>`)}
532
+ </div>
533
+ <p class="muted small">
534
+ ${isLast ? lit.html`What the last run of
535
+ <code>${run.agentId ?? "the agent"}</code> sent${run.startedAt ? `, at ${new Date(run.startedAt).toLocaleTimeString()}` : ""}.` : lit.html`
536
+ What the next run will send, from the page as it is now.
537
+ `}
538
+ Your own system prompt and tools are not shown.
539
+ </p>
540
+ ${run.prompt.map((section, index) => {
541
+ const key = `prompt:${index}`;
542
+ return lit.html`<section>
543
+ <div class="section-head">
544
+ <h3>${section.title}</h3>
545
+ <span class="muted small">${formatTokens(section.text)}</span>
546
+ ${this.renderShowButton(key)}
547
+ <button
548
+ type="button"
549
+ class="button"
550
+ @click=${() => void this.copy(key, section.text)}
551
+ >
552
+ ${this.copied === key ? "Copied" : "Copy"}
553
+ </button>
554
+ </div>
555
+ <p class="muted small">${PROMPT_SOURCE_NOTES[section.source]}</p>
556
+ ${this.expanded.has(key) ? lit.html`<pre class="prompt">${section.text || "(empty)"}</pre>` : lit.nothing}
557
+ </section>`;
558
+ })}
559
+ <section>
560
+ <div class="section-head">
561
+ <h3>Envelope</h3>
562
+ <span class="muted small">${formatTokens(envelope)}</span>
563
+ ${this.renderShowButton("envelope")}
564
+ <button
565
+ type="button"
566
+ class="button"
567
+ @click=${() => void this.copy("envelope", envelope)}
568
+ >
569
+ ${this.copied === "envelope" ? "Copied" : "Copy"}
570
+ </button>
571
+ </div>
572
+ <p class="muted small">
573
+ The run sends this as <code>forwardedProps.copilotkit.ui</code>.
574
+ </p>
575
+ ${this.expanded.has("envelope") ? require_json_block.renderHighlightedJsonBlock(run.envelope) : lit.nothing}
576
+ </section>
577
+ `;
578
+ }
579
+ static {
580
+ this.styles = lit.css`
581
+ :host {
582
+ --gui-ink: #202127;
583
+ --gui-muted: #64656f;
584
+ --gui-line: #dcdce4;
585
+ --gui-soft: #f7f7fa;
586
+ --gui-canvas: #fff;
587
+ --gui-accent: #7567ff;
588
+ --gui-accent-soft: #f0edff;
589
+ --gui-green: #168b69;
590
+ --gui-green-soft: #eaf6f1;
591
+ --gui-amber: #8a5a00;
592
+ --gui-amber-soft: #fff6e0;
593
+ --gui-danger: #a12f2f;
594
+ --gui-danger-soft: #fff4f4;
595
+ --cpk-json-key: #3d408f;
596
+ --cpk-json-str: #0b6b4c;
597
+ --cpk-json-num: #8a5900;
598
+ --cpk-json-bool: #c0333a;
599
+ --cpk-json-nil: #57575b;
600
+ display: block;
601
+ height: 100%;
602
+ overflow: auto;
603
+ color: var(--gui-ink);
604
+ background: var(--gui-canvas);
605
+ font-family: Inter, ui-sans-serif, system-ui, sans-serif;
606
+ font-size: 12px;
607
+ }
608
+ :host([data-color-scheme="dark"]) {
609
+ color-scheme: dark;
610
+ --gui-ink: #f3f4f8;
611
+ --gui-muted: #b0b3be;
612
+ --gui-line: #3a3e4b;
613
+ --gui-soft: #20232d;
614
+ --gui-canvas: #15171e;
615
+ --gui-accent: #a296ff;
616
+ --gui-accent-soft: #2a2940;
617
+ --gui-green: #4dc69d;
618
+ --gui-green-soft: #172923;
619
+ --gui-amber: #f2c46d;
620
+ --gui-amber-soft: #2f2716;
621
+ --gui-danger: #ffabab;
622
+ --gui-danger-soft: #321f25;
623
+ --cpk-json-key: #bec2ff;
624
+ --cpk-json-str: #85ecce;
625
+ --cpk-json-num: #ffac4d;
626
+ --cpk-json-bool: #fa5f67;
627
+ --cpk-json-nil: #afafb7;
628
+ }
629
+ .header {
630
+ position: sticky;
631
+ top: 0;
632
+ z-index: 1;
633
+ padding: 12px 16px 0;
634
+ background: var(--gui-canvas);
635
+ border-bottom: 1px solid var(--gui-line);
636
+ }
637
+ .title-row,
638
+ .row-title,
639
+ .section-head {
640
+ display: flex;
641
+ flex-wrap: wrap;
642
+ align-items: center;
643
+ gap: 6px;
644
+ }
645
+ .title-row,
646
+ .row-title {
647
+ align-items: baseline;
648
+ }
649
+ .section-head h3 {
650
+ margin-right: auto;
651
+ }
652
+ h2 {
653
+ margin: 0;
654
+ font-size: 13px;
655
+ font-weight: 600;
656
+ }
657
+ h3 {
658
+ margin: 0 0 4px;
659
+ font-size: 12px;
660
+ font-weight: 600;
661
+ }
662
+ h4 {
663
+ margin: 12px 0 4px;
664
+ font-size: 11px;
665
+ font-weight: 600;
666
+ color: var(--gui-muted);
667
+ }
668
+ p {
669
+ margin: 2px 0 6px;
670
+ }
671
+ code {
672
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
673
+ font-size: 11px;
674
+ }
675
+ .body {
676
+ padding: 12px 16px 24px;
677
+ }
678
+ section {
679
+ margin-bottom: 20px;
680
+ }
681
+ .muted {
682
+ color: var(--gui-muted);
683
+ }
684
+ .small {
685
+ font-size: 11px;
686
+ }
687
+ .strong {
688
+ font-weight: 600;
689
+ color: var(--gui-ink);
690
+ }
691
+ .warn {
692
+ color: var(--gui-amber);
693
+ }
694
+ .danger {
695
+ color: var(--gui-danger);
696
+ }
697
+ .tabs,
698
+ .segmented {
699
+ display: flex;
700
+ gap: 4px;
701
+ margin-top: 8px;
702
+ }
703
+ .segmented {
704
+ margin: 0 0 8px;
705
+ }
706
+ .tab {
707
+ border: 0;
708
+ border-bottom: 2px solid transparent;
709
+ background: none;
710
+ color: var(--gui-muted);
711
+ font: inherit;
712
+ font-weight: 500;
713
+ padding: 6px 8px;
714
+ cursor: pointer;
715
+ }
716
+ .segmented .tab {
717
+ border: 1px solid var(--gui-line);
718
+ border-radius: 6px;
719
+ }
720
+ .tab.active {
721
+ color: var(--gui-ink);
722
+ border-bottom-color: var(--gui-accent);
723
+ }
724
+ .segmented .tab.active {
725
+ border-color: var(--gui-accent);
726
+ background: var(--gui-accent-soft);
727
+ }
728
+ .tab:disabled {
729
+ opacity: 0.5;
730
+ cursor: default;
731
+ }
732
+ .chip {
733
+ display: inline-block;
734
+ border: 1px solid var(--gui-line);
735
+ border-radius: 999px;
736
+ padding: 0 6px;
737
+ font-size: 10px;
738
+ line-height: 16px;
739
+ color: var(--gui-muted);
740
+ background: var(--gui-soft);
741
+ }
742
+ .chip.event {
743
+ color: var(--gui-accent);
744
+ background: var(--gui-accent-soft);
745
+ }
746
+ .status-ready {
747
+ color: var(--gui-green);
748
+ background: var(--gui-green-soft);
749
+ }
750
+ .status-streaming {
751
+ color: var(--gui-accent);
752
+ background: var(--gui-accent-soft);
753
+ }
754
+ .status-error {
755
+ color: var(--gui-danger);
756
+ background: var(--gui-danger-soft);
757
+ }
758
+ .row {
759
+ display: flex;
760
+ align-items: flex-start;
761
+ gap: 8px;
762
+ padding: 8px 0;
763
+ border-bottom: 1px solid var(--gui-line);
764
+ }
765
+ .row-main {
766
+ flex: 1;
767
+ min-width: 0;
768
+ }
769
+ .card {
770
+ border: 1px solid var(--gui-line);
771
+ border-radius: 8px;
772
+ margin-bottom: 6px;
773
+ overflow: hidden;
774
+ }
775
+ .card-head {
776
+ display: flex;
777
+ align-items: center;
778
+ gap: 8px;
779
+ padding-right: 8px;
780
+ }
781
+ .cpk-json-block {
782
+ margin: 4px 0 0;
783
+ max-height: 320px;
784
+ overflow: auto;
785
+ border: 1px solid var(--gui-line);
786
+ border-radius: 6px;
787
+ padding: 8px 10px;
788
+ background: var(--gui-soft);
789
+ color: var(--gui-ink);
790
+ font-family: "Spline Sans Mono", ui-monospace, monospace;
791
+ font-size: 11px;
792
+ line-height: 1.6;
793
+ white-space: pre-wrap;
794
+ overflow-wrap: anywhere;
795
+ }
796
+ .cpk-json-token--key {
797
+ color: var(--cpk-json-key);
798
+ }
799
+ .cpk-json-token--str {
800
+ color: var(--cpk-json-str);
801
+ }
802
+ .cpk-json-token--num {
803
+ color: var(--cpk-json-num);
804
+ }
805
+ .cpk-json-token--bool {
806
+ color: var(--cpk-json-bool);
807
+ }
808
+ .cpk-json-token--nil {
809
+ color: var(--cpk-json-nil);
810
+ }
811
+ .card-toggle {
812
+ display: flex;
813
+ flex: 1;
814
+ box-sizing: border-box;
815
+ width: 100%;
816
+ flex-direction: column;
817
+ align-items: flex-start;
818
+ gap: 2px;
819
+ min-width: 0;
820
+ border: 0;
821
+ background: none;
822
+ color: inherit;
823
+ font: inherit;
824
+ text-align: left;
825
+ padding: 8px 10px;
826
+ cursor: pointer;
827
+ }
828
+ .card-toggle:hover {
829
+ background: var(--gui-soft);
830
+ }
831
+ .card-body {
832
+ padding: 8px 10px;
833
+ border-top: 1px solid var(--gui-line);
834
+ }
835
+ .card > .card-body:first-child {
836
+ border-top: 0;
837
+ }
838
+ .button {
839
+ flex-shrink: 0;
840
+ border: 1px solid var(--gui-line);
841
+ border-radius: 6px;
842
+ background: var(--gui-canvas);
843
+ color: var(--gui-ink);
844
+ font: inherit;
845
+ font-size: 11px;
846
+ padding: 2px 8px;
847
+ cursor: pointer;
848
+ }
849
+ .button:hover {
850
+ border-color: var(--gui-accent);
851
+ }
852
+ .section-head {
853
+ display: flex;
854
+ align-items: center;
855
+ justify-content: space-between;
856
+ gap: 8px;
857
+ }
858
+ .filter {
859
+ width: 160px;
860
+ box-sizing: border-box;
861
+ border: 1px solid var(--gui-line);
862
+ border-radius: 6px;
863
+ background: var(--gui-canvas);
864
+ color: var(--gui-ink);
865
+ font: inherit;
866
+ font-size: 11px;
867
+ padding: 3px 6px;
868
+ }
869
+ .catalog-toggle::before {
870
+ content: "▸";
871
+ display: inline-block;
872
+ width: 10px;
873
+ color: var(--gui-muted);
874
+ transition: transform 0.1s;
875
+ }
876
+ .catalog-toggle[aria-expanded="true"]::before {
877
+ transform: rotate(90deg);
878
+ }
879
+ pre {
880
+ margin: 4px 0 0;
881
+ max-height: 320px;
882
+ overflow: auto;
883
+ border-radius: 6px;
884
+ background: var(--gui-soft);
885
+ padding: 8px;
886
+ font-family: ui-monospace, SFMono-Regular, Menlo, monospace;
887
+ font-size: 11px;
888
+ line-height: 1.45;
889
+ white-space: pre-wrap;
890
+ word-break: break-word;
891
+ }
892
+ pre.prompt {
893
+ max-height: 480px;
894
+ }
895
+ .list,
896
+ .ops {
897
+ margin: 0;
898
+ padding-left: 18px;
899
+ }
900
+ .list li {
901
+ margin-bottom: 4px;
902
+ }
903
+ .ops {
904
+ list-style: none;
905
+ padding: 0;
906
+ }
907
+ .tree {
908
+ list-style: none;
909
+ margin: 0;
910
+ padding-left: 14px;
911
+ border-left: 1px solid var(--gui-line);
912
+ }
913
+ .tree.root {
914
+ padding-left: 0;
915
+ border-left: 0;
916
+ }
917
+ .op-toggle {
918
+ display: flex;
919
+ align-items: baseline;
920
+ gap: 6px;
921
+ border: 0;
922
+ background: none;
923
+ color: inherit;
924
+ font: inherit;
925
+ padding: 2px 0;
926
+ cursor: pointer;
927
+ }
928
+ .empty {
929
+ padding: 48px 24px;
930
+ text-align: center;
931
+ color: var(--gui-muted);
932
+ }
933
+ `;
934
+ }
935
+ };
936
+ if (!customElements.get("cpk-generative-ui-view")) customElements.define("cpk-generative-ui-view", CpkGenerativeUIView);
937
+
938
+ //#endregion
939
+ //# sourceMappingURL=generative-ui-view.cjs.map