Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
const require_generated = require('./styles/generated.cjs');
const require_inspector_logo = require('./assets/inspector-logo.cjs');
const require_inspector_logo_icon = require('./assets/inspector-logo-icon.cjs');
const require_context_helpers = require('./lib/context-helpers.cjs');
const require_persistence = require('./lib/persistence.cjs');
let lit = require("lit");
let lit_directives_style_map_js = require("lit/directives/style-map.js");
let lit_directives_unsafe_html_js = require("lit/directives/unsafe-html.js");
let marked = require("marked");
let lucide = require("lucide");
let _copilotkitnext_core = require("@copilotkitnext/core");
//#region src/index.ts
const WEB_INSPECTOR_TAG = "cpk-web-inspector";
const EDGE_MARGIN = 16;
const DRAG_THRESHOLD = 6;
const MIN_WINDOW_WIDTH = 600;
const MIN_WINDOW_WIDTH_DOCKED_LEFT = 420;
const MIN_WINDOW_HEIGHT = 200;
const INSPECTOR_STORAGE_KEY = "cpk:inspector:state";
const ANNOUNCEMENT_STORAGE_KEY = "cpk:inspector:announcements";
const ANNOUNCEMENT_URL = "https://cdn.copilotkit.ai/announcements.json";
const DEFAULT_BUTTON_SIZE = {
width: 48,
height: 48
};
const DEFAULT_WINDOW_SIZE = {
width: 840,
height: 560
};
const DOCKED_LEFT_WIDTH = 500;
const MAX_AGENT_EVENTS = 200;
const MAX_TOTAL_EVENTS = 500;
const AGENT_EVENT_TYPES = [
"RUN_STARTED",
"RUN_FINISHED",
"RUN_ERROR",
"TEXT_MESSAGE_START",
"TEXT_MESSAGE_CONTENT",
"TEXT_MESSAGE_END",
"TOOL_CALL_START",
"TOOL_CALL_ARGS",
"TOOL_CALL_END",
"TOOL_CALL_RESULT",
"STATE_SNAPSHOT",
"STATE_DELTA",
"MESSAGES_SNAPSHOT",
"RAW_EVENT",
"CUSTOM_EVENT",
"REASONING_START",
"REASONING_MESSAGE_START",
"REASONING_MESSAGE_CONTENT",
"REASONING_MESSAGE_END",
"REASONING_END",
"REASONING_ENCRYPTED_VALUE"
];
var WebInspectorElement = class extends lit.LitElement {
constructor(..._args) {
super(..._args);
this._core = null;
this.coreSubscriber = null;
this.coreUnsubscribe = null;
this.runtimeStatus = null;
this.coreProperties = {};
this.lastCoreError = null;
this.agentSubscriptions = /* @__PURE__ */ new Map();
this.agentEvents = /* @__PURE__ */ new Map();
this.agentMessages = /* @__PURE__ */ new Map();
this.agentStates = /* @__PURE__ */ new Map();
this.flattenedEvents = [];
this.eventCounter = 0;
this.contextStore = {};
this.pointerId = null;
this.dragStart = null;
this.dragOffset = {
x: 0,
y: 0
};
this.isDragging = false;
this.pointerContext = null;
this.isOpen = false;
this.draggedDuringInteraction = false;
this.ignoreNextButtonClick = false;
this.selectedMenu = "ag-ui-events";
this.contextMenuOpen = false;
this.dockMode = "floating";
this.previousBodyMargins = null;
this.transitionTimeoutId = null;
this.pendingSelectedContext = null;
this.autoAttachCore = true;
this.attemptedAutoAttach = false;
this.cachedTools = [];
this.toolSignature = "";
this.eventFilterText = "";
this.eventTypeFilter = "all";
this.announcementMarkdown = null;
this.announcementHtml = null;
this.announcementTimestamp = null;
this.announcementPreviewText = null;
this.hasUnseenAnnouncement = false;
this.announcementLoaded = false;
this.announcementLoadError = null;
this.announcementPromise = null;
this.showAnnouncementPreview = true;
this.contextState = {
button: {
position: {
x: EDGE_MARGIN,
y: EDGE_MARGIN
},
size: { ...DEFAULT_BUTTON_SIZE },
anchor: {
horizontal: "right",
vertical: "top"
},
anchorOffset: {
x: EDGE_MARGIN,
y: EDGE_MARGIN
}
},
window: {
position: {
x: EDGE_MARGIN,
y: EDGE_MARGIN
},
size: { ...DEFAULT_WINDOW_SIZE },
anchor: {
horizontal: "right",
vertical: "top"
},
anchorOffset: {
x: EDGE_MARGIN,
y: EDGE_MARGIN
}
}
};
this.hasCustomPosition = {
button: false,
window: false
};
this.resizePointerId = null;
this.resizeStart = null;
this.resizeInitialSize = null;
this.isResizing = false;
this.menuItems = [
{
key: "ag-ui-events",
label: "AG-UI Events",
icon: "Zap"
},
{
key: "agents",
label: "Agent",
icon: "Bot"
},
{
key: "frontend-tools",
label: "Frontend Tools",
icon: "Hammer"
},
{
key: "agent-context",
label: "Context",
icon: "FileText"
}
];
this.handlePointerDown = (event) => {
if (this.dockMode !== "floating" && this.isOpen) return;
const target = event.currentTarget;
const context = target?.dataset.dragContext === "window" ? "window" : "button";
const eventTarget = event.target;
if (context === "window" && eventTarget?.closest("button")) return;
this.pointerContext = context;
this.measureContext(context);
event.preventDefault();
this.pointerId = event.pointerId;
this.dragStart = {
x: event.clientX,
y: event.clientY
};
const state = this.contextState[context];
this.dragOffset = {
x: event.clientX - state.position.x,
y: event.clientY - state.position.y
};
this.isDragging = false;
this.draggedDuringInteraction = false;
this.ignoreNextButtonClick = false;
target?.setPointerCapture?.(this.pointerId);
};
this.handlePointerMove = (event) => {
if (this.pointerId !== event.pointerId || !this.dragStart || !this.pointerContext) return;
const distance = Math.hypot(event.clientX - this.dragStart.x, event.clientY - this.dragStart.y);
if (!this.isDragging && distance < DRAG_THRESHOLD) return;
event.preventDefault();
this.setDragging(true);
this.draggedDuringInteraction = true;
const desired = {
x: event.clientX - this.dragOffset.x,
y: event.clientY - this.dragOffset.y
};
const constrained = this.constrainToViewport(desired, this.pointerContext);
this.contextState[this.pointerContext].position = constrained;
this.updateHostTransform(this.pointerContext);
};
this.handlePointerUp = (event) => {
if (this.pointerId !== event.pointerId) return;
const target = event.currentTarget;
if (target?.hasPointerCapture(this.pointerId)) target.releasePointerCapture(this.pointerId);
const context = this.pointerContext ?? this.activeContext;
if (this.isDragging && this.pointerContext) {
event.preventDefault();
this.setDragging(false);
if (this.pointerContext === "window") {
this.updateAnchorFromPosition(this.pointerContext);
this.hasCustomPosition.window = true;
this.applyAnchorPosition(this.pointerContext);
} else if (this.pointerContext === "button") {
this.snapButtonToCorner();
this.hasCustomPosition.button = true;
if (this.draggedDuringInteraction) this.ignoreNextButtonClick = true;
}
} else if (context === "button" && !this.isOpen && !this.draggedDuringInteraction) this.openInspector();
this.resetPointerTracking();
};
this.handlePointerCancel = (event) => {
if (this.pointerId !== event.pointerId) return;
const target = event.currentTarget;
if (target?.hasPointerCapture(this.pointerId)) target.releasePointerCapture(this.pointerId);
this.resetPointerTracking();
};
this.handleButtonClick = (event) => {
if (this.isDragging) {
event.preventDefault();
return;
}
if (this.ignoreNextButtonClick) {
event.preventDefault();
this.ignoreNextButtonClick = false;
return;
}
if (!this.isOpen) {
event.preventDefault();
this.openInspector();
}
};
this.handleClosePointerDown = (event) => {
event.stopPropagation();
event.preventDefault();
};
this.handleCloseClick = () => {
this.closeInspector();
};
this.handleResizePointerDown = (event) => {
event.stopPropagation();
event.preventDefault();
this.hasCustomPosition.window = true;
this.isResizing = true;
this.resizePointerId = event.pointerId;
this.resizeStart = {
x: event.clientX,
y: event.clientY
};
this.resizeInitialSize = { ...this.contextState.window.size };
if (document.body && this.dockMode !== "floating") document.body.style.transition = "";
event.currentTarget?.setPointerCapture?.(event.pointerId);
};
this.handleResizePointerMove = (event) => {
if (!this.isResizing || this.resizePointerId !== event.pointerId || !this.resizeStart || !this.resizeInitialSize) return;
event.preventDefault();
const deltaX = event.clientX - this.resizeStart.x;
const deltaY = event.clientY - this.resizeStart.y;
const state = this.contextState.window;
if (this.dockMode === "docked-left") {
state.size = this.clampWindowSize({
width: this.resizeInitialSize.width + deltaX,
height: state.size.height
});
if (document.body) document.body.style.marginLeft = `${state.size.width}px`;
} else {
state.size = this.clampWindowSize({
width: this.resizeInitialSize.width + deltaX,
height: this.resizeInitialSize.height + deltaY
});
this.keepPositionWithinViewport("window");
this.updateAnchorFromPosition("window");
}
this.requestUpdate();
this.updateHostTransform("window");
};
this.handleResizePointerUp = (event) => {
if (this.resizePointerId !== event.pointerId) return;
const target = event.currentTarget;
if (target?.hasPointerCapture(this.resizePointerId)) target.releasePointerCapture(this.resizePointerId);
if (this.dockMode === "floating") {
this.updateAnchorFromPosition("window");
this.applyAnchorPosition("window");
}
this.persistState();
this.resetResizeTracking();
};
this.handleResizePointerCancel = (event) => {
if (this.resizePointerId !== event.pointerId) return;
const target = event.currentTarget;
if (target?.hasPointerCapture(this.resizePointerId)) target.releasePointerCapture(this.resizePointerId);
if (this.dockMode === "floating") {
this.updateAnchorFromPosition("window");
this.applyAnchorPosition("window");
}
this.persistState();
this.resetResizeTracking();
};
this.handleResize = () => {
this.measureContext("button");
this.applyAnchorPosition("button");
this.measureContext("window");
if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
else this.centerContext("window");
this.updateHostTransform();
};
this.contextOptions = [{
key: "all-agents",
label: "All Agents"
}];
this.selectedContext = "all-agents";
this.expandedRows = /* @__PURE__ */ new Set();
this.copiedEvents = /* @__PURE__ */ new Set();
this.expandedTools = /* @__PURE__ */ new Set();
this.expandedContextItems = /* @__PURE__ */ new Set();
this.copiedContextItems = /* @__PURE__ */ new Set();
this.handleClearEvents = () => {
if (this.selectedContext === "all-agents") {
this.agentEvents.clear();
this.flattenedEvents = [];
} else {
this.agentEvents.delete(this.selectedContext);
this.flattenedEvents = this.flattenedEvents.filter((event) => event.agentId !== this.selectedContext);
}
this.expandedRows.clear();
this.copiedEvents.clear();
this.requestUpdate();
};
this.handleGlobalPointerDown = (event) => {
if (!this.contextMenuOpen) return;
if (!event.composedPath().some((node) => {
return node instanceof HTMLElement && node.dataset?.contextDropdownRoot === "true";
})) {
this.contextMenuOpen = false;
this.requestUpdate();
}
};
this.handleDismissAnnouncement = () => {
this.markAnnouncementSeen();
};
}
static {
this.properties = {
core: { attribute: false },
autoAttachCore: {
type: Boolean,
attribute: "auto-attach-core"
}
};
}
get core() {
return this._core;
}
set core(value) {
const oldValue = this._core;
if (oldValue === value) return;
this.detachFromCore();
this._core = value ?? null;
this.requestUpdate("core", oldValue);
if (this._core) this.attachToCore(this._core);
}
attachToCore(core) {
this.runtimeStatus = core.runtimeConnectionStatus;
this.coreProperties = core.properties;
this.lastCoreError = null;
this.coreSubscriber = {
onRuntimeConnectionStatusChanged: ({ status }) => {
this.runtimeStatus = status;
this.requestUpdate();
},
onPropertiesChanged: ({ properties }) => {
this.coreProperties = properties;
this.requestUpdate();
},
onError: ({ code, error }) => {
this.lastCoreError = {
code,
message: error.message
};
this.requestUpdate();
},
onAgentsChanged: ({ agents }) => {
this.processAgentsChanged(agents);
},
onContextChanged: ({ context }) => {
this.contextStore = this.normalizeContextStore(context);
this.requestUpdate();
}
};
this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;
this.processAgentsChanged(core.agents);
if (core.context) this.contextStore = this.normalizeContextStore(core.context);
}
detachFromCore() {
if (this.coreUnsubscribe) {
this.coreUnsubscribe();
this.coreUnsubscribe = null;
}
this.coreSubscriber = null;
this.runtimeStatus = null;
this.lastCoreError = null;
this.coreProperties = {};
this.cachedTools = [];
this.toolSignature = "";
this.teardownAgentSubscriptions();
}
teardownAgentSubscriptions() {
for (const unsubscribe of this.agentSubscriptions.values()) unsubscribe();
this.agentSubscriptions.clear();
this.agentEvents.clear();
this.agentMessages.clear();
this.agentStates.clear();
this.flattenedEvents = [];
this.eventCounter = 0;
}
processAgentsChanged(agents) {
const seenAgentIds = /* @__PURE__ */ new Set();
for (const agent of Object.values(agents)) {
if (!agent?.agentId) continue;
seenAgentIds.add(agent.agentId);
this.subscribeToAgent(agent);
}
for (const agentId of Array.from(this.agentSubscriptions.keys())) if (!seenAgentIds.has(agentId)) {
this.unsubscribeFromAgent(agentId);
this.agentEvents.delete(agentId);
this.agentMessages.delete(agentId);
this.agentStates.delete(agentId);
}
this.updateContextOptions(seenAgentIds);
this.refreshToolsSnapshot();
this.requestUpdate();
}
refreshToolsSnapshot() {
if (!this._core) {
if (this.cachedTools.length > 0) {
this.cachedTools = [];
this.toolSignature = "";
this.requestUpdate();
}
return;
}
const tools = this.extractToolsFromAgents();
const signature = JSON.stringify(tools.map((tool) => ({
agentId: tool.agentId,
name: tool.name,
type: tool.type,
hasDescription: Boolean(tool.description),
hasParameters: Boolean(tool.parameters)
})));
if (signature !== this.toolSignature) {
this.toolSignature = signature;
this.cachedTools = tools;
this.requestUpdate();
}
}
tryAutoAttachCore() {
if (this.attemptedAutoAttach || this._core || !this.autoAttachCore || typeof window === "undefined") return;
this.attemptedAutoAttach = true;
const globalWindow = window;
const foundCore = [
globalWindow.__COPILOTKIT_CORE__,
globalWindow.copilotkit?.core,
globalWindow.copilotkitCore
].find((candidate) => !!candidate && typeof candidate === "object");
if (foundCore) this.core = foundCore;
}
subscribeToAgent(agent) {
if (!agent.agentId) return;
const agentId = agent.agentId;
this.unsubscribeFromAgent(agentId);
const { unsubscribe } = agent.subscribe({
onRunStartedEvent: ({ event }) => {
this.recordAgentEvent(agentId, "RUN_STARTED", event);
},
onRunFinishedEvent: ({ event, result }) => {
this.recordAgentEvent(agentId, "RUN_FINISHED", {
event,
result
});
},
onRunErrorEvent: ({ event }) => {
this.recordAgentEvent(agentId, "RUN_ERROR", event);
},
onTextMessageStartEvent: ({ event }) => {
this.recordAgentEvent(agentId, "TEXT_MESSAGE_START", event);
},
onTextMessageContentEvent: ({ event, textMessageBuffer }) => {
this.recordAgentEvent(agentId, "TEXT_MESSAGE_CONTENT", {
event,
textMessageBuffer
});
},
onTextMessageEndEvent: ({ event, textMessageBuffer }) => {
this.recordAgentEvent(agentId, "TEXT_MESSAGE_END", {
event,
textMessageBuffer
});
},
onToolCallStartEvent: ({ event }) => {
this.recordAgentEvent(agentId, "TOOL_CALL_START", event);
},
onToolCallArgsEvent: ({ event, toolCallBuffer, toolCallName, partialToolCallArgs }) => {
this.recordAgentEvent(agentId, "TOOL_CALL_ARGS", {
event,
toolCallBuffer,
toolCallName,
partialToolCallArgs
});
},
onToolCallEndEvent: ({ event, toolCallArgs, toolCallName }) => {
this.recordAgentEvent(agentId, "TOOL_CALL_END", {
event,
toolCallArgs,
toolCallName
});
},
onToolCallResultEvent: ({ event }) => {
this.recordAgentEvent(agentId, "TOOL_CALL_RESULT", event);
},
onStateSnapshotEvent: ({ event }) => {
this.recordAgentEvent(agentId, "STATE_SNAPSHOT", event);
this.syncAgentState(agent);
},
onStateDeltaEvent: ({ event }) => {
this.recordAgentEvent(agentId, "STATE_DELTA", event);
this.syncAgentState(agent);
},
onMessagesSnapshotEvent: ({ event }) => {
this.recordAgentEvent(agentId, "MESSAGES_SNAPSHOT", event);
this.syncAgentMessages(agent);
},
onMessagesChanged: () => {
this.syncAgentMessages(agent);
},
onRawEvent: ({ event }) => {
this.recordAgentEvent(agentId, "RAW_EVENT", event);
},
onCustomEvent: ({ event }) => {
this.recordAgentEvent(agentId, "CUSTOM_EVENT", event);
},
onReasoningStartEvent: ({ event }) => {
this.recordAgentEvent(agentId, "REASONING_START", event);
},
onReasoningMessageStartEvent: ({ event }) => {
this.recordAgentEvent(agentId, "REASONING_MESSAGE_START", event);
},
onReasoningMessageContentEvent: ({ event, reasoningMessageBuffer }) => {
this.recordAgentEvent(agentId, "REASONING_MESSAGE_CONTENT", {
event,
reasoningMessageBuffer
});
},
onReasoningMessageEndEvent: ({ event, reasoningMessageBuffer }) => {
this.recordAgentEvent(agentId, "REASONING_MESSAGE_END", {
event,
reasoningMessageBuffer
});
},
onReasoningEndEvent: ({ event }) => {
this.recordAgentEvent(agentId, "REASONING_END", event);
},
onReasoningEncryptedValueEvent: ({ event }) => {
this.recordAgentEvent(agentId, "REASONING_ENCRYPTED_VALUE", event);
}
});
this.agentSubscriptions.set(agentId, unsubscribe);
this.syncAgentMessages(agent);
this.syncAgentState(agent);
if (!this.agentEvents.has(agentId)) this.agentEvents.set(agentId, []);
}
unsubscribeFromAgent(agentId) {
const unsubscribe = this.agentSubscriptions.get(agentId);
if (unsubscribe) {
unsubscribe();
this.agentSubscriptions.delete(agentId);
}
}
recordAgentEvent(agentId, type, payload) {
const eventId = `${agentId}:${++this.eventCounter}`;
const normalizedPayload = this.normalizeEventPayload(type, payload);
const event = {
id: eventId,
agentId,
type,
timestamp: Date.now(),
payload: normalizedPayload
};
const nextAgentEvents = [event, ...this.agentEvents.get(agentId) ?? []].slice(0, MAX_AGENT_EVENTS);
this.agentEvents.set(agentId, nextAgentEvents);
this.flattenedEvents = [event, ...this.flattenedEvents].slice(0, MAX_TOTAL_EVENTS);
this.refreshToolsSnapshot();
this.requestUpdate();
}
syncAgentMessages(agent) {
if (!agent?.agentId) return;
const messages = this.normalizeAgentMessages(agent.messages);
if (messages) this.agentMessages.set(agent.agentId, messages);
else this.agentMessages.delete(agent.agentId);
this.requestUpdate();
}
syncAgentState(agent) {
if (!agent?.agentId) return;
const state = agent.state;
if (state === void 0 || state === null) this.agentStates.delete(agent.agentId);
else this.agentStates.set(agent.agentId, this.sanitizeForLogging(state));
this.requestUpdate();
}
updateContextOptions(agentIds) {
const nextOptions = [{
key: "all-agents",
label: "All Agents"
}, ...Array.from(agentIds).sort((a, b) => a.localeCompare(b)).map((id) => ({
key: id,
label: id
}))];
if (this.contextOptions.length !== nextOptions.length || this.contextOptions.some((option, index) => option.key !== nextOptions[index]?.key)) this.contextOptions = nextOptions;
const pendingContext = this.pendingSelectedContext;
if (pendingContext) {
if (pendingContext === "all-agents" || agentIds.has(pendingContext)) {
if (this.selectedContext !== pendingContext) {
this.selectedContext = pendingContext;
this.expandedRows.clear();
}
this.pendingSelectedContext = null;
} else if (agentIds.size > 0) this.pendingSelectedContext = null;
}
if (!nextOptions.some((option) => option.key === this.selectedContext) && this.pendingSelectedContext === null) {
let nextSelected = "all-agents";
if (agentIds.has("default")) nextSelected = "default";
else if (agentIds.size > 0) nextSelected = Array.from(agentIds).sort((a, b) => a.localeCompare(b))[0];
if (this.selectedContext !== nextSelected) {
this.selectedContext = nextSelected;
this.expandedRows.clear();
this.persistState();
}
}
}
getEventsForSelectedContext() {
if (this.selectedContext === "all-agents") return this.flattenedEvents;
return this.agentEvents.get(this.selectedContext) ?? [];
}
filterEvents(events) {
const query = this.eventFilterText.trim().toLowerCase();
return events.filter((event) => {
if (this.eventTypeFilter !== "all" && event.type !== this.eventTypeFilter) return false;
if (!query) return true;
const payloadText = this.stringifyPayload(event.payload, false).toLowerCase();
return event.type.toLowerCase().includes(query) || event.agentId.toLowerCase().includes(query) || payloadText.includes(query);
});
}
getLatestStateForAgent(agentId) {
if (this.agentStates.has(agentId)) {
const value = this.agentStates.get(agentId);
return value === void 0 ? null : value;
}
const stateEvent = (this.agentEvents.get(agentId) ?? []).find((e) => e.type === "STATE_SNAPSHOT");
if (!stateEvent) return null;
return stateEvent.payload;
}
getLatestMessagesForAgent(agentId) {
return this.agentMessages.get(agentId) ?? null;
}
getAgentStatus(agentId) {
const events = this.agentEvents.get(agentId) ?? [];
if (events.length === 0) return "idle";
const runEvent = events.find((e) => e.type === "RUN_STARTED" || e.type === "RUN_FINISHED" || e.type === "RUN_ERROR");
if (!runEvent) return "idle";
if (runEvent.type === "RUN_ERROR") return "error";
if (runEvent.type === "RUN_STARTED") return events.find((e) => e.type === "RUN_FINISHED" && e.timestamp > runEvent.timestamp) ? "idle" : "running";
return "idle";
}
getAgentStats(agentId) {
const events = this.agentEvents.get(agentId) ?? [];
const messages = this.agentMessages.get(agentId);
const toolCallCount = messages ? messages.reduce((count, message) => count + (message.toolCalls?.length ?? 0), 0) : events.filter((e) => e.type === "TOOL_CALL_END").length;
const messageCount = messages?.length ?? 0;
return {
totalEvents: events.length,
lastActivity: events[0]?.timestamp ?? null,
messages: messageCount,
toolCalls: toolCallCount,
errors: events.filter((e) => e.type === "RUN_ERROR").length
};
}
renderToolCallDetails(toolCalls) {
if (!Array.isArray(toolCalls) || toolCalls.length === 0) return lit.nothing;
return lit.html`
${toolCalls.map((call, index) => {
const functionName = call.function?.name ?? call.toolName ?? "Unknown function";
const callId = typeof call?.id === "string" ? call.id : `tool-call-${index + 1}`;
const argsString = this.formatToolCallArguments(call.function?.arguments);
return lit.html`
${functionName}
ID: ${callId}
${argsString ? lit.html`
${argsString}` : lit.nothing}
`;
})}
`;
}
formatToolCallArguments(args) {
if (args === void 0 || args === null || args === "") return null;
if (typeof args === "string") try {
const parsed = JSON.parse(args);
return JSON.stringify(parsed, null, 2);
} catch {
return args;
}
if (typeof args === "object") try {
return JSON.stringify(args, null, 2);
} catch {
return String(args);
}
return String(args);
}
hasRenderableState(state) {
if (state === null || state === void 0) return false;
if (Array.isArray(state)) return state.length > 0;
if (typeof state === "object") return Object.keys(state).length > 0;
if (typeof state === "string") {
const trimmed = state.trim();
return trimmed.length > 0 && trimmed !== "{}";
}
return true;
}
formatStateForDisplay(state) {
if (state === null || state === void 0) return "";
if (typeof state === "string") {
const trimmed = state.trim();
if (trimmed.length === 0) return "";
try {
const parsed = JSON.parse(trimmed);
return JSON.stringify(parsed, null, 2);
} catch {
return state;
}
}
if (typeof state === "object") try {
return JSON.stringify(state, null, 2);
} catch {
return String(state);
}
return String(state);
}
getEventBadgeClasses(type) {
const base = "font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border";
if (type.startsWith("RUN_")) return `${base} bg-blue-50 text-blue-700 border-blue-200`;
if (type.startsWith("TEXT_MESSAGE")) return `${base} bg-emerald-50 text-emerald-700 border-emerald-200`;
if (type.startsWith("TOOL_CALL")) return `${base} bg-amber-50 text-amber-700 border-amber-200`;
if (type.startsWith("REASONING")) return `${base} bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200`;
if (type.startsWith("STATE")) return `${base} bg-violet-50 text-violet-700 border-violet-200`;
if (type.startsWith("MESSAGES")) return `${base} bg-sky-50 text-sky-700 border-sky-200`;
if (type === "RUN_ERROR") return `${base} bg-rose-50 text-rose-700 border-rose-200`;
return `${base} bg-gray-100 text-gray-600 border-gray-200`;
}
stringifyPayload(payload, pretty) {
try {
if (payload === void 0) return pretty ? "undefined" : "undefined";
if (typeof payload === "string") return payload;
return JSON.stringify(payload, null, pretty ? 2 : 0) ?? "";
} catch (error) {
console.warn("Failed to stringify inspector payload", error);
return String(payload);
}
}
extractEventFromPayload(payload) {
if (payload && typeof payload === "object" && "event" in payload) return payload.event;
return payload;
}
async copyToClipboard(text, eventId) {
try {
await navigator.clipboard.writeText(text);
this.copiedEvents.add(eventId);
this.requestUpdate();
setTimeout(() => {
this.copiedEvents.delete(eventId);
this.requestUpdate();
}, 2e3);
} catch (err) {
console.error("Failed to copy to clipboard:", err);
}
}
static {
this.styles = [(0, lit.unsafeCSS)(require_generated.default), lit.css`
:host {
position: fixed;
top: 0;
left: 0;
z-index: 2147483646;
display: block;
will-change: transform;
}
:host([data-transitioning="true"]) {
transition: transform 300ms ease;
}
.console-button {
transition:
transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),
opacity 160ms ease;
}
.console-button[data-dragging="true"] {
transition: opacity 160ms ease;
}
.inspector-window[data-transitioning="true"] {
transition:
width 300ms ease,
height 300ms ease;
}
.inspector-window[data-docked="true"] {
border-radius: 0 !important;
box-shadow: none !important;
}
.resize-handle {
touch-action: none;
user-select: none;
}
.dock-resize-handle {
position: absolute;
top: 0;
right: 0;
width: 10px;
height: 100%;
cursor: ew-resize;
touch-action: none;
z-index: 50;
background: transparent;
}
.tooltip-target {
position: relative;
}
.tooltip-target::after {
content: attr(data-tooltip);
position: absolute;
top: calc(100% + 6px);
left: 50%;
transform: translateX(-50%) translateY(-4px);
white-space: nowrap;
background: rgba(17, 24, 39, 0.95);
color: white;
padding: 4px 8px;
border-radius: 6px;
font-size: 10px;
line-height: 1.2;
box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);
opacity: 0;
pointer-events: none;
transition:
opacity 120ms ease,
transform 120ms ease;
z-index: 4000;
}
.tooltip-target:hover::after {
opacity: 1;
transform: translateX(-50%) translateY(0);
}
.announcement-preview {
position: absolute;
top: 50%;
transform: translateY(-50%);
min-width: 300px;
max-width: 300px;
background: white;
color: #111827;
font-size: 13px;
line-height: 1.4;
border-radius: 12px;
box-shadow: 0 12px 28px rgba(15, 23, 42, 0.22);
padding: 10px 12px;
display: inline-flex;
align-items: flex-start;
gap: 8px;
z-index: 4500;
animation: fade-slide-in 160ms ease;
border: 1px solid rgba(148, 163, 184, 0.35);
white-space: normal;
word-break: break-word;
text-align: left;
}
.announcement-preview[data-side="left"] {
right: 100%;
margin-right: 10px;
}
.announcement-preview[data-side="right"] {
left: 100%;
margin-left: 10px;
}
.announcement-preview__arrow {
position: absolute;
width: 10px;
height: 10px;
background: white;
border: 1px solid rgba(148, 163, 184, 0.35);
transform: rotate(45deg);
top: 50%;
margin-top: -5px;
z-index: -1;
}
.announcement-preview[data-side="left"] .announcement-preview__arrow {
right: -5px;
box-shadow: 6px -6px 10px rgba(15, 23, 42, 0.12);
}
.announcement-preview[data-side="right"] .announcement-preview__arrow {
left: -5px;
box-shadow: -6px 6px 10px rgba(15, 23, 42, 0.12);
}
.announcement-dismiss {
color: #6b7280;
font-size: 12px;
padding: 2px 8px;
border-radius: 8px;
border: 1px solid rgba(148, 163, 184, 0.5);
background: rgba(248, 250, 252, 0.9);
transition:
background 120ms ease,
color 120ms ease;
}
.announcement-dismiss:hover {
background: rgba(241, 245, 249, 1);
color: #111827;
}
.announcement-content {
color: #111827;
font-size: 14px;
line-height: 1.6;
}
.announcement-content h1,
.announcement-content h2,
.announcement-content h3 {
font-weight: 700;
margin: 0.4rem 0 0.2rem;
}
.announcement-content h1 {
font-size: 1.1rem;
}
.announcement-content h2 {
font-size: 1rem;
}
.announcement-content h3 {
font-size: 0.95rem;
}
.announcement-content p {
margin: 0.25rem 0;
}
.announcement-content ul {
list-style: disc;
padding-left: 1.25rem;
margin: 0.3rem 0;
}
.announcement-content ol {
list-style: decimal;
padding-left: 1.25rem;
margin: 0.3rem 0;
}
.announcement-content a {
color: #0f766e;
text-decoration: underline;
}
`];
}
connectedCallback() {
super.connectedCallback();
if (typeof window !== "undefined") {
window.addEventListener("resize", this.handleResize);
window.addEventListener("pointerdown", this.handleGlobalPointerDown);
this.hydrateStateFromStorageEarly();
this.tryAutoAttachCore();
this.ensureAnnouncementLoading();
}
}
disconnectedCallback() {
super.disconnectedCallback();
if (typeof window !== "undefined") {
window.removeEventListener("resize", this.handleResize);
window.removeEventListener("pointerdown", this.handleGlobalPointerDown);
}
this.removeDockStyles();
this.detachFromCore();
}
firstUpdated() {
if (typeof window === "undefined") return;
if (!this._core) this.tryAutoAttachCore();
this.measureContext("button");
this.measureContext("window");
this.contextState.button.anchor = {
horizontal: "right",
vertical: "top"
};
this.contextState.button.anchorOffset = {
x: EDGE_MARGIN,
y: EDGE_MARGIN
};
this.contextState.window.anchor = {
horizontal: "right",
vertical: "top"
};
this.contextState.window.anchorOffset = {
x: EDGE_MARGIN,
y: EDGE_MARGIN
};
this.hydrateStateFromStorage();
if (this.isOpen && this.dockMode !== "floating") this.applyDockStyles(true);
this.applyAnchorPosition("button");
if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
else this.centerContext("window");
this.ensureAnnouncementLoading();
this.updateHostTransform(this.isOpen ? "window" : "button");
}
render() {
return this.isOpen ? this.renderWindow() : this.renderButton();
}
renderButton() {
return lit.html`
`;
}
renderWindow() {
const windowState = this.contextState.window;
const isDocked = this.dockMode !== "floating";
const isTransitioning = this.hasAttribute("data-transitioning");
const windowStyles = isDocked ? this.getDockedWindowStyles() : {
width: `${Math.round(windowState.size.width)}px`,
height: `${Math.round(windowState.size.height)}px`,
minWidth: `${MIN_WINDOW_WIDTH}px`,
minHeight: `${MIN_WINDOW_HEIGHT}px`
};
const hasContextDropdown = this.contextOptions.length > 0;
const contextDropdown = hasContextDropdown ? this.renderContextDropdown() : lit.nothing;
const coreStatus = this.getCoreStatusSummary();
const agentSelector = hasContextDropdown ? contextDropdown : lit.html`
${this.renderIcon("Bot")}
No agents available
`;
return lit.html`
${isDocked ? lit.html`
` : lit.nothing}
${agentSelector}
${this.renderDockControls()}
${this.menuItems.map(({ key, label, icon }) => {
const isSelected = this.selectedMenu === key;
return lit.html`
`;
})}
${this.renderAnnouncementPanel()}
${this.renderCoreWarningBanner()} ${this.renderMainContent()}
${this.renderIcon("Activity")}
${coreStatus.label}
${coreStatus.description}
`;
}
hydrateStateFromStorageEarly() {
if (typeof document === "undefined" || typeof window === "undefined") return;
const persisted = require_persistence.loadInspectorState(INSPECTOR_STORAGE_KEY);
if (!persisted) return;
if (typeof persisted.isOpen === "boolean") this.isOpen = persisted.isOpen;
if (require_persistence.isValidDockMode(persisted.dockMode)) this.dockMode = persisted.dockMode;
if (typeof persisted.selectedMenu === "string") {
const validMenu = this.menuItems.find((item) => item.key === persisted.selectedMenu);
if (validMenu) this.selectedMenu = validMenu.key;
}
if (typeof persisted.selectedContext === "string") {
this.selectedContext = persisted.selectedContext;
this.pendingSelectedContext = persisted.selectedContext;
}
}
hydrateStateFromStorage() {
if (typeof document === "undefined" || typeof window === "undefined") return;
const persisted = require_persistence.loadInspectorState(INSPECTOR_STORAGE_KEY);
if (!persisted) return;
const persistedButton = persisted.button;
if (persistedButton) {
if (require_persistence.isValidAnchor(persistedButton.anchor)) this.contextState.button.anchor = persistedButton.anchor;
if (require_persistence.isValidPosition(persistedButton.anchorOffset)) this.contextState.button.anchorOffset = persistedButton.anchorOffset;
if (typeof persistedButton.hasCustomPosition === "boolean") this.hasCustomPosition.button = persistedButton.hasCustomPosition;
}
const persistedWindow = persisted.window;
if (persistedWindow) {
if (require_persistence.isValidAnchor(persistedWindow.anchor)) this.contextState.window.anchor = persistedWindow.anchor;
if (require_persistence.isValidPosition(persistedWindow.anchorOffset)) this.contextState.window.anchorOffset = persistedWindow.anchorOffset;
if (require_persistence.isValidSize(persistedWindow.size)) this.contextState.window.size = this.clampWindowSize(persistedWindow.size);
if (typeof persistedWindow.hasCustomPosition === "boolean") this.hasCustomPosition.window = persistedWindow.hasCustomPosition;
}
if (typeof persisted.selectedContext === "string") {
this.selectedContext = persisted.selectedContext;
this.pendingSelectedContext = persisted.selectedContext;
}
}
get activeContext() {
return this.isOpen ? "window" : "button";
}
measureContext(context) {
const selector = context === "window" ? ".inspector-window" : ".console-button";
const element = this.renderRoot?.querySelector(selector);
if (!element) return;
const fallback = context === "window" ? DEFAULT_WINDOW_SIZE : DEFAULT_BUTTON_SIZE;
require_context_helpers.updateSizeFromElement(this.contextState[context], element, fallback);
}
centerContext(context) {
if (typeof window === "undefined") return;
const viewport = this.getViewportSize();
require_context_helpers.centerContext(this.contextState[context], viewport, EDGE_MARGIN);
if (context === this.activeContext) this.updateHostTransform(context);
this.hasCustomPosition[context] = false;
this.persistState();
}
ensureWindowPlacement() {
if (typeof window === "undefined") return;
if (!this.hasCustomPosition.window) {
this.centerContext("window");
return;
}
const viewport = this.getViewportSize();
require_context_helpers.keepPositionWithinViewport(this.contextState.window, viewport, EDGE_MARGIN);
require_context_helpers.updateAnchorFromPosition(this.contextState.window, viewport, EDGE_MARGIN);
this.updateHostTransform("window");
this.persistState();
}
constrainToViewport(position, context) {
if (typeof window === "undefined") return position;
const viewport = this.getViewportSize();
return require_context_helpers.constrainToViewport(this.contextState[context], position, viewport, EDGE_MARGIN);
}
keepPositionWithinViewport(context) {
if (typeof window === "undefined") return;
const viewport = this.getViewportSize();
require_context_helpers.keepPositionWithinViewport(this.contextState[context], viewport, EDGE_MARGIN);
}
getViewportSize() {
if (typeof window === "undefined") return { ...DEFAULT_WINDOW_SIZE };
return {
width: window.innerWidth,
height: window.innerHeight
};
}
persistState() {
const state = {
button: {
anchor: this.contextState.button.anchor,
anchorOffset: this.contextState.button.anchorOffset,
hasCustomPosition: this.hasCustomPosition.button
},
window: {
anchor: this.contextState.window.anchor,
anchorOffset: this.contextState.window.anchorOffset,
size: {
width: Math.round(this.contextState.window.size.width),
height: Math.round(this.contextState.window.size.height)
},
hasCustomPosition: this.hasCustomPosition.window
},
isOpen: this.isOpen,
dockMode: this.dockMode,
selectedMenu: this.selectedMenu,
selectedContext: this.selectedContext
};
require_persistence.saveInspectorState(INSPECTOR_STORAGE_KEY, state);
this.pendingSelectedContext = state.selectedContext ?? null;
}
clampWindowSize(size) {
const minWidth = this.dockMode === "docked-left" ? MIN_WINDOW_WIDTH_DOCKED_LEFT : MIN_WINDOW_WIDTH;
if (typeof window === "undefined") return {
width: Math.max(minWidth, size.width),
height: Math.max(MIN_WINDOW_HEIGHT, size.height)
};
return require_context_helpers.clampSize(size, this.getViewportSize(), EDGE_MARGIN, minWidth, MIN_WINDOW_HEIGHT);
}
setDockMode(mode) {
if (this.dockMode === mode) return;
this.startHostTransition();
this.removeDockStyles();
this.dockMode = mode;
if (mode !== "floating") {
if (mode === "docked-left") this.contextState.window.size.width = DOCKED_LEFT_WIDTH;
this.applyDockStyles();
} else {
this.contextState.window.size = { ...DEFAULT_WINDOW_SIZE };
this.centerContext("window");
}
this.persistState();
this.requestUpdate();
this.updateHostTransform("window");
}
startHostTransition(duration = 300) {
this.setAttribute("data-transitioning", "true");
if (this.transitionTimeoutId !== null) clearTimeout(this.transitionTimeoutId);
this.transitionTimeoutId = setTimeout(() => {
this.removeAttribute("data-transitioning");
this.transitionTimeoutId = null;
}, duration);
}
applyDockStyles(skipTransition = false) {
if (typeof document === "undefined" || !document.body) return;
const computedStyle = window.getComputedStyle(document.body);
this.previousBodyMargins = {
left: computedStyle.marginLeft,
bottom: computedStyle.marginBottom
};
if (!this.isResizing && !skipTransition) document.body.style.transition = "margin 300ms ease";
if (this.dockMode === "docked-left") document.body.style.marginLeft = `${this.contextState.window.size.width}px`;
if (!this.isResizing && !skipTransition) setTimeout(() => {
if (document.body) document.body.style.transition = "";
}, 300);
}
removeDockStyles() {
if (typeof document === "undefined" || !document.body) return;
if (!this.isResizing) document.body.style.transition = "margin 300ms ease";
if (this.previousBodyMargins) {
document.body.style.marginLeft = this.previousBodyMargins.left;
document.body.style.marginBottom = this.previousBodyMargins.bottom;
this.previousBodyMargins = null;
} else {
document.body.style.marginLeft = "";
document.body.style.marginBottom = "";
}
setTimeout(() => {
if (document.body) document.body.style.transition = "";
}, 300);
}
updateHostTransform(context = this.activeContext) {
if (context !== this.activeContext) return;
if (this.isOpen && this.dockMode === "docked-left") this.style.transform = `translate3d(0, 0, 0)`;
else {
const { position } = this.contextState[context];
this.style.transform = `translate3d(${position.x}px, ${position.y}px, 0)`;
}
}
setDragging(value) {
if (this.isDragging !== value) {
this.isDragging = value;
this.requestUpdate();
}
}
updateAnchorFromPosition(context) {
if (typeof window === "undefined") return;
const viewport = this.getViewportSize();
require_context_helpers.updateAnchorFromPosition(this.contextState[context], viewport, EDGE_MARGIN);
}
snapButtonToCorner() {
if (typeof window === "undefined") return;
const viewport = this.getViewportSize();
const state = this.contextState.button;
const centerX = state.position.x + state.size.width / 2;
const centerY = state.position.y + state.size.height / 2;
state.anchor = {
horizontal: centerX < viewport.width / 2 ? "left" : "right",
vertical: centerY < viewport.height / 2 ? "top" : "bottom"
};
state.anchorOffset = {
x: EDGE_MARGIN,
y: EDGE_MARGIN
};
this.startHostTransition();
this.applyAnchorPosition("button");
}
applyAnchorPosition(context) {
if (typeof window === "undefined") return;
const viewport = this.getViewportSize();
require_context_helpers.applyAnchorPosition(this.contextState[context], viewport, EDGE_MARGIN);
this.updateHostTransform(context);
this.persistState();
}
resetResizeTracking() {
this.resizePointerId = null;
this.resizeStart = null;
this.resizeInitialSize = null;
this.isResizing = false;
}
resetPointerTracking() {
this.pointerId = null;
this.dragStart = null;
this.pointerContext = null;
this.setDragging(false);
this.draggedDuringInteraction = false;
}
openInspector() {
if (this.isOpen) return;
this.showAnnouncementPreview = false;
this.ensureAnnouncementLoading();
this.isOpen = true;
this.persistState();
if (this.dockMode !== "floating") this.applyDockStyles();
this.ensureWindowPlacement();
this.requestUpdate();
this.updateComplete.then(() => {
this.measureContext("window");
if (this.dockMode === "floating") if (this.hasCustomPosition.window) this.applyAnchorPosition("window");
else this.centerContext("window");
else this.updateHostTransform("window");
});
}
closeInspector() {
if (!this.isOpen) return;
this.isOpen = false;
if (this.dockMode !== "floating") this.removeDockStyles();
this.persistState();
this.updateHostTransform("button");
this.requestUpdate();
this.updateComplete.then(() => {
this.measureContext("button");
this.applyAnchorPosition("button");
});
}
renderIcon(name) {
const iconNode = lucide.icons[name];
if (!iconNode) return lit.nothing;
return (0, lit_directives_unsafe_html_js.unsafeHTML)(``);
}
renderDockControls() {
if (this.dockMode === "floating") return lit.html`
`;
else return lit.html`
`;
}
getDockedWindowStyles() {
if (this.dockMode === "docked-left") return {
position: "fixed",
top: "0",
left: "0",
bottom: "0",
width: `${Math.round(this.contextState.window.size.width)}px`,
height: "100vh",
minWidth: `${MIN_WINDOW_WIDTH_DOCKED_LEFT}px`,
borderRadius: "0"
};
return {
width: `${Math.round(this.contextState.window.size.width)}px`,
height: `${Math.round(this.contextState.window.size.height)}px`,
minWidth: `${MIN_WINDOW_WIDTH}px`,
minHeight: `${MIN_WINDOW_HEIGHT}px`
};
}
handleDockClick(mode) {
this.setDockMode(mode);
}
serializeAttributes(attributes) {
return Object.entries(attributes).filter(([key, value]) => key !== "key" && value !== void 0 && value !== null && value !== "").map(([key, value]) => `${key}="${String(value).replace(/"/g, """)}"`).join(" ");
}
sanitizeForLogging(value, depth = 0, seen = /* @__PURE__ */ new WeakSet()) {
if (value === void 0) return "[undefined]";
if (value === null || typeof value === "number" || typeof value === "boolean") return value;
if (typeof value === "string") return value;
if (typeof value === "bigint" || typeof value === "symbol" || typeof value === "function") return String(value);
if (value instanceof Date) return value.toISOString();
if (Array.isArray(value)) {
if (depth >= 4) return "[Truncated depth]";
return value.map((item) => this.sanitizeForLogging(item, depth + 1, seen));
}
if (typeof value === "object") {
if (seen.has(value)) return "[Circular]";
seen.add(value);
if (depth >= 4) return "[Truncated depth]";
const result = {};
for (const [key, entry] of Object.entries(value)) result[key] = this.sanitizeForLogging(entry, depth + 1, seen);
return result;
}
return String(value);
}
normalizeEventPayload(_type, payload) {
if (payload && typeof payload === "object" && "event" in payload) {
const { event, ...rest } = payload;
const cleaned = Object.keys(rest).length === 0 ? event : {
event,
...rest
};
return this.sanitizeForLogging(cleaned);
}
return this.sanitizeForLogging(payload);
}
normalizeMessageContent(content) {
if (typeof content === "string") return content;
if (content && typeof content === "object" && "text" in content) {
const maybeText = content.text;
if (typeof maybeText === "string") return maybeText;
}
if (content === null || content === void 0) return "";
if (typeof content === "object") try {
return JSON.stringify(this.sanitizeForLogging(content));
} catch {
return "";
}
return String(content);
}
normalizeToolCalls(raw) {
if (!Array.isArray(raw)) return [];
return raw.map((entry) => {
if (!entry || typeof entry !== "object") return null;
const call = entry;
const fn = call.function;
const functionName = typeof fn?.name === "string" ? fn.name : typeof call.toolName === "string" ? call.toolName : void 0;
const args = fn && "arguments" in fn ? fn.arguments : call.arguments;
const normalized = {
id: typeof call.id === "string" ? call.id : void 0,
toolName: typeof call.toolName === "string" ? call.toolName : functionName,
status: typeof call.status === "string" ? call.status : void 0
};
if (functionName) normalized.function = {
name: functionName,
arguments: this.sanitizeForLogging(args)
};
return normalized;
}).filter((call) => Boolean(call));
}
normalizeAgentMessage(message) {
if (!message || typeof message !== "object") return null;
const raw = message;
const role = typeof raw.role === "string" ? raw.role : "unknown";
const contentText = this.normalizeMessageContent(raw.content);
const toolCalls = this.normalizeToolCalls(raw.toolCalls);
return {
id: typeof raw.id === "string" ? raw.id : void 0,
role,
contentText,
contentRaw: raw.content !== void 0 ? this.sanitizeForLogging(raw.content) : void 0,
toolCalls
};
}
normalizeAgentMessages(messages) {
if (!Array.isArray(messages)) return null;
return messages.map((message) => this.normalizeAgentMessage(message)).filter((msg) => msg !== null);
}
normalizeContextStore(context) {
if (!context || typeof context !== "object") return {};
const normalized = {};
for (const [key, entry] of Object.entries(context)) if (entry && typeof entry === "object" && "value" in entry) {
const candidate = entry;
normalized[key] = {
description: typeof candidate.description === "string" && candidate.description.trim().length > 0 ? candidate.description : void 0,
value: candidate.value
};
} else normalized[key] = { value: entry };
return normalized;
}
getSelectedMenu() {
return this.menuItems.find((item) => item.key === this.selectedMenu) ?? this.menuItems[0];
}
renderCoreWarningBanner() {
if (this._core) return lit.nothing;
return lit.html`
${this.renderIcon("AlertTriangle")}
CopilotKit core not attached
Pass a live CopilotKitCore instance to
<cpk-web-inspector> or expose it on
window.__COPILOTKIT_CORE__ for auto-attach.
`;
}
getCoreStatusSummary() {
if (!this._core) return {
label: "Core not attached",
tone: "border border-amber-200 bg-amber-50 text-amber-800",
description: "Pass a CopilotKitCore instance to or enable auto-attach."
};
const status = this.runtimeStatus ?? _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected;
const lastErrorMessage = this.lastCoreError?.message;
if (status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Error) return {
label: "Runtime error",
tone: "border border-rose-200 bg-rose-50 text-rose-700",
description: lastErrorMessage ?? "CopilotKit runtime reported an error."
};
if (status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Connecting) return {
label: "Connecting",
tone: "border border-amber-200 bg-amber-50 text-amber-800",
description: "Waiting for CopilotKit runtime to finish connecting."
};
if (status === _copilotkitnext_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return {
label: "Connected",
tone: "border border-emerald-200 bg-emerald-50 text-emerald-700",
description: "Live runtime connection established."
};
return {
label: "Disconnected",
tone: "border border-gray-200 bg-gray-50 text-gray-700",
description: lastErrorMessage ?? "Waiting for CopilotKit runtime to connect."
};
}
renderMainContent() {
if (this.selectedMenu === "ag-ui-events") return this.renderEventsTable();
if (this.selectedMenu === "agents") return this.renderAgentsView();
if (this.selectedMenu === "frontend-tools") return this.renderToolsView();
if (this.selectedMenu === "agent-context") return this.renderContextView();
return lit.nothing;
}
renderEventsTable() {
const events = this.getEventsForSelectedContext();
const filteredEvents = this.filterEvents(events);
const selectedLabel = this.selectedContext === "all-agents" ? "all agents" : `agent ${this.selectedContext}`;
if (events.length === 0) return lit.html`
${this.renderIcon("Zap")}
No events yet
Trigger an agent run to see live activity.
`;
if (filteredEvents.length === 0) return lit.html`
${this.renderIcon("Filter")}
No events match the current filters.
`;
return lit.html`
Showing ${filteredEvents.length} of
${events.length}${this.selectedContext === "all-agents" ? "" : ` for ${selectedLabel}`}
|
Agent
|
Time
|
Event Type
|
AG-UI Event
|
${filteredEvents.map((event, index) => {
const rowBg = index % 2 === 0 ? "bg-white" : "bg-gray-50/50";
const badgeClasses = this.getEventBadgeClasses(event.type);
const extractedEvent = this.extractEventFromPayload(event.payload);
const inlineEvent = this.stringifyPayload(extractedEvent, false) || "—";
const prettyEvent = this.stringifyPayload(extractedEvent, true) || inlineEvent;
const isExpanded = this.expandedRows.has(event.id);
return lit.html`
this.toggleRowExpansion(event.id)}
>
|
${event.agentId}
|
${new Date(event.timestamp).toLocaleTimeString()}
|
${event.type}
|
${isExpanded ? lit.html`
${prettyEvent}
` : inlineEvent}
|
`;
})}
`;
}
handleEventFilterInput(event) {
this.eventFilterText = event.target?.value ?? "";
this.requestUpdate();
}
handleEventTypeChange(event) {
const value = event.target?.value;
if (!value) return;
this.eventTypeFilter = value;
this.requestUpdate();
}
resetEventFilters() {
this.eventFilterText = "";
this.eventTypeFilter = "all";
this.requestUpdate();
}
exportEvents(events) {
try {
const payload = JSON.stringify(events, null, 2);
const blob = new Blob([payload], { type: "application/json" });
const url = URL.createObjectURL(blob);
const anchor = document.createElement("a");
anchor.href = url;
anchor.download = `copilotkit-events-${Date.now()}.json`;
anchor.click();
URL.revokeObjectURL(url);
} catch (error) {
console.error("Failed to export events", error);
}
}
renderAgentsView() {
if (this.selectedContext === "all-agents") return lit.html`
${this.renderIcon("Bot")}
No agent selected
Select an agent from the dropdown above to view details.
`;
const agentId = this.selectedContext;
const status = this.getAgentStatus(agentId);
const stats = this.getAgentStats(agentId);
const state = this.getLatestStateForAgent(agentId);
const messages = this.getLatestMessagesForAgent(agentId);
return lit.html`
${this.renderIcon("Bot")}
${agentId}
${status.charAt(0).toUpperCase() + status.slice(1)}
${stats.lastActivity ? lit.html`
Last activity:
${new Date(stats.lastActivity).toLocaleTimeString()}` : lit.nothing}
Messages
${stats.messages}
Tool Calls
${stats.toolCalls}
Current State
${this.hasRenderableState(state) ? lit.html`
${this.formatStateForDisplay(state)}
` : lit.html`
${this.renderIcon("Database")}
State is empty
`}
Current Messages
${messages && messages.length > 0 ? lit.html`
|
Role
|
Content
|
${messages.map((msg) => {
const role = msg.role || "unknown";
const roleColors = {
user: "bg-blue-100 text-blue-800",
assistant: "bg-green-100 text-green-800",
system: "bg-gray-100 text-gray-800",
tool: "bg-amber-100 text-amber-800",
unknown: "bg-gray-100 text-gray-600"
};
const rawContent = msg.contentText ?? "";
const toolCalls = msg.toolCalls ?? [];
const hasContent = rawContent.trim().length > 0;
const contentFallback = toolCalls.length > 0 ? "Invoked tool call" : "—";
return lit.html`
|
${role}
|
${hasContent ? lit.html`
${rawContent}
` : lit.html`
${contentFallback}
`}
${role === "assistant" && toolCalls.length > 0 ? this.renderToolCallDetails(toolCalls) : lit.nothing}
|
`;
})}
` : lit.html`
${this.renderIcon("MessageSquare")}
No messages available
`}
`;
}
renderContextDropdown() {
const filteredOptions = this.selectedMenu === "agents" ? this.contextOptions.filter((opt) => opt.key !== "all-agents") : this.contextOptions;
const selectedLabel = filteredOptions.find((opt) => opt.key === this.selectedContext)?.label ?? "";
return lit.html`
${this.contextMenuOpen ? lit.html`
${filteredOptions.map((option) => lit.html`
`)}
` : lit.nothing}
`;
}
handleMenuSelect(key) {
if (!this.menuItems.some((item) => item.key === key)) return;
this.selectedMenu = key;
if (key === "agents" && this.selectedContext === "all-agents") {
const agentOptions = this.contextOptions.filter((opt) => opt.key !== "all-agents");
if (agentOptions.length > 0) {
const defaultAgent = agentOptions.find((opt) => opt.key === "default");
this.selectedContext = defaultAgent ? defaultAgent.key : agentOptions[0].key;
}
}
this.contextMenuOpen = false;
this.persistState();
this.requestUpdate();
}
handleContextDropdownToggle(event) {
event.preventDefault();
event.stopPropagation();
this.contextMenuOpen = !this.contextMenuOpen;
this.requestUpdate();
}
handleContextOptionSelect(key) {
if (!this.contextOptions.some((option) => option.key === key)) return;
if (this.selectedContext !== key) {
this.selectedContext = key;
this.expandedRows.clear();
}
this.contextMenuOpen = false;
this.persistState();
this.requestUpdate();
}
renderToolsView() {
if (!this._core) return lit.html`
No core instance available
`;
this.refreshToolsSnapshot();
const allTools = this.cachedTools;
if (allTools.length === 0) return lit.html`
${this.renderIcon("Hammer")}
No tools available
Tools will appear here once agents are configured with tool
handlers or renderers.
`;
return lit.html`
${(this.selectedContext === "all-agents" ? allTools : allTools.filter((tool) => !tool.agentId || tool.agentId === this.selectedContext)).map((tool) => this.renderToolCard(tool))}
`;
}
extractToolsFromAgents() {
if (!this._core) return [];
const tools = [];
for (const coreTool of this._core.tools ?? []) tools.push({
agentId: coreTool.agentId ?? "",
name: coreTool.name,
description: coreTool.description,
parameters: coreTool.parameters,
type: "handler"
});
for (const [agentId, agent] of Object.entries(this._core.agents)) {
if (!agent) continue;
const handlers = agent.toolHandlers;
if (handlers && typeof handlers === "object") {
for (const [toolName, handler] of Object.entries(handlers)) if (handler && typeof handler === "object") {
const handlerObj = handler;
tools.push({
agentId,
name: toolName,
description: typeof handlerObj.description === "string" && handlerObj.description || handlerObj.tool?.description,
parameters: handlerObj.parameters ?? handlerObj.tool?.parameters,
type: "handler"
});
}
}
const renderers = agent.toolRenderers;
if (renderers && typeof renderers === "object") {
for (const [toolName, renderer] of Object.entries(renderers)) if (!tools.some((t) => t.agentId === agentId && t.name === toolName)) {
if (renderer && typeof renderer === "object") {
const rendererObj = renderer;
tools.push({
agentId,
name: toolName,
description: typeof rendererObj.description === "string" && rendererObj.description || rendererObj.tool?.description,
parameters: rendererObj.parameters ?? rendererObj.tool?.parameters,
type: "renderer"
});
}
}
}
}
return tools.sort((a, b) => {
const agentCompare = a.agentId.localeCompare(b.agentId);
if (agentCompare !== 0) return agentCompare;
return a.name.localeCompare(b.name);
});
}
renderToolCard(tool) {
const isExpanded = this.expandedTools.has(`${tool.agentId}:${tool.name}`);
const schema = this.extractSchemaInfo(tool.parameters);
return lit.html`
${isExpanded ? lit.html`
${schema.properties.length > 0 ? lit.html`
Parameters
${schema.properties.map((prop) => lit.html`
${prop.name}
${prop.required ? lit.html`required` : lit.html`optional`}
${prop.type ? lit.html`${prop.type}` : lit.nothing}
${prop.description ? lit.html`
${prop.description}
` : lit.nothing}
${prop.defaultValue !== void 0 ? lit.html`
Default:
${JSON.stringify(prop.defaultValue)}
` : lit.nothing}
${prop.enum && prop.enum.length > 0 ? lit.html`
Allowed values:
${prop.enum.map((val) => lit.html`
${JSON.stringify(val)}
`)}
` : lit.nothing}
`)}
` : lit.html`
No parameters defined
`}
` : lit.nothing}
`;
}
extractSchemaInfo(parameters) {
const result = { properties: [] };
if (!parameters || typeof parameters !== "object") return result;
const zodDef = parameters._def;
if (zodDef && typeof zodDef === "object") {
if (zodDef.typeName === "ZodObject") {
const rawShape = zodDef.shape;
const shape = typeof rawShape === "function" ? rawShape() : rawShape;
if (!shape || typeof shape !== "object") return result;
const requiredKeys = /* @__PURE__ */ new Set();
if (zodDef.unknownKeys === "strict" || !zodDef.catchall) Object.keys(shape || {}).forEach((key) => {
const candidate = shape[key];
if (candidate?._def && !this.isZodOptional(candidate)) requiredKeys.add(key);
});
for (const [key, value] of Object.entries(shape || {})) {
const fieldInfo = this.extractZodFieldInfo(value);
result.properties.push({
name: key,
type: fieldInfo.type,
description: fieldInfo.description,
required: requiredKeys.has(key),
defaultValue: fieldInfo.defaultValue,
enum: fieldInfo.enum
});
}
}
} else if (parameters.type === "object" && parameters.properties) {
const props = parameters.properties;
const required = new Set(Array.isArray(parameters.required) ? parameters.required : []);
for (const [key, value] of Object.entries(props ?? {})) {
const prop = value;
result.properties.push({
name: key,
type: prop.type,
description: typeof prop.description === "string" ? prop.description : void 0,
required: required.has(key),
defaultValue: prop.default,
enum: Array.isArray(prop.enum) ? prop.enum : void 0
});
}
}
return result;
}
isZodOptional(zodSchema) {
const schema = zodSchema;
if (!schema?._def) return false;
const def = schema._def;
if (def.typeName === "ZodOptional" || def.typeName === "ZodNullable") return true;
if (def.defaultValue !== void 0) return true;
return false;
}
extractZodFieldInfo(zodSchema) {
const info = {};
const schema = zodSchema;
if (!schema?._def) return info;
let currentSchema = schema;
let def = currentSchema._def;
while (def.typeName === "ZodOptional" || def.typeName === "ZodNullable" || def.typeName === "ZodDefault") {
if (def.typeName === "ZodDefault" && def.defaultValue !== void 0) info.defaultValue = typeof def.defaultValue === "function" ? def.defaultValue() : def.defaultValue;
currentSchema = def.innerType ?? currentSchema;
if (!currentSchema?._def) break;
def = currentSchema._def;
}
info.description = typeof def.description === "string" ? def.description : void 0;
const typeName = typeof def.typeName === "string" ? def.typeName : void 0;
info.type = typeName ? {
ZodString: "string",
ZodNumber: "number",
ZodBoolean: "boolean",
ZodArray: "array",
ZodObject: "object",
ZodEnum: "enum",
ZodLiteral: "literal",
ZodUnion: "union",
ZodAny: "any",
ZodUnknown: "unknown"
}[typeName] || typeName.replace("Zod", "").toLowerCase() : void 0;
if (typeName === "ZodEnum" && Array.isArray(def.values)) info.enum = def.values;
else if (typeName === "ZodLiteral" && def.value !== void 0) info.enum = [def.value];
return info;
}
toggleToolExpansion(toolId) {
if (this.expandedTools.has(toolId)) this.expandedTools.delete(toolId);
else this.expandedTools.add(toolId);
this.requestUpdate();
}
renderContextView() {
const contextEntries = Object.entries(this.contextStore);
if (contextEntries.length === 0) return lit.html`
${this.renderIcon("FileText")}
No context available
Context will appear here once added to CopilotKit.
`;
return lit.html`
${contextEntries.map(([id, context]) => this.renderContextCard(id, context))}
`;
}
renderContextCard(id, context) {
const isExpanded = this.expandedContextItems.has(id);
const valuePreview = this.getContextValuePreview(context.value);
const hasValue = context.value !== void 0 && context.value !== null;
return lit.html`
${isExpanded ? lit.html`
ID
${id}
${hasValue ? lit.html`
Value
${this.formatContextValue(context.value)}
` : lit.html`
No value available
`}
` : lit.nothing}
`;
}
getContextValuePreview(value) {
if (value === void 0 || value === null) return "—";
if (typeof value === "string") return value.length > 50 ? `${value.substring(0, 50)}...` : value;
if (typeof value === "number" || typeof value === "boolean") return String(value);
if (Array.isArray(value)) return `Array(${value.length})`;
if (typeof value === "object") {
const keys = Object.keys(value);
return `Object with ${keys.length} key${keys.length !== 1 ? "s" : ""}`;
}
if (typeof value === "function") return "Function";
return String(value);
}
formatContextValue(value) {
if (value === void 0) return "undefined";
if (value === null) return "null";
if (typeof value === "function") return value.toString();
try {
return JSON.stringify(value, null, 2);
} catch {
return String(value);
}
}
async copyContextValue(value, contextId) {
if (typeof navigator === "undefined" || !navigator.clipboard?.writeText) {
console.warn("Clipboard API is not available in this environment.");
return;
}
const serialized = this.formatContextValue(value);
try {
await navigator.clipboard.writeText(serialized);
this.copiedContextItems.add(contextId);
this.requestUpdate();
setTimeout(() => {
this.copiedContextItems.delete(contextId);
this.requestUpdate();
}, 1500);
} catch (error) {
console.error("Failed to copy context value:", error);
}
}
toggleContextExpansion(contextId) {
if (this.expandedContextItems.has(contextId)) this.expandedContextItems.delete(contextId);
else this.expandedContextItems.add(contextId);
this.requestUpdate();
}
toggleRowExpansion(eventId) {
const selection = window.getSelection();
if (selection && selection.toString().length > 0) return;
if (this.expandedRows.has(eventId)) this.expandedRows.delete(eventId);
else this.expandedRows.add(eventId);
this.requestUpdate();
}
renderAnnouncementPanel() {
if (!this.isOpen) return lit.nothing;
this.ensureAnnouncementLoading();
if (!this.hasUnseenAnnouncement) return lit.nothing;
if (!this.announcementLoaded && !this.announcementMarkdown) return lit.html`
${this.renderIcon("Megaphone")}
Loading latest announcement…
`;
if (this.announcementLoadError) return lit.html`
${this.renderIcon("Megaphone")}
Announcement unavailable
We couldn’t load the latest notice. Please try opening the inspector
again.
`;
if (!this.announcementMarkdown) return lit.nothing;
const content = this.announcementHtml ? (0, lit_directives_unsafe_html_js.unsafeHTML)(this.announcementHtml) : lit.html`
${this.announcementMarkdown}`;
return lit.html`
${this.renderIcon("Megaphone")}
Announcement
${content}
`;
}
ensureAnnouncementLoading() {
if (this.announcementPromise || typeof window === "undefined" || typeof fetch === "undefined") return;
this.announcementPromise = this.fetchAnnouncement();
}
renderAnnouncementPreview() {
if (!this.hasUnseenAnnouncement || !this.showAnnouncementPreview || !this.announcementPreviewText) return lit.nothing;
return lit.html` this.handleAnnouncementPreviewClick()}
>
${this.announcementPreviewText}
`;
}
handleAnnouncementPreviewClick() {
this.showAnnouncementPreview = false;
this.openInspector();
}
async fetchAnnouncement() {
try {
const response = await fetch(ANNOUNCEMENT_URL, { cache: "no-cache" });
if (!response.ok) throw new Error(`Failed to load announcement (${response.status})`);
const data = await response.json();
const timestamp = typeof data?.timestamp === "string" ? data.timestamp : null;
const previewText = typeof data?.previewText === "string" ? data.previewText : null;
const markdown = typeof data?.announcement === "string" ? data.announcement : null;
if (!timestamp || !markdown) throw new Error("Malformed announcement payload");
const storedTimestamp = this.loadStoredAnnouncementTimestamp();
this.announcementTimestamp = timestamp;
this.announcementPreviewText = previewText ?? "";
this.announcementMarkdown = markdown;
this.hasUnseenAnnouncement = (!storedTimestamp || storedTimestamp !== timestamp) && !!this.announcementPreviewText;
this.showAnnouncementPreview = this.hasUnseenAnnouncement;
this.announcementHtml = await this.convertMarkdownToHtml(markdown);
this.announcementLoaded = true;
this.requestUpdate();
} catch (error) {
this.announcementLoadError = error;
this.announcementLoaded = true;
this.requestUpdate();
}
}
async convertMarkdownToHtml(markdown) {
const renderer = new marked.marked.Renderer();
renderer.link = (href, title, text) => {
return `${text}`;
};
return marked.marked.parse(markdown, { renderer });
}
appendRefParam(href) {
try {
const url = new URL(href, typeof window !== "undefined" ? window.location.href : "https://copilotkit.ai");
if (!url.searchParams.has("ref")) url.searchParams.append("ref", "cpk-inspector");
return url.toString();
} catch {
return href;
}
}
escapeHtmlAttr(value) {
return value.replace(/&/g, "&").replace(//g, ">").replace(/\"/g, """).replace(/'/g, "'");
}
loadStoredAnnouncementTimestamp() {
if (typeof window === "undefined" || !window.localStorage) return null;
try {
const raw = window.localStorage.getItem(ANNOUNCEMENT_STORAGE_KEY);
if (!raw) return null;
const parsed = JSON.parse(raw);
if (parsed && typeof parsed.timestamp === "string") return parsed.timestamp;
return null;
} catch {}
return null;
}
persistAnnouncementTimestamp(timestamp) {
if (typeof window === "undefined" || !window.localStorage) return;
try {
const payload = JSON.stringify({ timestamp });
window.localStorage.setItem(ANNOUNCEMENT_STORAGE_KEY, payload);
} catch {}
}
markAnnouncementSeen() {
this.hasUnseenAnnouncement = false;
this.showAnnouncementPreview = false;
if (!this.announcementTimestamp) {
if (this.announcementPromise && !this.announcementLoaded) this.announcementPromise.then(() => this.markAnnouncementSeen()).catch(() => void 0);
this.requestUpdate();
return;
}
this.persistAnnouncementTimestamp(this.announcementTimestamp);
this.requestUpdate();
}
};
function defineWebInspector() {
if (!customElements.get(WEB_INSPECTOR_TAG)) customElements.define(WEB_INSPECTOR_TAG, WebInspectorElement);
}
defineWebInspector();
//#endregion
exports.WEB_INSPECTOR_TAG = WEB_INSPECTOR_TAG;
exports.WebInspectorElement = WebInspectorElement;
exports.defineWebInspector = defineWebInspector;
//# sourceMappingURL=index.cjs.map