1 line
179 KiB
Plaintext
1 line
179 KiB
Plaintext
{"version":3,"file":"index.cjs","names":["LitElement","nothing","tailwindStyles","inspectorLogoIconUrl","inspectorLogoUrl","loadInspectorState","isValidDockMode","isValidAnchor","isValidPosition","isValidSize","constrainToViewport","clampSizeToViewport","icons","CopilotKitCoreRuntimeConnectionStatus"],"sources":["../src/index.ts"],"sourcesContent":["import { LitElement, css, html, nothing, unsafeCSS } from \"lit\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport tailwindStyles from \"./styles/generated.css\";\nimport inspectorLogoUrl from \"./assets/inspector-logo.svg\";\nimport inspectorLogoIconUrl from \"./assets/inspector-logo-icon.svg\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { marked } from \"marked\";\nimport { icons } from \"lucide\";\nimport {\n CopilotKitCore,\n CopilotKitCoreRuntimeConnectionStatus,\n type CopilotKitCoreSubscriber,\n type CopilotKitCoreErrorCode,\n} from \"@copilotkitnext/core\";\nimport type { AbstractAgent, AgentSubscriber } from \"@ag-ui/client\";\nimport type {\n Anchor,\n ContextKey,\n ContextState,\n DockMode,\n Position,\n Size,\n} from \"./lib/types\";\nimport {\n applyAnchorPosition as applyAnchorPositionHelper,\n centerContext as centerContextHelper,\n constrainToViewport,\n keepPositionWithinViewport,\n updateAnchorFromPosition as updateAnchorFromPositionHelper,\n updateSizeFromElement,\n clampSize as clampSizeToViewport,\n} from \"./lib/context-helpers\";\nimport {\n loadInspectorState,\n saveInspectorState,\n type PersistedState,\n isValidAnchor,\n isValidPosition,\n isValidSize,\n isValidDockMode,\n} from \"./lib/persistence\";\n\nexport const WEB_INSPECTOR_TAG = \"cpk-web-inspector\" as const;\n\ntype LucideIconName = keyof typeof icons;\n\ntype MenuKey = \"ag-ui-events\" | \"agents\" | \"frontend-tools\" | \"agent-context\";\n\ntype MenuItem = {\n key: MenuKey;\n label: string;\n icon: LucideIconName;\n};\n\nconst EDGE_MARGIN = 16;\nconst DRAG_THRESHOLD = 6;\nconst MIN_WINDOW_WIDTH = 600;\nconst MIN_WINDOW_WIDTH_DOCKED_LEFT = 420;\nconst MIN_WINDOW_HEIGHT = 200;\nconst INSPECTOR_STORAGE_KEY = \"cpk:inspector:state\";\nconst ANNOUNCEMENT_STORAGE_KEY = \"cpk:inspector:announcements\";\nconst ANNOUNCEMENT_URL = \"https://cdn.copilotkit.ai/announcements.json\";\nconst DEFAULT_BUTTON_SIZE: Size = { width: 48, height: 48 };\nconst DEFAULT_WINDOW_SIZE: Size = { width: 840, height: 560 };\nconst DOCKED_LEFT_WIDTH = 500; // Sensible width for left dock with collapsed sidebar\nconst MAX_AGENT_EVENTS = 200;\nconst MAX_TOTAL_EVENTS = 500;\n\ntype InspectorAgentEventType =\n | \"RUN_STARTED\"\n | \"RUN_FINISHED\"\n | \"RUN_ERROR\"\n | \"TEXT_MESSAGE_START\"\n | \"TEXT_MESSAGE_CONTENT\"\n | \"TEXT_MESSAGE_END\"\n | \"TOOL_CALL_START\"\n | \"TOOL_CALL_ARGS\"\n | \"TOOL_CALL_END\"\n | \"TOOL_CALL_RESULT\"\n | \"STATE_SNAPSHOT\"\n | \"STATE_DELTA\"\n | \"MESSAGES_SNAPSHOT\"\n | \"RAW_EVENT\"\n | \"CUSTOM_EVENT\"\n | \"REASONING_START\"\n | \"REASONING_MESSAGE_START\"\n | \"REASONING_MESSAGE_CONTENT\"\n | \"REASONING_MESSAGE_END\"\n | \"REASONING_END\"\n | \"REASONING_ENCRYPTED_VALUE\";\n\nconst AGENT_EVENT_TYPES: readonly InspectorAgentEventType[] = [\n \"RUN_STARTED\",\n \"RUN_FINISHED\",\n \"RUN_ERROR\",\n \"TEXT_MESSAGE_START\",\n \"TEXT_MESSAGE_CONTENT\",\n \"TEXT_MESSAGE_END\",\n \"TOOL_CALL_START\",\n \"TOOL_CALL_ARGS\",\n \"TOOL_CALL_END\",\n \"TOOL_CALL_RESULT\",\n \"STATE_SNAPSHOT\",\n \"STATE_DELTA\",\n \"MESSAGES_SNAPSHOT\",\n \"RAW_EVENT\",\n \"CUSTOM_EVENT\",\n \"REASONING_START\",\n \"REASONING_MESSAGE_START\",\n \"REASONING_MESSAGE_CONTENT\",\n \"REASONING_MESSAGE_END\",\n \"REASONING_END\",\n \"REASONING_ENCRYPTED_VALUE\",\n] as const;\n\ntype SanitizedValue =\n | string\n | number\n | boolean\n | null\n | SanitizedValue[]\n | { [key: string]: SanitizedValue };\n\ntype InspectorToolCall = {\n id?: string;\n function?: {\n name?: string;\n arguments?: SanitizedValue | string;\n };\n toolName?: string;\n status?: string;\n};\n\ntype InspectorMessage = {\n id?: string;\n role: string;\n contentText: string;\n contentRaw?: SanitizedValue;\n toolCalls: InspectorToolCall[];\n};\n\ntype InspectorToolDefinition = {\n agentId: string;\n name: string;\n description?: string;\n parameters?: unknown;\n type: \"handler\" | \"renderer\";\n};\n\ntype InspectorEvent = {\n id: string;\n agentId: string;\n type: InspectorAgentEventType;\n timestamp: number;\n payload: SanitizedValue;\n};\n\nexport class WebInspectorElement extends LitElement {\n static properties = {\n core: { attribute: false },\n autoAttachCore: { type: Boolean, attribute: \"auto-attach-core\" },\n } as const;\n\n private _core: CopilotKitCore | null = null;\n private coreSubscriber: CopilotKitCoreSubscriber | null = null;\n private coreUnsubscribe: (() => void) | null = null;\n private runtimeStatus: CopilotKitCoreRuntimeConnectionStatus | null = null;\n private coreProperties: Readonly<Record<string, unknown>> = {};\n private lastCoreError: {\n code: CopilotKitCoreErrorCode;\n message: string;\n } | null = null;\n private agentSubscriptions: Map<string, () => void> = new Map();\n private agentEvents: Map<string, InspectorEvent[]> = new Map();\n private agentMessages: Map<string, InspectorMessage[]> = new Map();\n private agentStates: Map<string, SanitizedValue> = new Map();\n private flattenedEvents: InspectorEvent[] = [];\n private eventCounter = 0;\n private contextStore: Record<\n string,\n { description?: string; value: unknown }\n > = {};\n\n private pointerId: number | null = null;\n private dragStart: Position | null = null;\n private dragOffset: Position = { x: 0, y: 0 };\n private isDragging = false;\n private pointerContext: ContextKey | null = null;\n private isOpen = false;\n private draggedDuringInteraction = false;\n private ignoreNextButtonClick = false;\n private selectedMenu: MenuKey = \"ag-ui-events\";\n private contextMenuOpen = false;\n private dockMode: DockMode = \"floating\";\n private previousBodyMargins: { left: string; bottom: string } | null = null;\n private transitionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private pendingSelectedContext: string | null = null;\n private autoAttachCore = true;\n private attemptedAutoAttach = false;\n private cachedTools: InspectorToolDefinition[] = [];\n private toolSignature = \"\";\n private eventFilterText = \"\";\n private eventTypeFilter: InspectorAgentEventType | \"all\" = \"all\";\n\n private announcementMarkdown: string | null = null;\n private announcementHtml: string | null = null;\n private announcementTimestamp: string | null = null;\n private announcementPreviewText: string | null = null;\n private hasUnseenAnnouncement = false;\n private announcementLoaded = false;\n private announcementLoadError: unknown = null;\n private announcementPromise: Promise<void> | null = null;\n private showAnnouncementPreview = true;\n\n get core(): CopilotKitCore | null {\n return this._core;\n }\n\n set core(value: CopilotKitCore | null) {\n const oldValue = this._core;\n if (oldValue === value) {\n return;\n }\n\n this.detachFromCore();\n\n this._core = value ?? null;\n this.requestUpdate(\"core\", oldValue);\n\n if (this._core) {\n this.attachToCore(this._core);\n }\n }\n\n private readonly contextState: Record<ContextKey, ContextState> = {\n button: {\n position: { x: EDGE_MARGIN, y: EDGE_MARGIN },\n size: { ...DEFAULT_BUTTON_SIZE },\n anchor: { horizontal: \"right\", vertical: \"top\" },\n anchorOffset: { x: EDGE_MARGIN, y: EDGE_MARGIN },\n },\n window: {\n position: { x: EDGE_MARGIN, y: EDGE_MARGIN },\n size: { ...DEFAULT_WINDOW_SIZE },\n anchor: { horizontal: \"right\", vertical: \"top\" },\n anchorOffset: { x: EDGE_MARGIN, y: EDGE_MARGIN },\n },\n };\n\n private hasCustomPosition: Record<ContextKey, boolean> = {\n button: false,\n window: false,\n };\n\n private resizePointerId: number | null = null;\n private resizeStart: Position | null = null;\n private resizeInitialSize: { width: number; height: number } | null = null;\n private isResizing = false;\n\n private readonly menuItems: MenuItem[] = [\n { key: \"ag-ui-events\", label: \"AG-UI Events\", icon: \"Zap\" },\n { key: \"agents\", label: \"Agent\", icon: \"Bot\" },\n { key: \"frontend-tools\", label: \"Frontend Tools\", icon: \"Hammer\" },\n { key: \"agent-context\", label: \"Context\", icon: \"FileText\" },\n ];\n\n private attachToCore(core: CopilotKitCore): void {\n this.runtimeStatus = core.runtimeConnectionStatus;\n this.coreProperties = core.properties;\n this.lastCoreError = null;\n\n this.coreSubscriber = {\n onRuntimeConnectionStatusChanged: ({ status }) => {\n this.runtimeStatus = status;\n this.requestUpdate();\n },\n onPropertiesChanged: ({ properties }) => {\n this.coreProperties = properties;\n this.requestUpdate();\n },\n onError: ({ code, error }) => {\n this.lastCoreError = { code, message: error.message };\n this.requestUpdate();\n },\n onAgentsChanged: ({ agents }) => {\n this.processAgentsChanged(agents);\n },\n onContextChanged: ({ context }) => {\n this.contextStore = this.normalizeContextStore(context);\n this.requestUpdate();\n },\n } satisfies CopilotKitCoreSubscriber;\n\n this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;\n this.processAgentsChanged(core.agents);\n\n // Initialize context from core\n if (core.context) {\n this.contextStore = this.normalizeContextStore(core.context);\n }\n }\n\n private detachFromCore(): void {\n if (this.coreUnsubscribe) {\n this.coreUnsubscribe();\n this.coreUnsubscribe = null;\n }\n this.coreSubscriber = null;\n this.runtimeStatus = null;\n this.lastCoreError = null;\n this.coreProperties = {};\n this.cachedTools = [];\n this.toolSignature = \"\";\n this.teardownAgentSubscriptions();\n }\n\n private teardownAgentSubscriptions(): void {\n for (const unsubscribe of this.agentSubscriptions.values()) {\n unsubscribe();\n }\n this.agentSubscriptions.clear();\n this.agentEvents.clear();\n this.agentMessages.clear();\n this.agentStates.clear();\n this.flattenedEvents = [];\n this.eventCounter = 0;\n }\n\n private processAgentsChanged(\n agents: Readonly<Record<string, AbstractAgent>>,\n ): void {\n const seenAgentIds = new Set<string>();\n\n for (const agent of Object.values(agents)) {\n if (!agent?.agentId) {\n continue;\n }\n seenAgentIds.add(agent.agentId);\n this.subscribeToAgent(agent);\n }\n\n for (const agentId of Array.from(this.agentSubscriptions.keys())) {\n if (!seenAgentIds.has(agentId)) {\n this.unsubscribeFromAgent(agentId);\n this.agentEvents.delete(agentId);\n this.agentMessages.delete(agentId);\n this.agentStates.delete(agentId);\n }\n }\n\n this.updateContextOptions(seenAgentIds);\n this.refreshToolsSnapshot();\n this.requestUpdate();\n }\n\n private refreshToolsSnapshot(): void {\n if (!this._core) {\n if (this.cachedTools.length > 0) {\n this.cachedTools = [];\n this.toolSignature = \"\";\n this.requestUpdate();\n }\n return;\n }\n\n const tools = this.extractToolsFromAgents();\n const signature = JSON.stringify(\n tools.map((tool) => ({\n agentId: tool.agentId,\n name: tool.name,\n type: tool.type,\n hasDescription: Boolean(tool.description),\n hasParameters: Boolean(tool.parameters),\n })),\n );\n\n if (signature !== this.toolSignature) {\n this.toolSignature = signature;\n this.cachedTools = tools;\n this.requestUpdate();\n }\n }\n\n private tryAutoAttachCore(): void {\n if (\n this.attemptedAutoAttach ||\n this._core ||\n !this.autoAttachCore ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n this.attemptedAutoAttach = true;\n\n const globalWindow = window as unknown as Record<string, unknown>;\n const globalCandidates: Array<unknown> = [\n // Common app-level globals used during development\n globalWindow.__COPILOTKIT_CORE__,\n (globalWindow.copilotkit as { core?: unknown } | undefined)?.core,\n globalWindow.copilotkitCore,\n ];\n\n const foundCore = globalCandidates.find(\n (candidate): candidate is CopilotKitCore =>\n !!candidate && typeof candidate === \"object\",\n );\n\n if (foundCore) {\n this.core = foundCore;\n }\n }\n\n private subscribeToAgent(agent: AbstractAgent): void {\n if (!agent.agentId) {\n return;\n }\n\n const agentId = agent.agentId;\n\n this.unsubscribeFromAgent(agentId);\n\n const subscriber: AgentSubscriber = {\n onRunStartedEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"RUN_STARTED\", event);\n },\n onRunFinishedEvent: ({ event, result }) => {\n this.recordAgentEvent(agentId, \"RUN_FINISHED\", { event, result });\n },\n onRunErrorEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"RUN_ERROR\", event);\n },\n onTextMessageStartEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"TEXT_MESSAGE_START\", event);\n },\n onTextMessageContentEvent: ({ event, textMessageBuffer }) => {\n this.recordAgentEvent(agentId, \"TEXT_MESSAGE_CONTENT\", {\n event,\n textMessageBuffer,\n });\n },\n onTextMessageEndEvent: ({ event, textMessageBuffer }) => {\n this.recordAgentEvent(agentId, \"TEXT_MESSAGE_END\", {\n event,\n textMessageBuffer,\n });\n },\n onToolCallStartEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"TOOL_CALL_START\", event);\n },\n onToolCallArgsEvent: ({\n event,\n toolCallBuffer,\n toolCallName,\n partialToolCallArgs,\n }) => {\n this.recordAgentEvent(agentId, \"TOOL_CALL_ARGS\", {\n event,\n toolCallBuffer,\n toolCallName,\n partialToolCallArgs,\n });\n },\n onToolCallEndEvent: ({ event, toolCallArgs, toolCallName }) => {\n this.recordAgentEvent(agentId, \"TOOL_CALL_END\", {\n event,\n toolCallArgs,\n toolCallName,\n });\n },\n onToolCallResultEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"TOOL_CALL_RESULT\", event);\n },\n onStateSnapshotEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STATE_SNAPSHOT\", event);\n this.syncAgentState(agent);\n },\n onStateDeltaEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STATE_DELTA\", event);\n this.syncAgentState(agent);\n },\n onMessagesSnapshotEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"MESSAGES_SNAPSHOT\", event);\n this.syncAgentMessages(agent);\n },\n onMessagesChanged: () => {\n this.syncAgentMessages(agent);\n },\n onRawEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"RAW_EVENT\", event);\n },\n onCustomEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"CUSTOM_EVENT\", event);\n },\n onReasoningStartEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"REASONING_START\", event);\n },\n onReasoningMessageStartEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"REASONING_MESSAGE_START\", event);\n },\n onReasoningMessageContentEvent: ({ event, reasoningMessageBuffer }) => {\n this.recordAgentEvent(agentId, \"REASONING_MESSAGE_CONTENT\", {\n event,\n reasoningMessageBuffer,\n });\n },\n onReasoningMessageEndEvent: ({ event, reasoningMessageBuffer }) => {\n this.recordAgentEvent(agentId, \"REASONING_MESSAGE_END\", {\n event,\n reasoningMessageBuffer,\n });\n },\n onReasoningEndEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"REASONING_END\", event);\n },\n onReasoningEncryptedValueEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"REASONING_ENCRYPTED_VALUE\", event);\n },\n };\n\n const { unsubscribe } = agent.subscribe(subscriber);\n this.agentSubscriptions.set(agentId, unsubscribe);\n this.syncAgentMessages(agent);\n this.syncAgentState(agent);\n\n if (!this.agentEvents.has(agentId)) {\n this.agentEvents.set(agentId, []);\n }\n }\n\n private unsubscribeFromAgent(agentId: string): void {\n const unsubscribe = this.agentSubscriptions.get(agentId);\n if (unsubscribe) {\n unsubscribe();\n this.agentSubscriptions.delete(agentId);\n }\n }\n\n private recordAgentEvent(\n agentId: string,\n type: InspectorAgentEventType,\n payload: unknown,\n ): void {\n const eventId = `${agentId}:${++this.eventCounter}`;\n const normalizedPayload = this.normalizeEventPayload(type, payload);\n const event: InspectorEvent = {\n id: eventId,\n agentId,\n type,\n timestamp: Date.now(),\n payload: normalizedPayload,\n };\n\n const currentAgentEvents = this.agentEvents.get(agentId) ?? [];\n const nextAgentEvents = [event, ...currentAgentEvents].slice(\n 0,\n MAX_AGENT_EVENTS,\n );\n this.agentEvents.set(agentId, nextAgentEvents);\n\n this.flattenedEvents = [event, ...this.flattenedEvents].slice(\n 0,\n MAX_TOTAL_EVENTS,\n );\n this.refreshToolsSnapshot();\n this.requestUpdate();\n }\n\n private syncAgentMessages(agent: AbstractAgent): void {\n if (!agent?.agentId) {\n return;\n }\n\n const messages = this.normalizeAgentMessages(\n (agent as { messages?: unknown }).messages,\n );\n if (messages) {\n this.agentMessages.set(agent.agentId, messages);\n } else {\n this.agentMessages.delete(agent.agentId);\n }\n\n this.requestUpdate();\n }\n\n private syncAgentState(agent: AbstractAgent): void {\n if (!agent?.agentId) {\n return;\n }\n\n const state = (agent as { state?: unknown }).state;\n\n if (state === undefined || state === null) {\n this.agentStates.delete(agent.agentId);\n } else {\n this.agentStates.set(agent.agentId, this.sanitizeForLogging(state));\n }\n\n this.requestUpdate();\n }\n\n private updateContextOptions(agentIds: Set<string>): void {\n const nextOptions: Array<{ key: string; label: string }> = [\n { key: \"all-agents\", label: \"All Agents\" },\n ...Array.from(agentIds)\n .sort((a, b) => a.localeCompare(b))\n .map((id) => ({ key: id, label: id })),\n ];\n\n const optionsChanged =\n this.contextOptions.length !== nextOptions.length ||\n this.contextOptions.some(\n (option, index) => option.key !== nextOptions[index]?.key,\n );\n\n if (optionsChanged) {\n this.contextOptions = nextOptions;\n }\n\n const pendingContext = this.pendingSelectedContext;\n if (pendingContext) {\n const isPendingAvailable =\n pendingContext === \"all-agents\" || agentIds.has(pendingContext);\n if (isPendingAvailable) {\n if (this.selectedContext !== pendingContext) {\n this.selectedContext = pendingContext;\n this.expandedRows.clear();\n }\n this.pendingSelectedContext = null;\n } else if (agentIds.size > 0) {\n // Agents are loaded but the pending selection no longer exists\n this.pendingSelectedContext = null;\n }\n }\n\n const hasSelectedContext = nextOptions.some(\n (option) => option.key === this.selectedContext,\n );\n\n if (!hasSelectedContext && this.pendingSelectedContext === null) {\n // Auto-select \"default\" agent if it exists, otherwise first agent, otherwise \"all-agents\"\n let nextSelected: string = \"all-agents\";\n\n if (agentIds.has(\"default\")) {\n nextSelected = \"default\";\n } else if (agentIds.size > 0) {\n nextSelected = Array.from(agentIds).sort((a, b) =>\n a.localeCompare(b),\n )[0]!;\n }\n\n if (this.selectedContext !== nextSelected) {\n this.selectedContext = nextSelected;\n this.expandedRows.clear();\n this.persistState();\n }\n }\n }\n\n private getEventsForSelectedContext(): InspectorEvent[] {\n if (this.selectedContext === \"all-agents\") {\n return this.flattenedEvents;\n }\n\n return this.agentEvents.get(this.selectedContext) ?? [];\n }\n\n private filterEvents(events: InspectorEvent[]): InspectorEvent[] {\n const query = this.eventFilterText.trim().toLowerCase();\n\n return events.filter((event) => {\n if (\n this.eventTypeFilter !== \"all\" &&\n event.type !== this.eventTypeFilter\n ) {\n return false;\n }\n\n if (!query) {\n return true;\n }\n\n const payloadText = this.stringifyPayload(\n event.payload,\n false,\n ).toLowerCase();\n return (\n event.type.toLowerCase().includes(query) ||\n event.agentId.toLowerCase().includes(query) ||\n payloadText.includes(query)\n );\n });\n }\n\n private getLatestStateForAgent(agentId: string): SanitizedValue | null {\n if (this.agentStates.has(agentId)) {\n const value = this.agentStates.get(agentId);\n return value === undefined ? null : value;\n }\n\n const events = this.agentEvents.get(agentId) ?? [];\n const stateEvent = events.find((e) => e.type === \"STATE_SNAPSHOT\");\n if (!stateEvent) {\n return null;\n }\n return stateEvent.payload;\n }\n\n private getLatestMessagesForAgent(\n agentId: string,\n ): InspectorMessage[] | null {\n const messages = this.agentMessages.get(agentId);\n return messages ?? null;\n }\n\n private getAgentStatus(agentId: string): \"running\" | \"idle\" | \"error\" {\n const events = this.agentEvents.get(agentId) ?? [];\n if (events.length === 0) {\n return \"idle\";\n }\n\n // Check most recent run-related event\n const runEvent = events.find(\n (e) =>\n e.type === \"RUN_STARTED\" ||\n e.type === \"RUN_FINISHED\" ||\n e.type === \"RUN_ERROR\",\n );\n\n if (!runEvent) {\n return \"idle\";\n }\n\n if (runEvent.type === \"RUN_ERROR\") {\n return \"error\";\n }\n\n if (runEvent.type === \"RUN_STARTED\") {\n // Check if there's a RUN_FINISHED after this\n const finishedAfter = events.find(\n (e) => e.type === \"RUN_FINISHED\" && e.timestamp > runEvent.timestamp,\n );\n return finishedAfter ? \"idle\" : \"running\";\n }\n\n return \"idle\";\n }\n\n private getAgentStats(agentId: string): {\n totalEvents: number;\n lastActivity: number | null;\n messages: number;\n toolCalls: number;\n errors: number;\n } {\n const events = this.agentEvents.get(agentId) ?? [];\n\n const messages = this.agentMessages.get(agentId);\n\n const toolCallCount = messages\n ? messages.reduce(\n (count, message) => count + (message.toolCalls?.length ?? 0),\n 0,\n )\n : events.filter((e) => e.type === \"TOOL_CALL_END\").length;\n\n const messageCount = messages?.length ?? 0;\n\n return {\n totalEvents: events.length,\n lastActivity: events[0]?.timestamp ?? null,\n messages: messageCount,\n toolCalls: toolCallCount,\n errors: events.filter((e) => e.type === \"RUN_ERROR\").length,\n };\n }\n\n private renderToolCallDetails(toolCalls: InspectorToolCall[]) {\n if (!Array.isArray(toolCalls) || toolCalls.length === 0) {\n return nothing;\n }\n\n return html`\n <div class=\"mt-2 space-y-2\">\n ${toolCalls.map((call, index) => {\n const functionName =\n call.function?.name ?? call.toolName ?? \"Unknown function\";\n const callId =\n typeof call?.id === \"string\" ? call.id : `tool-call-${index + 1}`;\n const argsString = this.formatToolCallArguments(\n call.function?.arguments,\n );\n return html`\n <div\n class=\"rounded-md border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700\"\n >\n <div\n class=\"flex flex-wrap items-center justify-between gap-1 font-medium text-gray-900\"\n >\n <span>${functionName}</span>\n <span class=\"text-[10px] text-gray-500\">ID: ${callId}</span>\n </div>\n ${argsString\n ? html`<pre\n class=\"mt-2 overflow-auto rounded bg-white p-2 text-[11px] leading-relaxed text-gray-800\"\n >\n${argsString}</pre\n >`\n : nothing}\n </div>\n `;\n })}\n </div>\n `;\n }\n\n private formatToolCallArguments(args: unknown): string | null {\n if (args === undefined || args === null || args === \"\") {\n return null;\n }\n\n if (typeof args === \"string\") {\n try {\n const parsed = JSON.parse(args);\n return JSON.stringify(parsed, null, 2);\n } catch {\n return args;\n }\n }\n\n if (typeof args === \"object\") {\n try {\n return JSON.stringify(args, null, 2);\n } catch {\n return String(args);\n }\n }\n\n return String(args);\n }\n\n private hasRenderableState(state: unknown): boolean {\n if (state === null || state === undefined) {\n return false;\n }\n\n if (Array.isArray(state)) {\n return state.length > 0;\n }\n\n if (typeof state === \"object\") {\n return Object.keys(state as Record<string, unknown>).length > 0;\n }\n\n if (typeof state === \"string\") {\n const trimmed = state.trim();\n return trimmed.length > 0 && trimmed !== \"{}\";\n }\n\n return true;\n }\n\n private formatStateForDisplay(state: unknown): string {\n if (state === null || state === undefined) {\n return \"\";\n }\n\n if (typeof state === \"string\") {\n const trimmed = state.trim();\n if (trimmed.length === 0) {\n return \"\";\n }\n try {\n const parsed = JSON.parse(trimmed);\n return JSON.stringify(parsed, null, 2);\n } catch {\n return state;\n }\n }\n\n if (typeof state === \"object\") {\n try {\n return JSON.stringify(state, null, 2);\n } catch {\n return String(state);\n }\n }\n\n return String(state);\n }\n\n private getEventBadgeClasses(type: string): string {\n const base =\n \"font-mono text-[10px] font-medium inline-flex items-center rounded-sm px-1.5 py-0.5 border\";\n\n if (type.startsWith(\"RUN_\")) {\n return `${base} bg-blue-50 text-blue-700 border-blue-200`;\n }\n\n if (type.startsWith(\"TEXT_MESSAGE\")) {\n return `${base} bg-emerald-50 text-emerald-700 border-emerald-200`;\n }\n\n if (type.startsWith(\"TOOL_CALL\")) {\n return `${base} bg-amber-50 text-amber-700 border-amber-200`;\n }\n\n if (type.startsWith(\"REASONING\")) {\n return `${base} bg-fuchsia-50 text-fuchsia-700 border-fuchsia-200`;\n }\n\n if (type.startsWith(\"STATE\")) {\n return `${base} bg-violet-50 text-violet-700 border-violet-200`;\n }\n\n if (type.startsWith(\"MESSAGES\")) {\n return `${base} bg-sky-50 text-sky-700 border-sky-200`;\n }\n\n if (type === \"RUN_ERROR\") {\n return `${base} bg-rose-50 text-rose-700 border-rose-200`;\n }\n\n return `${base} bg-gray-100 text-gray-600 border-gray-200`;\n }\n\n private stringifyPayload(payload: unknown, pretty: boolean): string {\n try {\n if (payload === undefined) {\n return pretty ? \"undefined\" : \"undefined\";\n }\n if (typeof payload === \"string\") {\n return payload;\n }\n return JSON.stringify(payload, null, pretty ? 2 : 0) ?? \"\";\n } catch (error) {\n console.warn(\"Failed to stringify inspector payload\", error);\n return String(payload);\n }\n }\n\n private extractEventFromPayload(payload: unknown): unknown {\n // If payload is an object with an 'event' field, extract it\n if (payload && typeof payload === \"object\" && \"event\" in payload) {\n return (payload as Record<string, unknown>).event;\n }\n // Otherwise, assume the payload itself is the event\n return payload;\n }\n\n private async copyToClipboard(text: string, eventId: string): Promise<void> {\n try {\n await navigator.clipboard.writeText(text);\n this.copiedEvents.add(eventId);\n this.requestUpdate();\n\n // Clear the \"copied\" state after 2 seconds\n setTimeout(() => {\n this.copiedEvents.delete(eventId);\n this.requestUpdate();\n }, 2000);\n } catch (err) {\n console.error(\"Failed to copy to clipboard:\", err);\n }\n }\n\n static styles = [\n unsafeCSS(tailwindStyles),\n css`\n :host {\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2147483646;\n display: block;\n will-change: transform;\n }\n\n :host([data-transitioning=\"true\"]) {\n transition: transform 300ms ease;\n }\n\n .console-button {\n transition:\n transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),\n opacity 160ms ease;\n }\n\n .console-button[data-dragging=\"true\"] {\n transition: opacity 160ms ease;\n }\n\n .inspector-window[data-transitioning=\"true\"] {\n transition:\n width 300ms ease,\n height 300ms ease;\n }\n\n .inspector-window[data-docked=\"true\"] {\n border-radius: 0 !important;\n box-shadow: none !important;\n }\n\n .resize-handle {\n touch-action: none;\n user-select: none;\n }\n\n .dock-resize-handle {\n position: absolute;\n top: 0;\n right: 0;\n width: 10px;\n height: 100%;\n cursor: ew-resize;\n touch-action: none;\n z-index: 50;\n background: transparent;\n }\n\n .tooltip-target {\n position: relative;\n }\n\n .tooltip-target::after {\n content: attr(data-tooltip);\n position: absolute;\n top: calc(100% + 6px);\n left: 50%;\n transform: translateX(-50%) translateY(-4px);\n white-space: nowrap;\n background: rgba(17, 24, 39, 0.95);\n color: white;\n padding: 4px 8px;\n border-radius: 6px;\n font-size: 10px;\n line-height: 1.2;\n box-shadow: 0 4px 10px rgba(0, 0, 0, 0.15);\n opacity: 0;\n pointer-events: none;\n transition:\n opacity 120ms ease,\n transform 120ms ease;\n z-index: 4000;\n }\n\n .tooltip-target:hover::after {\n opacity: 1;\n transform: translateX(-50%) translateY(0);\n }\n\n .announcement-preview {\n position: absolute;\n top: 50%;\n transform: translateY(-50%);\n min-width: 300px;\n max-width: 300px;\n background: white;\n color: #111827;\n font-size: 13px;\n line-height: 1.4;\n border-radius: 12px;\n box-shadow: 0 12px 28px rgba(15, 23, 42, 0.22);\n padding: 10px 12px;\n display: inline-flex;\n align-items: flex-start;\n gap: 8px;\n z-index: 4500;\n animation: fade-slide-in 160ms ease;\n border: 1px solid rgba(148, 163, 184, 0.35);\n white-space: normal;\n word-break: break-word;\n text-align: left;\n }\n\n .announcement-preview[data-side=\"left\"] {\n right: 100%;\n margin-right: 10px;\n }\n\n .announcement-preview[data-side=\"right\"] {\n left: 100%;\n margin-left: 10px;\n }\n\n .announcement-preview__arrow {\n position: absolute;\n width: 10px;\n height: 10px;\n background: white;\n border: 1px solid rgba(148, 163, 184, 0.35);\n transform: rotate(45deg);\n top: 50%;\n margin-top: -5px;\n z-index: -1;\n }\n\n .announcement-preview[data-side=\"left\"] .announcement-preview__arrow {\n right: -5px;\n box-shadow: 6px -6px 10px rgba(15, 23, 42, 0.12);\n }\n\n .announcement-preview[data-side=\"right\"] .announcement-preview__arrow {\n left: -5px;\n box-shadow: -6px 6px 10px rgba(15, 23, 42, 0.12);\n }\n\n .announcement-dismiss {\n color: #6b7280;\n font-size: 12px;\n padding: 2px 8px;\n border-radius: 8px;\n border: 1px solid rgba(148, 163, 184, 0.5);\n background: rgba(248, 250, 252, 0.9);\n transition:\n background 120ms ease,\n color 120ms ease;\n }\n\n .announcement-dismiss:hover {\n background: rgba(241, 245, 249, 1);\n color: #111827;\n }\n\n .announcement-content {\n color: #111827;\n font-size: 14px;\n line-height: 1.6;\n }\n\n .announcement-content h1,\n .announcement-content h2,\n .announcement-content h3 {\n font-weight: 700;\n margin: 0.4rem 0 0.2rem;\n }\n\n .announcement-content h1 {\n font-size: 1.1rem;\n }\n\n .announcement-content h2 {\n font-size: 1rem;\n }\n\n .announcement-content h3 {\n font-size: 0.95rem;\n }\n\n .announcement-content p {\n margin: 0.25rem 0;\n }\n\n .announcement-content ul {\n list-style: disc;\n padding-left: 1.25rem;\n margin: 0.3rem 0;\n }\n\n .announcement-content ol {\n list-style: decimal;\n padding-left: 1.25rem;\n margin: 0.3rem 0;\n }\n\n .announcement-content a {\n color: #0f766e;\n text-decoration: underline;\n }\n `,\n ];\n\n connectedCallback(): void {\n super.connectedCallback();\n if (typeof window !== \"undefined\") {\n window.addEventListener(\"resize\", this.handleResize);\n window.addEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n\n // Load state early (before first render) so menu selection is correct\n this.hydrateStateFromStorageEarly();\n this.tryAutoAttachCore();\n this.ensureAnnouncementLoading();\n }\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n if (typeof window !== \"undefined\") {\n window.removeEventListener(\"resize\", this.handleResize);\n window.removeEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n }\n this.removeDockStyles(); // Clean up any docking styles\n this.detachFromCore();\n }\n\n firstUpdated(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (!this._core) {\n this.tryAutoAttachCore();\n }\n\n this.measureContext(\"button\");\n this.measureContext(\"window\");\n\n this.contextState.button.anchor = { horizontal: \"right\", vertical: \"top\" };\n this.contextState.button.anchorOffset = { x: EDGE_MARGIN, y: EDGE_MARGIN };\n\n this.contextState.window.anchor = { horizontal: \"right\", vertical: \"top\" };\n this.contextState.window.anchorOffset = { x: EDGE_MARGIN, y: EDGE_MARGIN };\n\n this.hydrateStateFromStorage();\n\n // Apply docking styles if open and docked (skip transition on initial load)\n if (this.isOpen && this.dockMode !== \"floating\") {\n this.applyDockStyles(true);\n }\n\n this.applyAnchorPosition(\"button\");\n\n if (this.dockMode === \"floating\") {\n if (this.hasCustomPosition.window) {\n this.applyAnchorPosition(\"window\");\n } else {\n this.centerContext(\"window\");\n }\n }\n\n this.ensureAnnouncementLoading();\n\n this.updateHostTransform(this.isOpen ? \"window\" : \"button\");\n }\n\n render() {\n return this.isOpen ? this.renderWindow() : this.renderButton();\n }\n\n private renderButton() {\n const buttonClasses = [\n \"console-button\",\n \"group\",\n \"relative\",\n \"pointer-events-auto\",\n \"inline-flex\",\n \"h-12\",\n \"w-12\",\n \"items-center\",\n \"justify-center\",\n \"rounded-full\",\n \"border\",\n \"border-white/20\",\n \"bg-slate-950/95\",\n \"text-xs\",\n \"font-medium\",\n \"text-white\",\n \"ring-1\",\n \"ring-white/10\",\n \"backdrop-blur-md\",\n \"transition\",\n \"hover:border-white/30\",\n \"hover:bg-slate-900/95\",\n \"hover:scale-105\",\n \"focus-visible:outline\",\n \"focus-visible:outline-2\",\n \"focus-visible:outline-offset-2\",\n \"focus-visible:outline-rose-500\",\n \"touch-none\",\n \"select-none\",\n this.isDragging ? \"cursor-grabbing\" : \"cursor-grab\",\n ].join(\" \");\n\n return html`\n <button\n class=${buttonClasses}\n type=\"button\"\n aria-label=\"Web Inspector\"\n data-drag-context=\"button\"\n data-dragging=${this.isDragging && this.pointerContext === \"button\"\n ? \"true\"\n : \"false\"}\n @pointerdown=${this.handlePointerDown}\n @pointermove=${this.handlePointerMove}\n @pointerup=${this.handlePointerUp}\n @pointercancel=${this.handlePointerCancel}\n @click=${this.handleButtonClick}\n >\n ${this.renderAnnouncementPreview()}\n <img\n src=${inspectorLogoIconUrl}\n alt=\"Inspector logo\"\n class=\"h-5 w-auto\"\n loading=\"lazy\"\n />\n </button>\n `;\n }\n\n private renderWindow() {\n const windowState = this.contextState.window;\n const isDocked = this.dockMode !== \"floating\";\n const isTransitioning = this.hasAttribute(\"data-transitioning\");\n\n const windowStyles = isDocked\n ? this.getDockedWindowStyles()\n : {\n width: `${Math.round(windowState.size.width)}px`,\n height: `${Math.round(windowState.size.height)}px`,\n minWidth: `${MIN_WINDOW_WIDTH}px`,\n minHeight: `${MIN_WINDOW_HEIGHT}px`,\n };\n\n const hasContextDropdown = this.contextOptions.length > 0;\n const contextDropdown = hasContextDropdown\n ? this.renderContextDropdown()\n : nothing;\n const coreStatus = this.getCoreStatusSummary();\n const agentSelector = hasContextDropdown\n ? contextDropdown\n : html`\n <div\n class=\"flex items-center gap-2 rounded-md border border-dashed border-gray-200 px-2 py-1 text-xs text-gray-400\"\n >\n <span>${this.renderIcon(\"Bot\")}</span>\n <span class=\"truncate\">No agents available</span>\n </div>\n `;\n\n return html`\n <section\n 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\"\n style=${styleMap(windowStyles)}\n data-docked=${isDocked}\n data-transitioning=${isTransitioning}\n >\n ${isDocked\n ? html`\n <div\n class=\"dock-resize-handle pointer-events-auto\"\n role=\"presentation\"\n aria-hidden=\"true\"\n @pointerdown=${this.handleResizePointerDown}\n @pointermove=${this.handleResizePointerMove}\n @pointerup=${this.handleResizePointerUp}\n @pointercancel=${this.handleResizePointerCancel}\n ></div>\n `\n : nothing}\n <div\n class=\"flex flex-1 flex-col overflow-hidden bg-white text-gray-800\"\n >\n <div\n class=\"drag-handle relative z-30 flex flex-col border-b border-gray-200 bg-white/95 backdrop-blur-sm ${isDocked\n ? \"\"\n : this.isDragging && this.pointerContext === \"window\"\n ? \"cursor-grabbing\"\n : \"cursor-grab\"}\"\n data-drag-context=\"window\"\n @pointerdown=${isDocked ? undefined : this.handlePointerDown}\n @pointermove=${isDocked ? undefined : this.handlePointerMove}\n @pointerup=${isDocked ? undefined : this.handlePointerUp}\n @pointercancel=${isDocked ? undefined : this.handlePointerCancel}\n >\n <div class=\"flex flex-wrap items-center gap-3 px-4 py-3\">\n <div class=\"flex items-center min-w-0\">\n <img\n src=${inspectorLogoUrl}\n alt=\"Inspector logo\"\n class=\"h-6 w-auto\"\n loading=\"lazy\"\n />\n </div>\n <div class=\"ml-auto flex min-w-0 items-center gap-2\">\n <div class=\"min-w-[160px] max-w-xs\">${agentSelector}</div>\n <div class=\"flex items-center gap-1\">\n ${this.renderDockControls()}\n <button\n 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\"\n type=\"button\"\n aria-label=\"Close Web Inspector\"\n @pointerdown=${this.handleClosePointerDown}\n @click=${this.handleCloseClick}\n >\n ${this.renderIcon(\"X\")}\n </button>\n </div>\n </div>\n </div>\n <div\n class=\"flex flex-wrap items-center gap-2 border-t border-gray-100 px-3 py-2 text-xs\"\n >\n ${this.menuItems.map(({ key, label, icon }) => {\n const isSelected = this.selectedMenu === key;\n const tabClasses = [\n \"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\",\n isSelected\n ? \"bg-gray-900 text-white shadow-sm\"\n : \"text-gray-600 hover:bg-gray-100 hover:text-gray-900\",\n ].join(\" \");\n\n return html`\n <button\n type=\"button\"\n class=${tabClasses}\n aria-pressed=${isSelected}\n @click=${() => this.handleMenuSelect(key)}\n >\n <span\n class=\"text-gray-400 ${isSelected ? \"text-white\" : \"\"}\"\n >\n ${this.renderIcon(icon)}\n </span>\n <span>${label}</span>\n </button>\n `;\n })}\n </div>\n </div>\n <div class=\"flex flex-1 flex-col overflow-hidden\">\n <div class=\"flex-1 overflow-auto\">\n ${this.renderAnnouncementPanel()}\n ${this.renderCoreWarningBanner()} ${this.renderMainContent()}\n <slot></slot>\n </div>\n <div class=\"border-t border-gray-200 bg-gray-50 px-4 py-2\">\n <div\n class=\"flex items-center gap-2 rounded-md px-3 py-2 text-xs ${coreStatus.tone} w-full overflow-hidden my-1\"\n title=${coreStatus.description}\n >\n <span\n class=\"flex h-6 w-6 items-center justify-center rounded bg-white/60\"\n >\n ${this.renderIcon(\"Activity\")}\n </span>\n <span class=\"font-medium\">${coreStatus.label}</span>\n <span class=\"truncate text-[11px] opacity-80\"\n >${coreStatus.description}</span\n >\n </div>\n </div>\n </div>\n </div>\n <div\n 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\"\n role=\"presentation\"\n aria-hidden=\"true\"\n @pointerdown=${this.handleResizePointerDown}\n @pointermove=${this.handleResizePointerMove}\n @pointerup=${this.handleResizePointerUp}\n @pointercancel=${this.handleResizePointerCancel}\n >\n <svg\n class=\"h-3 w-3\"\n viewBox=\"0 0 16 16\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-width=\"1.5\"\n >\n <path d=\"M5 15L15 5\" />\n <path d=\"M9 15L15 9\" />\n </svg>\n </div>\n </section>\n `;\n }\n\n private hydrateStateFromStorageEarly(): void {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return;\n }\n\n const persisted = loadInspectorState(INSPECTOR_STORAGE_KEY);\n if (!persisted) {\n return;\n }\n\n // Restore the open/closed state\n if (typeof persisted.isOpen === \"boolean\") {\n this.isOpen = persisted.isOpen;\n }\n\n // Restore the dock mode\n if (isValidDockMode(persisted.dockMode)) {\n this.dockMode = persisted.dockMode;\n }\n\n // Restore selected menu\n if (typeof persisted.selectedMenu === \"string\") {\n const validMenu = this.menuItems.find(\n (item) => item.key === persisted.selectedMenu,\n );\n if (validMenu) {\n this.selectedMenu = validMenu.key;\n }\n }\n\n // Restore selected context (agent), will be validated later against available agents\n if (typeof persisted.selectedContext === \"string\") {\n this.selectedContext = persisted.selectedContext;\n this.pendingSelectedContext = persisted.selectedContext;\n }\n }\n\n private hydrateStateFromStorage(): void {\n if (typeof document === \"undefined\" || typeof window === \"undefined\") {\n return;\n }\n\n const persisted = loadInspectorState(INSPECTOR_STORAGE_KEY);\n if (!persisted) {\n return;\n }\n\n const persistedButton = persisted.button;\n if (persistedButton) {\n if (isValidAnchor(persistedButton.anchor)) {\n this.contextState.button.anchor = persistedButton.anchor;\n }\n\n if (isValidPosition(persistedButton.anchorOffset)) {\n this.contextState.button.anchorOffset = persistedButton.anchorOffset;\n }\n\n if (typeof persistedButton.hasCustomPosition === \"boolean\") {\n this.hasCustomPosition.button = persistedButton.hasCustomPosition;\n }\n }\n\n const persistedWindow = persisted.window;\n if (persistedWindow) {\n if (isValidAnchor(persistedWindow.anchor)) {\n this.contextState.window.anchor = persistedWindow.anchor;\n }\n\n if (isValidPosition(persistedWindow.anchorOffset)) {\n this.contextState.window.anchorOffset = persistedWindow.anchorOffset;\n }\n\n if (isValidSize(persistedWindow.size)) {\n // Now clampWindowSize will use the correct minimum based on dockMode\n this.contextState.window.size = this.clampWindowSize(\n persistedWindow.size,\n );\n }\n\n if (typeof persistedWindow.hasCustomPosition === \"boolean\") {\n this.hasCustomPosition.window = persistedWindow.hasCustomPosition;\n }\n }\n\n if (typeof persisted.selectedContext === \"string\") {\n this.selectedContext = persisted.selectedContext;\n this.pendingSelectedContext = persisted.selectedContext;\n }\n }\n\n private get activeContext(): ContextKey {\n return this.isOpen ? \"window\" : \"button\";\n }\n\n private handlePointerDown = (event: PointerEvent) => {\n // Don't allow dragging when docked\n if (this.dockMode !== \"floating\" && this.isOpen) {\n return;\n }\n\n const target = event.currentTarget as HTMLElement | null;\n const contextAttr = target?.dataset.dragContext;\n const context: ContextKey = contextAttr === \"window\" ? \"window\" : \"button\";\n\n const eventTarget = event.target as HTMLElement | null;\n if (context === \"window\" && eventTarget?.closest(\"button\")) {\n return;\n }\n\n this.pointerContext = context;\n this.measureContext(context);\n\n event.preventDefault();\n\n this.pointerId = event.pointerId;\n this.dragStart = { x: event.clientX, y: event.clientY };\n const state = this.contextState[context];\n this.dragOffset = {\n x: event.clientX - state.position.x,\n y: event.clientY - state.position.y,\n };\n this.isDragging = false;\n this.draggedDuringInteraction = false;\n this.ignoreNextButtonClick = false;\n\n target?.setPointerCapture?.(this.pointerId);\n };\n\n private handlePointerMove = (event: PointerEvent) => {\n if (\n this.pointerId !== event.pointerId ||\n !this.dragStart ||\n !this.pointerContext\n ) {\n return;\n }\n\n const distance = Math.hypot(\n event.clientX - this.dragStart.x,\n event.clientY - this.dragStart.y,\n );\n if (!this.isDragging && distance < DRAG_THRESHOLD) {\n return;\n }\n\n event.preventDefault();\n this.setDragging(true);\n this.draggedDuringInteraction = true;\n\n const desired: Position = {\n x: event.clientX - this.dragOffset.x,\n y: event.clientY - this.dragOffset.y,\n };\n\n const constrained = this.constrainToViewport(desired, this.pointerContext);\n this.contextState[this.pointerContext].position = constrained;\n this.updateHostTransform(this.pointerContext);\n };\n\n private handlePointerUp = (event: PointerEvent) => {\n if (this.pointerId !== event.pointerId) {\n return;\n }\n\n const target = event.currentTarget as HTMLElement | null;\n if (target?.hasPointerCapture(this.pointerId)) {\n target.releasePointerCapture(this.pointerId);\n }\n\n const context = this.pointerContext ?? this.activeContext;\n\n if (this.isDragging && this.pointerContext) {\n event.preventDefault();\n this.setDragging(false);\n if (this.pointerContext === \"window\") {\n this.updateAnchorFromPosition(this.pointerContext);\n this.hasCustomPosition.window = true;\n this.applyAnchorPosition(this.pointerContext);\n } else if (this.pointerContext === \"button\") {\n // Snap button to nearest corner\n this.snapButtonToCorner();\n this.hasCustomPosition.button = true;\n if (this.draggedDuringInteraction) {\n this.ignoreNextButtonClick = true;\n }\n }\n } else if (\n context === \"button\" &&\n !this.isOpen &&\n !this.draggedDuringInteraction\n ) {\n this.openInspector();\n }\n\n this.resetPointerTracking();\n };\n\n private handlePointerCancel = (event: PointerEvent) => {\n if (this.pointerId !== event.pointerId) {\n return;\n }\n\n const target = event.currentTarget as HTMLElement | null;\n if (target?.hasPointerCapture(this.pointerId)) {\n target.releasePointerCapture(this.pointerId);\n }\n\n this.resetPointerTracking();\n };\n\n private handleButtonClick = (event: Event) => {\n if (this.isDragging) {\n event.preventDefault();\n return;\n }\n\n if (this.ignoreNextButtonClick) {\n event.preventDefault();\n this.ignoreNextButtonClick = false;\n return;\n }\n\n if (!this.isOpen) {\n event.preventDefault();\n this.openInspector();\n }\n };\n\n private handleClosePointerDown = (event: PointerEvent) => {\n event.stopPropagation();\n event.preventDefault();\n };\n\n private handleCloseClick = () => {\n this.closeInspector();\n };\n\n private handleResizePointerDown = (event: PointerEvent) => {\n event.stopPropagation();\n event.preventDefault();\n\n this.hasCustomPosition.window = true;\n this.isResizing = true;\n this.resizePointerId = event.pointerId;\n this.resizeStart = { x: event.clientX, y: event.clientY };\n this.resizeInitialSize = { ...this.contextState.window.size };\n\n // Remove transition from body during resize to prevent lag\n if (document.body && this.dockMode !== \"floating\") {\n document.body.style.transition = \"\";\n }\n\n const target = event.currentTarget as HTMLElement | null;\n target?.setPointerCapture?.(event.pointerId);\n };\n\n private handleResizePointerMove = (event: PointerEvent) => {\n if (\n !this.isResizing ||\n this.resizePointerId !== event.pointerId ||\n !this.resizeStart ||\n !this.resizeInitialSize\n ) {\n return;\n }\n\n event.preventDefault();\n\n const deltaX = event.clientX - this.resizeStart.x;\n const deltaY = event.clientY - this.resizeStart.y;\n const state = this.contextState.window;\n\n // For docked states, only resize in the appropriate dimension\n if (this.dockMode === \"docked-left\") {\n // Only resize width for left dock\n state.size = this.clampWindowSize({\n width: this.resizeInitialSize.width + deltaX,\n height: state.size.height,\n });\n // Update the body margin\n if (document.body) {\n document.body.style.marginLeft = `${state.size.width}px`;\n }\n } else {\n // Full resize for floating mode\n state.size = this.clampWindowSize({\n width: this.resizeInitialSize.width + deltaX,\n height: this.resizeInitialSize.height + deltaY,\n });\n this.keepPositionWithinViewport(\"window\");\n this.updateAnchorFromPosition(\"window\");\n }\n\n this.requestUpdate();\n this.updateHostTransform(\"window\");\n };\n\n private handleResizePointerUp = (event: PointerEvent) => {\n if (this.resizePointerId !== event.pointerId) {\n return;\n }\n\n const target = event.currentTarget as HTMLElement | null;\n if (target?.hasPointerCapture(this.resizePointerId)) {\n target.releasePointerCapture(this.resizePointerId);\n }\n\n // Only update anchor position for floating mode\n if (this.dockMode === \"floating\") {\n this.updateAnchorFromPosition(\"window\");\n this.applyAnchorPosition(\"window\");\n }\n\n // Persist the new size after resize completes\n this.persistState();\n this.resetResizeTracking();\n };\n\n private handleResizePointerCancel = (event: PointerEvent) => {\n if (this.resizePointerId !== event.pointerId) {\n return;\n }\n\n const target = event.currentTarget as HTMLElement | null;\n if (target?.hasPointerCapture(this.resizePointerId)) {\n target.releasePointerCapture(this.resizePointerId);\n }\n\n // Only update anchor position for floating mode\n if (this.dockMode === \"floating\") {\n this.updateAnchorFromPosition(\"window\");\n this.applyAnchorPosition(\"window\");\n }\n\n // Persist the new size after resize completes\n this.persistState();\n this.resetResizeTracking();\n };\n\n private handleResize = () => {\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n\n this.measureContext(\"window\");\n if (this.hasCustomPosition.window) {\n this.applyAnchorPosition(\"window\");\n } else {\n this.centerContext(\"window\");\n }\n\n this.updateHostTransform();\n };\n\n private measureContext(context: ContextKey): void {\n const selector =\n context === \"window\" ? \".inspector-window\" : \".console-button\";\n const element = this.renderRoot?.querySelector(\n selector,\n ) as HTMLElement | null;\n if (!element) {\n return;\n }\n const fallback =\n context === \"window\" ? DEFAULT_WINDOW_SIZE : DEFAULT_BUTTON_SIZE;\n updateSizeFromElement(this.contextState[context], element, fallback);\n }\n\n private centerContext(context: ContextKey): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const viewport = this.getViewportSize();\n centerContextHelper(this.contextState[context], viewport, EDGE_MARGIN);\n\n if (context === this.activeContext) {\n this.updateHostTransform(context);\n }\n\n this.hasCustomPosition[context] = false;\n this.persistState();\n }\n\n private ensureWindowPlacement(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n if (!this.hasCustomPosition.window) {\n this.centerContext(\"window\");\n return;\n }\n\n const viewport = this.getViewportSize();\n keepPositionWithinViewport(this.contextState.window, viewport, EDGE_MARGIN);\n updateAnchorFromPositionHelper(\n this.contextState.window,\n viewport,\n EDGE_MARGIN,\n );\n this.updateHostTransform(\"window\");\n this.persistState();\n }\n\n private constrainToViewport(\n position: Position,\n context: ContextKey,\n ): Position {\n if (typeof window === \"undefined\") {\n return position;\n }\n\n const viewport = this.getViewportSize();\n return constrainToViewport(\n this.contextState[context],\n position,\n viewport,\n EDGE_MARGIN,\n );\n }\n\n private keepPositionWithinViewport(context: ContextKey): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const viewport = this.getViewportSize();\n keepPositionWithinViewport(\n this.contextState[context],\n viewport,\n EDGE_MARGIN,\n );\n }\n\n private getViewportSize(): Size {\n if (typeof window === \"undefined\") {\n return { ...DEFAULT_WINDOW_SIZE };\n }\n\n return { width: window.innerWidth, height: window.innerHeight };\n }\n\n private persistState(): void {\n const state: PersistedState = {\n button: {\n anchor: this.contextState.button.anchor,\n anchorOffset: this.contextState.button.anchorOffset,\n hasCustomPosition: this.hasCustomPosition.button,\n },\n window: {\n anchor: this.contextState.window.anchor,\n anchorOffset: this.contextState.window.anchorOffset,\n size: {\n width: Math.round(this.contextState.window.size.width),\n height: Math.round(this.contextState.window.size.height),\n },\n hasCustomPosition: this.hasCustomPosition.window,\n },\n isOpen: this.isOpen,\n dockMode: this.dockMode,\n selectedMenu: this.selectedMenu,\n selectedContext: this.selectedContext,\n };\n saveInspectorState(INSPECTOR_STORAGE_KEY, state);\n this.pendingSelectedContext = state.selectedContext ?? null;\n }\n\n private clampWindowSize(size: Size): Size {\n // Use smaller minimum width when docked left\n const minWidth =\n this.dockMode === \"docked-left\"\n ? MIN_WINDOW_WIDTH_DOCKED_LEFT\n : MIN_WINDOW_WIDTH;\n\n if (typeof window === \"undefined\") {\n return {\n width: Math.max(minWidth, size.width),\n height: Math.max(MIN_WINDOW_HEIGHT, size.height),\n };\n }\n\n const viewport = this.getViewportSize();\n return clampSizeToViewport(\n size,\n viewport,\n EDGE_MARGIN,\n minWidth,\n MIN_WINDOW_HEIGHT,\n );\n }\n\n private setDockMode(mode: DockMode): void {\n if (this.dockMode === mode) {\n return;\n }\n\n // Add transition class for smooth dock mode changes\n this.startHostTransition();\n\n // Clean up previous dock state\n this.removeDockStyles();\n\n this.dockMode = mode;\n\n if (mode !== \"floating\") {\n // For docking, set the target size immediately so body margins are correct\n if (mode === \"docked-left\") {\n this.contextState.window.size.width = DOCKED_LEFT_WIDTH;\n }\n\n // Then apply dock styles with correct sizes\n this.applyDockStyles();\n } else {\n // When floating, set size first then center\n this.contextState.window.size = { ...DEFAULT_WINDOW_SIZE };\n this.centerContext(\"window\");\n }\n\n this.persistState();\n this.requestUpdate();\n this.updateHostTransform(\"window\");\n }\n\n private startHostTransition(duration = 300): void {\n this.setAttribute(\"data-transitioning\", \"true\");\n\n if (this.transitionTimeoutId !== null) {\n clearTimeout(this.transitionTimeoutId);\n }\n\n this.transitionTimeoutId = setTimeout(() => {\n this.removeAttribute(\"data-transitioning\");\n this.transitionTimeoutId = null;\n }, duration);\n }\n\n private applyDockStyles(skipTransition = false): void {\n if (typeof document === \"undefined\" || !document.body) {\n return;\n }\n\n // Save original body margins\n const computedStyle = window.getComputedStyle(document.body);\n this.previousBodyMargins = {\n left: computedStyle.marginLeft,\n bottom: computedStyle.marginBottom,\n };\n\n // Apply transition to body for smooth animation (only when docking, not during resize or initial load)\n if (!this.isResizing && !skipTransition) {\n document.body.style.transition = \"margin 300ms ease\";\n }\n\n // Apply body margins with the actual window sizes\n if (this.dockMode === \"docked-left\") {\n document.body.style.marginLeft = `${this.contextState.window.size.width}px`;\n }\n\n // Remove transition after animation completes\n if (!this.isResizing && !skipTransition) {\n setTimeout(() => {\n if (document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n }\n }\n\n private removeDockStyles(): void {\n if (typeof document === \"undefined\" || !document.body) {\n return;\n }\n\n // Only add transition if not resizing\n if (!this.isResizing) {\n document.body.style.transition = \"margin 300ms ease\";\n }\n\n // Restore original margins if saved\n if (this.previousBodyMargins) {\n document.body.style.marginLeft = this.previousBodyMargins.left;\n document.body.style.marginBottom = this.previousBodyMargins.bottom;\n this.previousBodyMargins = null;\n } else {\n // Reset to default if no previous values\n document.body.style.marginLeft = \"\";\n document.body.style.marginBottom = \"\";\n }\n\n // Clean up transition after animation completes\n setTimeout(() => {\n if (document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n }\n\n private updateHostTransform(context: ContextKey = this.activeContext): void {\n if (context !== this.activeContext) {\n return;\n }\n\n // For docked states, CSS handles positioning with fixed positioning\n if (this.isOpen && this.dockMode === \"docked-left\") {\n this.style.transform = `translate3d(0, 0, 0)`;\n } else {\n const { position } = this.contextState[context];\n this.style.transform = `translate3d(${position.x}px, ${position.y}px, 0)`;\n }\n }\n\n private setDragging(value: boolean): void {\n if (this.isDragging !== value) {\n this.isDragging = value;\n this.requestUpdate();\n }\n }\n\n private updateAnchorFromPosition(context: ContextKey): void {\n if (typeof window === \"undefined\") {\n return;\n }\n const viewport = this.getViewportSize();\n updateAnchorFromPositionHelper(\n this.contextState[context],\n viewport,\n EDGE_MARGIN,\n );\n }\n\n private snapButtonToCorner(): void {\n if (typeof window === \"undefined\") {\n return;\n }\n\n const viewport = this.getViewportSize();\n const state = this.contextState.button;\n\n // Determine which corner is closest based on center of button\n const centerX = state.position.x + state.size.width / 2;\n const centerY = state.position.y + state.size.height / 2;\n\n const horizontal: Anchor[\"horizontal\"] =\n centerX < viewport.width / 2 ? \"left\" : \"right\";\n const vertical: Anchor[\"vertical\"] =\n centerY < viewport.height / 2 ? \"top\" : \"bottom\";\n\n // Set anchor to nearest corner\n state.anchor = { horizontal, vertical };\n\n // Always use EDGE_MARGIN as offset (pinned to corner)\n state.anchorOffset = { x: EDGE_MARGIN, y: EDGE_MARGIN };\n\n // Apply the anchor position to snap to corner\n this.startHostTransition();\n this.applyAnchorPosition(\"button\");\n }\n\n private applyAnchorPosition(context: ContextKey): void {\n if (typeof window === \"undefined\") {\n return;\n }\n const viewport = this.getViewportSize();\n applyAnchorPositionHelper(\n this.contextState[context],\n viewport,\n EDGE_MARGIN,\n );\n this.updateHostTransform(context);\n this.persistState();\n }\n\n private resetResizeTracking(): void {\n this.resizePointerId = null;\n this.resizeStart = null;\n this.resizeInitialSize = null;\n this.isResizing = false;\n }\n\n private resetPointerTracking(): void {\n this.pointerId = null;\n this.dragStart = null;\n this.pointerContext = null;\n this.setDragging(false);\n this.draggedDuringInteraction = false;\n }\n\n private openInspector(): void {\n if (this.isOpen) {\n return;\n }\n\n this.showAnnouncementPreview = false; // hide the bubble once the inspector is opened\n\n this.ensureAnnouncementLoading();\n\n this.isOpen = true;\n this.persistState(); // Save the open state\n\n // Apply docking styles if in docked mode\n if (this.dockMode !== \"floating\") {\n this.applyDockStyles();\n }\n\n this.ensureWindowPlacement();\n this.requestUpdate();\n void this.updateComplete.then(() => {\n this.measureContext(\"window\");\n if (this.dockMode === \"floating\") {\n if (this.hasCustomPosition.window) {\n this.applyAnchorPosition(\"window\");\n } else {\n this.centerContext(\"window\");\n }\n } else {\n // Update transform for docked position\n this.updateHostTransform(\"window\");\n }\n });\n }\n\n private closeInspector(): void {\n if (!this.isOpen) {\n return;\n }\n\n this.isOpen = false;\n\n // Remove docking styles when closing\n if (this.dockMode !== \"floating\") {\n this.removeDockStyles();\n }\n\n this.persistState(); // Save the closed state\n this.updateHostTransform(\"button\");\n this.requestUpdate();\n void this.updateComplete.then(() => {\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n });\n }\n\n private renderIcon(name: LucideIconName) {\n const iconNode = icons[name];\n if (!iconNode) {\n return nothing;\n }\n\n const svgAttrs: Record<string, string | number> = {\n xmlns: \"http://www.w3.org/2000/svg\",\n viewBox: \"0 0 24 24\",\n fill: \"none\",\n stroke: \"currentColor\",\n \"stroke-width\": \"1.5\",\n \"stroke-linecap\": \"round\",\n \"stroke-linejoin\": \"round\",\n class: \"h-3.5 w-3.5\",\n };\n\n const svgMarkup = `<svg ${this.serializeAttributes(svgAttrs)}>${iconNode\n .map(([tag, attrs]) => `<${tag} ${this.serializeAttributes(attrs)} />`)\n .join(\"\")}</svg>`;\n\n return unsafeHTML(svgMarkup);\n }\n\n private renderDockControls() {\n if (this.dockMode === \"floating\") {\n // Show dock left button\n return html`\n <button\n 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\"\n type=\"button\"\n aria-label=\"Dock to left\"\n title=\"Dock Left\"\n @click=${() => this.handleDockClick(\"docked-left\")}\n >\n ${this.renderIcon(\"PanelLeft\")}\n </button>\n `;\n } else {\n // Show float button\n return html`\n <button\n 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\"\n type=\"button\"\n aria-label=\"Float window\"\n title=\"Float\"\n @click=${() => this.handleDockClick(\"floating\")}\n >\n ${this.renderIcon(\"Maximize2\")}\n </button>\n `;\n }\n }\n\n private getDockedWindowStyles(): Record<string, string> {\n if (this.dockMode === \"docked-left\") {\n return {\n position: \"fixed\",\n top: \"0\",\n left: \"0\",\n bottom: \"0\",\n width: `${Math.round(this.contextState.window.size.width)}px`,\n height: \"100vh\",\n minWidth: `${MIN_WINDOW_WIDTH_DOCKED_LEFT}px`,\n borderRadius: \"0\",\n };\n }\n // Default to floating styles\n return {\n width: `${Math.round(this.contextState.window.size.width)}px`,\n height: `${Math.round(this.contextState.window.size.height)}px`,\n minWidth: `${MIN_WINDOW_WIDTH}px`,\n minHeight: `${MIN_WINDOW_HEIGHT}px`,\n };\n }\n\n private handleDockClick(mode: DockMode): void {\n this.setDockMode(mode);\n }\n\n private serializeAttributes(\n attributes: Record<string, string | number | undefined>,\n ): string {\n return Object.entries(attributes)\n .filter(\n ([key, value]) =>\n key !== \"key\" &&\n value !== undefined &&\n value !== null &&\n value !== \"\",\n )\n .map(\n ([key, value]) => `${key}=\"${String(value).replace(/\"/g, \""\")}\"`,\n )\n .join(\" \");\n }\n\n private sanitizeForLogging(\n value: unknown,\n depth = 0,\n seen = new WeakSet<object>(),\n ): SanitizedValue {\n if (value === undefined) {\n return \"[undefined]\";\n }\n\n if (\n value === null ||\n typeof value === \"number\" ||\n typeof value === \"boolean\"\n ) {\n return value;\n }\n\n if (typeof value === \"string\") {\n return value;\n }\n\n if (\n typeof value === \"bigint\" ||\n typeof value === \"symbol\" ||\n typeof value === \"function\"\n ) {\n return String(value);\n }\n\n if (value instanceof Date) {\n return value.toISOString();\n }\n\n if (Array.isArray(value)) {\n if (depth >= 4) {\n return \"[Truncated depth]\" as SanitizedValue;\n }\n return value.map((item) =>\n this.sanitizeForLogging(item, depth + 1, seen),\n );\n }\n\n if (typeof value === \"object\") {\n if (seen.has(value as object)) {\n return \"[Circular]\" as SanitizedValue;\n }\n seen.add(value as object);\n\n if (depth >= 4) {\n return \"[Truncated depth]\" as SanitizedValue;\n }\n\n const result: Record<string, SanitizedValue> = {};\n for (const [key, entry] of Object.entries(\n value as Record<string, unknown>,\n )) {\n result[key] = this.sanitizeForLogging(entry, depth + 1, seen);\n }\n return result;\n }\n\n return String(value);\n }\n\n private normalizeEventPayload(\n _type: InspectorAgentEventType,\n payload: unknown,\n ): SanitizedValue {\n if (payload && typeof payload === \"object\" && \"event\" in payload) {\n const { event, ...rest } = payload as Record<string, unknown>;\n const cleaned =\n Object.keys(rest).length === 0 ? event : { event, ...rest };\n return this.sanitizeForLogging(cleaned);\n }\n\n return this.sanitizeForLogging(payload);\n }\n\n private normalizeMessageContent(content: unknown): string {\n if (typeof content === \"string\") {\n return content;\n }\n\n if (\n content &&\n typeof content === \"object\" &&\n \"text\" in (content as Record<string, unknown>)\n ) {\n const maybeText = (content as Record<string, unknown>).text;\n if (typeof maybeText === \"string\") {\n return maybeText;\n }\n }\n\n if (content === null || content === undefined) {\n return \"\";\n }\n\n if (typeof content === \"object\") {\n try {\n return JSON.stringify(this.sanitizeForLogging(content));\n } catch {\n return \"\";\n }\n }\n\n return String(content);\n }\n\n private normalizeToolCalls(raw: unknown): InspectorToolCall[] {\n if (!Array.isArray(raw)) {\n return [];\n }\n\n return raw\n .map((entry) => {\n if (!entry || typeof entry !== \"object\") {\n return null;\n }\n const call = entry as Record<string, unknown>;\n const fn = call.function as Record<string, unknown> | undefined;\n const functionName =\n typeof fn?.name === \"string\"\n ? fn.name\n : typeof call.toolName === \"string\"\n ? call.toolName\n : undefined;\n const args =\n fn && \"arguments\" in fn\n ? (fn as Record<string, unknown>).arguments\n : call.arguments;\n\n const normalized: InspectorToolCall = {\n id: typeof call.id === \"string\" ? call.id : undefined,\n toolName:\n typeof call.toolName === \"string\" ? call.toolName : functionName,\n status: typeof call.status === \"string\" ? call.status : undefined,\n };\n\n if (functionName) {\n normalized.function = {\n name: functionName,\n arguments: this.sanitizeForLogging(args),\n };\n }\n\n return normalized;\n })\n .filter((call): call is InspectorToolCall => Boolean(call));\n }\n\n private normalizeAgentMessage(message: unknown): InspectorMessage | null {\n if (!message || typeof message !== \"object\") {\n return null;\n }\n\n const raw = message as Record<string, unknown>;\n const role = typeof raw.role === \"string\" ? raw.role : \"unknown\";\n const contentText = this.normalizeMessageContent(raw.content);\n const toolCalls = this.normalizeToolCalls(raw.toolCalls);\n\n return {\n id: typeof raw.id === \"string\" ? raw.id : undefined,\n role,\n contentText,\n contentRaw:\n raw.content !== undefined\n ? this.sanitizeForLogging(raw.content)\n : undefined,\n toolCalls,\n };\n }\n\n private normalizeAgentMessages(messages: unknown): InspectorMessage[] | null {\n if (!Array.isArray(messages)) {\n return null;\n }\n\n const normalized = messages\n .map((message) => this.normalizeAgentMessage(message))\n .filter((msg): msg is InspectorMessage => msg !== null);\n\n return normalized;\n }\n\n private normalizeContextStore(\n context: Readonly<Record<string, unknown>> | null | undefined,\n ): Record<string, { description?: string; value: unknown }> {\n if (!context || typeof context !== \"object\") {\n return {};\n }\n\n const normalized: Record<string, { description?: string; value: unknown }> =\n {};\n for (const [key, entry] of Object.entries(context)) {\n if (\n entry &&\n typeof entry === \"object\" &&\n \"value\" in (entry as Record<string, unknown>)\n ) {\n const candidate = entry as Record<string, unknown>;\n const description =\n typeof candidate.description === \"string\" &&\n candidate.description.trim().length > 0\n ? candidate.description\n : undefined;\n normalized[key] = { description, value: candidate.value };\n } else {\n normalized[key] = { value: entry };\n }\n }\n\n return normalized;\n }\n\n private contextOptions: Array<{ key: string; label: string }> = [\n { key: \"all-agents\", label: \"All Agents\" },\n ];\n\n private selectedContext = \"all-agents\";\n private expandedRows: Set<string> = new Set();\n private copiedEvents: Set<string> = new Set();\n private expandedTools: Set<string> = new Set();\n private expandedContextItems: Set<string> = new Set();\n private copiedContextItems: Set<string> = new Set();\n\n private getSelectedMenu(): MenuItem {\n const found = this.menuItems.find((item) => item.key === this.selectedMenu);\n return found ?? this.menuItems[0]!;\n }\n\n private renderCoreWarningBanner() {\n if (this._core) {\n return nothing;\n }\n\n return html`\n <div\n 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\"\n >\n <span class=\"mt-0.5 shrink-0 text-amber-600\"\n >${this.renderIcon(\"AlertTriangle\")}</span\n >\n <div class=\"space-y-1\">\n <div class=\"font-semibold text-amber-900\">\n CopilotKit core not attached\n </div>\n <p class=\"text-[11px] leading-snug text-amber-800\">\n Pass a live <code>CopilotKitCore</code> instance to\n <code><cpk-web-inspector></code> or expose it on\n <code>window.__COPILOTKIT_CORE__</code> for auto-attach.\n </p>\n </div>\n </div>\n `;\n }\n\n private getCoreStatusSummary(): {\n label: string;\n tone: string;\n description: string;\n } {\n if (!this._core) {\n return {\n label: \"Core not attached\",\n tone: \"border border-amber-200 bg-amber-50 text-amber-800\",\n description:\n \"Pass a CopilotKitCore instance to <cpk-web-inspector> or enable auto-attach.\",\n };\n }\n\n const status =\n this.runtimeStatus ?? CopilotKitCoreRuntimeConnectionStatus.Disconnected;\n const lastErrorMessage = this.lastCoreError?.message;\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Error) {\n return {\n label: \"Runtime error\",\n tone: \"border border-rose-200 bg-rose-50 text-rose-700\",\n description:\n lastErrorMessage ?? \"CopilotKit runtime reported an error.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connecting) {\n return {\n label: \"Connecting\",\n tone: \"border border-amber-200 bg-amber-50 text-amber-800\",\n description: \"Waiting for CopilotKit runtime to finish connecting.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connected) {\n return {\n label: \"Connected\",\n tone: \"border border-emerald-200 bg-emerald-50 text-emerald-700\",\n description: \"Live runtime connection established.\",\n };\n }\n\n return {\n label: \"Disconnected\",\n tone: \"border border-gray-200 bg-gray-50 text-gray-700\",\n description:\n lastErrorMessage ?? \"Waiting for CopilotKit runtime to connect.\",\n };\n }\n\n private renderMainContent() {\n if (this.selectedMenu === \"ag-ui-events\") {\n return this.renderEventsTable();\n }\n\n if (this.selectedMenu === \"agents\") {\n return this.renderAgentsView();\n }\n\n if (this.selectedMenu === \"frontend-tools\") {\n return this.renderToolsView();\n }\n\n if (this.selectedMenu === \"agent-context\") {\n return this.renderContextView();\n }\n\n return nothing;\n }\n\n private renderEventsTable() {\n const events = this.getEventsForSelectedContext();\n const filteredEvents = this.filterEvents(events);\n const selectedLabel =\n this.selectedContext === \"all-agents\"\n ? \"all agents\"\n : `agent ${this.selectedContext}`;\n\n if (events.length === 0) {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-center\"\n >\n <div class=\"max-w-md\">\n <div\n class=\"mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\"\n >\n ${this.renderIcon(\"Zap\")}\n </div>\n <p class=\"text-sm text-gray-600\">No events yet</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Trigger an agent run to see live activity.\n </p>\n </div>\n </div>\n `;\n }\n\n if (filteredEvents.length === 0) {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-center\"\n >\n <div class=\"max-w-md space-y-3\">\n <div\n class=\"flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\"\n >\n ${this.renderIcon(\"Filter\")}\n </div>\n <p class=\"text-sm text-gray-600\">\n No events match the current filters.\n </p>\n <div>\n <button\n type=\"button\"\n 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\"\n @click=${this.resetEventFilters}\n >\n ${this.renderIcon(\"RefreshCw\")}\n <span>Reset filters</span>\n </button>\n </div>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"flex h-full flex-col\">\n <div\n class=\"flex flex-col gap-1.5 border-b border-gray-200 bg-white px-4 py-2.5\"\n >\n <div class=\"flex flex-wrap items-center gap-2\">\n <div class=\"relative min-w-[200px] flex-1\">\n <input\n type=\"search\"\n 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\"\n placeholder=\"Search agent, type, payload\"\n .value=${this.eventFilterText}\n @input=${this.handleEventFilterInput}\n />\n </div>\n <select\n 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\"\n .value=${this.eventTypeFilter}\n @change=${this.handleEventTypeChange}\n >\n <option value=\"all\">All event types</option>\n ${AGENT_EVENT_TYPES.map(\n (type) =>\n html`<option value=${type}>\n ${type.toLowerCase().replace(/_/g, \" \")}\n </option>`,\n )}\n </select>\n <div class=\"flex items-center gap-1 text-[11px]\">\n <button\n type=\"button\"\n 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\"\n title=\"Reset filters\"\n data-tooltip=\"Reset filters\"\n aria-label=\"Reset filters\"\n @click=${this.resetEventFilters}\n ?disabled=${!this.eventFilterText &&\n this.eventTypeFilter === \"all\"}\n >\n ${this.renderIcon(\"RotateCw\")}\n </button>\n <button\n type=\"button\"\n 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\"\n title=\"Export JSON\"\n data-tooltip=\"Export JSON\"\n aria-label=\"Export JSON\"\n @click=${() => this.exportEvents(filteredEvents)}\n ?disabled=${filteredEvents.length === 0}\n >\n ${this.renderIcon(\"Download\")}\n </button>\n <button\n type=\"button\"\n 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\"\n title=\"Clear events\"\n data-tooltip=\"Clear events\"\n aria-label=\"Clear events\"\n @click=${this.handleClearEvents}\n ?disabled=${events.length === 0}\n >\n ${this.renderIcon(\"Trash2\")}\n </button>\n </div>\n </div>\n <div class=\"text-[11px] text-gray-500\">\n Showing ${filteredEvents.length} of\n ${events.length}${this.selectedContext === \"all-agents\"\n ? \"\"\n : ` for ${selectedLabel}`}\n </div>\n </div>\n <div class=\"relative h-full w-full overflow-y-auto overflow-x-hidden\">\n <table class=\"w-full table-fixed border-collapse text-xs box-border\">\n <thead class=\"sticky top-0 z-10\">\n <tr class=\"bg-white\">\n <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n >\n Agent\n </th>\n <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n >\n Time\n </th>\n <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n >\n Event Type\n </th>\n <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n >\n AG-UI Event\n </th>\n </tr>\n </thead>\n <tbody>\n ${filteredEvents.map((event, index) => {\n const rowBg = index % 2 === 0 ? \"bg-white\" : \"bg-gray-50/50\";\n const badgeClasses = this.getEventBadgeClasses(event.type);\n const extractedEvent = this.extractEventFromPayload(\n event.payload,\n );\n const inlineEvent =\n this.stringifyPayload(extractedEvent, false) || \"—\";\n const prettyEvent =\n this.stringifyPayload(extractedEvent, true) || inlineEvent;\n const isExpanded = this.expandedRows.has(event.id);\n\n return html`\n <tr\n class=\"${rowBg} cursor-pointer transition hover:bg-blue-50/50\"\n @click=${() => this.toggleRowExpansion(event.id)}\n >\n <td\n class=\"border-l border-r border-b border-gray-200 px-3 py-2\"\n >\n <span class=\"font-mono text-[11px] text-gray-600\"\n >${event.agentId}</span\n >\n </td>\n <td\n class=\"border-r border-b border-gray-200 px-3 py-2 font-mono text-[11px] text-gray-600\"\n >\n <span title=${new Date(event.timestamp).toLocaleString()}>\n ${new Date(event.timestamp).toLocaleTimeString()}\n </span>\n </td>\n <td class=\"border-r border-b border-gray-200 px-3 py-2\">\n <span class=${badgeClasses}>${event.type}</span>\n </td>\n <td\n class=\"border-r border-b border-gray-200 px-3 py-2 font-mono text-[10px] text-gray-600 ${isExpanded\n ? \"\"\n : \"truncate max-w-xs\"}\"\n >\n ${isExpanded\n ? html`\n <div class=\"group relative\">\n <pre\n class=\"m-0 whitespace-pre-wrap break-words text-[10px] font-mono text-gray-600\"\n >\n${prettyEvent}</pre\n >\n <button\n 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(\n event.id,\n )\n ? \"bg-green-100 text-green-700\"\n : \"bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900\"}\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this.copyToClipboard(prettyEvent, event.id);\n }}\n >\n ${this.copiedEvents.has(event.id)\n ? html`<span>✓ Copied</span>`\n : html`<span>Copy</span>`}\n </button>\n </div>\n `\n : inlineEvent}\n </td>\n </tr>\n `;\n })}\n </tbody>\n </table>\n </div>\n </div>\n `;\n }\n\n private handleEventFilterInput(event: Event): void {\n const target = event.target as HTMLInputElement | null;\n this.eventFilterText = target?.value ?? \"\";\n this.requestUpdate();\n }\n\n private handleEventTypeChange(event: Event): void {\n const target = event.target as HTMLSelectElement | null;\n const value = target?.value as InspectorAgentEventType | \"all\" | undefined;\n if (!value) {\n return;\n }\n this.eventTypeFilter = value;\n this.requestUpdate();\n }\n\n private resetEventFilters(): void {\n this.eventFilterText = \"\";\n this.eventTypeFilter = \"all\";\n this.requestUpdate();\n }\n\n private handleClearEvents = (): void => {\n if (this.selectedContext === \"all-agents\") {\n this.agentEvents.clear();\n this.flattenedEvents = [];\n } else {\n this.agentEvents.delete(this.selectedContext);\n this.flattenedEvents = this.flattenedEvents.filter(\n (event) => event.agentId !== this.selectedContext,\n );\n }\n\n this.expandedRows.clear();\n this.copiedEvents.clear();\n this.requestUpdate();\n };\n\n private exportEvents(events: InspectorEvent[]): void {\n try {\n const payload = JSON.stringify(events, null, 2);\n const blob = new Blob([payload], { type: \"application/json\" });\n const url = URL.createObjectURL(blob);\n const anchor = document.createElement(\"a\");\n anchor.href = url;\n anchor.download = `copilotkit-events-${Date.now()}.json`;\n anchor.click();\n URL.revokeObjectURL(url);\n } catch (error) {\n console.error(\"Failed to export events\", error);\n }\n }\n\n private renderAgentsView() {\n // Show message if \"all-agents\" is selected or no agents available\n if (this.selectedContext === \"all-agents\") {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-center\"\n >\n <div class=\"max-w-md\">\n <div\n class=\"mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\"\n >\n ${this.renderIcon(\"Bot\")}\n </div>\n <p class=\"text-sm text-gray-600\">No agent selected</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Select an agent from the dropdown above to view details.\n </p>\n </div>\n </div>\n `;\n }\n\n const agentId = this.selectedContext;\n const status = this.getAgentStatus(agentId);\n const stats = this.getAgentStats(agentId);\n const state = this.getLatestStateForAgent(agentId);\n const messages = this.getLatestMessagesForAgent(agentId);\n\n const statusColors = {\n running: \"bg-emerald-50 text-emerald-700\",\n idle: \"bg-gray-100 text-gray-600\",\n error: \"bg-rose-50 text-rose-700\",\n };\n\n return html`\n <div class=\"flex flex-col gap-4 p-4 overflow-auto\">\n <!-- Agent Overview Card -->\n <div class=\"rounded-lg border border-gray-200 bg-white p-4\">\n <div class=\"flex items-start justify-between mb-4\">\n <div class=\"flex items-center gap-3\">\n <div\n class=\"flex h-10 w-10 items-center justify-center rounded-lg bg-blue-100 text-blue-600\"\n >\n ${this.renderIcon(\"Bot\")}\n </div>\n <div>\n <h3 class=\"font-semibold text-sm text-gray-900\">${agentId}</h3>\n <span\n class=\"inline-flex items-center gap-1.5 rounded-full px-2 py-0.5 text-xs font-medium ${statusColors[\n status\n ]} relative -translate-y-[2px]\"\n >\n <span\n class=\"h-1.5 w-1.5 rounded-full ${status === \"running\"\n ? \"bg-emerald-500 animate-pulse\"\n : status === \"error\"\n ? \"bg-rose-500\"\n : \"bg-gray-400\"}\"\n ></span>\n ${status.charAt(0).toUpperCase() + status.slice(1)}\n </span>\n </div>\n </div>\n ${stats.lastActivity\n ? html`<span class=\"text-xs text-gray-500\"\n >Last activity:\n ${new Date(stats.lastActivity).toLocaleTimeString()}</span\n >`\n : nothing}\n </div>\n <div class=\"grid grid-cols-2 gap-4 md:grid-cols-4\">\n <button\n type=\"button\"\n class=\"rounded-md bg-gray-50 px-3 py-2 text-left transition hover:bg-gray-100 cursor-pointer overflow-hidden\"\n @click=${() => this.handleMenuSelect(\"ag-ui-events\")}\n title=\"View all events in AG-UI Events\"\n >\n <div class=\"truncate whitespace-nowrap text-xs text-gray-600\">\n Total Events\n </div>\n <div class=\"text-lg font-semibold text-gray-900\">\n ${stats.totalEvents}\n </div>\n </button>\n <div class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden\">\n <div class=\"truncate whitespace-nowrap text-xs text-gray-600\">\n Messages\n </div>\n <div class=\"text-lg font-semibold text-gray-900\">\n ${stats.messages}\n </div>\n </div>\n <div class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden\">\n <div class=\"truncate whitespace-nowrap text-xs text-gray-600\">\n Tool Calls\n </div>\n <div class=\"text-lg font-semibold text-gray-900\">\n ${stats.toolCalls}\n </div>\n </div>\n <div class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden\">\n <div class=\"truncate whitespace-nowrap text-xs text-gray-600\">\n Errors\n </div>\n <div class=\"text-lg font-semibold text-gray-900\">\n ${stats.errors}\n </div>\n </div>\n </div>\n </div>\n\n <!-- Current State Section -->\n <div class=\"rounded-lg border border-gray-200 bg-white\">\n <div class=\"border-b border-gray-200 px-4 py-3\">\n <h4 class=\"text-sm font-semibold text-gray-900\">Current State</h4>\n </div>\n <div class=\"overflow-auto p-4\">\n ${this.hasRenderableState(state)\n ? html`\n <pre\n class=\"overflow-auto rounded-md bg-gray-50 p-3 text-xs text-gray-800 max-h-64\"\n ><code>${this.formatStateForDisplay(state)}</code></pre>\n `\n : html`\n <div\n class=\"flex h-40 items-center justify-center text-xs text-gray-500\"\n >\n <div class=\"flex items-center gap-2 text-gray-500\">\n <span class=\"text-lg text-gray-400\"\n >${this.renderIcon(\"Database\")}</span\n >\n <span>State is empty</span>\n </div>\n </div>\n `}\n </div>\n </div>\n\n <!-- Current Messages Section -->\n <div class=\"rounded-lg border border-gray-200 bg-white\">\n <div class=\"border-b border-gray-200 px-4 py-3\">\n <h4 class=\"text-sm font-semibold text-gray-900\">\n Current Messages\n </h4>\n </div>\n <div class=\"overflow-auto\">\n ${messages && messages.length > 0\n ? html`\n <table class=\"w-full text-xs\">\n <thead class=\"bg-gray-50\">\n <tr>\n <th\n class=\"px-4 py-2 text-left font-medium text-gray-700\"\n >\n Role\n </th>\n <th\n class=\"px-4 py-2 text-left font-medium text-gray-700\"\n >\n Content\n </th>\n </tr>\n </thead>\n <tbody class=\"divide-y divide-gray-200\">\n ${messages.map((msg) => {\n const role = msg.role || \"unknown\";\n const roleColors: Record<string, string> = {\n user: \"bg-blue-100 text-blue-800\",\n assistant: \"bg-green-100 text-green-800\",\n system: \"bg-gray-100 text-gray-800\",\n tool: \"bg-amber-100 text-amber-800\",\n unknown: \"bg-gray-100 text-gray-600\",\n };\n\n const rawContent = msg.contentText ?? \"\";\n const toolCalls = msg.toolCalls ?? [];\n const hasContent = rawContent.trim().length > 0;\n const contentFallback =\n toolCalls.length > 0 ? \"Invoked tool call\" : \"—\";\n\n return html`\n <tr>\n <td class=\"px-4 py-2 align-top\">\n <span\n class=\"inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${roleColors[\n role\n ] || roleColors.unknown}\"\n >\n ${role}\n </span>\n </td>\n <td class=\"px-4 py-2\">\n ${hasContent\n ? html`<div\n class=\"max-w-2xl whitespace-pre-wrap break-words text-gray-700\"\n >\n ${rawContent}\n </div>`\n : html`<div\n class=\"text-xs italic text-gray-400\"\n >\n ${contentFallback}\n </div>`}\n ${role === \"assistant\" && toolCalls.length > 0\n ? this.renderToolCallDetails(toolCalls)\n : nothing}\n </td>\n </tr>\n `;\n })}\n </tbody>\n </table>\n `\n : html`\n <div\n class=\"flex h-40 items-center justify-center text-xs text-gray-500\"\n >\n <div class=\"flex items-center gap-2 text-gray-500\">\n <span class=\"text-lg text-gray-400\"\n >${this.renderIcon(\"MessageSquare\")}</span\n >\n <span>No messages available</span>\n </div>\n </div>\n `}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderContextDropdown() {\n // Filter out \"all-agents\" when in agents view\n const filteredOptions =\n this.selectedMenu === \"agents\"\n ? this.contextOptions.filter((opt) => opt.key !== \"all-agents\")\n : this.contextOptions;\n\n const selectedLabel =\n filteredOptions.find((opt) => opt.key === this.selectedContext)?.label ??\n \"\";\n\n return html`\n <div\n class=\"relative z-40 min-w-0 flex-1\"\n data-context-dropdown-root=\"true\"\n >\n <button\n type=\"button\"\n 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\"\n @pointerdown=${this.handleContextDropdownToggle}\n >\n <span class=\"truncate flex-1 text-left\">${selectedLabel}</span>\n <span class=\"shrink-0 text-gray-400\"\n >${this.renderIcon(\"ChevronDown\")}</span\n >\n </button>\n ${this.contextMenuOpen\n ? html`\n <div\n 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\"\n data-context-dropdown-root=\"true\"\n >\n ${filteredOptions.map(\n (option) => html`\n <button\n type=\"button\"\n 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\"\n data-context-dropdown-root=\"true\"\n @click=${() => this.handleContextOptionSelect(option.key)}\n >\n <span\n class=\"truncate ${option.key === this.selectedContext\n ? \"text-gray-900 font-medium\"\n : \"text-gray-600\"}\"\n >${option.label}</span\n >\n ${option.key === this.selectedContext\n ? html`<span class=\"text-gray-500\"\n >${this.renderIcon(\"Check\")}</span\n >`\n : nothing}\n </button>\n `,\n )}\n </div>\n `\n : nothing}\n </div>\n `;\n }\n\n private handleMenuSelect(key: MenuKey): void {\n if (!this.menuItems.some((item) => item.key === key)) {\n return;\n }\n\n this.selectedMenu = key;\n\n // If switching to agents view and \"all-agents\" is selected, switch to default or first agent\n if (key === \"agents\" && this.selectedContext === \"all-agents\") {\n const agentOptions = this.contextOptions.filter(\n (opt) => opt.key !== \"all-agents\",\n );\n if (agentOptions.length > 0) {\n // Try to find \"default\" agent first\n const defaultAgent = agentOptions.find((opt) => opt.key === \"default\");\n this.selectedContext = defaultAgent\n ? defaultAgent.key\n : agentOptions[0]!.key;\n }\n }\n\n this.contextMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private handleContextDropdownToggle(event: PointerEvent): void {\n event.preventDefault();\n event.stopPropagation();\n this.contextMenuOpen = !this.contextMenuOpen;\n this.requestUpdate();\n }\n\n private handleContextOptionSelect(key: string): void {\n if (!this.contextOptions.some((option) => option.key === key)) {\n return;\n }\n\n if (this.selectedContext !== key) {\n this.selectedContext = key;\n this.expandedRows.clear();\n }\n\n this.contextMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private renderToolsView() {\n if (!this._core) {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-xs text-gray-500\"\n >\n No core instance available\n </div>\n `;\n }\n\n this.refreshToolsSnapshot();\n const allTools = this.cachedTools;\n\n if (allTools.length === 0) {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-center\"\n >\n <div class=\"max-w-md\">\n <div\n class=\"mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\"\n >\n ${this.renderIcon(\"Hammer\")}\n </div>\n <p class=\"text-sm text-gray-600\">No tools available</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Tools will appear here once agents are configured with tool\n handlers or renderers.\n </p>\n </div>\n </div>\n `;\n }\n\n // Filter tools by selected agent\n const filteredTools =\n this.selectedContext === \"all-agents\"\n ? allTools\n : allTools.filter(\n (tool) => !tool.agentId || tool.agentId === this.selectedContext,\n );\n\n return html`\n <div class=\"flex h-full flex-col overflow-hidden\">\n <div class=\"overflow-auto p-4\">\n <div class=\"space-y-3\">\n ${filteredTools.map((tool) => this.renderToolCard(tool))}\n </div>\n </div>\n </div>\n `;\n }\n\n private extractToolsFromAgents(): InspectorToolDefinition[] {\n if (!this._core) {\n return [];\n }\n\n const tools: InspectorToolDefinition[] = [];\n\n // Start with tools registered on the core (frontend tools / HIL)\n for (const coreTool of this._core.tools ?? []) {\n tools.push({\n agentId: coreTool.agentId ?? \"\",\n name: coreTool.name,\n description: coreTool.description,\n parameters: coreTool.parameters,\n type: \"handler\",\n });\n }\n\n // Augment with agent-level tool handlers/renderers\n for (const [agentId, agent] of Object.entries(this._core.agents)) {\n if (!agent) continue;\n\n // Try to extract tool handlers\n const handlers = (agent as { toolHandlers?: Record<string, unknown> })\n .toolHandlers;\n if (handlers && typeof handlers === \"object\") {\n for (const [toolName, handler] of Object.entries(handlers)) {\n if (handler && typeof handler === \"object\") {\n const handlerObj = handler as Record<string, unknown>;\n tools.push({\n agentId,\n name: toolName,\n description:\n (typeof handlerObj.description === \"string\" &&\n handlerObj.description) ||\n (handlerObj.tool as { description?: string } | undefined)\n ?.description,\n parameters:\n handlerObj.parameters ??\n (handlerObj.tool as { parameters?: unknown } | undefined)\n ?.parameters,\n type: \"handler\",\n });\n }\n }\n }\n\n // Try to extract tool renderers\n const renderers = (agent as { toolRenderers?: Record<string, unknown> })\n .toolRenderers;\n if (renderers && typeof renderers === \"object\") {\n for (const [toolName, renderer] of Object.entries(renderers)) {\n // Don't duplicate if we already have it as a handler\n if (\n !tools.some((t) => t.agentId === agentId && t.name === toolName)\n ) {\n if (renderer && typeof renderer === \"object\") {\n const rendererObj = renderer as Record<string, unknown>;\n tools.push({\n agentId,\n name: toolName,\n description:\n (typeof rendererObj.description === \"string\" &&\n rendererObj.description) ||\n (rendererObj.tool as { description?: string } | undefined)\n ?.description,\n parameters:\n rendererObj.parameters ??\n (rendererObj.tool as { parameters?: unknown } | undefined)\n ?.parameters,\n type: \"renderer\",\n });\n }\n }\n }\n }\n }\n\n return tools.sort((a, b) => {\n const agentCompare = a.agentId.localeCompare(b.agentId);\n if (agentCompare !== 0) return agentCompare;\n return a.name.localeCompare(b.name);\n });\n }\n\n private renderToolCard(tool: InspectorToolDefinition) {\n const isExpanded = this.expandedTools.has(`${tool.agentId}:${tool.name}`);\n const schema = this.extractSchemaInfo(tool.parameters);\n\n const typeColors = {\n handler: \"bg-blue-50 text-blue-700 border-blue-200\",\n renderer: \"bg-purple-50 text-purple-700 border-purple-200\",\n };\n\n return html`\n <div class=\"rounded-lg border border-gray-200 bg-white overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full px-4 py-3 text-left transition hover:bg-gray-50\"\n @click=${() =>\n this.toggleToolExpansion(`${tool.agentId}:${tool.name}`)}\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"flex-1 min-w-0\">\n <div class=\"flex items-center gap-2 mb-1\">\n <span class=\"font-mono text-sm font-semibold text-gray-900\"\n >${tool.name}</span\n >\n <span\n class=\"inline-flex items-center rounded-sm border px-1.5 py-0.5 text-[10px] font-medium ${typeColors[\n tool.type\n ]}\"\n >\n ${tool.type}\n </span>\n </div>\n <div class=\"flex items-center gap-2 text-xs text-gray-500\">\n <span class=\"flex items-center gap-1\">\n ${this.renderIcon(\"Bot\")}\n <span class=\"font-mono\">${tool.agentId}</span>\n </span>\n ${schema.properties.length > 0\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span\n >${schema.properties.length}\n parameter${schema.properties.length !== 1\n ? \"s\"\n : \"\"}</span\n >\n `\n : nothing}\n </div>\n ${tool.description\n ? html`<p class=\"mt-2 text-xs text-gray-600\">\n ${tool.description}\n </p>`\n : nothing}\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${isExpanded\n ? \"rotate-180\"\n : \"\"}\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${isExpanded\n ? html`\n <div class=\"border-t border-gray-200 bg-gray-50/50 px-4 py-3\">\n ${schema.properties.length > 0\n ? html`\n <h5 class=\"mb-3 text-xs font-semibold text-gray-700\">\n Parameters\n </h5>\n <div class=\"space-y-3\">\n ${schema.properties.map(\n (prop) => html`\n <div\n class=\"rounded-md border border-gray-200 bg-white p-3\"\n >\n <div\n class=\"flex items-start justify-between gap-2 mb-1\"\n >\n <span\n class=\"font-mono text-xs font-medium text-gray-900\"\n >${prop.name}</span\n >\n <div class=\"flex items-center gap-1.5 shrink-0\">\n ${prop.required\n ? html`<span\n class=\"text-[9px] rounded border border-rose-200 bg-rose-50 px-1 py-0.5 font-medium text-rose-700\"\n >required</span\n >`\n : html`<span\n class=\"text-[9px] rounded border border-gray-200 bg-gray-50 px-1 py-0.5 font-medium text-gray-600\"\n >optional</span\n >`}\n ${prop.type\n ? html`<span\n class=\"text-[9px] rounded border border-gray-200 bg-gray-50 px-1 py-0.5 font-mono text-gray-600\"\n >${prop.type}</span\n >`\n : nothing}\n </div>\n </div>\n ${prop.description\n ? html`<p class=\"mt-1 text-xs text-gray-600\">\n ${prop.description}\n </p>`\n : nothing}\n ${prop.defaultValue !== undefined\n ? html`\n <div\n class=\"mt-2 flex items-center gap-1.5 text-[10px] text-gray-500\"\n >\n <span>Default:</span>\n <code\n class=\"rounded bg-gray-100 px-1 py-0.5 font-mono\"\n >${JSON.stringify(\n prop.defaultValue,\n )}</code\n >\n </div>\n `\n : nothing}\n ${prop.enum && prop.enum.length > 0\n ? html`\n <div class=\"mt-2\">\n <span class=\"text-[10px] text-gray-500\"\n >Allowed values:</span\n >\n <div class=\"mt-1 flex flex-wrap gap-1\">\n ${prop.enum.map(\n (val) => html`\n <code\n class=\"rounded border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[10px] font-mono text-gray-700\"\n >${JSON.stringify(val)}</code\n >\n `,\n )}\n </div>\n </div>\n `\n : nothing}\n </div>\n `,\n )}\n </div>\n `\n : html`\n <div\n class=\"flex items-center justify-center py-4 text-xs text-gray-500\"\n >\n <span>No parameters defined</span>\n </div>\n `}\n </div>\n `\n : nothing}\n </div>\n `;\n }\n\n private extractSchemaInfo(parameters: unknown): {\n properties: Array<{\n name: string;\n type?: string;\n description?: string;\n required: boolean;\n defaultValue?: unknown;\n enum?: unknown[];\n }>;\n } {\n const result: {\n properties: Array<{\n name: string;\n type?: string;\n description?: string;\n required: boolean;\n defaultValue?: unknown;\n enum?: unknown[];\n }>;\n } = { properties: [] };\n\n if (!parameters || typeof parameters !== \"object\") {\n return result;\n }\n\n // Try Zod schema introspection\n const zodDef = (parameters as { _def?: Record<string, unknown> })._def;\n if (zodDef && typeof zodDef === \"object\") {\n // Handle Zod object schema\n if (zodDef.typeName === \"ZodObject\") {\n const rawShape = zodDef.shape;\n const shape =\n typeof rawShape === \"function\"\n ? (rawShape as () => Record<string, unknown>)()\n : (rawShape as Record<string, unknown> | undefined);\n\n if (!shape || typeof shape !== \"object\") {\n return result;\n }\n const requiredKeys = new Set<string>();\n\n // Get required fields\n if (zodDef.unknownKeys === \"strict\" || !zodDef.catchall) {\n Object.keys(shape || {}).forEach((key) => {\n const candidate = (shape as Record<string, unknown>)[key];\n const fieldDef = (\n candidate as { _def?: Record<string, unknown> } | undefined\n )?._def;\n if (fieldDef && !this.isZodOptional(candidate)) {\n requiredKeys.add(key);\n }\n });\n }\n\n // Extract properties\n for (const [key, value] of Object.entries(shape || {})) {\n const fieldInfo = this.extractZodFieldInfo(value);\n result.properties.push({\n name: key,\n type: fieldInfo.type,\n description: fieldInfo.description,\n required: requiredKeys.has(key),\n defaultValue: fieldInfo.defaultValue,\n enum: fieldInfo.enum,\n });\n }\n }\n } else if (\n (parameters as { type?: string; properties?: Record<string, unknown> })\n .type === \"object\" &&\n (parameters as { properties?: Record<string, unknown> }).properties\n ) {\n // Handle JSON Schema format\n const props = (parameters as { properties?: Record<string, unknown> })\n .properties;\n const required = new Set(\n Array.isArray((parameters as { required?: string[] }).required)\n ? (parameters as { required?: string[] }).required\n : [],\n );\n\n for (const [key, value] of Object.entries(props ?? {})) {\n const prop = value as Record<string, unknown>;\n result.properties.push({\n name: key,\n type: prop.type as string | undefined,\n description:\n typeof prop.description === \"string\" ? prop.description : undefined,\n required: required.has(key),\n defaultValue: prop.default,\n enum: Array.isArray(prop.enum) ? prop.enum : undefined,\n });\n }\n }\n\n return result;\n }\n\n private isZodOptional(zodSchema: unknown): boolean {\n const schema = zodSchema as { _def?: Record<string, unknown> };\n if (!schema?._def) return false;\n\n const def = schema._def;\n\n // Check if it's explicitly optional or nullable\n if (def.typeName === \"ZodOptional\" || def.typeName === \"ZodNullable\") {\n return true;\n }\n\n // Check if it has a default value\n if (def.defaultValue !== undefined) {\n return true;\n }\n\n return false;\n }\n\n private extractZodFieldInfo(zodSchema: unknown): {\n type?: string;\n description?: string;\n defaultValue?: unknown;\n enum?: unknown[];\n } {\n const info: {\n type?: string;\n description?: string;\n defaultValue?: unknown;\n enum?: unknown[];\n } = {};\n\n const schema = zodSchema as { _def?: Record<string, unknown> };\n if (!schema?._def) return info;\n\n let currentSchema = schema as { _def?: Record<string, unknown> };\n let def = currentSchema._def as Record<string, unknown>;\n\n // Unwrap optional/nullable\n while (\n def.typeName === \"ZodOptional\" ||\n def.typeName === \"ZodNullable\" ||\n def.typeName === \"ZodDefault\"\n ) {\n if (def.typeName === \"ZodDefault\" && def.defaultValue !== undefined) {\n info.defaultValue =\n typeof def.defaultValue === \"function\"\n ? def.defaultValue()\n : def.defaultValue;\n }\n currentSchema =\n (def.innerType as { _def?: Record<string, unknown> }) ?? currentSchema;\n if (!currentSchema?._def) break;\n def = currentSchema._def as Record<string, unknown>;\n }\n\n // Extract description\n info.description =\n typeof def.description === \"string\" ? def.description : undefined;\n\n const typeName =\n typeof def.typeName === \"string\" ? def.typeName : undefined;\n\n // Extract type\n const typeMap: Record<string, string> = {\n ZodString: \"string\",\n ZodNumber: \"number\",\n ZodBoolean: \"boolean\",\n ZodArray: \"array\",\n ZodObject: \"object\",\n ZodEnum: \"enum\",\n ZodLiteral: \"literal\",\n ZodUnion: \"union\",\n ZodAny: \"any\",\n ZodUnknown: \"unknown\",\n };\n info.type = typeName\n ? typeMap[typeName] || typeName.replace(\"Zod\", \"\").toLowerCase()\n : undefined;\n\n // Extract enum values\n if (typeName === \"ZodEnum\" && Array.isArray(def.values)) {\n info.enum = def.values as unknown[];\n } else if (typeName === \"ZodLiteral\" && def.value !== undefined) {\n info.enum = [def.value];\n }\n\n return info;\n }\n\n private toggleToolExpansion(toolId: string): void {\n if (this.expandedTools.has(toolId)) {\n this.expandedTools.delete(toolId);\n } else {\n this.expandedTools.add(toolId);\n }\n this.requestUpdate();\n }\n\n private renderContextView() {\n const contextEntries = Object.entries(this.contextStore);\n\n if (contextEntries.length === 0) {\n return html`\n <div\n class=\"flex h-full items-center justify-center px-4 py-8 text-center\"\n >\n <div class=\"max-w-md\">\n <div\n class=\"mb-3 flex justify-center text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\"\n >\n ${this.renderIcon(\"FileText\")}\n </div>\n <p class=\"text-sm text-gray-600\">No context available</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Context will appear here once added to CopilotKit.\n </p>\n </div>\n </div>\n `;\n }\n\n return html`\n <div class=\"flex h-full flex-col overflow-hidden\">\n <div class=\"overflow-auto p-4\">\n <div class=\"space-y-3\">\n ${contextEntries.map(([id, context]) =>\n this.renderContextCard(id, context),\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderContextCard(\n id: string,\n context: { description?: string; value: unknown },\n ) {\n const isExpanded = this.expandedContextItems.has(id);\n const valuePreview = this.getContextValuePreview(context.value);\n const hasValue = context.value !== undefined && context.value !== null;\n const title = context.description?.trim() || id;\n\n return html`\n <div class=\"rounded-lg border border-gray-200 bg-white overflow-hidden\">\n <button\n type=\"button\"\n class=\"w-full px-4 py-3 text-left transition hover:bg-gray-50\"\n @click=${() => this.toggleContextExpansion(id)}\n >\n <div class=\"flex items-start justify-between gap-3\">\n <div class=\"flex-1 min-w-0\">\n <p class=\"text-sm font-medium text-gray-900 mb-1\">${title}</p>\n <div class=\"flex items-center gap-2 text-xs text-gray-500\">\n <span\n class=\"font-mono truncate inline-block align-middle\"\n style=\"max-width: 180px;\"\n >${id}</span\n >\n ${hasValue\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span class=\"truncate\">${valuePreview}</span>\n `\n : nothing}\n </div>\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${isExpanded\n ? \"rotate-180\"\n : \"\"}\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${isExpanded\n ? html`\n <div class=\"border-t border-gray-200 bg-gray-50/50 px-4 py-3\">\n <div class=\"mb-3\">\n <h5 class=\"mb-1 text-xs font-semibold text-gray-700\">ID</h5>\n <code\n class=\"block rounded bg-white border border-gray-200 px-2 py-1 text-[10px] font-mono text-gray-600\"\n >${id}</code\n >\n </div>\n ${hasValue\n ? html`\n <div class=\"mb-2 flex items-center justify-between gap-2\">\n <h5 class=\"text-xs font-semibold text-gray-700\">\n Value\n </h5>\n <button\n 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\"\n type=\"button\"\n @click=${(e: Event) => {\n e.stopPropagation();\n void this.copyContextValue(context.value, id);\n }}\n >\n ${this.copiedContextItems.has(id)\n ? \"Copied\"\n : \"Copy JSON\"}\n </button>\n </div>\n <div\n class=\"rounded-md border border-gray-200 bg-white p-3\"\n >\n <pre\n class=\"overflow-auto text-xs text-gray-800 max-h-96\"\n ><code>${this.formatContextValue(\n context.value,\n )}</code></pre>\n </div>\n `\n : html`\n <div\n class=\"flex items-center justify-center py-4 text-xs text-gray-500\"\n >\n <span>No value available</span>\n </div>\n `}\n </div>\n `\n : nothing}\n </div>\n `;\n }\n\n private getContextValuePreview(value: unknown): string {\n if (value === undefined || value === null) {\n return \"—\";\n }\n\n if (typeof value === \"string\") {\n return value.length > 50 ? `${value.substring(0, 50)}...` : value;\n }\n\n if (typeof value === \"number\" || typeof value === \"boolean\") {\n return String(value);\n }\n\n if (Array.isArray(value)) {\n return `Array(${value.length})`;\n }\n\n if (typeof value === \"object\") {\n const keys = Object.keys(value);\n return `Object with ${keys.length} key${keys.length !== 1 ? \"s\" : \"\"}`;\n }\n\n if (typeof value === \"function\") {\n return \"Function\";\n }\n\n return String(value);\n }\n\n private formatContextValue(value: unknown): string {\n if (value === undefined) {\n return \"undefined\";\n }\n\n if (value === null) {\n return \"null\";\n }\n\n if (typeof value === \"function\") {\n return value.toString();\n }\n\n try {\n return JSON.stringify(value, null, 2);\n } catch {\n return String(value);\n }\n }\n\n private async copyContextValue(\n value: unknown,\n contextId: string,\n ): Promise<void> {\n if (typeof navigator === \"undefined\" || !navigator.clipboard?.writeText) {\n console.warn(\"Clipboard API is not available in this environment.\");\n return;\n }\n\n const serialized = this.formatContextValue(value);\n try {\n await navigator.clipboard.writeText(serialized);\n this.copiedContextItems.add(contextId);\n this.requestUpdate();\n setTimeout(() => {\n this.copiedContextItems.delete(contextId);\n this.requestUpdate();\n }, 1500);\n } catch (error) {\n console.error(\"Failed to copy context value:\", error);\n }\n }\n\n private toggleContextExpansion(contextId: string): void {\n if (this.expandedContextItems.has(contextId)) {\n this.expandedContextItems.delete(contextId);\n } else {\n this.expandedContextItems.add(contextId);\n }\n this.requestUpdate();\n }\n\n private handleGlobalPointerDown = (event: PointerEvent): void => {\n if (!this.contextMenuOpen) {\n return;\n }\n\n const clickedDropdown = event.composedPath().some((node) => {\n return (\n node instanceof HTMLElement &&\n node.dataset?.contextDropdownRoot === \"true\"\n );\n });\n\n if (!clickedDropdown) {\n this.contextMenuOpen = false;\n this.requestUpdate();\n }\n };\n\n private toggleRowExpansion(eventId: string): void {\n // Don't toggle if user is selecting text\n const selection = window.getSelection();\n if (selection && selection.toString().length > 0) {\n return;\n }\n\n if (this.expandedRows.has(eventId)) {\n this.expandedRows.delete(eventId);\n } else {\n this.expandedRows.add(eventId);\n }\n this.requestUpdate();\n }\n\n private renderAnnouncementPanel() {\n if (!this.isOpen) {\n return nothing;\n }\n\n // Ensure loading is triggered even if we mounted in an already-open state\n this.ensureAnnouncementLoading();\n\n if (!this.hasUnseenAnnouncement) {\n return nothing;\n }\n\n if (!this.announcementLoaded && !this.announcementMarkdown) {\n return html`<div\n 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)]\"\n >\n <div class=\"flex items-center gap-2 font-semibold\">\n <span\n class=\"inline-flex h-6 w-6 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm\"\n >\n ${this.renderIcon(\"Megaphone\")}\n </span>\n <span>Loading latest announcement…</span>\n </div>\n </div>`;\n }\n\n if (this.announcementLoadError) {\n return html`<div\n 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)]\"\n >\n <div class=\"flex items-center gap-2 font-semibold\">\n <span\n class=\"inline-flex h-6 w-6 items-center justify-center rounded-md bg-rose-600 text-white shadow-sm\"\n >\n ${this.renderIcon(\"Megaphone\")}\n </span>\n <span>Announcement unavailable</span>\n </div>\n <p class=\"mt-2 text-xs text-rose-800\">\n We couldn’t load the latest notice. Please try opening the inspector\n again.\n </p>\n </div>`;\n }\n\n if (!this.announcementMarkdown) {\n return nothing;\n }\n\n const content = this.announcementHtml\n ? unsafeHTML(this.announcementHtml)\n : html`<pre class=\"whitespace-pre-wrap text-sm text-gray-900\">\n${this.announcementMarkdown}</pre\n >`;\n\n return html`<div\n 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)]\"\n >\n <div\n class=\"mb-3 flex items-center gap-2 text-sm font-semibold text-slate-900\"\n >\n <span\n class=\"inline-flex h-7 w-7 items-center justify-center rounded-md bg-slate-900 text-white shadow-sm\"\n >\n ${this.renderIcon(\"Megaphone\")}\n </span>\n <span>Announcement</span>\n <button\n class=\"announcement-dismiss ml-auto\"\n type=\"button\"\n @click=${this.handleDismissAnnouncement}\n aria-label=\"Dismiss announcement\"\n >\n Dismiss\n </button>\n </div>\n <div class=\"announcement-content text-sm leading-relaxed text-gray-900\">\n ${content}\n </div>\n </div>`;\n }\n\n private ensureAnnouncementLoading(): void {\n if (\n this.announcementPromise ||\n typeof window === \"undefined\" ||\n typeof fetch === \"undefined\"\n ) {\n return;\n }\n this.announcementPromise = this.fetchAnnouncement();\n }\n\n private renderAnnouncementPreview() {\n if (\n !this.hasUnseenAnnouncement ||\n !this.showAnnouncementPreview ||\n !this.announcementPreviewText\n ) {\n return nothing;\n }\n\n const side =\n this.contextState.button.anchor.horizontal === \"left\" ? \"right\" : \"left\";\n\n return html`<div\n class=\"announcement-preview\"\n data-side=${side}\n role=\"note\"\n @click=${() => this.handleAnnouncementPreviewClick()}\n >\n <span>${this.announcementPreviewText}</span>\n <span class=\"announcement-preview__arrow\"></span>\n </div>`;\n }\n\n private handleAnnouncementPreviewClick(): void {\n this.showAnnouncementPreview = false;\n this.openInspector();\n }\n\n private handleDismissAnnouncement = (): void => {\n this.markAnnouncementSeen();\n };\n\n private async fetchAnnouncement(): Promise<void> {\n try {\n const response = await fetch(ANNOUNCEMENT_URL, { cache: \"no-cache\" });\n if (!response.ok) {\n throw new Error(`Failed to load announcement (${response.status})`);\n }\n\n const data = (await response.json()) as {\n timestamp?: unknown;\n previewText?: unknown;\n announcement?: unknown;\n };\n\n const timestamp =\n typeof data?.timestamp === \"string\" ? data.timestamp : null;\n const previewText =\n typeof data?.previewText === \"string\" ? data.previewText : null;\n const markdown =\n typeof data?.announcement === \"string\" ? data.announcement : null;\n\n if (!timestamp || !markdown) {\n throw new Error(\"Malformed announcement payload\");\n }\n\n const storedTimestamp = this.loadStoredAnnouncementTimestamp();\n\n this.announcementTimestamp = timestamp;\n this.announcementPreviewText = previewText ?? \"\";\n this.announcementMarkdown = markdown;\n this.hasUnseenAnnouncement =\n (!storedTimestamp || storedTimestamp !== timestamp) &&\n !!this.announcementPreviewText;\n this.showAnnouncementPreview = this.hasUnseenAnnouncement;\n this.announcementHtml = await this.convertMarkdownToHtml(markdown);\n this.announcementLoaded = true;\n\n this.requestUpdate();\n } catch (error) {\n this.announcementLoadError = error;\n this.announcementLoaded = true;\n this.requestUpdate();\n }\n }\n\n private async convertMarkdownToHtml(\n markdown: string,\n ): Promise<string | null> {\n const renderer = new marked.Renderer();\n renderer.link = (href, title, text) => {\n const safeHref = this.escapeHtmlAttr(this.appendRefParam(href ?? \"\"));\n const titleAttr = title ? ` title=\"${this.escapeHtmlAttr(title)}\"` : \"\";\n return `<a href=\"${safeHref}\" target=\"_blank\" rel=\"noopener\"${titleAttr}>${text}</a>`;\n };\n return marked.parse(markdown, { renderer });\n }\n\n private appendRefParam(href: string): string {\n try {\n const url = new URL(\n href,\n typeof window !== \"undefined\"\n ? window.location.href\n : \"https://copilotkit.ai\",\n );\n if (!url.searchParams.has(\"ref\")) {\n url.searchParams.append(\"ref\", \"cpk-inspector\");\n }\n return url.toString();\n } catch {\n return href;\n }\n }\n\n private escapeHtmlAttr(value: string): string {\n return value\n .replace(/&/g, \"&\")\n .replace(/</g, \"<\")\n .replace(/>/g, \">\")\n .replace(/\\\"/g, \""\")\n .replace(/'/g, \"'\");\n }\n\n private loadStoredAnnouncementTimestamp(): string | null {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return null;\n }\n try {\n const raw = window.localStorage.getItem(ANNOUNCEMENT_STORAGE_KEY);\n if (!raw) {\n return null;\n }\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed.timestamp === \"string\") {\n return parsed.timestamp;\n }\n // Backward compatibility: previous shape { hash }\n return null;\n } catch {\n // ignore malformed storage\n }\n return null;\n }\n\n private persistAnnouncementTimestamp(timestamp: string): void {\n if (typeof window === \"undefined\" || !window.localStorage) {\n return;\n }\n try {\n const payload = JSON.stringify({ timestamp });\n window.localStorage.setItem(ANNOUNCEMENT_STORAGE_KEY, payload);\n } catch {\n // Non-fatal if storage is unavailable\n }\n }\n\n private markAnnouncementSeen(): void {\n // Clear badge only when explicitly dismissed\n this.hasUnseenAnnouncement = false;\n this.showAnnouncementPreview = false;\n\n if (!this.announcementTimestamp) {\n // If still loading, attempt once more after promise resolves; avoid infinite requeues\n if (this.announcementPromise && !this.announcementLoaded) {\n void this.announcementPromise\n .then(() => this.markAnnouncementSeen())\n .catch(() => undefined);\n }\n this.requestUpdate();\n return;\n }\n\n this.persistAnnouncementTimestamp(this.announcementTimestamp);\n this.requestUpdate();\n }\n}\n\nexport function defineWebInspector(): void {\n if (!customElements.get(WEB_INSPECTOR_TAG)) {\n customElements.define(WEB_INSPECTOR_TAG, WebInspectorElement);\n }\n}\n\ndefineWebInspector();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"cpk-web-inspector\": WebInspectorElement;\n }\n}\n"],"mappings":"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"} |