@copilotkit/web-inspector 1.55.0-next.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +454 -0
- package/LICENSE +21 -0
- package/dist/assets/inspector-logo-icon.cjs +12 -0
- package/dist/assets/inspector-logo-icon.cjs.map +1 -0
- package/dist/assets/inspector-logo-icon.mjs +6 -0
- package/dist/assets/inspector-logo-icon.mjs.map +1 -0
- package/dist/assets/inspector-logo.cjs +12 -0
- package/dist/assets/inspector-logo.cjs.map +1 -0
- package/dist/assets/inspector-logo.mjs +6 -0
- package/dist/assets/inspector-logo.mjs.map +1 -0
- package/dist/index.cjs +2862 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +207 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +207 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +2859 -0
- package/dist/index.mjs.map +1 -0
- package/dist/index.umd.js +3030 -0
- package/dist/index.umd.js.map +1 -0
- package/dist/lib/context-helpers.cjs +82 -0
- package/dist/lib/context-helpers.cjs.map +1 -0
- package/dist/lib/context-helpers.mjs +75 -0
- package/dist/lib/context-helpers.mjs.map +1 -0
- package/dist/lib/persistence.cjs +62 -0
- package/dist/lib/persistence.cjs.map +1 -0
- package/dist/lib/persistence.mjs +56 -0
- package/dist/lib/persistence.mjs.map +1 -0
- package/dist/styles/generated.cjs +12 -0
- package/dist/styles/generated.cjs.map +1 -0
- package/dist/styles/generated.mjs +6 -0
- package/dist/styles/generated.mjs.map +1 -0
- package/eslint.config.mjs +3 -0
- package/package.json +54 -0
- package/src/__tests__/web-inspector.spec.ts +187 -0
- package/src/assets/inspector-logo-icon.svg +8 -0
- package/src/assets/inspector-logo.svg +40 -0
- package/src/components.d.ts +20 -0
- package/src/index.ts +4284 -0
- package/src/lib/context-helpers.ts +166 -0
- package/src/lib/persistence.ts +109 -0
- package/src/lib/types.ts +19 -0
- package/src/styles/generated.css +2 -0
- package/src/styles/tailwind.css +23 -0
- package/src/types/css.d.ts +4 -0
- package/src/types/svg.d.ts +4 -0
- package/tsconfig.json +14 -0
- package/tsdown.config.ts +45 -0
- package/vitest.config.ts +10 -0
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,2862 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
2
|
+
const require_generated = require('./styles/generated.cjs');
|
|
3
|
+
const require_inspector_logo = require('./assets/inspector-logo.cjs');
|
|
4
|
+
const require_inspector_logo_icon = require('./assets/inspector-logo-icon.cjs');
|
|
5
|
+
const require_context_helpers = require('./lib/context-helpers.cjs');
|
|
6
|
+
const require_persistence = require('./lib/persistence.cjs');
|
|
7
|
+
let lit = require("lit");
|
|
8
|
+
let lit_directives_style_map_js = require("lit/directives/style-map.js");
|
|
9
|
+
let lit_directives_unsafe_html_js = require("lit/directives/unsafe-html.js");
|
|
10
|
+
let marked = require("marked");
|
|
11
|
+
let lucide = require("lucide");
|
|
12
|
+
let _copilotkit_core = require("@copilotkit/core");
|
|
13
|
+
|
|
14
|
+
//#region src/index.ts
|
|
15
|
+
const WEB_INSPECTOR_TAG = "cpk-web-inspector";
|
|
16
|
+
const EDGE_MARGIN = 16;
|
|
17
|
+
const DRAG_THRESHOLD = 6;
|
|
18
|
+
const MIN_WINDOW_WIDTH = 600;
|
|
19
|
+
const MIN_WINDOW_WIDTH_DOCKED_LEFT = 420;
|
|
20
|
+
const MIN_WINDOW_HEIGHT = 200;
|
|
21
|
+
const INSPECTOR_STORAGE_KEY = "cpk:inspector:state";
|
|
22
|
+
const ANNOUNCEMENT_STORAGE_KEY = "cpk:inspector:announcements";
|
|
23
|
+
const ANNOUNCEMENT_URL = "https://cdn.copilotkit.ai/announcements.json";
|
|
24
|
+
const DEFAULT_BUTTON_SIZE = {
|
|
25
|
+
width: 48,
|
|
26
|
+
height: 48
|
|
27
|
+
};
|
|
28
|
+
const DEFAULT_WINDOW_SIZE = {
|
|
29
|
+
width: 840,
|
|
30
|
+
height: 560
|
|
31
|
+
};
|
|
32
|
+
const DOCKED_LEFT_WIDTH = 500;
|
|
33
|
+
const MAX_AGENT_EVENTS = 200;
|
|
34
|
+
const MAX_TOTAL_EVENTS = 500;
|
|
35
|
+
const AGENT_EVENT_TYPES = [
|
|
36
|
+
"RUN_STARTED",
|
|
37
|
+
"RUN_FINISHED",
|
|
38
|
+
"RUN_ERROR",
|
|
39
|
+
"TEXT_MESSAGE_START",
|
|
40
|
+
"TEXT_MESSAGE_CONTENT",
|
|
41
|
+
"TEXT_MESSAGE_END",
|
|
42
|
+
"TOOL_CALL_START",
|
|
43
|
+
"TOOL_CALL_ARGS",
|
|
44
|
+
"TOOL_CALL_END",
|
|
45
|
+
"TOOL_CALL_RESULT",
|
|
46
|
+
"STATE_SNAPSHOT",
|
|
47
|
+
"STATE_DELTA",
|
|
48
|
+
"MESSAGES_SNAPSHOT",
|
|
49
|
+
"RAW_EVENT",
|
|
50
|
+
"CUSTOM_EVENT",
|
|
51
|
+
"REASONING_START",
|
|
52
|
+
"REASONING_MESSAGE_START",
|
|
53
|
+
"REASONING_MESSAGE_CONTENT",
|
|
54
|
+
"REASONING_MESSAGE_END",
|
|
55
|
+
"REASONING_END",
|
|
56
|
+
"REASONING_ENCRYPTED_VALUE"
|
|
57
|
+
];
|
|
58
|
+
var WebInspectorElement = class extends lit.LitElement {
|
|
59
|
+
constructor(..._args) {
|
|
60
|
+
super(..._args);
|
|
61
|
+
this._core = null;
|
|
62
|
+
this.coreSubscriber = null;
|
|
63
|
+
this.coreUnsubscribe = null;
|
|
64
|
+
this.runtimeStatus = null;
|
|
65
|
+
this.coreProperties = {};
|
|
66
|
+
this.lastCoreError = null;
|
|
67
|
+
this.agentSubscriptions = /* @__PURE__ */ new Map();
|
|
68
|
+
this.agentEvents = /* @__PURE__ */ new Map();
|
|
69
|
+
this.agentMessages = /* @__PURE__ */ new Map();
|
|
70
|
+
this.agentStates = /* @__PURE__ */ new Map();
|
|
71
|
+
this.flattenedEvents = [];
|
|
72
|
+
this.eventCounter = 0;
|
|
73
|
+
this.contextStore = {};
|
|
74
|
+
this.pointerId = null;
|
|
75
|
+
this.dragStart = null;
|
|
76
|
+
this.dragOffset = {
|
|
77
|
+
x: 0,
|
|
78
|
+
y: 0
|
|
79
|
+
};
|
|
80
|
+
this.isDragging = false;
|
|
81
|
+
this.pointerContext = null;
|
|
82
|
+
this.isOpen = false;
|
|
83
|
+
this.draggedDuringInteraction = false;
|
|
84
|
+
this.ignoreNextButtonClick = false;
|
|
85
|
+
this.selectedMenu = "ag-ui-events";
|
|
86
|
+
this.contextMenuOpen = false;
|
|
87
|
+
this.dockMode = "floating";
|
|
88
|
+
this.previousBodyMargins = null;
|
|
89
|
+
this.transitionTimeoutId = null;
|
|
90
|
+
this.pendingSelectedContext = null;
|
|
91
|
+
this.autoAttachCore = true;
|
|
92
|
+
this.attemptedAutoAttach = false;
|
|
93
|
+
this.cachedTools = [];
|
|
94
|
+
this.toolSignature = "";
|
|
95
|
+
this.eventFilterText = "";
|
|
96
|
+
this.eventTypeFilter = "all";
|
|
97
|
+
this.announcementMarkdown = null;
|
|
98
|
+
this.announcementHtml = null;
|
|
99
|
+
this.announcementTimestamp = null;
|
|
100
|
+
this.announcementPreviewText = null;
|
|
101
|
+
this.hasUnseenAnnouncement = false;
|
|
102
|
+
this.announcementLoaded = false;
|
|
103
|
+
this.announcementLoadError = null;
|
|
104
|
+
this.announcementPromise = null;
|
|
105
|
+
this.showAnnouncementPreview = true;
|
|
106
|
+
this.contextState = {
|
|
107
|
+
button: {
|
|
108
|
+
position: {
|
|
109
|
+
x: EDGE_MARGIN,
|
|
110
|
+
y: EDGE_MARGIN
|
|
111
|
+
},
|
|
112
|
+
size: { ...DEFAULT_BUTTON_SIZE },
|
|
113
|
+
anchor: {
|
|
114
|
+
horizontal: "right",
|
|
115
|
+
vertical: "top"
|
|
116
|
+
},
|
|
117
|
+
anchorOffset: {
|
|
118
|
+
x: EDGE_MARGIN,
|
|
119
|
+
y: EDGE_MARGIN
|
|
120
|
+
}
|
|
121
|
+
},
|
|
122
|
+
window: {
|
|
123
|
+
position: {
|
|
124
|
+
x: EDGE_MARGIN,
|
|
125
|
+
y: EDGE_MARGIN
|
|
126
|
+
},
|
|
127
|
+
size: { ...DEFAULT_WINDOW_SIZE },
|
|
128
|
+
anchor: {
|
|
129
|
+
horizontal: "right",
|
|
130
|
+
vertical: "top"
|
|
131
|
+
},
|
|
132
|
+
anchorOffset: {
|
|
133
|
+
x: EDGE_MARGIN,
|
|
134
|
+
y: EDGE_MARGIN
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
};
|
|
138
|
+
this.hasCustomPosition = {
|
|
139
|
+
button: false,
|
|
140
|
+
window: false
|
|
141
|
+
};
|
|
142
|
+
this.resizePointerId = null;
|
|
143
|
+
this.resizeStart = null;
|
|
144
|
+
this.resizeInitialSize = null;
|
|
145
|
+
this.isResizing = false;
|
|
146
|
+
this.menuItems = [
|
|
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
|
+
];
|
|
168
|
+
this.handlePointerDown = (event) => {
|
|
169
|
+
if (this.dockMode !== "floating" && this.isOpen) return;
|
|
170
|
+
const target = event.currentTarget;
|
|
171
|
+
const context = target?.dataset.dragContext === "window" ? "window" : "button";
|
|
172
|
+
const eventTarget = event.target;
|
|
173
|
+
if (context === "window" && eventTarget?.closest("button")) return;
|
|
174
|
+
this.pointerContext = context;
|
|
175
|
+
this.measureContext(context);
|
|
176
|
+
event.preventDefault();
|
|
177
|
+
this.pointerId = event.pointerId;
|
|
178
|
+
this.dragStart = {
|
|
179
|
+
x: event.clientX,
|
|
180
|
+
y: event.clientY
|
|
181
|
+
};
|
|
182
|
+
const state = this.contextState[context];
|
|
183
|
+
this.dragOffset = {
|
|
184
|
+
x: event.clientX - state.position.x,
|
|
185
|
+
y: event.clientY - state.position.y
|
|
186
|
+
};
|
|
187
|
+
this.isDragging = false;
|
|
188
|
+
this.draggedDuringInteraction = false;
|
|
189
|
+
this.ignoreNextButtonClick = false;
|
|
190
|
+
target?.setPointerCapture?.(this.pointerId);
|
|
191
|
+
};
|
|
192
|
+
this.handlePointerMove = (event) => {
|
|
193
|
+
if (this.pointerId !== event.pointerId || !this.dragStart || !this.pointerContext) return;
|
|
194
|
+
const distance = Math.hypot(event.clientX - this.dragStart.x, event.clientY - this.dragStart.y);
|
|
195
|
+
if (!this.isDragging && distance < DRAG_THRESHOLD) return;
|
|
196
|
+
event.preventDefault();
|
|
197
|
+
this.setDragging(true);
|
|
198
|
+
this.draggedDuringInteraction = true;
|
|
199
|
+
const desired = {
|
|
200
|
+
x: event.clientX - this.dragOffset.x,
|
|
201
|
+
y: event.clientY - this.dragOffset.y
|
|
202
|
+
};
|
|
203
|
+
const constrained = this.constrainToViewport(desired, this.pointerContext);
|
|
204
|
+
this.contextState[this.pointerContext].position = constrained;
|
|
205
|
+
this.updateHostTransform(this.pointerContext);
|
|
206
|
+
};
|
|
207
|
+
this.handlePointerUp = (event) => {
|
|
208
|
+
if (this.pointerId !== event.pointerId) return;
|
|
209
|
+
const target = event.currentTarget;
|
|
210
|
+
if (target?.hasPointerCapture(this.pointerId)) target.releasePointerCapture(this.pointerId);
|
|
211
|
+
const context = this.pointerContext ?? this.activeContext;
|
|
212
|
+
if (this.isDragging && this.pointerContext) {
|
|
213
|
+
event.preventDefault();
|
|
214
|
+
this.setDragging(false);
|
|
215
|
+
if (this.pointerContext === "window") {
|
|
216
|
+
this.updateAnchorFromPosition(this.pointerContext);
|
|
217
|
+
this.hasCustomPosition.window = true;
|
|
218
|
+
this.applyAnchorPosition(this.pointerContext);
|
|
219
|
+
} else if (this.pointerContext === "button") {
|
|
220
|
+
this.snapButtonToCorner();
|
|
221
|
+
this.hasCustomPosition.button = true;
|
|
222
|
+
if (this.draggedDuringInteraction) this.ignoreNextButtonClick = true;
|
|
223
|
+
}
|
|
224
|
+
} else if (context === "button" && !this.isOpen && !this.draggedDuringInteraction) this.openInspector();
|
|
225
|
+
this.resetPointerTracking();
|
|
226
|
+
};
|
|
227
|
+
this.handlePointerCancel = (event) => {
|
|
228
|
+
if (this.pointerId !== event.pointerId) return;
|
|
229
|
+
const target = event.currentTarget;
|
|
230
|
+
if (target?.hasPointerCapture(this.pointerId)) target.releasePointerCapture(this.pointerId);
|
|
231
|
+
this.resetPointerTracking();
|
|
232
|
+
};
|
|
233
|
+
this.handleButtonClick = (event) => {
|
|
234
|
+
if (this.isDragging) {
|
|
235
|
+
event.preventDefault();
|
|
236
|
+
return;
|
|
237
|
+
}
|
|
238
|
+
if (this.ignoreNextButtonClick) {
|
|
239
|
+
event.preventDefault();
|
|
240
|
+
this.ignoreNextButtonClick = false;
|
|
241
|
+
return;
|
|
242
|
+
}
|
|
243
|
+
if (!this.isOpen) {
|
|
244
|
+
event.preventDefault();
|
|
245
|
+
this.openInspector();
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
this.handleClosePointerDown = (event) => {
|
|
249
|
+
event.stopPropagation();
|
|
250
|
+
event.preventDefault();
|
|
251
|
+
};
|
|
252
|
+
this.handleCloseClick = () => {
|
|
253
|
+
this.closeInspector();
|
|
254
|
+
};
|
|
255
|
+
this.handleResizePointerDown = (event) => {
|
|
256
|
+
event.stopPropagation();
|
|
257
|
+
event.preventDefault();
|
|
258
|
+
this.hasCustomPosition.window = true;
|
|
259
|
+
this.isResizing = true;
|
|
260
|
+
this.resizePointerId = event.pointerId;
|
|
261
|
+
this.resizeStart = {
|
|
262
|
+
x: event.clientX,
|
|
263
|
+
y: event.clientY
|
|
264
|
+
};
|
|
265
|
+
this.resizeInitialSize = { ...this.contextState.window.size };
|
|
266
|
+
if (document.body && this.dockMode !== "floating") document.body.style.transition = "";
|
|
267
|
+
event.currentTarget?.setPointerCapture?.(event.pointerId);
|
|
268
|
+
};
|
|
269
|
+
this.handleResizePointerMove = (event) => {
|
|
270
|
+
if (!this.isResizing || this.resizePointerId !== event.pointerId || !this.resizeStart || !this.resizeInitialSize) return;
|
|
271
|
+
event.preventDefault();
|
|
272
|
+
const deltaX = event.clientX - this.resizeStart.x;
|
|
273
|
+
const deltaY = event.clientY - this.resizeStart.y;
|
|
274
|
+
const state = this.contextState.window;
|
|
275
|
+
if (this.dockMode === "docked-left") {
|
|
276
|
+
state.size = this.clampWindowSize({
|
|
277
|
+
width: this.resizeInitialSize.width + deltaX,
|
|
278
|
+
height: state.size.height
|
|
279
|
+
});
|
|
280
|
+
if (document.body) document.body.style.marginLeft = `${state.size.width}px`;
|
|
281
|
+
} else {
|
|
282
|
+
state.size = this.clampWindowSize({
|
|
283
|
+
width: this.resizeInitialSize.width + deltaX,
|
|
284
|
+
height: this.resizeInitialSize.height + deltaY
|
|
285
|
+
});
|
|
286
|
+
this.keepPositionWithinViewport("window");
|
|
287
|
+
this.updateAnchorFromPosition("window");
|
|
288
|
+
}
|
|
289
|
+
this.requestUpdate();
|
|
290
|
+
this.updateHostTransform("window");
|
|
291
|
+
};
|
|
292
|
+
this.handleResizePointerUp = (event) => {
|
|
293
|
+
if (this.resizePointerId !== event.pointerId) return;
|
|
294
|
+
const target = event.currentTarget;
|
|
295
|
+
if (target?.hasPointerCapture(this.resizePointerId)) target.releasePointerCapture(this.resizePointerId);
|
|
296
|
+
if (this.dockMode === "floating") {
|
|
297
|
+
this.updateAnchorFromPosition("window");
|
|
298
|
+
this.applyAnchorPosition("window");
|
|
299
|
+
}
|
|
300
|
+
this.persistState();
|
|
301
|
+
this.resetResizeTracking();
|
|
302
|
+
};
|
|
303
|
+
this.handleResizePointerCancel = (event) => {
|
|
304
|
+
if (this.resizePointerId !== event.pointerId) return;
|
|
305
|
+
const target = event.currentTarget;
|
|
306
|
+
if (target?.hasPointerCapture(this.resizePointerId)) target.releasePointerCapture(this.resizePointerId);
|
|
307
|
+
if (this.dockMode === "floating") {
|
|
308
|
+
this.updateAnchorFromPosition("window");
|
|
309
|
+
this.applyAnchorPosition("window");
|
|
310
|
+
}
|
|
311
|
+
this.persistState();
|
|
312
|
+
this.resetResizeTracking();
|
|
313
|
+
};
|
|
314
|
+
this.handleResize = () => {
|
|
315
|
+
this.measureContext("button");
|
|
316
|
+
this.applyAnchorPosition("button");
|
|
317
|
+
this.measureContext("window");
|
|
318
|
+
if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
|
|
319
|
+
else this.centerContext("window");
|
|
320
|
+
this.updateHostTransform();
|
|
321
|
+
};
|
|
322
|
+
this.contextOptions = [{
|
|
323
|
+
key: "all-agents",
|
|
324
|
+
label: "All Agents"
|
|
325
|
+
}];
|
|
326
|
+
this.selectedContext = "all-agents";
|
|
327
|
+
this.expandedRows = /* @__PURE__ */ new Set();
|
|
328
|
+
this.copiedEvents = /* @__PURE__ */ new Set();
|
|
329
|
+
this.expandedTools = /* @__PURE__ */ new Set();
|
|
330
|
+
this.expandedContextItems = /* @__PURE__ */ new Set();
|
|
331
|
+
this.copiedContextItems = /* @__PURE__ */ new Set();
|
|
332
|
+
this.handleClearEvents = () => {
|
|
333
|
+
if (this.selectedContext === "all-agents") {
|
|
334
|
+
this.agentEvents.clear();
|
|
335
|
+
this.flattenedEvents = [];
|
|
336
|
+
} else {
|
|
337
|
+
this.agentEvents.delete(this.selectedContext);
|
|
338
|
+
this.flattenedEvents = this.flattenedEvents.filter((event) => event.agentId !== this.selectedContext);
|
|
339
|
+
}
|
|
340
|
+
this.expandedRows.clear();
|
|
341
|
+
this.copiedEvents.clear();
|
|
342
|
+
this.requestUpdate();
|
|
343
|
+
};
|
|
344
|
+
this.handleGlobalPointerDown = (event) => {
|
|
345
|
+
if (!this.contextMenuOpen) return;
|
|
346
|
+
if (!event.composedPath().some((node) => {
|
|
347
|
+
return node instanceof HTMLElement && node.dataset?.contextDropdownRoot === "true";
|
|
348
|
+
})) {
|
|
349
|
+
this.contextMenuOpen = false;
|
|
350
|
+
this.requestUpdate();
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
this.handleDismissAnnouncement = () => {
|
|
354
|
+
this.markAnnouncementSeen();
|
|
355
|
+
};
|
|
356
|
+
}
|
|
357
|
+
static {
|
|
358
|
+
this.properties = {
|
|
359
|
+
core: { attribute: false },
|
|
360
|
+
autoAttachCore: {
|
|
361
|
+
type: Boolean,
|
|
362
|
+
attribute: "auto-attach-core"
|
|
363
|
+
}
|
|
364
|
+
};
|
|
365
|
+
}
|
|
366
|
+
get core() {
|
|
367
|
+
return this._core;
|
|
368
|
+
}
|
|
369
|
+
set core(value) {
|
|
370
|
+
const oldValue = this._core;
|
|
371
|
+
if (oldValue === value) return;
|
|
372
|
+
this.detachFromCore();
|
|
373
|
+
this._core = value ?? null;
|
|
374
|
+
this.requestUpdate("core", oldValue);
|
|
375
|
+
if (this._core) this.attachToCore(this._core);
|
|
376
|
+
}
|
|
377
|
+
attachToCore(core) {
|
|
378
|
+
this.runtimeStatus = core.runtimeConnectionStatus;
|
|
379
|
+
this.coreProperties = core.properties;
|
|
380
|
+
this.lastCoreError = null;
|
|
381
|
+
this.coreSubscriber = {
|
|
382
|
+
onRuntimeConnectionStatusChanged: ({ status }) => {
|
|
383
|
+
this.runtimeStatus = status;
|
|
384
|
+
this.requestUpdate();
|
|
385
|
+
},
|
|
386
|
+
onPropertiesChanged: ({ properties }) => {
|
|
387
|
+
this.coreProperties = properties;
|
|
388
|
+
this.requestUpdate();
|
|
389
|
+
},
|
|
390
|
+
onError: ({ code, error }) => {
|
|
391
|
+
this.lastCoreError = {
|
|
392
|
+
code,
|
|
393
|
+
message: error.message
|
|
394
|
+
};
|
|
395
|
+
this.requestUpdate();
|
|
396
|
+
},
|
|
397
|
+
onAgentsChanged: ({ agents }) => {
|
|
398
|
+
this.processAgentsChanged(agents);
|
|
399
|
+
},
|
|
400
|
+
onContextChanged: ({ context }) => {
|
|
401
|
+
this.contextStore = this.normalizeContextStore(context);
|
|
402
|
+
this.requestUpdate();
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;
|
|
406
|
+
this.processAgentsChanged(core.agents);
|
|
407
|
+
if (core.context) this.contextStore = this.normalizeContextStore(core.context);
|
|
408
|
+
}
|
|
409
|
+
detachFromCore() {
|
|
410
|
+
if (this.coreUnsubscribe) {
|
|
411
|
+
this.coreUnsubscribe();
|
|
412
|
+
this.coreUnsubscribe = null;
|
|
413
|
+
}
|
|
414
|
+
this.coreSubscriber = null;
|
|
415
|
+
this.runtimeStatus = null;
|
|
416
|
+
this.lastCoreError = null;
|
|
417
|
+
this.coreProperties = {};
|
|
418
|
+
this.cachedTools = [];
|
|
419
|
+
this.toolSignature = "";
|
|
420
|
+
this.teardownAgentSubscriptions();
|
|
421
|
+
}
|
|
422
|
+
teardownAgentSubscriptions() {
|
|
423
|
+
for (const unsubscribe of this.agentSubscriptions.values()) unsubscribe();
|
|
424
|
+
this.agentSubscriptions.clear();
|
|
425
|
+
this.agentEvents.clear();
|
|
426
|
+
this.agentMessages.clear();
|
|
427
|
+
this.agentStates.clear();
|
|
428
|
+
this.flattenedEvents = [];
|
|
429
|
+
this.eventCounter = 0;
|
|
430
|
+
}
|
|
431
|
+
processAgentsChanged(agents) {
|
|
432
|
+
const seenAgentIds = /* @__PURE__ */ new Set();
|
|
433
|
+
for (const agent of Object.values(agents)) {
|
|
434
|
+
if (!agent?.agentId) continue;
|
|
435
|
+
seenAgentIds.add(agent.agentId);
|
|
436
|
+
this.subscribeToAgent(agent);
|
|
437
|
+
}
|
|
438
|
+
for (const agentId of Array.from(this.agentSubscriptions.keys())) if (!seenAgentIds.has(agentId)) {
|
|
439
|
+
this.unsubscribeFromAgent(agentId);
|
|
440
|
+
this.agentEvents.delete(agentId);
|
|
441
|
+
this.agentMessages.delete(agentId);
|
|
442
|
+
this.agentStates.delete(agentId);
|
|
443
|
+
}
|
|
444
|
+
this.updateContextOptions(seenAgentIds);
|
|
445
|
+
this.refreshToolsSnapshot();
|
|
446
|
+
this.requestUpdate();
|
|
447
|
+
}
|
|
448
|
+
refreshToolsSnapshot() {
|
|
449
|
+
if (!this._core) {
|
|
450
|
+
if (this.cachedTools.length > 0) {
|
|
451
|
+
this.cachedTools = [];
|
|
452
|
+
this.toolSignature = "";
|
|
453
|
+
this.requestUpdate();
|
|
454
|
+
}
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
const tools = this.extractToolsFromAgents();
|
|
458
|
+
const signature = JSON.stringify(tools.map((tool) => ({
|
|
459
|
+
agentId: tool.agentId,
|
|
460
|
+
name: tool.name,
|
|
461
|
+
type: tool.type,
|
|
462
|
+
hasDescription: Boolean(tool.description),
|
|
463
|
+
hasParameters: Boolean(tool.parameters)
|
|
464
|
+
})));
|
|
465
|
+
if (signature !== this.toolSignature) {
|
|
466
|
+
this.toolSignature = signature;
|
|
467
|
+
this.cachedTools = tools;
|
|
468
|
+
this.requestUpdate();
|
|
469
|
+
}
|
|
470
|
+
}
|
|
471
|
+
tryAutoAttachCore() {
|
|
472
|
+
if (this.attemptedAutoAttach || this._core || !this.autoAttachCore || typeof window === "undefined") return;
|
|
473
|
+
this.attemptedAutoAttach = true;
|
|
474
|
+
const globalWindow = window;
|
|
475
|
+
const foundCore = [
|
|
476
|
+
globalWindow.__COPILOTKIT_CORE__,
|
|
477
|
+
globalWindow.copilotkit?.core,
|
|
478
|
+
globalWindow.copilotkitCore
|
|
479
|
+
].find((candidate) => !!candidate && typeof candidate === "object");
|
|
480
|
+
if (foundCore) this.core = foundCore;
|
|
481
|
+
}
|
|
482
|
+
subscribeToAgent(agent) {
|
|
483
|
+
if (!agent.agentId) return;
|
|
484
|
+
const agentId = agent.agentId;
|
|
485
|
+
this.unsubscribeFromAgent(agentId);
|
|
486
|
+
const { unsubscribe } = agent.subscribe({
|
|
487
|
+
onRunStartedEvent: ({ event }) => {
|
|
488
|
+
this.recordAgentEvent(agentId, "RUN_STARTED", event);
|
|
489
|
+
},
|
|
490
|
+
onRunFinishedEvent: ({ event, result }) => {
|
|
491
|
+
this.recordAgentEvent(agentId, "RUN_FINISHED", {
|
|
492
|
+
event,
|
|
493
|
+
result
|
|
494
|
+
});
|
|
495
|
+
},
|
|
496
|
+
onRunErrorEvent: ({ event }) => {
|
|
497
|
+
this.recordAgentEvent(agentId, "RUN_ERROR", event);
|
|
498
|
+
},
|
|
499
|
+
onTextMessageStartEvent: ({ event }) => {
|
|
500
|
+
this.recordAgentEvent(agentId, "TEXT_MESSAGE_START", event);
|
|
501
|
+
},
|
|
502
|
+
onTextMessageContentEvent: ({ event, textMessageBuffer }) => {
|
|
503
|
+
this.recordAgentEvent(agentId, "TEXT_MESSAGE_CONTENT", {
|
|
504
|
+
event,
|
|
505
|
+
textMessageBuffer
|
|
506
|
+
});
|
|
507
|
+
},
|
|
508
|
+
onTextMessageEndEvent: ({ event, textMessageBuffer }) => {
|
|
509
|
+
this.recordAgentEvent(agentId, "TEXT_MESSAGE_END", {
|
|
510
|
+
event,
|
|
511
|
+
textMessageBuffer
|
|
512
|
+
});
|
|
513
|
+
},
|
|
514
|
+
onToolCallStartEvent: ({ event }) => {
|
|
515
|
+
this.recordAgentEvent(agentId, "TOOL_CALL_START", event);
|
|
516
|
+
},
|
|
517
|
+
onToolCallArgsEvent: ({ event, toolCallBuffer, toolCallName, partialToolCallArgs }) => {
|
|
518
|
+
this.recordAgentEvent(agentId, "TOOL_CALL_ARGS", {
|
|
519
|
+
event,
|
|
520
|
+
toolCallBuffer,
|
|
521
|
+
toolCallName,
|
|
522
|
+
partialToolCallArgs
|
|
523
|
+
});
|
|
524
|
+
},
|
|
525
|
+
onToolCallEndEvent: ({ event, toolCallArgs, toolCallName }) => {
|
|
526
|
+
this.recordAgentEvent(agentId, "TOOL_CALL_END", {
|
|
527
|
+
event,
|
|
528
|
+
toolCallArgs,
|
|
529
|
+
toolCallName
|
|
530
|
+
});
|
|
531
|
+
},
|
|
532
|
+
onToolCallResultEvent: ({ event }) => {
|
|
533
|
+
this.recordAgentEvent(agentId, "TOOL_CALL_RESULT", event);
|
|
534
|
+
},
|
|
535
|
+
onStateSnapshotEvent: ({ event }) => {
|
|
536
|
+
this.recordAgentEvent(agentId, "STATE_SNAPSHOT", event);
|
|
537
|
+
this.syncAgentState(agent);
|
|
538
|
+
},
|
|
539
|
+
onStateDeltaEvent: ({ event }) => {
|
|
540
|
+
this.recordAgentEvent(agentId, "STATE_DELTA", event);
|
|
541
|
+
this.syncAgentState(agent);
|
|
542
|
+
},
|
|
543
|
+
onMessagesSnapshotEvent: ({ event }) => {
|
|
544
|
+
this.recordAgentEvent(agentId, "MESSAGES_SNAPSHOT", event);
|
|
545
|
+
this.syncAgentMessages(agent);
|
|
546
|
+
},
|
|
547
|
+
onMessagesChanged: () => {
|
|
548
|
+
this.syncAgentMessages(agent);
|
|
549
|
+
},
|
|
550
|
+
onRawEvent: ({ event }) => {
|
|
551
|
+
this.recordAgentEvent(agentId, "RAW_EVENT", event);
|
|
552
|
+
},
|
|
553
|
+
onCustomEvent: ({ event }) => {
|
|
554
|
+
this.recordAgentEvent(agentId, "CUSTOM_EVENT", event);
|
|
555
|
+
},
|
|
556
|
+
onReasoningStartEvent: ({ event }) => {
|
|
557
|
+
this.recordAgentEvent(agentId, "REASONING_START", event);
|
|
558
|
+
},
|
|
559
|
+
onReasoningMessageStartEvent: ({ event }) => {
|
|
560
|
+
this.recordAgentEvent(agentId, "REASONING_MESSAGE_START", event);
|
|
561
|
+
},
|
|
562
|
+
onReasoningMessageContentEvent: ({ event, reasoningMessageBuffer }) => {
|
|
563
|
+
this.recordAgentEvent(agentId, "REASONING_MESSAGE_CONTENT", {
|
|
564
|
+
event,
|
|
565
|
+
reasoningMessageBuffer
|
|
566
|
+
});
|
|
567
|
+
},
|
|
568
|
+
onReasoningMessageEndEvent: ({ event, reasoningMessageBuffer }) => {
|
|
569
|
+
this.recordAgentEvent(agentId, "REASONING_MESSAGE_END", {
|
|
570
|
+
event,
|
|
571
|
+
reasoningMessageBuffer
|
|
572
|
+
});
|
|
573
|
+
},
|
|
574
|
+
onReasoningEndEvent: ({ event }) => {
|
|
575
|
+
this.recordAgentEvent(agentId, "REASONING_END", event);
|
|
576
|
+
},
|
|
577
|
+
onReasoningEncryptedValueEvent: ({ event }) => {
|
|
578
|
+
this.recordAgentEvent(agentId, "REASONING_ENCRYPTED_VALUE", event);
|
|
579
|
+
}
|
|
580
|
+
});
|
|
581
|
+
this.agentSubscriptions.set(agentId, unsubscribe);
|
|
582
|
+
this.syncAgentMessages(agent);
|
|
583
|
+
this.syncAgentState(agent);
|
|
584
|
+
if (!this.agentEvents.has(agentId)) this.agentEvents.set(agentId, []);
|
|
585
|
+
}
|
|
586
|
+
unsubscribeFromAgent(agentId) {
|
|
587
|
+
const unsubscribe = this.agentSubscriptions.get(agentId);
|
|
588
|
+
if (unsubscribe) {
|
|
589
|
+
unsubscribe();
|
|
590
|
+
this.agentSubscriptions.delete(agentId);
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
recordAgentEvent(agentId, type, payload) {
|
|
594
|
+
const eventId = `${agentId}:${++this.eventCounter}`;
|
|
595
|
+
const normalizedPayload = this.normalizeEventPayload(type, payload);
|
|
596
|
+
const event = {
|
|
597
|
+
id: eventId,
|
|
598
|
+
agentId,
|
|
599
|
+
type,
|
|
600
|
+
timestamp: Date.now(),
|
|
601
|
+
payload: normalizedPayload
|
|
602
|
+
};
|
|
603
|
+
const nextAgentEvents = [event, ...this.agentEvents.get(agentId) ?? []].slice(0, MAX_AGENT_EVENTS);
|
|
604
|
+
this.agentEvents.set(agentId, nextAgentEvents);
|
|
605
|
+
this.flattenedEvents = [event, ...this.flattenedEvents].slice(0, MAX_TOTAL_EVENTS);
|
|
606
|
+
this.refreshToolsSnapshot();
|
|
607
|
+
this.requestUpdate();
|
|
608
|
+
}
|
|
609
|
+
syncAgentMessages(agent) {
|
|
610
|
+
if (!agent?.agentId) return;
|
|
611
|
+
const messages = this.normalizeAgentMessages(agent.messages);
|
|
612
|
+
if (messages) this.agentMessages.set(agent.agentId, messages);
|
|
613
|
+
else this.agentMessages.delete(agent.agentId);
|
|
614
|
+
this.requestUpdate();
|
|
615
|
+
}
|
|
616
|
+
syncAgentState(agent) {
|
|
617
|
+
if (!agent?.agentId) return;
|
|
618
|
+
const state = agent.state;
|
|
619
|
+
if (state === void 0 || state === null) this.agentStates.delete(agent.agentId);
|
|
620
|
+
else this.agentStates.set(agent.agentId, this.sanitizeForLogging(state));
|
|
621
|
+
this.requestUpdate();
|
|
622
|
+
}
|
|
623
|
+
updateContextOptions(agentIds) {
|
|
624
|
+
const nextOptions = [{
|
|
625
|
+
key: "all-agents",
|
|
626
|
+
label: "All Agents"
|
|
627
|
+
}, ...Array.from(agentIds).sort((a, b) => a.localeCompare(b)).map((id) => ({
|
|
628
|
+
key: id,
|
|
629
|
+
label: id
|
|
630
|
+
}))];
|
|
631
|
+
if (this.contextOptions.length !== nextOptions.length || this.contextOptions.some((option, index) => option.key !== nextOptions[index]?.key)) this.contextOptions = nextOptions;
|
|
632
|
+
const pendingContext = this.pendingSelectedContext;
|
|
633
|
+
if (pendingContext) {
|
|
634
|
+
if (pendingContext === "all-agents" || agentIds.has(pendingContext)) {
|
|
635
|
+
if (this.selectedContext !== pendingContext) {
|
|
636
|
+
this.selectedContext = pendingContext;
|
|
637
|
+
this.expandedRows.clear();
|
|
638
|
+
}
|
|
639
|
+
this.pendingSelectedContext = null;
|
|
640
|
+
} else if (agentIds.size > 0) this.pendingSelectedContext = null;
|
|
641
|
+
}
|
|
642
|
+
if (!nextOptions.some((option) => option.key === this.selectedContext) && this.pendingSelectedContext === null) {
|
|
643
|
+
let nextSelected = "all-agents";
|
|
644
|
+
if (agentIds.has("default")) nextSelected = "default";
|
|
645
|
+
else if (agentIds.size > 0) nextSelected = Array.from(agentIds).sort((a, b) => a.localeCompare(b))[0];
|
|
646
|
+
if (this.selectedContext !== nextSelected) {
|
|
647
|
+
this.selectedContext = nextSelected;
|
|
648
|
+
this.expandedRows.clear();
|
|
649
|
+
this.persistState();
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
getEventsForSelectedContext() {
|
|
654
|
+
if (this.selectedContext === "all-agents") return this.flattenedEvents;
|
|
655
|
+
return this.agentEvents.get(this.selectedContext) ?? [];
|
|
656
|
+
}
|
|
657
|
+
filterEvents(events) {
|
|
658
|
+
const query = this.eventFilterText.trim().toLowerCase();
|
|
659
|
+
return events.filter((event) => {
|
|
660
|
+
if (this.eventTypeFilter !== "all" && event.type !== this.eventTypeFilter) return false;
|
|
661
|
+
if (!query) return true;
|
|
662
|
+
const payloadText = this.stringifyPayload(event.payload, false).toLowerCase();
|
|
663
|
+
return event.type.toLowerCase().includes(query) || event.agentId.toLowerCase().includes(query) || payloadText.includes(query);
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
getLatestStateForAgent(agentId) {
|
|
667
|
+
if (this.agentStates.has(agentId)) {
|
|
668
|
+
const value = this.agentStates.get(agentId);
|
|
669
|
+
return value === void 0 ? null : value;
|
|
670
|
+
}
|
|
671
|
+
const stateEvent = (this.agentEvents.get(agentId) ?? []).find((e) => e.type === "STATE_SNAPSHOT");
|
|
672
|
+
if (!stateEvent) return null;
|
|
673
|
+
return stateEvent.payload;
|
|
674
|
+
}
|
|
675
|
+
getLatestMessagesForAgent(agentId) {
|
|
676
|
+
return this.agentMessages.get(agentId) ?? null;
|
|
677
|
+
}
|
|
678
|
+
getAgentStatus(agentId) {
|
|
679
|
+
const events = this.agentEvents.get(agentId) ?? [];
|
|
680
|
+
if (events.length === 0) return "idle";
|
|
681
|
+
const runEvent = events.find((e) => e.type === "RUN_STARTED" || e.type === "RUN_FINISHED" || e.type === "RUN_ERROR");
|
|
682
|
+
if (!runEvent) return "idle";
|
|
683
|
+
if (runEvent.type === "RUN_ERROR") return "error";
|
|
684
|
+
if (runEvent.type === "RUN_STARTED") return events.find((e) => e.type === "RUN_FINISHED" && e.timestamp > runEvent.timestamp) ? "idle" : "running";
|
|
685
|
+
return "idle";
|
|
686
|
+
}
|
|
687
|
+
getAgentStats(agentId) {
|
|
688
|
+
const events = this.agentEvents.get(agentId) ?? [];
|
|
689
|
+
const messages = this.agentMessages.get(agentId);
|
|
690
|
+
const toolCallCount = messages ? messages.reduce((count, message) => count + (message.toolCalls?.length ?? 0), 0) : events.filter((e) => e.type === "TOOL_CALL_END").length;
|
|
691
|
+
const messageCount = messages?.length ?? 0;
|
|
692
|
+
return {
|
|
693
|
+
totalEvents: events.length,
|
|
694
|
+
lastActivity: events[0]?.timestamp ?? null,
|
|
695
|
+
messages: messageCount,
|
|
696
|
+
toolCalls: toolCallCount,
|
|
697
|
+
errors: events.filter((e) => e.type === "RUN_ERROR").length
|
|
698
|
+
};
|
|
699
|
+
}
|
|
700
|
+
renderToolCallDetails(toolCalls) {
|
|
701
|
+
if (!Array.isArray(toolCalls) || toolCalls.length === 0) return lit.nothing;
|
|
702
|
+
return lit.html`
|
|
703
|
+
<div class="mt-2 space-y-2">
|
|
704
|
+
${toolCalls.map((call, index) => {
|
|
705
|
+
const functionName = call.function?.name ?? call.toolName ?? "Unknown function";
|
|
706
|
+
const callId = typeof call?.id === "string" ? call.id : `tool-call-${index + 1}`;
|
|
707
|
+
const argsString = this.formatToolCallArguments(call.function?.arguments);
|
|
708
|
+
return lit.html`
|
|
709
|
+
<div
|
|
710
|
+
class="rounded-md border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700"
|
|
711
|
+
>
|
|
712
|
+
<div
|
|
713
|
+
class="flex flex-wrap items-center justify-between gap-1 font-medium text-gray-900"
|
|
714
|
+
>
|
|
715
|
+
<span>${functionName}</span>
|
|
716
|
+
<span class="text-[10px] text-gray-500">ID: ${callId}</span>
|
|
717
|
+
</div>
|
|
718
|
+
${argsString ? lit.html`<pre
|
|
719
|
+
class="mt-2 overflow-auto rounded bg-white p-2 text-[11px] leading-relaxed text-gray-800"
|
|
720
|
+
>
|
|
721
|
+
${argsString}</pre
|
|
722
|
+
>` : lit.nothing}
|
|
723
|
+
</div>
|
|
724
|
+
`;
|
|
725
|
+
})}
|
|
726
|
+
</div>
|
|
727
|
+
`;
|
|
728
|
+
}
|
|
729
|
+
formatToolCallArguments(args) {
|
|
730
|
+
if (args === void 0 || args === null || args === "") return null;
|
|
731
|
+
if (typeof args === "string") try {
|
|
732
|
+
const parsed = JSON.parse(args);
|
|
733
|
+
return JSON.stringify(parsed, null, 2);
|
|
734
|
+
} catch {
|
|
735
|
+
return args;
|
|
736
|
+
}
|
|
737
|
+
if (typeof args === "object") try {
|
|
738
|
+
return JSON.stringify(args, null, 2);
|
|
739
|
+
} catch {
|
|
740
|
+
return String(args);
|
|
741
|
+
}
|
|
742
|
+
return String(args);
|
|
743
|
+
}
|
|
744
|
+
hasRenderableState(state) {
|
|
745
|
+
if (state === null || state === void 0) return false;
|
|
746
|
+
if (Array.isArray(state)) return state.length > 0;
|
|
747
|
+
if (typeof state === "object") return Object.keys(state).length > 0;
|
|
748
|
+
if (typeof state === "string") {
|
|
749
|
+
const trimmed = state.trim();
|
|
750
|
+
return trimmed.length > 0 && trimmed !== "{}";
|
|
751
|
+
}
|
|
752
|
+
return true;
|
|
753
|
+
}
|
|
754
|
+
formatStateForDisplay(state) {
|
|
755
|
+
if (state === null || state === void 0) return "";
|
|
756
|
+
if (typeof state === "string") {
|
|
757
|
+
const trimmed = state.trim();
|
|
758
|
+
if (trimmed.length === 0) return "";
|
|
759
|
+
try {
|
|
760
|
+
const parsed = JSON.parse(trimmed);
|
|
761
|
+
return JSON.stringify(parsed, null, 2);
|
|
762
|
+
} catch {
|
|
763
|
+
return state;
|
|
764
|
+
}
|
|
765
|
+
}
|
|
766
|
+
if (typeof state === "object") try {
|
|
767
|
+
return JSON.stringify(state, null, 2);
|
|
768
|
+
} catch {
|
|
769
|
+
return String(state);
|
|
770
|
+
}
|
|
771
|
+
return String(state);
|
|
772
|
+
}
|
|
773
|
+
getEventBadgeClasses(type) {
|
|
774
|
+
const base = "font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border";
|
|
775
|
+
if (type.startsWith("RUN_")) return `${base} bg-blue-50 text-blue-700 border-blue-200`;
|
|
776
|
+
if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-emerald-50 text-emerald-700 border-emerald-200`;
|
|
777
|
+
if (type.startsWith("TOOL_CALL")) return `${base} bg-amber-50 text-amber-700 border-amber-200`;
|
|
778
|
+
if (type.startsWith("REASONING")) return `${base} bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200`;
|
|
779
|
+
if (type.startsWith("STATE")) return `${base} bg-violet-50 text-violet-700 border-violet-200`;
|
|
780
|
+
if (type.startsWith("MESSAGES")) return `${base} bg-sky-50 text-sky-700 border-sky-200`;
|
|
781
|
+
if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-700 border-rose-200`;
|
|
782
|
+
return `${base} bg-gray-100 text-gray-600 border-gray-200`;
|
|
783
|
+
}
|
|
784
|
+
stringifyPayload(payload, pretty) {
|
|
785
|
+
try {
|
|
786
|
+
if (payload === void 0) return pretty ? "undefined" : "undefined";
|
|
787
|
+
if (typeof payload === "string") return payload;
|
|
788
|
+
return JSON.stringify(payload, null, pretty ? 2 : 0) ?? "";
|
|
789
|
+
} catch (error) {
|
|
790
|
+
console.warn("Failed to stringify inspector payload", error);
|
|
791
|
+
return String(payload);
|
|
792
|
+
}
|
|
793
|
+
}
|
|
794
|
+
extractEventFromPayload(payload) {
|
|
795
|
+
if (payload && typeof payload === "object" && "event" in payload) return payload.event;
|
|
796
|
+
return payload;
|
|
797
|
+
}
|
|
798
|
+
async copyToClipboard(text, eventId) {
|
|
799
|
+
try {
|
|
800
|
+
await navigator.clipboard.writeText(text);
|
|
801
|
+
this.copiedEvents.add(eventId);
|
|
802
|
+
this.requestUpdate();
|
|
803
|
+
setTimeout(() => {
|
|
804
|
+
this.copiedEvents.delete(eventId);
|
|
805
|
+
this.requestUpdate();
|
|
806
|
+
}, 2e3);
|
|
807
|
+
} catch (err) {
|
|
808
|
+
console.error("Failed to copy to clipboard:", err);
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
static {
|
|
812
|
+
this.styles = [(0, lit.unsafeCSS)(require_generated.default), lit.css`
|
|
813
|
+
:host {
|
|
814
|
+
position: fixed;
|
|
815
|
+
top: 0;
|
|
816
|
+
left: 0;
|
|
817
|
+
z-index: 2147483646;
|
|
818
|
+
display: block;
|
|
819
|
+
will-change: transform;
|
|
820
|
+
}
|
|
821
|
+
|
|
822
|
+
:host([data-transitioning="true"]) {
|
|
823
|
+
transition: transform 300ms ease;
|
|
824
|
+
}
|
|
825
|
+
|
|
826
|
+
.console-button {
|
|
827
|
+
transition:
|
|
828
|
+
transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
|
|
829
|
+
opacity 160ms ease;
|
|
830
|
+
}
|
|
831
|
+
|
|
832
|
+
.console-button[data-dragging="true"] {
|
|
833
|
+
transition: opacity 160ms ease;
|
|
834
|
+
}
|
|
835
|
+
|
|
836
|
+
.inspector-window[data-transitioning="true"] {
|
|
837
|
+
transition:
|
|
838
|
+
width 300ms ease,
|
|
839
|
+
height 300ms ease;
|
|
840
|
+
}
|
|
841
|
+
|
|
842
|
+
.inspector-window[data-docked="true"] {
|
|
843
|
+
border-radius: 0 !important;
|
|
844
|
+
box-shadow: none !important;
|
|
845
|
+
}
|
|
846
|
+
|
|
847
|
+
.resize-handle {
|
|
848
|
+
touch-action: none;
|
|
849
|
+
user-select: none;
|
|
850
|
+
}
|
|
851
|
+
|
|
852
|
+
.dock-resize-handle {
|
|
853
|
+
position: absolute;
|
|
854
|
+
top: 0;
|
|
855
|
+
right: 0;
|
|
856
|
+
width: 10px;
|
|
857
|
+
height: 100%;
|
|
858
|
+
cursor: ew-resize;
|
|
859
|
+
touch-action: none;
|
|
860
|
+
z-index: 50;
|
|
861
|
+
background: transparent;
|
|
862
|
+
}
|
|
863
|
+
|
|
864
|
+
.tooltip-target {
|
|
865
|
+
position: relative;
|
|
866
|
+
}
|
|
867
|
+
|
|
868
|
+
.tooltip-target::after {
|
|
869
|
+
content: attr(data-tooltip);
|
|
870
|
+
position: absolute;
|
|
871
|
+
top: calc(100% + 6px);
|
|
872
|
+
left: 50%;
|
|
873
|
+
transform: translateX(-50%) translateY(-4px);
|
|
874
|
+
white-space: nowrap;
|
|
875
|
+
background: rgba(17, 24, 39, 0.95);
|
|
876
|
+
color: white;
|
|
877
|
+
padding: 4px 8px;
|
|
878
|
+
border-radius: 6px;
|
|
879
|
+
font-size: 10px;
|
|
880
|
+
line-height: 1.2;
|
|
881
|
+
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
|
|
882
|
+
opacity: 0;
|
|
883
|
+
pointer-events: none;
|
|
884
|
+
transition:
|
|
885
|
+
opacity 120ms ease,
|
|
886
|
+
transform 120ms ease;
|
|
887
|
+
z-index: 4000;
|
|
888
|
+
}
|
|
889
|
+
|
|
890
|
+
.tooltip-target:hover::after {
|
|
891
|
+
opacity: 1;
|
|
892
|
+
transform: translateX(-50%) translateY(0);
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
.announcement-preview {
|
|
896
|
+
position: absolute;
|
|
897
|
+
top: 50%;
|
|
898
|
+
transform: translateY(-50%);
|
|
899
|
+
min-width: 300px;
|
|
900
|
+
max-width: 300px;
|
|
901
|
+
background: white;
|
|
902
|
+
color: #111827;
|
|
903
|
+
font-size: 13px;
|
|
904
|
+
line-height: 1.4;
|
|
905
|
+
border-radius: 12px;
|
|
906
|
+
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.22);
|
|
907
|
+
padding: 10px 12px;
|
|
908
|
+
display: inline-flex;
|
|
909
|
+
align-items: flex-start;
|
|
910
|
+
gap: 8px;
|
|
911
|
+
z-index: 4500;
|
|
912
|
+
animation: fade-slide-in 160ms ease;
|
|
913
|
+
border: 1px solid rgba(148, 163, 184, 0.35);
|
|
914
|
+
white-space: normal;
|
|
915
|
+
word-break: break-word;
|
|
916
|
+
text-align: left;
|
|
917
|
+
}
|
|
918
|
+
|
|
919
|
+
.announcement-preview[data-side="left"] {
|
|
920
|
+
right: 100%;
|
|
921
|
+
margin-right: 10px;
|
|
922
|
+
}
|
|
923
|
+
|
|
924
|
+
.announcement-preview[data-side="right"] {
|
|
925
|
+
left: 100%;
|
|
926
|
+
margin-left: 10px;
|
|
927
|
+
}
|
|
928
|
+
|
|
929
|
+
.announcement-preview__arrow {
|
|
930
|
+
position: absolute;
|
|
931
|
+
width: 10px;
|
|
932
|
+
height: 10px;
|
|
933
|
+
background: white;
|
|
934
|
+
border: 1px solid rgba(148, 163, 184, 0.35);
|
|
935
|
+
transform: rotate(45deg);
|
|
936
|
+
top: 50%;
|
|
937
|
+
margin-top: -5px;
|
|
938
|
+
z-index: -1;
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
.announcement-preview[data-side="left"] .announcement-preview__arrow {
|
|
942
|
+
right: -5px;
|
|
943
|
+
box-shadow: 6px -6px 10px rgba(15, 23, 42, 0.12);
|
|
944
|
+
}
|
|
945
|
+
|
|
946
|
+
.announcement-preview[data-side="right"] .announcement-preview__arrow {
|
|
947
|
+
left: -5px;
|
|
948
|
+
box-shadow: -6px 6px 10px rgba(15, 23, 42, 0.12);
|
|
949
|
+
}
|
|
950
|
+
|
|
951
|
+
.announcement-dismiss {
|
|
952
|
+
color: #6b7280;
|
|
953
|
+
font-size: 12px;
|
|
954
|
+
padding: 2px 8px;
|
|
955
|
+
border-radius: 8px;
|
|
956
|
+
border: 1px solid rgba(148, 163, 184, 0.5);
|
|
957
|
+
background: rgba(248, 250, 252, 0.9);
|
|
958
|
+
transition:
|
|
959
|
+
background 120ms ease,
|
|
960
|
+
color 120ms ease;
|
|
961
|
+
}
|
|
962
|
+
|
|
963
|
+
.announcement-dismiss:hover {
|
|
964
|
+
background: rgba(241, 245, 249, 1);
|
|
965
|
+
color: #111827;
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
.announcement-content {
|
|
969
|
+
color: #111827;
|
|
970
|
+
font-size: 14px;
|
|
971
|
+
line-height: 1.6;
|
|
972
|
+
}
|
|
973
|
+
|
|
974
|
+
.announcement-content h1,
|
|
975
|
+
.announcement-content h2,
|
|
976
|
+
.announcement-content h3 {
|
|
977
|
+
font-weight: 700;
|
|
978
|
+
margin: 0.4rem 0 0.2rem;
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
.announcement-content h1 {
|
|
982
|
+
font-size: 1.1rem;
|
|
983
|
+
}
|
|
984
|
+
|
|
985
|
+
.announcement-content h2 {
|
|
986
|
+
font-size: 1rem;
|
|
987
|
+
}
|
|
988
|
+
|
|
989
|
+
.announcement-content h3 {
|
|
990
|
+
font-size: 0.95rem;
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
.announcement-content p {
|
|
994
|
+
margin: 0.25rem 0;
|
|
995
|
+
}
|
|
996
|
+
|
|
997
|
+
.announcement-content ul {
|
|
998
|
+
list-style: disc;
|
|
999
|
+
padding-left: 1.25rem;
|
|
1000
|
+
margin: 0.3rem 0;
|
|
1001
|
+
}
|
|
1002
|
+
|
|
1003
|
+
.announcement-content ol {
|
|
1004
|
+
list-style: decimal;
|
|
1005
|
+
padding-left: 1.25rem;
|
|
1006
|
+
margin: 0.3rem 0;
|
|
1007
|
+
}
|
|
1008
|
+
|
|
1009
|
+
.announcement-content a {
|
|
1010
|
+
color: #0f766e;
|
|
1011
|
+
text-decoration: underline;
|
|
1012
|
+
}
|
|
1013
|
+
`];
|
|
1014
|
+
}
|
|
1015
|
+
connectedCallback() {
|
|
1016
|
+
super.connectedCallback();
|
|
1017
|
+
if (typeof window !== "undefined") {
|
|
1018
|
+
window.addEventListener("resize", this.handleResize);
|
|
1019
|
+
window.addEventListener("pointerdown", this.handleGlobalPointerDown);
|
|
1020
|
+
this.hydrateStateFromStorageEarly();
|
|
1021
|
+
this.tryAutoAttachCore();
|
|
1022
|
+
this.ensureAnnouncementLoading();
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
disconnectedCallback() {
|
|
1026
|
+
super.disconnectedCallback();
|
|
1027
|
+
if (typeof window !== "undefined") {
|
|
1028
|
+
window.removeEventListener("resize", this.handleResize);
|
|
1029
|
+
window.removeEventListener("pointerdown", this.handleGlobalPointerDown);
|
|
1030
|
+
}
|
|
1031
|
+
this.removeDockStyles();
|
|
1032
|
+
this.detachFromCore();
|
|
1033
|
+
}
|
|
1034
|
+
firstUpdated() {
|
|
1035
|
+
if (typeof window === "undefined") return;
|
|
1036
|
+
if (!this._core) this.tryAutoAttachCore();
|
|
1037
|
+
this.measureContext("button");
|
|
1038
|
+
this.measureContext("window");
|
|
1039
|
+
this.contextState.button.anchor = {
|
|
1040
|
+
horizontal: "right",
|
|
1041
|
+
vertical: "top"
|
|
1042
|
+
};
|
|
1043
|
+
this.contextState.button.anchorOffset = {
|
|
1044
|
+
x: EDGE_MARGIN,
|
|
1045
|
+
y: EDGE_MARGIN
|
|
1046
|
+
};
|
|
1047
|
+
this.contextState.window.anchor = {
|
|
1048
|
+
horizontal: "right",
|
|
1049
|
+
vertical: "top"
|
|
1050
|
+
};
|
|
1051
|
+
this.contextState.window.anchorOffset = {
|
|
1052
|
+
x: EDGE_MARGIN,
|
|
1053
|
+
y: EDGE_MARGIN
|
|
1054
|
+
};
|
|
1055
|
+
this.hydrateStateFromStorage();
|
|
1056
|
+
if (this.isOpen && this.dockMode !== "floating") this.applyDockStyles(true);
|
|
1057
|
+
this.applyAnchorPosition("button");
|
|
1058
|
+
if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
|
|
1059
|
+
else this.centerContext("window");
|
|
1060
|
+
this.ensureAnnouncementLoading();
|
|
1061
|
+
this.updateHostTransform(this.isOpen ? "window" : "button");
|
|
1062
|
+
}
|
|
1063
|
+
render() {
|
|
1064
|
+
return this.isOpen ? this.renderWindow() : this.renderButton();
|
|
1065
|
+
}
|
|
1066
|
+
renderButton() {
|
|
1067
|
+
return lit.html`
|
|
1068
|
+
<button
|
|
1069
|
+
class=${[
|
|
1070
|
+
"console-button",
|
|
1071
|
+
"group",
|
|
1072
|
+
"relative",
|
|
1073
|
+
"pointer-events-auto",
|
|
1074
|
+
"inline-flex",
|
|
1075
|
+
"h-12",
|
|
1076
|
+
"w-12",
|
|
1077
|
+
"items-center",
|
|
1078
|
+
"justify-center",
|
|
1079
|
+
"rounded-full",
|
|
1080
|
+
"border",
|
|
1081
|
+
"border-white/20",
|
|
1082
|
+
"bg-slate-950/95",
|
|
1083
|
+
"text-xs",
|
|
1084
|
+
"font-medium",
|
|
1085
|
+
"text-white",
|
|
1086
|
+
"ring-1",
|
|
1087
|
+
"ring-white/10",
|
|
1088
|
+
"backdrop-blur-md",
|
|
1089
|
+
"transition",
|
|
1090
|
+
"hover:border-white/30",
|
|
1091
|
+
"hover:bg-slate-900/95",
|
|
1092
|
+
"hover:scale-105",
|
|
1093
|
+
"focus-visible:outline",
|
|
1094
|
+
"focus-visible:outline-2",
|
|
1095
|
+
"focus-visible:outline-offset-2",
|
|
1096
|
+
"focus-visible:outline-rose-500",
|
|
1097
|
+
"touch-none",
|
|
1098
|
+
"select-none",
|
|
1099
|
+
this.isDragging ? "cursor-grabbing" : "cursor-grab"
|
|
1100
|
+
].join(" ")}
|
|
1101
|
+
type="button"
|
|
1102
|
+
aria-label="Web Inspector"
|
|
1103
|
+
data-drag-context="button"
|
|
1104
|
+
data-dragging=${this.isDragging && this.pointerContext === "button" ? "true" : "false"}
|
|
1105
|
+
@pointerdown=${this.handlePointerDown}
|
|
1106
|
+
@pointermove=${this.handlePointerMove}
|
|
1107
|
+
@pointerup=${this.handlePointerUp}
|
|
1108
|
+
@pointercancel=${this.handlePointerCancel}
|
|
1109
|
+
@click=${this.handleButtonClick}
|
|
1110
|
+
>
|
|
1111
|
+
${this.renderAnnouncementPreview()}
|
|
1112
|
+
<img
|
|
1113
|
+
src=${require_inspector_logo_icon.default}
|
|
1114
|
+
alt="Inspector logo"
|
|
1115
|
+
class="h-5 w-auto"
|
|
1116
|
+
loading="lazy"
|
|
1117
|
+
/>
|
|
1118
|
+
</button>
|
|
1119
|
+
`;
|
|
1120
|
+
}
|
|
1121
|
+
renderWindow() {
|
|
1122
|
+
const windowState = this.contextState.window;
|
|
1123
|
+
const isDocked = this.dockMode !== "floating";
|
|
1124
|
+
const isTransitioning = this.hasAttribute("data-transitioning");
|
|
1125
|
+
const windowStyles = isDocked ? this.getDockedWindowStyles() : {
|
|
1126
|
+
width: `${Math.round(windowState.size.width)}px`,
|
|
1127
|
+
height: `${Math.round(windowState.size.height)}px`,
|
|
1128
|
+
minWidth: `${MIN_WINDOW_WIDTH}px`,
|
|
1129
|
+
minHeight: `${MIN_WINDOW_HEIGHT}px`
|
|
1130
|
+
};
|
|
1131
|
+
const hasContextDropdown = this.contextOptions.length > 0;
|
|
1132
|
+
const contextDropdown = hasContextDropdown ? this.renderContextDropdown() : lit.nothing;
|
|
1133
|
+
const coreStatus = this.getCoreStatusSummary();
|
|
1134
|
+
const agentSelector = hasContextDropdown ? contextDropdown : lit.html`
|
|
1135
|
+
<div
|
|
1136
|
+
class="flex items-center gap-2 rounded-md border border-dashed border-gray-200 px-2 py-1 text-xs text-gray-400"
|
|
1137
|
+
>
|
|
1138
|
+
<span>${this.renderIcon("Bot")}</span>
|
|
1139
|
+
<span class="truncate">No agents available</span>
|
|
1140
|
+
</div>
|
|
1141
|
+
`;
|
|
1142
|
+
return lit.html`
|
|
1143
|
+
<section
|
|
1144
|
+
class="inspector-window pointer-events-auto relative flex flex-col overflow-hidden rounded-xl border border-gray-200 bg-white text-gray-900 shadow-lg"
|
|
1145
|
+
style=${(0, lit_directives_style_map_js.styleMap)(windowStyles)}
|
|
1146
|
+
data-docked=${isDocked}
|
|
1147
|
+
data-transitioning=${isTransitioning}
|
|
1148
|
+
>
|
|
1149
|
+
${isDocked ? lit.html`
|
|
1150
|
+
<div
|
|
1151
|
+
class="dock-resize-handle pointer-events-auto"
|
|
1152
|
+
role="presentation"
|
|
1153
|
+
aria-hidden="true"
|
|
1154
|
+
@pointerdown=${this.handleResizePointerDown}
|
|
1155
|
+
@pointermove=${this.handleResizePointerMove}
|
|
1156
|
+
@pointerup=${this.handleResizePointerUp}
|
|
1157
|
+
@pointercancel=${this.handleResizePointerCancel}
|
|
1158
|
+
></div>
|
|
1159
|
+
` : lit.nothing}
|
|
1160
|
+
<div
|
|
1161
|
+
class="flex flex-1 flex-col overflow-hidden bg-white text-gray-800"
|
|
1162
|
+
>
|
|
1163
|
+
<div
|
|
1164
|
+
class="drag-handle relative z-30 flex flex-col border-b border-gray-200 bg-white/95 backdrop-blur-sm ${isDocked ? "" : this.isDragging && this.pointerContext === "window" ? "cursor-grabbing" : "cursor-grab"}"
|
|
1165
|
+
data-drag-context="window"
|
|
1166
|
+
@pointerdown=${isDocked ? void 0 : this.handlePointerDown}
|
|
1167
|
+
@pointermove=${isDocked ? void 0 : this.handlePointerMove}
|
|
1168
|
+
@pointerup=${isDocked ? void 0 : this.handlePointerUp}
|
|
1169
|
+
@pointercancel=${isDocked ? void 0 : this.handlePointerCancel}
|
|
1170
|
+
>
|
|
1171
|
+
<div class="flex flex-wrap items-center gap-3 px-4 py-3">
|
|
1172
|
+
<div class="flex items-center min-w-0">
|
|
1173
|
+
<img
|
|
1174
|
+
src=${require_inspector_logo.default}
|
|
1175
|
+
alt="Inspector logo"
|
|
1176
|
+
class="h-6 w-auto"
|
|
1177
|
+
loading="lazy"
|
|
1178
|
+
/>
|
|
1179
|
+
</div>
|
|
1180
|
+
<div class="ml-auto flex min-w-0 items-center gap-2">
|
|
1181
|
+
<div class="min-w-[160px] max-w-xs">${agentSelector}</div>
|
|
1182
|
+
<div class="flex items-center gap-1">
|
|
1183
|
+
${this.renderDockControls()}
|
|
1184
|
+
<button
|
|
1185
|
+
class="flex h-8 w-8 items-center justify-center rounded-md text-gray-400 transition hover:bg-gray-100 hover:text-gray-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400"
|
|
1186
|
+
type="button"
|
|
1187
|
+
aria-label="Close Web Inspector"
|
|
1188
|
+
@pointerdown=${this.handleClosePointerDown}
|
|
1189
|
+
@click=${this.handleCloseClick}
|
|
1190
|
+
>
|
|
1191
|
+
${this.renderIcon("X")}
|
|
1192
|
+
</button>
|
|
1193
|
+
</div>
|
|
1194
|
+
</div>
|
|
1195
|
+
</div>
|
|
1196
|
+
<div
|
|
1197
|
+
class="flex flex-wrap items-center gap-2 border-t border-gray-100 px-3 py-2 text-xs"
|
|
1198
|
+
>
|
|
1199
|
+
${this.menuItems.map(({ key, label, icon }) => {
|
|
1200
|
+
const isSelected = this.selectedMenu === key;
|
|
1201
|
+
return lit.html`
|
|
1202
|
+
<button
|
|
1203
|
+
type="button"
|
|
1204
|
+
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 ? "bg-gray-900 text-white shadow-sm" : "text-gray-600 hover:bg-gray-100 hover:text-gray-900"].join(" ")}
|
|
1205
|
+
aria-pressed=${isSelected}
|
|
1206
|
+
@click=${() => this.handleMenuSelect(key)}
|
|
1207
|
+
>
|
|
1208
|
+
<span
|
|
1209
|
+
class="text-gray-400 ${isSelected ? "text-white" : ""}"
|
|
1210
|
+
>
|
|
1211
|
+
${this.renderIcon(icon)}
|
|
1212
|
+
</span>
|
|
1213
|
+
<span>${label}</span>
|
|
1214
|
+
</button>
|
|
1215
|
+
`;
|
|
1216
|
+
})}
|
|
1217
|
+
</div>
|
|
1218
|
+
</div>
|
|
1219
|
+
<div class="flex flex-1 flex-col overflow-hidden">
|
|
1220
|
+
<div class="flex-1 overflow-auto">
|
|
1221
|
+
${this.renderAnnouncementPanel()}
|
|
1222
|
+
${this.renderCoreWarningBanner()} ${this.renderMainContent()}
|
|
1223
|
+
<slot></slot>
|
|
1224
|
+
</div>
|
|
1225
|
+
<div class="border-t border-gray-200 bg-gray-50 px-4 py-2">
|
|
1226
|
+
<div
|
|
1227
|
+
class="flex items-center gap-2 rounded-md px-3 py-2 text-xs ${coreStatus.tone} w-full overflow-hidden my-1"
|
|
1228
|
+
title=${coreStatus.description}
|
|
1229
|
+
>
|
|
1230
|
+
<span
|
|
1231
|
+
class="flex h-6 w-6 items-center justify-center rounded bg-white/60"
|
|
1232
|
+
>
|
|
1233
|
+
${this.renderIcon("Activity")}
|
|
1234
|
+
</span>
|
|
1235
|
+
<span class="font-medium">${coreStatus.label}</span>
|
|
1236
|
+
<span class="truncate text-[11px] opacity-80"
|
|
1237
|
+
>${coreStatus.description}</span
|
|
1238
|
+
>
|
|
1239
|
+
</div>
|
|
1240
|
+
</div>
|
|
1241
|
+
</div>
|
|
1242
|
+
</div>
|
|
1243
|
+
<div
|
|
1244
|
+
class="resize-handle pointer-events-auto absolute bottom-1 right-1 flex h-5 w-5 cursor-nwse-resize items-center justify-center text-gray-400 transition hover:text-gray-600"
|
|
1245
|
+
role="presentation"
|
|
1246
|
+
aria-hidden="true"
|
|
1247
|
+
@pointerdown=${this.handleResizePointerDown}
|
|
1248
|
+
@pointermove=${this.handleResizePointerMove}
|
|
1249
|
+
@pointerup=${this.handleResizePointerUp}
|
|
1250
|
+
@pointercancel=${this.handleResizePointerCancel}
|
|
1251
|
+
>
|
|
1252
|
+
<svg
|
|
1253
|
+
class="h-3 w-3"
|
|
1254
|
+
viewBox="0 0 16 16"
|
|
1255
|
+
fill="none"
|
|
1256
|
+
stroke="currentColor"
|
|
1257
|
+
stroke-linecap="round"
|
|
1258
|
+
stroke-width="1.5"
|
|
1259
|
+
>
|
|
1260
|
+
<path d="M5 15L15 5" />
|
|
1261
|
+
<path d="M9 15L15 9" />
|
|
1262
|
+
</svg>
|
|
1263
|
+
</div>
|
|
1264
|
+
</section>
|
|
1265
|
+
`;
|
|
1266
|
+
}
|
|
1267
|
+
hydrateStateFromStorageEarly() {
|
|
1268
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1269
|
+
const persisted = require_persistence.loadInspectorState(INSPECTOR_STORAGE_KEY);
|
|
1270
|
+
if (!persisted) return;
|
|
1271
|
+
if (typeof persisted.isOpen === "boolean") this.isOpen = persisted.isOpen;
|
|
1272
|
+
if (require_persistence.isValidDockMode(persisted.dockMode)) this.dockMode = persisted.dockMode;
|
|
1273
|
+
if (typeof persisted.selectedMenu === "string") {
|
|
1274
|
+
const validMenu = this.menuItems.find((item) => item.key === persisted.selectedMenu);
|
|
1275
|
+
if (validMenu) this.selectedMenu = validMenu.key;
|
|
1276
|
+
}
|
|
1277
|
+
if (typeof persisted.selectedContext === "string") {
|
|
1278
|
+
this.selectedContext = persisted.selectedContext;
|
|
1279
|
+
this.pendingSelectedContext = persisted.selectedContext;
|
|
1280
|
+
}
|
|
1281
|
+
}
|
|
1282
|
+
hydrateStateFromStorage() {
|
|
1283
|
+
if (typeof document === "undefined" || typeof window === "undefined") return;
|
|
1284
|
+
const persisted = require_persistence.loadInspectorState(INSPECTOR_STORAGE_KEY);
|
|
1285
|
+
if (!persisted) return;
|
|
1286
|
+
const persistedButton = persisted.button;
|
|
1287
|
+
if (persistedButton) {
|
|
1288
|
+
if (require_persistence.isValidAnchor(persistedButton.anchor)) this.contextState.button.anchor = persistedButton.anchor;
|
|
1289
|
+
if (require_persistence.isValidPosition(persistedButton.anchorOffset)) this.contextState.button.anchorOffset = persistedButton.anchorOffset;
|
|
1290
|
+
if (typeof persistedButton.hasCustomPosition === "boolean") this.hasCustomPosition.button = persistedButton.hasCustomPosition;
|
|
1291
|
+
}
|
|
1292
|
+
const persistedWindow = persisted.window;
|
|
1293
|
+
if (persistedWindow) {
|
|
1294
|
+
if (require_persistence.isValidAnchor(persistedWindow.anchor)) this.contextState.window.anchor = persistedWindow.anchor;
|
|
1295
|
+
if (require_persistence.isValidPosition(persistedWindow.anchorOffset)) this.contextState.window.anchorOffset = persistedWindow.anchorOffset;
|
|
1296
|
+
if (require_persistence.isValidSize(persistedWindow.size)) this.contextState.window.size = this.clampWindowSize(persistedWindow.size);
|
|
1297
|
+
if (typeof persistedWindow.hasCustomPosition === "boolean") this.hasCustomPosition.window = persistedWindow.hasCustomPosition;
|
|
1298
|
+
}
|
|
1299
|
+
if (typeof persisted.selectedContext === "string") {
|
|
1300
|
+
this.selectedContext = persisted.selectedContext;
|
|
1301
|
+
this.pendingSelectedContext = persisted.selectedContext;
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
get activeContext() {
|
|
1305
|
+
return this.isOpen ? "window" : "button";
|
|
1306
|
+
}
|
|
1307
|
+
measureContext(context) {
|
|
1308
|
+
const selector = context === "window" ? ".inspector-window" : ".console-button";
|
|
1309
|
+
const element = this.renderRoot?.querySelector(selector);
|
|
1310
|
+
if (!element) return;
|
|
1311
|
+
const fallback = context === "window" ? DEFAULT_WINDOW_SIZE : DEFAULT_BUTTON_SIZE;
|
|
1312
|
+
require_context_helpers.updateSizeFromElement(this.contextState[context], element, fallback);
|
|
1313
|
+
}
|
|
1314
|
+
centerContext(context) {
|
|
1315
|
+
if (typeof window === "undefined") return;
|
|
1316
|
+
const viewport = this.getViewportSize();
|
|
1317
|
+
require_context_helpers.centerContext(this.contextState[context], viewport, EDGE_MARGIN);
|
|
1318
|
+
if (context === this.activeContext) this.updateHostTransform(context);
|
|
1319
|
+
this.hasCustomPosition[context] = false;
|
|
1320
|
+
this.persistState();
|
|
1321
|
+
}
|
|
1322
|
+
ensureWindowPlacement() {
|
|
1323
|
+
if (typeof window === "undefined") return;
|
|
1324
|
+
if (!this.hasCustomPosition.window) {
|
|
1325
|
+
this.centerContext("window");
|
|
1326
|
+
return;
|
|
1327
|
+
}
|
|
1328
|
+
const viewport = this.getViewportSize();
|
|
1329
|
+
require_context_helpers.keepPositionWithinViewport(this.contextState.window, viewport, EDGE_MARGIN);
|
|
1330
|
+
require_context_helpers.updateAnchorFromPosition(this.contextState.window, viewport, EDGE_MARGIN);
|
|
1331
|
+
this.updateHostTransform("window");
|
|
1332
|
+
this.persistState();
|
|
1333
|
+
}
|
|
1334
|
+
constrainToViewport(position, context) {
|
|
1335
|
+
if (typeof window === "undefined") return position;
|
|
1336
|
+
const viewport = this.getViewportSize();
|
|
1337
|
+
return require_context_helpers.constrainToViewport(this.contextState[context], position, viewport, EDGE_MARGIN);
|
|
1338
|
+
}
|
|
1339
|
+
keepPositionWithinViewport(context) {
|
|
1340
|
+
if (typeof window === "undefined") return;
|
|
1341
|
+
const viewport = this.getViewportSize();
|
|
1342
|
+
require_context_helpers.keepPositionWithinViewport(this.contextState[context], viewport, EDGE_MARGIN);
|
|
1343
|
+
}
|
|
1344
|
+
getViewportSize() {
|
|
1345
|
+
if (typeof window === "undefined") return { ...DEFAULT_WINDOW_SIZE };
|
|
1346
|
+
return {
|
|
1347
|
+
width: window.innerWidth,
|
|
1348
|
+
height: window.innerHeight
|
|
1349
|
+
};
|
|
1350
|
+
}
|
|
1351
|
+
persistState() {
|
|
1352
|
+
const state = {
|
|
1353
|
+
button: {
|
|
1354
|
+
anchor: this.contextState.button.anchor,
|
|
1355
|
+
anchorOffset: this.contextState.button.anchorOffset,
|
|
1356
|
+
hasCustomPosition: this.hasCustomPosition.button
|
|
1357
|
+
},
|
|
1358
|
+
window: {
|
|
1359
|
+
anchor: this.contextState.window.anchor,
|
|
1360
|
+
anchorOffset: this.contextState.window.anchorOffset,
|
|
1361
|
+
size: {
|
|
1362
|
+
width: Math.round(this.contextState.window.size.width),
|
|
1363
|
+
height: Math.round(this.contextState.window.size.height)
|
|
1364
|
+
},
|
|
1365
|
+
hasCustomPosition: this.hasCustomPosition.window
|
|
1366
|
+
},
|
|
1367
|
+
isOpen: this.isOpen,
|
|
1368
|
+
dockMode: this.dockMode,
|
|
1369
|
+
selectedMenu: this.selectedMenu,
|
|
1370
|
+
selectedContext: this.selectedContext
|
|
1371
|
+
};
|
|
1372
|
+
require_persistence.saveInspectorState(INSPECTOR_STORAGE_KEY, state);
|
|
1373
|
+
this.pendingSelectedContext = state.selectedContext ?? null;
|
|
1374
|
+
}
|
|
1375
|
+
clampWindowSize(size) {
|
|
1376
|
+
const minWidth = this.dockMode === "docked-left" ? MIN_WINDOW_WIDTH_DOCKED_LEFT : MIN_WINDOW_WIDTH;
|
|
1377
|
+
if (typeof window === "undefined") return {
|
|
1378
|
+
width: Math.max(minWidth, size.width),
|
|
1379
|
+
height: Math.max(MIN_WINDOW_HEIGHT, size.height)
|
|
1380
|
+
};
|
|
1381
|
+
return require_context_helpers.clampSize(size, this.getViewportSize(), EDGE_MARGIN, minWidth, MIN_WINDOW_HEIGHT);
|
|
1382
|
+
}
|
|
1383
|
+
setDockMode(mode) {
|
|
1384
|
+
if (this.dockMode === mode) return;
|
|
1385
|
+
this.startHostTransition();
|
|
1386
|
+
this.removeDockStyles();
|
|
1387
|
+
this.dockMode = mode;
|
|
1388
|
+
if (mode !== "floating") {
|
|
1389
|
+
if (mode === "docked-left") this.contextState.window.size.width = DOCKED_LEFT_WIDTH;
|
|
1390
|
+
this.applyDockStyles();
|
|
1391
|
+
} else {
|
|
1392
|
+
this.contextState.window.size = { ...DEFAULT_WINDOW_SIZE };
|
|
1393
|
+
this.centerContext("window");
|
|
1394
|
+
}
|
|
1395
|
+
this.persistState();
|
|
1396
|
+
this.requestUpdate();
|
|
1397
|
+
this.updateHostTransform("window");
|
|
1398
|
+
}
|
|
1399
|
+
startHostTransition(duration = 300) {
|
|
1400
|
+
this.setAttribute("data-transitioning", "true");
|
|
1401
|
+
if (this.transitionTimeoutId !== null) clearTimeout(this.transitionTimeoutId);
|
|
1402
|
+
this.transitionTimeoutId = setTimeout(() => {
|
|
1403
|
+
this.removeAttribute("data-transitioning");
|
|
1404
|
+
this.transitionTimeoutId = null;
|
|
1405
|
+
}, duration);
|
|
1406
|
+
}
|
|
1407
|
+
applyDockStyles(skipTransition = false) {
|
|
1408
|
+
if (typeof document === "undefined" || !document.body) return;
|
|
1409
|
+
const computedStyle = window.getComputedStyle(document.body);
|
|
1410
|
+
this.previousBodyMargins = {
|
|
1411
|
+
left: computedStyle.marginLeft,
|
|
1412
|
+
bottom: computedStyle.marginBottom
|
|
1413
|
+
};
|
|
1414
|
+
if (!this.isResizing && !skipTransition) document.body.style.transition = "margin 300ms ease";
|
|
1415
|
+
if (this.dockMode === "docked-left") document.body.style.marginLeft = `${this.contextState.window.size.width}px`;
|
|
1416
|
+
if (!this.isResizing && !skipTransition) setTimeout(() => {
|
|
1417
|
+
if (document.body) document.body.style.transition = "";
|
|
1418
|
+
}, 300);
|
|
1419
|
+
}
|
|
1420
|
+
removeDockStyles() {
|
|
1421
|
+
if (typeof document === "undefined" || !document.body) return;
|
|
1422
|
+
if (!this.isResizing) document.body.style.transition = "margin 300ms ease";
|
|
1423
|
+
if (this.previousBodyMargins) {
|
|
1424
|
+
document.body.style.marginLeft = this.previousBodyMargins.left;
|
|
1425
|
+
document.body.style.marginBottom = this.previousBodyMargins.bottom;
|
|
1426
|
+
this.previousBodyMargins = null;
|
|
1427
|
+
} else {
|
|
1428
|
+
document.body.style.marginLeft = "";
|
|
1429
|
+
document.body.style.marginBottom = "";
|
|
1430
|
+
}
|
|
1431
|
+
setTimeout(() => {
|
|
1432
|
+
if (document.body) document.body.style.transition = "";
|
|
1433
|
+
}, 300);
|
|
1434
|
+
}
|
|
1435
|
+
updateHostTransform(context = this.activeContext) {
|
|
1436
|
+
if (context !== this.activeContext) return;
|
|
1437
|
+
if (this.isOpen && this.dockMode === "docked-left") this.style.transform = `translate3d(0, 0, 0)`;
|
|
1438
|
+
else {
|
|
1439
|
+
const { position } = this.contextState[context];
|
|
1440
|
+
this.style.transform = `translate3d(${position.x}px, ${position.y}px, 0)`;
|
|
1441
|
+
}
|
|
1442
|
+
}
|
|
1443
|
+
setDragging(value) {
|
|
1444
|
+
if (this.isDragging !== value) {
|
|
1445
|
+
this.isDragging = value;
|
|
1446
|
+
this.requestUpdate();
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1449
|
+
updateAnchorFromPosition(context) {
|
|
1450
|
+
if (typeof window === "undefined") return;
|
|
1451
|
+
const viewport = this.getViewportSize();
|
|
1452
|
+
require_context_helpers.updateAnchorFromPosition(this.contextState[context], viewport, EDGE_MARGIN);
|
|
1453
|
+
}
|
|
1454
|
+
snapButtonToCorner() {
|
|
1455
|
+
if (typeof window === "undefined") return;
|
|
1456
|
+
const viewport = this.getViewportSize();
|
|
1457
|
+
const state = this.contextState.button;
|
|
1458
|
+
const centerX = state.position.x + state.size.width / 2;
|
|
1459
|
+
const centerY = state.position.y + state.size.height / 2;
|
|
1460
|
+
state.anchor = {
|
|
1461
|
+
horizontal: centerX < viewport.width / 2 ? "left" : "right",
|
|
1462
|
+
vertical: centerY < viewport.height / 2 ? "top" : "bottom"
|
|
1463
|
+
};
|
|
1464
|
+
state.anchorOffset = {
|
|
1465
|
+
x: EDGE_MARGIN,
|
|
1466
|
+
y: EDGE_MARGIN
|
|
1467
|
+
};
|
|
1468
|
+
this.startHostTransition();
|
|
1469
|
+
this.applyAnchorPosition("button");
|
|
1470
|
+
}
|
|
1471
|
+
applyAnchorPosition(context) {
|
|
1472
|
+
if (typeof window === "undefined") return;
|
|
1473
|
+
const viewport = this.getViewportSize();
|
|
1474
|
+
require_context_helpers.applyAnchorPosition(this.contextState[context], viewport, EDGE_MARGIN);
|
|
1475
|
+
this.updateHostTransform(context);
|
|
1476
|
+
this.persistState();
|
|
1477
|
+
}
|
|
1478
|
+
resetResizeTracking() {
|
|
1479
|
+
this.resizePointerId = null;
|
|
1480
|
+
this.resizeStart = null;
|
|
1481
|
+
this.resizeInitialSize = null;
|
|
1482
|
+
this.isResizing = false;
|
|
1483
|
+
}
|
|
1484
|
+
resetPointerTracking() {
|
|
1485
|
+
this.pointerId = null;
|
|
1486
|
+
this.dragStart = null;
|
|
1487
|
+
this.pointerContext = null;
|
|
1488
|
+
this.setDragging(false);
|
|
1489
|
+
this.draggedDuringInteraction = false;
|
|
1490
|
+
}
|
|
1491
|
+
openInspector() {
|
|
1492
|
+
if (this.isOpen) return;
|
|
1493
|
+
this.showAnnouncementPreview = false;
|
|
1494
|
+
this.ensureAnnouncementLoading();
|
|
1495
|
+
this.isOpen = true;
|
|
1496
|
+
this.persistState();
|
|
1497
|
+
if (this.dockMode !== "floating") this.applyDockStyles();
|
|
1498
|
+
this.ensureWindowPlacement();
|
|
1499
|
+
this.requestUpdate();
|
|
1500
|
+
this.updateComplete.then(() => {
|
|
1501
|
+
this.measureContext("window");
|
|
1502
|
+
if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
|
|
1503
|
+
else this.centerContext("window");
|
|
1504
|
+
else this.updateHostTransform("window");
|
|
1505
|
+
});
|
|
1506
|
+
}
|
|
1507
|
+
closeInspector() {
|
|
1508
|
+
if (!this.isOpen) return;
|
|
1509
|
+
this.isOpen = false;
|
|
1510
|
+
if (this.dockMode !== "floating") this.removeDockStyles();
|
|
1511
|
+
this.persistState();
|
|
1512
|
+
this.updateHostTransform("button");
|
|
1513
|
+
this.requestUpdate();
|
|
1514
|
+
this.updateComplete.then(() => {
|
|
1515
|
+
this.measureContext("button");
|
|
1516
|
+
this.applyAnchorPosition("button");
|
|
1517
|
+
});
|
|
1518
|
+
}
|
|
1519
|
+
renderIcon(name) {
|
|
1520
|
+
const iconNode = lucide.icons[name];
|
|
1521
|
+
if (!iconNode) return lit.nothing;
|
|
1522
|
+
return (0, lit_directives_unsafe_html_js.unsafeHTML)(`<svg ${this.serializeAttributes({
|
|
1523
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
1524
|
+
viewBox: "0 0 24 24",
|
|
1525
|
+
fill: "none",
|
|
1526
|
+
stroke: "currentColor",
|
|
1527
|
+
"stroke-width": "1.5",
|
|
1528
|
+
"stroke-linecap": "round",
|
|
1529
|
+
"stroke-linejoin": "round",
|
|
1530
|
+
class: "h-3.5 w-3.5"
|
|
1531
|
+
})}>${iconNode.map(([tag, attrs]) => `<${tag} ${this.serializeAttributes(attrs)} />`).join("")}</svg>`);
|
|
1532
|
+
}
|
|
1533
|
+
renderDockControls() {
|
|
1534
|
+
if (this.dockMode === "floating") return lit.html`
|
|
1535
|
+
<button
|
|
1536
|
+
class="flex h-8 w-8 items-center justify-center rounded-md text-gray-400 transition hover:bg-gray-100 hover:text-gray-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400"
|
|
1537
|
+
type="button"
|
|
1538
|
+
aria-label="Dock to left"
|
|
1539
|
+
title="Dock Left"
|
|
1540
|
+
@click=${() => this.handleDockClick("docked-left")}
|
|
1541
|
+
>
|
|
1542
|
+
${this.renderIcon("PanelLeft")}
|
|
1543
|
+
</button>
|
|
1544
|
+
`;
|
|
1545
|
+
else return lit.html`
|
|
1546
|
+
<button
|
|
1547
|
+
class="flex h-8 w-8 items-center justify-center rounded-md text-gray-400 transition hover:bg-gray-100 hover:text-gray-600 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-400"
|
|
1548
|
+
type="button"
|
|
1549
|
+
aria-label="Float window"
|
|
1550
|
+
title="Float"
|
|
1551
|
+
@click=${() => this.handleDockClick("floating")}
|
|
1552
|
+
>
|
|
1553
|
+
${this.renderIcon("Maximize2")}
|
|
1554
|
+
</button>
|
|
1555
|
+
`;
|
|
1556
|
+
}
|
|
1557
|
+
getDockedWindowStyles() {
|
|
1558
|
+
if (this.dockMode === "docked-left") return {
|
|
1559
|
+
position: "fixed",
|
|
1560
|
+
top: "0",
|
|
1561
|
+
left: "0",
|
|
1562
|
+
bottom: "0",
|
|
1563
|
+
width: `${Math.round(this.contextState.window.size.width)}px`,
|
|
1564
|
+
height: "100vh",
|
|
1565
|
+
minWidth: `${MIN_WINDOW_WIDTH_DOCKED_LEFT}px`,
|
|
1566
|
+
borderRadius: "0"
|
|
1567
|
+
};
|
|
1568
|
+
return {
|
|
1569
|
+
width: `${Math.round(this.contextState.window.size.width)}px`,
|
|
1570
|
+
height: `${Math.round(this.contextState.window.size.height)}px`,
|
|
1571
|
+
minWidth: `${MIN_WINDOW_WIDTH}px`,
|
|
1572
|
+
minHeight: `${MIN_WINDOW_HEIGHT}px`
|
|
1573
|
+
};
|
|
1574
|
+
}
|
|
1575
|
+
handleDockClick(mode) {
|
|
1576
|
+
this.setDockMode(mode);
|
|
1577
|
+
}
|
|
1578
|
+
serializeAttributes(attributes) {
|
|
1579
|
+
return Object.entries(attributes).filter(([key, value]) => key !== "key" && value !== void 0 && value !== null && value !== "").map(([key, value]) => `${key}="${String(value).replace(/"/g, """)}"`).join(" ");
|
|
1580
|
+
}
|
|
1581
|
+
sanitizeForLogging(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
|
|
1582
|
+
if (value === void 0) return "[undefined]";
|
|
1583
|
+
if (value === null || typeof value === "number" || typeof value === "boolean") return value;
|
|
1584
|
+
if (typeof value === "string") return value;
|
|
1585
|
+
if (typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") return String(value);
|
|
1586
|
+
if (value instanceof Date) return value.toISOString();
|
|
1587
|
+
if (Array.isArray(value)) {
|
|
1588
|
+
if (depth >= 4) return "[Truncated depth]";
|
|
1589
|
+
return value.map((item) => this.sanitizeForLogging(item, depth + 1, seen));
|
|
1590
|
+
}
|
|
1591
|
+
if (typeof value === "object") {
|
|
1592
|
+
if (seen.has(value)) return "[Circular]";
|
|
1593
|
+
seen.add(value);
|
|
1594
|
+
if (depth >= 4) return "[Truncated depth]";
|
|
1595
|
+
const result = {};
|
|
1596
|
+
for (const [key, entry] of Object.entries(value)) result[key] = this.sanitizeForLogging(entry, depth + 1, seen);
|
|
1597
|
+
return result;
|
|
1598
|
+
}
|
|
1599
|
+
return String(value);
|
|
1600
|
+
}
|
|
1601
|
+
normalizeEventPayload(_type, payload) {
|
|
1602
|
+
if (payload && typeof payload === "object" && "event" in payload) {
|
|
1603
|
+
const { event, ...rest } = payload;
|
|
1604
|
+
const cleaned = Object.keys(rest).length === 0 ? event : {
|
|
1605
|
+
event,
|
|
1606
|
+
...rest
|
|
1607
|
+
};
|
|
1608
|
+
return this.sanitizeForLogging(cleaned);
|
|
1609
|
+
}
|
|
1610
|
+
return this.sanitizeForLogging(payload);
|
|
1611
|
+
}
|
|
1612
|
+
normalizeMessageContent(content) {
|
|
1613
|
+
if (typeof content === "string") return content;
|
|
1614
|
+
if (content && typeof content === "object" && "text" in content) {
|
|
1615
|
+
const maybeText = content.text;
|
|
1616
|
+
if (typeof maybeText === "string") return maybeText;
|
|
1617
|
+
}
|
|
1618
|
+
if (content === null || content === void 0) return "";
|
|
1619
|
+
if (typeof content === "object") try {
|
|
1620
|
+
return JSON.stringify(this.sanitizeForLogging(content));
|
|
1621
|
+
} catch {
|
|
1622
|
+
return "";
|
|
1623
|
+
}
|
|
1624
|
+
return String(content);
|
|
1625
|
+
}
|
|
1626
|
+
normalizeToolCalls(raw) {
|
|
1627
|
+
if (!Array.isArray(raw)) return [];
|
|
1628
|
+
return raw.map((entry) => {
|
|
1629
|
+
if (!entry || typeof entry !== "object") return null;
|
|
1630
|
+
const call = entry;
|
|
1631
|
+
const fn = call.function;
|
|
1632
|
+
const functionName = typeof fn?.name === "string" ? fn.name : typeof call.toolName === "string" ? call.toolName : void 0;
|
|
1633
|
+
const args = fn && "arguments" in fn ? fn.arguments : call.arguments;
|
|
1634
|
+
const normalized = {
|
|
1635
|
+
id: typeof call.id === "string" ? call.id : void 0,
|
|
1636
|
+
toolName: typeof call.toolName === "string" ? call.toolName : functionName,
|
|
1637
|
+
status: typeof call.status === "string" ? call.status : void 0
|
|
1638
|
+
};
|
|
1639
|
+
if (functionName) normalized.function = {
|
|
1640
|
+
name: functionName,
|
|
1641
|
+
arguments: this.sanitizeForLogging(args)
|
|
1642
|
+
};
|
|
1643
|
+
return normalized;
|
|
1644
|
+
}).filter((call) => Boolean(call));
|
|
1645
|
+
}
|
|
1646
|
+
normalizeAgentMessage(message) {
|
|
1647
|
+
if (!message || typeof message !== "object") return null;
|
|
1648
|
+
const raw = message;
|
|
1649
|
+
const role = typeof raw.role === "string" ? raw.role : "unknown";
|
|
1650
|
+
const contentText = this.normalizeMessageContent(raw.content);
|
|
1651
|
+
const toolCalls = this.normalizeToolCalls(raw.toolCalls);
|
|
1652
|
+
return {
|
|
1653
|
+
id: typeof raw.id === "string" ? raw.id : void 0,
|
|
1654
|
+
role,
|
|
1655
|
+
contentText,
|
|
1656
|
+
contentRaw: raw.content !== void 0 ? this.sanitizeForLogging(raw.content) : void 0,
|
|
1657
|
+
toolCalls
|
|
1658
|
+
};
|
|
1659
|
+
}
|
|
1660
|
+
normalizeAgentMessages(messages) {
|
|
1661
|
+
if (!Array.isArray(messages)) return null;
|
|
1662
|
+
return messages.map((message) => this.normalizeAgentMessage(message)).filter((msg) => msg !== null);
|
|
1663
|
+
}
|
|
1664
|
+
normalizeContextStore(context) {
|
|
1665
|
+
if (!context || typeof context !== "object") return {};
|
|
1666
|
+
const normalized = {};
|
|
1667
|
+
for (const [key, entry] of Object.entries(context)) if (entry && typeof entry === "object" && "value" in entry) {
|
|
1668
|
+
const candidate = entry;
|
|
1669
|
+
normalized[key] = {
|
|
1670
|
+
description: typeof candidate.description === "string" && candidate.description.trim().length > 0 ? candidate.description : void 0,
|
|
1671
|
+
value: candidate.value
|
|
1672
|
+
};
|
|
1673
|
+
} else normalized[key] = { value: entry };
|
|
1674
|
+
return normalized;
|
|
1675
|
+
}
|
|
1676
|
+
getSelectedMenu() {
|
|
1677
|
+
return this.menuItems.find((item) => item.key === this.selectedMenu) ?? this.menuItems[0];
|
|
1678
|
+
}
|
|
1679
|
+
renderCoreWarningBanner() {
|
|
1680
|
+
if (this._core) return lit.nothing;
|
|
1681
|
+
return lit.html`
|
|
1682
|
+
<div
|
|
1683
|
+
class="mx-4 my-3 flex items-start gap-2 rounded-md border border-amber-200 bg-amber-50 px-3 py-2 text-xs text-amber-800"
|
|
1684
|
+
>
|
|
1685
|
+
<span class="mt-0.5 shrink-0 text-amber-600"
|
|
1686
|
+
>${this.renderIcon("AlertTriangle")}</span
|
|
1687
|
+
>
|
|
1688
|
+
<div class="space-y-1">
|
|
1689
|
+
<div class="font-semibold text-amber-900">
|
|
1690
|
+
CopilotKit core not attached
|
|
1691
|
+
</div>
|
|
1692
|
+
<p class="text-[11px] leading-snug text-amber-800">
|
|
1693
|
+
Pass a live <code>CopilotKitCore</code> instance to
|
|
1694
|
+
<code><cpk-web-inspector></code> or expose it on
|
|
1695
|
+
<code>window.__COPILOTKIT_CORE__</code> for auto-attach.
|
|
1696
|
+
</p>
|
|
1697
|
+
</div>
|
|
1698
|
+
</div>
|
|
1699
|
+
`;
|
|
1700
|
+
}
|
|
1701
|
+
getCoreStatusSummary() {
|
|
1702
|
+
if (!this._core) return {
|
|
1703
|
+
label: "Core not attached",
|
|
1704
|
+
tone: "border border-amber-200 bg-amber-50 text-amber-800",
|
|
1705
|
+
description: "Pass a CopilotKitCore instance to <cpk-web-inspector> or enable auto-attach."
|
|
1706
|
+
};
|
|
1707
|
+
const status = this.runtimeStatus ?? _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected;
|
|
1708
|
+
const lastErrorMessage = this.lastCoreError?.message;
|
|
1709
|
+
if (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) return {
|
|
1710
|
+
label: "Runtime error",
|
|
1711
|
+
tone: "border border-rose-200 bg-rose-50 text-rose-700",
|
|
1712
|
+
description: lastErrorMessage ?? "CopilotKit runtime reported an error."
|
|
1713
|
+
};
|
|
1714
|
+
if (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting) return {
|
|
1715
|
+
label: "Connecting",
|
|
1716
|
+
tone: "border border-amber-200 bg-amber-50 text-amber-800",
|
|
1717
|
+
description: "Waiting for CopilotKit runtime to finish connecting."
|
|
1718
|
+
};
|
|
1719
|
+
if (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return {
|
|
1720
|
+
label: "Connected",
|
|
1721
|
+
tone: "border border-emerald-200 bg-emerald-50 text-emerald-700",
|
|
1722
|
+
description: "Live runtime connection established."
|
|
1723
|
+
};
|
|
1724
|
+
return {
|
|
1725
|
+
label: "Disconnected",
|
|
1726
|
+
tone: "border border-gray-200 bg-gray-50 text-gray-700",
|
|
1727
|
+
description: lastErrorMessage ?? "Waiting for CopilotKit runtime to connect."
|
|
1728
|
+
};
|
|
1729
|
+
}
|
|
1730
|
+
renderMainContent() {
|
|
1731
|
+
if (this.selectedMenu === "ag-ui-events") return this.renderEventsTable();
|
|
1732
|
+
if (this.selectedMenu === "agents") return this.renderAgentsView();
|
|
1733
|
+
if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
|
|
1734
|
+
if (this.selectedMenu === "agent-context") return this.renderContextView();
|
|
1735
|
+
return lit.nothing;
|
|
1736
|
+
}
|
|
1737
|
+
renderEventsTable() {
|
|
1738
|
+
const events = this.getEventsForSelectedContext();
|
|
1739
|
+
const filteredEvents = this.filterEvents(events);
|
|
1740
|
+
const selectedLabel = this.selectedContext === "all-agents" ? "all agents" : `agent ${this.selectedContext}`;
|
|
1741
|
+
if (events.length === 0) return lit.html`
|
|
1742
|
+
<div
|
|
1743
|
+
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
1744
|
+
>
|
|
1745
|
+
<div class="max-w-md">
|
|
1746
|
+
<div
|
|
1747
|
+
class="mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
1748
|
+
>
|
|
1749
|
+
${this.renderIcon("Zap")}
|
|
1750
|
+
</div>
|
|
1751
|
+
<p class="text-sm text-gray-600">No events yet</p>
|
|
1752
|
+
<p class="mt-2 text-xs text-gray-500">
|
|
1753
|
+
Trigger an agent run to see live activity.
|
|
1754
|
+
</p>
|
|
1755
|
+
</div>
|
|
1756
|
+
</div>
|
|
1757
|
+
`;
|
|
1758
|
+
if (filteredEvents.length === 0) return lit.html`
|
|
1759
|
+
<div
|
|
1760
|
+
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
1761
|
+
>
|
|
1762
|
+
<div class="max-w-md space-y-3">
|
|
1763
|
+
<div
|
|
1764
|
+
class="flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
1765
|
+
>
|
|
1766
|
+
${this.renderIcon("Filter")}
|
|
1767
|
+
</div>
|
|
1768
|
+
<p class="text-sm text-gray-600">
|
|
1769
|
+
No events match the current filters.
|
|
1770
|
+
</p>
|
|
1771
|
+
<div>
|
|
1772
|
+
<button
|
|
1773
|
+
type="button"
|
|
1774
|
+
class="inline-flex items-center gap-1 rounded-md bg-gray-900 px-3 py-1.5 text-[11px] font-medium text-white transition hover:bg-gray-800"
|
|
1775
|
+
@click=${this.resetEventFilters}
|
|
1776
|
+
>
|
|
1777
|
+
${this.renderIcon("RefreshCw")}
|
|
1778
|
+
<span>Reset filters</span>
|
|
1779
|
+
</button>
|
|
1780
|
+
</div>
|
|
1781
|
+
</div>
|
|
1782
|
+
</div>
|
|
1783
|
+
`;
|
|
1784
|
+
return lit.html`
|
|
1785
|
+
<div class="flex h-full flex-col">
|
|
1786
|
+
<div
|
|
1787
|
+
class="flex flex-col gap-1.5 border-b border-gray-200 bg-white px-4 py-2.5"
|
|
1788
|
+
>
|
|
1789
|
+
<div class="flex flex-wrap items-center gap-2">
|
|
1790
|
+
<div class="relative min-w-[200px] flex-1">
|
|
1791
|
+
<input
|
|
1792
|
+
type="search"
|
|
1793
|
+
class="w-full rounded-md border border-gray-200 px-3 py-1.5 text-[11px] text-gray-700 shadow-sm outline-none ring-1 ring-transparent transition focus:border-gray-300 focus:ring-gray-200"
|
|
1794
|
+
placeholder="Search agent, type, payload"
|
|
1795
|
+
.value=${this.eventFilterText}
|
|
1796
|
+
@input=${this.handleEventFilterInput}
|
|
1797
|
+
/>
|
|
1798
|
+
</div>
|
|
1799
|
+
<select
|
|
1800
|
+
class="w-40 rounded-md border border-gray-200 bg-white px-2 py-1.5 text-[11px] text-gray-700 shadow-sm outline-none transition focus:border-gray-300 focus:ring-2 focus:ring-gray-200"
|
|
1801
|
+
.value=${this.eventTypeFilter}
|
|
1802
|
+
@change=${this.handleEventTypeChange}
|
|
1803
|
+
>
|
|
1804
|
+
<option value="all">All event types</option>
|
|
1805
|
+
${AGENT_EVENT_TYPES.map((type) => lit.html`<option value=${type}>
|
|
1806
|
+
${type.toLowerCase().replace(/_/g, " ")}
|
|
1807
|
+
</option>`)}
|
|
1808
|
+
</select>
|
|
1809
|
+
<div class="flex items-center gap-1 text-[11px]">
|
|
1810
|
+
<button
|
|
1811
|
+
type="button"
|
|
1812
|
+
class="tooltip-target flex h-8 w-8 items-center justify-center rounded-md border border-gray-200 bg-white text-gray-600 transition hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50"
|
|
1813
|
+
title="Reset filters"
|
|
1814
|
+
data-tooltip="Reset filters"
|
|
1815
|
+
aria-label="Reset filters"
|
|
1816
|
+
@click=${this.resetEventFilters}
|
|
1817
|
+
?disabled=${!this.eventFilterText && this.eventTypeFilter === "all"}
|
|
1818
|
+
>
|
|
1819
|
+
${this.renderIcon("RotateCw")}
|
|
1820
|
+
</button>
|
|
1821
|
+
<button
|
|
1822
|
+
type="button"
|
|
1823
|
+
class="tooltip-target flex h-8 w-8 items-center justify-center rounded-md border border-gray-200 bg-white text-gray-600 transition hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50"
|
|
1824
|
+
title="Export JSON"
|
|
1825
|
+
data-tooltip="Export JSON"
|
|
1826
|
+
aria-label="Export JSON"
|
|
1827
|
+
@click=${() => this.exportEvents(filteredEvents)}
|
|
1828
|
+
?disabled=${filteredEvents.length === 0}
|
|
1829
|
+
>
|
|
1830
|
+
${this.renderIcon("Download")}
|
|
1831
|
+
</button>
|
|
1832
|
+
<button
|
|
1833
|
+
type="button"
|
|
1834
|
+
class="tooltip-target flex h-8 w-8 items-center justify-center rounded-md border border-gray-200 bg-white text-gray-600 transition hover:bg-gray-50 disabled:cursor-not-allowed disabled:opacity-50"
|
|
1835
|
+
title="Clear events"
|
|
1836
|
+
data-tooltip="Clear events"
|
|
1837
|
+
aria-label="Clear events"
|
|
1838
|
+
@click=${this.handleClearEvents}
|
|
1839
|
+
?disabled=${events.length === 0}
|
|
1840
|
+
>
|
|
1841
|
+
${this.renderIcon("Trash2")}
|
|
1842
|
+
</button>
|
|
1843
|
+
</div>
|
|
1844
|
+
</div>
|
|
1845
|
+
<div class="text-[11px] text-gray-500">
|
|
1846
|
+
Showing ${filteredEvents.length} of
|
|
1847
|
+
${events.length}${this.selectedContext === "all-agents" ? "" : ` for ${selectedLabel}`}
|
|
1848
|
+
</div>
|
|
1849
|
+
</div>
|
|
1850
|
+
<div class="relative h-full w-full overflow-y-auto overflow-x-hidden">
|
|
1851
|
+
<table class="w-full table-fixed border-collapse text-xs box-border">
|
|
1852
|
+
<thead class="sticky top-0 z-10">
|
|
1853
|
+
<tr class="bg-white">
|
|
1854
|
+
<th
|
|
1855
|
+
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
1856
|
+
>
|
|
1857
|
+
Agent
|
|
1858
|
+
</th>
|
|
1859
|
+
<th
|
|
1860
|
+
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
1861
|
+
>
|
|
1862
|
+
Time
|
|
1863
|
+
</th>
|
|
1864
|
+
<th
|
|
1865
|
+
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
1866
|
+
>
|
|
1867
|
+
Event Type
|
|
1868
|
+
</th>
|
|
1869
|
+
<th
|
|
1870
|
+
class="border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900"
|
|
1871
|
+
>
|
|
1872
|
+
AG-UI Event
|
|
1873
|
+
</th>
|
|
1874
|
+
</tr>
|
|
1875
|
+
</thead>
|
|
1876
|
+
<tbody>
|
|
1877
|
+
${filteredEvents.map((event, index) => {
|
|
1878
|
+
const rowBg = index % 2 === 0 ? "bg-white" : "bg-gray-50/50";
|
|
1879
|
+
const badgeClasses = this.getEventBadgeClasses(event.type);
|
|
1880
|
+
const extractedEvent = this.extractEventFromPayload(event.payload);
|
|
1881
|
+
const inlineEvent = this.stringifyPayload(extractedEvent, false) || "—";
|
|
1882
|
+
const prettyEvent = this.stringifyPayload(extractedEvent, true) || inlineEvent;
|
|
1883
|
+
const isExpanded = this.expandedRows.has(event.id);
|
|
1884
|
+
return lit.html`
|
|
1885
|
+
<tr
|
|
1886
|
+
class="${rowBg} cursor-pointer transition hover:bg-blue-50/50"
|
|
1887
|
+
@click=${() => this.toggleRowExpansion(event.id)}
|
|
1888
|
+
>
|
|
1889
|
+
<td
|
|
1890
|
+
class="border-l border-r border-b border-gray-200 px-3 py-2"
|
|
1891
|
+
>
|
|
1892
|
+
<span class="font-mono text-[11px] text-gray-600"
|
|
1893
|
+
>${event.agentId}</span
|
|
1894
|
+
>
|
|
1895
|
+
</td>
|
|
1896
|
+
<td
|
|
1897
|
+
class="border-r border-b border-gray-200 px-3 py-2 font-mono text-[11px] text-gray-600"
|
|
1898
|
+
>
|
|
1899
|
+
<span title=${new Date(event.timestamp).toLocaleString()}>
|
|
1900
|
+
${new Date(event.timestamp).toLocaleTimeString()}
|
|
1901
|
+
</span>
|
|
1902
|
+
</td>
|
|
1903
|
+
<td class="border-r border-b border-gray-200 px-3 py-2">
|
|
1904
|
+
<span class=${badgeClasses}>${event.type}</span>
|
|
1905
|
+
</td>
|
|
1906
|
+
<td
|
|
1907
|
+
class="border-r border-b border-gray-200 px-3 py-2 font-mono text-[10px] text-gray-600 ${isExpanded ? "" : "truncate max-w-xs"}"
|
|
1908
|
+
>
|
|
1909
|
+
${isExpanded ? lit.html`
|
|
1910
|
+
<div class="group relative">
|
|
1911
|
+
<pre
|
|
1912
|
+
class="m-0 whitespace-pre-wrap break-words text-[10px] font-mono text-gray-600"
|
|
1913
|
+
>
|
|
1914
|
+
${prettyEvent}</pre
|
|
1915
|
+
>
|
|
1916
|
+
<button
|
|
1917
|
+
class="absolute right-0 top-0 cursor-pointer rounded px-2 py-1 text-[10px] opacity-0 transition group-hover:opacity-100 ${this.copiedEvents.has(event.id) ? "bg-green-100 text-green-700" : "bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900"}"
|
|
1918
|
+
@click=${(e) => {
|
|
1919
|
+
e.stopPropagation();
|
|
1920
|
+
this.copyToClipboard(prettyEvent, event.id);
|
|
1921
|
+
}}
|
|
1922
|
+
>
|
|
1923
|
+
${this.copiedEvents.has(event.id) ? lit.html`<span>✓ Copied</span>` : lit.html`<span>Copy</span>`}
|
|
1924
|
+
</button>
|
|
1925
|
+
</div>
|
|
1926
|
+
` : inlineEvent}
|
|
1927
|
+
</td>
|
|
1928
|
+
</tr>
|
|
1929
|
+
`;
|
|
1930
|
+
})}
|
|
1931
|
+
</tbody>
|
|
1932
|
+
</table>
|
|
1933
|
+
</div>
|
|
1934
|
+
</div>
|
|
1935
|
+
`;
|
|
1936
|
+
}
|
|
1937
|
+
handleEventFilterInput(event) {
|
|
1938
|
+
this.eventFilterText = event.target?.value ?? "";
|
|
1939
|
+
this.requestUpdate();
|
|
1940
|
+
}
|
|
1941
|
+
handleEventTypeChange(event) {
|
|
1942
|
+
const value = event.target?.value;
|
|
1943
|
+
if (!value) return;
|
|
1944
|
+
this.eventTypeFilter = value;
|
|
1945
|
+
this.requestUpdate();
|
|
1946
|
+
}
|
|
1947
|
+
resetEventFilters() {
|
|
1948
|
+
this.eventFilterText = "";
|
|
1949
|
+
this.eventTypeFilter = "all";
|
|
1950
|
+
this.requestUpdate();
|
|
1951
|
+
}
|
|
1952
|
+
exportEvents(events) {
|
|
1953
|
+
try {
|
|
1954
|
+
const payload = JSON.stringify(events, null, 2);
|
|
1955
|
+
const blob = new Blob([payload], { type: "application/json" });
|
|
1956
|
+
const url = URL.createObjectURL(blob);
|
|
1957
|
+
const anchor = document.createElement("a");
|
|
1958
|
+
anchor.href = url;
|
|
1959
|
+
anchor.download = `copilotkit-events-${Date.now()}.json`;
|
|
1960
|
+
anchor.click();
|
|
1961
|
+
URL.revokeObjectURL(url);
|
|
1962
|
+
} catch (error) {
|
|
1963
|
+
console.error("Failed to export events", error);
|
|
1964
|
+
}
|
|
1965
|
+
}
|
|
1966
|
+
renderAgentsView() {
|
|
1967
|
+
if (this.selectedContext === "all-agents") return lit.html`
|
|
1968
|
+
<div
|
|
1969
|
+
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
1970
|
+
>
|
|
1971
|
+
<div class="max-w-md">
|
|
1972
|
+
<div
|
|
1973
|
+
class="mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
1974
|
+
>
|
|
1975
|
+
${this.renderIcon("Bot")}
|
|
1976
|
+
</div>
|
|
1977
|
+
<p class="text-sm text-gray-600">No agent selected</p>
|
|
1978
|
+
<p class="mt-2 text-xs text-gray-500">
|
|
1979
|
+
Select an agent from the dropdown above to view details.
|
|
1980
|
+
</p>
|
|
1981
|
+
</div>
|
|
1982
|
+
</div>
|
|
1983
|
+
`;
|
|
1984
|
+
const agentId = this.selectedContext;
|
|
1985
|
+
const status = this.getAgentStatus(agentId);
|
|
1986
|
+
const stats = this.getAgentStats(agentId);
|
|
1987
|
+
const state = this.getLatestStateForAgent(agentId);
|
|
1988
|
+
const messages = this.getLatestMessagesForAgent(agentId);
|
|
1989
|
+
return lit.html`
|
|
1990
|
+
<div class="flex flex-col gap-4 p-4 overflow-auto">
|
|
1991
|
+
<!-- Agent Overview Card -->
|
|
1992
|
+
<div class="rounded-lg border border-gray-200 bg-white p-4">
|
|
1993
|
+
<div class="flex items-start justify-between mb-4">
|
|
1994
|
+
<div class="flex items-center gap-3">
|
|
1995
|
+
<div
|
|
1996
|
+
class="flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600"
|
|
1997
|
+
>
|
|
1998
|
+
${this.renderIcon("Bot")}
|
|
1999
|
+
</div>
|
|
2000
|
+
<div>
|
|
2001
|
+
<h3 class="font-semibold text-sm text-gray-900">${agentId}</h3>
|
|
2002
|
+
<span
|
|
2003
|
+
class="inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${{
|
|
2004
|
+
running: "bg-emerald-50 text-emerald-700",
|
|
2005
|
+
idle: "bg-gray-100 text-gray-600",
|
|
2006
|
+
error: "bg-rose-50 text-rose-700"
|
|
2007
|
+
}[status]} relative -translate-y-[2px]"
|
|
2008
|
+
>
|
|
2009
|
+
<span
|
|
2010
|
+
class="h-1.5 w-1.5 rounded-full ${status === "running" ? "bg-emerald-500 animate-pulse" : status === "error" ? "bg-rose-500" : "bg-gray-400"}"
|
|
2011
|
+
></span>
|
|
2012
|
+
${status.charAt(0).toUpperCase() + status.slice(1)}
|
|
2013
|
+
</span>
|
|
2014
|
+
</div>
|
|
2015
|
+
</div>
|
|
2016
|
+
${stats.lastActivity ? lit.html`<span class="text-xs text-gray-500"
|
|
2017
|
+
>Last activity:
|
|
2018
|
+
${new Date(stats.lastActivity).toLocaleTimeString()}</span
|
|
2019
|
+
>` : lit.nothing}
|
|
2020
|
+
</div>
|
|
2021
|
+
<div class="grid grid-cols-2 gap-4 md:grid-cols-4">
|
|
2022
|
+
<button
|
|
2023
|
+
type="button"
|
|
2024
|
+
class="rounded-md bg-gray-50 px-3 py-2 text-left transition hover:bg-gray-100 cursor-pointer overflow-hidden"
|
|
2025
|
+
@click=${() => this.handleMenuSelect("ag-ui-events")}
|
|
2026
|
+
title="View all events in AG-UI Events"
|
|
2027
|
+
>
|
|
2028
|
+
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2029
|
+
Total Events
|
|
2030
|
+
</div>
|
|
2031
|
+
<div class="text-lg font-semibold text-gray-900">
|
|
2032
|
+
${stats.totalEvents}
|
|
2033
|
+
</div>
|
|
2034
|
+
</button>
|
|
2035
|
+
<div class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden">
|
|
2036
|
+
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2037
|
+
Messages
|
|
2038
|
+
</div>
|
|
2039
|
+
<div class="text-lg font-semibold text-gray-900">
|
|
2040
|
+
${stats.messages}
|
|
2041
|
+
</div>
|
|
2042
|
+
</div>
|
|
2043
|
+
<div class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden">
|
|
2044
|
+
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2045
|
+
Tool Calls
|
|
2046
|
+
</div>
|
|
2047
|
+
<div class="text-lg font-semibold text-gray-900">
|
|
2048
|
+
${stats.toolCalls}
|
|
2049
|
+
</div>
|
|
2050
|
+
</div>
|
|
2051
|
+
<div class="rounded-md bg-gray-50 px-3 py-2 overflow-hidden">
|
|
2052
|
+
<div class="truncate whitespace-nowrap text-xs text-gray-600">
|
|
2053
|
+
Errors
|
|
2054
|
+
</div>
|
|
2055
|
+
<div class="text-lg font-semibold text-gray-900">
|
|
2056
|
+
${stats.errors}
|
|
2057
|
+
</div>
|
|
2058
|
+
</div>
|
|
2059
|
+
</div>
|
|
2060
|
+
</div>
|
|
2061
|
+
|
|
2062
|
+
<!-- Current State Section -->
|
|
2063
|
+
<div class="rounded-lg border border-gray-200 bg-white">
|
|
2064
|
+
<div class="border-b border-gray-200 px-4 py-3">
|
|
2065
|
+
<h4 class="text-sm font-semibold text-gray-900">Current State</h4>
|
|
2066
|
+
</div>
|
|
2067
|
+
<div class="overflow-auto p-4">
|
|
2068
|
+
${this.hasRenderableState(state) ? lit.html`
|
|
2069
|
+
<pre
|
|
2070
|
+
class="overflow-auto rounded-md bg-gray-50 p-3 text-xs text-gray-800 max-h-64"
|
|
2071
|
+
><code>${this.formatStateForDisplay(state)}</code></pre>
|
|
2072
|
+
` : lit.html`
|
|
2073
|
+
<div
|
|
2074
|
+
class="flex h-40 items-center justify-center text-xs text-gray-500"
|
|
2075
|
+
>
|
|
2076
|
+
<div class="flex items-center gap-2 text-gray-500">
|
|
2077
|
+
<span class="text-lg text-gray-400"
|
|
2078
|
+
>${this.renderIcon("Database")}</span
|
|
2079
|
+
>
|
|
2080
|
+
<span>State is empty</span>
|
|
2081
|
+
</div>
|
|
2082
|
+
</div>
|
|
2083
|
+
`}
|
|
2084
|
+
</div>
|
|
2085
|
+
</div>
|
|
2086
|
+
|
|
2087
|
+
<!-- Current Messages Section -->
|
|
2088
|
+
<div class="rounded-lg border border-gray-200 bg-white">
|
|
2089
|
+
<div class="border-b border-gray-200 px-4 py-3">
|
|
2090
|
+
<h4 class="text-sm font-semibold text-gray-900">
|
|
2091
|
+
Current Messages
|
|
2092
|
+
</h4>
|
|
2093
|
+
</div>
|
|
2094
|
+
<div class="overflow-auto">
|
|
2095
|
+
${messages && messages.length > 0 ? lit.html`
|
|
2096
|
+
<table class="w-full text-xs">
|
|
2097
|
+
<thead class="bg-gray-50">
|
|
2098
|
+
<tr>
|
|
2099
|
+
<th
|
|
2100
|
+
class="px-4 py-2 text-left font-medium text-gray-700"
|
|
2101
|
+
>
|
|
2102
|
+
Role
|
|
2103
|
+
</th>
|
|
2104
|
+
<th
|
|
2105
|
+
class="px-4 py-2 text-left font-medium text-gray-700"
|
|
2106
|
+
>
|
|
2107
|
+
Content
|
|
2108
|
+
</th>
|
|
2109
|
+
</tr>
|
|
2110
|
+
</thead>
|
|
2111
|
+
<tbody class="divide-y divide-gray-200">
|
|
2112
|
+
${messages.map((msg) => {
|
|
2113
|
+
const role = msg.role || "unknown";
|
|
2114
|
+
const roleColors = {
|
|
2115
|
+
user: "bg-blue-100 text-blue-800",
|
|
2116
|
+
assistant: "bg-green-100 text-green-800",
|
|
2117
|
+
system: "bg-gray-100 text-gray-800",
|
|
2118
|
+
tool: "bg-amber-100 text-amber-800",
|
|
2119
|
+
unknown: "bg-gray-100 text-gray-600"
|
|
2120
|
+
};
|
|
2121
|
+
const rawContent = msg.contentText ?? "";
|
|
2122
|
+
const toolCalls = msg.toolCalls ?? [];
|
|
2123
|
+
const hasContent = rawContent.trim().length > 0;
|
|
2124
|
+
const contentFallback = toolCalls.length > 0 ? "Invoked tool call" : "—";
|
|
2125
|
+
return lit.html`
|
|
2126
|
+
<tr>
|
|
2127
|
+
<td class="px-4 py-2 align-top">
|
|
2128
|
+
<span
|
|
2129
|
+
class="inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${roleColors[role] || roleColors.unknown}"
|
|
2130
|
+
>
|
|
2131
|
+
${role}
|
|
2132
|
+
</span>
|
|
2133
|
+
</td>
|
|
2134
|
+
<td class="px-4 py-2">
|
|
2135
|
+
${hasContent ? lit.html`<div
|
|
2136
|
+
class="max-w-2xl whitespace-pre-wrap break-words text-gray-700"
|
|
2137
|
+
>
|
|
2138
|
+
${rawContent}
|
|
2139
|
+
</div>` : lit.html`<div
|
|
2140
|
+
class="text-xs italic text-gray-400"
|
|
2141
|
+
>
|
|
2142
|
+
${contentFallback}
|
|
2143
|
+
</div>`}
|
|
2144
|
+
${role === "assistant" && toolCalls.length > 0 ? this.renderToolCallDetails(toolCalls) : lit.nothing}
|
|
2145
|
+
</td>
|
|
2146
|
+
</tr>
|
|
2147
|
+
`;
|
|
2148
|
+
})}
|
|
2149
|
+
</tbody>
|
|
2150
|
+
</table>
|
|
2151
|
+
` : lit.html`
|
|
2152
|
+
<div
|
|
2153
|
+
class="flex h-40 items-center justify-center text-xs text-gray-500"
|
|
2154
|
+
>
|
|
2155
|
+
<div class="flex items-center gap-2 text-gray-500">
|
|
2156
|
+
<span class="text-lg text-gray-400"
|
|
2157
|
+
>${this.renderIcon("MessageSquare")}</span
|
|
2158
|
+
>
|
|
2159
|
+
<span>No messages available</span>
|
|
2160
|
+
</div>
|
|
2161
|
+
</div>
|
|
2162
|
+
`}
|
|
2163
|
+
</div>
|
|
2164
|
+
</div>
|
|
2165
|
+
</div>
|
|
2166
|
+
`;
|
|
2167
|
+
}
|
|
2168
|
+
renderContextDropdown() {
|
|
2169
|
+
const filteredOptions = this.selectedMenu === "agents" ? this.contextOptions.filter((opt) => opt.key !== "all-agents") : this.contextOptions;
|
|
2170
|
+
const selectedLabel = filteredOptions.find((opt) => opt.key === this.selectedContext)?.label ?? "";
|
|
2171
|
+
return lit.html`
|
|
2172
|
+
<div
|
|
2173
|
+
class="relative z-40 min-w-0 flex-1"
|
|
2174
|
+
data-context-dropdown-root="true"
|
|
2175
|
+
>
|
|
2176
|
+
<button
|
|
2177
|
+
type="button"
|
|
2178
|
+
class="relative z-40 flex w-full min-w-0 max-w-[240px] items-center gap-1.5 rounded-md border border-gray-200 px-2 py-1 text-xs font-medium text-gray-700 transition hover:border-gray-300 hover:bg-gray-50"
|
|
2179
|
+
@pointerdown=${this.handleContextDropdownToggle}
|
|
2180
|
+
>
|
|
2181
|
+
<span class="truncate flex-1 text-left">${selectedLabel}</span>
|
|
2182
|
+
<span class="shrink-0 text-gray-400"
|
|
2183
|
+
>${this.renderIcon("ChevronDown")}</span
|
|
2184
|
+
>
|
|
2185
|
+
</button>
|
|
2186
|
+
${this.contextMenuOpen ? lit.html`
|
|
2187
|
+
<div
|
|
2188
|
+
class="absolute left-0 z-50 mt-1.5 w-40 rounded-md border border-gray-200 bg-white py-1 shadow-md ring-1 ring-black/5"
|
|
2189
|
+
data-context-dropdown-root="true"
|
|
2190
|
+
>
|
|
2191
|
+
${filteredOptions.map((option) => lit.html`
|
|
2192
|
+
<button
|
|
2193
|
+
type="button"
|
|
2194
|
+
class="flex w-full items-center justify-between px-3 py-1.5 text-left text-xs transition hover:bg-gray-50 focus:bg-gray-50 focus:outline-none"
|
|
2195
|
+
data-context-dropdown-root="true"
|
|
2196
|
+
@click=${() => this.handleContextOptionSelect(option.key)}
|
|
2197
|
+
>
|
|
2198
|
+
<span
|
|
2199
|
+
class="truncate ${option.key === this.selectedContext ? "text-gray-900 font-medium" : "text-gray-600"}"
|
|
2200
|
+
>${option.label}</span
|
|
2201
|
+
>
|
|
2202
|
+
${option.key === this.selectedContext ? lit.html`<span class="text-gray-500"
|
|
2203
|
+
>${this.renderIcon("Check")}</span
|
|
2204
|
+
>` : lit.nothing}
|
|
2205
|
+
</button>
|
|
2206
|
+
`)}
|
|
2207
|
+
</div>
|
|
2208
|
+
` : lit.nothing}
|
|
2209
|
+
</div>
|
|
2210
|
+
`;
|
|
2211
|
+
}
|
|
2212
|
+
handleMenuSelect(key) {
|
|
2213
|
+
if (!this.menuItems.some((item) => item.key === key)) return;
|
|
2214
|
+
this.selectedMenu = key;
|
|
2215
|
+
if (key === "agents" && this.selectedContext === "all-agents") {
|
|
2216
|
+
const agentOptions = this.contextOptions.filter((opt) => opt.key !== "all-agents");
|
|
2217
|
+
if (agentOptions.length > 0) {
|
|
2218
|
+
const defaultAgent = agentOptions.find((opt) => opt.key === "default");
|
|
2219
|
+
this.selectedContext = defaultAgent ? defaultAgent.key : agentOptions[0].key;
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
this.contextMenuOpen = false;
|
|
2223
|
+
this.persistState();
|
|
2224
|
+
this.requestUpdate();
|
|
2225
|
+
}
|
|
2226
|
+
handleContextDropdownToggle(event) {
|
|
2227
|
+
event.preventDefault();
|
|
2228
|
+
event.stopPropagation();
|
|
2229
|
+
this.contextMenuOpen = !this.contextMenuOpen;
|
|
2230
|
+
this.requestUpdate();
|
|
2231
|
+
}
|
|
2232
|
+
handleContextOptionSelect(key) {
|
|
2233
|
+
if (!this.contextOptions.some((option) => option.key === key)) return;
|
|
2234
|
+
if (this.selectedContext !== key) {
|
|
2235
|
+
this.selectedContext = key;
|
|
2236
|
+
this.expandedRows.clear();
|
|
2237
|
+
}
|
|
2238
|
+
this.contextMenuOpen = false;
|
|
2239
|
+
this.persistState();
|
|
2240
|
+
this.requestUpdate();
|
|
2241
|
+
}
|
|
2242
|
+
renderToolsView() {
|
|
2243
|
+
if (!this._core) return lit.html`
|
|
2244
|
+
<div
|
|
2245
|
+
class="flex h-full items-center justify-center px-4 py-8 text-xs text-gray-500"
|
|
2246
|
+
>
|
|
2247
|
+
No core instance available
|
|
2248
|
+
</div>
|
|
2249
|
+
`;
|
|
2250
|
+
this.refreshToolsSnapshot();
|
|
2251
|
+
const allTools = this.cachedTools;
|
|
2252
|
+
if (allTools.length === 0) return lit.html`
|
|
2253
|
+
<div
|
|
2254
|
+
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
2255
|
+
>
|
|
2256
|
+
<div class="max-w-md">
|
|
2257
|
+
<div
|
|
2258
|
+
class="mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
2259
|
+
>
|
|
2260
|
+
${this.renderIcon("Hammer")}
|
|
2261
|
+
</div>
|
|
2262
|
+
<p class="text-sm text-gray-600">No tools available</p>
|
|
2263
|
+
<p class="mt-2 text-xs text-gray-500">
|
|
2264
|
+
Tools will appear here once agents are configured with tool
|
|
2265
|
+
handlers or renderers.
|
|
2266
|
+
</p>
|
|
2267
|
+
</div>
|
|
2268
|
+
</div>
|
|
2269
|
+
`;
|
|
2270
|
+
return lit.html`
|
|
2271
|
+
<div class="flex h-full flex-col overflow-hidden">
|
|
2272
|
+
<div class="overflow-auto p-4">
|
|
2273
|
+
<div class="space-y-3">
|
|
2274
|
+
${(this.selectedContext === "all-agents" ? allTools : allTools.filter((tool) => !tool.agentId || tool.agentId === this.selectedContext)).map((tool) => this.renderToolCard(tool))}
|
|
2275
|
+
</div>
|
|
2276
|
+
</div>
|
|
2277
|
+
</div>
|
|
2278
|
+
`;
|
|
2279
|
+
}
|
|
2280
|
+
extractToolsFromAgents() {
|
|
2281
|
+
if (!this._core) return [];
|
|
2282
|
+
const tools = [];
|
|
2283
|
+
for (const coreTool of this._core.tools ?? []) tools.push({
|
|
2284
|
+
agentId: coreTool.agentId ?? "",
|
|
2285
|
+
name: coreTool.name,
|
|
2286
|
+
description: coreTool.description,
|
|
2287
|
+
parameters: coreTool.parameters,
|
|
2288
|
+
type: "handler"
|
|
2289
|
+
});
|
|
2290
|
+
for (const [agentId, agent] of Object.entries(this._core.agents)) {
|
|
2291
|
+
if (!agent) continue;
|
|
2292
|
+
const handlers = agent.toolHandlers;
|
|
2293
|
+
if (handlers && typeof handlers === "object") {
|
|
2294
|
+
for (const [toolName, handler] of Object.entries(handlers)) if (handler && typeof handler === "object") {
|
|
2295
|
+
const handlerObj = handler;
|
|
2296
|
+
tools.push({
|
|
2297
|
+
agentId,
|
|
2298
|
+
name: toolName,
|
|
2299
|
+
description: typeof handlerObj.description === "string" && handlerObj.description || handlerObj.tool?.description,
|
|
2300
|
+
parameters: handlerObj.parameters ?? handlerObj.tool?.parameters,
|
|
2301
|
+
type: "handler"
|
|
2302
|
+
});
|
|
2303
|
+
}
|
|
2304
|
+
}
|
|
2305
|
+
const renderers = agent.toolRenderers;
|
|
2306
|
+
if (renderers && typeof renderers === "object") {
|
|
2307
|
+
for (const [toolName, renderer] of Object.entries(renderers)) if (!tools.some((t) => t.agentId === agentId && t.name === toolName)) {
|
|
2308
|
+
if (renderer && typeof renderer === "object") {
|
|
2309
|
+
const rendererObj = renderer;
|
|
2310
|
+
tools.push({
|
|
2311
|
+
agentId,
|
|
2312
|
+
name: toolName,
|
|
2313
|
+
description: typeof rendererObj.description === "string" && rendererObj.description || rendererObj.tool?.description,
|
|
2314
|
+
parameters: rendererObj.parameters ?? rendererObj.tool?.parameters,
|
|
2315
|
+
type: "renderer"
|
|
2316
|
+
});
|
|
2317
|
+
}
|
|
2318
|
+
}
|
|
2319
|
+
}
|
|
2320
|
+
}
|
|
2321
|
+
return tools.sort((a, b) => {
|
|
2322
|
+
const agentCompare = a.agentId.localeCompare(b.agentId);
|
|
2323
|
+
if (agentCompare !== 0) return agentCompare;
|
|
2324
|
+
return a.name.localeCompare(b.name);
|
|
2325
|
+
});
|
|
2326
|
+
}
|
|
2327
|
+
renderToolCard(tool) {
|
|
2328
|
+
const isExpanded = this.expandedTools.has(`${tool.agentId}:${tool.name}`);
|
|
2329
|
+
const schema = this.extractSchemaInfo(tool.parameters);
|
|
2330
|
+
return lit.html`
|
|
2331
|
+
<div class="rounded-lg border border-gray-200 bg-white overflow-hidden">
|
|
2332
|
+
<button
|
|
2333
|
+
type="button"
|
|
2334
|
+
class="w-full px-4 py-3 text-left transition hover:bg-gray-50"
|
|
2335
|
+
@click=${() => this.toggleToolExpansion(`${tool.agentId}:${tool.name}`)}
|
|
2336
|
+
>
|
|
2337
|
+
<div class="flex items-start justify-between gap-3">
|
|
2338
|
+
<div class="flex-1 min-w-0">
|
|
2339
|
+
<div class="flex items-center gap-2 mb-1">
|
|
2340
|
+
<span class="font-mono text-sm font-semibold text-gray-900"
|
|
2341
|
+
>${tool.name}</span
|
|
2342
|
+
>
|
|
2343
|
+
<span
|
|
2344
|
+
class="inline-flex items-center rounded-sm border px-1.5 py-0.5 text-[10px] font-medium ${{
|
|
2345
|
+
handler: "bg-blue-50 text-blue-700 border-blue-200",
|
|
2346
|
+
renderer: "bg-purple-50 text-purple-700 border-purple-200"
|
|
2347
|
+
}[tool.type]}"
|
|
2348
|
+
>
|
|
2349
|
+
${tool.type}
|
|
2350
|
+
</span>
|
|
2351
|
+
</div>
|
|
2352
|
+
<div class="flex items-center gap-2 text-xs text-gray-500">
|
|
2353
|
+
<span class="flex items-center gap-1">
|
|
2354
|
+
${this.renderIcon("Bot")}
|
|
2355
|
+
<span class="font-mono">${tool.agentId}</span>
|
|
2356
|
+
</span>
|
|
2357
|
+
${schema.properties.length > 0 ? lit.html`
|
|
2358
|
+
<span class="text-gray-300">•</span>
|
|
2359
|
+
<span
|
|
2360
|
+
>${schema.properties.length}
|
|
2361
|
+
parameter${schema.properties.length !== 1 ? "s" : ""}</span
|
|
2362
|
+
>
|
|
2363
|
+
` : lit.nothing}
|
|
2364
|
+
</div>
|
|
2365
|
+
${tool.description ? lit.html`<p class="mt-2 text-xs text-gray-600">
|
|
2366
|
+
${tool.description}
|
|
2367
|
+
</p>` : lit.nothing}
|
|
2368
|
+
</div>
|
|
2369
|
+
<span
|
|
2370
|
+
class="shrink-0 text-gray-400 transition ${isExpanded ? "rotate-180" : ""}"
|
|
2371
|
+
>
|
|
2372
|
+
${this.renderIcon("ChevronDown")}
|
|
2373
|
+
</span>
|
|
2374
|
+
</div>
|
|
2375
|
+
</button>
|
|
2376
|
+
|
|
2377
|
+
${isExpanded ? lit.html`
|
|
2378
|
+
<div class="border-t border-gray-200 bg-gray-50/50 px-4 py-3">
|
|
2379
|
+
${schema.properties.length > 0 ? lit.html`
|
|
2380
|
+
<h5 class="mb-3 text-xs font-semibold text-gray-700">
|
|
2381
|
+
Parameters
|
|
2382
|
+
</h5>
|
|
2383
|
+
<div class="space-y-3">
|
|
2384
|
+
${schema.properties.map((prop) => lit.html`
|
|
2385
|
+
<div
|
|
2386
|
+
class="rounded-md border border-gray-200 bg-white p-3"
|
|
2387
|
+
>
|
|
2388
|
+
<div
|
|
2389
|
+
class="flex items-start justify-between gap-2 mb-1"
|
|
2390
|
+
>
|
|
2391
|
+
<span
|
|
2392
|
+
class="font-mono text-xs font-medium text-gray-900"
|
|
2393
|
+
>${prop.name}</span
|
|
2394
|
+
>
|
|
2395
|
+
<div class="flex items-center gap-1.5 shrink-0">
|
|
2396
|
+
${prop.required ? lit.html`<span
|
|
2397
|
+
class="text-[9px] rounded border border-rose-200 bg-rose-50 px-1 py-0.5 font-medium text-rose-700"
|
|
2398
|
+
>required</span
|
|
2399
|
+
>` : lit.html`<span
|
|
2400
|
+
class="text-[9px] rounded border border-gray-200 bg-gray-50 px-1 py-0.5 font-medium text-gray-600"
|
|
2401
|
+
>optional</span
|
|
2402
|
+
>`}
|
|
2403
|
+
${prop.type ? lit.html`<span
|
|
2404
|
+
class="text-[9px] rounded border border-gray-200 bg-gray-50 px-1 py-0.5 font-mono text-gray-600"
|
|
2405
|
+
>${prop.type}</span
|
|
2406
|
+
>` : lit.nothing}
|
|
2407
|
+
</div>
|
|
2408
|
+
</div>
|
|
2409
|
+
${prop.description ? lit.html`<p class="mt-1 text-xs text-gray-600">
|
|
2410
|
+
${prop.description}
|
|
2411
|
+
</p>` : lit.nothing}
|
|
2412
|
+
${prop.defaultValue !== void 0 ? lit.html`
|
|
2413
|
+
<div
|
|
2414
|
+
class="mt-2 flex items-center gap-1.5 text-[10px] text-gray-500"
|
|
2415
|
+
>
|
|
2416
|
+
<span>Default:</span>
|
|
2417
|
+
<code
|
|
2418
|
+
class="rounded bg-gray-100 px-1 py-0.5 font-mono"
|
|
2419
|
+
>${JSON.stringify(prop.defaultValue)}</code
|
|
2420
|
+
>
|
|
2421
|
+
</div>
|
|
2422
|
+
` : lit.nothing}
|
|
2423
|
+
${prop.enum && prop.enum.length > 0 ? lit.html`
|
|
2424
|
+
<div class="mt-2">
|
|
2425
|
+
<span class="text-[10px] text-gray-500"
|
|
2426
|
+
>Allowed values:</span
|
|
2427
|
+
>
|
|
2428
|
+
<div class="mt-1 flex flex-wrap gap-1">
|
|
2429
|
+
${prop.enum.map((val) => lit.html`
|
|
2430
|
+
<code
|
|
2431
|
+
class="rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[10px] font-mono text-gray-700"
|
|
2432
|
+
>${JSON.stringify(val)}</code
|
|
2433
|
+
>
|
|
2434
|
+
`)}
|
|
2435
|
+
</div>
|
|
2436
|
+
</div>
|
|
2437
|
+
` : lit.nothing}
|
|
2438
|
+
</div>
|
|
2439
|
+
`)}
|
|
2440
|
+
</div>
|
|
2441
|
+
` : lit.html`
|
|
2442
|
+
<div
|
|
2443
|
+
class="flex items-center justify-center py-4 text-xs text-gray-500"
|
|
2444
|
+
>
|
|
2445
|
+
<span>No parameters defined</span>
|
|
2446
|
+
</div>
|
|
2447
|
+
`}
|
|
2448
|
+
</div>
|
|
2449
|
+
` : lit.nothing}
|
|
2450
|
+
</div>
|
|
2451
|
+
`;
|
|
2452
|
+
}
|
|
2453
|
+
extractSchemaInfo(parameters) {
|
|
2454
|
+
const result = { properties: [] };
|
|
2455
|
+
if (!parameters || typeof parameters !== "object") return result;
|
|
2456
|
+
const zodDef = parameters._def;
|
|
2457
|
+
if (zodDef && typeof zodDef === "object") {
|
|
2458
|
+
if (zodDef.typeName === "ZodObject") {
|
|
2459
|
+
const rawShape = zodDef.shape;
|
|
2460
|
+
const shape = typeof rawShape === "function" ? rawShape() : rawShape;
|
|
2461
|
+
if (!shape || typeof shape !== "object") return result;
|
|
2462
|
+
const requiredKeys = /* @__PURE__ */ new Set();
|
|
2463
|
+
if (zodDef.unknownKeys === "strict" || !zodDef.catchall) Object.keys(shape || {}).forEach((key) => {
|
|
2464
|
+
const candidate = shape[key];
|
|
2465
|
+
if (candidate?._def && !this.isZodOptional(candidate)) requiredKeys.add(key);
|
|
2466
|
+
});
|
|
2467
|
+
for (const [key, value] of Object.entries(shape || {})) {
|
|
2468
|
+
const fieldInfo = this.extractZodFieldInfo(value);
|
|
2469
|
+
result.properties.push({
|
|
2470
|
+
name: key,
|
|
2471
|
+
type: fieldInfo.type,
|
|
2472
|
+
description: fieldInfo.description,
|
|
2473
|
+
required: requiredKeys.has(key),
|
|
2474
|
+
defaultValue: fieldInfo.defaultValue,
|
|
2475
|
+
enum: fieldInfo.enum
|
|
2476
|
+
});
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
} else if (parameters.type === "object" && parameters.properties) {
|
|
2480
|
+
const props = parameters.properties;
|
|
2481
|
+
const required = new Set(Array.isArray(parameters.required) ? parameters.required : []);
|
|
2482
|
+
for (const [key, value] of Object.entries(props ?? {})) {
|
|
2483
|
+
const prop = value;
|
|
2484
|
+
result.properties.push({
|
|
2485
|
+
name: key,
|
|
2486
|
+
type: prop.type,
|
|
2487
|
+
description: typeof prop.description === "string" ? prop.description : void 0,
|
|
2488
|
+
required: required.has(key),
|
|
2489
|
+
defaultValue: prop.default,
|
|
2490
|
+
enum: Array.isArray(prop.enum) ? prop.enum : void 0
|
|
2491
|
+
});
|
|
2492
|
+
}
|
|
2493
|
+
}
|
|
2494
|
+
return result;
|
|
2495
|
+
}
|
|
2496
|
+
isZodOptional(zodSchema) {
|
|
2497
|
+
const schema = zodSchema;
|
|
2498
|
+
if (!schema?._def) return false;
|
|
2499
|
+
const def = schema._def;
|
|
2500
|
+
if (def.typeName === "ZodOptional" || def.typeName === "ZodNullable") return true;
|
|
2501
|
+
if (def.defaultValue !== void 0) return true;
|
|
2502
|
+
return false;
|
|
2503
|
+
}
|
|
2504
|
+
extractZodFieldInfo(zodSchema) {
|
|
2505
|
+
const info = {};
|
|
2506
|
+
const schema = zodSchema;
|
|
2507
|
+
if (!schema?._def) return info;
|
|
2508
|
+
let currentSchema = schema;
|
|
2509
|
+
let def = currentSchema._def;
|
|
2510
|
+
while (def.typeName === "ZodOptional" || def.typeName === "ZodNullable" || def.typeName === "ZodDefault") {
|
|
2511
|
+
if (def.typeName === "ZodDefault" && def.defaultValue !== void 0) info.defaultValue = typeof def.defaultValue === "function" ? def.defaultValue() : def.defaultValue;
|
|
2512
|
+
currentSchema = def.innerType ?? currentSchema;
|
|
2513
|
+
if (!currentSchema?._def) break;
|
|
2514
|
+
def = currentSchema._def;
|
|
2515
|
+
}
|
|
2516
|
+
info.description = typeof def.description === "string" ? def.description : void 0;
|
|
2517
|
+
const typeName = typeof def.typeName === "string" ? def.typeName : void 0;
|
|
2518
|
+
info.type = typeName ? {
|
|
2519
|
+
ZodString: "string",
|
|
2520
|
+
ZodNumber: "number",
|
|
2521
|
+
ZodBoolean: "boolean",
|
|
2522
|
+
ZodArray: "array",
|
|
2523
|
+
ZodObject: "object",
|
|
2524
|
+
ZodEnum: "enum",
|
|
2525
|
+
ZodLiteral: "literal",
|
|
2526
|
+
ZodUnion: "union",
|
|
2527
|
+
ZodAny: "any",
|
|
2528
|
+
ZodUnknown: "unknown"
|
|
2529
|
+
}[typeName] || typeName.replace("Zod", "").toLowerCase() : void 0;
|
|
2530
|
+
if (typeName === "ZodEnum" && Array.isArray(def.values)) info.enum = def.values;
|
|
2531
|
+
else if (typeName === "ZodLiteral" && def.value !== void 0) info.enum = [def.value];
|
|
2532
|
+
return info;
|
|
2533
|
+
}
|
|
2534
|
+
toggleToolExpansion(toolId) {
|
|
2535
|
+
if (this.expandedTools.has(toolId)) this.expandedTools.delete(toolId);
|
|
2536
|
+
else this.expandedTools.add(toolId);
|
|
2537
|
+
this.requestUpdate();
|
|
2538
|
+
}
|
|
2539
|
+
renderContextView() {
|
|
2540
|
+
const contextEntries = Object.entries(this.contextStore);
|
|
2541
|
+
if (contextEntries.length === 0) return lit.html`
|
|
2542
|
+
<div
|
|
2543
|
+
class="flex h-full items-center justify-center px-4 py-8 text-center"
|
|
2544
|
+
>
|
|
2545
|
+
<div class="max-w-md">
|
|
2546
|
+
<div
|
|
2547
|
+
class="mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8"
|
|
2548
|
+
>
|
|
2549
|
+
${this.renderIcon("FileText")}
|
|
2550
|
+
</div>
|
|
2551
|
+
<p class="text-sm text-gray-600">No context available</p>
|
|
2552
|
+
<p class="mt-2 text-xs text-gray-500">
|
|
2553
|
+
Context will appear here once added to CopilotKit.
|
|
2554
|
+
</p>
|
|
2555
|
+
</div>
|
|
2556
|
+
</div>
|
|
2557
|
+
`;
|
|
2558
|
+
return lit.html`
|
|
2559
|
+
<div class="flex h-full flex-col overflow-hidden">
|
|
2560
|
+
<div class="overflow-auto p-4">
|
|
2561
|
+
<div class="space-y-3">
|
|
2562
|
+
${contextEntries.map(([id, context]) => this.renderContextCard(id, context))}
|
|
2563
|
+
</div>
|
|
2564
|
+
</div>
|
|
2565
|
+
</div>
|
|
2566
|
+
`;
|
|
2567
|
+
}
|
|
2568
|
+
renderContextCard(id, context) {
|
|
2569
|
+
const isExpanded = this.expandedContextItems.has(id);
|
|
2570
|
+
const valuePreview = this.getContextValuePreview(context.value);
|
|
2571
|
+
const hasValue = context.value !== void 0 && context.value !== null;
|
|
2572
|
+
return lit.html`
|
|
2573
|
+
<div class="rounded-lg border border-gray-200 bg-white overflow-hidden">
|
|
2574
|
+
<button
|
|
2575
|
+
type="button"
|
|
2576
|
+
class="w-full px-4 py-3 text-left transition hover:bg-gray-50"
|
|
2577
|
+
@click=${() => this.toggleContextExpansion(id)}
|
|
2578
|
+
>
|
|
2579
|
+
<div class="flex items-start justify-between gap-3">
|
|
2580
|
+
<div class="flex-1 min-w-0">
|
|
2581
|
+
<p class="text-sm font-medium text-gray-900 mb-1">${context.description?.trim() || id}</p>
|
|
2582
|
+
<div class="flex items-center gap-2 text-xs text-gray-500">
|
|
2583
|
+
<span
|
|
2584
|
+
class="font-mono truncate inline-block align-middle"
|
|
2585
|
+
style="max-width: 180px;"
|
|
2586
|
+
>${id}</span
|
|
2587
|
+
>
|
|
2588
|
+
${hasValue ? lit.html`
|
|
2589
|
+
<span class="text-gray-300">•</span>
|
|
2590
|
+
<span class="truncate">${valuePreview}</span>
|
|
2591
|
+
` : lit.nothing}
|
|
2592
|
+
</div>
|
|
2593
|
+
</div>
|
|
2594
|
+
<span
|
|
2595
|
+
class="shrink-0 text-gray-400 transition ${isExpanded ? "rotate-180" : ""}"
|
|
2596
|
+
>
|
|
2597
|
+
${this.renderIcon("ChevronDown")}
|
|
2598
|
+
</span>
|
|
2599
|
+
</div>
|
|
2600
|
+
</button>
|
|
2601
|
+
|
|
2602
|
+
${isExpanded ? lit.html`
|
|
2603
|
+
<div class="border-t border-gray-200 bg-gray-50/50 px-4 py-3">
|
|
2604
|
+
<div class="mb-3">
|
|
2605
|
+
<h5 class="mb-1 text-xs font-semibold text-gray-700">ID</h5>
|
|
2606
|
+
<code
|
|
2607
|
+
class="block rounded bg-white border border-gray-200 px-2 py-1 text-[10px] font-mono text-gray-600"
|
|
2608
|
+
>${id}</code
|
|
2609
|
+
>
|
|
2610
|
+
</div>
|
|
2611
|
+
${hasValue ? lit.html`
|
|
2612
|
+
<div class="mb-2 flex items-center justify-between gap-2">
|
|
2613
|
+
<h5 class="text-xs font-semibold text-gray-700">
|
|
2614
|
+
Value
|
|
2615
|
+
</h5>
|
|
2616
|
+
<button
|
|
2617
|
+
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"
|
|
2618
|
+
type="button"
|
|
2619
|
+
@click=${(e) => {
|
|
2620
|
+
e.stopPropagation();
|
|
2621
|
+
this.copyContextValue(context.value, id);
|
|
2622
|
+
}}
|
|
2623
|
+
>
|
|
2624
|
+
${this.copiedContextItems.has(id) ? "Copied" : "Copy JSON"}
|
|
2625
|
+
</button>
|
|
2626
|
+
</div>
|
|
2627
|
+
<div
|
|
2628
|
+
class="rounded-md border border-gray-200 bg-white p-3"
|
|
2629
|
+
>
|
|
2630
|
+
<pre
|
|
2631
|
+
class="overflow-auto text-xs text-gray-800 max-h-96"
|
|
2632
|
+
><code>${this.formatContextValue(context.value)}</code></pre>
|
|
2633
|
+
</div>
|
|
2634
|
+
` : lit.html`
|
|
2635
|
+
<div
|
|
2636
|
+
class="flex items-center justify-center py-4 text-xs text-gray-500"
|
|
2637
|
+
>
|
|
2638
|
+
<span>No value available</span>
|
|
2639
|
+
</div>
|
|
2640
|
+
`}
|
|
2641
|
+
</div>
|
|
2642
|
+
` : lit.nothing}
|
|
2643
|
+
</div>
|
|
2644
|
+
`;
|
|
2645
|
+
}
|
|
2646
|
+
getContextValuePreview(value) {
|
|
2647
|
+
if (value === void 0 || value === null) return "—";
|
|
2648
|
+
if (typeof value === "string") return value.length > 50 ? `${value.substring(0, 50)}...` : value;
|
|
2649
|
+
if (typeof value === "number" || typeof value === "boolean") return String(value);
|
|
2650
|
+
if (Array.isArray(value)) return `Array(${value.length})`;
|
|
2651
|
+
if (typeof value === "object") {
|
|
2652
|
+
const keys = Object.keys(value);
|
|
2653
|
+
return `Object with ${keys.length} key${keys.length !== 1 ? "s" : ""}`;
|
|
2654
|
+
}
|
|
2655
|
+
if (typeof value === "function") return "Function";
|
|
2656
|
+
return String(value);
|
|
2657
|
+
}
|
|
2658
|
+
formatContextValue(value) {
|
|
2659
|
+
if (value === void 0) return "undefined";
|
|
2660
|
+
if (value === null) return "null";
|
|
2661
|
+
if (typeof value === "function") return value.toString();
|
|
2662
|
+
try {
|
|
2663
|
+
return JSON.stringify(value, null, 2);
|
|
2664
|
+
} catch {
|
|
2665
|
+
return String(value);
|
|
2666
|
+
}
|
|
2667
|
+
}
|
|
2668
|
+
async copyContextValue(value, contextId) {
|
|
2669
|
+
if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
|
|
2670
|
+
console.warn("Clipboard API is not available in this environment.");
|
|
2671
|
+
return;
|
|
2672
|
+
}
|
|
2673
|
+
const serialized = this.formatContextValue(value);
|
|
2674
|
+
try {
|
|
2675
|
+
await navigator.clipboard.writeText(serialized);
|
|
2676
|
+
this.copiedContextItems.add(contextId);
|
|
2677
|
+
this.requestUpdate();
|
|
2678
|
+
setTimeout(() => {
|
|
2679
|
+
this.copiedContextItems.delete(contextId);
|
|
2680
|
+
this.requestUpdate();
|
|
2681
|
+
}, 1500);
|
|
2682
|
+
} catch (error) {
|
|
2683
|
+
console.error("Failed to copy context value:", error);
|
|
2684
|
+
}
|
|
2685
|
+
}
|
|
2686
|
+
toggleContextExpansion(contextId) {
|
|
2687
|
+
if (this.expandedContextItems.has(contextId)) this.expandedContextItems.delete(contextId);
|
|
2688
|
+
else this.expandedContextItems.add(contextId);
|
|
2689
|
+
this.requestUpdate();
|
|
2690
|
+
}
|
|
2691
|
+
toggleRowExpansion(eventId) {
|
|
2692
|
+
const selection = window.getSelection();
|
|
2693
|
+
if (selection && selection.toString().length > 0) return;
|
|
2694
|
+
if (this.expandedRows.has(eventId)) this.expandedRows.delete(eventId);
|
|
2695
|
+
else this.expandedRows.add(eventId);
|
|
2696
|
+
this.requestUpdate();
|
|
2697
|
+
}
|
|
2698
|
+
renderAnnouncementPanel() {
|
|
2699
|
+
if (!this.isOpen) return lit.nothing;
|
|
2700
|
+
this.ensureAnnouncementLoading();
|
|
2701
|
+
if (!this.hasUnseenAnnouncement) return lit.nothing;
|
|
2702
|
+
if (!this.announcementLoaded && !this.announcementMarkdown) return lit.html`<div
|
|
2703
|
+
class="mx-4 my-3 rounded-xl border border-slate-200 bg-white px-4 py-3 text-sm text-slate-800 shadow-[0_12px_30px_rgba(15,23,42,0.12)]"
|
|
2704
|
+
>
|
|
2705
|
+
<div class="flex items-center gap-2 font-semibold">
|
|
2706
|
+
<span
|
|
2707
|
+
class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm"
|
|
2708
|
+
>
|
|
2709
|
+
${this.renderIcon("Megaphone")}
|
|
2710
|
+
</span>
|
|
2711
|
+
<span>Loading latest announcement…</span>
|
|
2712
|
+
</div>
|
|
2713
|
+
</div>`;
|
|
2714
|
+
if (this.announcementLoadError) return lit.html`<div
|
|
2715
|
+
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)]"
|
|
2716
|
+
>
|
|
2717
|
+
<div class="flex items-center gap-2 font-semibold">
|
|
2718
|
+
<span
|
|
2719
|
+
class="inline-flex h-6 w-6 items-center justify-center rounded-md bg-rose-600 text-white shadow-sm"
|
|
2720
|
+
>
|
|
2721
|
+
${this.renderIcon("Megaphone")}
|
|
2722
|
+
</span>
|
|
2723
|
+
<span>Announcement unavailable</span>
|
|
2724
|
+
</div>
|
|
2725
|
+
<p class="mt-2 text-xs text-rose-800">
|
|
2726
|
+
We couldn’t load the latest notice. Please try opening the inspector
|
|
2727
|
+
again.
|
|
2728
|
+
</p>
|
|
2729
|
+
</div>`;
|
|
2730
|
+
if (!this.announcementMarkdown) return lit.nothing;
|
|
2731
|
+
const content = this.announcementHtml ? (0, lit_directives_unsafe_html_js.unsafeHTML)(this.announcementHtml) : lit.html`<pre class="whitespace-pre-wrap text-sm text-gray-900">
|
|
2732
|
+
${this.announcementMarkdown}</pre
|
|
2733
|
+
>`;
|
|
2734
|
+
return lit.html`<div
|
|
2735
|
+
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)]"
|
|
2736
|
+
>
|
|
2737
|
+
<div
|
|
2738
|
+
class="mb-3 flex items-center gap-2 text-sm font-semibold text-slate-900"
|
|
2739
|
+
>
|
|
2740
|
+
<span
|
|
2741
|
+
class="inline-flex h-7 w-7 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm"
|
|
2742
|
+
>
|
|
2743
|
+
${this.renderIcon("Megaphone")}
|
|
2744
|
+
</span>
|
|
2745
|
+
<span>Announcement</span>
|
|
2746
|
+
<button
|
|
2747
|
+
class="announcement-dismiss ml-auto"
|
|
2748
|
+
type="button"
|
|
2749
|
+
@click=${this.handleDismissAnnouncement}
|
|
2750
|
+
aria-label="Dismiss announcement"
|
|
2751
|
+
>
|
|
2752
|
+
Dismiss
|
|
2753
|
+
</button>
|
|
2754
|
+
</div>
|
|
2755
|
+
<div class="announcement-content text-sm leading-relaxed text-gray-900">
|
|
2756
|
+
${content}
|
|
2757
|
+
</div>
|
|
2758
|
+
</div>`;
|
|
2759
|
+
}
|
|
2760
|
+
ensureAnnouncementLoading() {
|
|
2761
|
+
if (this.announcementPromise || typeof window === "undefined" || typeof fetch === "undefined") return;
|
|
2762
|
+
this.announcementPromise = this.fetchAnnouncement();
|
|
2763
|
+
}
|
|
2764
|
+
renderAnnouncementPreview() {
|
|
2765
|
+
if (!this.hasUnseenAnnouncement || !this.showAnnouncementPreview || !this.announcementPreviewText) return lit.nothing;
|
|
2766
|
+
return lit.html`<div
|
|
2767
|
+
class="announcement-preview"
|
|
2768
|
+
data-side=${this.contextState.button.anchor.horizontal === "left" ? "right" : "left"}
|
|
2769
|
+
role="note"
|
|
2770
|
+
@click=${() => this.handleAnnouncementPreviewClick()}
|
|
2771
|
+
>
|
|
2772
|
+
<span>${this.announcementPreviewText}</span>
|
|
2773
|
+
<span class="announcement-preview__arrow"></span>
|
|
2774
|
+
</div>`;
|
|
2775
|
+
}
|
|
2776
|
+
handleAnnouncementPreviewClick() {
|
|
2777
|
+
this.showAnnouncementPreview = false;
|
|
2778
|
+
this.openInspector();
|
|
2779
|
+
}
|
|
2780
|
+
async fetchAnnouncement() {
|
|
2781
|
+
try {
|
|
2782
|
+
const response = await fetch(ANNOUNCEMENT_URL, { cache: "no-cache" });
|
|
2783
|
+
if (!response.ok) throw new Error(`Failed to load announcement (${response.status})`);
|
|
2784
|
+
const data = await response.json();
|
|
2785
|
+
const timestamp = typeof data?.timestamp === "string" ? data.timestamp : null;
|
|
2786
|
+
const previewText = typeof data?.previewText === "string" ? data.previewText : null;
|
|
2787
|
+
const markdown = typeof data?.announcement === "string" ? data.announcement : null;
|
|
2788
|
+
if (!timestamp || !markdown) throw new Error("Malformed announcement payload");
|
|
2789
|
+
const storedTimestamp = this.loadStoredAnnouncementTimestamp();
|
|
2790
|
+
this.announcementTimestamp = timestamp;
|
|
2791
|
+
this.announcementPreviewText = previewText ?? "";
|
|
2792
|
+
this.announcementMarkdown = markdown;
|
|
2793
|
+
this.hasUnseenAnnouncement = (!storedTimestamp || storedTimestamp !== timestamp) && !!this.announcementPreviewText;
|
|
2794
|
+
this.showAnnouncementPreview = this.hasUnseenAnnouncement;
|
|
2795
|
+
this.announcementHtml = await this.convertMarkdownToHtml(markdown);
|
|
2796
|
+
this.announcementLoaded = true;
|
|
2797
|
+
this.requestUpdate();
|
|
2798
|
+
} catch (error) {
|
|
2799
|
+
this.announcementLoadError = error;
|
|
2800
|
+
this.announcementLoaded = true;
|
|
2801
|
+
this.requestUpdate();
|
|
2802
|
+
}
|
|
2803
|
+
}
|
|
2804
|
+
async convertMarkdownToHtml(markdown) {
|
|
2805
|
+
const renderer = new marked.marked.Renderer();
|
|
2806
|
+
renderer.link = (href, title, text) => {
|
|
2807
|
+
return `<a href="${this.escapeHtmlAttr(this.appendRefParam(href ?? ""))}" target="_blank" rel="noopener"${title ? ` title="${this.escapeHtmlAttr(title)}"` : ""}>${text}</a>`;
|
|
2808
|
+
};
|
|
2809
|
+
return marked.marked.parse(markdown, { renderer });
|
|
2810
|
+
}
|
|
2811
|
+
appendRefParam(href) {
|
|
2812
|
+
try {
|
|
2813
|
+
const url = new URL(href, typeof window !== "undefined" ? window.location.href : "https://copilotkit.ai");
|
|
2814
|
+
if (!url.searchParams.has("ref")) url.searchParams.append("ref", "cpk-inspector");
|
|
2815
|
+
return url.toString();
|
|
2816
|
+
} catch {
|
|
2817
|
+
return href;
|
|
2818
|
+
}
|
|
2819
|
+
}
|
|
2820
|
+
escapeHtmlAttr(value) {
|
|
2821
|
+
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">").replace(/\"/g, """).replace(/'/g, "'");
|
|
2822
|
+
}
|
|
2823
|
+
loadStoredAnnouncementTimestamp() {
|
|
2824
|
+
if (typeof window === "undefined" || !window.localStorage) return null;
|
|
2825
|
+
try {
|
|
2826
|
+
const raw = window.localStorage.getItem(ANNOUNCEMENT_STORAGE_KEY);
|
|
2827
|
+
if (!raw) return null;
|
|
2828
|
+
const parsed = JSON.parse(raw);
|
|
2829
|
+
if (parsed && typeof parsed.timestamp === "string") return parsed.timestamp;
|
|
2830
|
+
return null;
|
|
2831
|
+
} catch {}
|
|
2832
|
+
return null;
|
|
2833
|
+
}
|
|
2834
|
+
persistAnnouncementTimestamp(timestamp) {
|
|
2835
|
+
if (typeof window === "undefined" || !window.localStorage) return;
|
|
2836
|
+
try {
|
|
2837
|
+
const payload = JSON.stringify({ timestamp });
|
|
2838
|
+
window.localStorage.setItem(ANNOUNCEMENT_STORAGE_KEY, payload);
|
|
2839
|
+
} catch {}
|
|
2840
|
+
}
|
|
2841
|
+
markAnnouncementSeen() {
|
|
2842
|
+
this.hasUnseenAnnouncement = false;
|
|
2843
|
+
this.showAnnouncementPreview = false;
|
|
2844
|
+
if (!this.announcementTimestamp) {
|
|
2845
|
+
if (this.announcementPromise && !this.announcementLoaded) this.announcementPromise.then(() => this.markAnnouncementSeen()).catch(() => void 0);
|
|
2846
|
+
this.requestUpdate();
|
|
2847
|
+
return;
|
|
2848
|
+
}
|
|
2849
|
+
this.persistAnnouncementTimestamp(this.announcementTimestamp);
|
|
2850
|
+
this.requestUpdate();
|
|
2851
|
+
}
|
|
2852
|
+
};
|
|
2853
|
+
function defineWebInspector() {
|
|
2854
|
+
if (!customElements.get(WEB_INSPECTOR_TAG)) customElements.define(WEB_INSPECTOR_TAG, WebInspectorElement);
|
|
2855
|
+
}
|
|
2856
|
+
defineWebInspector();
|
|
2857
|
+
|
|
2858
|
+
//#endregion
|
|
2859
|
+
exports.WEB_INSPECTOR_TAG = WEB_INSPECTOR_TAG;
|
|
2860
|
+
exports.WebInspectorElement = WebInspectorElement;
|
|
2861
|
+
exports.defineWebInspector = defineWebInspector;
|
|
2862
|
+
//# sourceMappingURL=index.cjs.map
|