@copilotkit/web-inspector 1.56.5 → 1.57.0-canary.1778082736
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/dist/index.cjs +2756 -199
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +264 -10
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +264 -10
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2757 -201
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +2794 -211
- package/dist/index.umd.js.map +1 -1
- package/dist/styles/generated.cjs +1 -1
- package/dist/styles/generated.cjs.map +1 -1
- package/dist/styles/generated.mjs +1 -1
- package/dist/styles/generated.mjs.map +1 -1
- package/package.json +2 -2
- package/src/__tests__/web-inspector.spec.ts +179 -1
- package/src/index.ts +3456 -300
- package/src/styles/generated.css +1 -1
package/dist/index.mjs
CHANGED
|
@@ -4,11 +4,11 @@ import inspector_logo_icon_default from "./assets/inspector-logo-icon.mjs";
|
|
|
4
4
|
import { applyAnchorPosition, centerContext, clampSize, constrainToViewport, keepPositionWithinViewport, updateAnchorFromPosition, updateSizeFromElement } from "./lib/context-helpers.mjs";
|
|
5
5
|
import { isValidAnchor, isValidDockMode, isValidPosition, isValidSize, loadInspectorState, saveInspectorState } from "./lib/persistence.mjs";
|
|
6
6
|
import { LitElement, css, html, nothing, unsafeCSS } from "lit";
|
|
7
|
+
import { marked } from "marked";
|
|
7
8
|
import { styleMap } from "lit/directives/style-map.js";
|
|
8
9
|
import { unsafeHTML } from "lit/directives/unsafe-html.js";
|
|
9
|
-
import { marked } from "marked";
|
|
10
10
|
import { icons } from "lucide";
|
|
11
|
-
import { CopilotKitCoreRuntimeConnectionStatus } from "@copilotkit/core";
|
|
11
|
+
import { CopilotKitCoreRuntimeConnectionStatus, ɵcreateThreadStore, ɵselectThreads, ɵselectThreadsError } from "@copilotkit/core";
|
|
12
12
|
|
|
13
13
|
//#region src/index.ts
|
|
14
14
|
const WEB_INSPECTOR_TAG = "cpk-web-inspector";
|
|
@@ -26,7 +26,7 @@ const DEFAULT_BUTTON_SIZE = {
|
|
|
26
26
|
};
|
|
27
27
|
const DEFAULT_WINDOW_SIZE = {
|
|
28
28
|
width: 840,
|
|
29
|
-
height:
|
|
29
|
+
height: 700
|
|
30
30
|
};
|
|
31
31
|
const DOCKED_LEFT_WIDTH = 500;
|
|
32
32
|
const MAX_AGENT_EVENTS = 200;
|
|
@@ -52,11 +52,1765 @@ const AGENT_EVENT_TYPES = [
|
|
|
52
52
|
"REASONING_MESSAGE_CONTENT",
|
|
53
53
|
"REASONING_MESSAGE_END",
|
|
54
54
|
"REASONING_END",
|
|
55
|
-
"REASONING_ENCRYPTED_VALUE"
|
|
55
|
+
"REASONING_ENCRYPTED_VALUE",
|
|
56
|
+
"ACTIVITY_SNAPSHOT",
|
|
57
|
+
"ACTIVITY_DELTA"
|
|
56
58
|
];
|
|
57
|
-
|
|
59
|
+
function escapeHtml(s) {
|
|
60
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
61
|
+
}
|
|
62
|
+
const highlightedJsonCache = /* @__PURE__ */ new WeakMap();
|
|
63
|
+
function highlightedJson(obj) {
|
|
64
|
+
if (typeof obj === "object" && obj !== null) {
|
|
65
|
+
const cached = highlightedJsonCache.get(obj);
|
|
66
|
+
if (cached !== void 0) return cached;
|
|
67
|
+
}
|
|
68
|
+
const colors = {
|
|
69
|
+
key: "#5558B2",
|
|
70
|
+
str: "#189370",
|
|
71
|
+
num: "#996300",
|
|
72
|
+
bool: "#c0333a",
|
|
73
|
+
nil: "#838389"
|
|
74
|
+
};
|
|
75
|
+
const json = JSON.stringify(obj, null, 2);
|
|
76
|
+
if (!json) return "";
|
|
77
|
+
const parts = [];
|
|
78
|
+
let lastIndex = 0;
|
|
79
|
+
const re = /("(?:\\u[a-fA-F0-9]{4}|\\[^u]|[^\\"])*"(?:\s*:)?|\b(?:true|false|null)\b|-?\d+(?:\.\d*)?(?:[eE][+-]?\d+)?)/g;
|
|
80
|
+
let match;
|
|
81
|
+
while ((match = re.exec(json)) !== null) {
|
|
82
|
+
parts.push(escapeHtml(json.slice(lastIndex, match.index)));
|
|
83
|
+
const m = match[0];
|
|
84
|
+
let color = colors.num;
|
|
85
|
+
if (m.startsWith("\"")) color = m.trimEnd().endsWith(":") ? colors.key : colors.str;
|
|
86
|
+
else if (m === "true" || m === "false") color = colors.bool;
|
|
87
|
+
else if (m === "null") color = colors.nil;
|
|
88
|
+
parts.push(`<span style="color:${color}">${escapeHtml(m)}</span>`);
|
|
89
|
+
lastIndex = match.index + m.length;
|
|
90
|
+
}
|
|
91
|
+
parts.push(escapeHtml(json.slice(lastIndex)));
|
|
92
|
+
const result = parts.join("");
|
|
93
|
+
if (typeof obj === "object" && obj !== null) highlightedJsonCache.set(obj, result);
|
|
94
|
+
return result;
|
|
95
|
+
}
|
|
96
|
+
function eventColors(type) {
|
|
97
|
+
if (type.startsWith("TEXT_MESSAGE")) return {
|
|
98
|
+
bg: "#EEE6FE",
|
|
99
|
+
fg: "#57575B"
|
|
100
|
+
};
|
|
101
|
+
if (type.startsWith("TOOL_CALL")) return {
|
|
102
|
+
bg: "rgba(133,236,206,0.15)",
|
|
103
|
+
fg: "#189370"
|
|
104
|
+
};
|
|
105
|
+
if (type.startsWith("STATE")) return {
|
|
106
|
+
bg: "rgba(190,194,255,0.102)",
|
|
107
|
+
fg: "#5558B2"
|
|
108
|
+
};
|
|
109
|
+
if (type.startsWith("RUN_") || type.startsWith("STEP_")) return {
|
|
110
|
+
bg: "rgba(255,172,77,0.2)",
|
|
111
|
+
fg: "#996300"
|
|
112
|
+
};
|
|
113
|
+
if (type === "ERROR") return {
|
|
114
|
+
bg: "rgba(250,95,103,0.13)",
|
|
115
|
+
fg: "#c0333a"
|
|
116
|
+
};
|
|
117
|
+
return {
|
|
118
|
+
bg: "#F7F7F9",
|
|
119
|
+
fg: "#838389"
|
|
120
|
+
};
|
|
121
|
+
}
|
|
122
|
+
function formatTimestamp(ts) {
|
|
123
|
+
const date = typeof ts === "number" ? new Date(ts) : new Date(ts);
|
|
124
|
+
if (Number.isNaN(date.getTime())) return "";
|
|
125
|
+
const ms = date.getMilliseconds().toString().padStart(3, "0");
|
|
126
|
+
return date.toLocaleTimeString("en-US", {
|
|
127
|
+
hour: "2-digit",
|
|
128
|
+
minute: "2-digit",
|
|
129
|
+
second: "2-digit",
|
|
130
|
+
hour12: false
|
|
131
|
+
}) + "." + ms;
|
|
132
|
+
}
|
|
133
|
+
var CpkThreadList = class extends LitElement {
|
|
58
134
|
constructor(..._args) {
|
|
59
135
|
super(..._args);
|
|
136
|
+
this.threads = [];
|
|
137
|
+
this.selectedThreadId = null;
|
|
138
|
+
this.errorMessage = null;
|
|
139
|
+
this._query = "";
|
|
140
|
+
this.onSearchInput = (event) => {
|
|
141
|
+
this._query = event.target.value;
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
static {
|
|
145
|
+
this.properties = {
|
|
146
|
+
threads: { attribute: false },
|
|
147
|
+
selectedThreadId: { attribute: false },
|
|
148
|
+
errorMessage: { attribute: false },
|
|
149
|
+
_query: { state: true }
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
static {
|
|
153
|
+
this.styles = css`
|
|
154
|
+
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap");
|
|
155
|
+
|
|
156
|
+
:host {
|
|
157
|
+
display: flex;
|
|
158
|
+
flex-direction: column;
|
|
159
|
+
height: 100%;
|
|
160
|
+
overflow: hidden;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
.cpk-tl {
|
|
164
|
+
font-family: "Plus Jakarta Sans", sans-serif;
|
|
165
|
+
display: flex;
|
|
166
|
+
flex-direction: column;
|
|
167
|
+
height: 100%;
|
|
168
|
+
overflow: hidden;
|
|
169
|
+
background: #f7f7f9;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/* ── Search ── */
|
|
173
|
+
.cpk-tl__search {
|
|
174
|
+
padding: 10px 12px;
|
|
175
|
+
border-bottom: 1px solid #dbdbe5;
|
|
176
|
+
flex-shrink: 0;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
.cpk-tl__search-input {
|
|
180
|
+
width: 100%;
|
|
181
|
+
box-sizing: border-box;
|
|
182
|
+
font-family: "Plus Jakarta Sans", sans-serif;
|
|
183
|
+
font-size: 12px;
|
|
184
|
+
padding: 7px 10px;
|
|
185
|
+
border-radius: 6px;
|
|
186
|
+
border: 1px solid #dbdbe5;
|
|
187
|
+
background: #ffffff;
|
|
188
|
+
color: #010507;
|
|
189
|
+
outline: none;
|
|
190
|
+
transition: border-color 0.15s;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.cpk-tl__search-input:focus {
|
|
194
|
+
border-color: #bec2ff;
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
/* ── List ── */
|
|
198
|
+
.cpk-tl__list {
|
|
199
|
+
flex: 1;
|
|
200
|
+
overflow-y: auto;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/* ── Thread item ── */
|
|
204
|
+
.cpk-tl__item {
|
|
205
|
+
padding: 11px 13px;
|
|
206
|
+
cursor: pointer;
|
|
207
|
+
border-bottom: 1px solid #e9e9ef;
|
|
208
|
+
border-left: 3px solid transparent;
|
|
209
|
+
transition: background 0.1s;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
.cpk-tl__item:hover {
|
|
213
|
+
background: #ffffff;
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
.cpk-tl__item--active {
|
|
217
|
+
background: #bec2ff1a;
|
|
218
|
+
border-left-color: #bec2ff;
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
.cpk-tl__item--active:hover {
|
|
222
|
+
background: #bec2ff33;
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
.cpk-tl__row1 {
|
|
226
|
+
display: flex;
|
|
227
|
+
align-items: center;
|
|
228
|
+
gap: 8px;
|
|
229
|
+
margin-bottom: 3px;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
.cpk-tl__name {
|
|
233
|
+
font-size: 12px;
|
|
234
|
+
font-weight: 500;
|
|
235
|
+
color: #010507;
|
|
236
|
+
flex: 1;
|
|
237
|
+
overflow: hidden;
|
|
238
|
+
text-overflow: ellipsis;
|
|
239
|
+
white-space: nowrap;
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
.cpk-tl__name--unnamed {
|
|
243
|
+
color: #838389;
|
|
244
|
+
font-style: italic;
|
|
245
|
+
font-weight: 400;
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
.cpk-tl__time {
|
|
249
|
+
font-family: "Spline Sans Mono", monospace;
|
|
250
|
+
font-size: 10px;
|
|
251
|
+
color: #838389;
|
|
252
|
+
flex-shrink: 0;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
.cpk-tl__meta {
|
|
256
|
+
display: flex;
|
|
257
|
+
gap: 6px;
|
|
258
|
+
align-items: center;
|
|
259
|
+
flex-wrap: wrap;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
.cpk-tl__pill {
|
|
263
|
+
font-family: "Spline Sans Mono", monospace;
|
|
264
|
+
font-size: 9px;
|
|
265
|
+
padding: 1px 7px;
|
|
266
|
+
border-radius: 4px;
|
|
267
|
+
text-transform: uppercase;
|
|
268
|
+
font-weight: 500;
|
|
269
|
+
white-space: nowrap;
|
|
270
|
+
background: #eee6fe;
|
|
271
|
+
color: #57575b;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
/* ── Empty state ── */
|
|
275
|
+
.cpk-tl__empty {
|
|
276
|
+
padding: 32px 16px;
|
|
277
|
+
text-align: center;
|
|
278
|
+
color: #838389;
|
|
279
|
+
font-size: 12px;
|
|
280
|
+
display: flex;
|
|
281
|
+
flex-direction: column;
|
|
282
|
+
align-items: center;
|
|
283
|
+
gap: 8px;
|
|
284
|
+
}
|
|
285
|
+
|
|
286
|
+
.cpk-tl__empty-icon {
|
|
287
|
+
color: #c0c0c8;
|
|
288
|
+
}
|
|
289
|
+
`;
|
|
290
|
+
}
|
|
291
|
+
relativeTime(dateStr) {
|
|
292
|
+
const date = new Date(dateStr);
|
|
293
|
+
const diffMs = Date.now() - date.getTime();
|
|
294
|
+
const diffSec = Math.floor(diffMs / 1e3);
|
|
295
|
+
if (diffSec < 60) return `${diffSec}s ago`;
|
|
296
|
+
const diffMin = Math.floor(diffSec / 60);
|
|
297
|
+
if (diffMin < 60) return `${diffMin}m ago`;
|
|
298
|
+
const diffH = Math.floor(diffMin / 60);
|
|
299
|
+
if (diffH < 24) return `${diffH}h ago`;
|
|
300
|
+
return `${Math.floor(diffH / 24)}d ago`;
|
|
301
|
+
}
|
|
302
|
+
get filtered() {
|
|
303
|
+
const q = this._query.toLowerCase();
|
|
304
|
+
if (!q) return this.threads;
|
|
305
|
+
return this.threads.filter((t) => (t.name?.toLowerCase().includes(q) ?? false) || t.agentId.toLowerCase().includes(q) || t.id.toLowerCase().includes(q));
|
|
306
|
+
}
|
|
307
|
+
onThreadClick(threadId) {
|
|
308
|
+
this.dispatchEvent(new CustomEvent("threadSelected", {
|
|
309
|
+
detail: threadId,
|
|
310
|
+
bubbles: true,
|
|
311
|
+
composed: true
|
|
312
|
+
}));
|
|
313
|
+
}
|
|
314
|
+
render() {
|
|
315
|
+
const filtered = this.filtered;
|
|
316
|
+
return html`
|
|
317
|
+
<div class="cpk-tl">
|
|
318
|
+
<!-- Search -->
|
|
319
|
+
<div class="cpk-tl__search">
|
|
320
|
+
<input
|
|
321
|
+
type="text"
|
|
322
|
+
placeholder="Search threads…"
|
|
323
|
+
.value=${this._query}
|
|
324
|
+
@input=${this.onSearchInput}
|
|
325
|
+
class="cpk-tl__search-input"
|
|
326
|
+
/>
|
|
327
|
+
</div>
|
|
328
|
+
|
|
329
|
+
<!-- Thread list -->
|
|
330
|
+
<div class="cpk-tl__list">
|
|
331
|
+
${filtered.map((thread) => html`
|
|
332
|
+
<div
|
|
333
|
+
class="cpk-tl__item ${this.selectedThreadId === thread.id ? "cpk-tl__item--active" : ""}"
|
|
334
|
+
@click=${() => this.onThreadClick(thread.id)}
|
|
335
|
+
>
|
|
336
|
+
<div class="cpk-tl__row1">
|
|
337
|
+
<span
|
|
338
|
+
class="cpk-tl__name ${!thread.name ? "cpk-tl__name--unnamed" : ""}"
|
|
339
|
+
>${thread.name ?? "Untitled"}</span
|
|
340
|
+
>
|
|
341
|
+
<span class="cpk-tl__time"
|
|
342
|
+
>${this.relativeTime(thread.updatedAt)}</span
|
|
343
|
+
>
|
|
344
|
+
</div>
|
|
345
|
+
<div class="cpk-tl__meta">
|
|
346
|
+
<span class="cpk-tl__pill">${thread.agentId}</span>
|
|
347
|
+
</div>
|
|
348
|
+
</div>
|
|
349
|
+
`)}
|
|
350
|
+
${filtered.length === 0 ? html`
|
|
351
|
+
<div class="cpk-tl__empty">
|
|
352
|
+
${this.errorMessage ? html`
|
|
353
|
+
<svg
|
|
354
|
+
width="24"
|
|
355
|
+
height="24"
|
|
356
|
+
viewBox="0 0 24 24"
|
|
357
|
+
fill="none"
|
|
358
|
+
stroke="currentColor"
|
|
359
|
+
stroke-width="1.5"
|
|
360
|
+
stroke-linecap="round"
|
|
361
|
+
stroke-linejoin="round"
|
|
362
|
+
class="cpk-tl__empty-icon"
|
|
363
|
+
>
|
|
364
|
+
<circle cx="12" cy="12" r="10" />
|
|
365
|
+
<line x1="12" y1="8" x2="12" y2="12" />
|
|
366
|
+
<line x1="12" y1="16" x2="12.01" y2="16" />
|
|
367
|
+
</svg>
|
|
368
|
+
<div>
|
|
369
|
+
Failed to load threads
|
|
370
|
+
<div style="font-size:11px;margin-top:4px;color:#c0333a;">
|
|
371
|
+
${this.errorMessage}
|
|
372
|
+
</div>
|
|
373
|
+
</div>
|
|
374
|
+
` : this.threads.length === 0 ? html`
|
|
375
|
+
<svg
|
|
376
|
+
width="24"
|
|
377
|
+
height="24"
|
|
378
|
+
viewBox="0 0 24 24"
|
|
379
|
+
fill="none"
|
|
380
|
+
stroke="currentColor"
|
|
381
|
+
stroke-width="1.5"
|
|
382
|
+
stroke-linecap="round"
|
|
383
|
+
stroke-linejoin="round"
|
|
384
|
+
class="cpk-tl__empty-icon"
|
|
385
|
+
>
|
|
386
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
387
|
+
</svg>
|
|
388
|
+
No threads yet
|
|
389
|
+
` : html`
|
|
390
|
+
No threads match your search.
|
|
391
|
+
`}
|
|
392
|
+
</div>
|
|
393
|
+
` : nothing}
|
|
394
|
+
</div>
|
|
395
|
+
</div>
|
|
396
|
+
`;
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
var ɵCpkThreadDetails = class ɵCpkThreadDetails extends LitElement {
|
|
400
|
+
constructor(..._args2) {
|
|
401
|
+
super(..._args2);
|
|
402
|
+
this.threadId = null;
|
|
403
|
+
this.thread = null;
|
|
404
|
+
this.runtimeUrl = "";
|
|
405
|
+
this.headers = {};
|
|
406
|
+
this.agentStateInput = null;
|
|
407
|
+
this.agentEventsInput = [];
|
|
408
|
+
this.liveMessageVersion = 0;
|
|
409
|
+
this._tab = "conversation";
|
|
410
|
+
this._conversation = [];
|
|
411
|
+
this._fetchedEvents = null;
|
|
412
|
+
this._fetchedState = null;
|
|
413
|
+
this._loadingMessages = false;
|
|
414
|
+
this._loadingEvents = false;
|
|
415
|
+
this._loadingState = false;
|
|
416
|
+
this._messagesError = null;
|
|
417
|
+
this._eventsError = null;
|
|
418
|
+
this._stateError = null;
|
|
419
|
+
this._expandedTools = /* @__PURE__ */ new Set();
|
|
420
|
+
this._expandedMessages = /* @__PURE__ */ new Set();
|
|
421
|
+
this._showDetailPanel = false;
|
|
422
|
+
this._detailPanelWidth = 250;
|
|
423
|
+
this._eventsNotAvailable = false;
|
|
424
|
+
this._stateNotAvailable = false;
|
|
425
|
+
this._panelInitializing = false;
|
|
426
|
+
this._activatedTabs = new Set(["conversation"]);
|
|
427
|
+
this._panelTplCache = /* @__PURE__ */ new Map();
|
|
428
|
+
this._eventsFetched = false;
|
|
429
|
+
this._stateFetched = false;
|
|
430
|
+
this._lastFetchedThreadId = null;
|
|
431
|
+
this._lastSeenLiveMessageVersion = 0;
|
|
432
|
+
this._messagesAbort = null;
|
|
433
|
+
this._eventsAbort = null;
|
|
434
|
+
this._stateAbort = null;
|
|
435
|
+
this._dividerResizing = false;
|
|
436
|
+
this._dividerPointerId = -1;
|
|
437
|
+
this._dividerStartX = 0;
|
|
438
|
+
this._dividerStartWidth = 0;
|
|
439
|
+
this.onDetailDividerDown = (event) => {
|
|
440
|
+
this._dividerResizing = true;
|
|
441
|
+
this._dividerPointerId = event.pointerId;
|
|
442
|
+
this._dividerStartX = event.clientX;
|
|
443
|
+
this._dividerStartWidth = this._detailPanelWidth;
|
|
444
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
445
|
+
event.preventDefault();
|
|
446
|
+
};
|
|
447
|
+
this.onDetailDividerMove = (event) => {
|
|
448
|
+
if (!this._dividerResizing || this._dividerPointerId !== event.pointerId) return;
|
|
449
|
+
const delta = this._dividerStartX - event.clientX;
|
|
450
|
+
this._detailPanelWidth = Math.max(160, Math.min(400, this._dividerStartWidth + delta));
|
|
451
|
+
};
|
|
452
|
+
this.onDetailDividerUp = (event) => {
|
|
453
|
+
if (this._dividerPointerId !== event.pointerId) return;
|
|
454
|
+
const target = event.currentTarget;
|
|
455
|
+
if (target.hasPointerCapture(this._dividerPointerId)) target.releasePointerCapture(this._dividerPointerId);
|
|
456
|
+
this._dividerResizing = false;
|
|
457
|
+
};
|
|
458
|
+
}
|
|
459
|
+
static {
|
|
460
|
+
this.properties = {
|
|
461
|
+
threadId: { attribute: false },
|
|
462
|
+
thread: { attribute: false },
|
|
463
|
+
runtimeUrl: { attribute: false },
|
|
464
|
+
headers: { attribute: false },
|
|
465
|
+
agentStateInput: { attribute: false },
|
|
466
|
+
agentEventsInput: { attribute: false },
|
|
467
|
+
liveMessageVersion: { attribute: false },
|
|
468
|
+
_tab: { state: true },
|
|
469
|
+
_conversation: { state: true },
|
|
470
|
+
_fetchedEvents: { state: true },
|
|
471
|
+
_fetchedState: { state: true },
|
|
472
|
+
_loadingMessages: { state: true },
|
|
473
|
+
_loadingEvents: { state: true },
|
|
474
|
+
_loadingState: { state: true },
|
|
475
|
+
_messagesError: { state: true },
|
|
476
|
+
_eventsError: { state: true },
|
|
477
|
+
_stateError: { state: true },
|
|
478
|
+
_expandedTools: { state: true },
|
|
479
|
+
_expandedMessages: { state: true },
|
|
480
|
+
_showDetailPanel: { state: true },
|
|
481
|
+
_detailPanelWidth: { state: true },
|
|
482
|
+
_eventsNotAvailable: { state: true },
|
|
483
|
+
_stateNotAvailable: { state: true },
|
|
484
|
+
_panelInitializing: { state: true },
|
|
485
|
+
_activatedTabs: { state: true }
|
|
486
|
+
};
|
|
487
|
+
}
|
|
488
|
+
static {
|
|
489
|
+
this.COLLAPSE_THRESHOLD = 800;
|
|
490
|
+
}
|
|
491
|
+
static {
|
|
492
|
+
this.TAB_LIST = [
|
|
493
|
+
{
|
|
494
|
+
id: "conversation",
|
|
495
|
+
label: "Conversation"
|
|
496
|
+
},
|
|
497
|
+
{
|
|
498
|
+
id: "agent-state",
|
|
499
|
+
label: "Agent State"
|
|
500
|
+
},
|
|
501
|
+
{
|
|
502
|
+
id: "ag-ui-events",
|
|
503
|
+
label: "AG-UI Events"
|
|
504
|
+
}
|
|
505
|
+
];
|
|
506
|
+
}
|
|
507
|
+
renderTabContent(id) {
|
|
508
|
+
if (id === "conversation") return this.renderConversation();
|
|
509
|
+
if (id === "agent-state") return this.renderState();
|
|
510
|
+
return this.renderEvents();
|
|
511
|
+
}
|
|
512
|
+
activateTab(id) {
|
|
513
|
+
if (this._tab === id) return;
|
|
514
|
+
const isFirstActivation = !this._activatedTabs.has(id);
|
|
515
|
+
this._tab = id;
|
|
516
|
+
if (isFirstActivation) {
|
|
517
|
+
this._panelInitializing = true;
|
|
518
|
+
requestAnimationFrame(() => {
|
|
519
|
+
this._activatedTabs = new Set([...this._activatedTabs, id]);
|
|
520
|
+
this._panelInitializing = false;
|
|
521
|
+
});
|
|
522
|
+
}
|
|
523
|
+
this.maybeFetchTabData(id);
|
|
524
|
+
}
|
|
525
|
+
maybeFetchTabData(id) {
|
|
526
|
+
if (!this.threadId) return;
|
|
527
|
+
if (id === "ag-ui-events" && !this._eventsFetched) {
|
|
528
|
+
this._eventsFetched = true;
|
|
529
|
+
this.fetchEvents(this.threadId);
|
|
530
|
+
} else if (id === "agent-state" && !this._stateFetched) {
|
|
531
|
+
this._stateFetched = true;
|
|
532
|
+
this.fetchState(this.threadId);
|
|
533
|
+
}
|
|
534
|
+
}
|
|
535
|
+
static {
|
|
536
|
+
this.styles = css`
|
|
537
|
+
@import url("https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap");
|
|
538
|
+
|
|
539
|
+
/* ── Root ────────────────────────────────────────────────────────── */
|
|
540
|
+
:host {
|
|
541
|
+
display: flex;
|
|
542
|
+
flex-direction: row;
|
|
543
|
+
overflow: hidden;
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
.cpk-td {
|
|
547
|
+
font-family: "Plus Jakarta Sans", sans-serif;
|
|
548
|
+
font-size: 13px;
|
|
549
|
+
display: flex;
|
|
550
|
+
flex-direction: row;
|
|
551
|
+
width: 100%;
|
|
552
|
+
height: 100%;
|
|
553
|
+
overflow: hidden;
|
|
554
|
+
background: #ffffff;
|
|
555
|
+
}
|
|
556
|
+
|
|
557
|
+
/* ── Left area ───────────────────────────────────────────────────── */
|
|
558
|
+
.cpk-td__left {
|
|
559
|
+
flex: 1;
|
|
560
|
+
min-width: 0;
|
|
561
|
+
display: flex;
|
|
562
|
+
flex-direction: column;
|
|
563
|
+
overflow: hidden;
|
|
564
|
+
}
|
|
565
|
+
|
|
566
|
+
/* ── Tab bar header ──────────────────────────────────────────────── */
|
|
567
|
+
.cpk-td__tabs-header {
|
|
568
|
+
/* No top/right padding so tabs and toggle sit flush against the
|
|
569
|
+
top and right edges of the inspector. */
|
|
570
|
+
padding: 0 0 0 12px;
|
|
571
|
+
border-bottom: 1px solid #dbdbe5;
|
|
572
|
+
flex-shrink: 0;
|
|
573
|
+
display: flex;
|
|
574
|
+
align-items: stretch;
|
|
575
|
+
}
|
|
576
|
+
|
|
577
|
+
.cpk-td__tab-group {
|
|
578
|
+
display: flex;
|
|
579
|
+
gap: 0;
|
|
580
|
+
margin-bottom: -1px;
|
|
581
|
+
/* Allow the tab list to shrink rather than pushing the panel-toggle
|
|
582
|
+
button past the right edge of the inspector when horizontal space
|
|
583
|
+
gets tight (the drawer being open eats noticeably into width). */
|
|
584
|
+
min-width: 0;
|
|
585
|
+
flex-shrink: 1;
|
|
586
|
+
overflow: hidden;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.cpk-td__tab {
|
|
590
|
+
font-family: "Plus Jakarta Sans", sans-serif;
|
|
591
|
+
font-size: 11px;
|
|
592
|
+
font-weight: 500;
|
|
593
|
+
padding: 10px 12px;
|
|
594
|
+
border: none;
|
|
595
|
+
border-bottom: 2px solid transparent;
|
|
596
|
+
cursor: pointer;
|
|
597
|
+
background: transparent;
|
|
598
|
+
color: #838389;
|
|
599
|
+
transition:
|
|
600
|
+
color 0.12s,
|
|
601
|
+
border-color 0.12s;
|
|
602
|
+
white-space: nowrap;
|
|
603
|
+
}
|
|
604
|
+
|
|
605
|
+
.cpk-td__tab:hover {
|
|
606
|
+
color: #010507;
|
|
607
|
+
}
|
|
608
|
+
|
|
609
|
+
.cpk-td__tab--active {
|
|
610
|
+
color: #010507;
|
|
611
|
+
border-bottom-color: #bec2ff;
|
|
612
|
+
}
|
|
613
|
+
|
|
614
|
+
/* Toggle is a separate control, not a tab — so it does NOT use the
|
|
615
|
+
tabs' bottom-border active indicator. Instead, a subtle filled
|
|
616
|
+
state communicates "the drawer is open," and a vertical separator
|
|
617
|
+
on the left visually divorces it from the tab group. */
|
|
618
|
+
.cpk-td__panel-toggle {
|
|
619
|
+
margin-left: auto;
|
|
620
|
+
align-self: stretch;
|
|
621
|
+
display: flex;
|
|
622
|
+
align-items: center;
|
|
623
|
+
justify-content: center;
|
|
624
|
+
padding: 0 12px;
|
|
625
|
+
border: none;
|
|
626
|
+
border-left: 1px solid #dbdbe5;
|
|
627
|
+
background: transparent;
|
|
628
|
+
color: #838389;
|
|
629
|
+
cursor: pointer;
|
|
630
|
+
flex-shrink: 0;
|
|
631
|
+
transition:
|
|
632
|
+
color 0.12s,
|
|
633
|
+
background 0.12s;
|
|
634
|
+
}
|
|
635
|
+
.cpk-td__panel-toggle:hover {
|
|
636
|
+
color: #010507;
|
|
637
|
+
background: #f4f4f9;
|
|
638
|
+
}
|
|
639
|
+
.cpk-td__panel-toggle--active {
|
|
640
|
+
color: #5558b2;
|
|
641
|
+
background: #eee6fe;
|
|
642
|
+
}
|
|
643
|
+
.cpk-td__panel-toggle--active:hover {
|
|
644
|
+
background: #e4d8fc;
|
|
645
|
+
}
|
|
646
|
+
|
|
647
|
+
/* ── Scrollable content ──────────────────────────────────────────── */
|
|
648
|
+
.cpk-td__content {
|
|
649
|
+
flex: 1;
|
|
650
|
+
overflow-y: auto;
|
|
651
|
+
padding: 16px;
|
|
652
|
+
display: flex;
|
|
653
|
+
flex-direction: column;
|
|
654
|
+
gap: 8px;
|
|
655
|
+
}
|
|
656
|
+
|
|
657
|
+
/* Pin direct children so expanded tool bodies don't get flex-shrunk. */
|
|
658
|
+
.cpk-td__content > * {
|
|
659
|
+
flex-shrink: 0;
|
|
660
|
+
}
|
|
661
|
+
|
|
662
|
+
/*
|
|
663
|
+
* Each tab's content is wrapped in this panel so the keep-mounted
|
|
664
|
+
* inactive panels can be hidden via display:none without disturbing
|
|
665
|
+
* the gap between visible siblings. The flex column + gap gives each
|
|
666
|
+
* conversation item / event row breathing room (the cpk-td__content
|
|
667
|
+
* rule above no longer reaches them now that they are nested inside
|
|
668
|
+
* the per-panel wrapper).
|
|
669
|
+
*/
|
|
670
|
+
.cpk-td__panel {
|
|
671
|
+
display: flex;
|
|
672
|
+
flex-direction: column;
|
|
673
|
+
gap: 12px;
|
|
674
|
+
}
|
|
675
|
+
.cpk-td__panel > * {
|
|
676
|
+
flex-shrink: 0;
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
/* ── Empty state ─────────────────────────────────────────────────── */
|
|
680
|
+
.cpk-td__empty-state {
|
|
681
|
+
flex: 1;
|
|
682
|
+
display: flex;
|
|
683
|
+
flex-direction: column;
|
|
684
|
+
align-items: center;
|
|
685
|
+
justify-content: center;
|
|
686
|
+
gap: 8px;
|
|
687
|
+
color: #838389;
|
|
688
|
+
font-size: 13px;
|
|
689
|
+
padding: 40px 0;
|
|
690
|
+
}
|
|
691
|
+
|
|
692
|
+
.cpk-td__empty-hint {
|
|
693
|
+
font-size: 11px;
|
|
694
|
+
color: #838389;
|
|
695
|
+
text-align: center;
|
|
696
|
+
max-width: 220px;
|
|
697
|
+
line-height: 1.5;
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
/* ── Status messages ─────────────────────────────────────────────── */
|
|
701
|
+
.cpk-td__status {
|
|
702
|
+
padding: 16px;
|
|
703
|
+
font-size: 12px;
|
|
704
|
+
color: #838389;
|
|
705
|
+
text-align: center;
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
.cpk-td__status--error {
|
|
709
|
+
color: #c0333a;
|
|
710
|
+
}
|
|
711
|
+
|
|
712
|
+
/* ── Conversation bubbles ────────────────────────────────────────── */
|
|
713
|
+
.cpk-td__bubble {
|
|
714
|
+
display: flex;
|
|
715
|
+
margin-bottom: 2px;
|
|
716
|
+
}
|
|
717
|
+
|
|
718
|
+
.cpk-td__bubble--user {
|
|
719
|
+
justify-content: flex-end;
|
|
720
|
+
}
|
|
721
|
+
|
|
722
|
+
.cpk-td__bubble--assistant {
|
|
723
|
+
justify-content: flex-start;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
.cpk-td__bubble-inner {
|
|
727
|
+
padding: 9px 14px;
|
|
728
|
+
max-width: 75%;
|
|
729
|
+
font-size: 13px;
|
|
730
|
+
line-height: 1.55;
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
.cpk-td__bubble-inner--user {
|
|
734
|
+
background: #eee6fe;
|
|
735
|
+
color: #57575b;
|
|
736
|
+
border-radius: 10px 10px 3px 10px;
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
.cpk-td__show-more {
|
|
740
|
+
display: inline-block;
|
|
741
|
+
margin-top: 4px;
|
|
742
|
+
font-size: 11px;
|
|
743
|
+
font-weight: 500;
|
|
744
|
+
color: #57575b;
|
|
745
|
+
cursor: pointer;
|
|
746
|
+
text-decoration: underline;
|
|
747
|
+
text-underline-offset: 2px;
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
.cpk-td__bubble-inner--assistant {
|
|
751
|
+
background: #f7f7f9;
|
|
752
|
+
color: #010507;
|
|
753
|
+
border-radius: 10px 10px 10px 3px;
|
|
754
|
+
border: 1px solid #e9e9ef;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
/* ── Tool call blocks ────────────────────────────────────────────── */
|
|
758
|
+
.cpk-td__tool-block {
|
|
759
|
+
border: 1px solid #e9e9ef;
|
|
760
|
+
border-radius: 6px;
|
|
761
|
+
overflow: hidden;
|
|
762
|
+
}
|
|
763
|
+
|
|
764
|
+
.cpk-td__tool-header {
|
|
765
|
+
display: flex;
|
|
766
|
+
align-items: center;
|
|
767
|
+
gap: 6px;
|
|
768
|
+
padding: 6px 10px;
|
|
769
|
+
background: rgba(133, 236, 206, 0.15);
|
|
770
|
+
cursor: pointer;
|
|
771
|
+
font-size: 11px;
|
|
772
|
+
user-select: none;
|
|
773
|
+
}
|
|
774
|
+
|
|
775
|
+
.cpk-td__tool-header:hover {
|
|
776
|
+
background: rgba(133, 236, 206, 0.22);
|
|
777
|
+
}
|
|
778
|
+
|
|
779
|
+
.cpk-td__tool-name {
|
|
780
|
+
font-family: "Spline Sans Mono", monospace;
|
|
781
|
+
font-size: 10px;
|
|
782
|
+
font-weight: 500;
|
|
783
|
+
color: #189370;
|
|
784
|
+
text-transform: uppercase;
|
|
785
|
+
flex: 1;
|
|
786
|
+
}
|
|
787
|
+
|
|
788
|
+
.cpk-td__tool-status {
|
|
789
|
+
font-family: "Spline Sans Mono", monospace;
|
|
790
|
+
font-size: 9px;
|
|
791
|
+
text-transform: uppercase;
|
|
792
|
+
color: #189370;
|
|
793
|
+
}
|
|
794
|
+
|
|
795
|
+
.cpk-td__tool-status--pending {
|
|
796
|
+
color: #996300;
|
|
797
|
+
}
|
|
798
|
+
|
|
799
|
+
.cpk-td__tool-chevron {
|
|
800
|
+
color: #838389;
|
|
801
|
+
font-size: 10px;
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
.cpk-td__tool-body {
|
|
805
|
+
padding: 8px 10px;
|
|
806
|
+
border-top: 1px solid #e9e9ef;
|
|
807
|
+
background: #ffffff;
|
|
808
|
+
}
|
|
809
|
+
|
|
810
|
+
.cpk-td__tool-section-label {
|
|
811
|
+
font-family: "Spline Sans Mono", monospace;
|
|
812
|
+
font-size: 9px;
|
|
813
|
+
font-weight: 500;
|
|
814
|
+
color: #838389;
|
|
815
|
+
text-transform: uppercase;
|
|
816
|
+
margin-bottom: 4px;
|
|
817
|
+
letter-spacing: 0.3px;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
.cpk-td__tool-pre {
|
|
821
|
+
margin: 0;
|
|
822
|
+
font-family: "Spline Sans Mono", monospace;
|
|
823
|
+
font-size: 10px;
|
|
824
|
+
background: #f7f7f9;
|
|
825
|
+
padding: 6px 8px;
|
|
826
|
+
border-radius: 4px;
|
|
827
|
+
overflow-x: auto;
|
|
828
|
+
white-space: pre-wrap;
|
|
829
|
+
word-break: break-all;
|
|
830
|
+
color: #010507;
|
|
831
|
+
line-height: 1.6;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
/* ── Tool call group ─────────────────────────────────────────────── */
|
|
835
|
+
.cpk-td__tool-group {
|
|
836
|
+
border: 1px solid #e9e9ef;
|
|
837
|
+
border-radius: 6px;
|
|
838
|
+
overflow: hidden;
|
|
839
|
+
}
|
|
840
|
+
|
|
841
|
+
.cpk-td__tool-group-header {
|
|
842
|
+
padding: 5px 10px;
|
|
843
|
+
background: rgba(133, 236, 206, 0.15);
|
|
844
|
+
font-family: "Spline Sans Mono", monospace;
|
|
845
|
+
font-size: 10px;
|
|
846
|
+
color: #189370;
|
|
847
|
+
text-transform: uppercase;
|
|
848
|
+
font-weight: 500;
|
|
849
|
+
border-bottom: 1px solid #e9e9ef;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.cpk-td__tool-group .cpk-td__tool-block {
|
|
853
|
+
border: none;
|
|
854
|
+
border-bottom: 1px solid #e9e9ef;
|
|
855
|
+
border-radius: 0;
|
|
856
|
+
}
|
|
857
|
+
|
|
858
|
+
.cpk-td__tool-group .cpk-td__tool-block:last-child {
|
|
859
|
+
border-bottom: none;
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
/* ── Inline chips (reasoning / state update) ─────────────────────── */
|
|
863
|
+
.cpk-td__inline-chip {
|
|
864
|
+
display: flex;
|
|
865
|
+
align-items: center;
|
|
866
|
+
gap: 8px;
|
|
867
|
+
padding: 5px 0;
|
|
868
|
+
color: #838389;
|
|
869
|
+
font-family: "Spline Sans Mono", monospace;
|
|
870
|
+
font-size: 9px;
|
|
871
|
+
text-transform: uppercase;
|
|
872
|
+
}
|
|
873
|
+
|
|
874
|
+
.cpk-td__inline-chip::before,
|
|
875
|
+
.cpk-td__inline-chip::after {
|
|
876
|
+
content: "";
|
|
877
|
+
flex: 1;
|
|
878
|
+
height: 1px;
|
|
879
|
+
background: #e9e9ef;
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/* ── Generative UI ──────────────────────────────────────────────── */
|
|
883
|
+
@keyframes cpk-genui-enter {
|
|
884
|
+
from {
|
|
885
|
+
opacity: 0;
|
|
886
|
+
transform: translateY(8px);
|
|
887
|
+
}
|
|
888
|
+
to {
|
|
889
|
+
opacity: 1;
|
|
890
|
+
transform: translateY(0);
|
|
891
|
+
}
|
|
892
|
+
}
|
|
893
|
+
|
|
894
|
+
.cpk-td__genui {
|
|
895
|
+
display: flex;
|
|
896
|
+
flex-direction: column;
|
|
897
|
+
gap: 6px;
|
|
898
|
+
padding: 4px 16px 8px;
|
|
899
|
+
animation: cpk-genui-enter 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;
|
|
900
|
+
}
|
|
901
|
+
|
|
902
|
+
.cpk-td__genui-badge {
|
|
903
|
+
display: inline-flex;
|
|
904
|
+
align-items: center;
|
|
905
|
+
gap: 4px;
|
|
906
|
+
padding: 2px 8px;
|
|
907
|
+
border-radius: 4px;
|
|
908
|
+
background: #eee6fe;
|
|
909
|
+
color: #57575b;
|
|
910
|
+
font-size: 10px;
|
|
911
|
+
font-weight: 600;
|
|
912
|
+
align-self: flex-start;
|
|
913
|
+
}
|
|
914
|
+
|
|
915
|
+
.cpk-td__genui-card {
|
|
916
|
+
overflow: hidden;
|
|
917
|
+
border-radius: 12px;
|
|
918
|
+
border: 1px solid #e2e8f0;
|
|
919
|
+
background: #fff;
|
|
920
|
+
box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.08);
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
.cpk-td__genui-placeholder {
|
|
924
|
+
padding: 8px 12px;
|
|
925
|
+
border-radius: 8px;
|
|
926
|
+
border: 1px solid #ede9fe;
|
|
927
|
+
background: #f5f3ff;
|
|
928
|
+
color: #7c3aed;
|
|
929
|
+
font-size: 11px;
|
|
930
|
+
}
|
|
931
|
+
|
|
932
|
+
/* ── AG-UI Events ────────────────────────────────────────────────── */
|
|
933
|
+
.cpk-td__event {
|
|
934
|
+
flex-shrink: 0;
|
|
935
|
+
border: 1px solid #e9e9ef;
|
|
936
|
+
border-radius: 6px;
|
|
937
|
+
overflow: hidden;
|
|
938
|
+
/*
|
|
939
|
+
* content-visibility: auto lets the browser skip layout + paint for
|
|
940
|
+
* off-screen events while keeping them in the DOM (so scroll size
|
|
941
|
+
* stays correct). Without this, switching back to AG-UI Events on a
|
|
942
|
+
* thread with hundreds of events triggers a full layout pass over
|
|
943
|
+
* every event row, which on Martha's intelligence-backed example
|
|
944
|
+
* shows up as a multi-second freeze each time the panel becomes
|
|
945
|
+
* visible. The intrinsic-size hint avoids the visible jump as the
|
|
946
|
+
* browser swaps in real heights when items scroll into view.
|
|
947
|
+
*/
|
|
948
|
+
content-visibility: auto;
|
|
949
|
+
contain-intrinsic-size: 0 80px;
|
|
950
|
+
}
|
|
951
|
+
|
|
952
|
+
.cpk-td__event-header {
|
|
953
|
+
display: flex;
|
|
954
|
+
justify-content: space-between;
|
|
955
|
+
align-items: center;
|
|
956
|
+
padding: 5px 10px;
|
|
957
|
+
}
|
|
958
|
+
|
|
959
|
+
.cpk-td__event-type {
|
|
960
|
+
font-family: "Spline Sans Mono", monospace;
|
|
961
|
+
font-size: 9px;
|
|
962
|
+
font-weight: 500;
|
|
963
|
+
text-transform: uppercase;
|
|
964
|
+
}
|
|
965
|
+
|
|
966
|
+
.cpk-td__event-time {
|
|
967
|
+
font-family: "Spline Sans Mono", monospace;
|
|
968
|
+
font-size: 9px;
|
|
969
|
+
color: #838389;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
.cpk-td__event-payload {
|
|
973
|
+
margin: 0;
|
|
974
|
+
font-family: "Spline Sans Mono", monospace;
|
|
975
|
+
font-size: 10px;
|
|
976
|
+
line-height: 1.6;
|
|
977
|
+
white-space: pre-wrap;
|
|
978
|
+
word-break: break-all;
|
|
979
|
+
color: #57575b;
|
|
980
|
+
padding: 8px 10px;
|
|
981
|
+
border-top: 1px solid #e9e9ef;
|
|
982
|
+
}
|
|
983
|
+
|
|
984
|
+
/* ── JSON block (agent state) ────────────────────────────────────── */
|
|
985
|
+
.cpk-td__json-block {
|
|
986
|
+
margin: 0;
|
|
987
|
+
font-family: "Spline Sans Mono", monospace;
|
|
988
|
+
font-size: 11px;
|
|
989
|
+
line-height: 1.8;
|
|
990
|
+
white-space: pre-wrap;
|
|
991
|
+
word-break: break-all;
|
|
992
|
+
color: #57575b;
|
|
993
|
+
}
|
|
994
|
+
|
|
995
|
+
/* ── Resize divider ──────────────────────────────────────────────── */
|
|
996
|
+
/* Floats over the drawer's left edge so the toggle and the drawer
|
|
997
|
+
touch directly without a 4px flex-gap between them. The hit zone
|
|
998
|
+
is wider than its visual hint to make it easy to grab. */
|
|
999
|
+
.cpk-td__detail-divider {
|
|
1000
|
+
position: absolute;
|
|
1001
|
+
top: 0;
|
|
1002
|
+
bottom: 0;
|
|
1003
|
+
left: -3px;
|
|
1004
|
+
width: 7px;
|
|
1005
|
+
cursor: col-resize;
|
|
1006
|
+
background: transparent;
|
|
1007
|
+
z-index: 5;
|
|
1008
|
+
}
|
|
1009
|
+
|
|
1010
|
+
.cpk-td__detail-divider:hover {
|
|
1011
|
+
background: rgba(190, 194, 255, 0.3);
|
|
1012
|
+
}
|
|
1013
|
+
|
|
1014
|
+
/* ── Right detail panel ──────────────────────────────────────────── */
|
|
1015
|
+
.cpk-td__detail {
|
|
1016
|
+
flex-shrink: 0;
|
|
1017
|
+
overflow: hidden;
|
|
1018
|
+
background: #f7f7f9;
|
|
1019
|
+
display: flex;
|
|
1020
|
+
flex-direction: column;
|
|
1021
|
+
gap: 0;
|
|
1022
|
+
padding: 0;
|
|
1023
|
+
box-sizing: border-box;
|
|
1024
|
+
position: relative;
|
|
1025
|
+
/* Slide open/closed via width + padding transition. When closed,
|
|
1026
|
+
width and padding are 0 so the drawer fully collapses. */
|
|
1027
|
+
transition:
|
|
1028
|
+
width 220ms cubic-bezier(0.4, 0, 0.2, 1),
|
|
1029
|
+
padding 220ms cubic-bezier(0.4, 0, 0.2, 1);
|
|
1030
|
+
}
|
|
1031
|
+
|
|
1032
|
+
.cpk-td__detail[data-open="true"] {
|
|
1033
|
+
overflow-y: auto;
|
|
1034
|
+
padding: 16px;
|
|
1035
|
+
}
|
|
1036
|
+
|
|
1037
|
+
.cpk-tdp__section-title {
|
|
1038
|
+
font-family: "Spline Sans Mono", monospace;
|
|
1039
|
+
font-size: 10px;
|
|
1040
|
+
font-weight: 500;
|
|
1041
|
+
color: #838389;
|
|
1042
|
+
text-transform: uppercase;
|
|
1043
|
+
letter-spacing: 0.6px;
|
|
1044
|
+
margin-bottom: 8px;
|
|
1045
|
+
}
|
|
1046
|
+
|
|
1047
|
+
.cpk-tdp__divider {
|
|
1048
|
+
height: 1px;
|
|
1049
|
+
background: #dbdbe5;
|
|
1050
|
+
margin: 14px 0;
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
.cpk-tdp__row {
|
|
1054
|
+
display: flex;
|
|
1055
|
+
justify-content: space-between;
|
|
1056
|
+
align-items: flex-start;
|
|
1057
|
+
padding: 3px 0;
|
|
1058
|
+
gap: 8px;
|
|
1059
|
+
}
|
|
1060
|
+
|
|
1061
|
+
.cpk-tdp__label {
|
|
1062
|
+
color: #838389;
|
|
1063
|
+
font-size: 11px;
|
|
1064
|
+
white-space: nowrap;
|
|
1065
|
+
flex-shrink: 0;
|
|
1066
|
+
}
|
|
1067
|
+
|
|
1068
|
+
.cpk-tdp__value {
|
|
1069
|
+
color: #010507;
|
|
1070
|
+
font-family: "Spline Sans Mono", monospace;
|
|
1071
|
+
font-size: 11px;
|
|
1072
|
+
text-align: right;
|
|
1073
|
+
min-width: 0;
|
|
1074
|
+
}
|
|
1075
|
+
|
|
1076
|
+
.cpk-tdp__value--truncate {
|
|
1077
|
+
overflow: hidden;
|
|
1078
|
+
text-overflow: ellipsis;
|
|
1079
|
+
white-space: nowrap;
|
|
1080
|
+
max-width: 130px;
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
.cpk-tdp__value--wrap {
|
|
1084
|
+
white-space: normal;
|
|
1085
|
+
word-break: break-all;
|
|
1086
|
+
text-align: right;
|
|
1087
|
+
}
|
|
1088
|
+
`;
|
|
1089
|
+
}
|
|
1090
|
+
updated(_changed) {
|
|
1091
|
+
if (this.threadId !== this._lastFetchedThreadId) {
|
|
1092
|
+
this._lastFetchedThreadId = this.threadId;
|
|
1093
|
+
this._lastSeenLiveMessageVersion = this.liveMessageVersion;
|
|
1094
|
+
this._tab = "conversation";
|
|
1095
|
+
this._activatedTabs = new Set(["conversation"]);
|
|
1096
|
+
this._panelTplCache = /* @__PURE__ */ new Map();
|
|
1097
|
+
this._expandedTools = /* @__PURE__ */ new Set();
|
|
1098
|
+
this._expandedMessages = /* @__PURE__ */ new Set();
|
|
1099
|
+
this._messagesAbort?.abort();
|
|
1100
|
+
this._messagesAbort = null;
|
|
1101
|
+
this._eventsAbort?.abort();
|
|
1102
|
+
this._eventsAbort = null;
|
|
1103
|
+
this._stateAbort?.abort();
|
|
1104
|
+
this._stateAbort = null;
|
|
1105
|
+
this._eventsFetched = false;
|
|
1106
|
+
this._stateFetched = false;
|
|
1107
|
+
this._fetchedEvents = null;
|
|
1108
|
+
this._fetchedState = null;
|
|
1109
|
+
if (this.threadId) this.fetchMessages(this.threadId);
|
|
1110
|
+
else this._conversation = [];
|
|
1111
|
+
} else if (this.threadId && this.liveMessageVersion !== this._lastSeenLiveMessageVersion) {
|
|
1112
|
+
this._lastSeenLiveMessageVersion = this.liveMessageVersion;
|
|
1113
|
+
this._messagesAbort?.abort();
|
|
1114
|
+
this._messagesAbort = null;
|
|
1115
|
+
this.fetchMessages(this.threadId, true);
|
|
1116
|
+
}
|
|
1117
|
+
}
|
|
1118
|
+
/**
|
|
1119
|
+
* Fetch the canonical conversation for `threadId` from the runtime.
|
|
1120
|
+
*
|
|
1121
|
+
* `silent` is true for live re-fetches triggered by `liveMessageVersion`
|
|
1122
|
+
* bumps during streaming. In that mode we never toggle the loading state
|
|
1123
|
+
* (which would flash "Loading messages…" between every message) and we
|
|
1124
|
+
* keep the previous conversation on transient errors instead of blanking
|
|
1125
|
+
* it. Initial threadId-change fetches use the default (`silent=false`)
|
|
1126
|
+
* so users see an explicit loading indicator on first load.
|
|
1127
|
+
*/
|
|
1128
|
+
async fetchMessages(threadId, silent = false) {
|
|
1129
|
+
if (!this.runtimeUrl) {
|
|
1130
|
+
if (!silent) this._conversation = [];
|
|
1131
|
+
return;
|
|
1132
|
+
}
|
|
1133
|
+
const controller = new AbortController();
|
|
1134
|
+
this._messagesAbort = controller;
|
|
1135
|
+
if (!silent) {
|
|
1136
|
+
this._loadingMessages = true;
|
|
1137
|
+
this._messagesError = null;
|
|
1138
|
+
}
|
|
1139
|
+
try {
|
|
1140
|
+
const res = await fetch(`${this.runtimeUrl}/threads/${encodeURIComponent(threadId)}/messages`, {
|
|
1141
|
+
headers: { ...this.headers },
|
|
1142
|
+
signal: controller.signal
|
|
1143
|
+
});
|
|
1144
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1145
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1146
|
+
const data = await res.json();
|
|
1147
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1148
|
+
this._conversation = this.mapMessages(data.messages);
|
|
1149
|
+
} catch (err) {
|
|
1150
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
1151
|
+
if (!silent) {
|
|
1152
|
+
this._messagesError = err instanceof Error ? err.message : "Failed to load messages";
|
|
1153
|
+
this._conversation = [];
|
|
1154
|
+
}
|
|
1155
|
+
} finally {
|
|
1156
|
+
if (!silent && !controller.signal.aborted) this._loadingMessages = false;
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
async fetchEvents(threadId) {
|
|
1160
|
+
this._eventsNotAvailable = false;
|
|
1161
|
+
if (!this.runtimeUrl) {
|
|
1162
|
+
this._fetchedEvents = null;
|
|
1163
|
+
return;
|
|
1164
|
+
}
|
|
1165
|
+
const controller = new AbortController();
|
|
1166
|
+
this._eventsAbort = controller;
|
|
1167
|
+
this._loadingEvents = true;
|
|
1168
|
+
this._eventsError = null;
|
|
1169
|
+
try {
|
|
1170
|
+
const res = await fetch(`${this.runtimeUrl}/threads/${encodeURIComponent(threadId)}/events`, {
|
|
1171
|
+
headers: { ...this.headers },
|
|
1172
|
+
signal: controller.signal
|
|
1173
|
+
});
|
|
1174
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1175
|
+
if (res.status === 501) {
|
|
1176
|
+
this._eventsNotAvailable = true;
|
|
1177
|
+
this._fetchedEvents = null;
|
|
1178
|
+
return;
|
|
1179
|
+
}
|
|
1180
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1181
|
+
const data = await res.json();
|
|
1182
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1183
|
+
this._fetchedEvents = this.mapApiEvents(data.events);
|
|
1184
|
+
} catch (err) {
|
|
1185
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
1186
|
+
if (this.threadId !== threadId) return;
|
|
1187
|
+
this._eventsError = err instanceof Error ? err.message : "Failed to load events";
|
|
1188
|
+
this._fetchedEvents = [];
|
|
1189
|
+
} finally {
|
|
1190
|
+
if (!controller.signal.aborted && this.threadId === threadId) this._loadingEvents = false;
|
|
1191
|
+
}
|
|
1192
|
+
}
|
|
1193
|
+
async fetchState(threadId) {
|
|
1194
|
+
this._stateNotAvailable = false;
|
|
1195
|
+
if (!this.runtimeUrl) {
|
|
1196
|
+
this._fetchedState = null;
|
|
1197
|
+
return;
|
|
1198
|
+
}
|
|
1199
|
+
const controller = new AbortController();
|
|
1200
|
+
this._stateAbort = controller;
|
|
1201
|
+
this._loadingState = true;
|
|
1202
|
+
this._stateError = null;
|
|
1203
|
+
try {
|
|
1204
|
+
const res = await fetch(`${this.runtimeUrl}/threads/${encodeURIComponent(threadId)}/state`, {
|
|
1205
|
+
headers: { ...this.headers },
|
|
1206
|
+
signal: controller.signal
|
|
1207
|
+
});
|
|
1208
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1209
|
+
if (res.status === 501) {
|
|
1210
|
+
this._stateNotAvailable = true;
|
|
1211
|
+
this._fetchedState = null;
|
|
1212
|
+
return;
|
|
1213
|
+
}
|
|
1214
|
+
if (!res.ok) throw new Error(`HTTP ${res.status}`);
|
|
1215
|
+
const data = await res.json();
|
|
1216
|
+
if (controller.signal.aborted || this.threadId !== threadId) return;
|
|
1217
|
+
this._fetchedState = data.state ?? null;
|
|
1218
|
+
} catch (err) {
|
|
1219
|
+
if (err instanceof Error && err.name === "AbortError") return;
|
|
1220
|
+
if (this.threadId !== threadId) return;
|
|
1221
|
+
this._stateError = err instanceof Error ? err.message : "Failed to load state";
|
|
1222
|
+
this._fetchedState = null;
|
|
1223
|
+
} finally {
|
|
1224
|
+
if (!controller.signal.aborted && this.threadId === threadId) this._loadingState = false;
|
|
1225
|
+
}
|
|
1226
|
+
}
|
|
1227
|
+
mapMessages(messages) {
|
|
1228
|
+
const items = [];
|
|
1229
|
+
const toolCallMap = /* @__PURE__ */ new Map();
|
|
1230
|
+
for (const msg of messages) if (msg.role === "user" && msg.content) items.push({
|
|
1231
|
+
id: msg.id,
|
|
1232
|
+
type: "user",
|
|
1233
|
+
content: msg.content,
|
|
1234
|
+
createdAt: ""
|
|
1235
|
+
});
|
|
1236
|
+
else if (msg.role === "assistant") {
|
|
1237
|
+
if (msg.toolCalls?.length) for (const tc of msg.toolCalls) {
|
|
1238
|
+
let args = {};
|
|
1239
|
+
try {
|
|
1240
|
+
args = JSON.parse(tc.args);
|
|
1241
|
+
} catch (err) {
|
|
1242
|
+
console.error("[CopilotKit Inspector] Failed to parse tool-call arguments", {
|
|
1243
|
+
toolCallId: tc.id,
|
|
1244
|
+
raw: tc.args,
|
|
1245
|
+
error: err
|
|
1246
|
+
});
|
|
1247
|
+
args = {
|
|
1248
|
+
__parseError: true,
|
|
1249
|
+
__raw: tc.args
|
|
1250
|
+
};
|
|
1251
|
+
}
|
|
1252
|
+
const item = {
|
|
1253
|
+
id: tc.id,
|
|
1254
|
+
type: "tool_call",
|
|
1255
|
+
toolName: tc.name,
|
|
1256
|
+
toolCallId: tc.id,
|
|
1257
|
+
arguments: args,
|
|
1258
|
+
result: null,
|
|
1259
|
+
createdAt: ""
|
|
1260
|
+
};
|
|
1261
|
+
toolCallMap.set(tc.id, item);
|
|
1262
|
+
items.push(item);
|
|
1263
|
+
}
|
|
1264
|
+
if (msg.content) items.push({
|
|
1265
|
+
id: msg.id,
|
|
1266
|
+
type: "assistant",
|
|
1267
|
+
content: msg.content,
|
|
1268
|
+
createdAt: ""
|
|
1269
|
+
});
|
|
1270
|
+
} else if (msg.role === "activity") items.push({
|
|
1271
|
+
id: msg.id,
|
|
1272
|
+
type: "generative-ui",
|
|
1273
|
+
activityType: msg.activityType ?? "unknown",
|
|
1274
|
+
createdAt: ""
|
|
1275
|
+
});
|
|
1276
|
+
else if (msg.role === "tool" && msg.toolCallId) {
|
|
1277
|
+
const tc = toolCallMap.get(msg.toolCallId);
|
|
1278
|
+
if (tc) try {
|
|
1279
|
+
tc.result = JSON.parse(msg.content ?? "{}");
|
|
1280
|
+
} catch (err) {
|
|
1281
|
+
console.error("[CopilotKit Inspector] Failed to parse tool-call result content", {
|
|
1282
|
+
toolCallId: msg.toolCallId,
|
|
1283
|
+
raw: msg.content,
|
|
1284
|
+
error: err
|
|
1285
|
+
});
|
|
1286
|
+
tc.result = {
|
|
1287
|
+
__parseError: true,
|
|
1288
|
+
__raw: msg.content ?? null
|
|
1289
|
+
};
|
|
1290
|
+
}
|
|
1291
|
+
}
|
|
1292
|
+
return items;
|
|
1293
|
+
}
|
|
1294
|
+
mapApiEvents(events) {
|
|
1295
|
+
return events.map((event) => {
|
|
1296
|
+
const { type, timestamp, ...rest } = event;
|
|
1297
|
+
return {
|
|
1298
|
+
type: typeof type === "string" ? type : "UNKNOWN",
|
|
1299
|
+
timestamp: typeof timestamp === "string" || typeof timestamp === "number" ? timestamp : Date.now(),
|
|
1300
|
+
payload: rest
|
|
1301
|
+
};
|
|
1302
|
+
});
|
|
1303
|
+
}
|
|
1304
|
+
get renderItems() {
|
|
1305
|
+
const items = this._conversation;
|
|
1306
|
+
const result = [];
|
|
1307
|
+
const seen = /* @__PURE__ */ new Set();
|
|
1308
|
+
for (const item of items) {
|
|
1309
|
+
if (item.type === "agent_responded") continue;
|
|
1310
|
+
if (item.type !== "tool_call" || !item.groupId) {
|
|
1311
|
+
result.push(item);
|
|
1312
|
+
continue;
|
|
1313
|
+
}
|
|
1314
|
+
if (seen.has(item.groupId)) continue;
|
|
1315
|
+
seen.add(item.groupId);
|
|
1316
|
+
const group = {
|
|
1317
|
+
type: "tool_call_group",
|
|
1318
|
+
id: item.groupId,
|
|
1319
|
+
items: items.filter((i) => i.type === "tool_call" && i.groupId === item.groupId)
|
|
1320
|
+
};
|
|
1321
|
+
result.push(group);
|
|
1322
|
+
}
|
|
1323
|
+
return result;
|
|
1324
|
+
}
|
|
1325
|
+
get activityCounts() {
|
|
1326
|
+
let messages = 0;
|
|
1327
|
+
let toolCalls = 0;
|
|
1328
|
+
let generativeUi = 0;
|
|
1329
|
+
for (const item of this._conversation) {
|
|
1330
|
+
if (item.type === "user" || item.type === "assistant") messages++;
|
|
1331
|
+
if (item.type === "tool_call") toolCalls++;
|
|
1332
|
+
if (item.type === "generative-ui") generativeUi++;
|
|
1333
|
+
}
|
|
1334
|
+
return {
|
|
1335
|
+
messages,
|
|
1336
|
+
toolCalls,
|
|
1337
|
+
generativeUi
|
|
1338
|
+
};
|
|
1339
|
+
}
|
|
1340
|
+
get duration() {
|
|
1341
|
+
const t = this.thread;
|
|
1342
|
+
if (!t?.createdAt || !t?.updatedAt) return "—";
|
|
1343
|
+
const ms = new Date(t.updatedAt).getTime() - new Date(t.createdAt).getTime();
|
|
1344
|
+
if (ms < 0) return "—";
|
|
1345
|
+
if (ms < 1e3) return `${ms}ms`;
|
|
1346
|
+
const s = Math.floor(ms / 1e3);
|
|
1347
|
+
if (s < 60) return `${s}s`;
|
|
1348
|
+
return `${Math.floor(s / 60)}m ${s % 60}s`;
|
|
1349
|
+
}
|
|
1350
|
+
toggleToolExpand(id) {
|
|
1351
|
+
const next = new Set(this._expandedTools);
|
|
1352
|
+
if (next.has(id)) next.delete(id);
|
|
1353
|
+
else next.add(id);
|
|
1354
|
+
this._expandedTools = next;
|
|
1355
|
+
}
|
|
1356
|
+
toggleMessageExpand(id) {
|
|
1357
|
+
const next = new Set(this._expandedMessages);
|
|
1358
|
+
if (next.has(id)) next.delete(id);
|
|
1359
|
+
else next.add(id);
|
|
1360
|
+
this._expandedMessages = next;
|
|
1361
|
+
}
|
|
1362
|
+
get activeEvents() {
|
|
1363
|
+
if (this._eventsNotAvailable) return [];
|
|
1364
|
+
return this._fetchedEvents ?? this.agentEventsInput ?? [];
|
|
1365
|
+
}
|
|
1366
|
+
get activeState() {
|
|
1367
|
+
if (this._stateNotAvailable) return null;
|
|
1368
|
+
return this._fetchedState ?? this.agentStateInput ?? null;
|
|
1369
|
+
}
|
|
1370
|
+
hasRenderableState() {
|
|
1371
|
+
const s = this.activeState;
|
|
1372
|
+
return !!s && typeof s === "object" && Object.keys(s).length > 0;
|
|
1373
|
+
}
|
|
1374
|
+
shortId(id) {
|
|
1375
|
+
if (!id) return "—";
|
|
1376
|
+
return id.length > 20 ? id.slice(0, 8) + "…" : id;
|
|
1377
|
+
}
|
|
1378
|
+
fmtTime(dateStr) {
|
|
1379
|
+
if (!dateStr) return "—";
|
|
1380
|
+
const d = new Date(dateStr);
|
|
1381
|
+
if (Number.isNaN(d.getTime())) return "—";
|
|
1382
|
+
return d.toLocaleTimeString("en-US", {
|
|
1383
|
+
hour: "2-digit",
|
|
1384
|
+
minute: "2-digit",
|
|
1385
|
+
second: "2-digit",
|
|
1386
|
+
hour12: false
|
|
1387
|
+
});
|
|
1388
|
+
}
|
|
1389
|
+
render() {
|
|
1390
|
+
return html`
|
|
1391
|
+
<div class="cpk-td">
|
|
1392
|
+
<!-- ── Left area: tabs + content ─────────────────────────────────── -->
|
|
1393
|
+
<div class="cpk-td__left">
|
|
1394
|
+
<!-- Tab bar -->
|
|
1395
|
+
<div class="cpk-td__tabs-header">
|
|
1396
|
+
<div class="cpk-td__tab-group" role="tablist">
|
|
1397
|
+
${ɵCpkThreadDetails.TAB_LIST.map((tab) => html`
|
|
1398
|
+
<button
|
|
1399
|
+
role="tab"
|
|
1400
|
+
class="cpk-td__tab ${this._tab === tab.id ? "cpk-td__tab--active" : ""}"
|
|
1401
|
+
@click=${() => this.activateTab(tab.id)}
|
|
1402
|
+
>
|
|
1403
|
+
${tab.label}
|
|
1404
|
+
</button>
|
|
1405
|
+
`)}
|
|
1406
|
+
</div>
|
|
1407
|
+
${this.renderPanelToggle()}
|
|
1408
|
+
</div>
|
|
1409
|
+
|
|
1410
|
+
<!-- Scrollable content -->
|
|
1411
|
+
<div class="cpk-td__content">
|
|
1412
|
+
${this._panelInitializing ? html`
|
|
1413
|
+
<div class="cpk-td__status">Loading…</div>
|
|
1414
|
+
` : nothing}
|
|
1415
|
+
${ɵCpkThreadDetails.TAB_LIST.map((tab) => this._activatedTabs.has(tab.id) ? html`<div
|
|
1416
|
+
class="cpk-td__panel"
|
|
1417
|
+
style=${this._tab === tab.id && !this._panelInitializing ? "" : "display:none"}
|
|
1418
|
+
>
|
|
1419
|
+
${this.renderTabContent(tab.id)}
|
|
1420
|
+
</div>` : nothing)}
|
|
1421
|
+
</div>
|
|
1422
|
+
</div>
|
|
1423
|
+
|
|
1424
|
+
<!--
|
|
1425
|
+
Drawer always rendered so width animates between 0 and its
|
|
1426
|
+
target. Divider lives INSIDE the drawer and is absolutely
|
|
1427
|
+
positioned over its left edge so the toggle (rightmost of the
|
|
1428
|
+
tab row) and the drawer touch with no flex-gap between them.
|
|
1429
|
+
-->
|
|
1430
|
+
<div
|
|
1431
|
+
class="cpk-td__detail"
|
|
1432
|
+
data-open=${this._showDetailPanel ? "true" : "false"}
|
|
1433
|
+
style="width:${this._showDetailPanel ? this._detailPanelWidth : 0}px"
|
|
1434
|
+
aria-hidden=${this._showDetailPanel ? "false" : "true"}
|
|
1435
|
+
>
|
|
1436
|
+
${this._showDetailPanel ? html`
|
|
1437
|
+
<div
|
|
1438
|
+
class="cpk-td__detail-divider"
|
|
1439
|
+
@pointerdown=${this.onDetailDividerDown}
|
|
1440
|
+
@pointermove=${this.onDetailDividerMove}
|
|
1441
|
+
@pointerup=${this.onDetailDividerUp}
|
|
1442
|
+
@pointercancel=${this.onDetailDividerUp}
|
|
1443
|
+
></div>
|
|
1444
|
+
` : nothing}
|
|
1445
|
+
${this.renderDetailPanel()}
|
|
1446
|
+
</div>
|
|
1447
|
+
</div>
|
|
1448
|
+
`;
|
|
1449
|
+
}
|
|
1450
|
+
renderConversation() {
|
|
1451
|
+
if (this._loadingMessages) return html`
|
|
1452
|
+
<div class="cpk-td__status">Loading messages…</div>
|
|
1453
|
+
`;
|
|
1454
|
+
if (this._messagesError) return html`<div class="cpk-td__status cpk-td__status--error">
|
|
1455
|
+
${this._messagesError}
|
|
1456
|
+
</div>`;
|
|
1457
|
+
if (this._conversation.length === 0) return html`
|
|
1458
|
+
<div class="cpk-td__empty-state">
|
|
1459
|
+
<svg
|
|
1460
|
+
width="28"
|
|
1461
|
+
height="28"
|
|
1462
|
+
viewBox="0 0 24 24"
|
|
1463
|
+
fill="none"
|
|
1464
|
+
stroke="currentColor"
|
|
1465
|
+
stroke-width="1.5"
|
|
1466
|
+
stroke-linecap="round"
|
|
1467
|
+
stroke-linejoin="round"
|
|
1468
|
+
>
|
|
1469
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
1470
|
+
</svg>
|
|
1471
|
+
<span>No messages yet</span>
|
|
1472
|
+
</div>
|
|
1473
|
+
`;
|
|
1474
|
+
return this.cachedPanelTpl("conversation", [
|
|
1475
|
+
this._conversation,
|
|
1476
|
+
this._expandedTools,
|
|
1477
|
+
this._expandedMessages
|
|
1478
|
+
], () => {
|
|
1479
|
+
return html`${this.renderItems.map((item) => this.renderRenderItem(item))}`;
|
|
1480
|
+
});
|
|
1481
|
+
}
|
|
1482
|
+
/**
|
|
1483
|
+
* Memoize the rendered TemplateResult for `slot` keyed by tuple
|
|
1484
|
+
* element-wise reference equality. The hot path for tab switches: when
|
|
1485
|
+
* the underlying data hasn't changed, return the previously built
|
|
1486
|
+
* TemplateResult so Lit's diff short-circuits. Each panel's `key` is
|
|
1487
|
+
* the tuple of inputs the template reads — pass everything the template
|
|
1488
|
+
* depends on, or the cache will return stale output when those inputs
|
|
1489
|
+
* change without the listed key flipping.
|
|
1490
|
+
*/
|
|
1491
|
+
cachedPanelTpl(slot, key, build) {
|
|
1492
|
+
const cached = this._panelTplCache.get(slot);
|
|
1493
|
+
if (cached && cached.key.length === key.length && cached.key.every((v, i) => v === key[i])) return cached.tpl;
|
|
1494
|
+
const tpl = build();
|
|
1495
|
+
this._panelTplCache.set(slot, {
|
|
1496
|
+
key,
|
|
1497
|
+
tpl
|
|
1498
|
+
});
|
|
1499
|
+
return tpl;
|
|
1500
|
+
}
|
|
1501
|
+
renderRenderItem(item) {
|
|
1502
|
+
switch (item.type) {
|
|
1503
|
+
case "user":
|
|
1504
|
+
case "assistant": return this.renderBubble(item);
|
|
1505
|
+
case "tool_call": return this.renderToolBlock(item);
|
|
1506
|
+
case "tool_call_group": return this.renderToolGroup(item);
|
|
1507
|
+
case "reasoning": return html`<div class="cpk-td__inline-chip">
|
|
1508
|
+
<span>Reasoned for ${item.duration}</span>
|
|
1509
|
+
</div>`;
|
|
1510
|
+
case "state_update": return html`
|
|
1511
|
+
<div class="cpk-td__inline-chip">
|
|
1512
|
+
<span>Updated agent state</span>
|
|
1513
|
+
</div>
|
|
1514
|
+
`;
|
|
1515
|
+
case "generative-ui": return this.renderGenerativeUI(item);
|
|
1516
|
+
case "agent_responded": return nothing;
|
|
1517
|
+
}
|
|
1518
|
+
}
|
|
1519
|
+
renderBubble(item) {
|
|
1520
|
+
const isUser = item.type === "user";
|
|
1521
|
+
const threshold = ɵCpkThreadDetails.COLLAPSE_THRESHOLD;
|
|
1522
|
+
const expanded = this._expandedMessages.has(item.id);
|
|
1523
|
+
const tooLong = item.content.length > threshold;
|
|
1524
|
+
const shown = tooLong && !expanded ? item.content.slice(0, threshold) + "…" : item.content;
|
|
1525
|
+
return html`
|
|
1526
|
+
<div
|
|
1527
|
+
class="cpk-td__bubble ${isUser ? "cpk-td__bubble--user" : "cpk-td__bubble--assistant"}"
|
|
1528
|
+
>
|
|
1529
|
+
<div
|
|
1530
|
+
class="cpk-td__bubble-inner ${isUser ? "cpk-td__bubble-inner--user" : "cpk-td__bubble-inner--assistant"}"
|
|
1531
|
+
>
|
|
1532
|
+
${shown}
|
|
1533
|
+
${tooLong ? html`<span
|
|
1534
|
+
class="cpk-td__show-more"
|
|
1535
|
+
@click=${() => this.toggleMessageExpand(item.id)}
|
|
1536
|
+
>${expanded ? "Show less" : "Show more"}</span
|
|
1537
|
+
>` : nothing}
|
|
1538
|
+
</div>
|
|
1539
|
+
</div>
|
|
1540
|
+
`;
|
|
1541
|
+
}
|
|
1542
|
+
renderToolBlock(item) {
|
|
1543
|
+
const expanded = this._expandedTools.has(item.id);
|
|
1544
|
+
return html`
|
|
1545
|
+
<div class="cpk-td__tool-block">
|
|
1546
|
+
<div
|
|
1547
|
+
class="cpk-td__tool-header"
|
|
1548
|
+
@click=${() => this.toggleToolExpand(item.id)}
|
|
1549
|
+
>
|
|
1550
|
+
<svg width="10" height="10" viewBox="0 0 10 10" fill="none">
|
|
1551
|
+
<path
|
|
1552
|
+
d="M1 9C1 9 2 7 5 7C8 7 9 9 9 9M5 1C5 1 7 2.5 7 4.5C7 6.5 5 7 5 7C5 7 3 6.5 3 4.5C3 2.5 5 1 5 1Z"
|
|
1553
|
+
stroke="#189370"
|
|
1554
|
+
stroke-width="1.2"
|
|
1555
|
+
stroke-linecap="round"
|
|
1556
|
+
stroke-linejoin="round"
|
|
1557
|
+
/>
|
|
1558
|
+
</svg>
|
|
1559
|
+
<span class="cpk-td__tool-name">${item.toolName}</span>
|
|
1560
|
+
${item.result || Object.keys(item.arguments).length > 0 ? html`
|
|
1561
|
+
<span class="cpk-td__tool-status">DONE</span>
|
|
1562
|
+
` : html`
|
|
1563
|
+
<span class="cpk-td__tool-status cpk-td__tool-status--pending">PENDING</span>
|
|
1564
|
+
`}
|
|
1565
|
+
<span class="cpk-td__tool-chevron">${expanded ? "▾" : "▸"}</span>
|
|
1566
|
+
</div>
|
|
1567
|
+
${expanded ? html`
|
|
1568
|
+
<div class="cpk-td__tool-body">
|
|
1569
|
+
<div class="cpk-td__tool-section-label">Arguments</div>
|
|
1570
|
+
<pre class="cpk-td__tool-pre">
|
|
1571
|
+
${unsafeHTML(highlightedJson(item.arguments))}</pre
|
|
1572
|
+
>
|
|
1573
|
+
${item.result ? html`
|
|
1574
|
+
<div
|
|
1575
|
+
class="cpk-td__tool-section-label"
|
|
1576
|
+
style="margin-top:8px"
|
|
1577
|
+
>
|
|
1578
|
+
Result
|
|
1579
|
+
</div>
|
|
1580
|
+
<pre class="cpk-td__tool-pre">
|
|
1581
|
+
${unsafeHTML(highlightedJson(item.result))}</pre
|
|
1582
|
+
>
|
|
1583
|
+
` : nothing}
|
|
1584
|
+
</div>
|
|
1585
|
+
` : nothing}
|
|
1586
|
+
</div>
|
|
1587
|
+
`;
|
|
1588
|
+
}
|
|
1589
|
+
renderToolGroup(group) {
|
|
1590
|
+
return html`
|
|
1591
|
+
<div class="cpk-td__tool-group">
|
|
1592
|
+
<div class="cpk-td__tool-group-header">
|
|
1593
|
+
${group.items.length} tool call${group.items.length !== 1 ? "s" : ""}
|
|
1594
|
+
</div>
|
|
1595
|
+
${group.items.map((tc) => this.renderToolBlock(tc))}
|
|
1596
|
+
</div>
|
|
1597
|
+
`;
|
|
1598
|
+
}
|
|
1599
|
+
renderGenerativeUI(item) {
|
|
1600
|
+
return html`
|
|
1601
|
+
<div class="cpk-td__genui">
|
|
1602
|
+
<div class="cpk-td__genui-badge">
|
|
1603
|
+
<svg width="9" height="9" viewBox="0 0 24 24" fill="currentColor">
|
|
1604
|
+
<path d="M13 2L3 14h9l-1 8 10-12h-9l1-8z" />
|
|
1605
|
+
</svg>
|
|
1606
|
+
Generative UI
|
|
1607
|
+
</div>
|
|
1608
|
+
<div class="cpk-td__genui-placeholder">
|
|
1609
|
+
${item.activityType} — rendered in chat
|
|
1610
|
+
</div>
|
|
1611
|
+
</div>
|
|
1612
|
+
`;
|
|
1613
|
+
}
|
|
1614
|
+
renderState() {
|
|
1615
|
+
if (this._loadingState) return html`
|
|
1616
|
+
<div class="cpk-td__status">Loading state…</div>
|
|
1617
|
+
`;
|
|
1618
|
+
if (this._stateError) return html`<div class="cpk-td__status cpk-td__status--error">
|
|
1619
|
+
${this._stateError}
|
|
1620
|
+
</div>`;
|
|
1621
|
+
if (this._stateNotAvailable) return html`
|
|
1622
|
+
<div class="cpk-td__empty-state">
|
|
1623
|
+
<svg
|
|
1624
|
+
width="28"
|
|
1625
|
+
height="28"
|
|
1626
|
+
viewBox="0 0 24 24"
|
|
1627
|
+
fill="none"
|
|
1628
|
+
stroke="currentColor"
|
|
1629
|
+
stroke-width="1.5"
|
|
1630
|
+
stroke-linecap="round"
|
|
1631
|
+
stroke-linejoin="round"
|
|
1632
|
+
>
|
|
1633
|
+
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
|
1634
|
+
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
|
|
1635
|
+
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
|
1636
|
+
</svg>
|
|
1637
|
+
<span>State history not available</span>
|
|
1638
|
+
<span class="cpk-td__empty-hint"
|
|
1639
|
+
>This runtime doesn't yet expose per-thread agent state. Available when
|
|
1640
|
+
running against the in-memory runner.</span
|
|
1641
|
+
>
|
|
1642
|
+
</div>
|
|
1643
|
+
`;
|
|
1644
|
+
if (!this.hasRenderableState()) return html`
|
|
1645
|
+
<div class="cpk-td__empty-state">
|
|
1646
|
+
<svg
|
|
1647
|
+
width="28"
|
|
1648
|
+
height="28"
|
|
1649
|
+
viewBox="0 0 24 24"
|
|
1650
|
+
fill="none"
|
|
1651
|
+
stroke="currentColor"
|
|
1652
|
+
stroke-width="1.5"
|
|
1653
|
+
stroke-linecap="round"
|
|
1654
|
+
stroke-linejoin="round"
|
|
1655
|
+
>
|
|
1656
|
+
<ellipse cx="12" cy="5" rx="9" ry="3" />
|
|
1657
|
+
<path d="M21 12c0 1.66-4 3-9 3s-9-1.34-9-3" />
|
|
1658
|
+
<path d="M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5" />
|
|
1659
|
+
</svg>
|
|
1660
|
+
<span>No state captured</span>
|
|
1661
|
+
<span class="cpk-td__empty-hint"
|
|
1662
|
+
>Emitted live from STATE_SNAPSHOT events.</span
|
|
1663
|
+
>
|
|
1664
|
+
</div>
|
|
1665
|
+
`;
|
|
1666
|
+
const stateValue = this.activeState;
|
|
1667
|
+
return this.cachedPanelTpl("agent-state", [stateValue], () => {
|
|
1668
|
+
return html`<pre class="cpk-td__json-block">
|
|
1669
|
+
${unsafeHTML(highlightedJson(stateValue))}</pre
|
|
1670
|
+
>`;
|
|
1671
|
+
});
|
|
1672
|
+
}
|
|
1673
|
+
renderEvents() {
|
|
1674
|
+
if (this._loadingEvents) return html`
|
|
1675
|
+
<div class="cpk-td__status">Loading events…</div>
|
|
1676
|
+
`;
|
|
1677
|
+
if (this._eventsError) return html`<div class="cpk-td__status cpk-td__status--error">
|
|
1678
|
+
${this._eventsError}
|
|
1679
|
+
</div>`;
|
|
1680
|
+
if (this._eventsNotAvailable) return html`
|
|
1681
|
+
<div class="cpk-td__empty-state">
|
|
1682
|
+
<span>Event history not available</span>
|
|
1683
|
+
<span class="cpk-td__empty-hint"
|
|
1684
|
+
>This runtime doesn't yet expose per-thread AG-UI events. Available when
|
|
1685
|
+
running against the in-memory runner.</span
|
|
1686
|
+
>
|
|
1687
|
+
</div>
|
|
1688
|
+
`;
|
|
1689
|
+
const events = this.activeEvents;
|
|
1690
|
+
if (events.length === 0) return html`
|
|
1691
|
+
<div class="cpk-td__empty-state">
|
|
1692
|
+
<span>No events captured</span>
|
|
1693
|
+
<span class="cpk-td__empty-hint"
|
|
1694
|
+
>Events are recorded live. Run the agent to see them here.</span
|
|
1695
|
+
>
|
|
1696
|
+
</div>
|
|
1697
|
+
`;
|
|
1698
|
+
return this.cachedPanelTpl("ag-ui-events", [events], () => {
|
|
1699
|
+
return html`${events.map((event) => {
|
|
1700
|
+
const { bg, fg } = eventColors(event.type);
|
|
1701
|
+
return html`
|
|
1702
|
+
<div class="cpk-td__event">
|
|
1703
|
+
<div class="cpk-td__event-header" style="background:${bg}">
|
|
1704
|
+
<span class="cpk-td__event-type" style="color:${fg}"
|
|
1705
|
+
>${event.type}</span
|
|
1706
|
+
>
|
|
1707
|
+
<span class="cpk-td__event-time"
|
|
1708
|
+
>${formatTimestamp(event.timestamp)}</span
|
|
1709
|
+
>
|
|
1710
|
+
</div>
|
|
1711
|
+
<pre class="cpk-td__event-payload">
|
|
1712
|
+
${unsafeHTML(highlightedJson(event.payload))}</pre
|
|
1713
|
+
>
|
|
1714
|
+
</div>
|
|
1715
|
+
`;
|
|
1716
|
+
})}`;
|
|
1717
|
+
});
|
|
1718
|
+
}
|
|
1719
|
+
renderPanelToggle() {
|
|
1720
|
+
return html`
|
|
1721
|
+
<button
|
|
1722
|
+
class="cpk-td__panel-toggle ${this._showDetailPanel ? "cpk-td__panel-toggle--active" : ""}"
|
|
1723
|
+
@click=${() => {
|
|
1724
|
+
this._showDetailPanel = !this._showDetailPanel;
|
|
1725
|
+
}}
|
|
1726
|
+
title="Toggle thread details"
|
|
1727
|
+
type="button"
|
|
1728
|
+
>
|
|
1729
|
+
<svg
|
|
1730
|
+
width="14"
|
|
1731
|
+
height="14"
|
|
1732
|
+
viewBox="0 0 24 24"
|
|
1733
|
+
fill="none"
|
|
1734
|
+
stroke="currentColor"
|
|
1735
|
+
stroke-width="2"
|
|
1736
|
+
stroke-linecap="round"
|
|
1737
|
+
stroke-linejoin="round"
|
|
1738
|
+
>
|
|
1739
|
+
<rect x="3" y="3" width="18" height="18" rx="2" />
|
|
1740
|
+
<line x1="15" y1="3" x2="15" y2="21" />
|
|
1741
|
+
</svg>
|
|
1742
|
+
</button>
|
|
1743
|
+
`;
|
|
1744
|
+
}
|
|
1745
|
+
renderDetailPanel() {
|
|
1746
|
+
const counts = this.activityCounts;
|
|
1747
|
+
return html`
|
|
1748
|
+
<!-- Thread -->
|
|
1749
|
+
<div class="cpk-tdp__section-title">Thread</div>
|
|
1750
|
+
<div class="cpk-tdp__row">
|
|
1751
|
+
<span class="cpk-tdp__label">ID</span>
|
|
1752
|
+
<span class="cpk-tdp__value cpk-tdp__value--wrap"
|
|
1753
|
+
>${this.shortId(this.thread?.id)}</span
|
|
1754
|
+
>
|
|
1755
|
+
</div>
|
|
1756
|
+
<div class="cpk-tdp__row">
|
|
1757
|
+
<span class="cpk-tdp__label">Name</span>
|
|
1758
|
+
<span class="cpk-tdp__value">${this.thread?.name ?? "—"}</span>
|
|
1759
|
+
</div>
|
|
1760
|
+
<div class="cpk-tdp__row">
|
|
1761
|
+
<span class="cpk-tdp__label">Agent</span>
|
|
1762
|
+
<span class="cpk-tdp__value cpk-tdp__value--truncate"
|
|
1763
|
+
>${this.thread?.agentId ?? "—"}</span
|
|
1764
|
+
>
|
|
1765
|
+
</div>
|
|
1766
|
+
<div class="cpk-tdp__row">
|
|
1767
|
+
<span class="cpk-tdp__label">Created by</span>
|
|
1768
|
+
<span class="cpk-tdp__value cpk-tdp__value--truncate"
|
|
1769
|
+
>${this.thread?.createdById ?? "—"}</span
|
|
1770
|
+
>
|
|
1771
|
+
</div>
|
|
1772
|
+
|
|
1773
|
+
<div class="cpk-tdp__divider"></div>
|
|
1774
|
+
|
|
1775
|
+
<!-- Timestamps -->
|
|
1776
|
+
<div class="cpk-tdp__section-title">Timestamps</div>
|
|
1777
|
+
<div class="cpk-tdp__row">
|
|
1778
|
+
<span class="cpk-tdp__label">Created</span>
|
|
1779
|
+
<span class="cpk-tdp__value">${this.fmtTime(this.thread?.createdAt)}</span>
|
|
1780
|
+
</div>
|
|
1781
|
+
<div class="cpk-tdp__row">
|
|
1782
|
+
<span class="cpk-tdp__label">Updated</span>
|
|
1783
|
+
<span class="cpk-tdp__value">${this.fmtTime(this.thread?.updatedAt)}</span>
|
|
1784
|
+
</div>
|
|
1785
|
+
<div class="cpk-tdp__row">
|
|
1786
|
+
<span class="cpk-tdp__label">Duration</span>
|
|
1787
|
+
<span class="cpk-tdp__value">${this.duration}</span>
|
|
1788
|
+
</div>
|
|
1789
|
+
|
|
1790
|
+
<div class="cpk-tdp__divider"></div>
|
|
1791
|
+
|
|
1792
|
+
<!-- Activity -->
|
|
1793
|
+
<div class="cpk-tdp__section-title">Activity</div>
|
|
1794
|
+
<div class="cpk-tdp__row">
|
|
1795
|
+
<span class="cpk-tdp__label">Messages</span>
|
|
1796
|
+
<span class="cpk-tdp__value">${counts.messages}</span>
|
|
1797
|
+
</div>
|
|
1798
|
+
<div class="cpk-tdp__row">
|
|
1799
|
+
<span class="cpk-tdp__label">Tool calls</span>
|
|
1800
|
+
<span class="cpk-tdp__value">${counts.toolCalls}</span>
|
|
1801
|
+
</div>
|
|
1802
|
+
<div class="cpk-tdp__row">
|
|
1803
|
+
<span class="cpk-tdp__label">AG-UI events</span>
|
|
1804
|
+
<span class="cpk-tdp__value">${this.activeEvents.length}</span>
|
|
1805
|
+
</div>
|
|
1806
|
+
`;
|
|
1807
|
+
}
|
|
1808
|
+
};
|
|
1809
|
+
if (!customElements.get("cpk-thread-list")) customElements.define("cpk-thread-list", CpkThreadList);
|
|
1810
|
+
if (!customElements.get("cpk-thread-details")) customElements.define("cpk-thread-details", ɵCpkThreadDetails);
|
|
1811
|
+
var WebInspectorElement = class extends LitElement {
|
|
1812
|
+
constructor(..._args3) {
|
|
1813
|
+
super(..._args3);
|
|
60
1814
|
this._core = null;
|
|
61
1815
|
this.coreSubscriber = null;
|
|
62
1816
|
this.coreUnsubscribe = null;
|
|
@@ -66,6 +1820,7 @@ var WebInspectorElement = class extends LitElement {
|
|
|
66
1820
|
this.agentSubscriptions = /* @__PURE__ */ new Map();
|
|
67
1821
|
this.agentEvents = /* @__PURE__ */ new Map();
|
|
68
1822
|
this.agentMessages = /* @__PURE__ */ new Map();
|
|
1823
|
+
this.liveMessageVersion = /* @__PURE__ */ new Map();
|
|
69
1824
|
this.agentStates = /* @__PURE__ */ new Map();
|
|
70
1825
|
this.flattenedEvents = [];
|
|
71
1826
|
this.eventCounter = 0;
|
|
@@ -82,6 +1837,17 @@ var WebInspectorElement = class extends LitElement {
|
|
|
82
1837
|
this.draggedDuringInteraction = false;
|
|
83
1838
|
this.ignoreNextButtonClick = false;
|
|
84
1839
|
this.selectedMenu = "ag-ui-events";
|
|
1840
|
+
this.selectedThreadId = null;
|
|
1841
|
+
this.threadListWidth = 290;
|
|
1842
|
+
this.threadDividerResizing = false;
|
|
1843
|
+
this.threadDividerPointerId = -1;
|
|
1844
|
+
this.threadDividerStartX = 0;
|
|
1845
|
+
this.threadDividerStartWidth = 0;
|
|
1846
|
+
this._threads = [];
|
|
1847
|
+
this._threadStoreSubscriptions = /* @__PURE__ */ new Map();
|
|
1848
|
+
this._threadsByAgent = /* @__PURE__ */ new Map();
|
|
1849
|
+
this._threadsErrorByAgent = /* @__PURE__ */ new Map();
|
|
1850
|
+
this._ownedThreadStores = /* @__PURE__ */ new Map();
|
|
85
1851
|
this.contextMenuOpen = false;
|
|
86
1852
|
this.dockMode = "floating";
|
|
87
1853
|
this.previousBodyMargins = null;
|
|
@@ -94,15 +1860,20 @@ var WebInspectorElement = class extends LitElement {
|
|
|
94
1860
|
this.toolSignature = "";
|
|
95
1861
|
this.eventFilterText = "";
|
|
96
1862
|
this.eventTypeFilter = "all";
|
|
97
|
-
this.
|
|
1863
|
+
this.evtColWidths = [
|
|
1864
|
+
100,
|
|
1865
|
+
80,
|
|
1866
|
+
150
|
|
1867
|
+
];
|
|
1868
|
+
this._evtColResize = null;
|
|
98
1869
|
this.announcementHtml = null;
|
|
99
1870
|
this.announcementTimestamp = null;
|
|
100
1871
|
this.announcementPreviewText = null;
|
|
101
1872
|
this.hasUnseenAnnouncement = false;
|
|
102
1873
|
this.announcementLoaded = false;
|
|
103
|
-
this.announcementLoadError = null;
|
|
104
1874
|
this.announcementPromise = null;
|
|
105
1875
|
this.showAnnouncementPreview = true;
|
|
1876
|
+
this.announcementExpanded = false;
|
|
106
1877
|
this.contextState = {
|
|
107
1878
|
button: {
|
|
108
1879
|
position: {
|
|
@@ -143,28 +1914,7 @@ var WebInspectorElement = class extends LitElement {
|
|
|
143
1914
|
this.resizeStart = null;
|
|
144
1915
|
this.resizeInitialSize = null;
|
|
145
1916
|
this.isResizing = false;
|
|
146
|
-
this.
|
|
147
|
-
{
|
|
148
|
-
key: "ag-ui-events",
|
|
149
|
-
label: "AG-UI Events",
|
|
150
|
-
icon: "Zap"
|
|
151
|
-
},
|
|
152
|
-
{
|
|
153
|
-
key: "agents",
|
|
154
|
-
label: "Agent",
|
|
155
|
-
icon: "Bot"
|
|
156
|
-
},
|
|
157
|
-
{
|
|
158
|
-
key: "frontend-tools",
|
|
159
|
-
label: "Frontend Tools",
|
|
160
|
-
icon: "Hammer"
|
|
161
|
-
},
|
|
162
|
-
{
|
|
163
|
-
key: "agent-context",
|
|
164
|
-
label: "Context",
|
|
165
|
-
icon: "FileText"
|
|
166
|
-
}
|
|
167
|
-
];
|
|
1917
|
+
this.customTabIcons = { threads: `<svg class="h-3.5 w-3.5" width="15" height="15" viewBox="0 0 15 15" fill="none" xmlns="http://www.w3.org/2000/svg"><path d="M9.04167 15C8.29167 15 7.65972 14.7431 7.14583 14.2292C6.63194 13.7153 6.375 13.0972 6.375 12.375C6.375 11.3194 6.80208 10.3646 7.65625 9.51042C8.51042 8.65625 9.57639 8.125 10.8542 7.91667C10.8125 7.41667 10.6875 7.03819 10.4792 6.78125C10.2708 6.52431 9.98611 6.39583 9.625 6.39583C9.20833 6.39583 8.75694 6.56944 8.27083 6.91667C7.78472 7.26389 7.20833 7.83333 6.54167 8.625C5.45833 9.91667 4.66319 10.7569 4.15625 11.1458C3.64931 11.5347 3.10417 11.7292 2.52083 11.7292C1.8125 11.7292 1.21528 11.4653 0.729167 10.9375C0.243056 10.4097 0 9.77083 0 9.02083C0 8.27083 0.163194 7.50347 0.489583 6.71875C0.815972 5.93403 1.36806 4.99306 2.14583 3.89583C2.40972 3.53472 2.60417 3.22917 2.72917 2.97917C2.85417 2.72917 2.91667 2.52778 2.91667 2.375C2.91667 2.27778 2.89931 2.20486 2.86458 2.15625C2.82986 2.10764 2.77778 2.08333 2.70833 2.08333C2.56944 2.08333 2.39583 2.17014 2.1875 2.34375C1.97917 2.51736 1.73611 2.78472 1.45833 3.14583L0 1.66667C0.444444 1.125 0.895833 0.711806 1.35417 0.427083C1.8125 0.142361 2.26389 0 2.70833 0C3.34722 0 3.88889 0.222222 4.33333 0.666667C4.77778 1.11111 5 1.66667 5 2.33333C5 2.73611 4.89583 3.18056 4.6875 3.66667C4.47917 4.15278 4.13194 4.73611 3.64583 5.41667C3.11806 6.16667 2.72569 6.82639 2.46875 7.39583C2.21181 7.96528 2.08333 8.46528 2.08333 8.89583C2.08333 9.13194 2.12153 9.31597 2.19792 9.44792C2.27431 9.57986 2.38194 9.64583 2.52083 9.64583C2.65972 9.64583 2.78125 9.60764 2.88542 9.53125C2.98958 9.45486 3.18056 9.27083 3.45833 8.97917C3.63889 8.78472 3.85417 8.54514 4.10417 8.26042C4.35417 7.97569 4.65972 7.625 5.02083 7.20833C5.89583 6.16667 6.6875 5.42361 7.39583 4.97917C8.10417 4.53472 8.84722 4.3125 9.625 4.3125C10.5556 4.3125 11.3194 4.625 11.9167 5.25C12.5139 5.875 12.8542 6.72917 12.9375 7.8125H15V9.89583H12.9375C12.8264 11.4514 12.4201 12.691 11.7188 13.6146C11.0174 14.5382 10.125 15 9.04167 15ZM9.08333 12.9167C9.52778 12.9167 9.90278 12.6632 10.2083 12.1562C10.5139 11.6493 10.7222 10.9444 10.8333 10.0417C10.1944 10.1944 9.63889 10.4965 9.16667 10.9479C8.69444 11.3993 8.45833 11.8472 8.45833 12.2917C8.45833 12.4861 8.51389 12.6389 8.625 12.75C8.73611 12.8611 8.88889 12.9167 9.08333 12.9167Z" fill="currentColor"/></svg>` };
|
|
168
1918
|
this.handlePointerDown = (event) => {
|
|
169
1919
|
if (this.dockMode !== "floating" && this.isOpen) return;
|
|
170
1920
|
const target = event.currentTarget;
|
|
@@ -329,6 +2079,26 @@ var WebInspectorElement = class extends LitElement {
|
|
|
329
2079
|
this.expandedTools = /* @__PURE__ */ new Set();
|
|
330
2080
|
this.expandedContextItems = /* @__PURE__ */ new Set();
|
|
331
2081
|
this.copiedContextItems = /* @__PURE__ */ new Set();
|
|
2082
|
+
this.handleThreadDividerPointerDown = (event) => {
|
|
2083
|
+
this.threadDividerResizing = true;
|
|
2084
|
+
this.threadDividerPointerId = event.pointerId;
|
|
2085
|
+
this.threadDividerStartX = event.clientX;
|
|
2086
|
+
this.threadDividerStartWidth = this.threadListWidth;
|
|
2087
|
+
event.currentTarget.setPointerCapture(event.pointerId);
|
|
2088
|
+
event.preventDefault();
|
|
2089
|
+
};
|
|
2090
|
+
this.handleThreadDividerPointerMove = (event) => {
|
|
2091
|
+
if (!this.threadDividerResizing || this.threadDividerPointerId !== event.pointerId) return;
|
|
2092
|
+
const delta = event.clientX - this.threadDividerStartX;
|
|
2093
|
+
this.threadListWidth = Math.max(180, Math.min(480, this.threadDividerStartWidth + delta));
|
|
2094
|
+
this.requestUpdate();
|
|
2095
|
+
};
|
|
2096
|
+
this.handleThreadDividerPointerUp = (event) => {
|
|
2097
|
+
if (this.threadDividerPointerId !== event.pointerId) return;
|
|
2098
|
+
const target = event.currentTarget;
|
|
2099
|
+
if (target.hasPointerCapture(this.threadDividerPointerId)) target.releasePointerCapture(this.threadDividerPointerId);
|
|
2100
|
+
this.threadDividerResizing = false;
|
|
2101
|
+
};
|
|
332
2102
|
this.handleClearEvents = () => {
|
|
333
2103
|
if (this.selectedContext === "all-agents") {
|
|
334
2104
|
this.agentEvents.clear();
|
|
@@ -353,6 +2123,31 @@ var WebInspectorElement = class extends LitElement {
|
|
|
353
2123
|
this.handleDismissAnnouncement = () => {
|
|
354
2124
|
this.markAnnouncementSeen();
|
|
355
2125
|
};
|
|
2126
|
+
this.copyResetTimeouts = /* @__PURE__ */ new WeakMap();
|
|
2127
|
+
this.handleAnnouncementContentClick = (event) => {
|
|
2128
|
+
const button = (event.target instanceof HTMLElement ? event.target : null)?.closest(".announcement-code__copy");
|
|
2129
|
+
if (!(button instanceof HTMLButtonElement)) return;
|
|
2130
|
+
event.preventDefault();
|
|
2131
|
+
event.stopPropagation();
|
|
2132
|
+
const encoded = button.getAttribute("data-copy") ?? "";
|
|
2133
|
+
const code = this.decodeBase64(encoded);
|
|
2134
|
+
if (!code) return;
|
|
2135
|
+
const showCopied = () => {
|
|
2136
|
+
const existing = this.copyResetTimeouts.get(button);
|
|
2137
|
+
if (existing !== void 0) window.clearTimeout(existing);
|
|
2138
|
+
button.setAttribute("data-copied", "true");
|
|
2139
|
+
button.setAttribute("aria-label", "Code copied");
|
|
2140
|
+
button.textContent = "Copied";
|
|
2141
|
+
const id = window.setTimeout(() => {
|
|
2142
|
+
button.removeAttribute("data-copied");
|
|
2143
|
+
button.setAttribute("aria-label", "Copy code");
|
|
2144
|
+
button.textContent = "Copy";
|
|
2145
|
+
this.copyResetTimeouts.delete(button);
|
|
2146
|
+
}, 1500);
|
|
2147
|
+
this.copyResetTimeouts.set(button, id);
|
|
2148
|
+
};
|
|
2149
|
+
if (typeof navigator !== "undefined" && navigator.clipboard?.writeText) navigator.clipboard.writeText(code).then(showCopied, () => {});
|
|
2150
|
+
};
|
|
356
2151
|
}
|
|
357
2152
|
static {
|
|
358
2153
|
this.properties = {
|
|
@@ -374,6 +2169,106 @@ var WebInspectorElement = class extends LitElement {
|
|
|
374
2169
|
this.requestUpdate("core", oldValue);
|
|
375
2170
|
if (this._core) this.attachToCore(this._core);
|
|
376
2171
|
}
|
|
2172
|
+
get menuItems() {
|
|
2173
|
+
return [
|
|
2174
|
+
{
|
|
2175
|
+
key: "ag-ui-events",
|
|
2176
|
+
label: "AG-UI Events",
|
|
2177
|
+
icon: "Zap"
|
|
2178
|
+
},
|
|
2179
|
+
{
|
|
2180
|
+
key: "agents",
|
|
2181
|
+
label: "Agent",
|
|
2182
|
+
icon: "Bot"
|
|
2183
|
+
},
|
|
2184
|
+
...(this._core?.tools?.length ?? 0) > 0 ? [{
|
|
2185
|
+
key: "frontend-tools",
|
|
2186
|
+
label: "Frontend Tools",
|
|
2187
|
+
icon: "Hammer"
|
|
2188
|
+
}] : [],
|
|
2189
|
+
{
|
|
2190
|
+
key: "agent-context",
|
|
2191
|
+
label: "Context",
|
|
2192
|
+
icon: "FileText"
|
|
2193
|
+
},
|
|
2194
|
+
{
|
|
2195
|
+
key: "threads",
|
|
2196
|
+
label: "Threads",
|
|
2197
|
+
icon: "MessageSquare"
|
|
2198
|
+
}
|
|
2199
|
+
];
|
|
2200
|
+
}
|
|
2201
|
+
subscribeToThreadStore(agentId, store) {
|
|
2202
|
+
if (this._threadStoreSubscriptions.has(agentId)) return;
|
|
2203
|
+
const threadsSub = store.select(ɵselectThreads).subscribe((threads) => {
|
|
2204
|
+
this._threadsByAgent.set(agentId, threads);
|
|
2205
|
+
this._threads = Array.from(this._threadsByAgent.values()).flat();
|
|
2206
|
+
this.autoSelectLatestThread();
|
|
2207
|
+
this.requestUpdate();
|
|
2208
|
+
});
|
|
2209
|
+
const errorSub = store.select(ɵselectThreadsError).subscribe((error) => {
|
|
2210
|
+
if (error) this._threadsErrorByAgent.set(agentId, error);
|
|
2211
|
+
else this._threadsErrorByAgent.delete(agentId);
|
|
2212
|
+
this.requestUpdate();
|
|
2213
|
+
});
|
|
2214
|
+
this._threadStoreSubscriptions.set(agentId, () => {
|
|
2215
|
+
threadsSub.unsubscribe();
|
|
2216
|
+
errorSub.unsubscribe();
|
|
2217
|
+
});
|
|
2218
|
+
const initialState = store.getState();
|
|
2219
|
+
this._threadsByAgent.set(agentId, ɵselectThreads(initialState));
|
|
2220
|
+
const initialError = ɵselectThreadsError(initialState);
|
|
2221
|
+
if (initialError) this._threadsErrorByAgent.set(agentId, initialError);
|
|
2222
|
+
else this._threadsErrorByAgent.delete(agentId);
|
|
2223
|
+
this._threads = Array.from(this._threadsByAgent.values()).flat();
|
|
2224
|
+
this.autoSelectLatestThread();
|
|
2225
|
+
}
|
|
2226
|
+
autoSelectLatestThread() {
|
|
2227
|
+
if (this._threads.length === 0) return;
|
|
2228
|
+
if (!(this.selectedThreadId != null && this._threads.some((t) => t.id === this.selectedThreadId))) this.selectedThreadId = this._threads[0].id;
|
|
2229
|
+
}
|
|
2230
|
+
teardownThreadStoreSubscriptions() {
|
|
2231
|
+
for (const unsub of this._threadStoreSubscriptions.values()) unsub();
|
|
2232
|
+
this._threadStoreSubscriptions.clear();
|
|
2233
|
+
this._threadsByAgent.clear();
|
|
2234
|
+
this._threadsErrorByAgent.clear();
|
|
2235
|
+
this._threads = [];
|
|
2236
|
+
}
|
|
2237
|
+
ensureOwnedThreadStore(agentId) {
|
|
2238
|
+
if (this._ownedThreadStores.has(agentId)) return;
|
|
2239
|
+
if (this.core?.getThreadStore(agentId)) return;
|
|
2240
|
+
const core = this.core;
|
|
2241
|
+
if (!core?.runtimeUrl) return;
|
|
2242
|
+
const store = ɵcreateThreadStore({ fetch: globalThis.fetch });
|
|
2243
|
+
store.start();
|
|
2244
|
+
store.setContext({
|
|
2245
|
+
runtimeUrl: core.runtimeUrl,
|
|
2246
|
+
headers: {},
|
|
2247
|
+
agentId
|
|
2248
|
+
});
|
|
2249
|
+
this._ownedThreadStores.set(agentId, store);
|
|
2250
|
+
this.subscribeToThreadStore(agentId, store);
|
|
2251
|
+
core.registerThreadStore(agentId, store);
|
|
2252
|
+
}
|
|
2253
|
+
refreshOwnedThreadStore(agentId) {
|
|
2254
|
+
const store = this._ownedThreadStores.get(agentId);
|
|
2255
|
+
if (!store) return;
|
|
2256
|
+
store.refresh();
|
|
2257
|
+
}
|
|
2258
|
+
removeOwnedThreadStore(agentId) {
|
|
2259
|
+
const store = this._ownedThreadStores.get(agentId);
|
|
2260
|
+
if (!store) return;
|
|
2261
|
+
store.stop();
|
|
2262
|
+
this.core?.unregisterThreadStore(agentId);
|
|
2263
|
+
this._ownedThreadStores.delete(agentId);
|
|
2264
|
+
}
|
|
2265
|
+
teardownOwnedThreadStores() {
|
|
2266
|
+
for (const [agentId, store] of this._ownedThreadStores) {
|
|
2267
|
+
store.stop();
|
|
2268
|
+
this.core?.unregisterThreadStore(agentId);
|
|
2269
|
+
}
|
|
2270
|
+
this._ownedThreadStores.clear();
|
|
2271
|
+
}
|
|
377
2272
|
attachToCore(core) {
|
|
378
2273
|
this.runtimeStatus = core.runtimeConnectionStatus;
|
|
379
2274
|
this.coreProperties = core.properties;
|
|
@@ -381,6 +2276,11 @@ var WebInspectorElement = class extends LitElement {
|
|
|
381
2276
|
this.coreSubscriber = {
|
|
382
2277
|
onRuntimeConnectionStatusChanged: ({ status }) => {
|
|
383
2278
|
this.runtimeStatus = status;
|
|
2279
|
+
if (status === "connected") for (const agentId of this._ownedThreadStores.keys()) this.refreshOwnedThreadStore(agentId);
|
|
2280
|
+
else {
|
|
2281
|
+
this._threadsByAgent.clear();
|
|
2282
|
+
this._threads = [];
|
|
2283
|
+
}
|
|
384
2284
|
this.requestUpdate();
|
|
385
2285
|
},
|
|
386
2286
|
onPropertiesChanged: ({ properties }) => {
|
|
@@ -397,16 +2297,30 @@ var WebInspectorElement = class extends LitElement {
|
|
|
397
2297
|
onAgentsChanged: ({ agents }) => {
|
|
398
2298
|
this.processAgentsChanged(agents);
|
|
399
2299
|
},
|
|
400
|
-
|
|
401
|
-
|
|
2300
|
+
onContextChanged: ({ context }) => {
|
|
2301
|
+
this.contextStore = this.normalizeContextStore(context);
|
|
2302
|
+
this.requestUpdate();
|
|
2303
|
+
},
|
|
2304
|
+
onThreadStoreRegistered: ({ agentId, store }) => {
|
|
2305
|
+
this.subscribeToThreadStore(agentId, store);
|
|
2306
|
+
this.requestUpdate();
|
|
402
2307
|
},
|
|
403
|
-
|
|
404
|
-
|
|
2308
|
+
onThreadStoreUnregistered: ({ agentId }) => {
|
|
2309
|
+
const unsub = this._threadStoreSubscriptions.get(agentId);
|
|
2310
|
+
if (unsub) {
|
|
2311
|
+
unsub();
|
|
2312
|
+
this._threadStoreSubscriptions.delete(agentId);
|
|
2313
|
+
}
|
|
2314
|
+
this._threadsByAgent.delete(agentId);
|
|
2315
|
+
this._threadsErrorByAgent.delete(agentId);
|
|
2316
|
+
this._threads = Array.from(this._threadsByAgent.values()).flat();
|
|
405
2317
|
this.requestUpdate();
|
|
406
2318
|
}
|
|
407
2319
|
};
|
|
408
2320
|
this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;
|
|
409
2321
|
this.processAgentsChanged(core.agents);
|
|
2322
|
+
const threadStores = typeof core.getThreadStores === "function" ? core.getThreadStores() : {};
|
|
2323
|
+
for (const [agentId, store] of Object.entries(threadStores)) this.subscribeToThreadStore(agentId, store);
|
|
410
2324
|
if (core.context) this.contextStore = this.normalizeContextStore(core.context);
|
|
411
2325
|
}
|
|
412
2326
|
detachFromCore() {
|
|
@@ -421,6 +2335,8 @@ var WebInspectorElement = class extends LitElement {
|
|
|
421
2335
|
this.cachedTools = [];
|
|
422
2336
|
this.toolSignature = "";
|
|
423
2337
|
this.teardownAgentSubscriptions();
|
|
2338
|
+
this.teardownThreadStoreSubscriptions();
|
|
2339
|
+
this.teardownOwnedThreadStores();
|
|
424
2340
|
}
|
|
425
2341
|
teardownAgentSubscriptions() {
|
|
426
2342
|
for (const unsubscribe of this.agentSubscriptions.values()) unsubscribe();
|
|
@@ -437,6 +2353,7 @@ var WebInspectorElement = class extends LitElement {
|
|
|
437
2353
|
if (!agent?.agentId) continue;
|
|
438
2354
|
seenAgentIds.add(agent.agentId);
|
|
439
2355
|
this.subscribeToAgent(agent);
|
|
2356
|
+
this.ensureOwnedThreadStore(agent.agentId);
|
|
440
2357
|
}
|
|
441
2358
|
for (const agentId of Array.from(this.agentSubscriptions.keys())) if (!seenAgentIds.has(agentId)) {
|
|
442
2359
|
this.unsubscribeFromAgent(agentId);
|
|
@@ -495,6 +2412,7 @@ var WebInspectorElement = class extends LitElement {
|
|
|
495
2412
|
event,
|
|
496
2413
|
result
|
|
497
2414
|
});
|
|
2415
|
+
this.refreshOwnedThreadStore(agentId);
|
|
498
2416
|
},
|
|
499
2417
|
onRunErrorEvent: ({ event }) => {
|
|
500
2418
|
this.recordAgentEvent(agentId, "RUN_ERROR", event);
|
|
@@ -582,6 +2500,14 @@ var WebInspectorElement = class extends LitElement {
|
|
|
582
2500
|
},
|
|
583
2501
|
onReasoningEncryptedValueEvent: ({ event }) => {
|
|
584
2502
|
this.recordAgentEvent(agentId, "REASONING_ENCRYPTED_VALUE", event);
|
|
2503
|
+
},
|
|
2504
|
+
onActivitySnapshotEvent: ({ event }) => {
|
|
2505
|
+
this.recordAgentEvent(agentId, "ACTIVITY_SNAPSHOT", event);
|
|
2506
|
+
this.syncAgentMessages(agent);
|
|
2507
|
+
},
|
|
2508
|
+
onActivityDeltaEvent: ({ event }) => {
|
|
2509
|
+
this.recordAgentEvent(agentId, "ACTIVITY_DELTA", event);
|
|
2510
|
+
this.syncAgentMessages(agent);
|
|
585
2511
|
}
|
|
586
2512
|
});
|
|
587
2513
|
this.agentSubscriptions.set(agentId, unsubscribe);
|
|
@@ -596,6 +2522,15 @@ var WebInspectorElement = class extends LitElement {
|
|
|
596
2522
|
this.agentSubscriptions.delete(agentId);
|
|
597
2523
|
}
|
|
598
2524
|
}
|
|
2525
|
+
mapMessagesToConversation(messages) {
|
|
2526
|
+
if (!messages) return null;
|
|
2527
|
+
return messages.filter((m) => m.role === "user" || m.role === "assistant" || m.role === "activity").map((m, i) => ({
|
|
2528
|
+
id: m.id ?? `msg-${i}`,
|
|
2529
|
+
type: m.role === "user" ? "user" : m.role === "activity" ? "generative-ui" : "assistant",
|
|
2530
|
+
content: m.role === "activity" ? m.activityType ?? "unknown" : m.contentText,
|
|
2531
|
+
createdAt: ""
|
|
2532
|
+
}));
|
|
2533
|
+
}
|
|
599
2534
|
recordAgentEvent(agentId, type, payload) {
|
|
600
2535
|
const eventId = `${agentId}:${++this.eventCounter}`;
|
|
601
2536
|
const normalizedPayload = this.normalizeEventPayload(type, payload);
|
|
@@ -618,6 +2553,8 @@ var WebInspectorElement = class extends LitElement {
|
|
|
618
2553
|
const messages = this.normalizeAgentMessages(agent.messages);
|
|
619
2554
|
if (messages) this.agentMessages.set(agent.agentId, messages);
|
|
620
2555
|
else this.agentMessages.delete(agent.agentId);
|
|
2556
|
+
const runThreadId = agent.threadId;
|
|
2557
|
+
if (runThreadId) this.liveMessageVersion.set(runThreadId, (this.liveMessageVersion.get(runThreadId) ?? 0) + 1);
|
|
621
2558
|
this.requestUpdate();
|
|
622
2559
|
} catch (error) {
|
|
623
2560
|
console.error(`[CopilotKit Inspector] Failed to sync messages for agent "${agent.agentId}":`, error);
|
|
@@ -645,18 +2582,23 @@ var WebInspectorElement = class extends LitElement {
|
|
|
645
2582
|
if (this.contextOptions.length !== nextOptions.length || this.contextOptions.some((option, index) => option.key !== nextOptions[index]?.key)) this.contextOptions = nextOptions;
|
|
646
2583
|
const pendingContext = this.pendingSelectedContext;
|
|
647
2584
|
if (pendingContext) {
|
|
648
|
-
if (pendingContext === "all-agents" || agentIds.has(pendingContext)) {
|
|
2585
|
+
if ((pendingContext === "all-agents" || agentIds.has(pendingContext)) && (pendingContext === "all-agents" || agentIds.size === 1)) {
|
|
649
2586
|
if (this.selectedContext !== pendingContext) {
|
|
650
2587
|
this.selectedContext = pendingContext;
|
|
651
2588
|
this.expandedRows.clear();
|
|
652
2589
|
}
|
|
653
2590
|
this.pendingSelectedContext = null;
|
|
654
|
-
} else if (agentIds.size > 0)
|
|
2591
|
+
} else if (agentIds.size > 0) {
|
|
2592
|
+
if (this.selectedContext !== "all-agents") {
|
|
2593
|
+
this.selectedContext = "all-agents";
|
|
2594
|
+
this.expandedRows.clear();
|
|
2595
|
+
}
|
|
2596
|
+
this.pendingSelectedContext = null;
|
|
2597
|
+
}
|
|
655
2598
|
}
|
|
656
2599
|
if (!nextOptions.some((option) => option.key === this.selectedContext) && this.pendingSelectedContext === null) {
|
|
657
2600
|
let nextSelected = "all-agents";
|
|
658
|
-
if (agentIds.
|
|
659
|
-
else if (agentIds.size > 0) nextSelected = Array.from(agentIds).sort((a, b) => a.localeCompare(b))[0];
|
|
2601
|
+
if (agentIds.size === 1) nextSelected = Array.from(agentIds)[0];
|
|
660
2602
|
if (this.selectedContext !== nextSelected) {
|
|
661
2603
|
this.selectedContext = nextSelected;
|
|
662
2604
|
this.expandedRows.clear();
|
|
@@ -831,6 +2773,7 @@ ${argsString}</pre
|
|
|
831
2773
|
z-index: 2147483646;
|
|
832
2774
|
display: block;
|
|
833
2775
|
will-change: transform;
|
|
2776
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
834
2777
|
}
|
|
835
2778
|
|
|
836
2779
|
:host([data-transitioning="true"]) {
|
|
@@ -886,13 +2829,14 @@ ${argsString}</pre
|
|
|
886
2829
|
left: 50%;
|
|
887
2830
|
transform: translateX(-50%) translateY(-4px);
|
|
888
2831
|
white-space: nowrap;
|
|
889
|
-
background: rgba(
|
|
2832
|
+
background: rgba(1, 5, 7, 0.95);
|
|
890
2833
|
color: white;
|
|
891
2834
|
padding: 4px 8px;
|
|
892
2835
|
border-radius: 6px;
|
|
893
2836
|
font-size: 10px;
|
|
2837
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
894
2838
|
line-height: 1.2;
|
|
895
|
-
box-shadow: 0 4px 10px rgba(
|
|
2839
|
+
box-shadow: 0 4px 10px rgba(1, 5, 7, 0.18);
|
|
896
2840
|
opacity: 0;
|
|
897
2841
|
pointer-events: none;
|
|
898
2842
|
transition:
|
|
@@ -913,18 +2857,19 @@ ${argsString}</pre
|
|
|
913
2857
|
min-width: 300px;
|
|
914
2858
|
max-width: 300px;
|
|
915
2859
|
background: white;
|
|
916
|
-
color: #
|
|
2860
|
+
color: #010507;
|
|
917
2861
|
font-size: 13px;
|
|
2862
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
918
2863
|
line-height: 1.4;
|
|
919
2864
|
border-radius: 12px;
|
|
920
|
-
box-shadow: 0 12px 28px rgba(
|
|
2865
|
+
box-shadow: 0 12px 28px rgba(1, 5, 7, 0.12);
|
|
921
2866
|
padding: 10px 12px;
|
|
922
2867
|
display: inline-flex;
|
|
923
2868
|
align-items: flex-start;
|
|
924
2869
|
gap: 8px;
|
|
925
2870
|
z-index: 4500;
|
|
926
2871
|
animation: fade-slide-in 160ms ease;
|
|
927
|
-
border: 1px solid rgba(
|
|
2872
|
+
border: 1px solid rgba(219, 219, 229, 0.4);
|
|
928
2873
|
white-space: normal;
|
|
929
2874
|
word-break: break-word;
|
|
930
2875
|
text-align: left;
|
|
@@ -945,7 +2890,7 @@ ${argsString}</pre
|
|
|
945
2890
|
width: 10px;
|
|
946
2891
|
height: 10px;
|
|
947
2892
|
background: white;
|
|
948
|
-
border: 1px solid rgba(
|
|
2893
|
+
border: 1px solid rgba(219, 219, 229, 0.4);
|
|
949
2894
|
transform: rotate(45deg);
|
|
950
2895
|
top: 50%;
|
|
951
2896
|
margin-top: -5px;
|
|
@@ -954,81 +2899,564 @@ ${argsString}</pre
|
|
|
954
2899
|
|
|
955
2900
|
.announcement-preview[data-side="left"] .announcement-preview__arrow {
|
|
956
2901
|
right: -5px;
|
|
957
|
-
box-shadow: 6px -6px 10px rgba(
|
|
2902
|
+
box-shadow: 6px -6px 10px rgba(1, 5, 7, 0.08);
|
|
958
2903
|
}
|
|
959
2904
|
|
|
960
2905
|
.announcement-preview[data-side="right"] .announcement-preview__arrow {
|
|
961
2906
|
left: -5px;
|
|
962
|
-
box-shadow: -6px 6px 10px rgba(
|
|
2907
|
+
box-shadow: -6px 6px 10px rgba(1, 5, 7, 0.08);
|
|
963
2908
|
}
|
|
964
2909
|
|
|
965
2910
|
.announcement-dismiss {
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
|
|
969
|
-
|
|
970
|
-
|
|
971
|
-
|
|
2911
|
+
background: none;
|
|
2912
|
+
border: none;
|
|
2913
|
+
cursor: pointer;
|
|
2914
|
+
color: #838389;
|
|
2915
|
+
width: 28px;
|
|
2916
|
+
height: 28px;
|
|
2917
|
+
display: flex;
|
|
2918
|
+
align-items: center;
|
|
2919
|
+
justify-content: center;
|
|
2920
|
+
border-radius: 6px;
|
|
2921
|
+
padding: 0;
|
|
972
2922
|
transition:
|
|
973
2923
|
background 120ms ease,
|
|
974
2924
|
color 120ms ease;
|
|
975
2925
|
}
|
|
976
2926
|
|
|
977
2927
|
.announcement-dismiss:hover {
|
|
978
|
-
background: rgba(
|
|
979
|
-
color: #
|
|
2928
|
+
background: rgba(0, 0, 0, 0.06);
|
|
2929
|
+
color: #010507;
|
|
2930
|
+
}
|
|
2931
|
+
|
|
2932
|
+
/* ── Agent tab section cards ─────────────────────────────────────── */
|
|
2933
|
+
.cpk-section-card {
|
|
2934
|
+
border-radius: 8px;
|
|
2935
|
+
background: #ffffff;
|
|
2936
|
+
overflow: hidden;
|
|
2937
|
+
}
|
|
2938
|
+
|
|
2939
|
+
/* ── Agent icon bubble ───────────────────────────────────────────── */
|
|
2940
|
+
.cpk-agent-icon {
|
|
2941
|
+
background-color: #f0f0f4 !important;
|
|
2942
|
+
color: #57575b !important;
|
|
2943
|
+
}
|
|
2944
|
+
|
|
2945
|
+
/* ── Agent stat cards ────────────────────────────────────────────── */
|
|
2946
|
+
.cpk-stat-card {
|
|
2947
|
+
background-color: #ffffff !important;
|
|
2948
|
+
border: 1px solid #dbdbe5 !important;
|
|
2949
|
+
}
|
|
2950
|
+
button.cpk-stat-card:hover {
|
|
2951
|
+
background-color: #f7f7f9 !important;
|
|
2952
|
+
}
|
|
2953
|
+
|
|
2954
|
+
/* ── Circle chevron (Frontend Tools + Context) ──────────────────── */
|
|
2955
|
+
.cpk-chevron-circle {
|
|
2956
|
+
display: inline-flex;
|
|
2957
|
+
align-items: center;
|
|
2958
|
+
justify-content: center;
|
|
2959
|
+
width: 24px;
|
|
2960
|
+
height: 24px;
|
|
2961
|
+
border-radius: 50%;
|
|
2962
|
+
background-color: #f0f0f4;
|
|
2963
|
+
color: #838389;
|
|
2964
|
+
flex-shrink: 0;
|
|
2965
|
+
transition: transform 0.2s;
|
|
2966
|
+
}
|
|
2967
|
+
.cpk-chevron-circle svg {
|
|
2968
|
+
width: 14px !important;
|
|
2969
|
+
height: 14px !important;
|
|
2970
|
+
}
|
|
2971
|
+
.cpk-chevron-circle--open {
|
|
2972
|
+
transform: rotate(180deg);
|
|
2973
|
+
}
|
|
2974
|
+
|
|
2975
|
+
/* ── Inline copy button ─────────────────────────────────────────── */
|
|
2976
|
+
.cpk-copy-btn {
|
|
2977
|
+
font-size: 10px;
|
|
2978
|
+
font-weight: 500;
|
|
2979
|
+
color: #57575b;
|
|
2980
|
+
background: #ffffff;
|
|
2981
|
+
border: 1px solid #dbdbe5;
|
|
2982
|
+
cursor: pointer;
|
|
2983
|
+
padding: 2px 8px;
|
|
2984
|
+
border-radius: 4px;
|
|
2985
|
+
flex-shrink: 0;
|
|
2986
|
+
transition:
|
|
2987
|
+
background-color 0.15s,
|
|
2988
|
+
border-color 0.15s;
|
|
2989
|
+
}
|
|
2990
|
+
.cpk-copy-btn:hover {
|
|
2991
|
+
background-color: #f0f0f4;
|
|
2992
|
+
border-color: #afafb7;
|
|
2993
|
+
}
|
|
2994
|
+
|
|
2995
|
+
.cpk-section-header {
|
|
2996
|
+
background: #e8edf5;
|
|
2997
|
+
border-bottom: 1px solid rgba(0, 0, 0, 0.08);
|
|
2998
|
+
padding: 10px 16px;
|
|
2999
|
+
}
|
|
3000
|
+
.cpk-section-header h4 {
|
|
3001
|
+
font-size: 11px;
|
|
3002
|
+
font-weight: 600;
|
|
3003
|
+
color: #181c1f;
|
|
3004
|
+
margin: 0;
|
|
3005
|
+
}
|
|
3006
|
+
|
|
3007
|
+
/* Inputs/selects inside the lavender header need an explicit white bg */
|
|
3008
|
+
.cpk-section-header input,
|
|
3009
|
+
.cpk-section-header select {
|
|
3010
|
+
background-color: #ffffff !important;
|
|
3011
|
+
box-shadow: none !important;
|
|
3012
|
+
}
|
|
3013
|
+
.cpk-section-header select {
|
|
3014
|
+
padding-right: 24px !important;
|
|
3015
|
+
}
|
|
3016
|
+
/* Events table column headers */
|
|
3017
|
+
table thead th {
|
|
3018
|
+
font-weight: 600 !important;
|
|
980
3019
|
}
|
|
981
3020
|
|
|
982
3021
|
.announcement-content {
|
|
983
|
-
color: #
|
|
984
|
-
font-size:
|
|
985
|
-
|
|
3022
|
+
color: #1f2230;
|
|
3023
|
+
font-size: 13px;
|
|
3024
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
3025
|
+
line-height: 1.55;
|
|
986
3026
|
}
|
|
987
3027
|
|
|
988
3028
|
.announcement-content h1,
|
|
989
3029
|
.announcement-content h2,
|
|
990
3030
|
.announcement-content h3 {
|
|
3031
|
+
color: #010507;
|
|
991
3032
|
font-weight: 700;
|
|
992
|
-
|
|
3033
|
+
line-height: 1.3;
|
|
3034
|
+
margin: 0.9rem 0 0.4rem;
|
|
3035
|
+
}
|
|
3036
|
+
.announcement-content > h1:first-child,
|
|
3037
|
+
.announcement-content > h2:first-child,
|
|
3038
|
+
.announcement-content > h3:first-child {
|
|
3039
|
+
margin-top: 0;
|
|
993
3040
|
}
|
|
994
3041
|
|
|
995
3042
|
.announcement-content h1 {
|
|
996
|
-
font-size: 1.
|
|
3043
|
+
font-size: 1.15rem;
|
|
3044
|
+
letter-spacing: -0.01em;
|
|
997
3045
|
}
|
|
998
|
-
|
|
999
3046
|
.announcement-content h2 {
|
|
1000
3047
|
font-size: 1rem;
|
|
1001
3048
|
}
|
|
1002
|
-
|
|
1003
3049
|
.announcement-content h3 {
|
|
1004
|
-
font-size: 0.
|
|
3050
|
+
font-size: 0.9rem;
|
|
3051
|
+
text-transform: none;
|
|
1005
3052
|
}
|
|
1006
3053
|
|
|
1007
3054
|
.announcement-content p {
|
|
1008
|
-
margin: 0.
|
|
3055
|
+
margin: 0.45rem 0;
|
|
3056
|
+
}
|
|
3057
|
+
|
|
3058
|
+
.announcement-content strong {
|
|
3059
|
+
color: #010507;
|
|
3060
|
+
font-weight: 700;
|
|
1009
3061
|
}
|
|
1010
3062
|
|
|
1011
3063
|
.announcement-content ul {
|
|
1012
3064
|
list-style: disc;
|
|
1013
3065
|
padding-left: 1.25rem;
|
|
1014
|
-
margin: 0.
|
|
3066
|
+
margin: 0.45rem 0;
|
|
1015
3067
|
}
|
|
1016
3068
|
|
|
1017
3069
|
.announcement-content ol {
|
|
1018
3070
|
list-style: decimal;
|
|
1019
3071
|
padding-left: 1.25rem;
|
|
1020
|
-
margin: 0.
|
|
3072
|
+
margin: 0.45rem 0;
|
|
3073
|
+
}
|
|
3074
|
+
|
|
3075
|
+
.announcement-content li + li {
|
|
3076
|
+
margin-top: 0.15rem;
|
|
1021
3077
|
}
|
|
1022
3078
|
|
|
1023
3079
|
.announcement-content a {
|
|
1024
|
-
color: #
|
|
3080
|
+
color: #757cf2;
|
|
1025
3081
|
text-decoration: underline;
|
|
1026
3082
|
}
|
|
3083
|
+
|
|
3084
|
+
.announcement-content :not(pre) > code {
|
|
3085
|
+
background: #f3f3f7;
|
|
3086
|
+
border: 1px solid #e4e4ec;
|
|
3087
|
+
border-radius: 4px;
|
|
3088
|
+
padding: 1px 5px;
|
|
3089
|
+
font-size: 0.85em;
|
|
3090
|
+
color: #4a3a8a;
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
.announcement-code {
|
|
3094
|
+
position: relative;
|
|
3095
|
+
margin: 0.6rem 0;
|
|
3096
|
+
}
|
|
3097
|
+
|
|
3098
|
+
.announcement-code pre {
|
|
3099
|
+
background: #0f1117;
|
|
3100
|
+
color: #e6e8f2;
|
|
3101
|
+
border-radius: 8px;
|
|
3102
|
+
padding: 10px 12px;
|
|
3103
|
+
overflow-x: auto;
|
|
3104
|
+
font-size: 12px;
|
|
3105
|
+
line-height: 1.5;
|
|
3106
|
+
white-space: pre;
|
|
3107
|
+
}
|
|
3108
|
+
|
|
3109
|
+
.announcement-code pre code::after {
|
|
3110
|
+
content: "";
|
|
3111
|
+
display: inline-block;
|
|
3112
|
+
width: 80px;
|
|
3113
|
+
}
|
|
3114
|
+
|
|
3115
|
+
.announcement-code__copy-shield {
|
|
3116
|
+
position: absolute;
|
|
3117
|
+
top: 4px;
|
|
3118
|
+
right: 4px;
|
|
3119
|
+
padding: 4px 4px 4px 24px;
|
|
3120
|
+
border-top-right-radius: 8px;
|
|
3121
|
+
background: linear-gradient(
|
|
3122
|
+
to right,
|
|
3123
|
+
rgba(15, 17, 23, 0) 0%,
|
|
3124
|
+
rgba(15, 17, 23, 0.95) 40%,
|
|
3125
|
+
#0f1117 100%
|
|
3126
|
+
);
|
|
3127
|
+
pointer-events: none;
|
|
3128
|
+
}
|
|
3129
|
+
|
|
3130
|
+
.announcement-code pre code {
|
|
3131
|
+
background: transparent;
|
|
3132
|
+
border: none;
|
|
3133
|
+
padding: 0;
|
|
3134
|
+
color: inherit;
|
|
3135
|
+
font-size: inherit;
|
|
3136
|
+
}
|
|
3137
|
+
|
|
3138
|
+
.announcement-code pre::-webkit-scrollbar {
|
|
3139
|
+
height: 6px;
|
|
3140
|
+
}
|
|
3141
|
+
.announcement-code pre::-webkit-scrollbar-track {
|
|
3142
|
+
background: transparent;
|
|
3143
|
+
}
|
|
3144
|
+
.announcement-code pre::-webkit-scrollbar-thumb {
|
|
3145
|
+
background: rgba(255, 255, 255, 0.2);
|
|
3146
|
+
border-radius: 3px;
|
|
3147
|
+
}
|
|
3148
|
+
|
|
3149
|
+
.announcement-code__copy {
|
|
3150
|
+
position: relative;
|
|
3151
|
+
pointer-events: auto;
|
|
3152
|
+
padding: 3px 8px;
|
|
3153
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
3154
|
+
font-size: 11px;
|
|
3155
|
+
font-weight: 600;
|
|
3156
|
+
color: #e6e8f2;
|
|
3157
|
+
background: #1f222d;
|
|
3158
|
+
border: 1px solid rgba(255, 255, 255, 0.15);
|
|
3159
|
+
border-radius: 5px;
|
|
3160
|
+
cursor: pointer;
|
|
3161
|
+
transition:
|
|
3162
|
+
background 0.12s ease,
|
|
3163
|
+
color 0.12s ease;
|
|
3164
|
+
}
|
|
3165
|
+
.announcement-code__copy:hover {
|
|
3166
|
+
background: #2a2e3c;
|
|
3167
|
+
}
|
|
3168
|
+
.announcement-code__copy[data-copied="true"] {
|
|
3169
|
+
background: #eee6fe;
|
|
3170
|
+
color: #6430ab;
|
|
3171
|
+
border-color: transparent;
|
|
3172
|
+
}
|
|
3173
|
+
|
|
3174
|
+
.announcement-body {
|
|
3175
|
+
position: relative;
|
|
3176
|
+
overflow: hidden;
|
|
3177
|
+
transition: max-height 0.25s ease;
|
|
3178
|
+
}
|
|
3179
|
+
.announcement-body--collapsed {
|
|
3180
|
+
max-height: 72px;
|
|
3181
|
+
}
|
|
3182
|
+
.announcement-body--expanded {
|
|
3183
|
+
max-height: 2000px;
|
|
3184
|
+
}
|
|
3185
|
+
.announcement-fade {
|
|
3186
|
+
position: absolute;
|
|
3187
|
+
bottom: 0;
|
|
3188
|
+
left: 0;
|
|
3189
|
+
right: 0;
|
|
3190
|
+
height: 48px;
|
|
3191
|
+
background: linear-gradient(to bottom, transparent, #ffffff);
|
|
3192
|
+
pointer-events: none;
|
|
3193
|
+
}
|
|
3194
|
+
.announcement-toggle {
|
|
3195
|
+
display: block;
|
|
3196
|
+
width: 100%;
|
|
3197
|
+
margin-top: 6px;
|
|
3198
|
+
padding: 0;
|
|
3199
|
+
background: none;
|
|
3200
|
+
border: none;
|
|
3201
|
+
font-family: "Plus Jakarta Sans", system-ui, sans-serif;
|
|
3202
|
+
font-size: 12px;
|
|
3203
|
+
font-weight: 500;
|
|
3204
|
+
color: #757cf2;
|
|
3205
|
+
cursor: pointer;
|
|
3206
|
+
text-align: center;
|
|
3207
|
+
}
|
|
3208
|
+
.announcement-toggle:hover {
|
|
3209
|
+
color: #6430ab;
|
|
3210
|
+
}
|
|
3211
|
+
|
|
3212
|
+
/* ── Brand typography ────────────────────────────────────────── */
|
|
3213
|
+
/* Override Tailwind font-mono stack → Spline Sans Mono */
|
|
3214
|
+
.font-mono,
|
|
3215
|
+
pre,
|
|
3216
|
+
code {
|
|
3217
|
+
font-family: "Spline Sans Mono", ui-monospace, "Cascadia Code", monospace;
|
|
3218
|
+
}
|
|
3219
|
+
|
|
3220
|
+
/* ── Floating button ─────────────────────────────────────────── */
|
|
3221
|
+
.console-button {
|
|
3222
|
+
background-color: rgba(1, 5, 7, 0.95) !important;
|
|
3223
|
+
border-color: rgba(190, 194, 255, 0.25) !important;
|
|
3224
|
+
box-shadow:
|
|
3225
|
+
0 0 0 1px rgba(190, 194, 255, 0.15),
|
|
3226
|
+
0 4px 14px rgba(1, 5, 7, 0.28) !important;
|
|
3227
|
+
}
|
|
3228
|
+
.console-button:hover {
|
|
3229
|
+
background-color: rgba(1, 5, 7, 1) !important;
|
|
3230
|
+
border-color: rgba(190, 194, 255, 0.45) !important;
|
|
3231
|
+
}
|
|
3232
|
+
.console-button:focus-visible {
|
|
3233
|
+
outline-color: #bec2ff !important;
|
|
3234
|
+
}
|
|
3235
|
+
|
|
3236
|
+
/* ── Inspector window ────────────────────────────────────────── */
|
|
3237
|
+
.inspector-window {
|
|
3238
|
+
border-color: #dbdbe5 !important;
|
|
3239
|
+
box-shadow:
|
|
3240
|
+
0 8px 32px rgba(1, 5, 7, 0.1),
|
|
3241
|
+
0 2px 8px rgba(1, 5, 7, 0.06) !important;
|
|
3242
|
+
}
|
|
3243
|
+
|
|
3244
|
+
/* ── Header drag area ────────────────────────────────────────── */
|
|
3245
|
+
.drag-handle {
|
|
3246
|
+
border-bottom-color: #dbdbe5 !important;
|
|
3247
|
+
/* Subtle pale lavender gradient — brand "light, spacious" surface */
|
|
3248
|
+
background: linear-gradient(180deg, #f4f4fd 0%, #ffffff 100%) !important;
|
|
3249
|
+
}
|
|
3250
|
+
|
|
3251
|
+
/* Tab strip row: soft off-white, separated from content */
|
|
3252
|
+
.drag-handle > div:last-child {
|
|
3253
|
+
border-top-color: #e2e2ea !important;
|
|
3254
|
+
background-color: #fafafc !important;
|
|
3255
|
+
}
|
|
3256
|
+
|
|
3257
|
+
/* ── Tab buttons ─────────────────────────────────────────────── */
|
|
3258
|
+
/*
|
|
3259
|
+
* Named classes owned by this component — no Tailwind conflict.
|
|
3260
|
+
* Active: brand surface/surfaceContainerActive (lilac tint) +
|
|
3261
|
+
* border/borderActionEnabled underline.
|
|
3262
|
+
* Dark fill is for primary action buttons only, not nav tabs.
|
|
3263
|
+
*/
|
|
3264
|
+
.cpk-tab-active {
|
|
3265
|
+
background-color: rgba(190, 194, 255, 0.18);
|
|
3266
|
+
color: #010507;
|
|
3267
|
+
font-weight: 600;
|
|
3268
|
+
}
|
|
3269
|
+
.cpk-tab-active .cpk-tab-icon {
|
|
3270
|
+
color: #757cf2;
|
|
3271
|
+
}
|
|
3272
|
+
.cpk-tab-inactive {
|
|
3273
|
+
background-color: transparent;
|
|
3274
|
+
color: #2b2b2b;
|
|
3275
|
+
}
|
|
3276
|
+
.cpk-tab-inactive .cpk-tab-icon {
|
|
3277
|
+
color: #838389;
|
|
3278
|
+
}
|
|
3279
|
+
.cpk-tab-inactive:hover {
|
|
3280
|
+
background-color: rgba(190, 194, 255, 0.08);
|
|
3281
|
+
color: #010507;
|
|
3282
|
+
cursor: pointer;
|
|
3283
|
+
}
|
|
3284
|
+
.cpk-tab-active {
|
|
3285
|
+
cursor: pointer;
|
|
3286
|
+
}
|
|
3287
|
+
|
|
3288
|
+
/* ── Header control buttons (dock, close) — first row only ───── */
|
|
3289
|
+
.drag-handle > div:first-child button {
|
|
3290
|
+
color: #838389 !important;
|
|
3291
|
+
}
|
|
3292
|
+
.drag-handle > div:first-child button:hover {
|
|
3293
|
+
background-color: #f0f0f4 !important;
|
|
3294
|
+
color: #57575b !important;
|
|
3295
|
+
}
|
|
3296
|
+
.drag-handle > div:first-child button:focus-visible {
|
|
3297
|
+
outline-color: #bec2ff !important;
|
|
3298
|
+
}
|
|
3299
|
+
|
|
3300
|
+
/* ── Agent/context dropdown ──────────────────────────────────── */
|
|
3301
|
+
[data-context-dropdown-root="true"] > button {
|
|
3302
|
+
border-color: #dbdbe5 !important;
|
|
3303
|
+
color: #010507 !important;
|
|
3304
|
+
}
|
|
3305
|
+
[data-context-dropdown-root="true"] > button:hover {
|
|
3306
|
+
border-color: #bec2ff !important;
|
|
3307
|
+
background-color: #f7f7f9 !important;
|
|
3308
|
+
}
|
|
3309
|
+
[data-context-dropdown-root="true"] > button > span:last-child {
|
|
3310
|
+
color: #838389 !important;
|
|
3311
|
+
}
|
|
3312
|
+
[data-context-dropdown-root="true"] > div {
|
|
3313
|
+
border-color: #dbdbe5 !important;
|
|
3314
|
+
box-shadow: 0 4px 12px rgba(1, 5, 7, 0.08) !important;
|
|
3315
|
+
}
|
|
3316
|
+
[data-context-dropdown-root="true"] > div button:hover,
|
|
3317
|
+
[data-context-dropdown-root="true"] > div button:focus {
|
|
3318
|
+
background-color: #f7f7f9 !important;
|
|
3319
|
+
}
|
|
3320
|
+
|
|
3321
|
+
/* ── Status bar (bottom chrome) ──────────────────────────────── */
|
|
3322
|
+
.inspector-window > div > div:last-child {
|
|
3323
|
+
border-top-color: #dbdbe5 !important;
|
|
3324
|
+
background-color: #f7f7f9 !important;
|
|
3325
|
+
}
|
|
3326
|
+
|
|
3327
|
+
/* ── Resize handle ───────────────────────────────────────────── */
|
|
3328
|
+
.resize-handle {
|
|
3329
|
+
color: #838389 !important;
|
|
3330
|
+
}
|
|
3331
|
+
.resize-handle:hover {
|
|
3332
|
+
color: #57575b !important;
|
|
3333
|
+
}
|
|
3334
|
+
|
|
3335
|
+
/* ── AG-UI Events tab ────────────────────────────────────────── */
|
|
3336
|
+
/* Row hover: replace blue tint with brand lilac */
|
|
3337
|
+
tr:hover td {
|
|
3338
|
+
background-color: rgba(190, 194, 255, 0.08) !important;
|
|
3339
|
+
}
|
|
3340
|
+
/* Reset/dark action button */
|
|
3341
|
+
button[class*="bg-gray-900"] {
|
|
3342
|
+
background-color: #010507 !important;
|
|
3343
|
+
}
|
|
3344
|
+
button[class*="bg-gray-800"] {
|
|
3345
|
+
background-color: #2b2b2b !important;
|
|
3346
|
+
}
|
|
3347
|
+
/* Copy "copied" state: generic green → brand mint */
|
|
3348
|
+
button[class*="bg-green-100"] {
|
|
3349
|
+
background-color: rgba(133, 236, 206, 0.2) !important;
|
|
3350
|
+
color: #189370 !important;
|
|
3351
|
+
}
|
|
3352
|
+
|
|
3353
|
+
/* ── Agents tab ──────────────────────────────────────────────── */
|
|
3354
|
+
/* Agent icon bubble: blue → lilac */
|
|
3355
|
+
span[class*="bg-blue-100"]:not([class*="text-blue-800"]) {
|
|
3356
|
+
background-color: rgba(190, 194, 255, 0.15) !important;
|
|
3357
|
+
}
|
|
3358
|
+
span[class*="text-blue-600"] {
|
|
3359
|
+
color: #757cf2 !important;
|
|
3360
|
+
}
|
|
3361
|
+
/* Running badge: emerald → mint */
|
|
3362
|
+
span[class*="bg-emerald-50"] {
|
|
3363
|
+
background-color: rgba(133, 236, 206, 0.15) !important;
|
|
3364
|
+
}
|
|
3365
|
+
span[class*="text-emerald-700"] {
|
|
3366
|
+
color: #189370 !important;
|
|
3367
|
+
}
|
|
3368
|
+
/* Running status dot */
|
|
3369
|
+
span[class*="bg-emerald-500"] {
|
|
3370
|
+
background-color: #85ecce !important;
|
|
3371
|
+
}
|
|
3372
|
+
/* Idle dot */
|
|
3373
|
+
span[class*="bg-gray-400"] {
|
|
3374
|
+
background-color: #afafb7 !important;
|
|
3375
|
+
}
|
|
3376
|
+
/* User role badge (blue → lilac) */
|
|
3377
|
+
span[class*="bg-blue-100"][class*="text-blue-800"] {
|
|
3378
|
+
background-color: rgba(190, 194, 255, 0.22) !important;
|
|
3379
|
+
border: 1px solid rgba(190, 194, 255, 0.45) !important;
|
|
3380
|
+
color: #57575b !important;
|
|
3381
|
+
}
|
|
3382
|
+
/* Assistant role badge (green → mint) */
|
|
3383
|
+
span[class*="bg-green-100"][class*="text-green-800"] {
|
|
3384
|
+
background-color: rgba(133, 236, 206, 0.18) !important;
|
|
3385
|
+
border: 1px solid rgba(133, 236, 206, 0.4) !important;
|
|
3386
|
+
color: #189370 !important;
|
|
3387
|
+
}
|
|
3388
|
+
/* Tool role badge (amber → orange brand) */
|
|
3389
|
+
span[class*="bg-amber-100"][class*="text-amber-800"] {
|
|
3390
|
+
background-color: rgba(255, 172, 77, 0.15) !important;
|
|
3391
|
+
color: #57575b !important;
|
|
3392
|
+
}
|
|
3393
|
+
|
|
3394
|
+
/* ── Frontend Tools tab ──────────────────────────────────────── */
|
|
3395
|
+
/* Handler badge (blue → lilac) */
|
|
3396
|
+
span[class*="bg-blue-50"][class*="text-blue-700"] {
|
|
3397
|
+
background-color: rgba(190, 194, 255, 0.12) !important;
|
|
3398
|
+
border-color: rgba(190, 194, 255, 0.3) !important;
|
|
3399
|
+
color: #010507 !important;
|
|
3400
|
+
}
|
|
3401
|
+
/* Renderer badge (purple → lilac-adjacent) */
|
|
3402
|
+
span[class*="bg-purple-50"][class*="text-purple-700"] {
|
|
3403
|
+
background-color: rgba(190, 194, 255, 0.12) !important;
|
|
3404
|
+
border-color: rgba(190, 194, 255, 0.3) !important;
|
|
3405
|
+
color: #57575b !important;
|
|
3406
|
+
}
|
|
3407
|
+
/* Required badge (rose → brand red) */
|
|
3408
|
+
span[class*="bg-rose-50"][class*="text-rose-700"] {
|
|
3409
|
+
background-color: rgba(250, 95, 103, 0.1) !important;
|
|
3410
|
+
border-color: rgba(250, 95, 103, 0.25) !important;
|
|
3411
|
+
color: #fa5f67 !important;
|
|
3412
|
+
}
|
|
3413
|
+
/* Code/default value blocks */
|
|
3414
|
+
code[class*="bg-gray-100"],
|
|
3415
|
+
span[class*="bg-gray-100"] {
|
|
3416
|
+
background-color: #f0f0f4 !important;
|
|
3417
|
+
}
|
|
3418
|
+
|
|
3419
|
+
/* ── Connected status bar: match threads header mint (#5BE4BB) ──── */
|
|
3420
|
+
/* Outer strip bg + top border + text when connected badge is present */
|
|
3421
|
+
.inspector-window
|
|
3422
|
+
> div
|
|
3423
|
+
> div:last-child
|
|
3424
|
+
> div:last-child:has(div[class*="bg-emerald-50"]) {
|
|
3425
|
+
background-color: rgba(91, 228, 187, 0.08) !important;
|
|
3426
|
+
border-top-color: rgba(91, 228, 187, 0.3) !important;
|
|
3427
|
+
color: #189370 !important;
|
|
3428
|
+
}
|
|
3429
|
+
/* Inner badge — slightly more opaque on the mint bg */
|
|
3430
|
+
div[class*="bg-emerald-50"][class*="border-emerald-200"] {
|
|
3431
|
+
background-color: rgba(91, 228, 187, 0.12) !important;
|
|
3432
|
+
border-color: rgba(91, 228, 187, 0.4) !important;
|
|
3433
|
+
color: #189370 !important;
|
|
3434
|
+
}
|
|
3435
|
+
/* Icon bubble inside connected badge → mint tint */
|
|
3436
|
+
div[class*="bg-emerald-50"] span[class*="bg-white"] {
|
|
3437
|
+
background-color: rgba(91, 228, 187, 0.3) !important;
|
|
3438
|
+
}
|
|
3439
|
+
|
|
3440
|
+
/* ── Announcement panel ──────────────────────────────────────── */
|
|
3441
|
+
div[class*="border-slate-200"][class*="bg-white"] {
|
|
3442
|
+
border-color: #dbdbe5 !important;
|
|
3443
|
+
}
|
|
3444
|
+
/* Announcement icon bubble: black → brand light lavender + lilac icon */
|
|
3445
|
+
span[class*="bg-slate-900"],
|
|
3446
|
+
div[class*="bg-slate-900"] {
|
|
3447
|
+
background-color: #eee6fe !important;
|
|
3448
|
+
color: #757cf2 !important;
|
|
3449
|
+
}
|
|
3450
|
+
span[class*="text-slate-800"],
|
|
3451
|
+
div[class*="text-slate-800"] {
|
|
3452
|
+
color: #010507 !important;
|
|
3453
|
+
}
|
|
1027
3454
|
`];
|
|
1028
3455
|
}
|
|
1029
3456
|
connectedCallback() {
|
|
1030
3457
|
super.connectedCallback();
|
|
1031
3458
|
if (typeof window !== "undefined") {
|
|
3459
|
+
this.ensureBrandFonts();
|
|
1032
3460
|
window.addEventListener("resize", this.handleResize);
|
|
1033
3461
|
window.addEventListener("pointerdown", this.handleGlobalPointerDown);
|
|
1034
3462
|
this.hydrateStateFromStorageEarly();
|
|
@@ -1036,6 +3464,15 @@ ${argsString}</pre
|
|
|
1036
3464
|
this.ensureAnnouncementLoading();
|
|
1037
3465
|
}
|
|
1038
3466
|
}
|
|
3467
|
+
ensureBrandFonts() {
|
|
3468
|
+
const FONT_LINK_ID = "cpk-inspector-brand-fonts";
|
|
3469
|
+
if (document.getElementById(FONT_LINK_ID)) return;
|
|
3470
|
+
const link = document.createElement("link");
|
|
3471
|
+
link.id = FONT_LINK_ID;
|
|
3472
|
+
link.rel = "stylesheet";
|
|
3473
|
+
link.href = "https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;600&family=Spline+Sans+Mono:wght@600&display=swap";
|
|
3474
|
+
document.head.appendChild(link);
|
|
3475
|
+
}
|
|
1039
3476
|
disconnectedCallback() {
|
|
1040
3477
|
super.disconnectedCallback();
|
|
1041
3478
|
if (typeof window !== "undefined") {
|
|
@@ -1113,7 +3550,7 @@ ${argsString}</pre
|
|
|
1113
3550
|
"focus-visible:outline",
|
|
1114
3551
|
"focus-visible:outline-2",
|
|
1115
3552
|
"focus-visible:outline-offset-2",
|
|
1116
|
-
"focus-visible:outline-
|
|
3553
|
+
"focus-visible:outline-[#BEC2FF]",
|
|
1117
3554
|
"touch-none",
|
|
1118
3555
|
"select-none",
|
|
1119
3556
|
this.isDragging ? "cursor-grabbing" : "cursor-grab"
|
|
@@ -1221,14 +3658,12 @@ ${argsString}</pre
|
|
|
1221
3658
|
return html`
|
|
1222
3659
|
<button
|
|
1223
3660
|
type="button"
|
|
1224
|
-
class=${["inline-flex items-center gap-2 rounded-md px-3 py-2 transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-300", isSelected ? "
|
|
3661
|
+
class=${["inline-flex items-center gap-2 rounded-md px-3 py-2 transition focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-300", isSelected ? "cpk-tab-active" : "cpk-tab-inactive"].join(" ")}
|
|
1225
3662
|
aria-pressed=${isSelected}
|
|
1226
3663
|
@click=${() => this.handleMenuSelect(key)}
|
|
1227
3664
|
>
|
|
1228
|
-
<span
|
|
1229
|
-
|
|
1230
|
-
>
|
|
1231
|
-
${this.renderIcon(icon)}
|
|
3665
|
+
<span class="cpk-tab-icon">
|
|
3666
|
+
${key in this.customTabIcons ? unsafeHTML(this.customTabIcons[key]) : this.renderIcon(icon)}
|
|
1232
3667
|
</span>
|
|
1233
3668
|
<span>${label}</span>
|
|
1234
3669
|
</button>
|
|
@@ -1237,8 +3672,8 @@ ${argsString}</pre
|
|
|
1237
3672
|
</div>
|
|
1238
3673
|
</div>
|
|
1239
3674
|
<div class="flex flex-1 flex-col overflow-hidden">
|
|
1240
|
-
<div class="flex-1 overflow-auto">
|
|
1241
|
-
${this.
|
|
3675
|
+
<div id="cpk-main-scroll" class="flex-1 overflow-auto">
|
|
3676
|
+
${this.renderAnnouncementBanner()}
|
|
1242
3677
|
${this.renderCoreWarningBanner()} ${this.renderMainContent()}
|
|
1243
3678
|
<slot></slot>
|
|
1244
3679
|
</div>
|
|
@@ -1682,7 +4117,8 @@ ${argsString}</pre
|
|
|
1682
4117
|
role,
|
|
1683
4118
|
contentText,
|
|
1684
4119
|
contentRaw: raw.content !== void 0 ? this.sanitizeForLogging(raw.content) : void 0,
|
|
1685
|
-
toolCalls
|
|
4120
|
+
toolCalls,
|
|
4121
|
+
activityType: typeof raw.activityType === "string" ? raw.activityType : void 0
|
|
1686
4122
|
};
|
|
1687
4123
|
}
|
|
1688
4124
|
normalizeAgentMessages(messages) {
|
|
@@ -1701,9 +4137,6 @@ ${argsString}</pre
|
|
|
1701
4137
|
} else normalized[key] = { value: entry };
|
|
1702
4138
|
return normalized;
|
|
1703
4139
|
}
|
|
1704
|
-
getSelectedMenu() {
|
|
1705
|
-
return this.menuItems.find((item) => item.key === this.selectedMenu) ?? this.menuItems[0];
|
|
1706
|
-
}
|
|
1707
4140
|
renderCoreWarningBanner() {
|
|
1708
4141
|
if (this._core) return nothing;
|
|
1709
4142
|
return html`
|
|
@@ -1760,27 +4193,99 @@ ${argsString}</pre
|
|
|
1760
4193
|
if (this.selectedMenu === "agents") return this.renderAgentsView();
|
|
1761
4194
|
if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
|
|
1762
4195
|
if (this.selectedMenu === "agent-context") return this.renderContextView();
|
|
4196
|
+
if (this.selectedMenu === "threads") return this.renderThreadsView();
|
|
1763
4197
|
return nothing;
|
|
1764
4198
|
}
|
|
4199
|
+
renderThreadsView() {
|
|
4200
|
+
const displayThreads = this.selectedContext === "all-agents" ? this._threads : this._threadsByAgent.get(this.selectedContext) ?? [];
|
|
4201
|
+
let threadsErrorMessage = null;
|
|
4202
|
+
if (this.selectedContext === "all-agents") threadsErrorMessage = this._threadsErrorByAgent.values().next().value?.message ?? null;
|
|
4203
|
+
else threadsErrorMessage = this._threadsErrorByAgent.get(this.selectedContext)?.message ?? null;
|
|
4204
|
+
const selectedThread = this.selectedThreadId != null ? displayThreads.find((t) => t.id === this.selectedThreadId) ?? null : null;
|
|
4205
|
+
return html`
|
|
4206
|
+
<div style="display:flex;height:100%;overflow:hidden;">
|
|
4207
|
+
<!-- Left sidebar: thread list -->
|
|
4208
|
+
<div
|
|
4209
|
+
style="width:${this.threadListWidth}px;flex-shrink:0;overflow:hidden;display:flex;flex-direction:column;border-right:1px solid #DBDBE5;"
|
|
4210
|
+
>
|
|
4211
|
+
<cpk-thread-list
|
|
4212
|
+
style="height:100%;"
|
|
4213
|
+
.threads=${displayThreads}
|
|
4214
|
+
.selectedThreadId=${this.selectedThreadId}
|
|
4215
|
+
.errorMessage=${threadsErrorMessage}
|
|
4216
|
+
@threadSelected=${(e) => {
|
|
4217
|
+
this.selectedThreadId = e.detail;
|
|
4218
|
+
this.requestUpdate();
|
|
4219
|
+
}}
|
|
4220
|
+
></cpk-thread-list>
|
|
4221
|
+
</div>
|
|
4222
|
+
|
|
4223
|
+
<!-- Resize divider -->
|
|
4224
|
+
<div
|
|
4225
|
+
style="width:4px;flex-shrink:0;cursor:col-resize;background:transparent;position:relative;z-index:1;"
|
|
4226
|
+
@pointerdown=${this.handleThreadDividerPointerDown}
|
|
4227
|
+
@pointermove=${this.handleThreadDividerPointerMove}
|
|
4228
|
+
@pointerup=${this.handleThreadDividerPointerUp}
|
|
4229
|
+
@pointercancel=${this.handleThreadDividerPointerUp}
|
|
4230
|
+
></div>
|
|
4231
|
+
|
|
4232
|
+
<!-- Center + right: thread details or empty state -->
|
|
4233
|
+
<div style="flex:1;min-width:0;overflow:hidden;display:flex;">
|
|
4234
|
+
${this.selectedThreadId ? html`<cpk-thread-details
|
|
4235
|
+
style="flex:1;min-width:0;"
|
|
4236
|
+
.threadId=${this.selectedThreadId}
|
|
4237
|
+
.thread=${selectedThread}
|
|
4238
|
+
.runtimeUrl=${this._core?.runtimeUrl ?? ""}
|
|
4239
|
+
.headers=${this._core?.headers ?? {}}
|
|
4240
|
+
.liveMessageVersion=${this.selectedThreadId ? this.liveMessageVersion.get(this.selectedThreadId) ?? 0 : 0}
|
|
4241
|
+
.agentStateInput=${selectedThread ? this.getLatestStateForAgent(selectedThread.agentId) : null}
|
|
4242
|
+
.agentEventsInput=${selectedThread ? this.agentEvents.get(selectedThread.agentId) ?? [] : []}
|
|
4243
|
+
></cpk-thread-details>` : html`
|
|
4244
|
+
<div
|
|
4245
|
+
style="
|
|
4246
|
+
flex: 1;
|
|
4247
|
+
display: flex;
|
|
4248
|
+
flex-direction: column;
|
|
4249
|
+
align-items: center;
|
|
4250
|
+
justify-content: center;
|
|
4251
|
+
gap: 8px;
|
|
4252
|
+
color: #838389;
|
|
4253
|
+
"
|
|
4254
|
+
>
|
|
4255
|
+
<svg
|
|
4256
|
+
width="32"
|
|
4257
|
+
height="32"
|
|
4258
|
+
viewBox="0 0 24 24"
|
|
4259
|
+
fill="none"
|
|
4260
|
+
stroke="#c0c0c8"
|
|
4261
|
+
stroke-width="1.5"
|
|
4262
|
+
stroke-linecap="round"
|
|
4263
|
+
stroke-linejoin="round"
|
|
4264
|
+
>
|
|
4265
|
+
<path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
|
|
4266
|
+
</svg>
|
|
4267
|
+
<span style="font-size: 13px">${displayThreads.length === 0 ? "No threads yet" : "Select a thread to inspect"}</span>
|
|
4268
|
+
</div>
|
|
4269
|
+
`}
|
|
4270
|
+
</div>
|
|
4271
|
+
</div>
|
|
4272
|
+
`;
|
|
4273
|
+
}
|
|
1765
4274
|
renderEventsTable() {
|
|
1766
4275
|
const events = this.getEventsForSelectedContext();
|
|
1767
4276
|
const filteredEvents = this.filterEvents(events);
|
|
1768
4277
|
const selectedLabel = this.selectedContext === "all-agents" ? "all agents" : `agent ${this.selectedContext}`;
|
|
1769
4278
|
if (events.length === 0) return html`
|
|
1770
4279
|
<div
|
|
1771
|
-
class="flex h-full items-center justify-center px-4 py-
|
|
4280
|
+
class="flex h-full flex-col items-center justify-center gap-2 px-4 py-10 text-center"
|
|
1772
4281
|
>
|
|
1773
|
-
<div class="
|
|
1774
|
-
|
|
1775
|
-
class="mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
1776
|
-
>
|
|
1777
|
-
${this.renderIcon("Zap")}
|
|
1778
|
-
</div>
|
|
1779
|
-
<p class="text-sm text-gray-600">No events yet</p>
|
|
1780
|
-
<p class="mt-2 text-xs text-gray-500">
|
|
1781
|
-
Trigger an agent run to see live activity.
|
|
1782
|
-
</p>
|
|
4282
|
+
<div class="text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8">
|
|
4283
|
+
${this.renderIcon("Zap")}
|
|
1783
4284
|
</div>
|
|
4285
|
+
<span class="text-sm text-gray-600">No events yet</span>
|
|
4286
|
+
<span class="max-w-[240px] text-xs leading-snug text-gray-400"
|
|
4287
|
+
>Events are recorded live. Run the agent to see them here.</span
|
|
4288
|
+
>
|
|
1784
4289
|
</div>
|
|
1785
4290
|
`;
|
|
1786
4291
|
if (filteredEvents.length === 0) return html`
|
|
@@ -1877,23 +4382,32 @@ ${argsString}</pre
|
|
|
1877
4382
|
</div>
|
|
1878
4383
|
<div class="relative h-full w-full overflow-y-auto overflow-x-hidden">
|
|
1879
4384
|
<table class="w-full table-fixed border-collapse text-xs box-border">
|
|
4385
|
+
<colgroup>
|
|
4386
|
+
<col style="width:${this.evtColWidths[0]}px">
|
|
4387
|
+
<col style="width:${this.evtColWidths[1]}px">
|
|
4388
|
+
<col style="width:${this.evtColWidths[2]}px">
|
|
4389
|
+
<col>
|
|
4390
|
+
</colgroup>
|
|
1880
4391
|
<thead class="sticky top-0 z-10">
|
|
1881
4392
|
<tr class="bg-white">
|
|
4393
|
+
${[
|
|
4394
|
+
"Agent",
|
|
4395
|
+
"Time",
|
|
4396
|
+
"Event Type"
|
|
4397
|
+
].map((label, col) => html`
|
|
1882
4398
|
<th
|
|
1883
4399
|
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
4400
|
+
style="position:relative;overflow:hidden;"
|
|
1884
4401
|
>
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
|
|
1890
|
-
|
|
1891
|
-
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
>
|
|
1895
|
-
Event Type
|
|
1896
|
-
</th>
|
|
4402
|
+
${label}
|
|
4403
|
+
<div
|
|
4404
|
+
style="position:absolute;top:0;right:0;width:5px;height:100%;cursor:col-resize;user-select:none;background:transparent;"
|
|
4405
|
+
@pointerdown=${(e) => this._onEvtColResizeStart(e, col)}
|
|
4406
|
+
@pointermove=${(e) => this._onEvtColResizeMove(e)}
|
|
4407
|
+
@pointerup=${() => this._onEvtColResizeEnd()}
|
|
4408
|
+
@pointercancel=${() => this._onEvtColResizeEnd()}
|
|
4409
|
+
></div>
|
|
4410
|
+
</th>`)}
|
|
1897
4411
|
<th
|
|
1898
4412
|
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
1899
4413
|
>
|
|
@@ -1981,6 +4495,25 @@ ${prettyEvent}</pre
|
|
|
1981
4495
|
this.eventTypeFilter = "all";
|
|
1982
4496
|
this.requestUpdate();
|
|
1983
4497
|
}
|
|
4498
|
+
_onEvtColResizeStart(e, col) {
|
|
4499
|
+
e.preventDefault();
|
|
4500
|
+
e.stopPropagation();
|
|
4501
|
+
e.currentTarget.setPointerCapture(e.pointerId);
|
|
4502
|
+
this._evtColResize = {
|
|
4503
|
+
col,
|
|
4504
|
+
startX: e.clientX,
|
|
4505
|
+
startW: this.evtColWidths[col] ?? 0
|
|
4506
|
+
};
|
|
4507
|
+
}
|
|
4508
|
+
_onEvtColResizeMove(e) {
|
|
4509
|
+
if (!this._evtColResize) return;
|
|
4510
|
+
const { col, startX, startW } = this._evtColResize;
|
|
4511
|
+
this.evtColWidths = this.evtColWidths.map((w, i) => i === col ? Math.max(40, startW + (e.clientX - startX)) : w);
|
|
4512
|
+
this.requestUpdate();
|
|
4513
|
+
}
|
|
4514
|
+
_onEvtColResizeEnd() {
|
|
4515
|
+
this._evtColResize = null;
|
|
4516
|
+
}
|
|
1984
4517
|
exportEvents(events) {
|
|
1985
4518
|
try {
|
|
1986
4519
|
const payload = JSON.stringify(events, null, 2);
|
|
@@ -2025,7 +4558,7 @@ ${prettyEvent}</pre
|
|
|
2025
4558
|
<div class="flex items-start justify-between mb-4">
|
|
2026
4559
|
<div class="flex items-center gap-3">
|
|
2027
4560
|
<div
|
|
2028
|
-
class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600"
|
|
4561
|
+
class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600 cpk-agent-icon"
|
|
2029
4562
|
>
|
|
2030
4563
|
${this.renderIcon("Bot")}
|
|
2031
4564
|
</div>
|
|
@@ -2053,7 +4586,7 @@ ${prettyEvent}</pre
|
|
|
2053
4586
|
<div class="grid grid-cols-2 gap-4 md:grid-cols-4">
|
|
2054
4587
|
<button
|
|
2055
4588
|
type="button"
|
|
2056
|
-
class="rounded-md bg-gray-50 px-3 py-2 text-left transition hover:bg-gray-100 cursor-pointer overflow-hidden"
|
|
4589
|
+
class="rounded-md bg-gray-50 px-3 py-2 text-left transition hover:bg-gray-100 cursor-pointer overflow-hidden cpk-stat-card"
|
|
2057
4590
|
@click=${() => this.handleMenuSelect("ag-ui-events")}
|
|
2058
4591
|
title="View all events in AG-UI Events"
|
|
2059
4592
|
>
|
|
@@ -2064,7 +4597,9 @@ ${prettyEvent}</pre
|
|
|
2064
4597
|
${stats.totalEvents}
|
|
2065
4598
|
</div>
|
|
2066
4599
|
</button>
|
|
2067
|
-
<div
|
|
4600
|
+
<div
|
|
4601
|
+
class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card"
|
|
4602
|
+
>
|
|
2068
4603
|
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2069
4604
|
Messages
|
|
2070
4605
|
</div>
|
|
@@ -2072,7 +4607,9 @@ ${prettyEvent}</pre
|
|
|
2072
4607
|
${stats.messages}
|
|
2073
4608
|
</div>
|
|
2074
4609
|
</div>
|
|
2075
|
-
<div
|
|
4610
|
+
<div
|
|
4611
|
+
class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card"
|
|
4612
|
+
>
|
|
2076
4613
|
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2077
4614
|
Tool Calls
|
|
2078
4615
|
</div>
|
|
@@ -2080,7 +4617,9 @@ ${prettyEvent}</pre
|
|
|
2080
4617
|
${stats.toolCalls}
|
|
2081
4618
|
</div>
|
|
2082
4619
|
</div>
|
|
2083
|
-
<div
|
|
4620
|
+
<div
|
|
4621
|
+
class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card"
|
|
4622
|
+
>
|
|
2084
4623
|
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2085
4624
|
Errors
|
|
2086
4625
|
</div>
|
|
@@ -2092,9 +4631,9 @@ ${prettyEvent}</pre
|
|
|
2092
4631
|
</div>
|
|
2093
4632
|
|
|
2094
4633
|
<!-- Current State Section -->
|
|
2095
|
-
<div class="
|
|
2096
|
-
<div class="
|
|
2097
|
-
<h4
|
|
4634
|
+
<div class="cpk-section-card">
|
|
4635
|
+
<div class="cpk-section-header">
|
|
4636
|
+
<h4>Current State</h4>
|
|
2098
4637
|
</div>
|
|
2099
4638
|
<div class="overflow-auto p-4">
|
|
2100
4639
|
${this.hasRenderableState(state) ? html`
|
|
@@ -2103,7 +4642,7 @@ ${prettyEvent}</pre
|
|
|
2103
4642
|
><code>${this.formatStateForDisplay(state)}</code></pre>
|
|
2104
4643
|
` : html`
|
|
2105
4644
|
<div
|
|
2106
|
-
class="flex h-
|
|
4645
|
+
class="flex h-12 items-center justify-center text-xs text-gray-500"
|
|
2107
4646
|
>
|
|
2108
4647
|
<div class="flex items-center gap-2 text-gray-500">
|
|
2109
4648
|
<span class="text-lg text-gray-400"
|
|
@@ -2117,30 +4656,18 @@ ${prettyEvent}</pre
|
|
|
2117
4656
|
</div>
|
|
2118
4657
|
|
|
2119
4658
|
<!-- Current Messages Section -->
|
|
2120
|
-
<div class="
|
|
2121
|
-
<div class="
|
|
2122
|
-
<h4
|
|
2123
|
-
Current Messages
|
|
2124
|
-
</h4>
|
|
4659
|
+
<div class="cpk-section-card">
|
|
4660
|
+
<div class="cpk-section-header">
|
|
4661
|
+
<h4>Current Messages</h4>
|
|
2125
4662
|
</div>
|
|
2126
4663
|
<div class="overflow-auto">
|
|
2127
4664
|
${messages && messages.length > 0 ? html`
|
|
2128
|
-
<
|
|
2129
|
-
<
|
|
2130
|
-
<
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
Role
|
|
2135
|
-
</th>
|
|
2136
|
-
<th
|
|
2137
|
-
class="px-4 py-2 text-left font-medium text-gray-700"
|
|
2138
|
-
>
|
|
2139
|
-
Content
|
|
2140
|
-
</th>
|
|
2141
|
-
</tr>
|
|
2142
|
-
</thead>
|
|
2143
|
-
<tbody class="divide-y divide-gray-200">
|
|
4665
|
+
<div class="w-full text-xs">
|
|
4666
|
+
<div class="flex bg-gray-50">
|
|
4667
|
+
<div class="w-40 shrink-0 px-4 py-2 font-medium text-gray-700">Role</div>
|
|
4668
|
+
<div class="flex-1 px-4 py-2 font-medium text-gray-700">Content</div>
|
|
4669
|
+
</div>
|
|
4670
|
+
<div class="divide-y divide-gray-200">
|
|
2144
4671
|
${messages.map((msg) => {
|
|
2145
4672
|
const role = msg.role || "unknown";
|
|
2146
4673
|
const roleColors = {
|
|
@@ -2155,34 +4682,32 @@ ${prettyEvent}</pre
|
|
|
2155
4682
|
const hasContent = rawContent.trim().length > 0;
|
|
2156
4683
|
const contentFallback = toolCalls.length > 0 ? "Invoked tool call" : "—";
|
|
2157
4684
|
return html`
|
|
2158
|
-
<
|
|
2159
|
-
<
|
|
4685
|
+
<div class="flex items-start">
|
|
4686
|
+
<div class="w-40 shrink-0 px-4 py-2">
|
|
2160
4687
|
<span
|
|
2161
4688
|
class="inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${roleColors[role] || roleColors.unknown}"
|
|
2162
4689
|
>
|
|
2163
4690
|
${role}
|
|
2164
4691
|
</span>
|
|
2165
|
-
</
|
|
2166
|
-
<
|
|
4692
|
+
</div>
|
|
4693
|
+
<div class="flex-1 px-4 py-2">
|
|
2167
4694
|
${hasContent ? html`<div
|
|
2168
|
-
class="
|
|
4695
|
+
class="whitespace-pre-line break-words text-gray-700"
|
|
2169
4696
|
>
|
|
2170
4697
|
${rawContent}
|
|
2171
|
-
</div>` : html`<div
|
|
2172
|
-
class="text-xs italic text-gray-400"
|
|
2173
|
-
>
|
|
4698
|
+
</div>` : html`<div class="italic text-gray-400">
|
|
2174
4699
|
${contentFallback}
|
|
2175
4700
|
</div>`}
|
|
2176
4701
|
${role === "assistant" && toolCalls.length > 0 ? this.renderToolCallDetails(toolCalls) : nothing}
|
|
2177
|
-
</
|
|
2178
|
-
</
|
|
4702
|
+
</div>
|
|
4703
|
+
</div>
|
|
2179
4704
|
`;
|
|
2180
4705
|
})}
|
|
2181
|
-
</
|
|
2182
|
-
</
|
|
4706
|
+
</div>
|
|
4707
|
+
</div>
|
|
2183
4708
|
` : html`
|
|
2184
4709
|
<div
|
|
2185
|
-
class="flex h-
|
|
4710
|
+
class="flex h-12 items-center justify-center text-xs text-gray-500"
|
|
2186
4711
|
>
|
|
2187
4712
|
<div class="flex items-center gap-2 text-gray-500">
|
|
2188
4713
|
<span class="text-lg text-gray-400"
|
|
@@ -2243,14 +4768,29 @@ ${prettyEvent}</pre
|
|
|
2243
4768
|
}
|
|
2244
4769
|
handleMenuSelect(key) {
|
|
2245
4770
|
if (!this.menuItems.some((item) => item.key === key)) return;
|
|
4771
|
+
const previousMenu = this.selectedMenu;
|
|
2246
4772
|
this.selectedMenu = key;
|
|
2247
4773
|
if (key === "agents" && this.selectedContext === "all-agents") {
|
|
2248
4774
|
const agentOptions = this.contextOptions.filter((opt) => opt.key !== "all-agents");
|
|
2249
4775
|
if (agentOptions.length > 0) {
|
|
2250
|
-
const
|
|
2251
|
-
|
|
4776
|
+
const mostRecent = agentOptions.reduce((best, opt) => {
|
|
4777
|
+
const ts = this.getAgentStats(opt.key).lastActivity ?? -1;
|
|
4778
|
+
return best === null || ts > best.ts ? {
|
|
4779
|
+
key: opt.key,
|
|
4780
|
+
ts
|
|
4781
|
+
} : best;
|
|
4782
|
+
}, null);
|
|
4783
|
+
this.selectedContext = mostRecent ? mostRecent.key : agentOptions[0].key;
|
|
2252
4784
|
}
|
|
2253
4785
|
}
|
|
4786
|
+
if (previousMenu === "agents" && key !== "agents") {
|
|
4787
|
+
if (this.contextOptions.filter((opt) => opt.key !== "all-agents").length > 1) this.selectedContext = "all-agents";
|
|
4788
|
+
}
|
|
4789
|
+
if (key === "threads") this.autoSelectLatestThread();
|
|
4790
|
+
if (key === "ag-ui-events" || key === "agents") requestAnimationFrame(() => {
|
|
4791
|
+
const scroller = this.shadowRoot?.getElementById("cpk-main-scroll");
|
|
4792
|
+
if (scroller) scroller.scrollTop = 0;
|
|
4793
|
+
});
|
|
2254
4794
|
this.contextMenuOpen = false;
|
|
2255
4795
|
this.persistState();
|
|
2256
4796
|
this.requestUpdate();
|
|
@@ -2638,9 +5178,19 @@ ${prettyEvent}</pre
|
|
|
2638
5178
|
<div class="mb-3">
|
|
2639
5179
|
<h5 class="mb-1 text-xs font-semibold text-gray-700">ID</h5>
|
|
2640
5180
|
<code
|
|
2641
|
-
class="
|
|
5181
|
+
class="font-mono text-xs font-medium text-gray-800 flex-1 truncate min-w-0"
|
|
2642
5182
|
>${id}</code
|
|
2643
5183
|
>
|
|
5184
|
+
<button
|
|
5185
|
+
type="button"
|
|
5186
|
+
class="cpk-copy-btn"
|
|
5187
|
+
@click=${(e) => {
|
|
5188
|
+
e.stopPropagation();
|
|
5189
|
+
this.copyContextValue(id, `${id}:id`);
|
|
5190
|
+
}}
|
|
5191
|
+
>
|
|
5192
|
+
${this.copiedContextItems.has(`${id}:id`) ? "✓" : "Copy"}
|
|
5193
|
+
</button>
|
|
2644
5194
|
</div>
|
|
2645
5195
|
${hasValue ? html`
|
|
2646
5196
|
<div class="mb-2 flex items-center justify-between gap-2">
|
|
@@ -2648,8 +5198,8 @@ ${prettyEvent}</pre
|
|
|
2648
5198
|
Value
|
|
2649
5199
|
</h5>
|
|
2650
5200
|
<button
|
|
2651
|
-
class="flex items-center gap-1 rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] font-medium text-gray-700 transition hover:bg-gray-50"
|
|
2652
5201
|
type="button"
|
|
5202
|
+
class="cpk-copy-btn"
|
|
2653
5203
|
@click=${(e) => {
|
|
2654
5204
|
e.stopPropagation();
|
|
2655
5205
|
this.copyContextValue(context.value, id);
|
|
@@ -2658,13 +5208,6 @@ ${prettyEvent}</pre
|
|
|
2658
5208
|
${this.copiedContextItems.has(id) ? "Copied" : "Copy JSON"}
|
|
2659
5209
|
</button>
|
|
2660
5210
|
</div>
|
|
2661
|
-
<div
|
|
2662
|
-
class="rounded-md border border-gray-200 bg-white p-3"
|
|
2663
|
-
>
|
|
2664
|
-
<pre
|
|
2665
|
-
class="overflow-auto text-xs text-gray-800 max-h-96"
|
|
2666
|
-
><code>${this.formatContextValue(context.value)}</code></pre>
|
|
2667
|
-
</div>
|
|
2668
5211
|
` : html`
|
|
2669
5212
|
<div class="flex items-center justify-center py-4 text-xs text-gray-500">
|
|
2670
5213
|
<span>No value available</span>
|
|
@@ -2677,7 +5220,7 @@ ${prettyEvent}</pre
|
|
|
2677
5220
|
}
|
|
2678
5221
|
getContextValuePreview(value) {
|
|
2679
5222
|
if (value === void 0 || value === null) return "—";
|
|
2680
|
-
if (typeof value === "string") return value.length > 50 ? `${value.
|
|
5223
|
+
if (typeof value === "string") return value.length > 50 ? `${value.slice(0, 50)}...` : value;
|
|
2681
5224
|
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2682
5225
|
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
2683
5226
|
if (typeof value === "object") {
|
|
@@ -2727,50 +5270,25 @@ ${prettyEvent}</pre
|
|
|
2727
5270
|
else this.expandedRows.add(eventId);
|
|
2728
5271
|
this.requestUpdate();
|
|
2729
5272
|
}
|
|
2730
|
-
|
|
2731
|
-
if (!this.isOpen) return nothing;
|
|
2732
|
-
this.ensureAnnouncementLoading();
|
|
5273
|
+
renderAnnouncementBanner() {
|
|
2733
5274
|
if (!this.hasUnseenAnnouncement) return nothing;
|
|
2734
|
-
if (!this.announcementLoaded && !this.
|
|
2735
|
-
class="
|
|
2736
|
-
>
|
|
2737
|
-
<div class="flex items-center gap-2 font-semibold">
|
|
2738
|
-
<span
|
|
2739
|
-
class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm"
|
|
2740
|
-
>
|
|
2741
|
-
${this.renderIcon("Megaphone")}
|
|
2742
|
-
</span>
|
|
2743
|
-
<span>Loading latest announcement…</span>
|
|
2744
|
-
</div>
|
|
2745
|
-
</div>`;
|
|
2746
|
-
if (this.announcementLoadError) return html`<div
|
|
2747
|
-
class="mx-4 my-3 rounded-xl border border-rose-200 bg-rose-50 px-4 py-3 text-sm text-rose-900 shadow-[0_12px_30px_rgba(15,23,42,0.12)]"
|
|
5275
|
+
if (!this.announcementLoaded && !this.announcementHtml) return html`<div
|
|
5276
|
+
class="flex items-center gap-2 px-4 py-3 text-sm font-semibold text-slate-800"
|
|
2748
5277
|
>
|
|
2749
|
-
<
|
|
2750
|
-
|
|
2751
|
-
|
|
2752
|
-
|
|
2753
|
-
|
|
2754
|
-
|
|
2755
|
-
<span>Announcement unavailable</span>
|
|
2756
|
-
</div>
|
|
2757
|
-
<p class="mt-2 text-xs text-rose-800">
|
|
2758
|
-
We couldn’t load the latest notice. Please try opening the inspector
|
|
2759
|
-
again.
|
|
2760
|
-
</p>
|
|
5278
|
+
<span
|
|
5279
|
+
class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm"
|
|
5280
|
+
>
|
|
5281
|
+
${this.renderIcon("Megaphone")}
|
|
5282
|
+
</span>
|
|
5283
|
+
<span>Loading latest announcement…</span>
|
|
2761
5284
|
</div>`;
|
|
2762
|
-
if (!this.
|
|
2763
|
-
|
|
2764
|
-
${this.announcementMarkdown}</pre
|
|
2765
|
-
>`;
|
|
2766
|
-
return html`<div
|
|
2767
|
-
class="mx-4 my-3 rounded-xl border border-slate-200 bg-white px-4 py-4 shadow-[0_12px_30px_rgba(15,23,42,0.12)]"
|
|
2768
|
-
>
|
|
5285
|
+
if (!this.announcementHtml) return nothing;
|
|
5286
|
+
return html`<div class="mx-4 mt-3 mb-3 rounded-xl border border-slate-200 bg-white px-4 py-3">
|
|
2769
5287
|
<div
|
|
2770
|
-
class="mb-
|
|
5288
|
+
class="mb-2 flex items-center gap-2 text-xs font-semibold text-slate-900"
|
|
2771
5289
|
>
|
|
2772
5290
|
<span
|
|
2773
|
-
class="inline-flex h-
|
|
5291
|
+
class="inline-flex h-5 w-5 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm"
|
|
2774
5292
|
>
|
|
2775
5293
|
${this.renderIcon("Megaphone")}
|
|
2776
5294
|
</span>
|
|
@@ -2781,12 +5299,30 @@ ${this.announcementMarkdown}</pre
|
|
|
2781
5299
|
@click=${this.handleDismissAnnouncement}
|
|
2782
5300
|
aria-label="Dismiss announcement"
|
|
2783
5301
|
>
|
|
2784
|
-
|
|
5302
|
+
${this.renderIcon("X")}
|
|
2785
5303
|
</button>
|
|
2786
5304
|
</div>
|
|
2787
|
-
<div class="announcement-
|
|
2788
|
-
|
|
5305
|
+
<div class="announcement-body ${this.announcementExpanded ? "announcement-body--expanded" : "announcement-body--collapsed"}">
|
|
5306
|
+
<div
|
|
5307
|
+
class="announcement-content"
|
|
5308
|
+
@click=${this.handleAnnouncementContentClick}
|
|
5309
|
+
>
|
|
5310
|
+
${unsafeHTML(this.announcementHtml)}
|
|
5311
|
+
</div>
|
|
5312
|
+
${!this.announcementExpanded ? html`
|
|
5313
|
+
<div class="announcement-fade"></div>
|
|
5314
|
+
` : nothing}
|
|
2789
5315
|
</div>
|
|
5316
|
+
<button
|
|
5317
|
+
class="announcement-toggle"
|
|
5318
|
+
type="button"
|
|
5319
|
+
@click=${() => {
|
|
5320
|
+
this.announcementExpanded = !this.announcementExpanded;
|
|
5321
|
+
this.requestUpdate();
|
|
5322
|
+
}}
|
|
5323
|
+
>
|
|
5324
|
+
${this.announcementExpanded ? "Show less ↑" : "Show more ↓"}
|
|
5325
|
+
</button>
|
|
2790
5326
|
</div>`;
|
|
2791
5327
|
}
|
|
2792
5328
|
ensureAnnouncementLoading() {
|
|
@@ -2821,14 +5357,13 @@ ${this.announcementMarkdown}</pre
|
|
|
2821
5357
|
const storedTimestamp = this.loadStoredAnnouncementTimestamp();
|
|
2822
5358
|
this.announcementTimestamp = timestamp;
|
|
2823
5359
|
this.announcementPreviewText = previewText ?? "";
|
|
2824
|
-
this.announcementMarkdown = markdown;
|
|
2825
5360
|
this.hasUnseenAnnouncement = (!storedTimestamp || storedTimestamp !== timestamp) && !!this.announcementPreviewText;
|
|
2826
5361
|
this.showAnnouncementPreview = this.hasUnseenAnnouncement;
|
|
2827
5362
|
this.announcementHtml = await this.convertMarkdownToHtml(markdown);
|
|
2828
5363
|
this.announcementLoaded = true;
|
|
2829
5364
|
this.requestUpdate();
|
|
2830
5365
|
} catch (error) {
|
|
2831
|
-
|
|
5366
|
+
console.warn("[CopilotKit Inspector] Failed to load announcement", error);
|
|
2832
5367
|
this.announcementLoaded = true;
|
|
2833
5368
|
this.requestUpdate();
|
|
2834
5369
|
}
|
|
@@ -2838,7 +5373,28 @@ ${this.announcementMarkdown}</pre
|
|
|
2838
5373
|
renderer.link = (href, title, text) => {
|
|
2839
5374
|
return `<a href="${this.escapeHtmlAttr(this.appendRefParam(href ?? ""))}" target="_blank" rel="noopener"${title ? ` title="${this.escapeHtmlAttr(title)}"` : ""}>${text}</a>`;
|
|
2840
5375
|
};
|
|
2841
|
-
|
|
5376
|
+
renderer.code = (code, lang) => {
|
|
5377
|
+
const safeLang = (lang ?? "").replace(/[^a-z0-9-]/gi, "");
|
|
5378
|
+
return `<div class="announcement-code"><pre><code${safeLang ? ` class="language-${safeLang}"` : ""}>${escapeHtml(code)}</code></pre><div class="announcement-code__copy-shield"><button type="button" class="announcement-code__copy" data-copy="${this.encodeBase64(code)}" aria-label="Copy code">Copy</button></div></div>`;
|
|
5379
|
+
};
|
|
5380
|
+
return marked.parse(markdown, {
|
|
5381
|
+
renderer,
|
|
5382
|
+
async: false
|
|
5383
|
+
});
|
|
5384
|
+
}
|
|
5385
|
+
encodeBase64(value) {
|
|
5386
|
+
if (typeof window === "undefined" || typeof window.btoa !== "function") return "";
|
|
5387
|
+
const bytes = new TextEncoder().encode(value);
|
|
5388
|
+
let binary = "";
|
|
5389
|
+
for (const b of bytes) binary += String.fromCharCode(b);
|
|
5390
|
+
return window.btoa(binary);
|
|
5391
|
+
}
|
|
5392
|
+
decodeBase64(value) {
|
|
5393
|
+
if (typeof window === "undefined" || typeof window.atob !== "function") return "";
|
|
5394
|
+
const decoded = window.atob(value);
|
|
5395
|
+
const bytes = new Uint8Array(decoded.length);
|
|
5396
|
+
for (let i = 0; i < decoded.length; i++) bytes[i] = decoded.charCodeAt(i);
|
|
5397
|
+
return new TextDecoder().decode(bytes);
|
|
2842
5398
|
}
|
|
2843
5399
|
appendRefParam(href) {
|
|
2844
5400
|
try {
|
|
@@ -2850,7 +5406,7 @@ ${this.announcementMarkdown}</pre
|
|
|
2850
5406
|
}
|
|
2851
5407
|
}
|
|
2852
5408
|
escapeHtmlAttr(value) {
|
|
2853
|
-
return value
|
|
5409
|
+
return escapeHtml(value).replace(/"/g, """).replace(/'/g, "'");
|
|
2854
5410
|
}
|
|
2855
5411
|
loadStoredAnnouncementTimestamp() {
|
|
2856
5412
|
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
@@ -2888,5 +5444,5 @@ function defineWebInspector() {
|
|
|
2888
5444
|
defineWebInspector();
|
|
2889
5445
|
|
|
2890
5446
|
//#endregion
|
|
2891
|
-
export { WEB_INSPECTOR_TAG, WebInspectorElement, defineWebInspector };
|
|
5447
|
+
export { WEB_INSPECTOR_TAG, WebInspectorElement, defineWebInspector, ɵCpkThreadDetails };
|
|
2892
5448
|
//# sourceMappingURL=index.mjs.map
|