@copilotkit/web-inspector 1.73.2 → 1.73.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"file":"index.mjs","names":["tailwindStyles","inspectorLogoKiteUrl","inspectorLogoUrl","clampSizeToViewport"],"sources":["../src/index.ts"],"sourcesContent":["import { LitElement, css, html, nothing, render, unsafeCSS } from \"lit\";\nimport type { TemplateResult } from \"lit\";\nimport { marked } from \"marked\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport tailwindStyles from \"./styles/generated.css\";\nimport inspectorLogoUrl from \"./assets/inspector-logo.svg\";\nimport inspectorLogoKiteUrl from \"./assets/inspector-logo-kite.svg\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { icons } from \"lucide\";\nimport type { CopilotKitCore } from \"@copilotkit/core\";\nimport {\n CopilotKitCoreErrorCode,\n CopilotKitCoreRuntimeConnectionStatus,\n createInspectorThreadRequestId,\n emitInspectorStopViewing,\n emitInspectorViewThread,\n isInspectorThreadBridgeEnabled,\n onInspectorActiveThread,\n onInspectorViewThreadResult,\n ɵselectThreads,\n ɵselectThreadsIsLoading,\n ɵselectThreadsError,\n ɵcreateThreadStore,\n ɵselectMemories,\n ɵselectMemoriesIsLoading,\n ɵselectMemoriesError,\n ɵselectMemoriesAvailable,\n ɵselectMemoriesRealtimeStatus,\n} from \"@copilotkit/core\";\nimport type {\n CopilotKitCoreSubscriber,\n ɵThreadStore,\n ɵThread,\n Memory,\n MemoryRealtimeStatus,\n RuntimeLicenseStatus,\n} from \"@copilotkit/core\";\nimport type { AbstractAgent, AgentSubscriber, Message } from \"@ag-ui/client\";\nimport type { InspectorLearningSnapshotV1 } from \"@copilotkit/shared\";\nimport { deriveLearningViewState } from \"./components/learning-view.js\";\nimport type { LearningViewState } from \"./components/learning-view.js\";\nimport type {\n Anchor,\n ContextKey,\n ContextState,\n DockMode,\n Position,\n Size,\n} from \"./lib/types.js\";\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.js\";\nimport {\n clearLegacyAnnouncementReadState,\n INSPECTOR_DISMISSAL_MAX_DURATION_MS,\n loadInspectorDismissedUntil,\n loadAnnouncementPulsedTimestamp,\n loadAnnouncementReadTimestamp,\n loadInspectorState,\n saveAnnouncementPulsedTimestamp,\n saveAnnouncementReadTimestamp,\n saveInspectorDismissedUntil,\n saveInspectorState,\n isValidAnchor,\n isValidPosition,\n isValidSize,\n isValidDockMode,\n} from \"./lib/persistence.js\";\nimport type { PersistedState } from \"./lib/persistence.js\";\nimport {\n clearLearningSetupMarker,\n learningSetupMarkerMatches,\n readLearningSetupMarker,\n subscribeToLearningSetupMarker,\n writeLearningSetupMarker,\n} from \"./lib/learning-setup.js\";\nimport type { LearningSetupMarker } from \"./lib/learning-setup.js\";\nimport {\n fetchInspectorLearning,\n InspectorLearningUnsupportedError,\n} from \"./lib/inspector-learning.js\";\nimport {\n buildPopOutFeatures,\n ensureBrandFont,\n openPopOutWindow,\n} from \"./lib/pop-out.js\";\nimport type { PopOutHandle } from \"./lib/pop-out.js\";\nimport { projectInspectorMetadata } from \"./lib/inspector-metadata.js\";\nimport type {\n InspectorMetadataAction,\n InspectorMetadataProjection,\n} from \"./lib/inspector-metadata.js\";\nimport {\n buildHomeModel,\n runtimeConnectionNeedsAttention,\n} from \"./lib/home-briefing.js\";\nimport type {\n HomeHeroAction,\n HomeModel,\n HomeRuntimeHealthTone,\n HomeServiceId,\n} from \"./lib/home-briefing.js\";\nimport {\n INSPECTOR_GROUPS,\n INSPECTOR_NAV_SECTIONS,\n getGroupForMenu,\n isInspectorMenuKey,\n shouldUseIconRail,\n} from \"./lib/inspector-nav.js\";\nimport type { InspectorNavGroupKey, MenuKey } from \"./lib/inspector-nav.js\";\nimport { selectVisibleRealThreadId } from \"./lib/thread-selection.js\";\nimport {\n TELEMETRY_DOCS_URL,\n ensureTelemetryDistinctId,\n getRuntimeUrlType,\n getTelemetryDistinctIdForUrl,\n maybeShowDisclosure,\n trackErrorSignalViewed,\n trackHomeCtaClicked,\n trackHomeFeaturePromptClicked,\n trackHomePromptCopied,\n trackHomeStoryBeatSelected,\n trackHomeViewed,\n trackInspectorOpened,\n learningCountBucket,\n learningDurationBucket,\n trackLearningEvidenceOpened,\n trackLearningPageChanged,\n trackLearningPaneViewed,\n trackLearningSetupPromptClicked,\n trackLearningSkillToggled,\n trackLearningSnapshotLoaded,\n trackLearningWebAppOpened,\n trackMetadataActionClicked,\n trackMetadataModuleViewed,\n trackTalkToEngineerClicked,\n trackThreadsEmptyEnabledViewed,\n trackThreadsEnabledViewed,\n trackThreadsExampleSelected,\n trackThreadsExampleTourCompleted,\n trackThreadsExampleTourDismissed,\n trackThreadsExampleTourReopened,\n trackThreadsExampleTourStarted,\n trackThreadsExampleTourStepViewed,\n trackThreadsExampleViewed,\n trackThreadsIntelligenceSignupClicked,\n trackThreadsLockedViewed,\n trackMemoriesTabClicked,\n trackThreadsTabClicked,\n trackThreadsTalkToEngineerClicked,\n trackThreadsTryFromHereClicked,\n trackWhatsNewClicked,\n trackWhatsNewSignalViewed,\n trackWhatsNewViewed,\n} from \"./lib/telemetry.js\";\nimport {\n createFeatureOnboardingPrompt,\n createOnboardingPrompt,\n createOnboardingRunId,\n} from \"./lib/onboarding-prompt.js\";\nimport type {\n ExampleKind,\n ExampleTourStep,\n ExampleTourTab,\n InspectorGroupKey,\n InspectorMetadataLicenseBucket,\n InspectorMetadataModuleViewedTelemetryProps,\n InspectorMetadataTelemetryModule,\n InspectorMemoryTelemetryProps,\n InspectorErrorSignalSource,\n InspectorEventErrorSource,\n InspectorWiringErrorSource,\n InspectorOpenSource,\n InspectorThreadTelemetryProps,\n MetadataActionPlacement,\n ThreadsExpiryBucket,\n ThreadsUsageBucket,\n WhatsNewSignalPresentation,\n WhatsNewSurface,\n} from \"./lib/telemetry.js\";\n\nexport type { Anchor } from \"./lib/types.js\";\nexport { buildCapabilityRows as ɵbuildCapabilityRows };\nexport type { CapabilityToolRow as ɵCapabilityToolRow };\n\nexport type InspectorOpenOptions = {\n /** Select the thread that contains the message. */\n threadId?: string;\n /** Narrow the Threads view to the agent that owns the thread. */\n agentId?: string;\n /** Scroll the selected thread timeline to this message when available. */\n messageId?: string;\n};\n\nexport const WEB_INSPECTOR_TAG = \"cpk-web-inspector\" as const;\nexport const THREAD_INSPECTOR_TAG = \"cpk-thread-inspector\" as const;\n\n/**\n * User-facing label for the learning view. The legacy menu key stays\n * \"memories\" for persistence and telemetry stability.\n */\nconst LEARNING_VIEW_LABEL = \"Automatic Learning\";\nconst LEARNING_RECOPY_CONFIRMATION_MS = 2_000;\n\n/**\n * User-facing label for the What's new view. Its menu key stays `whats-new`\n * for persistence and telemetry stability, following the `memories`/\"Memory\"\n * precedent above.\n */\nconst WHATS_NEW_VIEW_LABEL = \"What's new\";\n\n/** Menu key of the What's new leaf — the news signal's destination. */\nconst WHATS_NEW_MENU_KEY = \"whats-new\";\n\ntype LucideIconName = keyof typeof icons;\n\ntype MenuItem = {\n key: MenuKey;\n label: string;\n icon: LucideIconName;\n};\n\n// ── Launcher signals ──────────────────────────────────────────────────────\n//\n// There is one dot on the closed launcher and more than one thing that can\n// claim it, so each subject is described once, here, and every call site reads\n// the description rather than hardcoding a subject.\n//\n// The rule for this table is **no field without a second consumer**. That is\n// why there is no lifecycle field (one value was ever used, and \"never\n// persisted\" is expressed by not persisting) and why the two destinations are\n// separate: the news signal genuinely marks one entry and lands on another.\n//\n// This reintroduces a small shared shape where an earlier generic version was\n// removed as speculative. That removal was correct at the time — the\n// abstraction had exactly one user. A second user now exists.\n//\n// **The two subjects beat by different rules, deliberately**: an error beats\n// once per outage, an announcement once per tab per announcement. That follows\n// from a recurring condition versus a one-time publication. Do not harmonise\n// them; harmonising breaks one of them.\n\n/** Tone drives colour only. The launcher treatment is shared by every tone. */\ntype LauncherSignalTone = \"news\" | \"error\";\n\n/**\n * The error keys ARE the telemetry enum, so a source can never be reported\n * under a name the signal table does not describe.\n */\ntype LauncherSignalKey = \"whats-new\" | InspectorErrorSignalSource;\n\ntype LauncherSignalDefinition = Readonly<{\n tone: LauncherSignalTone;\n /** Which navigation entry carries the marker while this signal is armed. */\n markerTarget: MenuKey;\n /** Where a press on the launcher opens while this signal owns the dot. */\n landingTarget: MenuKey;\n /** One beat's duration. Errors beat faster than product news. */\n cadence: number;\n /** Higher wins the single dot. Errors outrank news. */\n priority: number;\n /**\n * Suffix appended to the marked navigation entry's accessible name, and —\n * for error tones only — to the launcher's own accessible name. Never\n * rendered as visible text: the dot says there is something to look at, and\n * the panel says what.\n */\n accessibleLabel: string;\n /**\n * The words the launcher opens sideways to show, and the words spoken once\n * into the polite live region. Absent means this subject opens no pill.\n *\n * Read from the signal rather than from a condition on the tone, so a third\n * signal can carry a pill by declaring one — and whoever declares it owns\n * the width problem that keeps the announcement out. The announcement's feed\n * preview measures 54 characters against a 36-pixel launcher, and the width\n * would be set by a feed we do not control.\n *\n * These are the words the panel already uses, never a paraphrase, so a\n * reader who sees the pill and then opens the panel has nothing to\n * reconcile. The failure *message* is never carried here — for width, and\n * because it can contain prompts, URLs and identifiers.\n */\n pillLabel?: string;\n}>;\n\nconst NEWS_SIGNAL_ID = \"whats-new\" as const;\nconst NEWS_SIGNAL_COLOR = \"#A78BFA\";\n/**\n * The error tone's red. Bright enough to read against the launcher's dark\n * face at the same perceived weight as the news lilac, and in the same family\n * as System Health's error tone (#b32d3b light / #ff9aa0 dark), which is too\n * dark and too pale respectively to use directly on the launcher.\n */\nconst ERROR_SIGNAL_COLOR = \"#F87171\";\n\nconst LAUNCHER_SIGNAL_COLORS: Readonly<Record<LauncherSignalTone, string>> = {\n news: NEWS_SIGNAL_COLOR,\n error: ERROR_SIGNAL_COLOR,\n};\n\n/**\n * The failure gesture, four phases in series:\n *\n * ```\n * beat 400ms → open 250ms → hold 2500ms → close 250ms (3400ms total)\n * ```\n *\n * Sequential rather than simultaneous, deliberately: the beat says *here*, the\n * pill says *this*. The beat is short so the words arrive quickly.\n *\n * **All four durations live here and nowhere else.** The stylesheet reads the\n * two animated phases as custom properties injected from these numbers rather\n * than restating them, because they are taste and will be tuned by eye after\n * the first live look — tuning the feel must be a number, not a refactor.\n */\nconst ERROR_GESTURE_MS = {\n /** Phase 1: one beat, which is also the error signals' cadence. */\n beat: 400,\n /** Phase 2: the sideways reveal. */\n open: 250,\n /** Phase 3: long enough to read three words without hurrying. */\n hold: 2500,\n /** Phase 4: back to the plain mark with its dot. */\n close: 250,\n} as const;\n\n/**\n * The words the pill carries, which are the words the panel already carries.\n *\n * `Runtime error` is the System Health runtime tile's own label, and\n * `Failed to load threads` is the Threads view's own heading. The outside and\n * the inside must agree, so these are shared rather than paraphrased.\n */\nconst RUNTIME_ERROR_LABEL = \"Runtime error\";\nconst THREADS_LOAD_ERROR_LABEL = \"Failed to load threads\";\nconst AGENT_RUN_FAILED_LABEL = \"Agent run failed\";\nconst TOOL_ERROR_LABEL = \"Tool error\";\nconst MEMORY_LOAD_ERROR_LABEL = \"Failed to load learning data\";\n\n/**\n * Copy on the landing view. Titles match the pill.\n *\n * The two fields differ in what they can promise. `advice` is about the\n * reader's next move and is always true. `highlight` is a claim about *this\n * view* — that the failed item is visible below — and the error carries no\n * guarantee of that: a code mapped to `run` can arrive with no run in the\n * buffer at all, and a tool error can arrive without the call id the\n * highlight needs. So it is rendered only once the item is actually there.\n * A card pointing at something the reader cannot find is worse than a card\n * that stays quiet, because it sends them looking.\n */\nconst EVENT_ERROR_GUIDANCE: Readonly<\n Record<\n InspectorEventErrorSource,\n Readonly<{ title: string; advice?: string; highlight?: string }>\n >\n> = {\n run: {\n title: AGENT_RUN_FAILED_LABEL,\n highlight: \"The failed run event is highlighted below.\",\n },\n tool: {\n title: TOOL_ERROR_LABEL,\n highlight: \"The failed tool call is highlighted below.\",\n },\n memory: {\n title: MEMORY_LOAD_ERROR_LABEL,\n advice:\n \"Confirm CopilotKit Intelligence is connected, then retry Learning.\",\n },\n};\n\n/**\n * The pill's second line, shared by every subject that carries a pill.\n *\n * **This is the one string in the feature that exists nowhere else in the\n * product.** Every other word the launcher shows is word-identical to the\n * panel, which is the standing rule; this line is a deliberate, owner-approved\n * exception to it, because the pill became clickable and an invitation that\n * says nothing is not an invitation.\n *\n * It is shown, never spoken: the polite live region carries the failure class\n * alone. A screen-reader user cannot act on an instruction delivered through\n * an announcement, and it would double the spoken length.\n */\nconst PILL_SUBLINE_LABEL = \"Open Inspector for details\";\n\ntype LauncherHudRowId = \"threads\" | \"learning\";\n\nconst HUD_INSPECTOR_LABEL = \"CopilotKit Inspector\";\nconst HUD_ANNOUNCEMENT_TITLE_LIMIT = 80;\nconst HUD_THREADS_LABEL = \"Rich Threads\";\nconst HUD_LEARNING_LABEL = \"Automatic Learning\";\nconst HUD_LEARN_MORE_LABEL = \"Click to learn more\";\n\ntype InspectorDismissalDuration = \"day\" | \"week\";\nconst INSPECTOR_DISMISSAL_MS: Readonly<\n Record<InspectorDismissalDuration, number>\n> = {\n day: 24 * 60 * 60 * 1000,\n week: INSPECTOR_DISMISSAL_MAX_DURATION_MS,\n};\n\ntype HomeFeaturePromptId = HomeServiceId;\ntype HomeFeaturePromptTarget = Readonly<{\n id: HomeFeaturePromptId;\n label: string;\n}>;\n\nconst LAUNCHER_SIGNALS: Readonly<\n Record<LauncherSignalKey, LauncherSignalDefinition>\n> = {\n // Marks What's new, lands on Home: Home carries the preview band that is\n // the way onward. Unchanged from before this table existed.\n \"whats-new\": {\n tone: \"news\",\n markerTarget: WHATS_NEW_MENU_KEY,\n landingTarget: \"home\",\n cadence: 2100,\n priority: 0,\n accessibleLabel: \"new content\",\n },\n // Errors mark and land on the same place, because the place that carries\n // the marker is the place that explains the failure.\n connection: {\n tone: \"error\",\n markerTarget: \"home\",\n landingTarget: \"home\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 5,\n accessibleLabel: \"runtime error\",\n pillLabel: RUNTIME_ERROR_LABEL,\n },\n threads: {\n tone: \"error\",\n markerTarget: \"threads\",\n landingTarget: \"threads\",\n cadence: ERROR_GESTURE_MS.beat,\n // Below the connection signal: a connection failure cascades into thread\n // failures, so when both could be armed the root cause owns the dot.\n priority: 4,\n accessibleLabel: \"thread loading error\",\n pillLabel: THREADS_LOAD_ERROR_LABEL,\n },\n // Unread *events*. They beat and name the failure, then clear when the\n // landing view is read. They lose the launcher dot to wiring state.\n run: {\n tone: \"error\",\n markerTarget: \"ag-ui-events\",\n landingTarget: \"ag-ui-events\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 3,\n accessibleLabel: \"agent run failed\",\n pillLabel: AGENT_RUN_FAILED_LABEL,\n },\n tool: {\n tone: \"error\",\n markerTarget: \"agents\",\n landingTarget: \"agents\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 2,\n accessibleLabel: \"tool error\",\n pillLabel: TOOL_ERROR_LABEL,\n },\n memory: {\n tone: \"error\",\n markerTarget: \"memories\",\n landingTarget: \"memories\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 1,\n accessibleLabel: \"learning error\",\n pillLabel: MEMORY_LOAD_ERROR_LABEL,\n },\n};\n\n/** Highest priority first, so the winner of the single dot is the head. */\nconst LAUNCHER_SIGNAL_PRIORITY_ORDER: ReadonlyArray<LauncherSignalKey> = (\n Object.keys(LAUNCHER_SIGNALS) as LauncherSignalKey[]\n).sort((a, b) => LAUNCHER_SIGNALS[b].priority - LAUNCHER_SIGNALS[a].priority);\n\n/** Wiring *state* — red until the problem heals. */\nconst WIRING_ERROR_KEYS = [\n \"connection\",\n \"threads\",\n] as const satisfies ReadonlyArray<InspectorWiringErrorSource>;\n\n/** Unread *events* — red until the landing view is read. */\nconst EVENT_ERROR_KEYS = [\n \"run\",\n \"tool\",\n \"memory\",\n] as const satisfies ReadonlyArray<InspectorEventErrorSource>;\n\ntype InspectorEventErrorDetails = Readonly<{\n message: string;\n agentId?: string;\n toolName?: string;\n toolCallId?: string;\n}>;\n\nfunction isWiringErrorKey(\n key: LauncherSignalKey,\n): key is InspectorWiringErrorSource {\n return (WIRING_ERROR_KEYS as readonly string[]).includes(key);\n}\n\n/**\n * Takes a plain string rather than a `LauncherSignalKey`, because one caller\n * reads the subject back out of a `data-` attribute, where the DOM can only\n * offer `string | undefined`. Narrowing untrusted input is what a guard is\n * for; `LauncherSignalKey` still satisfies the parameter, so the callers that\n * already hold one are unaffected.\n */\nfunction isEventErrorKey(key: string): key is InspectorEventErrorSource {\n return (EVENT_ERROR_KEYS as readonly string[]).includes(key);\n}\n\n/** Narrows a signal key to an error source, excluding the announcement. */\nfunction isErrorSignalKey(\n key: LauncherSignalKey,\n): key is InspectorErrorSignalSource {\n return isWiringErrorKey(key) || isEventErrorKey(key);\n}\n\n/**\n * The control range is the point, not an oversight: an attribute selector has\n * to escape those characters too, and CSS.escape — which the fallback below\n * stands in for — escapes them as well. Hoisted so the suppression can sit on\n * the pattern rather than three lines above it.\n */\n// oxlint-disable no-control-regex -- deliberate, see above\nconst SELECTOR_ESCAPE_PATTERN =\n /[\\0-\\x1f\\x7f!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/g;\n// oxlint-enable no-control-regex\n\n/** Attribute selector value. jsdom does not implement CSS.escape. */\nfunction escapeSelectorValue(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n return CSS.escape(value);\n }\n return value.replace(SELECTOR_ESCAPE_PATTERN, \"\\\\$&\");\n}\n\nfunction eventErrorKeyForCode(\n code: CopilotKitCoreErrorCode,\n): InspectorEventErrorSource | null {\n switch (code) {\n case CopilotKitCoreErrorCode.TOOL_NOT_FOUND:\n case CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED:\n case CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED:\n case CopilotKitCoreErrorCode.AGENT_NOT_FOUND:\n return \"tool\";\n case CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED:\n case CopilotKitCoreErrorCode.AGENT_RUN_FAILED:\n case CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT:\n case CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT:\n return \"run\";\n default:\n return null;\n }\n}\n\n/**\n * Coalesce inspector-owned GET /threads sends. The first refresh goes out\n * at once. Further calls in this window share one trailing request, so a\n * flaky network does not fire a burst of list fetches and error cards.\n */\nconst THREAD_LIST_DEBOUNCE_MS = 300;\n\n/** The launcher's accessible name with nothing wrong. */\nconst LAUNCHER_BASE_LABEL = \"Web Inspector\";\n\n/**\n * Where the pill is in the gesture.\n *\n * `closed` covers the whole beat: the pill is laid out at its full width and\n * clipped to nothing from the first frame, so the room it needs can be\n * measured before anything is shown and the reveal has nothing left to\n * compute.\n */\ntype LauncherPillPhase = \"closed\" | \"opening\" | \"holding\" | \"closing\";\n\n/**\n * Which side the pill grows towards. The launcher is anchored top-right, so\n * the natural direction is leftwards, away from its own edge — but it is\n * draggable and its position persists, so a reader who parked it near the left\n * edge would otherwise get a permanently truncated pill.\n */\ntype LauncherPillDirection = \"left\" | \"right\";\n\n/**\n * Whether the reader actually got a pill. `suppressed` is the honest-degrade\n * case: neither side had room, so the dot and the beat fire alone.\n */\ntype LauncherPillOutcome = \"shown\" | \"suppressed\";\n\ntype CoreStatusSummary = Readonly<{\n label: string;\n state: \"connected\" | \"connecting\" | \"disconnected\" | \"error\" | \"unavailable\";\n description: string;\n}>;\n\ntype InspectorColorScheme = \"light\" | \"dark\";\n\nconst EDGE_MARGIN = 16;\n/** HUD card plus the hover bridge. Used to pick left vs right. */\nconst LAUNCHER_HUD_WIDTH = 258;\n/**\n * One page-load preview of the launcher's feature HUD.\n *\n * The card arrives after the host page has had a beat to settle. Its feature\n * contents then arrive from top to bottom, stay readable, and leave together.\n * Nothing is persisted: a new Inspector element means a new preview.\n */\nconst LAUNCHER_HUD_INTRO_MS = {\n delay: 500,\n duration: 3400,\n waterfallStart: 180,\n waterfallStagger: 170,\n waterfallDuration: 300,\n blockedRetry: 250,\n} as const;\n\n/** Return the staggered reveal delay for one launcher HUD layer. */\nconst launcherHudWaterfallDelay = (introIndex: number): string =>\n `${\n LAUNCHER_HUD_INTRO_MS.waterfallStart +\n introIndex * LAUNCHER_HUD_INTRO_MS.waterfallStagger\n }ms`;\nconst DRAG_THRESHOLD = 6;\nconst MIN_WINDOW_WIDTH = 880;\nconst MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;\nconst MIN_WINDOW_HEIGHT = 480;\nconst INSPECTOR_STORAGE_KEY = \"cpk:inspector:state\";\nconst ANNOUNCEMENT_URL = \"https://cdn.copilotkit.ai/announcements.json\";\n// The launcher keeps its current touch target on compact screens and grows to\n// an exactly 20% larger desktop cap. `box-sizing` makes these OUTER sizes.\nconst LAUNCHER_MIN_SIZE = 51.84;\nconst LAUNCHER_MAX_SIZE = 62.208;\nconst DEFAULT_BUTTON_SIZE: Size = {\n width: LAUNCHER_MIN_SIZE,\n height: LAUNCHER_MIN_SIZE,\n};\nconst DEFAULT_WINDOW_SIZE: Size = { width: 960, height: 740 };\nconst DOCKED_LEFT_WIDTH = 720;\nconst MAX_AGENT_EVENTS = 200;\nconst INTERACTIVE_FOCUS_BASE_STYLE =\n \"outline-style:solid;outline-width:2px;outline-color:transparent;outline-offset:2px;cursor:pointer;\";\n// Cap on banner impressions held while waiting for the runtime handshake, so a\n// runtime that never connects can't accumulate an unbounded queue.\nconst MAX_PENDING_BANNER_VIEWED = 20;\nconst MAX_TOTAL_EVENTS = 500;\nconst INTELLIGENCE_SIGNUP_URL = \"https://intelligence.copilotkit.ai\";\nconst TALK_TO_ENGINEER_URL = \"https://www.copilotkit.ai/talk-to-an-engineer\";\n// Label for the Capabilities tab (client-authoritative dev experimentation\n// surface: toggle frontend tools + A2UI catalog components on/off, enforced\n// immediately via core.setToolEnabled / core.setCatalogComponentEnabled).\n// Renameable — keep the display string in this one place.\nconst CAPABILITIES_TAB_LABEL = \"Capabilities\";\n\nfunction createPlaygroundThreadId(): string {\n return globalThis.crypto?.randomUUID?.() ?? `playground-${Date.now()}`;\n}\n\nconst THREADS_DOCS_URL = \"https://docs.copilotkit.ai/threads\";\nconst SELF_HOSTED_INTELLIGENCE_URL =\n \"https://docs.copilotkit.ai/intelligence/self-hosting\";\n\n// ── The Intelligence story on Home ────────────────────────────────────────\n//\n// A condensed cut of the six-phase animation on the Intelligence home page\n// (`react-shell/src/home/learning-sample*`). Three beats, not six: the two\n// thread beats there open on the agent booking the wrong meeting, which is a\n// poor first frame for a card whose job is to argue for the product, and the\n// handoff beat only bridges between them.\n//\n// What is kept is the machinery a developer cannot hand-roll — many threads\n// collapsing into one pattern — then the artefact it produces, then the loop.\n// `meeting-scheduling.md` recurs in all three on purpose: the same filename\n// appearing in the last beat's badge is what turns the closing diagram from a\n// claim into something checkable.\n//\n// Durations are the shipped values for the corresponding phases upstream, so\n// the pacing stays recognisable to anyone who has seen the original.\n// Each beat owns its own two sentences, and the card shows exactly the pair\n// that belongs to the picture on screen. An earlier version argued for Threads\n// in prose while the animation showed Learning — two half-claims sitting next\n// to each other, neither supporting the other. Bound together they read as one\n// chain: your users' threads → the pattern in them → the file → it applies\n// itself.\n//\n// `lead` is the sentence that has to land on its own. `support` earns it.\n// Nothing else: a third line here is what makes this card feel crowded.\nconst INTELLIGENCE_STORY_BEATS = [\n {\n id: \"threads\",\n label: \"Rich Threads\",\n // Roughly 24 words of copy plus a picture to take in. The upstream timings\n // were written for a page where the animation carried itself; here it has\n // to be read, so every beat gets time for two sentences at a comfortable\n // pace rather than a glance. The rail is there for anyone who wants to\n // move faster.\n duration: 6_500,\n // \"Your users\" means the end users of the developer's app, not the\n // developer. That is what the platform means too: `identifyUser` resolves\n // one `{id, name}` per request from the app, and a thread carries\n // `end_user_id` — a column renamed from `user_id` precisely because the\n // old name \"caused repeated misdiagnosis\" against control-plane users.\n //\n // No count in the claim. A developer wiring this up locally has no users\n // yet, and \"thousands\" would read as a lie on day one while still being\n // true at scale. \"All the others\" holds in both cases.\n lead: \"You only see this session. Your users have all the others.\",\n // \"Rich Threads\" is the product's own name for the durable ones, and the\n // distinction is the sale: the Inspector's Threads tab already lists local\n // ones that die on reload.\n support:\n \"Rich Threads keep every conversation and its state, so you can open the one that broke instead of reproducing it.\",\n },\n {\n id: \"learning\",\n label: \"Automatic Learning\",\n duration: 6_000,\n lead: \"Your users already told you what to fix.\",\n // Insights are a first-class concept in the product, and the evidence link\n // is the credibility hook for a sceptical developer: a claim you can open,\n // not a model's opinion. Learning's own onboarding leads with \"46 evidence\n // refs\" across \"12 Threads\" for exactly this reason.\n support:\n \"Automatic Learning reads the runs behind those threads and finds the patterns — every Insight linked to the messages that back it.\",\n },\n {\n id: \"skill\",\n label: \"Skills\",\n duration: 5_500,\n lead: \"An Insight becomes a skill you own.\",\n // The review step is real (candidates land at pending_review and a human\n // approves), but it is sold as control rather than as reassurance. The\n // earlier wording — \"nothing reaches your agent until you approve it\" —\n // answered a fear the reader had not voiced yet, which reads as a defence\n // and plants the worry it deflects. Ownership is the same fact, stated as\n // a feature: a readable file you review, edit and ship.\n support:\n \"A SKILL.md built from that evidence — yours to review, edit and ship with your project.\",\n },\n {\n id: \"intelligence\",\n // Named after the product, not after the mechanism. The other three tabs\n // are the parts; this one is the whole, so the rail reads \"Threads ·\n // Learning · Skills · Intelligence\" — the pieces, then the thing that\n // unites them. \"Reuse\" named neither a surface nor an outcome.\n label: \"Intelligence\",\n duration: 6_000,\n lead: \"Every round of real use leaves your agent better.\",\n // Deliberately NOT \"Skills apply it for you\". The platform does not apply\n // skills at run time — there is no run-time read of published skills, only\n // a bundle the developer pulls down with `copilotkit skills download`.\n // Claiming automatic application would be a promise the product does not\n // keep, and the first developer to check would stop believing the rest.\n support:\n \"Approve a skill, pull it into your project, and the next run starts from what already worked.\",\n },\n] as const;\n\n/**\n * The threads the first beat shows.\n *\n * One of them failed, because that is the row a developer actually wants and\n * the reason durable threads are worth paying for. It is a user's thread that\n * went wrong, not a demo of our agent failing — the distinction matters for a\n * card that has to argue for the product.\n */\nconst INTELLIGENCE_STORY_THREADS = [\n { title: \"Reschedule the Tuesday sync\", meta: \"2 min ago\", failed: false },\n {\n title: \"Book time with the design team\",\n meta: \"18 min ago\",\n failed: false,\n },\n { title: \"Booked the wrong slot\", meta: \"Needs a look\", failed: true },\n] as const;\n\n/** The three rules the story derives, shown verbatim across all three beats. */\nconst INTELLIGENCE_STORY_RULES = [\n \"Check both calendars.\",\n \"Propose several times.\",\n \"Ask before booking.\",\n] as const;\n\n/**\n * The raw thread signals the first beat collapses into those rules.\n *\n * Kept at real-message length and varied on purpose — these have to read as\n * things people actually typed, not as three tidy bullet points. The longest\n * one truncates in a narrow panel, which is honest: it is an excerpt.\n */\nconst INTELLIGENCE_STORY_SIGNALS = [\n \"Check our calendars and find a time for both of us.\",\n \"Could you share a few options?\",\n \"Ask me before you book it.\",\n] as const;\n\n// A skill really is a directory holding a SKILL.md, so the path shows both the\n// skill's name and the document the platform actually stores.\nconst INTELLIGENCE_STORY_SKILL_FILE = \"meeting-scheduling/SKILL.md\";\n\n/**\n * How long the copied confirmation stands before the button invites a second\n * press. Longer than the 2s the Threads setup prompt uses, because this state\n * also carries an instruction that has to be read, not just an acknowledgement.\n */\nconst PROMPT_COPY_RESET_MS = 4_000;\n\n// The real pipeline, named the way the product names it: threads produce\n// evidence-backed Insights, Insights produce Skill candidates, a human\n// approves, and the approved set is what the project pulls in. `Lightbulb` is\n// Learning's own icon for an Insight, so the two surfaces agree.\nconst INTELLIGENCE_STORY_CHAIN = [\n {\n icon: \"MessagesSquare\",\n name: \"Threads\",\n detail: \"Every conversation\",\n },\n { icon: \"Lightbulb\", name: \"Insights\", detail: \"Backed by evidence\" },\n { icon: \"FileText\", name: \"Skills\", detail: \"You approve\" },\n { icon: \"Wand2\", name: \"Your agent\", detail: \"Starts from what worked\" },\n] as const;\nconst THREADS_EXAMPLE_OVERVIEW_VIDEO_URL =\n \"https://cdn.copilotkit.ai/corp-site/videos/copilotkit-generative-ui-agentic-frontend-demo.webm\";\nconst THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK =\n \"The demo video is unavailable. Use the example threads to explore Conversation, AG-UI Events, and State.\";\nconst THREADS_LOCKED_VIDEO_URL =\n \"https://www.loom.com/embed/79817778d29e490c97225127d2f17b3a?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true\";\nconst LEARNING_LOCKED_VIDEO_URL =\n \"https://www.loom.com/embed/2978fbfe42324e509057ac5fd46b7a70?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true\";\ntype LockedFeatureOutlineItem = Readonly<{\n icon: LucideIconName;\n title: string;\n description: string;\n}>;\nconst THREADS_LOCKED_FEATURE_OUTLINE = [\n {\n icon: \"MessagesSquare\",\n title: \"The whole conversation comes back\",\n description:\n \"Rich Threads restores the complete interaction, not just a transcript. Messages, tool calls, shared state, generated interfaces, and supported files return together when a user reopens the thread.\",\n },\n {\n icon: \"LayoutGrid\",\n title: \"Generated UI stays in the thread\",\n description:\n \"Cards, charts, A2UI surfaces, MCP Apps, and tool renderers remain part of the conversation. The demo above shows a generated spending chart returning after a reload.\",\n },\n {\n icon: \"RefreshCw\",\n title: \"Return without starting over\",\n description:\n \"Users can move across sessions and devices while thread lists stay synchronized across open tabs. Rich Threads replays missed events and reconnects to work already in progress.\",\n },\n {\n icon: \"Server\",\n title: \"Infrastructure you do not have to rebuild\",\n description:\n \"CopilotKit handles durable event storage, replay, synchronization, lifecycle APIs, and thread locks on one portable AG-UI history model. Use CopilotKit Cloud or deploy Intelligence in your own Kubernetes environment.\",\n },\n] as const satisfies ReadonlyArray<LockedFeatureOutlineItem>;\nconst LEARNING_LOCKED_FEATURE_OUTLINE = [\n {\n icon: \"History\",\n title: \"Memory across sessions\",\n description:\n \"Keep useful facts, preferences, and decisions after the thread closes. Learning gives future conversations the context they need without asking users to repeat themselves.\",\n },\n {\n icon: \"Search\",\n title: \"Recall by meaning\",\n description:\n \"Surface relevant memories by what they mean, not by an exact phrase. Your agent can bring the right context into a new interaction even when the user asks in a completely different way.\",\n },\n {\n icon: \"Layers\",\n title: \"Built-in structure\",\n description:\n \"Turn raw interactions into organized topical, episodic, and operational knowledge. Learning separates enduring facts from individual experiences and useful instructions automatically.\",\n },\n {\n icon: \"Eye\",\n title: \"Full visibility\",\n description:\n \"Inspect exactly what your agent learned and trace each memory back to the threads that shaped it. Review the stored context instead of treating memory like a black box.\",\n },\n] as const satisfies ReadonlyArray<LockedFeatureOutlineItem>;\nconst THREADS_EXAMPLE_TOUR_STORAGE_KEY =\n \"cpk:inspector:threads-example-tour:v1\";\nconst THREADS_EXAMPLE_AGENT_ID = \"threads-feature\";\n\ntype ThreadServiceStatus = \"available\" | \"unavailable\" | \"unknown\" | \"error\";\ntype ThreadsExampleOverviewVideoState =\n | \"deferred\"\n | \"ready\"\n | \"playing\"\n | \"failed\";\ntype HomeFeaturePromptCopyState = \"idle\" | \"copied\" | \"error\";\ntype ThreadsExampleOverviewVideoListeners = Readonly<{\n loadeddata: EventListener;\n play: EventListener;\n pause: EventListener;\n error: EventListener;\n}>;\n\ntype ThreadStoreStatus = Readonly<{\n error: Error | null;\n isLoading: boolean;\n}>;\n\n/** Keep one row per thread id when flattening per-agent stores. */\nfunction uniqueThreadsById(threads: ɵThread[]): ɵThread[] {\n const seen = new Set<string>();\n const unique: ɵThread[] = [];\n for (const thread of threads) {\n if (seen.has(thread.id)) {\n continue;\n }\n seen.add(thread.id);\n unique.push(thread);\n }\n return unique;\n}\n\nfunction flattenThreadsByAgent(\n threadsByAgent: Map<string, ɵThread[]>,\n): ɵThread[] {\n return uniqueThreadsById(Array.from(threadsByAgent.values()).flat());\n}\n\n/**\n * Selects the Thread store status with a stable object identity so loading-only\n * transitions reach one of the Inspector's two existing store subscriptions.\n */\nfunction createThreadStoreStatusSelector(): (\n state: ReturnType<ɵThreadStore[\"getState\"]>,\n) => ThreadStoreStatus {\n let previousError: Error | null | undefined;\n let previousIsLoading: boolean | undefined;\n let previousStatus: ThreadStoreStatus | undefined;\n\n return (state) => {\n const error = ɵselectThreadsError(state);\n const isLoading = ɵselectThreadsIsLoading(state);\n if (\n previousStatus &&\n previousError === error &&\n previousIsLoading === isLoading\n ) {\n return previousStatus;\n }\n\n previousError = error;\n previousIsLoading = isLoading;\n previousStatus = { error, isLoading };\n return previousStatus;\n };\n}\n\ntype InspectorAgentEventType =\n | \"RUN_STARTED\"\n | \"RUN_FINISHED\"\n | \"RUN_ERROR\"\n | \"STEP_STARTED\"\n | \"STEP_FINISHED\"\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 | \"ACTIVITY_SNAPSHOT\"\n | \"ACTIVITY_DELTA\";\n\nconst AGENT_EVENT_TYPES: readonly InspectorAgentEventType[] = [\n \"RUN_STARTED\",\n \"RUN_FINISHED\",\n \"RUN_ERROR\",\n \"STEP_STARTED\",\n \"STEP_FINISHED\",\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 \"ACTIVITY_SNAPSHOT\",\n \"ACTIVITY_DELTA\",\n] as const;\n\nconst THREADS_LOCKED_COPY = {\n heading:\n \"Production-grade chat threads without the complexity. Self hostable.\",\n description:\n \"Chat threads that go beyond text with generative UI and multimodal inputs, built to replay missed events and stay in sync across tabs, sessions, and devices.\",\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 toolCallId?: string;\n /** Populated for role=\"activity\" messages (Generative UI). */\n activityType?: string;\n};\n\nconst EMPTY_INSPECTOR_MESSAGES: InspectorMessage[] = [];\n\nfunction textFromUnknownContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const part of content) {\n if (typeof part === \"string\") {\n parts.push(part);\n continue;\n }\n if (typeof part === \"object\" && part !== null && \"text\" in part) {\n const text = part.text;\n if (typeof text === \"string\") parts.push(text);\n }\n }\n return parts.join(\"\");\n }\n if (typeof content === \"object\" && content !== null && \"text\" in content) {\n const text = content.text;\n if (typeof text === \"string\") return text;\n }\n return \"\";\n}\n\ntype InspectorToolDefinition = {\n agentId: string;\n name: string;\n description?: string;\n parameters?: unknown;\n type: \"handler\" | \"renderer\";\n};\n\n// ─── Capabilities tab view-models ────────────────────────────────────────────\n// A single toggle row. `key` is the stable identity used as a Lit list key; for\n// tools it is `${agentId}:${name}` (agentId \"\" for global tools), for catalog\n// components it is the component name.\ntype CapabilityToolRow = {\n key: string;\n name: string;\n description?: string;\n agentId?: string;\n enabled: boolean;\n};\n\n// Minimal structural view of CopilotKitCore that the pure helper needs, so\n// buildCapabilityRows is trivially unit-testable with a plain object. Method\n// names MUST match the A1 contract exactly.\ntype CapabilityToolSource = {\n tools?: ReadonlyArray<{\n name: string;\n description?: string;\n agentId?: string;\n }>;\n isToolEnabled: (name: string, agentId?: string) => boolean;\n};\n\n/**\n * Map core.tools (the registry INCLUDING disabled tools) into Capabilities-tab\n * frontend-tool rows. Pure: no DOM, no `this`. Reads current on/off state from\n * core.isToolEnabled(name, agentId?) per the A1 contract.\n */\nfunction buildCapabilityRows(core: CapabilityToolSource): CapabilityToolRow[] {\n const rows: CapabilityToolRow[] = [];\n for (const tool of core.tools ?? []) {\n const agentId = tool.agentId ?? \"\";\n const key = `${agentId}:${tool.name}`;\n rows.push({\n key,\n name: tool.name,\n description: tool.description,\n agentId: tool.agentId,\n enabled: core.isToolEnabled(tool.name, tool.agentId),\n });\n }\n return rows.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\ntype InspectorEvent = {\n id: string;\n agentId: string;\n type: InspectorAgentEventType;\n timestamp: number;\n payload: SanitizedValue;\n};\n\n// ─── Thread details types ────────────────────────────────────────────────────\n\nexport type ThreadDebuggerProviderLoadOptions = {\n signal: AbortSignal;\n};\n\nexport type ThreadDebuggerToolCall = {\n id: string;\n name: string;\n args: string | Record<string, unknown>;\n};\n\nexport type ThreadDebuggerMessage = {\n id: string;\n role: string;\n content?: string;\n toolCalls?: ThreadDebuggerToolCall[];\n toolCallId?: string;\n /** Present when role === \"activity\" (Generative UI output). */\n activityType?: string;\n};\n\nexport type ThreadDebuggerEvent = {\n type: string;\n timestamp: string | number;\n payload?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type ThreadDebuggerMetadata = {\n id: string;\n name?: string | null;\n agentId?: string | null;\n endUserId?: string | null;\n createdById?: string | null;\n status?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n};\n\nexport type ThreadDebuggerProvider = {\n getThreadMetadata?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerMetadata | null>;\n getMessages?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerMessage[]>;\n getEvents?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerEvent[]>;\n getState?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<Record<string, unknown> | null>;\n};\n\ninterface ConversationUser {\n id: string;\n type: \"user\";\n content: string;\n createdAt: string;\n}\n\ninterface ConversationAssistant {\n id: string;\n type: \"assistant\";\n content: string;\n createdAt: string;\n}\n\ninterface ConversationToolCall {\n id: string;\n type: \"tool_call\";\n toolName: string;\n toolCallId: string;\n arguments: Record<string, unknown>;\n result: Record<string, unknown> | null;\n createdAt: string;\n groupId?: string;\n}\n\ninterface ConversationReasoning {\n id: string;\n type: \"reasoning\";\n duration: string;\n createdAt: string;\n}\n\ninterface ConversationStateUpdate {\n id: string;\n type: \"state_update\";\n createdAt: string;\n}\n\ninterface ConversationAgentResponded {\n id: string;\n type: \"agent_responded\";\n createdAt: string;\n}\n\ninterface ConversationGenerativeUIItem {\n id: string;\n type: \"generative-ui\";\n activityType: string;\n createdAt: string;\n}\n\ninterface ToolCallGroup {\n type: \"tool_call_group\";\n id: string;\n items: ConversationToolCall[];\n}\n\ntype ConversationItem =\n | ConversationUser\n | ConversationAssistant\n | ConversationToolCall\n | ConversationReasoning\n | ConversationStateUpdate\n | ConversationAgentResponded\n | ConversationGenerativeUIItem;\n\ntype RenderItem = ConversationItem | ToolCallGroup;\n\ninterface ApiAgentEvent {\n type: string;\n timestamp: string | number;\n payload: Record<string, unknown>;\n sourceIndex?: number;\n rawEvent?: ThreadDebuggerEvent;\n}\n\ntype ThreadDetailsTab = \"timeline\" | \"state\" | \"raw-events\";\ntype ThreadDetailsPanelCacheSlot = ThreadDetailsTab | \"timeline-fallback\";\n\ntype TimelineItemKind =\n | \"message\"\n | \"tool\"\n | \"state\"\n | \"run\"\n | \"event\"\n | \"warning\";\n\ntype TimelineItem = {\n id: string;\n messageId?: string;\n kind: TimelineItemKind;\n title: string;\n body?: string;\n timestamp: string | number;\n sourceIndex: number;\n severity?: \"warning\" | \"error\";\n details?: Record<string, unknown>;\n};\n\ntype RuntimeEventsFetchResult =\n | { status: \"available\"; events: ThreadDebuggerEvent[] }\n | { status: \"not-available\" };\n\ntype RuntimeStateFetchResult =\n | { status: \"available\"; state: Record<string, unknown> | null }\n | { status: \"not-available\" };\n\ntype ExampleThread = ɵThread & { isExample: true };\n\ntype ExampleThreadDetails = {\n messages: ThreadDebuggerMessage[];\n events: ThreadDebuggerEvent[];\n state: Record<string, unknown>;\n};\n\nconst THREADS_EXAMPLE_THREADS: ExampleThread[] = [\n {\n id: \"example-realtime-sync\",\n name: \"Realtime thread sync\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-08T16:00:00.000Z\",\n updatedAt: \"2026-07-08T16:30:00.000Z\",\n isExample: true,\n },\n {\n id: \"example-manage-history\",\n name: \"Manage saved conversations\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-07T17:45:00.000Z\",\n updatedAt: \"2026-07-07T18:15:00.000Z\",\n isExample: true,\n },\n {\n id: \"example-inspect-runs\",\n name: \"Inspect durable run history\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-06T20:15:00.000Z\",\n updatedAt: \"2026-07-06T20:45:00.000Z\",\n isExample: true,\n },\n];\n\n/** Map Sam's fixed example IDs to a closed telemetry vocabulary. */\nfunction getExampleKind(threadId: string): ExampleKind | undefined {\n switch (threadId) {\n case \"example-realtime-sync\":\n return \"realtime_sync\";\n case \"example-manage-history\":\n return \"manage_history\";\n case \"example-inspect-runs\":\n return \"inspect_runs\";\n default:\n return undefined;\n }\n}\n\nconst THREADS_EXAMPLE_DETAILS: Record<string, ExampleThreadDetails> = {\n \"example-realtime-sync\": {\n messages: [\n {\n id: \"example-sync-user\",\n role: \"user\",\n content: \"Resume the checkout support thread from yesterday.\",\n },\n {\n id: \"example-sync-assistant\",\n role: \"assistant\",\n content:\n \"I found the saved thread, restored the cart state, and continued from the latest user message.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-08T16:30:00.000Z\",\n payload: {\n threadId: \"example-realtime-sync\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"MESSAGES_SNAPSHOT\",\n timestamp: \"2026-07-08T16:30:01.000Z\",\n payload: {\n messageCount: 6,\n source: \"thread-history\",\n },\n },\n {\n type: \"STATE_SNAPSHOT\",\n timestamp: \"2026-07-08T16:30:02.000Z\",\n payload: {\n cartId: \"cart_demo_42\",\n checkoutStep: \"shipping\",\n resumed: true,\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-08T16:30:04.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n cartId: \"cart_demo_42\",\n checkoutStep: \"shipping\",\n userIntent: \"resume_previous_checkout\",\n persistedThread: true,\n },\n },\n \"example-manage-history\": {\n messages: [\n {\n id: \"example-history-user\",\n role: \"user\",\n content: \"Rename this saved support conversation for the handoff.\",\n },\n {\n id: \"example-history-assistant\",\n role: \"assistant\",\n content:\n \"Renamed the thread and kept the prior messages available for the next session.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-07T18:15:00.000Z\",\n payload: {\n threadId: \"example-manage-history\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"CUSTOM_EVENT\",\n timestamp: \"2026-07-07T18:15:01.000Z\",\n payload: {\n action: \"thread_renamed\",\n previousName: \"Untitled\",\n name: \"Billing escalation handoff\",\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-07T18:15:03.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n name: \"Billing escalation handoff\",\n savedMessages: 14,\n lastHandoff: \"support-team\",\n },\n },\n \"example-inspect-runs\": {\n messages: [\n {\n id: \"example-inspect-user\",\n role: \"user\",\n content: \"Why did the assistant recommend the enterprise plan?\",\n },\n {\n id: \"example-inspect-assistant\",\n role: \"assistant\",\n content:\n \"The recommendation came from the account size, SSO requirement, and audit-log constraint in state.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-06T20:45:00.000Z\",\n payload: {\n threadId: \"example-inspect-runs\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"TOOL_CALL_START\",\n timestamp: \"2026-07-06T20:45:01.000Z\",\n payload: {\n toolCallId: \"call_account_lookup\",\n toolName: \"lookupAccount\",\n },\n },\n {\n type: \"TOOL_CALL_RESULT\",\n timestamp: \"2026-07-06T20:45:02.000Z\",\n payload: {\n toolCallId: \"call_account_lookup\",\n seats: 220,\n requiresSso: true,\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-06T20:45:04.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n accountTier: \"growth\",\n seats: 220,\n requiresSso: true,\n auditLogsRequired: true,\n },\n },\n};\n\nconst THREADS_EXAMPLE_TOUR_STEPS: ReadonlyArray<{\n tab: ThreadDetailsTab;\n label: string;\n title: string;\n body: string;\n}> = [\n {\n tab: \"timeline\",\n label: \"Conversation\",\n title: \"Read the run as a story\",\n body: \"Read messages and tool calls as a conversation. Switch to the event timeline to inspect state changes and run markers.\",\n },\n {\n tab: \"raw-events\",\n label: \"AG-UI Events\",\n title: \"Drop into the protocol payloads\",\n body: \"Raw events show the exact AG-UI stream behind the timeline when you need to verify ordering or payload shape.\",\n },\n {\n tab: \"state\",\n label: \"State\",\n title: \"Check the durable state\",\n body: \"The state tab shows the saved values that make a thread resumable across sessions.\",\n },\n];\n\ntype ExampleTourTelemetryPair = Readonly<{\n tour_step: ExampleTourStep;\n tour_tab: ExampleTourTab;\n}>;\n\n/** Return only the three supported tour step/tab pairs. */\nfunction getExampleTourTelemetryPair(\n index: number,\n): ExampleTourTelemetryPair | undefined {\n switch (index) {\n case 0:\n return { tour_step: 1, tour_tab: \"timeline\" };\n case 1:\n return { tour_step: 2, tour_tab: \"raw-events\" };\n case 2:\n return { tour_step: 3, tour_tab: \"state\" };\n default:\n return undefined;\n }\n}\n\n/** Convert rendered action placement to its stable telemetry key. */\nfunction getMetadataActionPlacement(\n placement: \"threads-footer\" | \"locked\",\n): MetadataActionPlacement {\n return placement === \"threads-footer\" ? \"threads_footer\" : \"threads_locked\";\n}\n\n// ─── JSON syntax highlighter ─────────────────────────────────────────────────\n// Inline-styled so shadow DOM encapsulation preserves colors when the output\n// is injected via unsafeHTML. Only for structured data — never raw user HTML.\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\n// Memoize highlight output by payload reference. Tab switches cause Lit to\n// re-render the active panel from scratch, and the JSON.stringify + regex\n// pass below is by far the most expensive thing in the events / state\n// panels (potentially MB of agent state). Caching by object reference\n// turns subsequent renders of an unchanged event list into near-zero JS work.\nconst highlightedJsonCache = new WeakMap<object, string>();\n\nfunction highlightedJson(obj: unknown): string {\n if (typeof obj === \"object\" && obj !== null) {\n const cached = highlightedJsonCache.get(obj);\n if (cached !== undefined) return cached;\n }\n const json = JSON.stringify(obj, null, 2);\n if (!json) return \"\";\n const parts: string[] = [];\n let lastIndex = 0;\n const re =\n /(\"(?:\\\\u[a-fA-F0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(?:\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(json)) !== null) {\n parts.push(escapeHtml(json.slice(lastIndex, match.index)));\n const m = match[0];\n let token = \"num\";\n if (m.startsWith('\"')) {\n token = m.trimEnd().endsWith(\":\") ? \"key\" : \"str\";\n } else if (m === \"true\" || m === \"false\") {\n token = \"bool\";\n } else if (m === \"null\") {\n token = \"nil\";\n }\n parts.push(\n `<span class=\"cpk-json-token cpk-json-token--${token}\">${escapeHtml(m)}</span>`,\n );\n lastIndex = match.index + m.length;\n }\n parts.push(escapeHtml(json.slice(lastIndex)));\n const result = parts.join(\"\");\n if (typeof obj === \"object\" && obj !== null) {\n highlightedJsonCache.set(obj, result);\n }\n return result;\n}\n\nfunction coerceJsonValue(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return value;\n }\n\n const looksJson =\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"));\n if (!looksJson) {\n return value;\n }\n\n try {\n return JSON.parse(trimmed);\n } catch {\n return value;\n }\n}\n\nfunction renderHighlightedJsonBlock(\n value: unknown,\n options: { maxHeight?: string } = {},\n) {\n const parsed = coerceJsonValue(value);\n const style = options.maxHeight\n ? `max-height:${options.maxHeight}`\n : undefined;\n return html`<pre class=\"cpk-json-block\" style=${style || nothing}>\n${unsafeHTML(highlightedJson(parsed))}</pre\n >`;\n}\n\nfunction humanizeEventType(type: string): string {\n const words = type\n .trim()\n .split(/[_\\s]+/)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n if (words.length === 0) return \"Event\";\n const [first = \"event\", ...rest] = words;\n return [`${first.charAt(0).toUpperCase()}${first.slice(1)}`, ...rest].join(\n \" \",\n );\n}\n\nfunction messageTitle(role: string): string {\n const normalized = role.trim() || \"message\";\n const label = `${normalized.charAt(0).toUpperCase()}${normalized.slice(1).toLowerCase()}`;\n return `${label} message`;\n}\n\nfunction eventCategory(\n type: string,\n): \"message\" | \"tool\" | \"state\" | \"run\" | \"error\" | \"event\" {\n if (type === \"RUN_ERROR\" || type === \"ERROR\") return \"error\";\n if (type.startsWith(\"TEXT_MESSAGE\")) return \"message\";\n if (type.startsWith(\"TOOL_CALL\")) return \"tool\";\n if (type.startsWith(\"STATE\") || type.startsWith(\"MESSAGES\")) return \"state\";\n if (type.startsWith(\"RUN_\") || type.startsWith(\"STEP_\")) return \"run\";\n return \"event\";\n}\n\nfunction formatTimestamp(ts: string | number): string {\n const date = typeof ts === \"number\" ? new Date(ts) : new Date(ts);\n if (Number.isNaN(date.getTime())) return \"\";\n const ms = date.getMilliseconds().toString().padStart(3, \"0\");\n return (\n date.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n }) +\n \".\" +\n ms\n );\n}\n\nfunction formatRelativeTimestamp(ts: string | number): string {\n const date = new Date(ts);\n if (Number.isNaN(date.getTime())) return \"\";\n\n const elapsedSeconds = Math.max(\n 1,\n Math.floor((Date.now() - date.getTime()) / 1_000),\n );\n if (elapsedSeconds < 60) {\n return `${elapsedSeconds} ${elapsedSeconds === 1 ? \"second\" : \"seconds\"} ago`;\n }\n\n const elapsedMinutes = Math.floor(elapsedSeconds / 60);\n return `${elapsedMinutes} ${elapsedMinutes === 1 ? \"minute\" : \"minutes\"} ago`;\n}\n\n/**\n * Lit's constructable stylesheets belong to the document that created them.\n * These child elements move between the app and pop-out documents, so keep\n * their styles as shadow-root style nodes that travel with the live element.\n */\nabstract class PortableLitElement extends LitElement {\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n const elementClass = this.constructor as unknown as {\n elementStyles: readonly (CSSStyleSheet | { cssText: string })[];\n shadowRootOptions: ShadowRootInit;\n };\n const renderRoot =\n this.shadowRoot ?? this.attachShadow(elementClass.shadowRootOptions);\n\n for (const style of elementClass.elementStyles) {\n const styleElement = this.ownerDocument.createElement(\"style\");\n styleElement.textContent =\n \"cssText\" in style\n ? style.cssText\n : Array.from(style.cssRules, (rule) => rule.cssText).join(\"\");\n renderRoot.append(styleElement);\n }\n\n return renderRoot;\n }\n}\n\n// ─── cpk-thread-list ────────────────────────────────────────────────────────\n\nclass CpkThreadList extends PortableLitElement {\n static properties = {\n threads: { attribute: false },\n selectedThreadId: { attribute: false },\n inAppThreadId: { attribute: false },\n errorMessage: { attribute: false },\n suppressEmptyState: { attribute: false },\n _query: { state: true },\n };\n threads: ɵThread[] = [];\n selectedThreadId: string | null = null;\n inAppThreadId: string | null = null;\n /**\n * Non-null when the underlying thread store reported a load error\n * (REST list rejection, Phoenix subscribe failure, retry exhaustion).\n * Surfaced inline so users see a real error state instead of stale or\n * empty data with no indication of what went wrong.\n */\n errorMessage: string | null = null;\n suppressEmptyState = false;\n private _query = \"\";\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .cpk-tl {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: #f7f7f9;\n }\n\n /* ── Search ── */\n .cpk-tl__search {\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n\n .cpk-tl__search-input {\n width: 100%;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .cpk-tl__search-input:focus {\n border-color: #bec2ff;\n }\n\n /* ── List ── */\n .cpk-tl__list {\n flex: 1;\n overflow-y: auto;\n }\n\n /* ── Thread item ── */\n .cpk-tl__item {\n appearance: none;\n display: block;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n border: 0;\n border-radius: 0;\n padding: 11px 13px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n border-bottom: 1px solid #e9e9ef;\n border-left: 3px solid transparent;\n transition: background 0.1s;\n }\n\n .cpk-tl__item:hover {\n background: #ffffff;\n }\n\n .cpk-tl__item--active {\n background: #bec2ff1a;\n border-left-color: #bec2ff;\n }\n\n .cpk-tl__item--active:hover {\n background: #bec2ff33;\n }\n\n .cpk-tl__item:focus-visible {\n outline-color: #5558b2;\n outline-offset: -2px;\n outline-style: solid;\n outline-width: 2px;\n }\n\n .cpk-tl__row1 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 3px;\n }\n\n .cpk-tl__name {\n font-size: 12px;\n font-weight: 500;\n color: #010507;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-tl__name--unnamed {\n color: #68686e;\n font-style: italic;\n font-weight: 400;\n }\n\n .cpk-tl__time {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-tl__meta {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .cpk-tl__pill {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n background: #eee6fe;\n color: #57575b;\n }\n\n .cpk-tl__pill--example {\n background: rgba(133, 236, 206, 0.22);\n color: #087653;\n }\n\n .cpk-tl__pill--in-app {\n background: #bec2ff;\n color: #010507;\n }\n\n /* ── Empty state ── */\n .cpk-tl__empty {\n padding: 32px 16px;\n text-align: center;\n color: #68686e;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .cpk-tl__empty-icon {\n color: #c0c0c8;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl {\n background: #15171e;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__search,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__search-input {\n border-color: #464957;\n background: #191c24;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item:hover {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item--active,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item--active:hover {\n background: #292b43;\n border-left-color: #8f93df;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__name {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__name--unnamed,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__time,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__empty {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__pill {\n background: #302b43;\n color: #d8d9ff;\n }\n `;\n\n private relativeTime(dateStr: string): string {\n const date = new Date(dateStr);\n const diffMs = Date.now() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n if (diffSec < 60) return `${diffSec}s ago`;\n const diffMin = Math.floor(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffH = Math.floor(diffMin / 60);\n if (diffH < 24) return `${diffH}h ago`;\n const diffD = Math.floor(diffH / 24);\n return `${diffD}d ago`;\n }\n\n private get filtered(): ɵThread[] {\n const q = this._query.toLowerCase();\n if (!q) return this.threads;\n return this.threads.filter(\n (t) =>\n (t.name?.toLowerCase().includes(q) ?? false) ||\n t.agentId.toLowerCase().includes(q) ||\n t.id.toLowerCase().includes(q),\n );\n }\n\n private onThreadClick(threadId: string): void {\n this.dispatchEvent(\n new CustomEvent(\"threadSelected\", {\n detail: threadId,\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private onSearchInput = (event: Event): void => {\n this._query = (event.target as HTMLInputElement).value;\n };\n\n render() {\n const filtered = this.filtered;\n return html`\n <div class=\"cpk-tl\">\n <!-- Search -->\n <div class=\"cpk-tl__search\">\n <input\n type=\"text\"\n placeholder=\"Search threads…\"\n .value=${this._query}\n @input=${this.onSearchInput}\n class=\"cpk-tl__search-input\"\n />\n </div>\n\n <!-- Thread list -->\n <div class=\"cpk-tl__list\">\n ${filtered.map(\n (thread) => html`\n <button\n type=\"button\"\n aria-current=${\n this.selectedThreadId === thread.id ? \"true\" : nothing\n }\n class=\"cpk-tl__item ${\n this.selectedThreadId === thread.id\n ? \"cpk-tl__item--active\"\n : \"\"\n }\"\n @click=${() => this.onThreadClick(thread.id)}\n >\n <span class=\"cpk-tl__row1\">\n <span\n class=\"cpk-tl__name ${\n !thread.name ? \"cpk-tl__name--unnamed\" : \"\"\n }\"\n >${thread.name ?? \"Untitled\"}</span\n >\n <span class=\"cpk-tl__time\"\n >${this.relativeTime(thread.updatedAt)}</span\n >\n </span>\n <span class=\"cpk-tl__meta\">\n <span class=\"cpk-tl__pill\">${thread.agentId}</span>\n ${\n (thread as Partial<ExampleThread>).isExample\n ? html`\n <span class=\"cpk-tl__pill cpk-tl__pill--example\">Example</span>\n `\n : nothing\n }\n ${\n this.inAppThreadId === thread.id\n ? html`\n <span class=\"cpk-tl__pill cpk-tl__pill--in-app\">In app</span>\n `\n : nothing\n }\n </span>\n </button>\n `,\n )}\n ${\n filtered.length === 0 && !this.suppressEmptyState\n ? html`\n <div class=\"cpk-tl__empty\">\n ${\n this.errorMessage\n ? html`\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-tl__empty-icon\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <div>\n Failed to load threads\n <div\n style=\"font-size:11px;margin-top:4px;color:#c0333a;\"\n >\n ${this.errorMessage}\n </div>\n </div>\n `\n : this.threads.length === 0\n ? html`\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-tl__empty-icon\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n No threads yet\n `\n : html`\n No threads match your search.\n `\n }\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n }\n}\n\n// ─── cpk-thread-inspector ────────────────────────────────────────────────────\n// Renders the selected thread's read-only timeline, state, raw AG-UI events,\n// and compact technical metadata. External hosts provide a ThreadDebuggerProvider;\n// the legacy CopilotKit Inspector wrapper can still pass runtime URL inputs.\nexport class CpkThreadInspector extends PortableLitElement {\n static properties = {\n threadId: { attribute: false },\n showThreadTitle: { type: Boolean, attribute: false },\n provider: { attribute: false },\n thread: { attribute: false },\n runtimeUrl: { attribute: false },\n headers: { attribute: false },\n threadInspectionAvailable: { attribute: false },\n agentStateInput: { attribute: false },\n agentEventsInput: { attribute: false },\n agentMessagesInput: { attribute: false },\n liveMessageVersion: { attribute: false },\n viewInAppMode: { attribute: false },\n viewInAppError: { attribute: false },\n focusMessageId: { attribute: false },\n focusRequestId: { attribute: false },\n tryFromHereAvailable: { attribute: false },\n tryFromHereBusy: { attribute: false },\n tryFromHereError: { attribute: false },\n _tab: { state: true },\n _fetchedMetadata: { state: true },\n _conversation: { state: true },\n _fetchedEvents: { state: true },\n _fetchedState: { state: true },\n _loadingMessages: { state: true },\n _loadingEvents: { state: true },\n _loadingState: { state: true },\n _messagesError: { state: true },\n _eventsError: { state: true },\n _stateError: { state: true },\n _expandedTools: { state: true },\n _expandedMessages: { state: true },\n _expandedTimelineDetails: { state: true },\n _expandedRawEvents: { state: true },\n _showDetailPanel: { state: true },\n _detailPanelWidth: { state: true },\n _eventsNotAvailable: { state: true },\n _stateNotAvailable: { state: true },\n _panelInitializing: { state: true },\n _activatedTabs: { state: true },\n };\n\n /** Whether to render the viewer title. Set false when the embedding page owns its heading. */\n showThreadTitle = true;\n threadId: string | null = null;\n provider: ThreadDebuggerProvider | null = null;\n thread: ThreadDebuggerMetadata | ɵThread | null = null;\n runtimeUrl = \"\";\n headers: Record<string, string> = {};\n threadInspectionAvailable = false;\n agentStateInput: Record<string, unknown> | null = null;\n agentEventsInput: ApiAgentEvent[] = [];\n agentMessagesInput: ReadonlyArray<{\n id?: string;\n role: string;\n contentText: string;\n }> = EMPTY_INSPECTOR_MESSAGES;\n /**\n * Monotonic per-thread counter the parent inspector ticks every time the\n * agent currently running on this thread emits a message change. When this\n * prop changes for the same `threadId`, we re-fetch `/threads/:id/messages`\n * so the conversation view reflects live streaming output.\n */\n liveMessageVersion = 0;\n viewInAppMode: \"hidden\" | \"view\" | \"stop\" = \"hidden\";\n viewInAppError: string | null = null;\n focusMessageId: string | null = null;\n focusRequestId = 0;\n tryFromHereAvailable = false;\n tryFromHereBusy = false;\n tryFromHereError: string | null = null;\n\n private _tab: ThreadDetailsTab = \"timeline\";\n private _showEventTimeline = false;\n private _fetchedMetadata: ThreadDebuggerMetadata | null = null;\n private _conversation: ConversationItem[] = [];\n private _fetchedEvents: ApiAgentEvent[] | null = null;\n private _fetchedState: Record<string, unknown> | null = null;\n private _loadingMessages = false;\n private _loadingEvents = false;\n private _loadingState = false;\n private _messagesError: string | null = null;\n private _eventsError: string | null = null;\n private _stateError: string | null = null;\n private _expandedTools = new Set<string>();\n private _expandedMessages = new Set<string>();\n private _expandedTimelineDetails = new Set<string>();\n private _expandedRawEvents = new Set<string>();\n private _showDetailPanel = false;\n private _detailPanelWidth = 250;\n /** True when the /events endpoint returned 501 — don't fall back to live data. */\n private _eventsNotAvailable = false;\n /** True when the /state endpoint returned 501 — don't fall back to live data. */\n private _stateNotAvailable = false;\n private _scrolledFocusRequestId = 0;\n private _highlightedFocusRequestId = -1;\n /**\n * Briefly true after a tab switch so the active-tab highlight + a generic\n * \"Loading…\" placeholder paint before the heavy per-tab render runs. Without\n * this, large event/conversation lists block the next paint and the user\n * sees the click as unresponsive for seconds.\n */\n private _panelInitializing = false;\n /**\n * Tabs that have been opened at least once for the current thread. Once a\n * tab is activated, its rendered DOM stays mounted (we hide inactive tabs\n * via display:none) so flipping back to it is just a CSS swap rather than\n * tearing down and rebuilding the entire panel from scratch. Without this,\n * switching back to AG-UI Events on a thread with hundreds of events\n * triggers a multi-second DOM-creation pass each time.\n *\n * Reset to {\"timeline\"} when the selected thread changes.\n */\n private _activatedTabs: Set<ThreadDetailsTab> = new Set([\"timeline\"]);\n /**\n * Memoized per-panel templates keyed by the inputs they render from.\n * When the underlying data hasn't changed (same `_conversation` /\n * `_fetchedState` / events array reference, plus expand-state for the\n * conversation panel), we return the previously built TemplateResult.\n * Lit then sees \"same template, same values\" and skips the diff entirely,\n * so re-rendering on tab switch is near-zero work even when the panel\n * content is large. The key is an opaque tuple compared element-wise by\n * reference; if any element flips, the cache misses and rebuilds.\n */\n private _panelTplCache: Map<\n ThreadDetailsPanelCacheSlot,\n { key: readonly unknown[]; tpl: TemplateResult }\n > = new Map();\n private _timelineItemsCache: {\n events: ApiAgentEvent[];\n conversation: ConversationItem[];\n agentMessages: CpkThreadInspector[\"agentMessagesInput\"];\n items: TimelineItem[];\n } | null = null;\n private _liveEventsWithSourceIndexCache: {\n events: ApiAgentEvent[];\n indexedEvents: ApiAgentEvent[];\n } | null = null;\n /**\n * Tracks whether we've fetched events for the current thread yet. Events\n * fetch lazily on first sub-tab click so a large response's JSON.parse\n * doesn't block the main thread when the user only ever cares about the\n * conversation.\n */\n private _eventsFetched = false;\n /**\n * Tracks whether we've fetched state for the current thread yet. Same\n * lazy-load reasoning as `_eventsFetched`.\n */\n private _stateFetched = false;\n private _lastLoadKey: string | null = null;\n private _lastSeenLiveMessageVersion = 0;\n private _metadataAbort: AbortController | null = null;\n private _messagesAbort: AbortController | null = null;\n private _eventsAbort: AbortController | null = null;\n private _stateAbort: AbortController | null = null;\n private _hasConnectedOnce = false;\n private _dividerResizing = false;\n private _dividerPointerId = -1;\n private _dividerStartX = 0;\n private _dividerStartWidth = 0;\n private static nextDomId = 1;\n private readonly domIdPrefix = `cpk-thread-detail-${CpkThreadInspector.nextDomId++}`;\n\n static readonly COLLAPSE_THRESHOLD = 800;\n static readonly TAB_LIST: ReadonlyArray<{\n id: ThreadDetailsTab;\n label: string;\n }> = [\n { id: \"timeline\", label: \"Conversation\" },\n { id: \"raw-events\", label: \"AG-UI Events\" },\n { id: \"state\", label: \"State\" },\n ];\n\n private static providerIds = new WeakMap<ThreadDebuggerProvider, number>();\n private static nextProviderId = 1;\n\n private static providerLoadKey(\n provider: ThreadDebuggerProvider | null,\n ): string {\n if (!provider) return \"provider:none\";\n let id = CpkThreadInspector.providerIds.get(provider);\n if (!id) {\n id = CpkThreadInspector.nextProviderId;\n CpkThreadInspector.nextProviderId += 1;\n CpkThreadInspector.providerIds.set(provider, id);\n }\n return [\n `provider:${id}`,\n provider.getThreadMetadata ? \"metadata:1\" : \"metadata:0\",\n provider.getMessages ? \"messages:1\" : \"messages:0\",\n provider.getEvents ? \"events:1\" : \"events:0\",\n provider.getState ? \"state:1\" : \"state:0\",\n ].join(\"|\");\n }\n\n /**\n * Build a deterministic signature for runtime fetch headers so auth/CSRF\n * changes invalidate cached thread data even when the selected thread is\n * otherwise unchanged.\n */\n private static headersLoadKey(headers: Record<string, string>): string {\n return JSON.stringify(\n Object.entries(headers).sort(([leftKey], [rightKey]) =>\n leftKey.localeCompare(rightKey),\n ),\n );\n }\n\n private renderConversationActions() {\n return html`<div class=\"cpk-td__timeline-toolbar\">\n <button type=\"button\" class=\"cpk-td__timeline-bulk-toggle\" aria-pressed=${this._showEventTimeline} @click=${() => {\n this._showEventTimeline = !this._showEventTimeline;\n this.requestUpdate();\n }}>${this._showEventTimeline ? \"Show conversation\" : \"Show event timeline\"}</button>\n ${this.renderTryFromHereControl()}\n </div>`;\n }\n\n private renderTabContent(id: ThreadDetailsTab): TemplateResult {\n if (id === \"timeline\") {\n return html`${\n this._showEventTimeline\n ? html`<div class=\"cpk-td__timeline-toolbar\">${this.renderTimelineBulkButtons()}</div>${this.renderTimeline()}`\n : this._conversation.length ||\n this._loadingMessages ||\n this._messagesError\n ? this.renderConversation()\n : this.renderTimeline()\n }`;\n }\n if (id === \"state\") return this.renderState();\n return this.renderEvents();\n }\n\n /** Returns the stable DOM ID for one tab in this inspector instance. */\n private tabDomId(id: ThreadDetailsTab): string {\n return `${this.domIdPrefix}-tab-${id}`;\n }\n\n /** Returns the stable DOM ID for the panel controlled by one tab. */\n private panelDomId(id: ThreadDetailsTab): string {\n return `${this.domIdPrefix}-panel-${id}`;\n }\n\n /** Selects and focuses the tab targeted by an ARIA tabs navigation key. */\n private handleTabKeyDown(\n event: KeyboardEvent,\n currentId: ThreadDetailsTab,\n ): void {\n const currentIndex = CpkThreadInspector.TAB_LIST.findIndex(\n (tab) => tab.id === currentId,\n );\n if (currentIndex < 0) return;\n\n let targetIndex: number | null = null;\n if (event.key === \"ArrowRight\") {\n targetIndex = (currentIndex + 1) % CpkThreadInspector.TAB_LIST.length;\n } else if (event.key === \"ArrowLeft\") {\n targetIndex =\n (currentIndex - 1 + CpkThreadInspector.TAB_LIST.length) %\n CpkThreadInspector.TAB_LIST.length;\n } else if (event.key === \"Home\") {\n targetIndex = 0;\n } else if (event.key === \"End\") {\n targetIndex = CpkThreadInspector.TAB_LIST.length - 1;\n }\n if (targetIndex === null) return;\n\n const target = CpkThreadInspector.TAB_LIST[targetIndex];\n if (!target) return;\n event.preventDefault();\n this.activateTab(target.id);\n this.shadowRoot\n ?.querySelector<HTMLButtonElement>(`#${this.tabDomId(target.id)}`)\n ?.focus();\n }\n\n private activateTab(id: ThreadDetailsTab): void {\n if (this._tab === id) return;\n const isFirstActivation = !this._activatedTabs.has(id);\n this._tab = id;\n if (isFirstActivation) {\n // First time opening this tab: paint a \"Loading…\" overlay for one\n // frame so the tab highlight + spinner appear before the heavy\n // per-tab render runs (events list, state JSON). The rAF batches\n // mounting the panel into `_activatedTabs` and clearing the spinner\n // into a single subsequent paint. Subsequent activations are pure\n // CSS toggles via display:none on the already-mounted panel — no\n // re-render required.\n this._panelInitializing = true;\n requestAnimationFrame(() => {\n this._activatedTabs = new Set([...this._activatedTabs, id]);\n this._panelInitializing = false;\n });\n }\n this.maybeFetchTabData(id);\n }\n\n selectTab(id: ThreadDetailsTab): void {\n this.activateTab(id);\n }\n\n private maybeFetchTabData(id: ThreadDetailsTab): void {\n // Lazy-trigger the events / state fetches so their (potentially huge)\n // JSON.parse only blocks the main thread after the user has shown\n // intent to view that sub-tab. Without lazy-load, the eager fetch runs\n // as soon as the thread opens and a single large response can stall\n // the entire panel for seconds — including making the tab buttons\n // themselves feel unresponsive.\n if (!this.threadId) return;\n if ((id === \"timeline\" || id === \"raw-events\") && !this._eventsFetched) {\n this._eventsFetched = true;\n void this.fetchEvents(this.threadId);\n } else if (id === \"state\" && !this._stateFetched) {\n this._stateFetched = true;\n void this.fetchState(this.threadId);\n }\n }\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n /* ── Root ────────────────────────────────────────────────────────── */\n :host {\n display: flex;\n flex-direction: row;\n overflow: hidden;\n --cpk-json-key: #3d408f;\n --cpk-json-str: #0b6b4c;\n --cpk-json-num: #8a5900;\n --cpk-json-bool: #c0333a;\n --cpk-json-nil: #57575b;\n }\n\n .cpk-td {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 13px;\n display: flex;\n flex-direction: row;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: #ffffff;\n }\n\n /* ── Left area ───────────────────────────────────────────────────── */\n .cpk-td__left {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* ── Tab bar header ──────────────────────────────────────────────── */\n .cpk-td__tabs-header {\n /* No top/right padding so tabs and toggle sit flush against the\n top and right edges of the inspector. */\n padding: 0 0 0 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n }\n\n .cpk-td__tab-group {\n display: flex;\n gap: 0;\n margin-bottom: -1px;\n /* Allow the tab list to shrink rather than pushing the panel-toggle\n button past the right edge of the inspector when horizontal space\n gets tight (the drawer being open eats noticeably into width). */\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n }\n\n .cpk-td__tab {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 10px 12px;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n background: transparent;\n color: #68686e;\n transition:\n color 0.12s,\n border-color 0.12s;\n white-space: nowrap;\n }\n\n .cpk-td__tab:hover {\n color: #010507;\n }\n\n .cpk-td__tab:focus-visible {\n outline: 2px solid #5558b2;\n outline-offset: -3px;\n border-radius: 5px;\n }\n\n .cpk-td__tab--active {\n color: #010507;\n border-bottom-color: #bec2ff;\n }\n\n /* Toggle is a separate control, not a tab — so it does NOT use the\n tabs' bottom-border active indicator. Instead, a subtle filled\n state communicates \"the drawer is open,\" and a vertical separator\n on the left visually divorces it from the tab group. */\n .cpk-td__panel-toggle {\n margin-left: auto;\n align-self: stretch;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 12px;\n border: none;\n border-left: 1px solid #dbdbe5;\n background: transparent;\n color: #68686e;\n cursor: pointer;\n flex-shrink: 0;\n transition:\n color 0.12s,\n background 0.12s;\n }\n .cpk-td__panel-toggle:hover {\n color: #010507;\n background: #f4f4f9;\n }\n .cpk-td__panel-toggle--active {\n color: #5558b2;\n background: #eee6fe;\n }\n .cpk-td__panel-toggle--active:hover {\n background: #e4d8fc;\n }\n\n /* ── Scrollable content ──────────────────────────────────────────── */\n .cpk-td__content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* Pin direct children so expanded tool bodies don't get flex-shrunk. */\n .cpk-td__content > * {\n flex-shrink: 0;\n }\n\n .cpk-td__chrome-actions {\n margin-inline-start: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n padding-inline: 8px;\n min-width: 0;\n }\n\n .cpk-td__chrome-actions + .cpk-td__panel-toggle {\n margin-inline-start: 0;\n }\n\n .cpk-td__thread-header {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px 16px;\n padding: 12px 16px;\n flex-shrink: 0;\n border-bottom: 1px solid #dbdbe540;\n }\n .cpk-td__thread-title {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n font-size: 15px;\n font-weight: 600;\n }\n .cpk-td__pinned-actions {\n margin-left: auto;\n max-width: 100%;\n }\n .cpk-td__pinned-actions .cpk-td__timeline-toolbar {\n justify-content: flex-end;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__bubble-inner--assistant {\n background: transparent;\n color: #e7e7ed;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__bubble-inner--user {\n background: #27272a;\n color: #f4f4f5;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__show-more {\n color: #c5b5ff;\n }\n .cpk-td__timeline-bulk-toggle[aria-pressed=\"true\"] {\n background: #ece7fa;\n color: #51418b;\n }\n .cpk-td__bubble-inner {\n line-height: 1.65;\n overflow-wrap: anywhere;\n }\n .cpk-td__metadata-strip {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 16px;\n border-bottom: 1px solid #e9e9ef;\n background: #fbfbfd;\n flex-shrink: 0;\n }\n\n .cpk-td__metadata-pills {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n flex-wrap: nowrap;\n }\n\n .cpk-td__metadata-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: 1 1 0;\n min-width: 0;\n height: 24px;\n padding: 0 8px;\n border: 1px solid #dbdbe5;\n border-radius: 6px;\n background: #ffffff;\n color: #57575b;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n white-space: nowrap;\n }\n\n .cpk-td__metadata-label {\n color: #68686e;\n text-transform: uppercase;\n font-size: 9px;\n }\n\n .cpk-td__metadata-value {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__metadata-value--wrap,\n .cpk-td__metadata-pill--wrap {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__view-in-app {\n appearance: none;\n flex-shrink: 0;\n margin: 0;\n border: 1px solid #5558b2;\n border-radius: 6px;\n background: #5558b2;\n color: #ffffff;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n line-height: 1.2;\n min-height: 24px;\n padding: 3px 8px;\n cursor: pointer;\n transition:\n transform 160ms cubic-bezier(0.23, 1, 0.32, 1),\n background 120ms ease,\n color 120ms ease,\n border-color 120ms ease;\n }\n\n .cpk-td__view-in-app:focus-visible {\n outline: 2px solid #010507;\n outline-offset: 2px;\n }\n\n .cpk-td__view-in-app:active {\n transform: scale(0.96);\n }\n\n .cpk-td__view-in-app--stop {\n background: #ffffff;\n color: #5558b2;\n }\n\n .cpk-td__view-in-app-error {\n flex-basis: 100%;\n color: #c0333a;\n font-size: 11px;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-td__view-in-app {\n transition: none;\n }\n\n .cpk-td__view-in-app:active {\n transform: none;\n }\n }\n\n .cpk-td__try-from-here {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-inline-start: auto;\n padding: 6px 10px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #ffffff;\n color: #36363a;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .cpk-td__try-from-here-icon {\n display: block;\n flex-shrink: 0;\n }\n\n :host([dir=\"rtl\"]) .cpk-td__try-from-here-icon {\n scale: -1 1;\n }\n\n .cpk-td__try-from-here:hover:not(:disabled) {\n border-color: rgba(85, 88, 178, 0.38);\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__try-from-here:focus-visible {\n outline: 2px solid #a78bfa;\n outline-offset: 1px;\n }\n\n .cpk-td__try-from-here:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n .cpk-td__try-from-here-error {\n flex-basis: 100%;\n color: #c0333a;\n font-size: 11px;\n line-height: 1.4;\n }\n\n /*\n * Each tab's content is wrapped in this panel so the keep-mounted\n * inactive panels can be hidden via display:none without disturbing\n * the gap between visible siblings. The flex column + gap gives each\n * conversation item / event row breathing room (the cpk-td__content\n * rule above no longer reaches them now that they are nested inside\n * the per-panel wrapper).\n */\n .cpk-td__panel {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .cpk-td__panel > * {\n flex-shrink: 0;\n }\n\n .cpk-td__panel[hidden] {\n display: none;\n }\n\n /* ── Empty state ─────────────────────────────────────────────────── */\n .cpk-td__empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n font-size: 13px;\n padding: 40px 0;\n }\n\n .cpk-td__empty-hint {\n font-size: 11px;\n color: #68686e;\n text-align: center;\n max-width: 220px;\n line-height: 1.5;\n }\n\n /* ── Status messages ─────────────────────────────────────────────── */\n .cpk-td__status {\n padding: 16px;\n font-size: 12px;\n color: #68686e;\n text-align: center;\n }\n\n .cpk-td__status--error {\n color: #c0333a;\n }\n\n @keyframes cpk-td-focus-pulse {\n 0% {\n outline-color: rgba(100, 48, 171, 0);\n box-shadow: 0 0 0 rgba(100, 48, 171, 0);\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n }\n 24%,\n 50% {\n outline-color: rgba(100, 48, 171, 0.78);\n box-shadow: 0 7px 20px rgba(100, 48, 171, 0.2);\n }\n 100% {\n outline-color: rgba(100, 48, 171, 0);\n box-shadow: 0 0 0 rgba(100, 48, 171, 0);\n }\n }\n\n .cpk-td__focus-pulse {\n position: relative;\n z-index: 1;\n outline: 2px solid transparent;\n outline-offset: 3px;\n animation: cpk-td-focus-pulse 760ms linear;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-td__focus-pulse {\n animation-duration: 320ms;\n }\n }\n\n /* ── Conversation bubbles ────────────────────────────────────────── */\n .cpk-td__bubble {\n display: flex;\n margin-bottom: 10px;\n }\n\n .cpk-td__bubble--user {\n justify-content: flex-end;\n }\n\n .cpk-td__bubble--assistant {\n justify-content: flex-start;\n }\n\n .cpk-td__bubble-inner {\n padding: 10px 16px;\n max-width: 80%;\n font-size: 14px;\n line-height: 1.65;\n }\n\n .cpk-td__bubble-inner--user {\n background: #f4f4f5;\n color: #18181b;\n border-radius: 18px;\n }\n\n .cpk-td__show-more {\n display: inline-block;\n margin-top: 4px;\n font-size: 11px;\n font-weight: 500;\n color: #57575b;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n\n .cpk-td__bubble-inner--assistant {\n background: transparent;\n color: #010507;\n max-width: 100%;\n padding: 4px 0;\n border: 0;\n }\n\n /* ── Tool call blocks ────────────────────────────────────────────── */\n .cpk-td__tool-block {\n border: 1px solid #e9e9ef;\n border-radius: 12px;\n overflow: hidden;\n }\n\n .cpk-td__tool-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px;\n background: #ffffff;\n color: #71717a;\n cursor: pointer;\n font-size: 11px;\n user-select: none;\n }\n\n .cpk-td__tool-header:hover {\n background: #fafafa;\n }\n\n .cpk-td__tool-name {\n font-size: 13px;\n font-weight: 500;\n color: #18181b;\n overflow-wrap: anywhere;\n min-width: 0;\n flex: 1;\n }\n\n .cpk-td__tool-status {\n font-size: 10px;\n font-weight: 500;\n padding: 3px 7px;\n border-radius: 999px;\n background: #d1fae5;\n color: #065f46;\n }\n\n .cpk-td__tool-status--pending {\n background: #fef3c7;\n color: #8a5900;\n }\n\n .cpk-td__tool-chevron {\n color: #68686e;\n font-size: 10px;\n }\n\n .cpk-td__tool-body {\n padding: 8px 10px;\n border-top: 1px solid #e9e9ef;\n background: #ffffff;\n }\n\n .cpk-td__tool-section-label {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n font-weight: 500;\n color: #68686e;\n text-transform: uppercase;\n margin-bottom: 4px;\n letter-spacing: 0.3px;\n }\n\n .cpk-td__tool-pre {\n margin: 0;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n background: #f7f7f9;\n padding: 10px 12px;\n border-radius: 6px;\n overflow-x: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n line-height: 1.65;\n }\n\n /* ── Tool call group ─────────────────────────────────────────────── */\n .cpk-td__tool-group {\n border: 1px solid #e9e9ef;\n border-radius: 7px;\n overflow: hidden;\n }\n\n .cpk-td__tool-group-header {\n padding: 5px 10px;\n background: rgba(133, 236, 206, 0.15);\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n color: #087653;\n text-transform: uppercase;\n font-weight: 500;\n border-bottom: 1px solid #e9e9ef;\n }\n\n .cpk-td__tool-group .cpk-td__tool-block {\n border: none;\n border-bottom: 1px solid #e9e9ef;\n border-radius: 0;\n }\n\n .cpk-td__tool-group .cpk-td__tool-block:last-child {\n border-bottom: none;\n }\n\n /* ── Inline chips (reasoning / state update) ─────────────────────── */\n .cpk-td__inline-chip {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 5px 0;\n color: #68686e;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n text-transform: uppercase;\n }\n\n .cpk-td__inline-chip::before,\n .cpk-td__inline-chip::after {\n content: \"\";\n flex: 1;\n height: 1px;\n background: #e9e9ef;\n }\n\n /* ── Interaction timeline ───────────────────────────────────────── */\n .cpk-td__timeline-item {\n border: 1px solid transparent;\n border-radius: 10px;\n background: transparent;\n overflow: hidden;\n }\n\n .cpk-td__timeline-item--run,\n .cpk-td__timeline-item--state,\n .cpk-td__timeline-item--event,\n .cpk-td__timeline-item--tool,\n .cpk-td__event--run,\n .cpk-td__event--event,\n .cpk-td__event--state,\n .cpk-td__event--message,\n .cpk-td__event--tool {\n border-color: #dbdbe5;\n background: #ffffff;\n }\n\n .cpk-td__timeline-item--message {\n border-color: #dbdbe5;\n background: #ffffff;\n box-shadow: 0 1px 2px #0105070d;\n }\n\n .cpk-td__timeline-item--warning {\n border-color: rgba(250, 95, 103, 0.35);\n background: rgba(250, 95, 103, 0.04);\n }\n\n .cpk-td__timeline-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: transparent;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-header {\n padding: 10px 12px;\n background: #f7f7f9;\n }\n\n .cpk-td__timeline-item--user .cpk-td__timeline-header {\n background: #bec2ff1a;\n }\n\n .cpk-td__timeline-item--assistant .cpk-td__timeline-header {\n background: #85ecce1a;\n }\n\n .cpk-td__timeline-kind {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n border-radius: 999px;\n background: #f0f0f4;\n color: #57575b;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.04em;\n line-height: 1.2;\n text-transform: uppercase;\n flex-shrink: 0;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-kind {\n background: #bec2ff33;\n color: #010507;\n }\n\n .cpk-td__timeline-item--assistant .cpk-td__timeline-kind {\n background: #85ecce4d;\n color: #010507;\n }\n\n .cpk-td__timeline-item--warning .cpk-td__timeline-kind {\n background: rgba(250, 95, 103, 0.16);\n color: #c0333a;\n }\n\n .cpk-td__timeline-title {\n flex: 1;\n min-width: 0;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 500;\n color: #57575b;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-title {\n font-size: 13px;\n font-weight: 600;\n color: #010507;\n }\n\n .cpk-td__timeline-time {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-td__timeline-body {\n margin: 0;\n padding: 0 10px 9px;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n line-height: 1.55;\n color: #57575b;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-body {\n padding: 0 12px 12px;\n font-size: 13px;\n color: #010507;\n }\n\n .cpk-td__timeline-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .cpk-td__timeline-bulk-toggle {\n margin: 0;\n padding: 6px 10px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #ffffff;\n color: #36363a;\n cursor: pointer;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .cpk-td__timeline-bulk-toggle:hover {\n border-color: rgba(85, 88, 178, 0.38);\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__timeline-bulk-toggle:disabled {\n cursor: not-allowed;\n opacity: 0.45;\n }\n\n .cpk-td__source-link {\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n color: #5558b2;\n cursor: pointer;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n text-decoration: underline;\n text-underline-offset: 2px;\n flex-shrink: 0;\n }\n\n .cpk-td__source-link:hover {\n color: #010507;\n }\n\n .cpk-td__timeline-details-toggle {\n margin: 0;\n padding: 5px 10px;\n border: none;\n background: #ffffff;\n color: #5558b2;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-family: \"Inter\", sans-serif;\n font-size: 12px;\n font-weight: 600;\n line-height: 1.2;\n width: 100%;\n }\n\n .cpk-td__timeline-details-toggle:hover {\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__timeline-details-toggle svg {\n width: 12px;\n height: 12px;\n stroke-width: 2;\n }\n\n /* ── Generative UI ──────────────────────────────────────────────── */\n @keyframes cpk-genui-enter {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .cpk-td__genui {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 0;\n animation: cpk-genui-enter 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-td__genui-badge {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 6px;\n padding: 12px;\n min-height: 44px;\n box-sizing: border-box;\n border: 1px solid #e5def5;\n border-radius: 12px;\n background: #f7f4fc;\n color: #57575b;\n font-size: 13px;\n line-height: 20px;\n font-weight: 500;\n }\n\n .cpk-td__genui-card {\n overflow: hidden;\n border-radius: 14px;\n border: 1px solid #e2e8f0;\n background: #fff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.08);\n }\n\n .cpk-td__genui-component {\n margin-left: 6px;\n font-size: 13px;\n font-weight: 400;\n overflow-wrap: anywhere;\n min-width: 0;\n line-height: inherit;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-badge {\n border-color: #49405f;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header {\n background: #191c24;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-name {\n color: #f4f4f5;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-status {\n background: #17392e;\n color: #6ee7b7;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-status--pending {\n background: #3d3019;\n color: #fbbf24;\n }\n\n /* ── AG-UI Events ────────────────────────────────────────────────── */\n .cpk-td__event {\n flex-shrink: 0;\n border: 1px solid #dbdbe5;\n border-radius: 10px;\n background: #ffffff;\n overflow: hidden;\n /*\n * content-visibility: auto lets the browser skip layout + paint for\n * off-screen events while keeping them in the DOM (so scroll size\n * stays correct). Without this, switching back to AG-UI Events on a\n * thread with hundreds of events triggers a full layout pass over\n * every event row, which on Martha's intelligence-backed example\n * shows up as a multi-second freeze each time the panel becomes\n * visible. The intrinsic-size hint avoids the visible jump as the\n * browser swaps in real heights when items scroll into view.\n */\n content-visibility: auto;\n contain-intrinsic-size: 0 80px;\n }\n\n .cpk-td__event--error {\n border-color: rgba(250, 95, 103, 0.35);\n background: rgba(250, 95, 103, 0.04);\n }\n\n .cpk-td__event-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: transparent;\n }\n\n .cpk-td__event-type {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n border-radius: 999px;\n background: #f0f0f4;\n color: #010507;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.02em;\n line-height: 1.2;\n }\n\n .cpk-td__event--message .cpk-td__event-type {\n background: #bec2ff33;\n }\n\n .cpk-td__event--tool .cpk-td__event-type {\n background: #85ecce4d;\n }\n\n .cpk-td__event--error .cpk-td__event-type {\n background: rgba(250, 95, 103, 0.16);\n color: #c0333a;\n }\n\n .cpk-td__event-time {\n margin-inline-start: auto;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-td__event-payload,\n .cpk-td__json-block,\n .cpk-json-block {\n margin: 0;\n padding: 10px 12px;\n border-top: 1px solid #dbdbe5;\n background: #f7f7f9;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n line-height: 1.65;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n overflow: auto;\n }\n\n .cpk-json-token--key {\n color: var(--cpk-json-key);\n }\n\n .cpk-json-token--str {\n color: var(--cpk-json-str);\n }\n\n .cpk-json-token--num {\n color: var(--cpk-json-num);\n }\n\n .cpk-json-token--bool {\n color: var(--cpk-json-bool);\n }\n\n .cpk-json-token--nil {\n color: var(--cpk-json-nil);\n }\n\n /* ── Resize divider ──────────────────────────────────────────────── */\n /* Floats over the drawer's left edge so the toggle and the drawer\n touch directly without a 4px flex-gap between them. The hit zone\n is wider than its visual hint to make it easy to grab. */\n .cpk-td__detail-divider {\n position: absolute;\n top: 0;\n bottom: 0;\n left: -3px;\n width: 7px;\n cursor: col-resize;\n background: transparent;\n z-index: 5;\n }\n\n .cpk-td__detail-divider:hover {\n background: rgba(190, 194, 255, 0.3);\n }\n\n /* ── Right detail panel ──────────────────────────────────────────── */\n .cpk-td__detail {\n flex-shrink: 0;\n overflow: hidden;\n background: #f7f7f9;\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n /* Slide open/closed via width + padding transition. When closed,\n width and padding are 0 so the drawer fully collapses. */\n transition:\n width 220ms cubic-bezier(0.4, 0, 0.2, 1),\n padding 220ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .cpk-td__detail[data-open=\"true\"] {\n overflow-y: auto;\n padding: 16px;\n }\n\n .cpk-tdp__section-title {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 500;\n color: #68686e;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n margin-bottom: 8px;\n }\n\n .cpk-tdp__divider {\n height: 1px;\n background: #dbdbe5;\n margin: 14px 0;\n }\n\n .cpk-tdp__row {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 3px 0;\n gap: 8px;\n }\n\n .cpk-tdp__label {\n color: #68686e;\n font-size: 11px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .cpk-tdp__value {\n color: #010507;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n text-align: right;\n min-width: 0;\n }\n\n .cpk-tdp__value--truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 130px;\n }\n\n .cpk-tdp__value--wrap {\n white-space: normal;\n word-break: break-all;\n text-align: right;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n --cpk-json-key: #bec2ff;\n --cpk-json-str: #85ecce;\n --cpk-json-num: #ffac4d;\n --cpk-json-bool: #fa5f67;\n --cpk-json-nil: #afafb7;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td {\n background: #111319;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tabs-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-strip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-pill,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-block,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-body,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-payload,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-strip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__detail {\n background: #15171e;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-pill,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-block,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-card,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle {\n border-color: #343742;\n background: #191c24;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-body {\n background: #171a22;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-pre {\n background: #111319;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle:hover {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle--active,\n :host([data-color-scheme=\"dark\"]) .cpk-td__inline-chip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-badge {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--message {\n background: #191c24;\n border-color: #343742;\n box-shadow: none;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--user\n .cpk-td__timeline-header {\n background: #bec2ff1a;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--assistant\n .cpk-td__timeline-header {\n background: #85ecce1a;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--message\n .cpk-td__timeline-kind {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--assistant\n .cpk-td__timeline-kind {\n background: #1a3a32;\n color: #85ecce;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--run,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--state,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--tool,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--run,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--state,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--message,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--tool {\n background: #191c24;\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--run\n .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--event\n .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--state\n .cpk-td__timeline-header {\n background: transparent;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-kind {\n background: #20232d;\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--run\n .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--event\n .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--state\n .cpk-td__timeline-title {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-header {\n background: transparent;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-type {\n background: #20232d;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--message .cpk-td__event-type {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--tool .cpk-td__event-type {\n background: #1a3a32;\n color: #85ecce;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--error .cpk-td__event-type {\n background: rgba(250, 95, 103, 0.2);\n color: #fa5f67;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--message\n .cpk-td__timeline-body {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab,\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-label,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-time,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-time,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-body,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__label,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__section-title {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab--active,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-value,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-name,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-pre,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__value {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-payload,\n :host([data-color-scheme=\"dark\"]) .cpk-td__json-block,\n :host([data-color-scheme=\"dark\"]) .cpk-json-block {\n background: #111319;\n border-top-color: #343742;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__divider {\n background: #343742;\n }\n `;\n\n updated(_changed: Map<string, unknown>): void {\n if (!this.isConnected) return;\n const loadKey = this.currentLoadKey();\n if (loadKey !== this._lastLoadKey) {\n this._lastLoadKey = loadKey;\n this._lastSeenLiveMessageVersion = this.liveMessageVersion;\n this.resetLoadedThreadData();\n\n if (this.threadId) {\n // Keep fetching events alongside messages so the timeline and raw\n // events views reuse the same response when opened.\n // User messages often never appear as TEXT_MESSAGE events (they are\n // added locally before RUN_STARTED), so also load the conversation.\n void this.fetchMetadata(this.threadId);\n if (this.canFetchEvents()) {\n this._eventsFetched = true;\n void this.fetchEvents(this.threadId);\n }\n if (this.canFetchMessages()) {\n void this.fetchMessages(this.threadId);\n }\n } else {\n this._fetchedMetadata = null;\n this._conversation = [];\n }\n } else if (\n this.threadId &&\n this.liveMessageVersion !== this._lastSeenLiveMessageVersion\n ) {\n // Same thread, but the parent inspector signalled new agent-emitted\n // messages on this thread (via `liveMessageVersion`). Re-fetch the\n // canonical conversation from the runtime so streaming output flows\n // into the view without us reimplementing AG-UI → ConversationItem\n // mapping in the parent. `silent: true` so the loading-state indicator\n // doesn't flash between every streaming chunk and we keep the\n // last-good view on transient fetch errors.\n this._lastSeenLiveMessageVersion = this.liveMessageVersion;\n this._messagesAbort?.abort();\n this._messagesAbort = null;\n void this.fetchMessages(this.threadId, true);\n }\n\n const focusedContentChanged =\n _changed.has(\"_fetchedEvents\") ||\n _changed.has(\"agentEventsInput\") ||\n _changed.has(\"agentMessagesInput\") ||\n _changed.has(\"_conversation\");\n if (\n this.focusMessageId &&\n (this.focusRequestId > this._scrolledFocusRequestId ||\n focusedContentChanged)\n ) {\n if (this._tab !== \"timeline\") {\n this._activatedTabs = new Set([...this._activatedTabs, \"timeline\"]);\n this._tab = \"timeline\";\n this.requestUpdate();\n }\n requestAnimationFrame(() => this.scrollToFocusedMessage());\n }\n }\n\n private scrollToFocusedMessage(): void {\n if (!this.focusMessageId) return;\n const message = Array.from(\n this.shadowRoot?.querySelectorAll<HTMLElement>(\"[data-message-id]\") ?? [],\n ).find((candidate) => candidate.dataset.messageId === this.focusMessageId);\n if (!message) return;\n message.scrollIntoView?.({ block: \"center\" });\n this._scrolledFocusRequestId = this.focusRequestId;\n this.pulseFocusedMessage(message);\n }\n\n private pulseFocusedMessage(message: HTMLElement): void {\n if (this.focusRequestId === this._highlightedFocusRequestId) return;\n this._highlightedFocusRequestId = this.focusRequestId;\n message.classList.remove(\"cpk-td__focus-pulse\");\n void message.offsetWidth;\n message.classList.add(\"cpk-td__focus-pulse\");\n message.addEventListener(\n \"animationend\",\n () => message.classList.remove(\"cpk-td__focus-pulse\"),\n { once: true },\n );\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (this._hasConnectedOnce) {\n this.requestUpdate();\n }\n this._hasConnectedOnce = true;\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.resetLoadedThreadData();\n this._lastLoadKey = null;\n }\n\n private canFetchMessages(): boolean {\n return (\n !!this.provider?.getMessages ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private canFetchEvents(): boolean {\n return (\n !!this.provider?.getEvents ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private canFetchState(): boolean {\n return (\n !!this.provider?.getState ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private currentLoadKey(): string {\n return [\n this.threadId ?? \"thread:none\",\n CpkThreadInspector.providerLoadKey(this.provider),\n `runtime:${this.runtimeUrl}`,\n `headers:${CpkThreadInspector.headersLoadKey(this.headers)}`,\n `inspect:${this.threadInspectionAvailable ? \"1\" : \"0\"}`,\n ].join(\"||\");\n }\n\n private resetLoadedThreadData(): void {\n this._tab = \"timeline\";\n this._activatedTabs = new Set([\"timeline\"]);\n this._panelTplCache = new Map();\n this._timelineItemsCache = null;\n this._liveEventsWithSourceIndexCache = null;\n this._expandedTools = new Set();\n this._expandedMessages = new Set();\n this._expandedTimelineDetails = new Set();\n this._expandedRawEvents = new Set();\n this._metadataAbort?.abort();\n this._metadataAbort = null;\n this._messagesAbort?.abort();\n this._messagesAbort = null;\n this._eventsAbort?.abort();\n this._eventsAbort = null;\n this._stateAbort?.abort();\n this._stateAbort = null;\n // Reset cleared so the next click into events/state triggers a fresh\n // fetch. Eagerly clear fetched data so a provider/runtime swap cannot\n // briefly show the old source's values for the same threadId.\n this._eventsFetched = false;\n this._stateFetched = false;\n this._eventsNotAvailable = false;\n this._stateNotAvailable = false;\n this._loadingMessages = false;\n this._loadingEvents = false;\n this._loadingState = false;\n this._messagesError = null;\n this._eventsError = null;\n this._stateError = null;\n this._fetchedMetadata = null;\n this._conversation = [];\n this._fetchedEvents = null;\n this._fetchedState = null;\n }\n\n private async fetchMetadata(threadId: string): Promise<void> {\n if (!this.provider?.getThreadMetadata) return;\n this._metadataAbort?.abort();\n const controller = new AbortController();\n this._metadataAbort = controller;\n try {\n const metadata = await this.provider.getThreadMetadata(threadId, {\n signal: controller.signal,\n });\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._fetchedMetadata = metadata;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (this.threadId !== threadId) return;\n this._fetchedMetadata = null;\n }\n }\n\n /**\n * Fetch the canonical conversation for `threadId` from the runtime.\n *\n * `silent` is true for live re-fetches triggered by `liveMessageVersion`\n * bumps during streaming. In that mode we never toggle the loading state\n * (which would flash \"Loading messages…\" between every message) and we\n * keep the previous conversation on transient errors instead of blanking\n * it. Initial threadId-change fetches use the default (`silent=false`)\n * so users see an explicit loading indicator on first load.\n */\n private async fetchMessages(\n threadId: string,\n silent: boolean = false,\n ): Promise<void> {\n if (!this.canFetchMessages()) {\n if (!silent) this._conversation = [];\n return;\n }\n this._messagesAbort?.abort();\n const controller = new AbortController();\n this._messagesAbort = controller;\n if (!silent) {\n this._loadingMessages = true;\n this._messagesError = null;\n }\n try {\n const messages = this.provider?.getMessages\n ? await this.provider.getMessages(threadId, {\n signal: controller.signal,\n })\n : await this.fetchRuntimeMessages(threadId, controller.signal);\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._conversation = this.mapMessages(messages);\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (!silent) {\n this._messagesError =\n err instanceof Error ? err.message : \"Failed to load messages\";\n this._conversation = [];\n }\n // Silent mode: keep last-good conversation, don't surface the error.\n // The next successful live re-fetch will recover automatically.\n } finally {\n if (!silent && !controller.signal.aborted) {\n this._loadingMessages = false;\n }\n }\n }\n\n private async fetchEvents(threadId: string): Promise<void> {\n if (!this.canFetchEvents()) {\n this._fetchedEvents = null;\n return;\n }\n this._eventsAbort?.abort();\n const controller = new AbortController();\n this._eventsAbort = controller;\n this._loadingEvents = true;\n this._eventsError = null;\n try {\n const result = this.provider?.getEvents\n ? {\n status: \"available\" as const,\n events: await this.provider.getEvents(threadId, {\n signal: controller.signal,\n }),\n }\n : await this.fetchRuntimeEvents(threadId, controller.signal);\n // Drop results if a newer fetch superseded this one (thread switched\n // or provider/runtime changed mid-flight). Without this, switching A→B\n // can leave thread B's view showing thread A's events when A's request\n // resolves last.\n if (controller.signal.aborted || this.threadId !== threadId) return;\n if (result.status === \"not-available\") {\n this._eventsNotAvailable = true;\n this._fetchedEvents = [];\n return;\n }\n const mappedEvents = this.mapApiEvents(result.events);\n this._fetchedEvents = mappedEvents;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (this.threadId !== threadId) return;\n this._eventsError =\n err instanceof Error ? err.message : \"Failed to load events\";\n this._fetchedEvents = [];\n } finally {\n if (!controller.signal.aborted && this.threadId === threadId) {\n this._loadingEvents = false;\n }\n }\n }\n\n private async fetchState(threadId: string): Promise<void> {\n if (!this.canFetchState()) {\n this._fetchedState = null;\n return;\n }\n this._stateAbort?.abort();\n const controller = new AbortController();\n this._stateAbort = controller;\n this._loadingState = true;\n this._stateError = null;\n try {\n const result = this.provider?.getState\n ? {\n status: \"available\" as const,\n state: await this.provider.getState(threadId, {\n signal: controller.signal,\n }),\n }\n : await this.fetchRuntimeState(threadId, controller.signal);\n if (controller.signal.aborted || this.threadId !== threadId) return;\n if (result.status === \"not-available\") {\n this._stateNotAvailable = true;\n this._fetchedState = null;\n return;\n }\n this._fetchedState = result.state ?? null;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (this.threadId !== threadId) return;\n this._stateError =\n err instanceof Error ? err.message : \"Failed to load state\";\n this._fetchedState = null;\n } finally {\n if (!controller.signal.aborted && this.threadId === threadId) {\n this._loadingState = false;\n }\n }\n }\n\n private async fetchRuntimeMessages(\n threadId: string,\n signal: AbortSignal,\n ): Promise<ThreadDebuggerMessage[]> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"messages\"), {\n headers: { ...this.headers },\n signal,\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as { messages: ThreadDebuggerMessage[] };\n return data.messages;\n }\n\n private async fetchRuntimeEvents(\n threadId: string,\n signal: AbortSignal,\n ): Promise<RuntimeEventsFetchResult> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"events\"), {\n headers: { ...this.headers },\n signal,\n });\n if (res.status === 501) {\n return { status: \"not-available\" };\n }\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as {\n events: ThreadDebuggerEvent[];\n };\n return { status: \"available\", events: data.events };\n }\n\n private async fetchRuntimeState(\n threadId: string,\n signal: AbortSignal,\n ): Promise<RuntimeStateFetchResult> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"state\"), {\n headers: { ...this.headers },\n signal,\n });\n if (res.status === 501) {\n return { status: \"not-available\" };\n }\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as {\n state: Record<string, unknown> | null;\n };\n return { status: \"available\", state: data.state ?? null };\n }\n\n private getThreadInspectionUrl(\n threadId: string,\n resource: \"messages\" | \"events\" | \"state\",\n ): string {\n return `${this.runtimeUrl.replace(/\\/+$/, \"\")}/threads/${encodeURIComponent(threadId)}/${resource}`;\n }\n\n private mapMessages(messages: ThreadDebuggerMessage[]): ConversationItem[] {\n const items: ConversationItem[] = [];\n const toolCallMap = new Map<string, ConversationToolCall>();\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const content = textFromUnknownContent(msg.content);\n if (content) {\n items.push({\n id: msg.id,\n type: \"user\",\n content,\n createdAt: \"\",\n });\n }\n } else if (msg.role === \"assistant\") {\n if (msg.toolCalls?.length) {\n for (const tc of msg.toolCalls) {\n let args: Record<string, unknown> = {};\n if (typeof tc.args === \"string\") {\n try {\n args = this.parseToolCallContent(tc.args);\n } catch (err) {\n // Empty content is normalized to `{}` for both tool arguments\n // and results. The inspector still surfaces malformed JSON.\n console.error(\n \"[CopilotKit Inspector] Failed to parse tool-call arguments\",\n { toolCallId: tc.id, raw: tc.args, error: err },\n );\n args = { __parseError: true, __raw: tc.args };\n }\n } else {\n args = tc.args;\n }\n const item: ConversationToolCall = {\n id: tc.id,\n type: \"tool_call\",\n toolName: tc.name,\n toolCallId: tc.id,\n arguments: args,\n result: null,\n createdAt: \"\",\n };\n toolCallMap.set(tc.id, item);\n items.push(item);\n }\n }\n const assistantContent = textFromUnknownContent(msg.content);\n if (assistantContent) {\n items.push({\n id: msg.id,\n type: \"assistant\",\n content: assistantContent,\n createdAt: \"\",\n });\n }\n } else if (msg.role === \"activity\") {\n items.push({\n id: msg.id,\n type: \"generative-ui\",\n activityType: msg.activityType ?? \"unknown\",\n createdAt: \"\",\n });\n } else if (msg.role === \"tool\" && msg.toolCallId) {\n const tc = toolCallMap.get(msg.toolCallId);\n if (tc) {\n try {\n tc.result = this.parseToolCallContent(msg.content);\n } catch (err) {\n // See the comment on the assistant tool-call args parse above —\n // same rationale, same sentinel shape so the renderer can treat\n // both consistently.\n console.error(\n \"[CopilotKit Inspector] Failed to parse tool-call result content\",\n { toolCallId: msg.toolCallId, raw: msg.content, error: err },\n );\n tc.result = { __parseError: true, __raw: msg.content ?? null };\n }\n }\n }\n }\n return items;\n }\n\n private parseToolCallContent(\n content: string | null | undefined,\n ): Record<string, unknown> {\n const normalizedContent = content?.trim();\n if (!normalizedContent) {\n return {};\n }\n\n return JSON.parse(normalizedContent) as Record<string, unknown>;\n }\n\n private mapApiEvents(events: ThreadDebuggerEvent[]): ApiAgentEvent[] {\n return events.map((event, index) => {\n const { type, timestamp, payload, ...rest } = event;\n return {\n type: typeof type === \"string\" ? type : \"UNKNOWN\",\n timestamp:\n typeof timestamp === \"string\" || typeof timestamp === \"number\"\n ? timestamp\n : Date.now(),\n payload: payload ?? rest,\n sourceIndex: index + 1,\n rawEvent: event,\n };\n });\n }\n\n private get activeTimelineItems(): TimelineItem[] {\n return this.timelineItemsForEvents(this.activeEvents);\n }\n\n private timelineItemsForEvents(events: ApiAgentEvent[]): TimelineItem[] {\n const conversation = this._conversation;\n const agentMessages = this.agentMessagesInput;\n if (\n this._timelineItemsCache?.events === events &&\n this._timelineItemsCache.conversation === conversation &&\n this._timelineItemsCache.agentMessages === agentMessages\n ) {\n return this._timelineItemsCache.items;\n }\n const items = this.mergeUserMessagesIntoTimeline(\n this.timelineItemsFromEvents(events),\n );\n this._timelineItemsCache = { events, conversation, agentMessages, items };\n return items;\n }\n\n private conversationUsers(): ConversationUser[] {\n const users: ConversationUser[] = [];\n const seenIds = new Set<string>();\n const seenBodies = new Set<string>();\n const push = (user: ConversationUser) => {\n const body = user.content.trim();\n if (!body) return;\n if (seenIds.has(user.id) || seenBodies.has(body)) return;\n seenIds.add(user.id);\n seenBodies.add(body);\n users.push(user);\n };\n for (const item of this._conversation) {\n if (item.type === \"user\") push(item);\n }\n this.agentMessagesInput.forEach((message, index) => {\n if (message.role !== \"user\") return;\n push({\n id: message.id ?? `live-user-${index}`,\n type: \"user\",\n content: message.contentText,\n createdAt: \"\",\n });\n });\n return users;\n }\n\n private mergeUserMessagesIntoTimeline(items: TimelineItem[]): TimelineItem[] {\n if (items.length === 0) return items;\n const users = this.conversationUsers();\n if (users.length === 0) return items;\n\n const shownIds = new Set<string>();\n const shownBodies = new Set<string>();\n for (const item of items) {\n if (item.kind !== \"message\") continue;\n if (!item.title.toLowerCase().startsWith(\"user\")) continue;\n if (item.messageId) shownIds.add(item.messageId);\n const body = item.body?.trim();\n if (body) shownBodies.add(body);\n }\n\n const missing = users.filter((user) => {\n if (shownIds.has(user.id)) return false;\n if (shownBodies.has(user.content.trim())) return false;\n return true;\n });\n if (missing.length === 0) return items;\n\n const insertAt: number[] = [];\n for (let index = 0; index < items.length; index++) {\n const item = items[index]!;\n if (item.kind === \"run\" && item.title === \"Run started\") {\n insertAt.push(index);\n }\n }\n if (insertAt.length === 0) {\n for (let index = 0; index < items.length; index++) {\n const item = items[index]!;\n if (\n item.kind === \"message\" &&\n item.title.toLowerCase().includes(\"assistant\")\n ) {\n insertAt.push(index);\n }\n }\n }\n\n const merged = [...items];\n for (let index = missing.length - 1; index >= 0; index--) {\n const user = missing[index]!;\n const row: TimelineItem = {\n id: `conversation-user-${user.id}`,\n messageId: user.id,\n kind: \"message\",\n title: \"User message\",\n body: user.content,\n timestamp: user.createdAt || 0,\n sourceIndex: 0,\n };\n merged.splice(insertAt[index] ?? 0, 0, row);\n }\n return merged;\n }\n\n private timelineItemsFromEvents(events: ApiAgentEvent[]): TimelineItem[] {\n if (events.length === 0) return [];\n\n const items: TimelineItem[] = [];\n const messageItems = new Map<string, TimelineItem>();\n const toolItems = new Map<string, TimelineItem & { rawArgs?: string }>();\n\n const readString = (\n payload: Record<string, unknown>,\n keys: string[],\n ): string | null => {\n for (const key of keys) {\n const value = payload[key];\n if (typeof value === \"string\") return value;\n }\n return null;\n };\n\n const sourceIndexFor = (event: ApiAgentEvent): number =>\n event.sourceIndex ?? 0;\n\n const appendWarning = (\n event: ApiAgentEvent,\n title: string,\n body: string,\n severity: \"warning\" | \"error\" = \"warning\",\n ): void => {\n const sourceIndex = sourceIndexFor(event);\n items.push({\n id: `warning-${sourceIndex}-${items.length}`,\n kind: \"warning\",\n title,\n body,\n timestamp: event.timestamp,\n sourceIndex,\n severity,\n });\n };\n\n const ensureMessage = (\n event: ApiAgentEvent,\n role: string,\n ): TimelineItem => {\n const sourceIndex = sourceIndexFor(event);\n const key =\n readString(event.payload, [\"messageId\", \"message_id\", \"id\"]) ??\n `message-${sourceIndex}`;\n let item = messageItems.get(key);\n if (!item) {\n item = {\n id: `message-${key}`,\n messageId: key,\n kind: \"message\",\n title: messageTitle(role || \"message\"),\n body: \"\",\n timestamp: event.timestamp,\n sourceIndex,\n };\n messageItems.set(key, item);\n items.push(item);\n }\n return item;\n };\n\n const ensureTool = (\n event: ApiAgentEvent,\n ): TimelineItem & {\n rawArgs?: string;\n } => {\n const sourceIndex = sourceIndexFor(event);\n const key =\n readString(event.payload, [\n \"toolCallId\",\n \"tool_call_id\",\n \"id\",\n \"callId\",\n ]) ?? `tool-${sourceIndex}`;\n let item = toolItems.get(key);\n if (!item) {\n item = {\n id: `tool-${key}`,\n kind: \"tool\",\n title:\n readString(event.payload, [\n \"toolCallName\",\n \"toolName\",\n \"name\",\n \"functionName\",\n ]) ?? \"Tool call\",\n body: \"\",\n timestamp: event.timestamp,\n sourceIndex,\n };\n toolItems.set(key, item);\n items.push(item);\n }\n return item;\n };\n\n for (const event of events) {\n const { type, payload } = event;\n const sourceIndex = sourceIndexFor(event);\n\n if (type === \"UNKNOWN\") {\n appendWarning(\n event,\n \"Unknown AG-UI event\",\n \"The event is missing a string type and could not be normalized.\",\n );\n continue;\n }\n\n if (type === \"RUN_STARTED\" || type === \"STEP_STARTED\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"run\",\n title: type === \"RUN_STARTED\" ? \"Run started\" : \"Step started\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n if (type === \"RUN_FINISHED\" || type === \"STEP_FINISHED\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"run\",\n title: type === \"RUN_FINISHED\" ? \"Run finished\" : \"Step finished\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n if (type === \"RUN_ERROR\" || type === \"ERROR\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"warning\",\n title: \"Run error\",\n body: readString(payload, [\"message\", \"error\", \"description\"]) ?? \"\",\n timestamp: event.timestamp,\n sourceIndex,\n severity: \"error\",\n details: payload,\n });\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_START\") {\n ensureMessage(event, readString(payload, [\"role\"]) ?? \"assistant\");\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_CONTENT\") {\n const item = ensureMessage(\n event,\n readString(payload, [\"role\"]) ?? \"assistant\",\n );\n item.body = `${item.body ?? \"\"}${\n readString(payload, [\"delta\", \"content\", \"text\"]) ?? \"\"\n }`;\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_END\") {\n ensureMessage(event, readString(payload, [\"role\"]) ?? \"assistant\");\n continue;\n }\n\n if (type === \"TOOL_CALL_START\") {\n ensureTool(event);\n continue;\n }\n\n if (type === \"TOOL_CALL_ARGS\") {\n const item = ensureTool(event);\n const chunk =\n readString(payload, [\"args\", \"arguments\", \"delta\"]) ??\n (typeof payload.args === \"object\"\n ? JSON.stringify(payload.args)\n : null);\n if (chunk) {\n item.rawArgs = `${item.rawArgs ?? \"\"}${chunk}`;\n item.body = item.rawArgs;\n }\n continue;\n }\n\n if (type === \"TOOL_CALL_END\") {\n const item = ensureTool(event);\n if (item.rawArgs) {\n try {\n JSON.parse(item.rawArgs);\n } catch {\n appendWarning(\n event,\n \"Could not decode tool call arguments\",\n item.rawArgs,\n );\n }\n }\n continue;\n }\n\n if (type === \"TOOL_CALL_RESULT\") {\n const item = ensureTool(event);\n const result = readString(payload, [\"result\", \"content\", \"delta\"]);\n if (result) {\n item.body = item.body\n ? `${item.body}\\nResult: ${result}`\n : `Result: ${result}`;\n try {\n JSON.parse(result);\n } catch {\n appendWarning(event, \"Could not decode tool result\", result);\n }\n }\n continue;\n }\n\n if (type.startsWith(\"STATE_\")) {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"state\",\n title: type === \"STATE_SNAPSHOT\" ? \"State snapshot\" : \"State delta\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n items.push({\n id: `event-${sourceIndex}`,\n kind: \"event\",\n title: humanizeEventType(type),\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n }\n\n return items;\n }\n\n private get renderItems(): RenderItem[] {\n const items = this._conversation;\n const result: RenderItem[] = [];\n const seen = new Set<string>();\n for (const item of items) {\n if (item.type === \"agent_responded\") continue;\n if (item.type !== \"tool_call\" || !item.groupId) {\n result.push(item);\n continue;\n }\n if (seen.has(item.groupId)) continue;\n seen.add(item.groupId);\n const group: ToolCallGroup = {\n type: \"tool_call_group\",\n id: item.groupId,\n items: items.filter(\n (i): i is ConversationToolCall =>\n i.type === \"tool_call\" && i.groupId === item.groupId,\n ),\n };\n result.push(group);\n }\n return result;\n }\n\n private get activityCounts(): {\n messages: number;\n toolCalls: number;\n generativeUi: number;\n } {\n let messages = 0;\n let toolCalls = 0;\n let generativeUi = 0;\n for (const item of this._conversation) {\n if (item.type === \"user\" || item.type === \"assistant\") messages++;\n if (item.type === \"tool_call\") toolCalls++;\n if (item.type === \"generative-ui\") generativeUi++;\n }\n return { messages, toolCalls, generativeUi };\n }\n\n private get duration(): string {\n const t = this.metadata;\n if (!t?.createdAt || !t?.updatedAt) return \"—\";\n const ms =\n new Date(t.updatedAt).getTime() - new Date(t.createdAt).getTime();\n if (ms < 0) return \"—\";\n if (ms < 1000) return `${ms}ms`;\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n const rs = s % 60;\n return `${m}m ${rs}s`;\n }\n\n private toggleToolExpand(id: string): void {\n const next = new Set(this._expandedTools);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedTools = next;\n }\n\n private toggleMessageExpand(id: string): void {\n const next = new Set(this._expandedMessages);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedMessages = next;\n }\n\n private toggleTimelineDetails(id: string): void {\n const next = new Set(this._expandedTimelineDetails);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedTimelineDetails = next;\n }\n\n private expandTimelineDetails(ids: string[]): void {\n this._expandedTimelineDetails = new Set([\n ...this._expandedTimelineDetails,\n ...ids,\n ]);\n }\n\n private collapseTimelineDetails(ids: string[]): void {\n const next = new Set(this._expandedTimelineDetails);\n for (const id of ids) next.delete(id);\n this._expandedTimelineDetails = next;\n }\n\n private toggleRawEventDetails(id: string): void {\n const next = new Set(this._expandedRawEvents);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedRawEvents = next;\n }\n\n private expandRawEventDetails(ids: string[]): void {\n this._expandedRawEvents = new Set([...this._expandedRawEvents, ...ids]);\n }\n\n private collapseRawEventDetails(ids: string[]): void {\n const next = new Set(this._expandedRawEvents);\n for (const id of ids) next.delete(id);\n this._expandedRawEvents = next;\n }\n\n private rawEventId(event: ApiAgentEvent): string {\n return `raw-event-${event.sourceIndex ?? event.timestamp ?? event.type}`;\n }\n\n private get activeEvents(): ApiAgentEvent[] {\n // When the endpoint explicitly returned 501 we report no events rather\n // than leaking the parent's agent-keyed live events across historical\n // threads (those would render identically for every thread on the same\n // agent and mislead the reader).\n if (this._eventsNotAvailable) return [];\n const events = this._fetchedEvents ?? this.agentEventsInput ?? [];\n if (events.every((event) => event.sourceIndex != null)) return events;\n if (this._liveEventsWithSourceIndexCache?.events === events) {\n return this._liveEventsWithSourceIndexCache.indexedEvents;\n }\n const indexedEvents = events.map((event, index) =>\n event.sourceIndex == null ? { ...event, sourceIndex: index + 1 } : event,\n );\n this._liveEventsWithSourceIndexCache = { events, indexedEvents };\n return indexedEvents;\n }\n\n private get activeState(): Record<string, unknown> | null {\n if (this._stateNotAvailable) return null;\n return this._fetchedState ?? this.agentStateInput ?? null;\n }\n\n private hasRenderableState(): boolean {\n const s = this.activeState;\n return !!s && typeof s === \"object\" && Object.keys(s).length > 0;\n }\n\n private shortId(id: string | null | undefined): string {\n if (!id) return \"—\";\n return id.length > 20 ? id.slice(0, 8) + \"…\" : id;\n }\n\n private get metadata(): ThreadDebuggerMetadata | null {\n return this._fetchedMetadata ?? this.thread ?? null;\n }\n\n private fmtTime(dateStr: string | null | undefined): string {\n if (!dateStr) return \"—\";\n const d = new Date(dateStr);\n if (Number.isNaN(d.getTime())) return \"—\";\n return d.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n }\n\n private onDetailDividerDown = (event: PointerEvent): void => {\n this._dividerResizing = true;\n this._dividerPointerId = event.pointerId;\n this._dividerStartX = event.clientX;\n this._dividerStartWidth = this._detailPanelWidth;\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n event.preventDefault();\n };\n\n private onDetailDividerMove = (event: PointerEvent): void => {\n if (!this._dividerResizing || this._dividerPointerId !== event.pointerId)\n return;\n const delta = this._dividerStartX - event.clientX;\n this._detailPanelWidth = Math.max(\n 160,\n Math.min(400, this._dividerStartWidth + delta),\n );\n };\n\n private onDetailDividerUp = (event: PointerEvent): void => {\n if (this._dividerPointerId !== event.pointerId) return;\n const target = event.currentTarget as HTMLElement;\n if (target.hasPointerCapture(this._dividerPointerId)) {\n target.releasePointerCapture(this._dividerPointerId);\n }\n this._dividerResizing = false;\n };\n\n render() {\n const viewInApp = this.renderViewInAppAction();\n return html`\n <div class=\"cpk-td\">\n <!-- ── Left area: tabs + content ─────────────────────────────────── -->\n <div class=\"cpk-td__left\">\n <!-- Tab bar -->\n <div class=\"cpk-td__tabs-header\">\n <div\n class=\"cpk-td__tab-group\"\n role=\"tablist\"\n aria-label=\"Thread detail views\"\n >\n ${CpkThreadInspector.TAB_LIST.map(\n (tab) => html`\n <button\n id=${this.tabDomId(tab.id)}\n type=\"button\"\n role=\"tab\"\n aria-controls=${this.panelDomId(tab.id)}\n aria-selected=${this._tab === tab.id ? \"true\" : \"false\"}\n tabindex=${this._tab === tab.id ? \"0\" : \"-1\"}\n class=\"cpk-td__tab ${\n this._tab === tab.id ? \"cpk-td__tab--active\" : \"\"\n }\"\n @click=${() => this.activateTab(tab.id)}\n @keydown=${(event: KeyboardEvent) =>\n this.handleTabKeyDown(event, tab.id)}\n >\n ${tab.label}\n </button>\n `,\n )}\n </div>\n ${\n viewInApp !== nothing\n ? html`<div class=\"cpk-td__chrome-actions\">${viewInApp}</div>`\n : nothing\n }\n ${this.renderPanelToggle()}\n </div>\n <div class=\"cpk-td__thread-header\">\n ${\n this.showThreadTitle\n ? html`<div class=\"cpk-td__thread-title\">${this.metadata?.name || this.thread?.name || \"Rich Thread\"}</div>`\n : nothing\n }\n ${this._tab === \"timeline\" ? html`<div class=\"cpk-td__pinned-actions\">${this.renderConversationActions()}</div>` : nothing}\n </div>\n\n <!-- Scrollable content -->\n <div class=\"cpk-td__content\">\n ${\n this._panelInitializing\n ? html`\n <div class=\"cpk-td__status\">Loading…</div>\n `\n : nothing\n }\n ${CpkThreadInspector.TAB_LIST.map((tab) =>\n this._activatedTabs.has(tab.id)\n ? html`<div\n id=${this.panelDomId(tab.id)}\n class=\"cpk-td__panel\"\n role=\"tabpanel\"\n aria-labelledby=${this.tabDomId(tab.id)}\n ?hidden=${this._tab !== tab.id || this._panelInitializing}\n >\n ${this.renderTabContent(tab.id)}\n </div>`\n : nothing,\n )}\n </div>\n </div>\n\n <!--\n Drawer always rendered so width animates between 0 and its\n target. Divider lives INSIDE the drawer and is absolutely\n positioned over its left edge so the toggle (rightmost of the\n tab row) and the drawer touch with no flex-gap between them.\n -->\n <div\n class=\"cpk-td__detail\"\n data-open=${this._showDetailPanel ? \"true\" : \"false\"}\n style=\"width:${this._showDetailPanel ? this._detailPanelWidth : 0}px\"\n aria-hidden=${this._showDetailPanel ? \"false\" : \"true\"}\n >\n ${\n this._showDetailPanel\n ? html`\n <div\n class=\"cpk-td__detail-divider\"\n @pointerdown=${this.onDetailDividerDown}\n @pointermove=${this.onDetailDividerMove}\n @pointerup=${this.onDetailDividerUp}\n @pointercancel=${this.onDetailDividerUp}\n ></div>\n `\n : nothing\n }\n ${this.renderDetailPanel()}\n </div>\n </div>\n `;\n }\n\n private renderViewInAppAction() {\n if (this.viewInAppMode === \"hidden\") return nothing;\n const isStop = this.viewInAppMode === \"stop\";\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__view-in-app ${isStop ? \"cpk-td__view-in-app--stop\" : \"\"}\"\n data-testid=\"cpk-inspector-view-in-app\"\n aria-label=${\n isStop\n ? \"Stop viewing this thread in the app\"\n : \"View this thread in your app\"\n }\n @click=${() => {\n this.dispatchEvent(\n new CustomEvent(isStop ? \"stopViewing\" : \"viewInApp\", {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n >\n ${isStop ? \"Stop viewing\" : \"View in your app\"}\n </button>\n ${\n this.viewInAppError\n ? html`<span class=\"cpk-td__view-in-app-error\" role=\"alert\"\n >${this.viewInAppError}</span\n >`\n : nothing\n }\n `;\n }\n\n private renderTryFromHereControl() {\n if (!this.tryFromHereAvailable) return nothing;\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__try-from-here\"\n aria-label=\"Try from here\"\n ?disabled=${this.tryFromHereBusy}\n @click=${this.onTryFromHere}\n >\n ${this.tryFromHereBusy ? \"Loading…\" : \"Try from here\"}\n <svg\n class=\"cpk-td__try-from-here-icon\"\n aria-hidden=\"true\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M7 7h10v10\" />\n <path d=\"M7 17 17 7\" />\n </svg>\n </button>\n ${\n this.tryFromHereError\n ? html`<span class=\"cpk-td__try-from-here-error\" role=\"alert\"\n >${this.tryFromHereError}</span\n >`\n : nothing\n }\n `;\n }\n\n private onTryFromHere = (event: Event): void => {\n event.preventDefault();\n if (!this.tryFromHereAvailable || this.tryFromHereBusy) return;\n this.dispatchEvent(\n new CustomEvent(\"tryFromHere\", {\n detail: this.threadId,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private renderTimelineBulkButtons() {\n if (this._eventsNotAvailable) return nothing;\n\n const detailIds = this.timelineItemsForEvents(this.activeEvents)\n .filter((item) => item.details)\n .map((item) => item.id);\n if (detailIds.length <= 1) return nothing;\n\n const allExpanded = detailIds.every((id) =>\n this._expandedTimelineDetails.has(id),\n );\n\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__timeline-bulk-toggle\"\n @click=${() => (allExpanded ? this.collapseTimelineDetails(detailIds) : this.expandTimelineDetails(detailIds))}\n >\n ${allExpanded ? \"Collapse all\" : \"Expand all\"}\n </button>\n `;\n }\n\n private renderRawEventBulkControls() {\n const eventIds = this.activeEvents.map((event) => this.rawEventId(event));\n if (eventIds.length <= 1) return nothing;\n\n const allExpanded = eventIds.every((id) => this._expandedRawEvents.has(id));\n\n return html`<div class=\"cpk-td__timeline-toolbar\">\n <button\n type=\"button\"\n class=\"cpk-td__timeline-bulk-toggle\"\n @click=${() => (allExpanded ? this.collapseRawEventDetails(eventIds) : this.expandRawEventDetails(eventIds))}\n >\n ${allExpanded ? \"Collapse all\" : \"Expand all\"}\n </button>\n </div>`;\n }\n\n private revealSourceEvent(sourceIndex: number): void {\n this._activatedTabs = new Set([...this._activatedTabs, \"raw-events\"]);\n this._tab = \"raw-events\";\n this.requestUpdate();\n requestAnimationFrame(() => {\n const source = this.shadowRoot?.querySelector<HTMLElement>(\n `[data-source-index=\"${sourceIndex}\"]`,\n );\n source?.scrollIntoView?.({ block: \"center\" });\n });\n }\n\n private renderTimeline() {\n if (this._loadingEvents) {\n return html`\n <div class=\"cpk-td__status\">Loading timeline…</div>\n `;\n }\n if (this._eventsError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._eventsError}\n </div>`;\n }\n if (this._eventsNotAvailable) {\n if (this._conversation.length > 0) {\n return this.renderConversation();\n }\n if (this._loadingMessages) {\n return this.renderConversation();\n }\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>Timeline event history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread AG-UI events. Check State for\n the latest snapshot when available.</span\n >\n </div>\n `;\n }\n\n const events = this.activeEvents;\n const cachedTimeline = this.getCachedPanelTpl(\"timeline\", [\n events,\n this._conversation,\n this.agentMessagesInput,\n this._expandedTimelineDetails,\n ]);\n if (cachedTimeline) return cachedTimeline;\n\n const timelineItems = this.timelineItemsForEvents(events);\n if (timelineItems.length === 0) {\n if (this._conversation.length > 0) {\n return this.renderConversation();\n }\n if (this._loadingMessages) {\n return this.renderConversation();\n }\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>No timeline events captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Timeline rows are normalized from AG-UI events. Open AG-UI Events or State\n to inspect the available thread data.</span\n >\n </div>\n `;\n }\n\n return this.cachedPanelTpl(\n \"timeline\",\n [\n events,\n this._conversation,\n this.agentMessagesInput,\n this._expandedTimelineDetails,\n ],\n () => html`${timelineItems.map((item) => this.renderTimelineItem(item))}`,\n );\n }\n\n private timelineItemClass(item: TimelineItem): string {\n const classes = [\n \"cpk-td__timeline-item\",\n `cpk-td__timeline-item--${item.kind}`,\n ];\n if (item.kind === \"warning\" || item.severity === \"error\") {\n classes.push(\"cpk-td__timeline-item--warning\");\n }\n if (item.kind === \"message\") {\n const title = item.title.toLowerCase();\n if (title.startsWith(\"user\")) {\n classes.push(\"cpk-td__timeline-item--user\");\n } else if (title.includes(\"assistant\")) {\n classes.push(\"cpk-td__timeline-item--assistant\");\n }\n }\n return classes.join(\" \");\n }\n\n private renderTimelineItem(item: TimelineItem) {\n const detailsExpanded = this._expandedTimelineDetails.has(item.id);\n return html`\n <div\n class=${this.timelineItemClass(item)}\n data-message-id=${item.messageId ?? nothing}\n >\n <div class=\"cpk-td__timeline-header\">\n <span class=\"cpk-td__timeline-kind\"\n >${item.severity === \"error\" ? \"error\" : item.kind}</span\n >\n <span class=\"cpk-td__timeline-title\">${item.title}</span>\n ${\n item.sourceIndex\n ? html`\n <button\n type=\"button\"\n class=\"cpk-td__source-link\"\n @click=${() => this.revealSourceEvent(item.sourceIndex)}\n >\n Source event #${item.sourceIndex}\n </button>\n `\n : nothing\n }\n <span class=\"cpk-td__timeline-time\"\n >${formatTimestamp(item.timestamp)}</span\n >\n </div>\n ${\n item.details\n ? html`<button\n type=\"button\"\n class=\"cpk-td__timeline-details-toggle\"\n aria-expanded=${detailsExpanded ? \"true\" : \"false\"}\n @click=${() => this.toggleTimelineDetails(item.id)}\n >\n ${\n detailsExpanded\n ? html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n : html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n `\n }\n <span>${detailsExpanded ? \"Hide details\" : \"Show details\"}</span>\n </button>`\n : nothing\n }\n ${\n item.body\n ? html`<div class=\"cpk-td__timeline-body\">${item.body}</div>`\n : nothing\n }\n ${\n item.details && detailsExpanded\n ? renderHighlightedJsonBlock(item.details)\n : nothing\n }\n </div>\n `;\n }\n\n private renderConversation() {\n if (this._loadingMessages) {\n return html`\n <div class=\"cpk-td__status\">Loading messages…</div>\n `;\n }\n if (this._messagesError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._messagesError}\n </div>`;\n }\n if (this._conversation.length === 0) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n <span>No messages yet</span>\n </div>\n `;\n }\n // Expand state is part of the cache key because clicking a tool-call\n // header or the \"Show more\" button on a long message replaces\n // `_expandedTools` / `_expandedMessages` without touching\n // `_conversation` — without those keys the cache returns the\n // pre-toggle template and the disclosure appears broken.\n return this.cachedPanelTpl(\n \"timeline-fallback\",\n [this._conversation, this._expandedTools, this._expandedMessages],\n () => {\n const items = this.renderItems;\n return html`${items.map((item) => this.renderRenderItem(item))}`;\n },\n );\n }\n\n /**\n * Memoize the rendered TemplateResult for `slot` keyed by tuple\n * element-wise reference equality. The hot path for tab switches: when\n * the underlying data hasn't changed, return the previously built\n * TemplateResult so Lit's diff short-circuits. Each panel's `key` is\n * the tuple of inputs the template reads — pass everything the template\n * depends on, or the cache will return stale output when those inputs\n * change without the listed key flipping.\n */\n private cachedPanelTpl(\n slot: ThreadDetailsPanelCacheSlot,\n key: readonly unknown[],\n build: () => TemplateResult,\n ): TemplateResult {\n const cached = this.getCachedPanelTpl(slot, key);\n if (cached) return cached;\n const tpl = build();\n this._panelTplCache.set(slot, { key, tpl });\n return tpl;\n }\n\n private getCachedPanelTpl(\n slot: ThreadDetailsPanelCacheSlot,\n key: readonly unknown[],\n ): TemplateResult | null {\n const cached = this._panelTplCache.get(slot);\n if (\n cached &&\n cached.key.length === key.length &&\n cached.key.every((v, i) => v === key[i])\n ) {\n return cached.tpl;\n }\n return null;\n }\n\n private renderRenderItem(item: RenderItem) {\n switch (item.type) {\n case \"user\":\n case \"assistant\":\n return this.renderBubble(item);\n case \"tool_call\":\n return this.renderToolBlock(item);\n case \"tool_call_group\":\n return this.renderToolGroup(item);\n case \"reasoning\":\n return html`<div class=\"cpk-td__inline-chip\">\n <span>Reasoned for ${item.duration}</span>\n </div>`;\n case \"state_update\":\n return html`\n <div class=\"cpk-td__inline-chip\">\n <span>Updated agent state</span>\n </div>\n `;\n case \"generative-ui\":\n return this.renderGenerativeUI(item);\n case \"agent_responded\":\n return nothing;\n }\n }\n\n private renderBubble(item: ConversationUser | ConversationAssistant) {\n const isUser = item.type === \"user\";\n const threshold = CpkThreadInspector.COLLAPSE_THRESHOLD;\n const expanded = this._expandedMessages.has(item.id);\n const tooLong = item.content.length > threshold;\n const shown =\n tooLong && !expanded\n ? item.content.slice(0, threshold) + \"…\"\n : item.content;\n return html`\n <div\n class=\"cpk-td__bubble ${\n isUser ? \"cpk-td__bubble--user\" : \"cpk-td__bubble--assistant\"\n }\"\n data-message-id=${item.id}\n role=\"group\"\n aria-label=${isUser ? \"User message\" : \"Assistant message\"}\n >\n <div\n class=\"cpk-td__bubble-inner ${\n isUser\n ? \"cpk-td__bubble-inner--user\"\n : \"cpk-td__bubble-inner--assistant\"\n }\"\n >\n <div style=\"white-space:pre-wrap\">${shown}</div>\n ${\n tooLong\n ? html`<span\n class=\"cpk-td__show-more\"\n @click=${() => this.toggleMessageExpand(item.id)}\n >${expanded ? \"Show less\" : \"Show more\"}</span\n >`\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private renderToolBlock(item: ConversationToolCall) {\n const expanded = this._expandedTools.has(item.id);\n return html`\n <div class=\"cpk-td__tool-block\">\n <div\n class=\"cpk-td__tool-header\"\n @click=${() => this.toggleToolExpand(item.id)}\n >\n <svg width=\"10\" height=\"10\" viewBox=\"0 0 10 10\" fill=\"none\">\n <path\n d=\"M1 9C1 9 2 7 5 7C8 7 9 9 9 9M5 1C5 1 7 2.5 7 4.5C7 6.5 5 7 5 7C5 7 3 6.5 3 4.5C3 2.5 5 1 5 1Z\"\n stroke=\"currentColor\"\n stroke-width=\"1.2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <span class=\"cpk-td__tool-name\">${item.toolName}</span>\n ${\n item.result || Object.keys(item.arguments).length > 0\n ? html`\n <span class=\"cpk-td__tool-status\">Complete</span>\n `\n : html`\n <span class=\"cpk-td__tool-status cpk-td__tool-status--pending\">Pending</span>\n `\n }\n <span class=\"cpk-td__tool-chevron\">${expanded ? \"▾\" : \"▸\"}</span>\n </div>\n ${\n expanded\n ? html`\n <div class=\"cpk-td__tool-body\">\n <div class=\"cpk-td__tool-section-label\">Arguments</div>\n ${renderHighlightedJsonBlock(item.arguments)}\n ${\n item.result\n ? html`\n <div\n class=\"cpk-td__tool-section-label\"\n style=\"margin-top:8px\"\n >\n Result\n </div>\n ${renderHighlightedJsonBlock(item.result)}\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private renderToolGroup(group: ToolCallGroup) {\n return html`\n <div class=\"cpk-td__tool-group\">\n <div class=\"cpk-td__tool-group-header\">\n ${group.items.length} tool call${group.items.length !== 1 ? \"s\" : \"\"}\n </div>\n ${group.items.map((tc) => this.renderToolBlock(tc))}\n </div>\n `;\n }\n\n private renderGenerativeUI(item: ConversationGenerativeUIItem) {\n return html`\n <div class=\"cpk-td__genui\">\n <div class=\"cpk-td__genui-badge\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n <span>Generative UI</span>\n <code class=\"cpk-td__genui-component\">${item.activityType}</code>\n </div>\n </div>\n `;\n }\n\n private renderState() {\n if (this._loadingState) {\n return html`\n <div class=\"cpk-td__status\">Loading state…</div>\n `;\n }\n if (this._stateError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._stateError}\n </div>`;\n }\n if (this._stateNotAvailable) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n <span>State history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread agent state. Available when\n running against the in-memory runner.</span\n >\n </div>\n `;\n }\n if (!this.hasRenderableState()) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n <span>No state captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Emitted live from STATE_SNAPSHOT events.</span\n >\n </div>\n `;\n }\n const stateValue = this.activeState;\n return this.cachedPanelTpl(\"state\", [stateValue], () => {\n return renderHighlightedJsonBlock(stateValue);\n });\n }\n\n private renderEvents() {\n if (this._loadingEvents) {\n return html`\n <div class=\"cpk-td__status\">Loading events…</div>\n `;\n }\n if (this._eventsError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._eventsError}\n </div>`;\n }\n if (this._eventsNotAvailable) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>Event history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread AG-UI events. Available when\n running against the in-memory runner.</span\n >\n </div>\n `;\n }\n const events = this.activeEvents;\n if (events.length === 0) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>No events captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Events are recorded live. Run the agent to see them here.</span\n >\n </div>\n `;\n }\n return this.cachedPanelTpl(\n \"raw-events\",\n [events, this._expandedRawEvents],\n () => {\n return html`${this.renderRawEventBulkControls()}${events.map(\n (event) => {\n const eventId = this.rawEventId(event);\n const detailsExpanded = this._expandedRawEvents.has(eventId);\n return html`\n <div\n class=\"cpk-td__event cpk-td__event--${eventCategory(\n event.type,\n )}\"\n data-source-index=${event.sourceIndex}\n >\n <div class=\"cpk-td__event-header\">\n <span class=\"cpk-td__event-type\" title=${event.type}\n >${humanizeEventType(event.type)}</span\n >\n <span class=\"cpk-td__event-time\"\n >${formatTimestamp(event.timestamp)}</span\n >\n </div>\n <button\n type=\"button\"\n class=\"cpk-td__timeline-details-toggle\"\n aria-expanded=${detailsExpanded ? \"true\" : \"false\"}\n @click=${() => this.toggleRawEventDetails(eventId)}\n >\n ${\n detailsExpanded\n ? html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n : html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n `\n }\n <span\n >${detailsExpanded ? \"Hide details\" : \"Show details\"}</span\n >\n </button>\n ${\n detailsExpanded\n ? renderHighlightedJsonBlock(event.rawEvent ?? event)\n : nothing\n }\n </div>\n `;\n },\n )}`;\n },\n );\n }\n\n private renderPanelToggle() {\n return html`\n <button\n class=\"cpk-td__panel-toggle ${\n this._showDetailPanel ? \"cpk-td__panel-toggle--active\" : \"\"\n }\"\n @click=${() => {\n this._showDetailPanel = !this._showDetailPanel;\n }}\n title=\"Toggle thread details\"\n type=\"button\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n </button>\n `;\n }\n\n private renderDetailPanel() {\n const counts = this.activityCounts;\n const metadata = this.metadata;\n return html`\n <!-- Thread -->\n <div class=\"cpk-tdp__section-title\">Thread</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">ID</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--wrap\"\n >${metadata?.id ?? this.threadId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Name</span>\n <span class=\"cpk-tdp__value\">${metadata?.name ?? \"—\"}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Agent</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.agentId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">End user</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.endUserId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Created by</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.createdById ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Status</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.status ?? \"—\"}</span\n >\n </div>\n\n <div class=\"cpk-tdp__divider\"></div>\n\n <!-- Timestamps -->\n <div class=\"cpk-tdp__section-title\">Timestamps</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Created</span>\n <span class=\"cpk-tdp__value\">${this.fmtTime(metadata?.createdAt)}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Updated</span>\n <span class=\"cpk-tdp__value\">${this.fmtTime(metadata?.updatedAt)}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Duration</span>\n <span class=\"cpk-tdp__value\">${this.duration}</span>\n </div>\n\n <div class=\"cpk-tdp__divider\"></div>\n\n <!-- Activity -->\n <div class=\"cpk-tdp__section-title\">Activity</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Messages</span>\n <span class=\"cpk-tdp__value\">${counts.messages}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Tool calls</span>\n <span class=\"cpk-tdp__value\">${counts.toolCalls}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">AG-UI events</span>\n <span class=\"cpk-tdp__value\">${this.activeEvents.length}</span>\n </div>\n `;\n }\n}\n\n// ─── memory recall relevance helpers ─────────────────────────────────────────\n\n/**\n * Normalizes a memory's raw recall score to a 0..1 relevance ratio relative to\n * the strongest result in the same result set. Recall scores are RRF scores\n * (relative), so a bar is only meaningful against the set max. Returns\n * `undefined` when no meaningful ranking exists (empty set, non-positive max,\n * missing score) so the caller renders no bar.\n */\nfunction normalizeRelevance(\n score: number | undefined,\n maxScore: number,\n): number | undefined {\n if (maxScore <= 0) return undefined;\n if (score === undefined || !Number.isFinite(score)) return undefined;\n const ratio = score / maxScore;\n if (ratio <= 0) return 0;\n return ratio > 1 ? 1 : ratio;\n}\n\n/** Largest finite `score` across a result set, or 0 when none present. */\nfunction maxRecallScore(memories: readonly Memory[]): number {\n let max = 0;\n for (const m of memories) {\n const s = m.score;\n if (typeof s === \"number\" && Number.isFinite(s) && s > max) max = s;\n }\n return max;\n}\n\n/**\n * Percent width for a relevance bar. Mirrors the banking reference\n * (`max(6, round(rel*100))%`) so a matched-but-weak result still shows a sliver.\n * Returns a whole number in [6, 100].\n */\nfunction relevanceBarWidth(relevance: number): number {\n return Math.max(6, Math.min(100, Math.round(relevance * 100)));\n}\n\nexport {\n normalizeRelevance as ɵnormalizeRelevance,\n maxRecallScore as ɵmaxRecallScore,\n relevanceBarWidth as ɵrelevanceBarWidth,\n};\n\n// ─── cpk-memory-list ─────────────────────────────────────────────────────────\n\n/** Memory kind values including the \"all\" sentinel used by the filter UI. */\ntype MemoryKindFilter = \"all\" | \"topical\" | \"episodic\" | \"operational\";\n\nclass CpkMemoryList extends PortableLitElement {\n static properties = {\n memories: { attribute: false },\n recallResults: { attribute: false },\n recallLoading: { attribute: false },\n recallError: { attribute: false },\n recallQueryText: { attribute: false },\n search: { state: true },\n kind: { state: true },\n };\n\n /** Ordered (newest-first) list of memories supplied by the parent. */\n memories: Memory[] = [];\n /** Semantic-recall results. `null` = no recall run (section hidden); `[]` = ran, no matches. */\n recallResults: Memory[] | null = null;\n /** True while a recall request is in flight. */\n recallLoading = false;\n /** Error message from the most recent recall attempt, or null. */\n recallError: string | null = null;\n /** The recall input text (owned by the parent). */\n recallQueryText = \"\";\n private search = \"\";\n private kind: MemoryKindFilter = \"all\";\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .cpk-ml {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: #f7f7f9;\n }\n\n /* ── Search ── */\n .cpk-ml__search {\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n\n .cpk-ml__search-input {\n width: 100%;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .cpk-ml__search-input:focus {\n border-color: #bec2ff;\n }\n\n /* ── Kind filter ── */\n .cpk-ml__filter {\n display: flex;\n gap: 4px;\n padding: 8px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n flex-wrap: wrap;\n }\n\n .cpk-ml__filter-seg {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 3px 9px;\n border-radius: 6px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #57575b;\n cursor: pointer;\n transition:\n background 0.1s,\n border-color 0.1s,\n color 0.1s;\n user-select: none;\n }\n\n .cpk-ml__filter-seg:hover {\n background: #f0f0f5;\n }\n\n .cpk-ml__filter-seg--active {\n background: #bec2ff1a;\n border-color: #bec2ff;\n color: #010507;\n }\n\n .cpk-ml__filter-count {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n margin-left: 4px;\n color: #68686e;\n }\n\n /* ── List ── */\n .cpk-ml__list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* ── Card ── */\n .cpk-ml__card {\n background: #ffffff;\n border: 1px solid #e9e9ef;\n border-radius: 10px;\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .cpk-ml__card-badges {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n /* Kind badge — color per kind */\n .cpk-ml__kind-badge {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n }\n\n .cpk-ml__kind-badge--topical {\n background: #eee6fe;\n color: #57575b;\n }\n\n .cpk-ml__kind-badge--episodic {\n background: #e6f4fe;\n color: #2d5f80;\n }\n\n .cpk-ml__kind-badge--operational {\n background: #e6feee;\n color: #2d6645;\n }\n\n /* Scope badge */\n .cpk-ml__scope-badge {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n background: #f0f0f5;\n color: #68686e;\n }\n\n /* Content */\n .cpk-ml__content {\n font-size: 12px;\n color: #010507;\n line-height: 1.5;\n word-break: break-word;\n }\n\n /* Footer */\n .cpk-ml__footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 2px;\n }\n\n .cpk-ml__footer-threads {\n font-size: 10px;\n color: #68686e;\n }\n\n .cpk-ml__footer-id {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #c0c0c8;\n }\n\n /* ── Empty state ── */\n .cpk-ml__empty {\n padding: 32px 16px;\n text-align: center;\n color: #68686e;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .cpk-ml__empty-icon {\n color: #c0c0c8;\n }\n\n /* ── Recall ── */\n .cpk-ml__recall {\n display: flex;\n gap: 6px;\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n .cpk-ml__recall-input {\n flex: 1;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #fff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n .cpk-ml__recall-input:focus {\n border-color: #bec2ff;\n }\n .cpk-ml__recall-btn {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 500;\n padding: 7px 12px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #fff;\n color: #010507;\n cursor: pointer;\n transition: background 0.1s;\n }\n .cpk-ml__recall-btn:hover:not(:disabled) {\n background: #f0f0f5;\n }\n .cpk-ml__recall-btn:disabled {\n opacity: 0.4;\n cursor: default;\n }\n .cpk-ml__recall-section {\n flex-shrink: 0;\n max-height: 45%;\n overflow-y: auto;\n padding: 8px 12px;\n border-bottom: 1px solid #dbdbe5;\n background: #fbfbfd;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .cpk-ml__recall-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .cpk-ml__recall-title {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 600;\n color: #010507;\n }\n .cpk-ml__recall-clear {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 10px;\n color: #68686e;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n }\n .cpk-ml__recall-clear:hover {\n color: #010507;\n }\n .cpk-ml__recall-msg {\n font-size: 11px;\n color: #68686e;\n line-height: 1.45;\n }\n .cpk-ml__recall-msg--error {\n color: #c0333a;\n }\n\n /* ── Relevance bar ── */\n .cpk-ml__relevance {\n height: 4px;\n width: 100%;\n overflow: hidden;\n border-radius: 9999px;\n background: #f0f0f5;\n }\n .cpk-ml__relevance-fill {\n height: 100%;\n border-radius: 9999px;\n background: #6366f1;\n }\n\n /* ── Scope badge variants ── */\n .cpk-ml__scope-badge--user {\n background: #f0f0f5;\n color: #68686e;\n }\n .cpk-ml__scope-badge--project {\n background: #fef3c7;\n color: #92660c;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml {\n background: #15171e;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__search,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-section,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__card {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__search-input,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-input,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-btn,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__card {\n border-color: #464957;\n background: #191c24;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-section {\n background: #171a22;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-btn:hover:not(:disabled) {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg--active {\n border-color: #777aae;\n background: #292b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__content,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-title {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-count,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__footer-threads,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__footer-id,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__empty,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-clear,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-msg {\n color: #aeb1bd;\n }\n `;\n\n /** Memories that pass the current text search (before kind filter). */\n private get searchFiltered(): Memory[] {\n const q = this.search.trim().toLowerCase();\n if (!q) return this.memories;\n return this.memories.filter((m) => m.content.toLowerCase().includes(q));\n }\n\n /** Memories that pass both search and kind filter. */\n private get filtered(): Memory[] {\n const searched = this.searchFiltered;\n if (this.kind === \"all\") return searched;\n return searched.filter((m) => m.kind === this.kind);\n }\n\n /** Count of search-filtered memories for a given kind (for segment labels). */\n private countForKind(kind: Exclude<MemoryKindFilter, \"all\">): number {\n return this.searchFiltered.filter((m) => m.kind === kind).length;\n }\n\n private onSearchInput = (event: Event): void => {\n this.search = (event.target as HTMLInputElement).value;\n };\n\n private onKindClick = (event: Event): void => {\n const seg = (event.target as HTMLElement).closest(\"[data-kind]\");\n if (!seg) return;\n const k = (seg as HTMLElement).dataset[\"kind\"] as MemoryKindFilter;\n this.kind = k;\n };\n\n /** Truncate an id to first-4…last-4 characters. */\n private shortId(id: string): string {\n if (id.length <= 12) return id;\n return `${id.slice(0, 4)}…${id.slice(-4)}`;\n }\n\n private renderKindBadge(kind: string): TemplateResult {\n return html`<span class=\"cpk-ml__kind-badge cpk-ml__kind-badge--${kind}\"\n >${kind}</span\n >`;\n }\n\n private renderScopeBadge(scope: string): TemplateResult {\n const variant = scope === \"project\" ? \"project\" : \"user\";\n return html`<span\n class=\"cpk-ml__scope-badge cpk-ml__scope-badge--${variant}\"\n >${scope}</span\n >`;\n }\n\n /**\n * Renders one memory card. `relevance` (0..1) is supplied only for recall\n * results — when present a relevance bar is drawn; the full list omits it.\n */\n private renderCard(m: Memory, relevance?: number): TemplateResult {\n const threads = m.sourceThreadIds.length;\n return html`\n <div class=\"cpk-ml__card\">\n <div class=\"cpk-ml__card-badges\">\n ${this.renderKindBadge(m.kind)}${this.renderScopeBadge(m.scope)}\n </div>\n <div class=\"cpk-ml__content\">${m.content}</div>\n ${\n relevance !== undefined\n ? html`<div class=\"cpk-ml__relevance\">\n <div\n class=\"cpk-ml__relevance-fill\"\n style=\"width:${relevanceBarWidth(relevance)}%;\"\n ></div>\n </div>`\n : nothing\n }\n <div class=\"cpk-ml__footer\">\n <span class=\"cpk-ml__footer-threads\"\n >${threads} source thread${threads === 1 ? \"\" : \"s\"}</span\n >\n <span class=\"cpk-ml__footer-id\">${this.shortId(m.id)}</span>\n </div>\n </div>\n `;\n }\n\n private onRecallInput = (event: Event): void => {\n const value = (event.target as HTMLInputElement).value;\n this.recallQueryText = value;\n this.dispatchEvent(\n new CustomEvent<string>(\"recallQueryChanged\", {\n detail: value,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private onRecallSubmit = (event: Event): void => {\n event.preventDefault();\n const query = this.recallQueryText.trim();\n if (query.length === 0 || this.recallLoading) return;\n this.dispatchEvent(\n new CustomEvent<string>(\"recallSubmitted\", {\n detail: query,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private onRecallClear = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"recallCleared\", { bubbles: true, composed: true }),\n );\n };\n\n private renderRecallForm(): TemplateResult {\n const disabled =\n this.recallLoading || this.recallQueryText.trim().length === 0;\n return html`\n <form class=\"cpk-ml__recall\" @submit=${this.onRecallSubmit}>\n <input\n type=\"text\"\n placeholder=\"Recall by meaning…\"\n aria-label=\"Recall learning records by meaning\"\n class=\"cpk-ml__recall-input\"\n .value=${this.recallQueryText}\n @input=${this.onRecallInput}\n />\n <button type=\"submit\" class=\"cpk-ml__recall-btn\" ?disabled=${disabled}>\n ${this.recallLoading ? \"…\" : \"Recall\"}\n </button>\n </form>\n `;\n }\n\n private renderRecallSection(): TemplateResult {\n const results = this.recallResults;\n if (results === null) return html``;\n const max = maxRecallScore(results);\n return html`\n <section\n class=\"cpk-ml__recall-section\"\n aria-label=\"Semantic recall results\"\n >\n <div class=\"cpk-ml__recall-header\">\n <span class=\"cpk-ml__recall-title\"\n >Semantic recall (${results.length})</span\n >\n <button\n type=\"button\"\n class=\"cpk-ml__recall-clear\"\n @click=${this.onRecallClear}\n >\n Clear\n </button>\n </div>\n ${\n this.recallError\n ? html`<p class=\"cpk-ml__recall-msg cpk-ml__recall-msg--error\">\n Recall failed: ${this.recallError}\n </p>`\n : results.length === 0\n ? html`\n <p class=\"cpk-ml__recall-msg\">No learning records matched that query.</p>\n `\n : results.map((m) =>\n this.renderCard(m, normalizeRelevance(m.score, max)),\n )\n }\n </section>\n `;\n }\n\n private renderEmpty(): TemplateResult {\n const q = this.search.trim();\n if (this.memories.length === 0) {\n return html`\n <div class=\"cpk-ml__empty\">\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-ml__empty-icon\"\n >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n No learning records yet — tell the agent a durable fact and watch it appear.\n </div>\n `;\n }\n if (q) {\n return html`\n <div class=\"cpk-ml__empty\">\n No learning records match &ldquo;${q}&rdquo;.\n </div>\n `;\n }\n return html`\n <div class=\"cpk-ml__empty\">No ${this.kind} learning records yet.</div>\n `;\n }\n\n render() {\n const filtered = this.filtered;\n const kinds: Array<Exclude<MemoryKindFilter, \"all\">> = [\n \"topical\",\n \"episodic\",\n \"operational\",\n ];\n\n return html`\n <div class=\"cpk-ml\">\n <!-- Semantic recall -->\n ${this.renderRecallForm()} ${this.renderRecallSection()}\n\n <!-- Search -->\n <div class=\"cpk-ml__search\">\n <input\n type=\"text\"\n placeholder=\"Search learning…\"\n .value=${this.search}\n @input=${this.onSearchInput}\n class=\"cpk-ml__search-input\"\n />\n </div>\n\n <!-- Kind filter -->\n <div class=\"cpk-ml__filter\" @click=${this.onKindClick}>\n <button\n class=\"cpk-ml__filter-seg ${\n this.kind === \"all\" ? \"cpk-ml__filter-seg--active\" : \"\"\n }\"\n data-kind=\"all\"\n >\n All<span class=\"cpk-ml__filter-count\"\n >${this.searchFiltered.length}</span\n >\n </button>\n ${kinds.map(\n (k) => html`\n <button\n class=\"cpk-ml__filter-seg ${\n this.kind === k ? \"cpk-ml__filter-seg--active\" : \"\"\n }\"\n data-kind=\"${k}\"\n >\n ${k}<span class=\"cpk-ml__filter-count\"\n >${this.countForKind(k)}</span\n >\n </button>\n `,\n )}\n </div>\n\n <!-- Memory list -->\n <div class=\"cpk-ml__list\">\n ${filtered.map((m) => this.renderCard(m))}\n ${filtered.length === 0 ? this.renderEmpty() : nothing}\n </div>\n </div>\n `;\n }\n}\n\n// Backwards-compatible internal element name used by the full CopilotKit\n// Inspector shell. Keep this class thin so the public body remains the single\n// implementation.\nexport class ɵCpkThreadDetails extends CpkThreadInspector {}\n\nfunction defineElementOnce(\n registry: CustomElementRegistry,\n tag: string,\n ctor: CustomElementConstructor,\n): void {\n if (!registry.get(tag)) {\n registry.define(tag, ctor);\n }\n}\n\nexport class WebInspectorElement extends LitElement {\n static properties = {\n core: { attribute: false },\n autoAttachCore: { type: Boolean, attribute: \"auto-attach-core\" },\n _capabilitiesVersion: { state: true },\n } as const;\n\n private _core: CopilotKitCore | null = null;\n private coreSubscriber: CopilotKitCoreSubscriber | null = null;\n private coreUnsubscribe: (() => void) | null = null;\n private _memories: Memory[] = [];\n private _memoriesLoading = false;\n private _memoriesError: Error | null = null;\n private _memoriesAvailable = true;\n // Realtime-connection health, independent of `_memoriesAvailable` (the REST\n // list route). Drives the \"live\" indicator: only \"connected\" shows \"live\".\n private _memoriesRealtimeStatus: MemoryRealtimeStatus = \"connecting\";\n private _memoryUnsub: (() => void) | null = null;\n // Lazy-subscription guard. The memory store is created + started + opens\n // realtime the first time `core.getMemoryStore()` is called, so we defer\n // that call until the user actually activates the Memories tab (see\n // `ensureMemorySubscription`). This flag prevents a repeated tab click from\n // double-subscribing; `detachFromCore` resets it so a later attach + tab\n // activation re-subscribes cleanly.\n private _memorySubscribed = false;\n // True when the attached core predates `getMemoryStore` (older @copilotkit\n // SDK). Distinct from `_memoriesAvailable` (memory not enabled on an\n // otherwise-current deployment) so the teaser can show upgrade-the-SDK copy.\n private _memoryStoreUnsupported = false;\n private learningSnapshot: InspectorLearningSnapshotV1 | null = null;\n private learningSnapshotScope: string | null = null;\n private learningProjectIdentity: string | null = null;\n private learningLoading = false;\n private learningRefreshing = false;\n private learningError: string | null = null;\n private learningSupported = false;\n private learningRequestGeneration = 0;\n private learningAbortController: AbortController | null = null;\n private learningPollTimer: ReturnType<typeof setTimeout> | null = null;\n private learningPollFailureCount = 0;\n private learningSetupMarker: LearningSetupMarker | null = null;\n private learningSetupCopyRequest = 0;\n private learningSetupUnsubscribe: (() => void) | null = null;\n private learningPromptCopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n private learningPromptRecopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n private learningPromptRecopyTimer: ReturnType<typeof setTimeout> | null =\n null;\n private learningViewedState: LearningViewState | null = null;\n // ── Semantic recall (B3) ──────────────────────────────────────────────\n // `null` = no recall run yet (section hidden). `[]` = ran, no matches.\n private _recallResults: Memory[] | null = null;\n private _recallLoading = false;\n private _recallError: string | null = null;\n private _recallQuery = \"\";\n // Monotonic token so a slow recall resolving after a newer one / Clear /\n // detach is ignored — last-write-wins without racing state.\n private _recallSeq = 0;\n private runtimeStatus: CopilotKitCoreRuntimeConnectionStatus | null = null;\n private inspectorMetadataValue: unknown;\n private inspectorMetadataProjection: InspectorMetadataProjection =\n projectInspectorMetadata(undefined, undefined);\n // The last *visible* local fingerprint for each metadata module. This is a\n // map rather than a cumulative set so A → B → A produces three impressions,\n // while close/reopen with unchanged metadata produces only one. Fingerprint\n // values can contain local labels and URLs because the map never leaves the\n // browser; outbound helpers rebuild a coarse allowlisted payload.\n private metadataTelemetryFingerprints: Map<\n InspectorMetadataTelemetryModule,\n string\n > = new Map();\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 // Per-thread monotonic version that ticks every time an agent currently\n // running on that thread emits a message change. `cpk-thread-details`\n // watches this prop and re-fetches `/threads/:id/messages` when it changes,\n // which is how live updates flow into the conversation view without\n // duplicating the runtime's message-shape conversion in the inspector.\n private liveMessageVersion: Map<string, number> = 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 accountCtaMotionPaused = false;\n private draggedDuringInteraction = false;\n private ignoreNextButtonClick = false;\n private selectedMenu: MenuKey = \"home\";\n private pendingPersistedMenu: MenuKey | null = null;\n private hasOpenedInspector = false;\n private sidebarCollapsed = false;\n private sidebarRailTooltip: { label: string; top: number } | null = null;\n private colorScheme: InspectorColorScheme = \"light\";\n private hasExplicitColorScheme = false;\n private systemColorSchemeMediaQuery: MediaQueryList | null = null;\n private briefingRestoreMenu: MenuKey | null = null;\n private homeViewedThisOpen = false;\n\n // ── Intelligence install prompt (Home) ──────────────────────────────────\n //\n // One run id per element lifetime, minted on first copy. The CLI treats the\n // id as one onboarding journey, so a developer who copies twice because they\n // switched editors must not look like two journeys.\n private onboardingRunId: string | null = null;\n /**\n * `copied` reverts after {@link PROMPT_COPY_RESET_MS}; `failed` does not.\n *\n * The instruction only has to survive long enough to be read. Keeping it\n * forever left a button wearing a checkmark and reading as spent, which is\n * the wrong signal for the likeliest reason someone comes back to this card:\n * to copy again. A failed copy is the opposite case — the prompt itself is\n * on screen to be selected by hand, so it stays until acted on.\n */\n private promptCopyState: \"idle\" | \"copied\" | \"failed\" = \"idle\";\n private promptCopyResetTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ── Intelligence story (Home) ───────────────────────────────────────────\n //\n // Three beats condensed from the six-phase animation on the Intelligence\n // home page. Runs only while Home is the visible tab AND the document is\n // visible: this is a debugging tool, and a permanent timer behind a closed\n // panel is exactly the kind of thing a developer would find in a profile and\n // rightly complain about.\n private intelStoryBeat = 0;\n private intelStoryUserPinned = false;\n private intelStoryTimer: ReturnType<typeof setTimeout> | null = null;\n private intelStoryReducedMotion: MediaQueryList | null = null;\n private hasResolvedCore = false;\n private settingsOpen = false;\n private readonly lastSelectedMenuByGroup: Record<\n InspectorNavGroupKey,\n MenuKey\n > = {\n home: \"home\",\n workbench: \"threads\",\n inspect: \"ag-ui-events\",\n };\n private lastScrolledAgentNavigationLayout: string | null = null;\n private selectedThreadId: string | null = null;\n private ephemeralThreadsSetupOpen = false;\n private inAppThreadId: string | null = null;\n private inAppAgentId: string | null = null;\n private inAppSource: \"app\" | \"override\" | null = null;\n private activeViewInAppRequestId: string | null = null;\n private viewInAppError: string | null = null;\n private inspectorBridgeUnsubscribers: Array<() => void> = [];\n private selectedRealThreadIsExplicit = false;\n private selectedLocalExampleThreadId: string | null = null;\n private requestedThreadId: string | null = null;\n private focusedThreadMessageId: string | null = null;\n private threadFocusRequestId = 0;\n private threadListWidth = 240;\n private threadListCollapsed = false;\n private threadDividerResizing = false;\n private threadDividerPointerId = -1;\n private threadDividerStartX = 0;\n private threadDividerStartWidth = 0;\n private _threads: ɵThread[] = [];\n private _threadStoreSubscriptions: Map<string, () => void> = new Map();\n private _threadsByAgent: Map<string, ɵThread[]> = new Map();\n private threadUsageSignature = \"\";\n private threadUsageRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n // Error from each agent's thread store (REST list rejection, Phoenix\n // subscribe failure, retry exhaustion). When non-empty for the active\n // selection, the threads view renders an error state instead of stale\n // data with no indication.\n private _threadsErrorByAgent: Map<string, Error> = new Map();\n private _threadsLoadingByAgent: Map<string, boolean> = new Map();\n // Thread stores created and owned by the inspector (keyed by agentId)\n private _ownedThreadStores: Map<string, ɵThreadStore> = new Map();\n private playgroundAgent: AbstractAgent | null = null;\n private playgroundAgentId: string | null = null;\n private playgroundAgentUnsubscribe: (() => void) | null = null;\n private playgroundMessages: InspectorMessage[] = [];\n private playgroundInput = \"\";\n private playgroundIsRunning = false;\n private playgroundRunStartedAt: number | null = null;\n private playgroundReasoningDurations: Map<string, number> = new Map();\n private playgroundIsLoadingThread = false;\n private playgroundError: string | null = null;\n private playgroundSourceThreadId: string | null = null;\n private playgroundShowEphemeralNotice = false;\n private tryFromHereBusy = false;\n private tryFromHereError: string | null = null;\n private threadCapabilityEnabled: boolean | null = null;\n private threadCapabilityGeneration = 0;\n private contextMenuOpen = false;\n private iconRailContextCloseTimer: ReturnType<typeof setTimeout> | null =\n null;\n private layoutMenuOpen = false;\n private dockMode: DockMode = \"floating\";\n private popOut: PopOutHandle | null = null;\n private inspectorPortal: HTMLDivElement | null = null;\n private previousBodyMargins: { left: string; bottom: string } | null = null;\n private previousHtmlOverflowX: string | null = null;\n private transitionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private bodyTransitionTimeoutIds: Set<ReturnType<typeof setTimeout>> =\n new Set();\n private pendingSelectedContext: string | null = null;\n public autoAttachCore = true;\n private attemptedAutoAttach = false;\n private cachedTools: InspectorToolDefinition[] = [];\n private toolSignature = \"\";\n // Bumped after every core.setToolEnabled / core.setCatalogComponentEnabled\n // call so the Capabilities tab re-paints from the fresh isToolEnabled /\n // isCatalogComponentEnabled getters. There is no core subscriber for\n // enablement changes — the inspector itself drives the toggle, so we force\n // the re-render locally.\n private _capabilitiesVersion = 0;\n private eventFilterText = \"\";\n private eventTypeFilter: InspectorAgentEventType | \"all\" = \"all\";\n // Column widths for the AG-UI events table (agent, time, event-type; last col is auto)\n private evtColWidths = [100, 80, 150];\n private _evtColResize: {\n col: number;\n startX: number;\n startW: number;\n } | null = null;\n\n private announcementHtml: string | null = null;\n private announcementMarkdown: string | null = null;\n private announcementTimestamp: string | null = null;\n private announcementPreviewText: string | null = null;\n // Forward-compat for an optional `cta_label` field on the announcement\n // CDN payload (e.g. \"Try threads\", \"New feature\"). The current schema\n // ({timestamp, previewText, announcement}) doesn't carry it, so this is\n // null in production today; we read it defensively in fetchAnnouncement\n // so a future CDN-side schema bump lights up `cta_label` on\n // whats_new_clicked without an inspector release.\n private announcementCtaLabel: string | null = null;\n private announcementLoaded = false;\n private announcementPromise: Promise<void> | null = null;\n private newsSignalArmed = false;\n /** Which signal's beat is in flight, or null between beats. */\n private pulsingSignal: LauncherSignalKey | null = null;\n /**\n * The single pending-beat slot. A beat that cannot land is deferred, never\n * discarded — see `startSignalPulse` for the five reasons it cannot land.\n */\n private pendingPulseSignal: LauncherSignalKey | null = null;\n private pulseTimeoutId: ReturnType<typeof setTimeout> | null = null;\n /**\n * Per-source latches for the error signal, fed from the subscriptions that\n * already exist rather than from the event history: the event buffer is\n * bounded per agent and in total and evicts entries, so counting events\n * could silently lose a live failure.\n */\n private readonly errorSignalArmed: Record<\n InspectorWiringErrorSource,\n boolean\n > = { connection: false, threads: false };\n /** Unread app errors. Cleared when the landing view is read. */\n private readonly eventErrorArmed: Record<InspectorEventErrorSource, boolean> =\n { run: false, tool: false, memory: false };\n /** Latest detail for each event source, retained after that source is read. */\n private readonly eventErrorDetails: Record<\n InspectorEventErrorSource,\n InspectorEventErrorDetails | null\n > = { run: null, tool: null, memory: null };\n private pendingScrollToEventId: string | null = null;\n private pendingScrollToToolCallId: string | null = null;\n /** Last time an inspector-owned /threads refresh left this host, per agent. */\n private readonly threadRefreshLastSentAt: Map<string, number> = new Map();\n /** Trailing /threads refresh timers, one per agent. */\n private readonly threadRefreshTrailingTimers: Map<\n string,\n ReturnType<typeof setTimeout>\n > = new Map();\n /**\n * Whether this outage has already had its beat. Global rather than\n * per-source: a connection failure cascades into thread failures, so one\n * root cause must not produce two nudges. Reset when nothing is red, which\n * is what makes a resolved-then-recurring failure beat again.\n */\n private errorBeatSpent = false;\n /** Per-outage dedup for `oss.inspector.error_signal_viewed`. */\n private readonly errorSignalViewedSources: Set<InspectorErrorSignalSource> =\n new Set();\n /**\n * The signal whose gesture is running its tail — the pill on screen and the\n * sentence in the live region, both of which outlive the beat.\n *\n * Together with `pulsingSignal` this IS the single pending-beat slot, not a\n * second scheduling concept: `startSignalPulse` defers while either is set,\n * so the third deferral reason simply covers a longer beat. Null for the\n * announcement, which has no tail and therefore behaves exactly as before.\n */\n private gestureSignal: LauncherSignalKey | null = null;\n /** Where the running gesture's pill is, or null when it has none. */\n private pillPhase: LauncherPillPhase | null = null;\n /**\n * Which side the pill opens from, or null before the room has been measured.\n * Decided once, at gesture start, and never revisited mid-gesture.\n */\n private pillDirection: LauncherPillDirection | null = null;\n private pillTimeoutId: ReturnType<typeof setTimeout> | null = null;\n /** Hover/focus menu on the closed launcher. */\n private launcherHudOpen = false;\n private launcherHudSide: \"left\" | \"right\" = \"left\";\n private launcherHudCloseTimer: ReturnType<typeof setTimeout> | null = null;\n private launcherHudIntro = false;\n private launcherHudIntroStartTimer: ReturnType<typeof setTimeout> | null =\n null;\n private launcherHudIntroEndTimer: ReturnType<typeof setTimeout> | null = null;\n /** Host-wide deadline that suppresses both the Inspector and its launcher. */\n private inspectorDismissedUntil: number | null = null;\n private lastReportedInspectorVisibility: boolean | null = null;\n private inspectorDismissalTimer: ReturnType<typeof setTimeout> | null = null;\n /**\n * Leaf a HUD row asked for. Consumed by `openInspector` so a red dot on\n * the circle cannot steal \"Turn on Threads\". Not a public open option.\n */\n private hudLandingMenu: MenuKey | null = null;\n /**\n * Whether this outage's pill actually opened. Per outage rather than per\n * phase, so a second source arming behind the first reports the same answer\n * the reader actually got. Reset with `errorBeatSpent`.\n */\n private pillOutcome: LauncherPillOutcome | null = null;\n private viewedNewsSignalIds: Set<string> = new Set();\n private pendingNewsSignalViewed: {\n banner_id: string;\n surface: \"launcher\";\n presentation: WhatsNewSignalPresentation;\n cta_label?: string;\n } | null = null;\n // Per-instance dedup for `oss.inspector.whats_new_viewed`, keyed by\n // `${timestamp}:${surface}` so the event fires at most once per\n // announcement per surface per inspector mount. Plan calls for \"de-dup per\n // timestamp per session\"; instance-scoping is closer to per-mount than\n // per-tab (sessionStorage), but for the inspector the distinction is\n // academic — inspector instances rarely outlive the page. The surface stays\n // part of the key so a second announcement surface would get its own\n // impression rather than being swallowed by the first one's.\n private viewedBannerSurfaces: Set<string> = new Set();\n // Impressions wait for the runtime handshake before going out: the runtime's\n // opt-out arrives in the /info response, and `telemetryDisabled` reads `false`\n // until then, so sending directly would post on a placeholder. This deferral\n // predates the surface split — preserved here, widened from a single slot to a\n // queue because opening the panel reveals the second surface and can happen\n // before the first impression has flushed.\n private pendingBannerViewed: Array<{\n banner_id: string;\n surface: WhatsNewSurface;\n cta_label?: string;\n }> = [];\n // Per-instance dedup for `oss.inspector.whats_new_clicked` (keyed by\n // `${bannerId}:${cta}`) so copy-button retries and accidental multi-clicks\n // don't inflate funnel counts beyond one signal per intent type per banner.\n private clickedBannerIds: Set<string> = new Set();\n private viewedThreadsTelemetryStates: Set<string> = new Set();\n private viewedExampleKinds: Set<ExampleKind> = new Set();\n private selectedExampleKinds: Set<ExampleKind> = new Set();\n private viewedExampleTourSteps: Set<string> = new Set();\n private exampleThreadProviders: Map<string, ThreadDebuggerProvider> =\n new Map();\n private exampleTourDismissed = false;\n private exampleTourActive = false;\n private exampleTourStep = 0;\n private exampleTourAutoShown = false;\n private threadsExampleOverviewVideoState: ThreadsExampleOverviewVideoState =\n \"deferred\";\n private threadsExampleOverviewVideoLoaded = false;\n private threadsExampleOverviewVideoReducedMotion = false;\n private threadsExampleOverviewVideoLoadTimer: number | null = null;\n private threadsExampleOverviewVideoIdleCallbackId: number | null = null;\n private threadsExampleOverviewVideoElement: HTMLVideoElement | null = null;\n private threadsExampleOverviewVideoListeners: ThreadsExampleOverviewVideoListeners | null =\n null;\n private threadsExampleOverviewVideoLifecycleGeneration = 0;\n private threadsExampleOverviewVideoPlayAttemptGeneration = 0;\n private threadsExampleOverviewVideoPlayPromise: Promise<void> | null = null;\n private threadsExampleOverviewVideoPlayOnNextBind = false;\n private homeFeaturePromptCopyState: {\n serviceId: HomeFeaturePromptId;\n state: HomeFeaturePromptCopyState;\n } | null = null;\n private homeFeaturePromptCopyResetTimeoutId: number | null = null;\n private homeFeaturePromptCopyGeneration = 0;\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 const hadResolvedCore = this.hasResolvedCore;\n this.ephemeralThreadsSetupOpen = false;\n this._core = value ?? null;\n if (this._core) {\n this.hasResolvedCore = true;\n }\n\n if (!hadResolvedCore && this._core) {\n this.resolvePendingPersistedMenu();\n } else if (hadResolvedCore) {\n this.reconcileSelectedMenuVisibility();\n }\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 resizeInitialPosition: Position | null = null;\n private resizeEdge: \"e\" | \"w\" | \"s\" | \"se\" | \"sw\" = \"se\";\n private isResizing = false;\n\n private readonly customTabIcons: Record<string, string> = {\n threads: `<svg class=\"h-3.5 w-3.5\" width=\"15\" height=\"15\" viewBox=\"0 0 15 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.04167 15C8.29167 15 7.65972 14.7431 7.14583 14.2292C6.63194 13.7153 6.375 13.0972 6.375 12.375C6.375 11.3194 6.80208 10.3646 7.65625 9.51042C8.51042 8.65625 9.57639 8.125 10.8542 7.91667C10.8125 7.41667 10.6875 7.03819 10.4792 6.78125C10.2708 6.52431 9.98611 6.39583 9.625 6.39583C9.20833 6.39583 8.75694 6.56944 8.27083 6.91667C7.78472 7.26389 7.20833 7.83333 6.54167 8.625C5.45833 9.91667 4.66319 10.7569 4.15625 11.1458C3.64931 11.5347 3.10417 11.7292 2.52083 11.7292C1.8125 11.7292 1.21528 11.4653 0.729167 10.9375C0.243056 10.4097 0 9.77083 0 9.02083C0 8.27083 0.163194 7.50347 0.489583 6.71875C0.815972 5.93403 1.36806 4.99306 2.14583 3.89583C2.40972 3.53472 2.60417 3.22917 2.72917 2.97917C2.85417 2.72917 2.91667 2.52778 2.91667 2.375C2.91667 2.27778 2.89931 2.20486 2.86458 2.15625C2.82986 2.10764 2.77778 2.08333 2.70833 2.08333C2.56944 2.08333 2.39583 2.17014 2.1875 2.34375C1.97917 2.51736 1.73611 2.78472 1.45833 3.14583L0 1.66667C0.444444 1.125 0.895833 0.711806 1.35417 0.427083C1.8125 0.142361 2.26389 0 2.70833 0C3.34722 0 3.88889 0.222222 4.33333 0.666667C4.77778 1.11111 5 1.66667 5 2.33333C5 2.73611 4.89583 3.18056 4.6875 3.66667C4.47917 4.15278 4.13194 4.73611 3.64583 5.41667C3.11806 6.16667 2.72569 6.82639 2.46875 7.39583C2.21181 7.96528 2.08333 8.46528 2.08333 8.89583C2.08333 9.13194 2.12153 9.31597 2.19792 9.44792C2.27431 9.57986 2.38194 9.64583 2.52083 9.64583C2.65972 9.64583 2.78125 9.60764 2.88542 9.53125C2.98958 9.45486 3.18056 9.27083 3.45833 8.97917C3.63889 8.78472 3.85417 8.54514 4.10417 8.26042C4.35417 7.97569 4.65972 7.625 5.02083 7.20833C5.89583 6.16667 6.6875 5.42361 7.39583 4.97917C8.10417 4.53472 8.84722 4.3125 9.625 4.3125C10.5556 4.3125 11.3194 4.625 11.9167 5.25C12.5139 5.875 12.8542 6.72917 12.9375 7.8125H15V9.89583H12.9375C12.8264 11.4514 12.4201 12.691 11.7188 13.6146C11.0174 14.5382 10.125 15 9.04167 15ZM9.08333 12.9167C9.52778 12.9167 9.90278 12.6632 10.2083 12.1562C10.5139 11.6493 10.7222 10.9444 10.8333 10.0417C10.1944 10.1944 9.63889 10.4965 9.16667 10.9479C8.69444 11.3993 8.45833 11.8472 8.45833 12.2917C8.45833 12.4861 8.51389 12.6389 8.625 12.75C8.73611 12.8611 8.88889 12.9167 9.08333 12.9167Z\" fill=\"currentColor\"/></svg>`,\n };\n\n private get menuItems(): MenuItem[] {\n const hasFrontendTools = (this._core?.tools?.length ?? 0) > 0;\n const hasCatalog = (this._core?.catalogComponents?.length ?? 0) > 0;\n // Capabilities is the A2UI catalog + tool toggle surface. If the only\n // live data is frontend tools, Frontend Tools already lists them, so\n // showing Capabilities as well is a duplicate leaf.\n const hasCapabilities = hasCatalog;\n return [\n { key: \"home\", label: \"Home\", icon: \"Home\" as LucideIconName },\n {\n key: \"whats-new\",\n label: \"What's New\",\n icon: \"Megaphone\" as LucideIconName,\n },\n {\n key: WHATS_NEW_MENU_KEY,\n label: WHATS_NEW_VIEW_LABEL,\n icon: \"Megaphone\" as LucideIconName,\n },\n {\n key: \"playground\",\n label: \"Playground\",\n icon: \"MessageCircle\" as LucideIconName,\n },\n {\n key: \"ag-ui-events\",\n label: \"AG-UI Events\",\n icon: \"Zap\" as LucideIconName,\n },\n { key: \"agents\", label: \"Agent\", icon: \"Bot\" as LucideIconName },\n ...(hasFrontendTools\n ? [\n {\n key: \"frontend-tools\" as const,\n label: \"Frontend Tools\",\n icon: \"Hammer\" as LucideIconName,\n },\n ]\n : []),\n ...(hasCapabilities\n ? [\n {\n key: \"capabilities\" as const,\n label: CAPABILITIES_TAB_LABEL,\n icon: \"SlidersHorizontal\" as LucideIconName,\n },\n ]\n : []),\n {\n key: \"agent-context\",\n label: \"Context\",\n icon: \"FileText\" as LucideIconName,\n },\n {\n key: \"threads\",\n label: \"Rich Threads\",\n icon: \"MessageSquare\" as LucideIconName,\n },\n {\n key: \"memories\",\n label: LEARNING_VIEW_LABEL,\n icon: \"Brain\" as LucideIconName,\n },\n ];\n }\n\n /** Return only currently visible leaves owned by a group. */\n private getVisibleMenuItemsForGroup(group: InspectorNavGroupKey): MenuItem[] {\n return INSPECTOR_GROUPS[group].flatMap((menuKey) => {\n const item = this.menuItems.find(\n (candidate) => candidate.key === menuKey,\n );\n return item ? [item] : [];\n });\n }\n\n /** Resolve a group's last visible leaf, falling back to its first leaf. */\n private getMenuForGroup(group: InspectorNavGroupKey): MenuKey {\n const visibleItems = this.getVisibleMenuItemsForGroup(group);\n const rememberedMenu = this.lastSelectedMenuByGroup[group];\n return (\n visibleItems.find((item) => item.key === rememberedMenu)?.key ??\n visibleItems[0]?.key ??\n \"home\"\n );\n }\n\n /** Replace a leaf that became hidden with its group's first visible leaf. */\n private reconcileSelectedMenuVisibility(): void {\n if (this.menuItems.some((item) => item.key === this.selectedMenu)) {\n return;\n }\n\n const group = getGroupForMenu(this.selectedMenu);\n const fallbackMenu = this.getVisibleMenuItemsForGroup(group)[0]?.key;\n this.selectedMenu = fallbackMenu ?? \"home\";\n this.lastSelectedMenuByGroup[group] = this.selectedMenu;\n this.persistState();\n }\n\n /** Open a sidebar group at its last currently visible leaf. */\n private handleGroupSelect(group: InspectorNavGroupKey): void {\n this.handleMenuSelect(this.getMenuForGroup(group));\n }\n\n /** Toggle Settings without replacing or persisting the active legacy leaf. */\n private handleSettingsToggle(): void {\n this.settingsOpen = !this.settingsOpen;\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.requestUpdate();\n }\n\n private getThreadServiceStatus(): ThreadServiceStatus {\n if (!this._core) return \"unknown\";\n if (!this._core.threadEndpoints) return \"unknown\";\n return this._core.threadEndpoints?.list === false\n ? \"unavailable\"\n : \"available\";\n }\n\n private areThreadEndpointsAvailable(): boolean {\n const endpoints = this._core?.threadEndpoints;\n return (\n endpoints !== null &&\n typeof endpoints === \"object\" &&\n endpoints.list !== false\n );\n }\n\n private synchronizeThreadCapability(): void {\n const enabled = this.areThreadEndpointsAvailable();\n if (this.threadCapabilityEnabled === enabled) return;\n\n this.threadCapabilityEnabled = enabled;\n this.threadCapabilityGeneration += 1;\n\n if (enabled) {\n const core = this.core;\n if (!core) return;\n\n const threadStores =\n typeof core.getThreadStores === \"function\"\n ? core.getThreadStores()\n : {};\n for (const [agentId, store] of Object.entries(threadStores)) {\n this.subscribeToThreadStore(agentId, store);\n }\n for (const agent of Object.values(core.agents)) {\n if (agent?.agentId) {\n this.ensureOwnedThreadStore(agent.agentId);\n }\n }\n return;\n }\n\n this.teardownThreadStoreSubscriptions();\n this.teardownOwnedThreadStores();\n if (this.selectedThreadId !== this.selectedLocalExampleThreadId) {\n this.selectedThreadId = null;\n this.selectedLocalExampleThreadId = null;\n }\n this.selectedRealThreadIsExplicit = false;\n this.requestUpdate();\n }\n\n private getActiveThreadsState(): {\n displayThreads: ɵThread[];\n threadsErrorMessage: string | null;\n threadsLoading: boolean;\n } {\n const displayThreads =\n this.selectedContext === \"all-agents\"\n ? this._threads\n : (this._threadsByAgent.get(this.selectedContext) ?? []);\n\n // Surface a thread-store load error inline. For \"all-agents\" we report\n // the first error encountered across all agents (good enough for a\n // debugging surface — the per-agent context filter narrows down the\n // culprit). For a specific agent we use that agent's error directly.\n let threadsErrorMessage: string | null = null;\n if (this.selectedContext === \"all-agents\") {\n const firstError = this._threadsErrorByAgent.values().next().value;\n threadsErrorMessage = firstError?.message ?? null;\n } else {\n threadsErrorMessage =\n this._threadsErrorByAgent.get(this.selectedContext)?.message ?? null;\n }\n\n const threadsLoading =\n this.selectedContext === \"all-agents\"\n ? Array.from(this._threadsLoadingByAgent.values()).some(Boolean)\n : (this._threadsLoadingByAgent.get(this.selectedContext) ?? false);\n\n return { displayThreads, threadsErrorMessage, threadsLoading };\n }\n\n /** Bucket trusted usage without retaining exact counts or limits. */\n private getThreadsUsageBucket(): ThreadsUsageBucket {\n const usage = this.inspectorMetadataProjection.usage;\n if (!usage) return \"absent\";\n if (usage.used === 0) return \"empty\";\n if (usage.limit.kind === \"finite\") {\n return usage.used < usage.limit.value\n ? \"within_limit\"\n : \"at_or_over_limit\";\n }\n if (usage.limit.kind === \"unlimited\") return \"unlimited\";\n return \"unknown_limit\";\n }\n\n /** Classify finite usage for render-only capacity copy and color. */\n private getThreadsCapacityState():\n | \"normal\"\n | \"warning\"\n | \"critical\"\n | undefined {\n const usage = this.inspectorMetadataProjection.usage;\n if (!usage || usage.limit.kind !== \"finite\") return undefined;\n if (usage.used >= usage.limit.value) return \"critical\";\n\n const warningThreshold =\n usage.limit.value - Math.floor(usage.limit.value / 10);\n return usage.used >= warningThreshold ? \"warning\" : \"normal\";\n }\n\n /** Bucket trusted expiry data independently from the usage-limit bucket. */\n private getThreadsExpiryBucket(): ThreadsExpiryBucket {\n const usage = this.inspectorMetadataProjection.usage;\n if (\n !usage ||\n !Object.prototype.hasOwnProperty.call(usage, \"expiringSoonCount\")\n ) {\n return \"unavailable\";\n }\n if (usage.expiringSoonCount === 0) return \"zero\";\n return typeof usage.expiringSoonCount === \"number\" &&\n usage.expiringSoonCount > 0\n ? \"positive\"\n : \"unavailable\";\n }\n\n /** Report only real rows visible in the active, settled Threads view. */\n private hasActiveVisibleThreads(): boolean {\n if (\n this.selectedMenu !== \"threads\" ||\n this.settingsOpen ||\n this.ephemeralThreadsSetupOpen ||\n !this.areThreadEndpointsAvailable()\n ) {\n return false;\n }\n const { displayThreads, threadsErrorMessage, threadsLoading } =\n this.getActiveThreadsState();\n return !threadsErrorMessage && !threadsLoading && displayThreads.length > 0;\n }\n\n /** Build the closed common property set shared by all Thread events. */\n private getThreadsTelemetryProps(): InspectorThreadTelemetryProps {\n const threadServiceStatus = this.getThreadServiceStatus();\n return {\n intelligence_status:\n threadServiceStatus === \"available\"\n ? \"intelligence_enabled\"\n : threadServiceStatus === \"unavailable\"\n ? \"intelligence_not_enabled\"\n : \"unknown\",\n thread_service_status: threadServiceStatus,\n license_status: this.core?.licenseStatus ?? undefined,\n runtime_mode: this.core?.runtimeMode ?? undefined,\n runtime_url_type: getRuntimeUrlType(this.core?.runtimeUrl),\n telemetry_disabled: false,\n has_threads: this.hasActiveVisibleThreads(),\n usage_bucket: this.getThreadsUsageBucket(),\n expiry_bucket: this.getThreadsExpiryBucket(),\n group_key: \"workbench\",\n leaf_key: \"threads\",\n };\n }\n\n /** Add the frozen CTA leaves and anonymous URL attribution when allowed. */\n private getThreadsCtaTelemetryProps(\n cta: \"signup\" | \"talk_to_engineer\",\n ctaSurface: \"threads_locked\" | \"threads_header\" | \"sidebar_footer\",\n ): InspectorThreadTelemetryProps {\n const distinctId = getTelemetryDistinctIdForUrl();\n return {\n ...this.getThreadsTelemetryProps(),\n cta,\n cta_surface: ctaSurface,\n posthog_distinct_id: distinctId ?? undefined,\n };\n }\n\n private getMemoriesTelemetryProps(): InspectorMemoryTelemetryProps {\n const distinctId = !this.core?.telemetryDisabled\n ? getTelemetryDistinctIdForUrl()\n : null;\n return {\n posthog_distinct_id: distinctId ?? undefined,\n memory_count: this._memories.length,\n available: this._memoriesAvailable,\n };\n }\n\n private getIntelligenceSignupUrl(): string {\n return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, \"cpk-inspector\");\n }\n\n private getTalkToEngineerUrl(): string {\n return this.appendRefParam(TALK_TO_ENGINEER_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsTalkToEngineerUrl(): string {\n return this.appendRefParam(TALK_TO_ENGINEER_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsDocsUrl(): string {\n return this.appendRefParam(THREADS_DOCS_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsIntelligenceSignupUrl(): string {\n return this.appendRefParam(\n INTELLIGENCE_SIGNUP_URL,\n \"cpk-inspector-threads\",\n );\n }\n\n private getSelfHostedIntelligenceUrl(): string {\n return this.appendRefParam(\n SELF_HOSTED_INTELLIGENCE_URL,\n \"cpk-inspector-threads\",\n );\n }\n\n /** Selects the onboarding path for an enabled runtime with no saved Threads. */\n private getThreadsEmptyOnboardingAction(): Readonly<{\n href: string;\n label: \"Sign up for Intelligence\" | \"Explore self-hosted Intelligence\";\n }> {\n const planCode = this.inspectorMetadataProjection.plan?.code\n .trim()\n .toLowerCase();\n if (planCode === \"team_self_hosted\" || planCode === \"team-self-hosted\") {\n return {\n href: this.getSelfHostedIntelligenceUrl(),\n label: \"Explore self-hosted Intelligence\",\n };\n }\n return {\n href: this.getThreadsIntelligenceSignupUrl(),\n label: \"Sign up for Intelligence\",\n };\n }\n\n private subscribeToThreadStore(agentId: string, store: ɵThreadStore): void {\n if (!this.areThreadEndpointsAvailable()) return;\n if (this._threadStoreSubscriptions.has(agentId)) return;\n const capabilityGeneration = this.threadCapabilityGeneration;\n const threadsSub = store.select(ɵselectThreads).subscribe((threads) => {\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n this._threadsByAgent.set(agentId, threads as ɵThread[]);\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n if (\n this.selectedMenu === \"memories\" &&\n this.shouldPollLearningSetup() &&\n !this.learningLoading &&\n !this.learningRefreshing\n ) {\n void this.refreshLearningSnapshot({ preserve: true });\n }\n this.requestUpdate();\n });\n const statusSub = store\n .select(createThreadStoreStatusSelector())\n .subscribe(({ error, isLoading }) => {\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n if (error) {\n this._threadsErrorByAgent.set(agentId, error);\n } else if (!isLoading) {\n this._threadsErrorByAgent.delete(agentId);\n }\n this._threadsLoadingByAgent.set(agentId, isLoading);\n this.requestUpdate();\n });\n this._threadStoreSubscriptions.set(agentId, () => {\n threadsSub.unsubscribe();\n statusSub.unsubscribe();\n });\n // Populate immediately from current state\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n const initialState = store.getState();\n this._threadsByAgent.set(agentId, ɵselectThreads(initialState));\n this._threadsLoadingByAgent.set(\n agentId,\n ɵselectThreadsIsLoading(initialState),\n );\n const initialError = ɵselectThreadsError(initialState);\n if (initialError) {\n this._threadsErrorByAgent.set(agentId, initialError);\n } else if (!ɵselectThreadsIsLoading(initialState)) {\n this._threadsErrorByAgent.delete(agentId);\n }\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n }\n\n private rebuildFlattenedThreads(): void {\n this._threads = flattenThreadsByAgent(this._threadsByAgent);\n this.scheduleInspectorUsageRefresh();\n }\n\n private scheduleInspectorUsageRefresh(): void {\n const signature = this._threads\n .map((thread) => thread.id)\n .sort()\n .join(\",\");\n if (signature === this.threadUsageSignature) {\n return;\n }\n this.threadUsageSignature = signature;\n if (this.threadUsageRefreshTimer !== null) {\n clearTimeout(this.threadUsageRefreshTimer);\n }\n this.threadUsageRefreshTimer = setTimeout(() => {\n this.threadUsageRefreshTimer = null;\n const core = this.core;\n if (core && typeof core.refreshInspectorMetadata === \"function\") {\n void core.refreshInspectorMetadata();\n }\n }, 300);\n }\n\n private clearInspectorUsageRefresh(): void {\n if (this.threadUsageRefreshTimer !== null) {\n clearTimeout(this.threadUsageRefreshTimer);\n this.threadUsageRefreshTimer = null;\n }\n this.threadUsageSignature = \"\";\n }\n\n private autoSelectLatestThread(): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const { displayThreads } = this.getActiveThreadsState();\n const previousSelectedThreadId = this.selectedThreadId;\n\n if (this.requestedThreadId !== null) {\n this.selectedThreadId = this.requestedThreadId;\n this.selectedRealThreadIsExplicit = true;\n if (\n displayThreads.some((thread) => thread.id === this.requestedThreadId)\n ) {\n this.requestedThreadId = null;\n }\n return;\n }\n\n if (\n this.selectedLocalExampleThreadId !== null &&\n previousSelectedThreadId === this.selectedLocalExampleThreadId &&\n displayThreads.length === 0\n ) {\n this.selectedRealThreadIsExplicit = false;\n return;\n }\n\n if (this.selectedLocalExampleThreadId !== null) {\n this.exampleTourActive = false;\n }\n this.selectedLocalExampleThreadId = null;\n const explicitSelectedThreadId = this.selectedRealThreadIsExplicit\n ? previousSelectedThreadId\n : null;\n const nextSelectedThreadId = selectVisibleRealThreadId({\n threads: displayThreads,\n selectedThreadId: explicitSelectedThreadId,\n });\n this.selectedThreadId = nextSelectedThreadId;\n this.selectedRealThreadIsExplicit =\n explicitSelectedThreadId !== null &&\n nextSelectedThreadId === explicitSelectedThreadId;\n }\n\n private teardownThreadStoreSubscriptions(): void {\n for (const unsub of this._threadStoreSubscriptions.values()) {\n unsub();\n }\n this._threadStoreSubscriptions.clear();\n this._threadsByAgent.clear();\n this._threadsErrorByAgent.clear();\n this._threadsLoadingByAgent.clear();\n this._threads = [];\n this.clearInspectorUsageRefresh();\n }\n\n private ensureOwnedThreadStore(agentId: string): void {\n if (!this.areThreadEndpointsAvailable()) return;\n if (this._ownedThreadStores.has(agentId)) return;\n // Don't overwrite a store already registered by useThreads() or another external caller\n if (this.core?.getThreadStore(agentId)) return;\n const core = this.core;\n if (!core?.runtimeUrl) return;\n\n const runtimeFetch =\n typeof core.ɵruntimeFetch === \"function\"\n ? core.ɵruntimeFetch\n : globalThis.fetch;\n const store = ɵcreateThreadStore({ fetch: runtimeFetch });\n store.start();\n store.setContext({\n runtimeUrl: core.runtimeUrl,\n headers: { ...core.headers },\n wsUrl: core.intelligence?.wsUrl,\n agentId,\n });\n this._ownedThreadStores.set(agentId, store);\n // Subscribe directly so threads render even before the registry callback\n // fires (some published-core code paths land on the subscriber after\n // registerThreadStore returns).\n this.subscribeToThreadStore(agentId, store);\n core.registerThreadStore(agentId, store);\n }\n\n private refreshOwnedThreadStore(agentId: string): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const store = this._ownedThreadStores.get(agentId);\n if (!store) return;\n\n const now = Date.now();\n const lastSentAt = this.threadRefreshLastSentAt.get(agentId) ?? 0;\n const waitMs = THREAD_LIST_DEBOUNCE_MS - (now - lastSentAt);\n if (waitMs <= 0) {\n this.sendOwnedThreadRefresh(agentId, store, now);\n return;\n }\n if (this.threadRefreshTrailingTimers.has(agentId)) return;\n this.threadRefreshTrailingTimers.set(\n agentId,\n setTimeout(() => {\n this.threadRefreshTrailingTimers.delete(agentId);\n const current = this._ownedThreadStores.get(agentId);\n if (!current) return;\n this.sendOwnedThreadRefresh(agentId, current, Date.now());\n }, waitMs),\n );\n }\n\n private sendOwnedThreadRefresh(\n agentId: string,\n store: ɵThreadStore,\n sentAt: number,\n ): void {\n this.threadRefreshLastSentAt.set(agentId, sentAt);\n // refresh() re-fetches without resetting threads to [] first, so the list\n // stays visible while new data loads and survives transient fetch failures.\n store.refresh();\n }\n\n private cancelThreadRefreshDebounce(): void {\n for (const timer of this.threadRefreshTrailingTimers.values()) {\n clearTimeout(timer);\n }\n this.threadRefreshTrailingTimers.clear();\n }\n\n // Keep inspector-owned thread stores in sync when the host updates headers\n // at runtime (e.g. a refreshed auth/CSRF token via core.setHeaders). Mirrors\n // useThreads(), which re-dispatches the context whenever core.headers change,\n // so the owned stores' /threads requests stay authorized.\n private updateOwnedThreadStoreHeaders(\n headers: Readonly<Record<string, string>>,\n ): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const core = this.core;\n if (!core?.runtimeUrl) return;\n for (const [agentId, store] of this._ownedThreadStores) {\n store.setContext({\n runtimeUrl: core.runtimeUrl,\n headers: { ...headers },\n wsUrl: core.intelligence?.wsUrl,\n agentId,\n });\n }\n }\n\n private removeOwnedThreadStore(agentId: string): void {\n const store = this._ownedThreadStores.get(agentId);\n if (!store) return;\n this._ownedThreadStores.delete(agentId);\n store.stop();\n if (this.core?.getThreadStore(agentId) === store) {\n this.core.unregisterThreadStore(agentId);\n }\n }\n\n private teardownOwnedThreadStores(): void {\n const ownedThreadStores = Array.from(this._ownedThreadStores);\n this._ownedThreadStores.clear();\n for (const [agentId, store] of ownedThreadStores) {\n store.stop();\n if (this.core?.getThreadStore(agentId) === store) {\n this.core.unregisterThreadStore(agentId);\n }\n }\n }\n\n private coreSupportsInspectorMetadata(core: CopilotKitCore): boolean {\n try {\n return \"inspectorMetadata\" in core;\n } catch {\n return false;\n }\n }\n\n private readCoreInspectorMetadata(core: CopilotKitCore): unknown {\n if (!this.coreSupportsInspectorMetadata(core)) {\n return undefined;\n }\n\n try {\n return core.inspectorMetadata;\n } catch {\n return undefined;\n }\n }\n\n private updateInspectorMetadataProjection(value: unknown): void {\n this.inspectorMetadataValue = value;\n let runtimeLicense: RuntimeLicenseStatus | undefined;\n try {\n runtimeLicense = this._core?.licenseStatus;\n } catch {\n runtimeLicense = undefined;\n }\n this.inspectorMetadataProjection = projectInspectorMetadata(\n value,\n runtimeLicense,\n );\n }\n\n private attachToCore(core: CopilotKitCore): void {\n this.runtimeStatus = core.runtimeConnectionStatus;\n this.coreProperties = core.properties;\n this.lastCoreError = null;\n this.clearAllEventErrors();\n const supportsInspectorMetadata = this.coreSupportsInspectorMetadata(core);\n this.updateInspectorMetadataProjection(\n this.readCoreInspectorMetadata(core),\n );\n this.learningSupported = core.inspectorLearning;\n this.learningProjectIdentity = JSON.stringify(\n this.inspectorMetadataProjection.identity ?? null,\n );\n\n this.coreSubscriber = {\n onRuntimeConnectionStatusChanged: ({ status }) => {\n this.runtimeStatus = status;\n this.updateInspectorMetadataProjection(this.inspectorMetadataValue);\n const threadCapabilityWasEnabled =\n this.threadCapabilityEnabled === true;\n this.synchronizeThreadCapability();\n if (status === \"connected\") {\n this.learningSupported = core.inspectorLearning;\n if (!core.telemetryDisabled) {\n ensureTelemetryDistinctId();\n maybeShowDisclosure();\n }\n this.flushPendingWhatsNewTelemetry();\n if (this.isLearningStatusVisible()) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\n if (\n threadCapabilityWasEnabled &&\n this.areThreadEndpointsAvailable()\n ) {\n for (const agentId of this._ownedThreadStores.keys()) {\n this.refreshOwnedThreadStore(agentId);\n }\n }\n } else {\n // Clear stale thread data immediately when the server goes away\n this._threadsByAgent.clear();\n this._threads = [];\n this.clearInspectorUsageRefresh();\n this.clearLearningSnapshot();\n }\n this.requestUpdate();\n },\n onPropertiesChanged: ({ properties }) => {\n this.coreProperties = properties;\n this.requestUpdate();\n },\n onHeadersChanged: ({ headers }) => {\n this.updateOwnedThreadStoreHeaders(headers);\n this.requestUpdate();\n },\n ...(supportsInspectorMetadata\n ? {\n onInspectorMetadataChanged: ({ inspectorMetadata }) => {\n if (this._core !== core) {\n return;\n }\n this.updateInspectorMetadataProjection(inspectorMetadata);\n const identity = JSON.stringify(\n this.inspectorMetadataProjection.identity ?? null,\n );\n if (identity !== this.learningProjectIdentity) {\n this.learningProjectIdentity = identity;\n this.clearLearningSnapshot();\n if (this.isLearningStatusVisible()) {\n void this.refreshLearningSnapshot({ preserve: false });\n }\n }\n this.requestUpdate();\n },\n }\n : {}),\n onError: ({ code, error, context }) => {\n this.lastCoreError = { code, message: error.message };\n this.armEventErrorFromCode(code, error.message, context);\n this.requestUpdate();\n },\n onAgentsChanged: ({ agents }) => {\n this.processAgentsChanged(agents);\n },\n onAgentRunStarted: ({ agent }) => {\n // Per-thread clones (from useAgent) are not in the agent registry, so\n // onAgentsChanged never fires for them. Subscribe to the running\n // instance here so its AG-UI events reach the event timeline.\n if (agent?.agentId) {\n this.subscribeToAgent(agent);\n }\n },\n onContextChanged: ({ context }) => {\n this.contextStore = this.normalizeContextStore(context);\n this.requestUpdate();\n },\n onSuggestionsChanged: () => this.requestUpdate(),\n onSuggestionsStartedLoading: () => this.requestUpdate(),\n onSuggestionsFinishedLoading: () => this.requestUpdate(),\n onSuggestionsConfigChanged: () => this.requestUpdate(),\n onThreadStoreRegistered: ({ agentId, store }) => {\n if (!this.areThreadEndpointsAvailable()) return;\n this.subscribeToThreadStore(agentId, store);\n this.requestUpdate();\n },\n onThreadStoreUnregistered: ({ agentId, prevStore }) => {\n const unsub = this._threadStoreSubscriptions.get(agentId);\n if (unsub) {\n unsub();\n this._threadStoreSubscriptions.delete(agentId);\n }\n if (this._ownedThreadStores.get(agentId) === prevStore) {\n this._ownedThreadStores.delete(agentId);\n prevStore.stop();\n }\n this._threadsByAgent.delete(agentId);\n this._threadsErrorByAgent.delete(agentId);\n this._threadsLoadingByAgent.delete(agentId);\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n this.requestUpdate();\n },\n } satisfies CopilotKitCoreSubscriber;\n\n this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;\n this.processAgentsChanged(core.agents);\n\n if (core.runtimeConnectionStatus === \"connected\") {\n if (!core.telemetryDisabled) {\n ensureTelemetryDistinctId();\n maybeShowDisclosure();\n }\n this.flushPendingWhatsNewTelemetry();\n }\n\n // Subscribe to any already-registered thread stores. `getThreadStores` was\n // added in the same release as this inspector; guard so consumers still on\n // an older @copilotkit/core don't throw when assigning `inspector.core`.\n const threadStores =\n typeof core.getThreadStores === \"function\" ? core.getThreadStores() : {};\n if (this.areThreadEndpointsAvailable()) {\n for (const [agentId, store] of Object.entries(threadStores)) {\n this.subscribeToThreadStore(agentId, store);\n }\n }\n\n // Initialize context from core\n if (core.context) {\n this.contextStore = this.normalizeContextStore(core.context);\n }\n\n // NOTE: the memory store is intentionally NOT touched here. Calling\n // `core.getMemoryStore()` lazily creates + `.start()`s the store and opens\n // a realtime connection, so merely attaching the inspector would spin up a\n // memory store + realtime even in apps that never use memory. Instead, the\n // store is created + subscribed on first Memories-tab activation via\n // `ensureMemorySubscription` (user-initiated, acceptable). Attaching the\n // inspector creates nothing.\n //\n // Exception: if the Memories tab is ALREADY the active tab when core is\n // wired (e.g. core attaches after `firstUpdated` restored a persisted\n // `selectedMenu: \"memories\"`), subscribe now so the live store + realtime\n // status paint instead of the stuck defaults. This preserves INSP-1 (no\n // unconditional subscribe on attach) because it is gated on the active tab,\n // and is safe to call when already subscribed — `ensureMemorySubscription`\n // early-returns on `_memorySubscribed`.\n if (this.selectedMenu === \"memories\") {\n this.ensureMemorySubscription();\n }\n }\n\n /**\n * Lazily subscribes to the singleton memory store the first time the user\n * activates the Memories tab. This is deferred out of `attachToCore` because\n * `core.getMemoryStore()` is what creates + starts the store and opens\n * realtime — doing it on attach would start memory for apps that never use\n * it. Idempotent: repeated tab activations are guarded by\n * `_memorySubscribed`. On an older @copilotkit/core without `getMemoryStore`,\n * records the unsupported state so the teaser can guide an SDK upgrade.\n */\n private ensureMemorySubscription(): void {\n if (this._memorySubscribed) {\n return;\n }\n const core = this._core;\n if (!core) {\n return;\n }\n\n // Guard like getThreadStores: older @copilotkit/core has no getMemoryStore.\n // When absent, flag the unsupported state so the teaser shows upgrade copy\n // instead of throwing a TypeError that would break the entire inspector.\n if (typeof core.getMemoryStore !== \"function\") {\n this._memoryStoreUnsupported = true;\n this._memoriesAvailable = false;\n this.requestUpdate();\n return;\n }\n\n this._memorySubscribed = true;\n this._memoryStoreUnsupported = false;\n\n // First touch of getMemoryStore() — creates + starts the store, opens realtime.\n const memoryStore = core.getMemoryStore();\n const ms = memoryStore.getState();\n this._memories = ɵselectMemories(ms);\n this._memoriesLoading = ɵselectMemoriesIsLoading(ms);\n this._memoriesError = ɵselectMemoriesError(ms);\n this._memoriesAvailable = ɵselectMemoriesAvailable(ms);\n this._memoriesRealtimeStatus = ɵselectMemoriesRealtimeStatus(ms);\n const memSubs = [\n memoryStore.select(ɵselectMemories).subscribe((v) => {\n this._memories = v;\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesIsLoading).subscribe((v) => {\n this._memoriesLoading = v;\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesError).subscribe((v) => {\n this._memoriesError = v;\n if (v) {\n this.armEventError(\"memory\", v.message);\n }\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesAvailable).subscribe((v) => {\n this._memoriesAvailable = v;\n this.requestUpdate();\n }),\n // Group E — realtime connection health.\n memoryStore.select(ɵselectMemoriesRealtimeStatus).subscribe((v) => {\n this._memoriesRealtimeStatus = v;\n this.requestUpdate();\n }),\n ];\n this._memoryUnsub = () => memSubs.forEach((s) => s.unsubscribe());\n this.requestUpdate();\n }\n\n /**\n * Runs a semantic recall via the memory store (`core.getMemoryStore().recall`,\n * from B2) and stores ranked results. Guarded by a monotonic sequence token\n * so a stale request cannot overwrite a newer result / Clear / detach. Only\n * reachable from the Intelligence-gated memory view, so it inherits the gate.\n */\n private runRecall(query: string): void {\n const trimmed = query.trim();\n if (trimmed.length === 0) return;\n const store = this._core?.getMemoryStore?.();\n if (!store || typeof store.recall !== \"function\") {\n this._recallResults = [];\n this._recallError = \"Recall is not supported by this SDK version.\";\n this._recallLoading = false;\n this.requestUpdate();\n return;\n }\n\n const seq = ++this._recallSeq;\n this._recallLoading = true;\n this._recallError = null;\n this.requestUpdate();\n\n store\n .recall(trimmed)\n .then((results) => {\n if (seq !== this._recallSeq) return;\n this._recallResults = results;\n this._recallError = null;\n this._recallLoading = false;\n this.requestUpdate();\n })\n .catch((error: unknown) => {\n if (seq !== this._recallSeq) return;\n this._recallResults = [];\n this._recallError =\n error instanceof Error ? error.message : \"unknown error\";\n this._recallLoading = false;\n this.requestUpdate();\n });\n }\n\n /** Clears recall results/section and cancels any in-flight recall. */\n private clearRecall(): void {\n this._recallSeq += 1;\n this._recallResults = null;\n this._recallError = null;\n this._recallLoading = false;\n this._recallQuery = \"\";\n this.requestUpdate();\n }\n\n private getLearningAgentId(): string | null {\n if (\n this.selectedContext !== \"all-agents\" &&\n this.core?.agents[this.selectedContext]\n ) {\n return this.selectedContext;\n }\n // `all-agents` is intentionally unscoped. Choosing the first object key\n // silently binds Learning to whichever agent happened to be enumerated\n // first and can select the wrong container. Omit agentId so Intelligence\n // applies its deterministic sole-container / selection-required rules.\n return null;\n }\n\n /** Whether a visible surface needs the current Learning connection status. */\n private isLearningStatusVisible(): boolean {\n return (\n this.launcherHudOpen ||\n (this.isOpen &&\n (this.selectedMenu === \"home\" || this.selectedMenu === \"memories\"))\n );\n }\n\n private isLearningSetupActive(): boolean {\n const runtimeUrl = this.core?.runtimeUrl;\n if (!runtimeUrl) return false;\n return learningSetupMarkerMatches(\n this.learningSetupMarker,\n runtimeUrl,\n this.getLearningAgentId(),\n );\n }\n\n private trackLearningViewState(): void {\n if (\n !this.isOpen ||\n this.selectedMenu !== \"memories\" ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n const state = deriveLearningViewState({\n supported: this.learningSupported,\n loading: this.learningLoading,\n error: this.learningError,\n snapshot: this.learningSnapshot,\n setupActive: this.isLearningSetupActive(),\n });\n if (state === this.learningViewedState) return;\n this.learningViewedState = state;\n trackLearningPaneViewed({ state });\n }\n\n private cancelLearningPoll(): void {\n if (this.learningPollTimer !== null) {\n clearTimeout(this.learningPollTimer);\n this.learningPollTimer = null;\n }\n }\n\n private shouldPollLearningSetup(): boolean {\n if (\n !this.isOpen ||\n this.selectedMenu !== \"memories\" ||\n document.visibilityState !== \"visible\" ||\n !this.learningSupported\n ) {\n return false;\n }\n const snapshot = this.learningSnapshot;\n if (!snapshot) return this.isLearningSetupActive();\n if (snapshot.configuration.state === \"not_configured\") {\n return this.isLearningSetupActive();\n }\n return (\n snapshot.configuration.state === \"configured\" &&\n !snapshot.run.hasEverSucceeded &&\n !snapshot.run.hasActiveRun &&\n snapshot.pendingThreadCount === 0 &&\n snapshot.skillsPage.total === 0 &&\n snapshot.insightsPage.total === 0\n );\n }\n\n private scheduleLearningPoll(): void {\n this.cancelLearningPoll();\n if (!this.shouldPollLearningSetup()) return;\n const delay =\n this.learningPollFailureCount === 0\n ? 5_000\n : this.learningPollFailureCount === 1\n ? 10_000\n : 30_000;\n this.learningPollTimer = setTimeout(() => {\n this.learningPollTimer = null;\n void this.refreshLearningSnapshot({ preserve: true });\n }, delay);\n }\n\n private clearLearningSnapshot(): void {\n this.cancelLearningRequest();\n this.learningSnapshot = null;\n this.learningSnapshotScope = null;\n this.learningError = null;\n this.learningLoading = false;\n this.learningRefreshing = false;\n this.cancelLearningPoll();\n }\n\n private cancelLearningRequest(): void {\n this.learningRequestGeneration += 1;\n this.learningAbortController?.abort();\n this.learningAbortController = null;\n }\n\n private refreshLearningSnapshot = async (\n options: {\n preserve?: boolean;\n skillsPage?: number;\n insightsPage?: number;\n } = {},\n ): Promise<void> => {\n const core = this.core;\n const runtimeUrl = core?.runtimeUrl;\n this.learningSupported = Boolean(core?.inspectorLearning);\n if (!core || !runtimeUrl || !this.learningSupported) {\n this.clearLearningSnapshot();\n this.requestUpdate();\n this.trackLearningViewState();\n return;\n }\n this.cancelLearningPoll();\n const startedAt = performance.now();\n let loadOutcome: \"success\" | \"unsupported\" | \"failure\" = \"failure\";\n let loadedSkills = 0;\n let loadedInsights = 0;\n let loadedPendingThreads = 0;\n let resetSkillsPage = false;\n let resetInsightsPage = false;\n const previousSnapshot = this.learningSnapshot;\n const agentId = this.getLearningAgentId();\n const requestContext = `${runtimeUrl.replace(/\\/+$/u, \"\")}|${agentId ?? \"\"}`;\n if (\n this.learningSnapshotScope &&\n !this.learningSnapshotScope.startsWith(`${requestContext}|`)\n ) {\n this.clearLearningSnapshot();\n }\n const generation = ++this.learningRequestGeneration;\n this.learningAbortController?.abort();\n const controller = new AbortController();\n this.learningAbortController = controller;\n const preserve =\n options.preserve === true && this.learningSnapshot !== null;\n this.learningLoading = !preserve;\n this.learningRefreshing = preserve;\n this.learningError = null;\n this.requestUpdate();\n try {\n const snapshot = await fetchInspectorLearning({\n runtimeUrl,\n runtimeTransport: core.runtimeTransport,\n request: {\n ...(agentId ? { agentId } : {}),\n skillsPage:\n options.skillsPage ?? this.learningSnapshot?.skillsPage.page ?? 1,\n insightsPage:\n options.insightsPage ??\n this.learningSnapshot?.insightsPage.page ??\n 1,\n },\n fetch: core.ɵruntimeFetch,\n headers: core.headers,\n credentials: core.credentials,\n signal: controller.signal,\n });\n if (generation !== this.learningRequestGeneration) return;\n if (\n (snapshot.pendingThreadCount > 0 && !snapshot.links.runs) ||\n (snapshot.pendingCandidateCount > 0 && !snapshot.links.candidates)\n ) {\n throw new Error(\n \"Learning snapshot is missing a required web-app link.\",\n );\n }\n const containerId =\n snapshot.configuration.state === \"configured\"\n ? snapshot.configuration.container.id\n : \"\";\n const previousContainerId =\n previousSnapshot?.configuration.state === \"configured\"\n ? previousSnapshot.configuration.container.id\n : \"\";\n const scopeChanged =\n previousSnapshot !== null &&\n (previousSnapshot.projectKey !== snapshot.projectKey ||\n previousContainerId !== containerId);\n const isBackgroundRefresh =\n options.skillsPage === undefined && options.insightsPage === undefined;\n resetSkillsPage = Boolean(\n isBackgroundRefresh &&\n previousSnapshot &&\n previousSnapshot.skillsPage.page > 1 &&\n (scopeChanged ||\n JSON.stringify([\n previousSnapshot.skillsPage.total,\n previousSnapshot.skillsPage.items.map((skill) => [\n skill.id,\n skill.revision,\n ]),\n ]) !==\n JSON.stringify([\n snapshot.skillsPage.total,\n snapshot.skillsPage.items.map((skill) => [\n skill.id,\n skill.revision,\n ]),\n ])),\n );\n resetInsightsPage = Boolean(\n isBackgroundRefresh &&\n previousSnapshot &&\n previousSnapshot.insightsPage.page > 1 &&\n (scopeChanged ||\n JSON.stringify([\n previousSnapshot.insightsPage.total,\n previousSnapshot.insightsPage.items.map((insight) => insight.id),\n ]) !==\n JSON.stringify([\n snapshot.insightsPage.total,\n snapshot.insightsPage.items.map((insight) => insight.id),\n ])),\n );\n this.learningSnapshot = snapshot;\n loadOutcome = \"success\";\n loadedSkills = snapshot.skillsPage.total;\n loadedInsights = snapshot.insightsPage.total;\n loadedPendingThreads = snapshot.pendingThreadCount;\n this.learningSnapshotScope = `${requestContext}|${snapshot.projectKey}|${containerId}`;\n this.learningError = null;\n this.learningPollFailureCount = 0;\n if (snapshot.configuration.state === \"configured\") {\n clearLearningSetupMarker();\n this.learningSetupMarker = null;\n }\n } catch (error) {\n if (\n generation !== this.learningRequestGeneration ||\n controller.signal.aborted\n )\n return;\n if (error instanceof InspectorLearningUnsupportedError) {\n loadOutcome = \"unsupported\";\n this.learningSupported = false;\n this.learningSnapshot = null;\n } else {\n this.learningError =\n error instanceof Error\n ? error.message\n : \"Learning data is unavailable.\";\n this.learningPollFailureCount += 1;\n }\n } finally {\n if (generation === this.learningRequestGeneration) {\n this.learningLoading = false;\n this.learningRefreshing = false;\n this.learningAbortController = null;\n if (!core.telemetryDisabled) {\n trackLearningSnapshotLoaded({\n outcome: loadOutcome,\n duration_bucket: learningDurationBucket(\n performance.now() - startedAt,\n ),\n skills_bucket: learningCountBucket(loadedSkills),\n insights_bucket: learningCountBucket(loadedInsights),\n pending_threads_bucket: learningCountBucket(loadedPendingThreads),\n });\n }\n this.scheduleLearningPoll();\n this.requestUpdate();\n this.trackLearningViewState();\n if (resetSkillsPage || resetInsightsPage) {\n void this.refreshLearningSnapshot({\n preserve: true,\n ...(resetSkillsPage ? { skillsPage: 1 } : {}),\n ...(resetInsightsPage ? { insightsPage: 1 } : {}),\n });\n }\n }\n }\n };\n\n private copyFeaturePromptToClipboard = async (\n service: HomeFeaturePromptTarget,\n event?: Event,\n onboardingRunId = createOnboardingRunId(),\n ): Promise<boolean> => {\n const clipboard = this.getClipboard(event);\n if (!clipboard?.writeText) return false;\n try {\n await clipboard.writeText(\n createFeatureOnboardingPrompt(service.id, onboardingRunId),\n );\n return true;\n } catch {\n return false;\n }\n };\n\n private handleLearningSetupCopy = async (\n event?: Event,\n recopy = false,\n ): Promise<void> => {\n // The Learning tile, not the Threads one. This pane borrowed the Threads\n // target, so its button copied a Threads prompt and announced itself as\n // \"Threads setup prompt copied\" under a Learning heading (OSS-1151).\n //\n // Learning does not need the Threads feature first. A runtime mounted\n // `mode: \"single-route\"` serves no thread route at all and still binds\n // Containers, because the binding happens server-side while a run starts;\n // and `learningOn` reads the `memory` tile independently of `threadsOn`.\n // `add-learning` inspects its own prerequisites and refuses through\n // `feature/stop` when one is missing, which is why the route decides that\n // rather than this pane.\n const service = this.getHomeFeaturePromptTarget(\"memory\");\n if (!service || !this.core?.runtimeUrl) return;\n const request = ++this.learningSetupCopyRequest;\n const copied = await this.copyFeaturePromptToClipboard(\n service,\n event,\n this.getOnboardingRunId(),\n );\n if (request !== this.learningSetupCopyRequest) return;\n if (!this.core.telemetryDisabled) {\n trackLearningSetupPromptClicked({\n outcome: copied ? \"success\" : \"failure\",\n });\n }\n if (!copied) {\n if (recopy) {\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"error\";\n } else {\n this.learningPromptCopyState = \"error\";\n }\n this.requestUpdate();\n return;\n }\n if (recopy) {\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"copied\";\n this.learningPromptRecopyTimer = setTimeout(() => {\n this.learningPromptRecopyTimer = null;\n this.learningPromptRecopyState = \"idle\";\n this.requestUpdate();\n }, LEARNING_RECOPY_CONFIRMATION_MS);\n } else {\n this.learningPromptCopyState = \"copied\";\n }\n this.learningSetupMarker = writeLearningSetupMarker({\n runtimeUrl: this.core.runtimeUrl,\n agentId: this.getLearningAgentId(),\n });\n this.selectedMenu = \"memories\";\n this.persistState();\n this.requestUpdate();\n void this.refreshLearningSnapshot({ preserve: false });\n };\n\n private cancelLearningPromptRecopyReset(): void {\n if (this.learningPromptRecopyTimer !== null) {\n clearTimeout(this.learningPromptRecopyTimer);\n this.learningPromptRecopyTimer = null;\n }\n }\n\n private handleLearningGoBack = (): void => {\n this.learningSetupCopyRequest += 1;\n this.cancelLearningPromptRecopyReset();\n clearLearningSetupMarker();\n this.learningSetupMarker = null;\n this.learningPromptCopyState = \"idle\";\n this.learningPromptRecopyState = \"idle\";\n this.cancelLearningPoll();\n this.requestUpdate();\n this.trackLearningViewState();\n };\n\n private handleLearningPage = (\n event: CustomEvent<{\n section: \"skills\" | \"insights\";\n page: number;\n }>,\n ): void => {\n const { section, page } = event.detail;\n const currentPage =\n section === \"skills\"\n ? (this.learningSnapshot?.skillsPage.page ?? 1)\n : (this.learningSnapshot?.insightsPage.page ?? 1);\n if (!this.core?.telemetryDisabled) {\n trackLearningPageChanged({\n section,\n direction: page < currentPage ? \"previous\" : \"next\",\n });\n }\n void this.refreshLearningSnapshot({\n preserve: true,\n ...(section === \"skills\" ? { skillsPage: page } : { insightsPage: page }),\n });\n };\n\n private handleLearningEvidence = (\n event: CustomEvent<{\n threadId: string;\n messageId?: string;\n }>,\n ): void => {\n this.focusThread({\n threadId: event.detail.threadId,\n ...(event.detail.messageId ? { messageId: event.detail.messageId } : {}),\n });\n };\n\n private detachFromCore(): void {\n this.threadCapabilityGeneration += 1;\n this.threadCapabilityEnabled = null;\n if (this.selectedThreadId !== this.selectedLocalExampleThreadId) {\n this.selectedThreadId = null;\n this.selectedLocalExampleThreadId = null;\n }\n this.selectedRealThreadIsExplicit = false;\n if (this.coreUnsubscribe) {\n this.coreUnsubscribe();\n this.coreUnsubscribe = null;\n }\n this._memoryUnsub?.();\n this._memoryUnsub = null;\n this._memories = [];\n this._memoriesLoading = false;\n this._memoriesError = null;\n this._memoriesAvailable = true;\n this._memoriesRealtimeStatus = \"connecting\";\n // Reset the lazy-subscription guards so a later attach + Memories-tab\n // activation re-subscribes (and re-evaluates SDK support) cleanly.\n this._memorySubscribed = false;\n this._memoryStoreUnsupported = false;\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"idle\";\n // Reset recall state and bump the sequence token so any in-flight recall\n // resolving after detach is ignored.\n this._recallSeq += 1;\n this._recallResults = null;\n this._recallLoading = false;\n this._recallError = null;\n this._recallQuery = \"\";\n this.clearLearningSnapshot();\n this.learningSupported = false;\n this.coreSubscriber = null;\n this.runtimeStatus = null;\n this.cancelThreadRefreshDebounce();\n this.inspectorMetadataValue = undefined;\n this.inspectorMetadataProjection = projectInspectorMetadata(\n undefined,\n undefined,\n );\n this.metadataTelemetryFingerprints.clear();\n this.lastCoreError = null;\n this.clearAllEventErrors();\n this.coreProperties = {};\n this.cachedTools = [];\n this.toolSignature = \"\";\n this.teardownAgentSubscriptions();\n this.teardownPlaygroundAgent();\n this.teardownThreadStoreSubscriptions();\n this.teardownOwnedThreadStores();\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 previousLearningAgentId = this.getLearningAgentId();\n this.synchronizeThreadCapability();\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 this.ensureOwnedThreadStore(agent.agentId);\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 // Do NOT remove owned thread stores here — they are independent of\n // whether the agent appears in core.agents (published cores discover\n // agents asynchronously so agents may be empty on first fire). Stores\n // are torn down in teardownOwnedThreadStores() when the core detaches.\n }\n }\n\n this.updateContextOptions(seenAgentIds);\n const learningAgentId = this.getLearningAgentId();\n if (\n learningAgentId &&\n this.core?.runtimeUrl &&\n this.learningSetupMarker?.agentId === null &&\n learningSetupMarkerMatches(\n this.learningSetupMarker,\n this.core.runtimeUrl,\n null,\n )\n ) {\n this.learningSetupMarker = writeLearningSetupMarker({\n runtimeUrl: this.core.runtimeUrl,\n agentId: learningAgentId,\n });\n }\n if (\n previousLearningAgentId !== learningAgentId &&\n this.isLearningStatusVisible()\n ) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\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: (params) => {\n this.recordAgentEvent(agentId, \"RUN_FINISHED\", {\n event: params.event,\n result: \"result\" in params ? params.result : undefined,\n });\n if (this.areThreadEndpointsAvailable()) {\n this.refreshOwnedThreadStore(agentId);\n }\n },\n onRunErrorEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"RUN_ERROR\", event);\n },\n onStepStartedEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STEP_STARTED\", event);\n },\n onStepFinishedEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STEP_FINISHED\", 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 onStateChanged: () => {\n this.syncAgentState(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 onActivitySnapshotEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"ACTIVITY_SNAPSHOT\", event);\n this.syncAgentMessages(agent);\n },\n onActivityDeltaEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"ACTIVITY_DELTA\", event);\n this.syncAgentMessages(agent);\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 mapMessagesToConversation(\n messages: InspectorMessage[] | null,\n ): { id: string; type: string; content: string; createdAt: string }[] | null {\n if (!messages) return null;\n return messages\n .filter(\n (m) =>\n m.role === \"user\" || m.role === \"assistant\" || m.role === \"activity\",\n )\n .map((m, i) => ({\n id: m.id ?? `msg-${i}`,\n type:\n m.role === \"user\"\n ? \"user\"\n : m.role === \"activity\"\n ? \"generative-ui\"\n : \"assistant\",\n // For activity messages, store the activityType as a label so the\n // renderer has something meaningful to display.\n // TODO: render activity payload once available.\n content:\n m.role === \"activity\" ? (m.activityType ?? \"unknown\") : m.contentText,\n createdAt: \"\",\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 try {\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 // Bump the live-message version for whichever thread this agent is\n // currently running on. cpk-thread-details watches this for the\n // selected thread and re-fetches `/threads/:id/messages` when it ticks,\n // so the conversation view stays in sync with the streaming agent\n // without the parent re-implementing AG-UI → ConversationItem mapping.\n const runThreadId = this.readAgentThreadId(agent);\n if (runThreadId) {\n this.liveMessageVersion.set(\n runThreadId,\n (this.liveMessageVersion.get(runThreadId) ?? 0) + 1,\n );\n }\n\n this.requestUpdate();\n } catch (error) {\n console.error(\n `[CopilotKit Inspector] Failed to sync messages for agent \"${agent.agentId}\":`,\n error,\n );\n }\n }\n\n private syncAgentState(agent: AbstractAgent): void {\n if (!agent?.agentId) {\n return;\n }\n\n try {\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 } catch (error) {\n console.error(\n `[CopilotKit Inspector] Failed to sync state for agent \"${agent.agentId}\":`,\n error,\n );\n }\n }\n\n private updateContextOptions(agentIds: Set<string>): void {\n let selectedContextChanged = false;\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 // Only restore a specific-agent selection when there is exactly one\n // agent registered. With multiple agents, fall back to \"all-agents\" so\n // events from any agent are visible regardless of what was persisted.\n const shouldRestore =\n isPendingAvailable &&\n (pendingContext === \"all-agents\" || agentIds.size === 1);\n if (shouldRestore) {\n if (this.selectedContext !== pendingContext) {\n this.selectedContext = pendingContext;\n selectedContextChanged = true;\n this.expandedRows.clear();\n }\n this.pendingSelectedContext = null;\n } else if (agentIds.size > 0) {\n // Persisted selection is unavailable or inappropriate for multiple\n // agents — reset to \"all-agents\" so nothing is silently filtered.\n if (this.selectedContext !== \"all-agents\") {\n this.selectedContext = \"all-agents\";\n selectedContextChanged = true;\n this.expandedRows.clear();\n }\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 // When there is exactly one agent, auto-select it so the view is\n // immediately focused. When multiple agents are registered (e.g. \"default\"\n // + \"openai\"), keep \"all-agents\" so events from any agent are visible.\n let nextSelected: string = \"all-agents\";\n\n if (agentIds.size === 1) {\n nextSelected = Array.from(agentIds)[0]!;\n }\n\n if (this.selectedContext !== nextSelected) {\n this.selectedContext = nextSelected;\n selectedContextChanged = true;\n this.expandedRows.clear();\n this.persistState();\n }\n }\n\n if (selectedContextChanged) {\n this.autoSelectLatestThread();\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 focusThread(options: InspectorOpenOptions): void {\n if (!options.threadId) return;\n this.pendingPersistedMenu = null;\n this.selectedMenu = \"threads\";\n this.settingsOpen = false;\n this.lastSelectedMenuByGroup.workbench = \"threads\";\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n this.selectedContext =\n options.agentId &&\n this.contextOptions.some((option) => option.key === options.agentId)\n ? options.agentId\n : \"all-agents\";\n this.requestedThreadId = options.threadId;\n this.selectedThreadId = options.threadId;\n this.selectedRealThreadIsExplicit = true;\n this.focusedThreadMessageId = options.messageId ?? null;\n this.threadFocusRequestId += 1;\n\n const { displayThreads } = this.getActiveThreadsState();\n if (displayThreads.some((thread) => thread.id === options.threadId)) {\n this.requestedThreadId = null;\n }\n\n this.persistState();\n this.requestUpdate();\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 readAgentThreadId(agent: AbstractAgent): string | undefined {\n if (!(\"threadId\" in agent)) return undefined;\n const threadId = agent.threadId;\n return typeof threadId === \"string\" ? threadId : undefined;\n }\n\n private getLiveAgentMessagesForThread(thread: ɵThread): InspectorMessage[] {\n const messages =\n this.agentMessages.get(thread.agentId) ?? EMPTY_INSPECTOR_MESSAGES;\n const core = this._core;\n if (!core || typeof core.getAgent !== \"function\") return messages;\n const agent = core.getAgent(thread.agentId);\n if (!agent) return EMPTY_INSPECTOR_MESSAGES;\n if (this.readAgentThreadId(agent) !== thread.id) {\n return EMPTY_INSPECTOR_MESSAGES;\n }\n return messages;\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 const toolError = this.eventErrorDetails.tool;\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 const isFailedCall =\n toolError?.toolCallId !== undefined &&\n toolError.toolCallId === callId;\n return html`\n <div\n class=${\n isFailedCall\n ? \"rounded-md border border-rose-300 bg-rose-50 p-3 text-xs text-gray-900\"\n : \"rounded-md border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700\"\n }\n data-cpk-failed-tool-call=${isFailedCall ? callId : undefined}\n >\n <div\n class=\"flex flex-wrap items-center justify-between gap-1 font-medium text-gray-900\"\n >\n <span>${functionName}${isFailedCall ? \" failed\" : \"\"}</span>\n <span class=\"text-[10px] text-gray-600\">ID: ${callId}</span>\n </div>\n ${\n isFailedCall && toolError?.message\n ? html`<p\n class=\"mt-2 break-words leading-relaxed text-gray-800\"\n >\n ${toolError.message}\n </p>`\n : nothing\n }\n ${\n argsString\n ? html`<div class=\"mt-2\">\n ${renderHighlightedJsonBlock(\n coerceJsonValue(call.function?.arguments),\n )}\n </div>`\n : nothing\n }\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-semibold inline-flex items-center rounded-sm px-1.5 py-0.5 border\";\n\n if (type === \"RUN_ERROR\") {\n return `${base} bg-rose-50 text-rose-800 border-rose-200`;\n }\n\n if (type.startsWith(\"TEXT_MESSAGE\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n if (type.startsWith(\"TOOL_CALL\")) {\n return `${base} bg-emerald-50 text-gray-900 border-emerald-200`;\n }\n\n if (type.startsWith(\"RUN_\") || type.startsWith(\"STEP_\")) {\n return `${base} bg-gray-100 text-gray-900 border-gray-200`;\n }\n\n if (type.startsWith(\"REASONING\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n if (type.startsWith(\"STATE\") || type.startsWith(\"MESSAGES\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n return `${base} bg-gray-100 text-gray-900 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 /** Prefer the window that owns the UI: the popup while popped out. */\n private getClipboard(event?: Event): Clipboard | undefined {\n if (this.isPoppedOut) {\n const popped = this.popOut?.win.navigator.clipboard;\n if (popped) {\n return popped;\n }\n }\n const view = event && \"view\" in event ? (event as UIEvent).view : null;\n const viewClipboard = view?.navigator.clipboard;\n if (viewClipboard) {\n return viewClipboard;\n }\n // Clipboard is required on Navigator in lib.dom, but missing in some runtimes.\n if (typeof navigator !== \"undefined\" && \"clipboard\" in navigator) {\n return navigator.clipboard;\n }\n return undefined;\n }\n\n private async copyToClipboard(\n text: string,\n eventId: string,\n event?: Event,\n ): Promise<void> {\n const clipboard = this.getClipboard(event);\n if (!clipboard) {\n console.error(\n \"Failed to copy to clipboard:\",\n \"Clipboard API is not available\",\n );\n return;\n }\n try {\n await 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 --cpk-inspector-shell-radius: 5px;\n --cpk-inspector-surface-dark: #111319;\n --cpk-json-key: #3d408f;\n --cpk-json-str: #0b6b4c;\n --cpk-json-num: #8a5900;\n --cpk-json-bool: #c0333a;\n --cpk-json-nil: #57575b;\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2147483646;\n display: block;\n will-change: transform;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n }\n\n :host([data-color-scheme=\"dark\"]),\n .inspector-window[data-color-scheme=\"dark\"] {\n --cpk-json-key: #bec2ff;\n --cpk-json-str: #85ecce;\n --cpk-json-num: #ffac4d;\n --cpk-json-bool: #fa5f67;\n --cpk-json-nil: #afafb7;\n }\n\n .cpk-json-token--key {\n color: var(--cpk-json-key);\n }\n\n .cpk-json-token--str {\n color: var(--cpk-json-str);\n }\n\n .cpk-json-token--num {\n color: var(--cpk-json-num);\n }\n\n .cpk-json-token--bool {\n color: var(--cpk-json-bool);\n }\n\n .cpk-json-token--nil {\n color: var(--cpk-json-nil);\n }\n\n .cpk-json-block {\n margin: 0;\n padding: 10px 12px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #f7f7f9;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n line-height: 1.65;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n overflow: auto;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-json-block,\n .inspector-window[data-color-scheme=\"dark\"] .cpk-json-block {\n background: #111319;\n border-color: #343742;\n color: #f3f4f8;\n }\n\n @keyframes cpk-playground-message-enter {\n from {\n opacity: 0;\n filter: blur(2px);\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n filter: blur(0);\n transform: translateY(0);\n }\n }\n\n @keyframes cpk-playground-thinking {\n 0%,\n 60%,\n 100% {\n opacity: 0.28;\n transform: translateY(0);\n }\n 30% {\n opacity: 1;\n transform: translateY(-2px);\n }\n }\n\n .cpk-playground-root {\n container-type: inline-size;\n background: #fbfbfd !important;\n }\n\n .cpk-playground-header {\n min-height: 58px;\n background: #f7f6fd !important;\n }\n\n .cpk-playground-welcome {\n max-width: 560px;\n padding: 24px;\n }\n\n .cpk-playground-welcome-title {\n color: #24242b;\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.015em;\n }\n\n .cpk-playground-composer {\n border: 1px solid #dcdce8;\n box-shadow:\n 0 8px 22px rgba(31, 23, 57, 0.08),\n 0 1px 2px rgba(31, 23, 57, 0.1);\n }\n\n .cpk-playground-composer:focus-within {\n border-color: #aaa4d4;\n box-shadow:\n 0 10px 26px rgba(86, 53, 155, 0.13),\n 0 0 0 3px rgba(190, 194, 255, 0.3);\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-root,\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-header {\n background: #15171e !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"]\n .cpk-playground-welcome-title {\n color: #f3f4f8 !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-composer {\n border-color: #464957;\n background: #15171e !important;\n box-shadow:\n 0 8px 22px rgba(0, 0, 0, 0.26),\n 0 1px 2px rgba(0, 0, 0, 0.36);\n }\n\n .inspector-window[data-color-scheme=\"dark\"]\n .cpk-playground-composer:focus-within {\n border-color: #777aae;\n box-shadow:\n 0 10px 26px rgba(0, 0, 0, 0.34),\n 0 0 0 3px rgba(102, 106, 158, 0.3);\n }\n\n .cpk-playground-message-enter {\n animation: cpk-playground-message-enter 0.24s\n cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-playground-thinking-dot {\n animation: cpk-playground-thinking 1.2s ease-in-out infinite;\n }\n\n .cpk-playground-thinking-dot:nth-child(2) {\n animation-delay: 0.12s;\n }\n\n .cpk-playground-thinking-dot:nth-child(3) {\n animation-delay: 0.24s;\n }\n\n .cpk-playground-reasoning summary::-webkit-details-marker {\n display: none;\n }\n\n .cpk-playground-reasoning[open] .cpk-playground-reasoning-chevron {\n transform: rotate(90deg);\n }\n\n @container (max-width: 560px) {\n .cpk-playground-header {\n align-items: stretch;\n }\n\n .cpk-playground-actions {\n width: 100%;\n }\n\n .cpk-playground-thread-select {\n min-width: 0;\n max-width: none;\n flex: 1;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-playground-message-enter,\n .cpk-playground-thinking-dot {\n animation: none;\n }\n }\n\n .rounded-sm {\n border-radius: 3px;\n }\n\n .rounded-md {\n border-radius: 7px;\n }\n\n .rounded-lg {\n border-radius: 10px;\n }\n\n .rounded-xl {\n border-radius: 14px;\n }\n\n :host([data-docked=\"true\"]) {\n top: 0;\n left: 0;\n bottom: 0;\n transform: none !important;\n will-change: auto;\n }\n\n :host([data-transitioning=\"true\"]) {\n transition: transform 300ms ease;\n }\n\n .console-button-wrapper {\n position: relative;\n display: inline-flex;\n /* The launcher's surface and edge, shared by the button and the pill so\n the two cannot drift apart. A dark grey rather than near-black: the\n launcher sits on a customer's page, and 1,5,7 against white is a\n harder edge than this surface needs. */\n --cpk-launcher-face: rgba(24, 28, 31, 0.95);\n --cpk-launcher-face-solid: rgb(24, 28, 31);\n --cpk-launcher-edge: rgba(190, 194, 255, 0.25);\n /* The launcher's own size, exposed so the signal dot can be placed\n against the OUTER rim with a length rather than a percentage.\n Percentages resolve against the padding box, which the 1px border\n insets, and the dot would land inside the rim.\n\n Declared on the wrapper rather than on the button so the pill, which\n is the button's sibling, can clear the mark by the same length. */\n --cpk-launcher-size: clamp(\n ${LAUNCHER_MIN_SIZE}px,\n 7vw,\n ${LAUNCHER_MAX_SIZE}px\n );\n }\n\n .console-button {\n width: var(--cpk-launcher-size);\n height: var(--cpk-launcher-size);\n /* Keep the 1px border inside the declared outer size. */\n box-sizing: border-box;\n transition:\n transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),\n scale 300ms cubic-bezier(0.34, 1.56, 0.64, 1),\n background-color 200ms ease,\n border-color 200ms ease,\n box-shadow 200ms ease,\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 top: 0 !important;\n left: 0 !important;\n bottom: 0 !important;\n height: auto !important;\n max-height: none !important;\n }\n\n .resize-handle {\n touch-action: none;\n user-select: none;\n z-index: 60;\n background: transparent;\n }\n\n .edge-resize-handle {\n position: absolute;\n z-index: 55;\n touch-action: none;\n user-select: none;\n background: transparent;\n }\n\n .edge-resize-handle-e {\n top: 48px;\n right: 0;\n width: 8px;\n height: calc(100% - 48px);\n cursor: ew-resize;\n }\n\n .edge-resize-handle-w {\n top: 48px;\n left: 0;\n width: 8px;\n height: calc(100% - 48px);\n cursor: ew-resize;\n }\n\n .edge-resize-handle-s {\n left: 0;\n bottom: 0;\n width: 100%;\n height: 8px;\n cursor: ns-resize;\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(1, 5, 7, 0.95);\n color: white;\n padding: 4px 8px;\n border-radius: 7px;\n font-size: 10px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n line-height: 1.2;\n box-shadow: 0 4px 10px rgba(1, 5, 7, 0.18);\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 /* ── Agent tab section cards ─────────────────────────────────────── */\n .cpk-section-card {\n border-radius: 10px;\n background: #ffffff;\n overflow: hidden;\n }\n\n /* ── Agent icon bubble ───────────────────────────────────────────── */\n .cpk-agent-icon {\n background-color: #f0f0f4 !important;\n color: #57575b !important;\n }\n\n /* ── Agent stat cards ────────────────────────────────────────────── */\n .cpk-stat-card {\n background-color: #ffffff !important;\n border: 1px solid #dbdbe5 !important;\n }\n button.cpk-stat-card:hover {\n background-color: #f7f7f9 !important;\n }\n\n /* ── Circle chevron (Frontend Tools + Context) ──────────────────── */\n .cpk-chevron-circle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background-color: #f0f0f4;\n color: #68686e;\n flex-shrink: 0;\n transition: transform 0.2s;\n }\n .cpk-chevron-circle svg {\n width: 14px !important;\n height: 14px !important;\n }\n .cpk-chevron-circle--open {\n transform: rotate(180deg);\n }\n\n /* ── Inline copy button ─────────────────────────────────────────── */\n .cpk-copy-btn {\n font-size: 10px;\n font-weight: 500;\n color: #57575b;\n background: #ffffff;\n border: 1px solid #dbdbe5;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: 5px;\n flex-shrink: 0;\n transition:\n background-color 0.15s,\n border-color 0.15s,\n color 0.15s;\n }\n .cpk-copy-btn:hover {\n background-color: #f0f0f4;\n border-color: #afafb7;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-copy-btn {\n background: #191c24;\n border-color: #3a3d49;\n color: #f3f4f8;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-copy-btn:hover {\n background: #20232d;\n border-color: #57575b;\n }\n\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-sidebar-agent-scope\n [data-context-dropdown-root=\"true\"]\n > div {\n left: 100%;\n margin-inline-start: 8px;\n }\n\n .inspector-icon-rail-menu {\n transform-origin: left center;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n transform: translateX(-8px) scale(0.96);\n transition:\n opacity 180ms ease,\n transform 180ms ease,\n visibility 180ms ease;\n }\n\n .inspector-icon-rail-menu[data-open=\"true\"] {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transform: translateX(0) scale(1);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .inspector-icon-rail-menu {\n transition: none;\n }\n }\n\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-sidebar-agent-scope\n [data-context-dropdown-root=\"true\"]\n > div::before {\n content: \"\";\n position: absolute;\n inset-block: 0;\n inset-inline-end: 100%;\n width: 12px;\n }\n\n .cpk-section-header {\n background: #e8edf5;\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n padding: 10px 16px;\n }\n .inspector-window[data-color-scheme=\"dark\"] .cpk-section-header {\n border-bottom-color: #3a3d49;\n }\n .cpk-section-header h4 {\n font-size: 11px;\n font-weight: 600;\n color: #181c1f;\n margin: 0;\n }\n\n /* Inputs/selects inside the lavender header need an explicit white bg */\n .cpk-section-header input,\n .cpk-section-header select {\n background-color: #ffffff !important;\n box-shadow: none !important;\n }\n .cpk-section-header select {\n padding-right: 24px !important;\n }\n /* Events table column headers */\n table thead th {\n font-weight: 600 !important;\n }\n\n .announcement-content {\n color: #1f2230;\n font-size: 13px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n line-height: 1.55;\n }\n\n .announcement-content h1,\n .announcement-content h2,\n .announcement-content h3 {\n color: #010507;\n font-weight: 700;\n line-height: 1.3;\n margin: 0.9rem 0 0.4rem;\n }\n .announcement-content > h1:first-child,\n .announcement-content > h2:first-child,\n .announcement-content > h3:first-child {\n margin-top: 0;\n }\n\n .announcement-content h1 {\n font-size: 1.15rem;\n letter-spacing: -0.01em;\n }\n .announcement-content h2 {\n font-size: 1rem;\n }\n .announcement-content h3 {\n font-size: 0.9rem;\n text-transform: none;\n }\n\n .announcement-content p {\n margin: 0.45rem 0;\n }\n\n .announcement-content strong {\n color: #010507;\n font-weight: 700;\n }\n\n .announcement-content ul {\n list-style: disc;\n padding-left: 1.25rem;\n margin: 0.45rem 0;\n }\n\n .announcement-content ol {\n list-style: decimal;\n padding-left: 1.25rem;\n margin: 0.45rem 0;\n }\n\n .announcement-content li + li {\n margin-top: 0.15rem;\n }\n\n .announcement-content a {\n color: #5558b2;\n text-decoration: underline;\n }\n\n .announcement-content :not(pre) > code {\n background: #f3f3f7;\n border: 1px solid #e4e4ec;\n border-radius: 5px;\n padding: 1px 5px;\n font-size: 0.85em;\n color: #4a3a8a;\n }\n\n .announcement-code {\n position: relative;\n margin: 0.6rem 0;\n }\n\n .announcement-code pre {\n background: #0f1117;\n color: #e6e8f2;\n border-radius: 10px;\n padding: 10px 12px;\n overflow-x: auto;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n }\n\n .announcement-code pre code::after {\n content: \"\";\n display: inline-block;\n width: 80px;\n }\n\n .announcement-code__copy-shield {\n position: absolute;\n top: 4px;\n right: 4px;\n padding: 4px 4px 4px 24px;\n border-top-right-radius: 10px;\n background: linear-gradient(\n to right,\n rgba(15, 17, 23, 0) 0%,\n rgba(15, 17, 23, 0.95) 40%,\n #0f1117 100%\n );\n pointer-events: none;\n }\n\n .announcement-code pre code {\n background: transparent;\n border: none;\n padding: 0;\n color: inherit;\n font-size: inherit;\n }\n\n .announcement-code pre::-webkit-scrollbar {\n height: 6px;\n }\n .announcement-code pre::-webkit-scrollbar-track {\n background: transparent;\n }\n .announcement-code pre::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n border-radius: 4px;\n }\n\n .announcement-code__copy {\n position: relative;\n pointer-events: auto;\n padding: 3px 8px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 11px;\n font-weight: 600;\n color: #e6e8f2;\n background: #1f222d;\n border: 1px solid rgba(255, 255, 255, 0.15);\n border-radius: 6px;\n cursor: pointer;\n transition:\n background 0.12s ease,\n color 0.12s ease;\n }\n .announcement-code__copy:hover {\n background: #2a2e3c;\n }\n .announcement-code__copy[data-copied=\"true\"] {\n background: #eee6fe;\n color: #6430ab;\n border-color: transparent;\n }\n\n /* ── What's new ──────────────────────────────────────────────── */\n .whats-new {\n display: block;\n padding: 16px;\n }\n\n .whats-new__heading {\n margin: 0 0 10px;\n color: #010507;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.35;\n letter-spacing: -0.01em;\n }\n\n .whats-new__status {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #57575b;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 13px;\n }\n\n .whats-new__status-icon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n background: #eee6fe;\n color: #5558b2;\n }\n\n /* ── Brand typography ────────────────────────────────────────── */\n /* Override Tailwind font-mono stack → Spline Sans Mono */\n .font-mono,\n pre,\n code {\n font-family:\n \"Spline Sans Mono\", ui-monospace, \"Cascadia Code\", monospace;\n }\n\n /* ── Floating button ─────────────────────────────────────────── */\n .console-button {\n background-color: var(--cpk-launcher-face) !important;\n border-color: var(--cpk-launcher-edge) !important;\n /* One hairline, not two. The border above is it; a second ring used to\n sit 1px outside as a box-shadow and hardcoded the lilac instead of\n reading the --cpk-launcher-edge token, so it could not follow it.\n What replaces it is a one-pixel light edge along the top, which is\n what keeps the face from reading flat without drawing a frame.\n\n The border is not decoration: the face is #181C1F, which against a\n dark host page (GitHub dark 1.10:1, Tailwind slate-900 1.04:1) is\n indistinguishable from the page. It is the only thing that gives the\n launcher an outline there, so it stays. */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.07),\n 0 4px 14px rgba(1, 5, 7, 0.28) !important;\n /* Promotes the launcher to its own compositing layer, which the\n backdrop-filter this replaces used to do as a side effect. Without\n a layer the hover scale re-rasterises the mark every frame and it\n visibly jitters; with one, the compositor scales it as a texture. */\n will-change: transform;\n }\n .console-button:hover {\n background-color: var(--cpk-launcher-face-solid) !important;\n border-color: rgba(190, 194, 255, 0.45) !important;\n transform: scale(1.05);\n }\n .console-button:focus-visible {\n outline-color: #bec2ff !important;\n }\n\n /* ── Launcher signal: water ripple + internal wash + dot ────── */\n /*\n * Two rings leave the rim in sequence, like ripples spreading from a\n * drop's point of impact. They share one keyframe but the second begins\n * 180ms later, so the first is already farther from the source.\n *\n * ONLY opacity and transform animate. This component is permanently\n * mounted on top of a customer's application, so animating anything\n * that forces a repaint every frame is not acceptable.\n */\n .console-button[data-cpk-signal] {\n isolation: isolate;\n }\n\n /*\n * The mark sits above the ripples. Both ring layers are absolutely\n * positioned, so without a stacking position of its own the mark — an\n * ordinary in-flow child — would paint under them. Keeping the centre\n * readable is the reason the motion begins at the rim.\n */\n .cpk-launcher-mark {\n position: relative;\n z-index: 2;\n width: auto;\n height: calc(var(--cpk-launcher-size) / 1.8);\n }\n\n .console-button[data-cpk-signal]::before,\n .console-button[data-cpk-signal]::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 0;\n box-sizing: border-box;\n border-radius: 50%;\n border: 2px solid\n color-mix(in srgb, var(--cpk-launcher-signal) 68%, transparent);\n box-shadow: 0 0 8px\n color-mix(in srgb, var(--cpk-launcher-signal) 38%, transparent);\n pointer-events: none;\n opacity: 0;\n transform: scale(1);\n }\n\n .cpk-launcher-signal-wash {\n position: absolute;\n inset: 0;\n z-index: 1;\n overflow: hidden;\n border-radius: 50%;\n pointer-events: none;\n opacity: 0;\n background: radial-gradient(\n circle at 50% 50%,\n transparent 26%,\n color-mix(in srgb, var(--cpk-launcher-signal) 78%, transparent) 63%,\n color-mix(in srgb, var(--cpk-launcher-signal) 30%, transparent) 84%,\n transparent 100%\n );\n }\n\n @keyframes cpk-launcher-ripple {\n 0% {\n opacity: 0.95;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(1.5);\n }\n }\n\n @keyframes cpk-launcher-wash {\n 0%,\n 100% {\n opacity: 0;\n }\n 45% {\n opacity: 1;\n }\n }\n\n /* Both ripples finish inside the existing one-beat pulse window. */\n .console-button[data-cpk-signal-pulsing=\"true\"]::before,\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation: cpk-launcher-ripple calc(var(--cpk-launcher-cadence) - 180ms)\n cubic-bezier(0.16, 1, 0.3, 1) 1 forwards;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation-delay: 180ms;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]\n .cpk-launcher-signal-wash {\n animation: cpk-launcher-wash var(--cpk-launcher-cadence) ease-in-out 1\n both;\n }\n\n /*\n * The dot's centre sits exactly ON the button's outer rim at 45°, where\n * 0.35355 is 0.5 x cos45. Lengths rather than percentage offsets:\n * percentages resolve against the padding box, which the border insets,\n * and the dot would land a pixel inside the rim.\n */\n .cpk-launcher-signal-dot {\n position: absolute;\n z-index: 3;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%)\n translate(\n calc(var(--cpk-launcher-size) * 0.35355),\n calc(var(--cpk-launcher-size) * -0.35355)\n );\n width: 19%;\n height: 19%;\n border-radius: 50%;\n /* Lit from the upper left and shaded at the lower right, so the dot\n reads as a lens rather than a flat disc. Both stops are derived from\n the signal colour, so a new tone needs no new values. */\n background: radial-gradient(\n circle at 32% 28%,\n color-mix(in srgb, var(--cpk-launcher-signal), white 40%) 0%,\n var(--cpk-launcher-signal) 60%,\n color-mix(in srgb, var(--cpk-launcher-signal), black 20%) 100%\n );\n /* Replaces an opaque 1.5px collar in the launcher's own face. That\n collar was 21% of the dot's footprint, and because the dot's centre\n sits *on* the rim, its outer half painted a hard dark crescent onto\n the host page rather than onto the launcher. A hairline plus a soft\n drop does the same separating job without the hard edge. */\n box-shadow:\n 0 0 0 0.5px rgba(1, 5, 7, 0.4),\n 0 1px 2.5px rgba(1, 5, 7, 0.5);\n }\n\n /* ── Launcher pill: the launcher opens sideways and says what ─── */\n /*\n * The pill is laid out at its FULL width from the first frame and\n * revealed by animating a rectangular clip. Nothing is scaled and\n * nothing is resized.\n *\n * That is not a stylistic choice. This component is permanently mounted\n * on top of a customer's application, so no property that forces a\n * layout on every frame is acceptable — and animating \"width\" does\n * exactly that, sixty times a second, on someone else's page. A clip\n * leaves the element's geometry constant and changes only the visible\n * region, which the compositor handles. Animating a horizontal scale\n * was the other candidate and squashes the mark itself, not merely the\n * rounded end, so the logo would need counter-scaling and the dot and\n * halo would become ellipses.\n *\n * The launcher's own face and border are repeated here so the two form\n * one capsule: the button paints last and therefore on top, with no\n * z-index needed. The mark's own ring and shadow are deliberately left\n * alone for the whole gesture — the circle's outline staying visible\n * inside the open pill was looked at against the alternative and kept.\n *\n * A column, not a row: the pill carries a heading and a subline stacked,\n * centred against a height that does not change. \"justify-content\"\n * centres the pair vertically and \"align-items\" keeps both lines flush\n * left, so the pill never grows taller than the launcher it opens from.\n */\n .cpk-launcher-pill {\n position: absolute;\n top: 50%;\n margin-top: calc(var(--cpk-launcher-size) / -2);\n height: var(--cpk-launcher-size);\n display: inline-flex;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n gap: 1px;\n box-sizing: border-box;\n border-radius: 999px;\n border: 1px solid var(--cpk-launcher-edge);\n background: var(--cpk-launcher-face);\n color: #ffffff;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n }\n\n /* The failure class, word-identical to the panel's own wording. */\n .cpk-launcher-pill__heading {\n font-size: 12px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n /*\n * The one line of copy in this feature that exists nowhere else in the\n * product. The heading above is word-identical to the panel, which is\n * the standing rule; this line is a deliberate, owner-approved exception\n * to it, because the pill is now clickable and has to say so.\n *\n * It is NOT spoken. A screen-reader user cannot act on an instruction\n * delivered through an announcement, and it would double the spoken\n * length — so the live region carries the failure class alone.\n */\n .cpk-launcher-pill__subline {\n font-size: 10.5px;\n font-weight: 500;\n line-height: 1.2;\n opacity: 0.72;\n }\n\n /*\n * Two directions, one animation with the inset on the other side. The\n * padding on the launcher's side clears the mark, so the words never sit\n * under it. The text-side padding is derived from the capsule's radius\n * (half the launcher size), NOT a bare literal: padding is measured from\n * the bounding box, but the first half-height of that side is the rounded\n * cap. Half the size lands the text exactly where the cap ends and the\n * straight edge begins. A literal 14px put it 16px inside the curve at the\n * production launcher size, which is itself a clamp on the viewport.\n */\n .cpk-launcher-pill[data-cpk-pill-direction=\"left\"] {\n right: 0;\n padding: 0 calc(var(--cpk-launcher-size) + 12px) 0\n calc(var(--cpk-launcher-size) / 2);\n clip-path: inset(0 0 0 calc(100% - var(--cpk-launcher-size)));\n }\n .cpk-launcher-pill[data-cpk-pill-direction=\"right\"] {\n left: 0;\n padding: 0 calc(var(--cpk-launcher-size) / 2) 0\n calc(var(--cpk-launcher-size) + 12px);\n clip-path: inset(0 calc(100% - var(--cpk-launcher-size)) 0 0);\n }\n\n /*\n * \"round\" on both stops, so the revealing edge is the capsule's own\n * rounded end travelling sideways rather than a straight vertical line\n * wiping across it. An unrounded inset reads as a wipe; this reads as an\n * opening. It adds no animated property: the clip is still the clip.\n */\n @keyframes cpk-launcher-pill-left {\n 0% {\n opacity: 0;\n clip-path: inset(\n 0 0 0 calc(100% - var(--cpk-launcher-size)) round 999px\n );\n }\n 100% {\n opacity: 1;\n clip-path: inset(0 0 0 0 round 999px);\n }\n }\n\n @keyframes cpk-launcher-pill-right {\n 0% {\n opacity: 0;\n clip-path: inset(\n 0 calc(100% - var(--cpk-launcher-size)) 0 0 round 999px\n );\n }\n 100% {\n opacity: 1;\n clip-path: inset(0 0 0 0 round 999px);\n }\n }\n\n /*\n * The pill takes the pointer exactly while it is on screen, so the\n * instruction it now carries is honest: a click on it opens the\n * Inspector, the same action as pressing the mark. During the beat the\n * clip covers only the mark itself, and a click target nobody can see\n * over someone else's page is not something to ship — so the base rule\n * keeps \"pointer-events: none\" and only the three visible phases take it\n * back.\n * The button paints last and therefore wins the pointer where the two\n * overlap, so dragging the launcher is unaffected throughout.\n */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n pointer-events: auto;\n cursor: pointer;\n }\n\n /* Closing is the same animation played backwards, so the two phases can\n never drift apart. */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"] {\n animation-duration: var(--cpk-launcher-pill-open);\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation-duration: var(--cpk-launcher-pill-close);\n animation-direction: reverse;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"][data-cpk-pill-direction=\"left\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"][data-cpk-pill-direction=\"left\"] {\n animation-name: cpk-launcher-pill-left;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"][data-cpk-pill-direction=\"right\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"][data-cpk-pill-direction=\"right\"] {\n animation-name: cpk-launcher-pill-right;\n }\n\n /* The hold is the end state of the reveal, held. */\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"] {\n opacity: 1;\n clip-path: inset(0 0 0 0);\n }\n\n /*\n * Reduced motion: the halo is held statically rather than animated, so\n * the information arrives without the movement.\n */\n @media (prefers-reduced-motion: reduce) {\n /*\n * The pill is shown by opacity alone, with no clip animation and the\n * same hold. The instruction is to reduce motion, not to withhold\n * information, and this reader needs the label as much as anyone.\n */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation: none !important;\n opacity: 1;\n clip-path: inset(0 0 0 0);\n }\n .cpk-launcher-signal-wash {\n opacity: 0.85;\n }\n .console-button[data-cpk-signal]::before {\n opacity: 0.5;\n }\n .console-button[data-cpk-signal]::after {\n opacity: 0;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]::before,\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation: none !important;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]\n .cpk-launcher-signal-wash {\n animation: none !important;\n }\n .console-button {\n transition: opacity 160ms ease;\n }\n .console-button:hover {\n transform: none;\n }\n }\n\n /* ── Launcher HUD: hover menu, quieter than the error island ── */\n .console-button-wrapper[data-cpk-hud=\"open\"] .cpk-launcher-hud {\n pointer-events: auto;\n opacity: 1;\n transform: none;\n visibility: visible;\n }\n\n .cpk-launcher-hud {\n --hud-fill: var(--cpk-inspector-surface-dark);\n --hud-line: rgb(190 194 255 / 0.38);\n --hud-accent: #b8adf5;\n --hud-accent-soft: rgb(184 173 245 / 0.13);\n --hud-hover-fill: #252231;\n --hud-blur: blur(12px) saturate(1.2);\n --hud-card-gap: 8px;\n --hud-dismiss-day-height: 32px;\n position: absolute;\n z-index: 4;\n width: 258px;\n pointer-events: none;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity 160ms ease,\n transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"top\"] {\n top: 0;\n bottom: auto;\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"] {\n top: auto;\n bottom: 0;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] {\n right: 100%;\n left: auto;\n padding-right: 14px;\n transform: translateX(8px);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] {\n left: 100%;\n right: auto;\n padding-left: 14px;\n transform: translateX(-8px);\n }\n\n .console-button-wrapper[data-cpk-hud=\"open\"] .cpk-launcher-hud {\n transform: none;\n }\n\n .cpk-launcher-hud__card {\n position: relative;\n display: grid;\n width: 244px;\n gap: var(--hud-card-gap);\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] {\n --hud-fill: #fff;\n --hud-line: #ddd6f4;\n --hud-accent: #6757b0;\n --hud-accent-soft: #f1edff;\n --hud-hover-fill: #f1edff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__card {\n color: #010507;\n }\n\n .cpk-launcher-hud__arrow {\n position: absolute;\n top: calc(var(--cpk-launcher-size) / 2);\n z-index: 2;\n width: 10px;\n height: 10px;\n border: 0;\n background: var(--hud-fill);\n transform: rotate(45deg);\n transition: background 120ms ease;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] .cpk-launcher-hud__arrow {\n right: 9px;\n border-top: 1px solid var(--hud-line);\n border-right: 1px solid var(--hud-line);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] .cpk-launcher-hud__arrow {\n left: 9px;\n border-bottom: 1px solid var(--hud-line);\n border-left: 1px solid var(--hud-line);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"top\"] .cpk-launcher-hud__arrow {\n top: calc(var(--cpk-launcher-size) / 2 - 5px);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"]\n .cpk-launcher-hud__arrow {\n top: auto;\n bottom: calc(var(--cpk-launcher-size) / 2 - 5px);\n }\n\n /* A bottom-anchored HUD can end with the narrower dismissal bubble.\n Keep the pointer attached to the full-width feature panel instead of\n letting it float in the empty space beside that final action. */\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"]:has(\n .cpk-launcher-hud__dismiss-day\n )\n .cpk-launcher-hud__arrow {\n bottom: calc(\n var(--hud-dismiss-day-height) + var(--hud-card-gap) + 2px\n );\n }\n\n /* With no news or setup actions, the dismissal is the whole HUD. */\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] {\n --hud-dismiss-day-height: 36px;\n width: max-content;\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only][data-cpk-hud-vertical=\"top\"] {\n top: calc((var(--cpk-launcher-size) - var(--hud-dismiss-day-height)) / 2);\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only][data-cpk-hud-vertical=\"bottom\"] {\n bottom: calc((var(--cpk-launcher-size) - var(--hud-dismiss-day-height)) / 2);\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] .cpk-launcher-hud__card {\n width: max-content;\n }\n\n .cpk-launcher-hud__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .cpk-launcher-hud__masthead {\n position: relative;\n z-index: 1;\n margin-top: 6px;\n padding: 0;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n backdrop-filter: var(--hud-blur);\n -webkit-backdrop-filter: var(--hud-blur);\n box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);\n transition: background 120ms ease;\n }\n\n .cpk-launcher-hud__news-wrap {\n position: relative;\n margin: 0;\n }\n\n .cpk-launcher-hud__news {\n position: relative;\n display: flex;\n width: 100%;\n min-width: 0;\n flex-direction: column;\n align-items: flex-start;\n padding: 18px 12px 11px;\n border: 0;\n border-radius: calc(var(--cpk-inspector-shell-radius) - 1px);\n background: transparent;\n color: #fff;\n font-family: inherit;\n line-height: 1;\n text-align: start;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__news:hover,\n .cpk-launcher-hud__news:focus-visible {\n background: transparent;\n }\n\n .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:hover),\n .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:focus-visible),\n .cpk-launcher-hud:has(.cpk-launcher-hud__news:hover)\n .cpk-launcher-hud__arrow,\n .cpk-launcher-hud:has(.cpk-launcher-hud__news:focus-visible)\n .cpk-launcher-hud__arrow {\n background: var(--hud-hover-fill);\n }\n\n .cpk-launcher-hud__news:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__news-title {\n display: block;\n font-size: 12px;\n font-weight: 650;\n line-height: 1.32;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .cpk-launcher-hud__news-label {\n position: absolute;\n top: -9px;\n left: 12px;\n display: inline-flex;\n min-height: 20px;\n align-items: center;\n padding: 3px 8px;\n border-radius: 6px;\n background: #7563c7;\n color: #fff;\n box-shadow: 0 3px 8px rgb(46 37 91 / 0.18);\n font-size: 9px;\n font-weight: 700;\n line-height: 1;\n }\n\n .cpk-launcher-hud__news-dismiss {\n position: absolute;\n top: -1px;\n right: 2px;\n z-index: 2;\n display: inline-flex;\n width: 20px;\n height: 20px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: rgb(255 255 255 / 0.68);\n cursor: pointer;\n }\n\n .cpk-launcher-hud__news-dismiss:hover,\n .cpk-launcher-hud__news-dismiss:focus-visible {\n background: var(--hud-accent-soft);\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss {\n color: #6e697c;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss:focus-visible {\n color: #27233a;\n }\n\n .cpk-launcher-hud__news-dismiss:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__news-dismiss svg {\n width: 7px;\n height: 7px;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__news {\n color: #17131f;\n }\n\n .cpk-launcher-hud__dismiss-day {\n position: relative;\n z-index: 1;\n display: flex;\n width: auto;\n min-height: var(--hud-dismiss-day-height);\n align-items: center;\n justify-content: center;\n justify-self: center;\n gap: 6px;\n margin: 0;\n padding: 7px 13px;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n color: #c9cad3;\n box-shadow: 0 8px 20px rgb(17 14 29 / 0.18);\n font-family: inherit;\n font-size: 10px;\n font-weight: 650;\n line-height: 1.2;\n cursor: pointer;\n transition:\n border-color 120ms ease,\n background 120ms ease,\n color 120ms ease;\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] .cpk-launcher-hud__dismiss-day {\n font-size: 11px;\n white-space: nowrap;\n }\n\n .cpk-launcher-hud__dismiss-day:hover,\n .cpk-launcher-hud__dismiss-day:focus-visible {\n border-color: var(--hud-accent);\n background: var(--hud-hover-fill);\n color: #f3f4f8;\n }\n\n .cpk-launcher-hud__dismiss-day:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__dismiss-day svg {\n width: 12px;\n height: 12px;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day {\n box-shadow: 0 8px 20px rgb(46 37 91 / 0.12);\n color: #5f6068;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day:focus-visible {\n color: #36373d;\n }\n\n .cpk-launcher-hud__feature-list {\n position: relative;\n z-index: 1;\n padding: 5px;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n backdrop-filter: var(--hud-blur);\n -webkit-backdrop-filter: var(--hud-blur);\n box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);\n }\n\n .cpk-launcher-hud__row {\n position: relative;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n min-height: 54px;\n border-radius: 9px;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__row + .cpk-launcher-hud__row {\n border-top: 1px solid var(--hud-line);\n border-radius: 0 0 9px 9px;\n }\n\n .cpk-launcher-hud__row:hover,\n .cpk-launcher-hud__row:focus-within {\n background: rgb(255 255 255 / 0.06);\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__row:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__row:focus-within {\n background: #f7f5ff;\n }\n\n .cpk-launcher-hud__primary {\n position: relative;\n display: flex;\n min-width: 0;\n }\n\n .cpk-launcher-hud__action {\n display: flex;\n width: 100%;\n gap: 8px;\n min-height: 52px;\n align-items: center;\n padding: 7px 4px;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #fff;\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n text-align: start;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__label {\n min-width: 0;\n }\n\n .cpk-launcher-hud__feature-icon {\n display: inline-flex;\n width: 28px;\n height: 32px;\n flex: none;\n align-items: center;\n justify-content: center;\n background: transparent;\n color: var(--hud-accent);\n }\n\n .cpk-launcher-hud__feature-icon svg {\n width: 17px;\n height: 17px;\n stroke-width: 1.8;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__action {\n color: #010507;\n }\n\n /* Stretch the row action over the whole tab. The icon controls sit\n above this layer and keep their own focused interactions. */\n .cpk-launcher-hud__action::after {\n content: \"\";\n position: absolute;\n inset: 0;\n }\n\n .cpk-launcher-hud__controls {\n position: relative;\n z-index: 1;\n display: flex;\n gap: 0;\n align-items: center;\n padding-right: 5px;\n }\n\n .cpk-launcher-hud__learn-more {\n display: inline-flex;\n width: 24px;\n height: 44px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n background: transparent;\n color: rgb(190 194 255 / 0.72);\n cursor: pointer;\n }\n\n .cpk-launcher-hud__learn-more:hover,\n .cpk-launcher-hud__learn-more:focus-visible {\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more {\n color: #777080;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more:focus-visible {\n color: #4b416b;\n }\n\n .cpk-launcher-hud__learn-more svg {\n width: 16px;\n height: 16px;\n stroke-width: 1.8;\n }\n\n .cpk-launcher-hud__toggle {\n display: inline-flex;\n width: 38px;\n height: 44px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n background: transparent;\n color: rgb(255 255 255 / 0.78);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__toggle:disabled {\n cursor: not-allowed;\n opacity: 1;\n }\n\n .cpk-launcher-hud__toggle-track {\n position: relative;\n display: block;\n width: 34px;\n height: 20px;\n border: 1px solid rgb(190 194 255 / 0.38);\n border-radius: 999px;\n background: rgb(255 255 255 / 0.08);\n transition:\n border-color 120ms ease,\n background 120ms ease;\n }\n\n .cpk-launcher-hud__toggle-track::after {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: #8c8e99;\n transition:\n background 120ms ease,\n transform 120ms ease;\n }\n\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #087653;\n background: #087653;\n }\n\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #fff;\n transform: translateX(14px);\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #c9c9d2;\n background: #e7e7ec;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #777780;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #087653;\n background: #087653;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #fff;\n }\n\n .cpk-launcher-hud__toggle:focus-visible,\n .cpk-launcher-hud__learn-more:focus-visible,\n .cpk-launcher-hud__action:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__tooltip {\n position: absolute;\n top: 50%;\n z-index: 30;\n width: max-content;\n max-width: min(220px, 52vw);\n padding: 7px 9px;\n border: 1px solid #3a3d49;\n border-radius: 4px;\n background: #15171e;\n color: #f3f4f8;\n box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);\n font-size: 10px;\n font-weight: 500;\n line-height: 1.45;\n opacity: 0;\n pointer-events: none;\n transform: translate(3px, -50%);\n white-space: normal;\n transition:\n opacity 120ms ease,\n transform 120ms ease;\n }\n\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)\n .cpk-launcher-hud__tooltip,\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)\n .cpk-launcher-hud__tooltip {\n opacity: 1;\n transform: translate(0, -50%);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] .cpk-launcher-hud__tooltip {\n right: calc(100% + 8px);\n left: auto;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] .cpk-launcher-hud__tooltip {\n right: auto;\n left: calc(100% + 8px);\n transform: translate(-3px, -50%);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"]\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)\n .cpk-launcher-hud__tooltip,\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"]\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)\n .cpk-launcher-hud__tooltip {\n transform: translate(0, -50%);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-launcher-hud,\n .cpk-launcher-hud__tooltip {\n transition: none;\n }\n }\n\n /*\n * On mount, borrow the hover HUD for one short introduction. The card\n * establishes the destination first; notification, features, and hide\n * action then fall into place from top to bottom. Only opacity and\n * transform move.\n */\n @keyframes cpk-launcher-hud-intro {\n 0% {\n opacity: 0;\n transform: translateY(-4px);\n }\n 8%,\n 88% {\n opacity: 1;\n transform: none;\n }\n 100% {\n opacity: 0;\n transform: translateY(3px);\n }\n }\n\n @keyframes cpk-launcher-hud-waterfall {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n }\n\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"] {\n animation: cpk-launcher-hud-intro var(--cpk-launcher-hud-intro-duration)\n cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"]\n :is(\n .cpk-launcher-hud__masthead,\n .cpk-launcher-hud__feature-list,\n .cpk-launcher-hud__row,\n .cpk-launcher-hud__dismiss-day\n ) {\n animation: cpk-launcher-hud-waterfall\n var(--cpk-launcher-hud-waterfall-duration)\n cubic-bezier(0.16, 1, 0.3, 1) both;\n animation-delay: var(--cpk-hud-waterfall-delay);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"],\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"]\n :is(\n .cpk-launcher-hud__masthead,\n .cpk-launcher-hud__feature-list,\n .cpk-launcher-hud__row,\n .cpk-launcher-hud__dismiss-day\n ) {\n animation: none !important;\n opacity: 1;\n transform: none;\n }\n }\n\n /*\n * Marker on the navigation entry, which is what keeps a signal alive\n * once the panel is open and the launcher is hidden. Static by design:\n * the beat belongs to the launcher, and movement here would compete with\n * the live event stream a developer is actually watching.\n *\n * Tone-selected rather than tone-agnostic, because the marker has to\n * agree with the dot that sent the reader here. Same shape, same\n * placement, one declaration different — as on the launcher, where the\n * treatment is shared and only the injected colour changes.\n */\n .inspector-nav-signal-dot {\n display: inline-block;\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${unsafeCSS(LAUNCHER_SIGNAL_COLORS.news)};\n }\n .inspector-nav-signal-dot[data-cpk-signal-tone=\"error\"] {\n background: ${unsafeCSS(LAUNCHER_SIGNAL_COLORS.error)};\n }\n\n /* ── Inspector window ────────────────────────────────────────── */\n .inspector-window {\n border: 1px solid #d8d8e8 !important;\n border-radius: var(--cpk-inspector-shell-radius) !important;\n box-shadow: none !important;\n }\n\n /* ── Header drag area ────────────────────────────────────────── */\n .drag-handle {\n border-bottom-color: #d8d8e8 !important;\n background-color: #f7f6fd !important;\n }\n\n .inspector-account-strip {\n background: #f7f6fd !important;\n color: #010507 !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .drag-handle,\n .inspector-window[data-color-scheme=\"dark\"] .inspector-account-strip {\n background: #15171e !important;\n }\n\n /* ── Tab buttons ─────────────────────────────────────────────── */\n /*\n * Named classes owned by this component — no Tailwind conflict.\n * Active: brand surface/surfaceContainerActive (lilac tint) +\n * border/borderActionEnabled underline.\n * Dark fill is for primary action buttons only, not nav tabs.\n */\n .cpk-tab-active {\n background-color: rgba(190, 194, 255, 0.18);\n color: #010507;\n font-weight: 600;\n }\n .cpk-tab-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n }\n .cpk-tab-active .cpk-tab-icon {\n color: #5558b2;\n }\n .cpk-tab-inactive {\n background-color: transparent;\n color: #2b2b2b;\n }\n .cpk-tab-inactive .cpk-tab-icon {\n color: #68686e;\n }\n .cpk-tab-inactive:hover {\n background-color: rgba(190, 194, 255, 0.08);\n color: #010507;\n cursor: pointer;\n }\n .cpk-tab-active {\n cursor: pointer;\n }\n .cpk-threads-overview-video-frame {\n position: relative;\n display: block;\n width: 100%;\n max-width: 440px;\n aspect-ratio: 16 / 9;\n margin: 0 0 14px;\n overflow: hidden;\n border: 1px solid #dbdbe5;\n border-radius: 10px;\n background:\n linear-gradient(\n 135deg,\n rgba(190, 194, 255, 0.18),\n rgba(133, 236, 206, 0.12)\n ),\n #ffffff;\n box-shadow: 0 8px 20px rgba(1, 5, 7, 0.08);\n }\n .cpk-threads-overview-video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n .cpk-threads-overview-video-embed {\n width: 100%;\n height: 100%;\n border: 0;\n }\n\n /* ── Header controls on the branded account strip ──────────── */\n .drag-handle > div[data-inspector-account-strip] button {\n color: #57575b !important;\n cursor: pointer;\n }\n .drag-handle > div[data-inspector-account-strip] button,\n .inspector-nav-control,\n [data-inspector-thread-cta] {\n outline: 2px solid transparent;\n outline-offset: 2px;\n }\n .drag-handle > div[data-inspector-account-strip] button:hover {\n background-color: rgba(100, 48, 171, 0.09) !important;\n color: #3f176f !important;\n }\n .drag-handle > div[data-inspector-account-strip] button:focus-visible {\n outline: 2px solid #bec2ff !important;\n outline-offset: 2px;\n }\n .inspector-nav-control:focus-visible,\n [data-inspector-thread-cta]:focus-visible,\n [data-inspector-action-placement=\"threads-footer\"]:focus-visible {\n outline: 2px solid #6430ab !important;\n outline-offset: 2px;\n }\n .inspector-sidebar .inspector-nav-control,\n .inspector-sidebar .inspector-sidebar-control,\n .inspector-sidebar .inspector-sidebar-label {\n display: flex !important;\n justify-content: flex-start !important;\n text-align: left !important;\n outline-offset: -2px;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-control,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-control,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-toggle {\n box-sizing: border-box !important;\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n justify-content: center !important;\n align-items: center !important;\n gap: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-icon,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-icon svg,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-icon,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-icon\n svg,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-placeholder\n svg {\n width: 18px !important;\n height: 18px !important;\n overflow: visible !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"] {\n display: flex !important;\n flex: none !important;\n width: 36px !important;\n min-width: 36px !important;\n max-width: 36px !important;\n justify-content: center !important;\n align-items: center !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-agent-placeholder {\n display: flex !important;\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 0 !important;\n padding: 0 !important;\n transition:\n background-color 180ms ease,\n border-color 180ms ease,\n color 180ms ease !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-label,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-chevron {\n display: none !important;\n width: 0 !important;\n min-width: 0 !important;\n flex: none !important;\n overflow: hidden !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-label,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-label {\n display: none !important;\n }\n .inspector-sidebar .inspector-nav-control:focus-visible,\n .inspector-sidebar .inspector-sidebar-label:focus-visible,\n .inspector-sidebar .inspector-sidebar-toggle:focus-visible {\n outline-offset: -2px !important;\n }\n\n /* ── Agent/context dropdown ──────────────────────────────────── */\n [data-context-dropdown-root=\"true\"] > button {\n border-color: #dbdbe5 !important;\n color: #010507 !important;\n }\n [data-context-dropdown-root=\"true\"] > button:hover {\n border-color: #bec2ff !important;\n background-color: #f7f7f9 !important;\n }\n [data-context-dropdown-root=\"true\"] > button > span:last-child {\n color: #68686e !important;\n }\n [data-context-dropdown-root=\"true\"] > div {\n border-color: #dbdbe5 !important;\n box-shadow: 0 4px 12px rgba(1, 5, 7, 0.08) !important;\n }\n [data-context-dropdown-root=\"true\"] > div button:hover,\n [data-context-dropdown-root=\"true\"] > div button:focus {\n background-color: #eceafa !important;\n color: #2f1664 !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button {\n border-color: #d8d8e8 !important;\n background-color: rgba(255, 255, 255, 0.7) !important;\n color: #010507 !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button:hover {\n border-color: #a5a9ee !important;\n background-color: #ffffff !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button\n > span:last-child {\n color: #68686e !important;\n }\n\n /* ── Resize handle ───────────────────────────────────────────── */\n .resize-handle {\n color: #68686e !important;\n }\n .resize-handle:hover {\n color: #57575b !important;\n }\n\n /* ── AG-UI Events tab ────────────────────────────────────────── */\n /* Row hover: replace blue tint with brand lilac */\n tr:hover td {\n background-color: rgba(190, 194, 255, 0.08) !important;\n }\n /* Reset/dark action button */\n button[class*=\"bg-gray-900\"] {\n background-color: #010507 !important;\n }\n button[class*=\"bg-gray-800\"] {\n background-color: #2b2b2b !important;\n }\n /* Copy \"copied\" state: generic green → brand mint */\n button[class*=\"bg-green-100\"] {\n background-color: rgba(133, 236, 206, 0.2) !important;\n color: #087653 !important;\n }\n\n /* ── Agents tab ──────────────────────────────────────────────── */\n /* Agent icon bubble: blue → lilac */\n span[class*=\"bg-blue-100\"]:not([class*=\"text-blue-800\"]) {\n background-color: rgba(190, 194, 255, 0.15) !important;\n }\n span[class*=\"text-blue-600\"] {\n color: #5558b2 !important;\n }\n /* Running badge: emerald → mint */\n span[class*=\"bg-emerald-50\"] {\n background-color: rgba(133, 236, 206, 0.15) !important;\n }\n span[class*=\"text-emerald-700\"] {\n color: #087653 !important;\n }\n /* Running status dot */\n span[class*=\"bg-emerald-500\"] {\n background-color: #85ecce !important;\n }\n /* Idle dot */\n span[class*=\"bg-gray-400\"] {\n background-color: #afafb7 !important;\n }\n /* User role badge (blue → lilac) */\n span[class*=\"bg-blue-100\"][class*=\"text-blue-800\"] {\n background-color: rgba(190, 194, 255, 0.22) !important;\n border: 1px solid rgba(190, 194, 255, 0.45) !important;\n color: #57575b !important;\n }\n /* Assistant role badge (green → mint) */\n span[class*=\"bg-green-100\"][class*=\"text-green-800\"] {\n background-color: rgba(133, 236, 206, 0.18) !important;\n border: 1px solid rgba(133, 236, 206, 0.4) !important;\n color: #087653 !important;\n }\n /* Tool role badge (amber → orange brand) */\n span[class*=\"bg-amber-100\"][class*=\"text-amber-800\"] {\n background-color: rgba(255, 172, 77, 0.15) !important;\n color: #57575b !important;\n }\n\n /* ── Frontend Tools tab ──────────────────────────────────────── */\n /* Handler badge (blue → lilac) */\n span[class*=\"bg-blue-50\"][class*=\"text-blue-700\"] {\n background-color: rgba(190, 194, 255, 0.12) !important;\n border-color: rgba(190, 194, 255, 0.3) !important;\n color: #010507 !important;\n }\n /* Renderer badge (purple → lilac-adjacent) */\n span[class*=\"bg-purple-50\"][class*=\"text-purple-700\"] {\n background-color: rgba(190, 194, 255, 0.12) !important;\n border-color: rgba(190, 194, 255, 0.3) !important;\n color: #57575b !important;\n }\n /* Required badge (rose → brand red) */\n span[class*=\"bg-rose-50\"][class*=\"text-rose-700\"] {\n background-color: rgba(250, 95, 103, 0.1) !important;\n border-color: rgba(250, 95, 103, 0.25) !important;\n color: #fa5f67 !important;\n }\n /* Code/default value blocks */\n code[class*=\"bg-gray-100\"],\n span[class*=\"bg-gray-100\"] {\n background-color: #f0f0f4 !important;\n }\n\n /* ── Connected status bar: match threads header mint (#5BE4BB) ──── */\n /* Outer strip bg + top border + text when connected badge is present */\n .inspector-window\n > div\n > div:last-child\n > div:last-child:has(div[class*=\"bg-emerald-50\"]) {\n background-color: rgba(91, 228, 187, 0.08) !important;\n border-top-color: rgba(91, 228, 187, 0.3) !important;\n color: #087653 !important;\n }\n /* Inner badge — slightly more opaque on the mint bg */\n div[class*=\"bg-emerald-50\"][class*=\"border-emerald-200\"] {\n background-color: rgba(91, 228, 187, 0.12) !important;\n border-color: rgba(91, 228, 187, 0.4) !important;\n color: #087653 !important;\n }\n div[class*=\"bg-emerald-50\"][class*=\"border-emerald-200\"]\n span[class*=\"opacity-80\"] {\n opacity: 1 !important;\n }\n /* Icon bubble inside connected badge → mint tint */\n div[class*=\"bg-emerald-50\"] span[class*=\"bg-white\"] {\n background-color: rgba(91, 228, 187, 0.3) !important;\n }\n\n /* ── Announcement panel ──────────────────────────────────────── */\n div[class*=\"border-slate-200\"][class*=\"bg-white\"] {\n border-color: #dbdbe5 !important;\n }\n /* Announcement icon bubble: black → brand light lavender + lilac icon */\n span[class*=\"bg-slate-900\"],\n div[class*=\"bg-slate-900\"] {\n background-color: #eee6fe !important;\n color: #5558b2 !important;\n }\n span[class*=\"text-slate-800\"],\n div[class*=\"text-slate-800\"] {\n color: #010507 !important;\n }\n `,\n ];\n\n connectedCallback(): void {\n super.connectedCallback();\n if (typeof window !== \"undefined\") {\n this.accountCtaMotionPaused = document.visibilityState !== \"visible\";\n this.threadsExampleOverviewVideoReducedMotion =\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ??\n false;\n this.ensureBrandFonts();\n window.addEventListener(\"resize\", this.handleResize);\n window.addEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n window.addEventListener(\"beforeunload\", this.handleAppBeforeUnload);\n document.addEventListener(\n \"visibilitychange\",\n this.handleDocumentVisibilityChange,\n );\n const viteHot = (\n import.meta as ImportMeta & {\n hot?: { on: (event: string, handler: () => void) => void };\n }\n ).hot;\n if (viteHot) {\n viteHot.on(\"vite:beforeUpdate\", this.handleAppBeforeUnload);\n }\n\n // Load state early (before first render) so menu selection is correct\n this.hydrateStateFromStorageEarly();\n this.learningSetupMarker = readLearningSetupMarker();\n this.learningSetupUnsubscribe = subscribeToLearningSetupMarker(\n (marker) => {\n this.learningSetupMarker = marker;\n this.requestUpdate();\n this.scheduleLearningPoll();\n },\n );\n this.refreshInspectorDismissalState();\n this.subscribeToSystemColorScheme();\n this.exampleTourDismissed = this.readThreadsExampleTourDismissed();\n // The superseded, origin-scoped read state is discarded rather than\n // migrated: every existing user is re-armed exactly once so they\n // discover the surface that replaced the announcement bubble. Deleting\n // the key rather than leaving it means nothing can fall back to it.\n clearLegacyAnnouncementReadState();\n this.tryAutoAttachCore();\n if (!this.isInspectorDismissed) {\n this.ensureAnnouncementLoading();\n }\n this.subscribeToInspectorThreadBridge();\n }\n this.requestUpdate();\n }\n\n private ensureBrandFonts(): void {\n ensureBrandFont(document);\n }\n\n private handleDocumentVisibilityChange = (): void => {\n this.accountCtaMotionPaused = document.visibilityState !== \"visible\";\n this.refreshInspectorDismissalState();\n // Flush point for defer reason 3: somebody is looking again.\n if (\n document.visibilityState === \"visible\" &&\n !this.isOpen &&\n !this.isInspectorDismissed\n ) {\n this.flushPendingSignalPulse();\n }\n if (\n document.visibilityState === \"visible\" &&\n this.isOpen &&\n this.selectedMenu === \"memories\"\n ) {\n void this.refreshLearningSnapshot({ preserve: true });\n } else {\n this.cancelLearningPoll();\n }\n this.requestUpdate();\n };\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.closePopOut();\n if (typeof window !== \"undefined\") {\n this.unsubscribeFromSystemColorScheme();\n window.removeEventListener(\"resize\", this.handleResize);\n window.removeEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n window.removeEventListener(\"beforeunload\", this.handleAppBeforeUnload);\n document.removeEventListener(\n \"visibilitychange\",\n this.handleDocumentVisibilityChange,\n );\n }\n // Clear pending body-transition timers to prevent post-teardown errors\n for (const id of this.bodyTransitionTimeoutIds) {\n clearTimeout(id);\n }\n this.bodyTransitionTimeoutIds.clear();\n if (this.transitionTimeoutId !== null) {\n clearTimeout(this.transitionTimeoutId);\n this.transitionTimeoutId = null;\n }\n this.clearIconRailContextCloseTimer();\n this.unsubscribeFromInspectorThreadBridge();\n this.learningSetupUnsubscribe?.();\n this.learningSetupUnsubscribe = null;\n this.clearLearningSnapshot();\n this.stopIntelligenceStory();\n this.clearIntelligencePromptReset();\n this.homeFeaturePromptCopyGeneration += 1;\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n this.homeFeaturePromptCopyResetTimeoutId = null;\n }\n this.homeFeaturePromptCopyState = null;\n this.stopSignalPulse();\n this.cancelGestureTail();\n this.cancelLauncherHudIntro();\n this.clearInspectorDismissalTimer();\n this.cancelThreadRefreshDebounce();\n this.clearInspectorUsageRefresh();\n this.cleanupThreadsExampleOverviewVideo();\n this.removeDockStyles(true); // Clean up any docking styles, skip transition\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 this.contextState.window.size = this.clampWindowSize(\n this.contextState.window.size,\n );\n\n // `hydrateStateFromStorage` may have restored `selectedMenu: \"memories\"`.\n // The memory subscription is normally created on a Memories-tab CLICK via\n // `handleMenuSelect`, which never fires when the tab boots already active —\n // leaving the realtime indicator stuck on the default \"connecting\" and the\n // list empty until the user toggles tabs. Subscribe now when the Memories\n // tab is the active tab. Gated on the active tab to preserve INSP-1 (no\n // unconditional subscribe), and safe if core is not yet attached or already\n // subscribed — `ensureMemorySubscription` early-returns in both cases.\n if (this.selectedMenu === \"memories\") {\n this.ensureMemorySubscription();\n }\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 if (this.isInspectorDismissed) {\n // The close action persists this immediately. This branch also covers a\n // different localhost port whose own Inspector state was still open.\n this.persistState();\n } else {\n this.ensureAnnouncementLoading();\n }\n\n this.updateHostTransform(this.isOpen ? \"window\" : \"button\");\n if (!this.isInspectorDismissed) {\n this.scheduleLauncherHudIntro();\n }\n }\n\n render() {\n if (this.isInspectorDismissed) return nothing;\n return this.isOpen\n ? html`\n <div data-inspector-portal-anchor></div>\n `\n : this.renderButton();\n }\n\n protected willUpdate(): void {\n // Before the render that paints the dot: every mutation of the underlying\n // connection / thread state already requests an update, so mirroring the\n // latches here keeps the resting dot in step with the state it reports.\n this.evaluateErrorSignals();\n this.reconcileSelectedMenuVisibility();\n if (this.isOpen && this.dockMode === \"docked-left\") {\n this.setAttribute(\"data-docked\", \"true\");\n } else {\n this.removeAttribute(\"data-docked\");\n }\n }\n\n protected updated(): void {\n // Host message shortcuts follow the actual Inspector, including persisted\n // dismissals and their expiry. Closing the panel still leaves it available.\n const visible = !this.isInspectorDismissed;\n if (visible !== this.lastReportedInspectorVisibility) {\n this.lastReportedInspectorVisibility = visible;\n this.dispatchEvent(\n new CustomEvent(\"cpk-inspector-visibility-change\", {\n detail: { visible },\n }),\n );\n }\n this.syncInspectorPortal();\n this.syncThreadsExampleOverviewVideo();\n this.maybeTrackInspectorMetadataViews();\n this.maybeTrackNewsSignalViewed();\n // The pill's full width is only measurable once it has been laid out, and\n // the answer decides both the direction and the telemetry label below, so\n // this runs before the visibility event rather than after it.\n this.resolvePillDirection();\n this.maybeTrackErrorSignalViewed();\n // \"Rendered with content\" is a property of the finished render, so the\n // news signal is retired here rather than from a render method.\n this.maybeCompleteWhatsNewView();\n this.maybeCompleteEventErrorView();\n this.flushErrorLandingScroll();\n this.maybeTrackHomeViewed();\n this.syncIntelligenceStory();\n\n if (!this.isOpen) {\n this.lastScrolledAgentNavigationLayout = null;\n return;\n }\n\n const navigation = this.activeRoot.querySelector<HTMLElement>(\n 'nav[aria-label=\"Inspector\"]',\n );\n if (!navigation) {\n return;\n }\n\n const activeControl = navigation.querySelector<HTMLElement>(\n '[aria-current=\"page\"]',\n );\n if (!activeControl) {\n return;\n }\n\n const layoutKey = [\n this.selectedMenu,\n this.dockMode,\n Math.round(this.contextState.window.size.width),\n typeof window === \"undefined\" ? 0 : window.innerWidth,\n navigation.clientWidth,\n navigation.scrollWidth,\n ].join(\":\");\n if (this.lastScrolledAgentNavigationLayout === layoutKey) {\n return;\n }\n\n if (typeof activeControl.scrollIntoView === \"function\") {\n activeControl.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }\n this.lastScrolledAgentNavigationLayout = layoutKey;\n }\n\n private renderButton() {\n // `.console-button` owns the launcher dimensions and publishes the same\n // number as `--cpk-launcher-size` for the signal dot's rim placement.\n // Tailwind scan tokens retained for generated-sheet stability: ease-in-out\n // ease-out\n const buttonClasses = [\n \"console-button\",\n \"group\",\n \"relative\",\n \"pointer-events-auto\",\n \"inline-flex\",\n // Kept as Tailwind scan tokens so the generated sheet stays stable;\n // the later `.console-button` rule owns the responsive dimensions.\n \"h-9\",\n \"w-9\",\n \"items-center\",\n \"justify-center\",\n \"rounded-full\",\n \"border\",\n \"text-xs\",\n \"font-medium\",\n \"text-white\",\n \"focus-visible:outline\",\n \"focus-visible:outline-2\",\n \"focus-visible:outline-offset-2\",\n \"focus-visible:outline-[#BEC2FF]\",\n \"touch-none\",\n \"select-none\",\n this.isDragging ? \"cursor-grabbing\" : \"cursor-pointer\",\n ].join(\" \");\n\n // One dot, and the highest-priority armed signal owns it. Everything the\n // launcher paints comes from that signal's description.\n const activeSignal = this.getActiveLauncherSignal();\n const signal = activeSignal ? LAUNCHER_SIGNALS[activeSignal] : null;\n const signalStyles = signal\n ? {\n \"--cpk-launcher-signal\": LAUNCHER_SIGNAL_COLORS[signal.tone],\n \"--cpk-launcher-cadence\": `${signal.cadence}ms`,\n }\n : {};\n\n return html`\n <div\n class=\"console-button-wrapper\"\n data-cpk-hud=${this.launcherHudOpen ? \"open\" : \"closed\"}\n @pointerenter=${this.handleLauncherHudEnter}\n @pointerleave=${this.handleLauncherHudLeave}\n @focusin=${this.handleLauncherHudFocusIn}\n @focusout=${this.handleLauncherHudFocusOut}\n @keydown=${this.handleLauncherHudKeydown}\n >\n ${this.renderLauncherPill()}\n <button\n class=${buttonClasses}\n type=\"button\"\n aria-expanded=${this.launcherHudOpen ? \"true\" : \"false\"}\n aria-controls=${this.launcherHudOpen ? \"cpk-launcher-hud\" : nothing}\n aria-label=${\n // The dot is decorative and hidden from assistive technology, and\n // the accessible signal for an announcement lives on its\n // navigation entry. A broken setup has no such entry until the\n // panel is open, so the launcher itself has to name the failure\n // class — otherwise a screen-reader user is the only user with no\n // signal outside the panel.\n signal && signal.tone === \"error\"\n ? `${LAUNCHER_BASE_LABEL}, ${signal.accessibleLabel}`\n : LAUNCHER_BASE_LABEL\n }\n title=${HUD_INSPECTOR_LABEL}\n data-drag-context=\"button\"\n data-cpk-signal=${signal ? signal.tone : nothing}\n data-cpk-signal-pulsing=${\n activeSignal !== null && this.pulsingSignal === activeSignal\n ? \"true\"\n : nothing\n }\n style=${styleMap(signalStyles)}\n data-dragging=${\n this.isDragging && this.pointerContext === \"button\"\n ? \"true\"\n : \"false\"\n }\n @pointerdown=${this.handlePointerDown}\n @pointermove=${this.handlePointerMove}\n @pointerup=${this.handlePointerUp}\n @pointercancel=${this.handlePointerCancel}\n @click=${this.handleButtonClick}\n >\n <img\n src=${inspectorLogoKiteUrl}\n alt=\"Inspector logo\"\n class=\"cpk-launcher-mark h-6 w-auto\"\n loading=\"lazy\"\n />\n ${\n // Purely decorative: the button is the target, it carries the\n // stable hover hint and the accessible name, and an unread\n // announcement is announced by its navigation entry, which is\n // where a keyboard user arrives.\n activeSignal !== null\n ? html`<span\n class=\"cpk-launcher-signal-wash\"\n aria-hidden=\"true\"\n ></span>\n <span\n class=\"cpk-launcher-signal-dot\"\n data-cpk-signal-dot=${activeSignal}\n aria-hidden=\"true\"\n ></span>`\n : nothing\n }\n </button>\n ${\n // The pill is a sighted-only surface, so the failure is also spoken\n // once per outage — otherwise the reader who was given the failure\n // class in the launcher's accessible name in the companion change is\n // excluded again, since a changed name is only read on focus.\n //\n // POLITE, never assertive. Speech is serial: it occupies the channel\n // the reader is using to operate their own software, and interrupting\n // that mid-sentence is out of the question for a development tool.\n //\n // It is rendered whenever the launcher is, empty and with no visual\n // footprint, because a live region has to exist on the page before\n // its content lands to be announced reliably.\n html`<span\n class=\"sr-only\"\n data-cpk-launcher-announcement\n role=\"status\"\n aria-live=\"polite\"\n >${this.getGestureLabel() ?? \"\"}</span\n >`\n }\n ${this.renderLauncherHud()}\n </div>\n `;\n }\n\n /**\n * The words the running gesture carries, or null when the launcher is quiet.\n *\n * Read from the signal's own description rather than from a condition on the\n * tone, so a third signal can carry a pill by declaring a label.\n */\n private getGestureLabel(): string | null {\n if (this.gestureSignal === null) return null;\n return LAUNCHER_SIGNALS[this.gestureSignal].pillLabel ?? null;\n }\n\n /**\n * The pill, laid out at its full width and clipped, for the whole gesture.\n *\n * It renders from the first frame of the beat — clipped to nothing, so it\n * shows nothing — because the room it needs cannot be measured until it has\n * been laid out, and the direction is decided at gesture start.\n */\n private renderLauncherPill(): TemplateResult | typeof nothing {\n const key = this.gestureSignal;\n if (key === null || this.pillPhase === null) return nothing;\n const signal = LAUNCHER_SIGNALS[key];\n const label = signal.pillLabel;\n if (label === undefined) return nothing;\n return html`\n <span\n class=\"cpk-launcher-pill\"\n data-cpk-launcher-pill=${key}\n data-cpk-pill-phase=${this.pillPhase}\n data-cpk-pill-direction=${\n // Before the measurement the pill is laid out as if it were opening\n // left, which is width-identical to the other side and shows nothing\n // either way while the clip is closed.\n this.pillDirection ?? \"left\"\n }\n style=${styleMap({\n \"--cpk-launcher-signal\": LAUNCHER_SIGNAL_COLORS[signal.tone],\n \"--cpk-launcher-pill-open\": `${ERROR_GESTURE_MS.open}ms`,\n \"--cpk-launcher-pill-close\": `${ERROR_GESTURE_MS.close}ms`,\n })}\n aria-hidden=\"true\"\n @click=${this.handlePillClick}\n >\n <span class=\"cpk-launcher-pill__heading\" data-cpk-pill-heading\n >${label}</span\n >\n <span class=\"cpk-launcher-pill__subline\" data-cpk-pill-subline\n >${PILL_SUBLINE_LABEL}</span\n >\n </span>\n `;\n }\n\n /**\n * A click on the pill opens the Inspector, exactly as pressing the mark\n * does — reusing the launcher's own open source, so the telemetry catalogue\n * is untouched and the two paths cannot be told apart downstream.\n *\n * Deliberately NOT focusable and deliberately not in the tab order: the\n * launcher beside it is already a focusable control for this same action,\n * and a second tab stop for one action is a regression. The pill stays\n * `aria-hidden` and this handler is a pointer affordance only.\n *\n * The gesture ends with the open, because `openInspector` cancels the tail —\n * the panel is over the launcher, so there is nothing left to reveal.\n */\n private handlePillClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.openInspector(\"floating_button\");\n };\n\n /** Whether a persisted temporary dismissal is still active. */\n private get isInspectorDismissed(): boolean {\n return (\n this.inspectorDismissedUntil !== null &&\n this.inspectorDismissedUntil > Date.now()\n );\n }\n\n /** Cancel the timer that restores Inspector after a temporary dismissal. */\n private clearInspectorDismissalTimer(): void {\n if (this.inspectorDismissalTimer === null) return;\n clearTimeout(this.inspectorDismissalTimer);\n this.inspectorDismissalTimer = null;\n }\n\n /** Schedule Inspector to return just after its persisted deadline. */\n private scheduleInspectorDismissalExpiry(): void {\n this.clearInspectorDismissalTimer();\n if (this.inspectorDismissedUntil === null) return;\n const delay = Math.max(0, this.inspectorDismissedUntil - Date.now() + 25);\n this.inspectorDismissalTimer = setTimeout(() => {\n this.inspectorDismissalTimer = null;\n this.refreshInspectorDismissalState();\n }, delay);\n }\n\n /** Reconcile this tab with host-scoped dismissal state from other ports. */\n private refreshInspectorDismissalState(): void {\n const hadDismissal = this.inspectorDismissedUntil !== null;\n this.inspectorDismissedUntil = loadInspectorDismissedUntil();\n this.clearInspectorDismissalTimer();\n\n if (this.inspectorDismissedUntil !== null) {\n this.closePopOut();\n this.closeInspector();\n this.scheduleInspectorDismissalExpiry();\n if (!hadDismissal) this.requestUpdate();\n return;\n }\n\n if (!hadDismissal || !this.isConnected) return;\n this.ensureAnnouncementLoading();\n this.requestUpdate();\n void this.updateComplete.then(() => {\n if (!this.isConnected || this.isInspectorDismissed) return;\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n this.scheduleLauncherHudIntro();\n this.flushPendingSignalPulse();\n });\n }\n\n /** Hide Inspector for a supported duration and persist it for this host. */\n private dismissInspectorFor(duration: InspectorDismissalDuration): void {\n const now = Date.now();\n const until = now + INSPECTOR_DISMISSAL_MS[duration];\n saveInspectorDismissedUntil(until, now);\n this.inspectorDismissedUntil = until;\n this.scheduleInspectorDismissalExpiry();\n this.settingsOpen = false;\n this.closeLauncherHud();\n this.stopSignalPulse();\n this.cancelGestureTail();\n this.cancelLauncherHudIntro();\n this.closePopOut();\n\n if (this.isOpen) {\n this.closeInspector();\n return;\n }\n\n this.persistState();\n this.requestUpdate();\n }\n\n private isLauncherHudBlocked(): boolean {\n return this.gestureSignal !== null || this.isInspectorDismissed;\n }\n\n private scheduleLauncherHudIntro(\n delay: number = LAUNCHER_HUD_INTRO_MS.delay,\n ): void {\n if (this.isInspectorDismissed) return;\n if (this.launcherHudIntroStartTimer !== null) {\n clearTimeout(this.launcherHudIntroStartTimer);\n }\n this.launcherHudIntroStartTimer = setTimeout(() => {\n this.launcherHudIntroStartTimer = null;\n if (!this.isConnected || this.isOpen || this.isInspectorDismissed) return;\n if (this.isLauncherHudBlocked()) {\n this.scheduleLauncherHudIntro(LAUNCHER_HUD_INTRO_MS.blockedRetry);\n return;\n }\n\n this.resolveLauncherHudSide();\n this.launcherHudIntro = true;\n this.launcherHudOpen = true;\n void this.refreshLearningSnapshot({ preserve: true });\n this.requestUpdate();\n this.launcherHudIntroEndTimer = setTimeout(() => {\n this.launcherHudIntroEndTimer = null;\n this.launcherHudIntro = false;\n this.launcherHudOpen = false;\n this.requestUpdate();\n }, LAUNCHER_HUD_INTRO_MS.duration);\n }, delay);\n }\n\n private cancelLauncherHudIntro(): void {\n if (this.launcherHudIntroStartTimer !== null) {\n clearTimeout(this.launcherHudIntroStartTimer);\n this.launcherHudIntroStartTimer = null;\n }\n if (this.launcherHudIntroEndTimer !== null) {\n clearTimeout(this.launcherHudIntroEndTimer);\n this.launcherHudIntroEndTimer = null;\n }\n if (!this.launcherHudIntro) return;\n this.launcherHudIntro = false;\n if (this.isConnected) {\n this.requestUpdate();\n }\n }\n\n private resolveLauncherHudSide(): void {\n if (typeof window === \"undefined\") {\n this.launcherHudSide = \"left\";\n return;\n }\n const button =\n this.activeRoot.querySelector<HTMLElement>(\".console-button\");\n if (!button) {\n this.launcherHudSide = \"left\";\n return;\n }\n const mark = button.getBoundingClientRect();\n if (mark.left - LAUNCHER_HUD_WIDTH >= EDGE_MARGIN) {\n this.launcherHudSide = \"left\";\n return;\n }\n this.launcherHudSide = \"right\";\n }\n\n private openLauncherHud(): void {\n if (this.isLauncherHudBlocked() || this.isOpen) return;\n this.resolveLauncherHudSide();\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n this.launcherHudCloseTimer = null;\n }\n if (this.launcherHudOpen) return;\n this.launcherHudOpen = true;\n void this.refreshLearningSnapshot({ preserve: true });\n this.requestUpdate();\n }\n\n private closeLauncherHud(): void {\n this.cancelLauncherHudIntro();\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n this.launcherHudCloseTimer = null;\n }\n if (!this.launcherHudOpen) return;\n this.launcherHudOpen = false;\n this.requestUpdate();\n }\n\n private handleLauncherHudEnter = (): void => {\n this.cancelLauncherHudIntro();\n this.openLauncherHud();\n };\n\n private handleLauncherHudLeave = (): void => {\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n }\n this.launcherHudCloseTimer = setTimeout(() => {\n this.launcherHudCloseTimer = null;\n this.closeLauncherHud();\n }, 160);\n };\n\n private handleLauncherHudFocusIn = (): void => {\n this.cancelLauncherHudIntro();\n this.openLauncherHud();\n };\n\n private handleLauncherHudFocusOut = (event: FocusEvent): void => {\n const next = event.relatedTarget;\n const wrapper = event.currentTarget;\n if (\n next instanceof Node &&\n wrapper instanceof Node &&\n wrapper.contains(next)\n ) {\n return;\n }\n this.closeLauncherHud();\n };\n\n private handleLauncherHudKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n if (!this.launcherHudOpen) return;\n event.preventDefault();\n event.stopPropagation();\n this.closeLauncherHud();\n this.activeRoot\n .querySelector<HTMLButtonElement>(\".console-button\")\n ?.focus();\n };\n\n private handleHudActionClick = (\n event: Event,\n row: LauncherHudRowId,\n ): void => {\n event.preventDefault();\n event.stopPropagation();\n this.hudLandingMenu =\n row === \"threads\" ? \"threads\" : row === \"learning\" ? \"memories\" : \"home\";\n this.closeLauncherHud();\n this.openInspector(\"floating_button\");\n };\n\n private handleHudRowClick = (event: Event, row: LauncherHudRowId): void => {\n const target = event.target;\n if (\n target instanceof Element &&\n target.closest(\".cpk-launcher-hud__controls, [data-cpk-hud-action]\")\n ) {\n return;\n }\n this.handleHudActionClick(event, row);\n };\n\n private handleHudNewsClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.hudLandingMenu = WHATS_NEW_MENU_KEY;\n this.closeLauncherHud();\n this.openInspector(\"floating_button\");\n };\n\n private handleHudNewsDismissClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.clearNewsSignal();\n this.activeRoot\n .querySelector<HTMLButtonElement>(\".console-button\")\n ?.focus({ preventScroll: true });\n };\n\n /** Apply the launcher HUD's one-day dismissal without opening Inspector. */\n private handleHudDismissDayClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.dismissInspectorFor(\"day\");\n };\n\n private getUnreadAnnouncementTitle(): string | null {\n if (!this.newsSignalArmed || !this.announcementLoaded) return null;\n const title = this.announcementPreviewText?.trim() || \"New in CopilotKit\";\n const titleCharacters = Array.from(title);\n return titleCharacters.length > HUD_ANNOUNCEMENT_TITLE_LIMIT\n ? `${titleCharacters\n .slice(0, HUD_ANNOUNCEMENT_TITLE_LIMIT)\n .join(\"\")\n .trimEnd()}...`\n : title;\n }\n\n private renderHudRow(args: {\n id: LauncherHudRowId;\n label: string;\n icon: LucideIconName;\n connected?: boolean;\n introIndex: number;\n }): TemplateResult | typeof nothing {\n if (args.connected) return nothing;\n const detailId = `cpk-hud-detail-${args.id}`;\n return html`\n <li\n class=\"cpk-launcher-hud__row\"\n data-cpk-hud-row=${args.id}\n data-cpk-hud-action-kind=\"navigate\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n args.introIndex,\n ),\n })}\n @click=${(event: Event) => this.handleHudRowClick(event, args.id)}\n >\n <span class=\"cpk-launcher-hud__primary\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__action\"\n data-cpk-hud-action\n aria-label=${`Open ${args.label} in Inspector`}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__feature-icon\"\n data-cpk-hud-icon=${args.id}\n aria-hidden=\"true\"\n >${this.renderIcon(args.icon)}</span\n >\n <span class=\"cpk-launcher-hud__label\">${args.label}</span>\n </button>\n <span\n class=\"cpk-launcher-hud__tooltip\"\n id=${detailId}\n role=\"tooltip\"\n >${HUD_LEARN_MORE_LABEL}</span\n >\n </span>\n <span class=\"cpk-launcher-hud__controls\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__learn-more\"\n data-cpk-hud-learn-more=${args.id}\n aria-label=${`Learn more about ${args.label}`}\n aria-describedby=${detailId}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n ${this.renderIcon(\"CircleHelp\")}\n </button>\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__toggle\"\n data-cpk-hud-toggle=${args.id}\n data-enabled=${args.connected ? \"true\" : \"false\"}\n aria-label=${\n args.connected\n ? `${args.label} is enabled`\n : `Open ${args.label} in Inspector`\n }\n ?disabled=${args.connected}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__toggle-track\"\n aria-hidden=\"true\"\n ></span>\n </button>\n </span>\n </li>\n `;\n }\n\n private renderLauncherHud(): TemplateResult | typeof nothing {\n if (!this.launcherHudOpen) return nothing;\n // The launcher must agree with Home about feature availability. Raw\n // transport flags can be present for a runtime that is not entitled to use\n // Intelligence, which previously made the HUD show every service as on.\n const homeModel = this.getHomeModel();\n const threadsOn = homeModel.services.some(\n (service) => service.id === \"threads\" && service.enabled,\n );\n const learningOn = homeModel.services.some(\n (service) => service.id === \"memory\" && service.enabled,\n );\n const announcementTitle = this.getUnreadAnnouncementTitle();\n const featureBlockIntroIndex = announcementTitle ? 1 : 0;\n const dismissOnly = !announcementTitle && threadsOn && learningOn;\n return html`\n <div\n class=\"cpk-launcher-hud\"\n id=\"cpk-launcher-hud\"\n data-cpk-launcher-hud\n ?data-cpk-hud-dismiss-only=${dismissOnly}\n data-cpk-hud-side=${this.launcherHudSide}\n data-cpk-hud-vertical=${this.contextState.button.anchor.vertical}\n data-cpk-hud-intro=${this.launcherHudIntro ? \"true\" : nothing}\n data-color-scheme=${this.colorScheme}\n style=${styleMap({\n \"--cpk-launcher-hud-intro-duration\": `${LAUNCHER_HUD_INTRO_MS.duration}ms`,\n \"--cpk-launcher-hud-waterfall-duration\": `${LAUNCHER_HUD_INTRO_MS.waterfallDuration}ms`,\n })}\n >\n ${\n dismissOnly\n ? nothing\n : html`\n <span class=\"cpk-launcher-hud__arrow\" aria-hidden=\"true\"></span>\n `\n }\n <div class=\"cpk-launcher-hud__card\">\n ${\n announcementTitle\n ? html`\n <div\n class=\"cpk-launcher-hud__masthead\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(0),\n })}\n >\n <div class=\"cpk-launcher-hud__news-wrap\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__news\"\n data-cpk-hud-news\n aria-label=${`Open new notification: ${announcementTitle}`}\n @click=${this.handleHudNewsClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__news-label\"\n data-cpk-hud-news-label\n aria-hidden=\"true\"\n >New</span\n >\n <span class=\"cpk-launcher-hud__news-title\"\n >${announcementTitle}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__news-dismiss\"\n data-cpk-hud-news-dismiss\n aria-label=\"Dismiss notification\"\n @click=${this.handleHudNewsDismissClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n ${this.renderIcon(\"X\")}\n </button>\n </div>\n </div>\n `\n : nothing\n }\n ${\n threadsOn && learningOn\n ? nothing\n : html`\n <ul\n class=\"cpk-launcher-hud__list cpk-launcher-hud__feature-list\"\n role=\"list\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n featureBlockIntroIndex,\n ),\n })}\n >\n ${this.renderHudRow({\n id: \"threads\",\n label: HUD_THREADS_LABEL,\n icon: \"MessageSquare\",\n connected: threadsOn,\n introIndex: featureBlockIntroIndex + 1,\n })}\n ${this.renderHudRow({\n id: \"learning\",\n label: HUD_LEARNING_LABEL,\n icon: \"Brain\",\n connected: learningOn,\n introIndex: featureBlockIntroIndex + (threadsOn ? 1 : 2),\n })}\n </ul>\n `\n }\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__dismiss-day\"\n data-cpk-dismiss-inspector=\"day\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n dismissOnly\n ? 0\n : featureBlockIntroIndex +\n Number(!threadsOn) +\n Number(!learningOn) +\n 1,\n ),\n })}\n @click=${this.handleHudDismissDayClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n Hide Inspector for a day\n </button>\n </div>\n </div>\n `;\n }\n\n /** Render a trusted action with optional context-specific copy. */\n private renderInspectorAction(\n action: InspectorMetadataAction,\n placement: \"threads-footer\" | \"locked\",\n displayLabel:\n | InspectorMetadataAction[\"label\"]\n | \"Upgrade Your Plan\" = action.label,\n ) {\n const actionIntent =\n displayLabel === \"Upgrade Your Plan\" ? \"upgrade\" : undefined;\n return html`\n <a\n data-inspector-action-placement=${placement}\n data-inspector-action-intent=${actionIntent ?? nothing}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${displayLabel} (opens in a new tab)\"\n style=${\n placement === \"threads-footer\"\n ? \"\"\n : \"display:inline-flex;min-height:34px;align-items:center;justify-content:center;gap:6px;border:1px solid #dbdbe5;border-radius:7px;background:#ffffff;padding:8px 12px;color:#57575b;font-size:12px;font-weight:600;text-decoration:none;outline-style:solid;outline-width:2px;outline-color:transparent;outline-offset:2px;cursor:pointer;\"\n }\n @click=${() =>\n this.handleInspectorMetadataActionClick(action, placement)}\n >\n ${displayLabel}\n </a>\n `;\n }\n\n private renderInspectorSidebar(\n iconRail: boolean,\n automaticallyCollapsed: boolean,\n agentSelector: TemplateResult | typeof nothing,\n ) {\n const homeModel = this.getHomeModel();\n return html`\n <aside\n class=\"inspector-sidebar\"\n data-icon-rail=${iconRail ? \"true\" : \"false\"}\n >\n ${\n iconRail && this.sidebarRailTooltip\n ? html`\n <span\n class=\"inspector-sidebar-rail-tooltip\"\n role=\"tooltip\"\n style=${`top: ${this.sidebarRailTooltip.top}px`}\n >${this.sidebarRailTooltip.label}</span\n >\n `\n : nothing\n }\n <div\n class=\"inspector-sidebar-agent-scope\"\n data-inspector-sidebar-agent-selector\n >\n <div class=\"inspector-agent-selector\">${agentSelector}</div>\n </div>\n <nav class=\"inspector-sidebar-nav\" aria-label=\"Inspector\">\n ${INSPECTOR_NAV_SECTIONS.map(({ group, label }) => {\n const items = this.getVisibleMenuItemsForGroup(group);\n if (items.length === 0) {\n return nothing;\n }\n return html`\n <div\n class=\"inspector-sidebar-section\"\n data-inspector-section=${group}\n >\n ${\n label\n ? html`<button\n type=\"button\"\n class=\"inspector-sidebar-label\"\n data-inspector-group=${group}\n aria-label=${label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleGroupSelect(group)}\n >\n ${label}\n </button>`\n : nothing\n }\n ${items.map((item) => {\n const isSelected = this.selectedMenu === item.key;\n const marker = this.getNavigationSignalFor(item.key);\n return html`\n <button\n type=\"button\"\n class=\"inspector-nav-control inspector-sidebar-control ${\n isSelected ? \"inspector-nav-control-active\" : \"\"\n }\"\n data-inspector-group=${group}\n data-inspector-menu-key=${item.key}\n aria-current=${isSelected ? \"page\" : nothing}\n aria-label=${\n marker\n ? `${item.label}, ${marker.accessibleLabel}`\n : item.label\n }\n data-inspector-tooltip=${item.label}\n title=${iconRail ? nothing : item.label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerenter=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @pointerleave=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @focus=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @blur=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @click=${() => this.handleMenuSelect(item.key)}\n >\n <span class=\"inspector-nav-icon\" aria-hidden=\"true\">\n ${\n item.key === \"threads\"\n ? unsafeHTML(this.customTabIcons.threads)\n : this.renderIcon(item.icon)\n }\n </span>\n <span class=\"inspector-nav-label\">${item.label}</span>\n ${\n marker\n ? html`\n <span\n class=\"inspector-nav-signal-dot\"\n data-cpk-signal-tone=${marker.tone}\n aria-hidden=\"true\"\n ></span>\n `\n : nothing\n }\n </button>\n `;\n })}\n </div>\n `;\n })}\n </nav>\n ${\n automaticallyCollapsed\n ? nothing\n : html`\n <div class=\"inspector-sidebar-footer\">\n ${\n iconRail\n ? nothing\n : html`\n <div class=\"inspector-sidebar-status-list\">\n ${this.renderSidebarIntelligenceStatus(homeModel)}\n </div>\n `\n }\n <button\n type=\"button\"\n class=\"inspector-sidebar-toggle\"\n data-inspector-sidebar-toggle\n aria-label=${iconRail ? \"Expand sidebar\" : \"Collapse sidebar\"}\n aria-expanded=${iconRail ? \"false\" : \"true\"}\n data-inspector-tooltip=${\n iconRail ? \"Expand sidebar\" : nothing\n }\n title=${iconRail ? nothing : \"Collapse sidebar\"}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerenter=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @pointerleave=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @focus=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @blur=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @click=${this.handleSidebarToggle}\n >\n <span class=\"inspector-nav-icon\" aria-hidden=\"true\">\n ${this.renderIcon(\n iconRail ? \"ChevronRight\" : \"ChevronLeft\",\n )}\n </span>\n <span class=\"inspector-nav-label\"\n >${iconRail ? \"Expand\" : \"Collapse\"}</span\n >\n </button>\n </div>\n `\n }\n </aside>\n `;\n }\n\n private renderSidebarIntelligenceStatus(model: HomeModel) {\n const connected = model.hero.connection === \"connected\";\n const organizationName = model.project?.organizationName;\n const planLabel = model.project?.planLabel;\n const action = model.hero.action;\n const renewing = action?.kind === \"renew\";\n if (!connected && action) {\n const stateLabel = renewing\n ? \"Intelligence plan expired\"\n : \"Intelligence is off\";\n const setupLabel = renewing\n ? \"Renew to restore access\"\n : \"Connect Intelligence\";\n return html`\n <a\n class=\"inspector-sidebar-status-card inspector-sidebar-intelligence inspector-sidebar-intelligence-setup\"\n data-inspector-sidebar-intelligence\n data-inspector-sidebar-intelligence-action=${action.kind}\n data-state=\"disconnected\"\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} to enable Rich Threads and Automatic Learning (opens in a new tab)\"\n title=${action.label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n <span class=\"inspector-sidebar-status-copy\">\n <strong>${stateLabel}</strong>\n <span>${setupLabel}</span>\n </span>\n <span class=\"inspector-sidebar-setup-arrow\" aria-hidden=\"true\">\n ${this.renderIcon(\"ArrowUpRight\")}\n </span>\n </a>\n `;\n }\n\n const primaryLabel = connected\n ? (organizationName ?? \"Intelligence\")\n : \"Intelligence unavailable\";\n const secondaryLabel = connected\n ? planLabel\n ? `${planLabel} plan`\n : \"Connected\"\n : \"Rich Threads and Automatic Learning are off\";\n const label = connected\n ? `${primaryLabel}, ${secondaryLabel}, Intelligence connected`\n : \"Connect Intelligence\";\n const actionLabel = action?.label;\n const description = connected\n ? `${secondaryLabel} · Intelligence connected`\n : \"Rich Threads and Automatic Learning need Intelligence.\";\n return html`\n <section\n class=\"inspector-sidebar-status-card inspector-sidebar-intelligence\"\n data-inspector-sidebar-intelligence\n data-state=${connected ? \"connected\" : \"disconnected\"}\n aria-label=${label}\n title=${description}\n >\n <span class=\"inspector-sidebar-status-copy\">\n <strong>${primaryLabel}</strong>\n <span>${secondaryLabel}</span>\n </span>\n ${\n action\n ? html`\n <a\n class=\"inspector-sidebar-status-action\"\n data-inspector-sidebar-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${actionLabel} (opens in a new tab)\"\n title=${actionLabel}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n <span class=\"inspector-sidebar-status-action-label\"\n >${actionLabel}</span\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"ArrowUpRight\")}</span\n >\n </a>\n `\n : nothing\n }\n </section>\n `;\n }\n\n private handleSidebarToggle = (): void => {\n this.sidebarRailTooltip = null;\n this.sidebarCollapsed = !this.sidebarCollapsed;\n this.persistState();\n this.requestUpdate();\n };\n\n private handleSidebarRailTooltipShow = (event: Event): void => {\n const target = event.currentTarget;\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n const label = target.dataset.inspectorTooltip;\n const sidebar = target.closest<HTMLElement>(\".inspector-sidebar\");\n if (!label || !sidebar) {\n return;\n }\n\n const targetBounds = target.getBoundingClientRect();\n const sidebarBounds = sidebar.getBoundingClientRect();\n this.sidebarRailTooltip = {\n label,\n top: targetBounds.top - sidebarBounds.top + targetBounds.height / 2,\n };\n this.requestUpdate();\n };\n\n private handleSidebarRailTooltipHide = (): void => {\n if (this.sidebarRailTooltip === null) {\n return;\n }\n this.sidebarRailTooltip = null;\n this.requestUpdate();\n };\n\n private handleColorSchemeToggle = (): void => {\n this.colorScheme = this.colorScheme === \"light\" ? \"dark\" : \"light\";\n this.hasExplicitColorScheme = true;\n this.persistState();\n this.requestUpdate();\n };\n\n private getHomeModel(): HomeModel {\n const lastRuntimeEvent = this.flattenedEvents[0];\n return buildHomeModel({\n intelligenceConnected: Boolean(this._core?.intelligence),\n threadsAvailable: this.areThreadEndpointsAvailable(),\n metadata: this.inspectorMetadataProjection,\n runtimeUrl: this._core?.runtimeUrl,\n runtimeConnectionState: this.getCoreStatusSummary().state,\n lastRuntimeEvent: lastRuntimeEvent\n ? {\n id: lastRuntimeEvent.id,\n agentId: lastRuntimeEvent.agentId,\n type: lastRuntimeEvent.type,\n timestamp: lastRuntimeEvent.timestamp,\n }\n : undefined,\n // A capability advertises the endpoint, not a configured Learning\n // container. Use its successful snapshot for Home and launcher status.\n learningOn:\n this.learningSupported &&\n this.learningError === null &&\n this.learningSnapshot?.configuration.state === \"configured\",\n a2uiOn: this._core?.a2uiEnabled === true,\n openGenUiOn: this._core?.openGenerativeUIEnabled === true,\n suggestionsOn: this._core?.suggestions === true,\n audioOn: this._core?.audioFileTranscriptionEnabled === true,\n websocketUrl: this._core?.intelligence?.wsUrl,\n announcementPreviewText: this.announcementPreviewText ?? undefined,\n announcementMarkdown: this.announcementMarkdown ?? undefined,\n announcementHtml: this.announcementHtml ?? undefined,\n intelligenceSignupUrl: this.getIntelligenceSignupUrl(),\n });\n }\n\n private renderHomeView() {\n const model = this.getHomeModel();\n const connected = model.hero.connection === \"connected\";\n return html`\n <div\n class=\"inspector-home\"\n data-inspector-home\n data-inspector-home-state=${connected ? \"connected\" : \"disconnected\"}\n >\n ${this.renderHomeWhatsNewPreview(model.news)}\n <header class=\"inspector-home-heading\"><div><h1>${connected ? (model.project?.projectName ?? \"Your agent workspace\") : \"Welcome to Intelligence\"}</h1><p>${connected ? \"Inspect conversations and see what your agent is learning.\" : \"Connect your agent. Intelligence learns from experience.\"}</p></div></header>\n ${connected ? this.renderHomeSystemHealth(model) : this.renderHomeIntelligenceHud(model)}\n ${connected ? this.renderHomeIntelligenceHud(model) : this.renderHomeSystemHealth(model)}\n ${this.renderHomeFeatures(model)}\n </div>\n `;\n }\n\n private renderHomeWhatsNewPreview(news: HomeModel[\"news\"]) {\n const unread = this.newsSignalArmed && this.announcementLoaded;\n if (news.empty || !unread) {\n return nothing;\n }\n\n return html`\n <section\n class=\"inspector-whats-new-preview\"\n data-inspector-home-band=\"news\"\n data-unread=\"true\"\n role=\"note\"\n aria-label=\"New CopilotKit update\"\n >\n <button\n type=\"button\"\n class=\"inspector-whats-new-preview-body\"\n data-inspector-whats-new-preview\n aria-label=\"Open What's New\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleMenuSelect(WHATS_NEW_MENU_KEY)}\n >\n <span class=\"inspector-whats-new-preview-copy\">\n <span class=\"inspector-whats-new-preview-title\">\n <span class=\"inspector-home-story-unread\">New</span>\n <strong>${news.title}</strong>\n </span>\n <span>${news.previewText}</span>\n </span>\n <span class=\"inspector-whats-new-preview-action\">\n View update ${this.renderIcon(\"ArrowRight\")}\n </span>\n </button>\n </section>\n `;\n }\n\n private renderWhatsNewView() {\n const state = this.getWhatsNewState();\n const news = this.getHomeModel().news;\n const updatedAt = this.announcementTimestamp\n ? new Date(this.announcementTimestamp)\n : null;\n const updatedLabel =\n updatedAt && !Number.isNaN(updatedAt.getTime())\n ? new Intl.DateTimeFormat(undefined, {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n }).format(updatedAt)\n : null;\n return html`\n <div\n class=\"inspector-home inspector-whats-new\"\n data-inspector-whats-new\n data-cpk-whats-new\n data-cpk-whats-new-state=${state}\n >\n <header class=\"inspector-whats-new-header\">\n <h1 class=\"inspector-home-title\">What's New</h1>\n ${\n updatedLabel\n ? html`\n <p class=\"inspector-whats-new-updated\">\n Updated\n <time datetime=${updatedAt?.toISOString()}\n >${updatedLabel}</time\n >\n </p>\n `\n : nothing\n }\n </header>\n <section class=\"inspector-home-news\" aria-label=\"CopilotKit updates\">\n ${\n news.empty || !news.documentHtml\n ? html`\n <article class=\"inspector-whats-new-empty\">\n <h2 class=\"inspector-home-card-title\">${news.title}</h2>\n <p class=\"inspector-home-card-copy\">${news.previewText}</p>\n </article>\n `\n : html`\n <article class=\"inspector-whats-new-document\">\n <div\n class=\"announcement-content\"\n @click=${this.handleAnnouncementContentClick}\n >\n ${unsafeHTML(news.documentHtml)}\n </div>\n </article>\n `\n }\n </section>\n </div>\n `;\n }\n\n private renderHomeIntelligenceHud(model: HomeModel) {\n const project = model.project;\n const connected = model.hero.connection === \"connected\";\n const action = model.hero.action;\n const renewing = action?.kind === \"renew\";\n // Three distinct jobs, not two. A lapsed plan needs a renewal link, not an\n // install prompt and an explainer — that developer already knows what\n // Intelligence is. Only the never-connected case gets the full pitch.\n const installing = !connected && !renewing;\n return html`\n <section\n class=\"inspector-home-section inspector-intelligence-hud\"\n data-inspector-home-card=\"intelligence\"\n data-state=${connected ? \"connected\" : \"disconnected\"}\n data-mode=${connected ? \"connected\" : renewing ? \"renew\" : \"install\"}\n aria-label=\"Intelligence ${\n connected ? \"connected\" : renewing ? \"plan expired\" : \"not enabled\"\n }\"\n >\n <header class=\"inspector-intelligence-hud-header\">\n <div class=\"inspector-intelligence-hud-heading\">\n <h2 class=\"inspector-home-section-title\">\n ${\n // The brand mark makes this read as a product lockup rather\n // than another status heading. Inside the h2 so it stays on\n // the same line, with an empty alt so the accessible name is\n // still just the product's name.\n installing\n ? html`\n <img\n class=\"inspector-intelligence-mark\"\n src=${inspectorLogoKiteUrl}\n alt=\"\"\n aria-hidden=\"true\"\n />\n `\n : nothing\n }\n ${connected ? \"Intelligence\" : model.hero.title}\n </h2>\n ${\n connected\n ? nothing\n : installing\n ? html`\n <p class=\"inspector-intelligence-sr-summary\">\n ${model.hero.body}\n </p>\n `\n : html`\n <p class=\"inspector-intelligence-hud-description\">\n ${model.hero.body}\n </p>\n `\n }\n </div>\n <div class=\"inspector-intelligence-hud-header-actions\">\n ${\n connected || renewing\n ? html`\n <span\n class=\"inspector-intelligence-hud-state\"\n data-tone=${connected ? \"success\" : \"checking\"}\n >\n <span aria-hidden=\"true\"></span>\n ${connected ? \"Connected\" : \"Plan expired\"}\n </span>\n `\n : nothing\n }\n ${\n renewing && action\n ? html`\n <a\n class=\"inspector-intelligence-hud-action inspector-intelligence-hud-connect-action\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n ${action.label} ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n }\n ${\n installing\n ? this.renderIntelligenceInstallActions(action)\n : nothing\n }\n </div>\n </header>\n\n ${\n // Exceptional state, so it gets its own full-width strip between the\n // bands rather than being squeezed into the header's action column.\n installing && this.promptCopyState === \"failed\"\n ? html`\n <code\n class=\"inspector-intelligence-install-fallback\"\n tabindex=\"0\"\n >${createOnboardingPrompt(this.getOnboardingRunId())}</code\n >\n `\n : nothing\n }\n ${installing ? this.renderIntelligenceStory() : nothing}\n ${\n connected\n ? html`\n <div\n class=\"inspector-intelligence-hud-details\"\n role=\"group\"\n aria-label=\"Intelligence account details\"\n >\n <section\n class=\"inspector-intelligence-hud-project\"\n data-inspector-metadata=${\n model.projectLinked && project ? \"identity\" : nothing\n }\n aria-label=${\n model.projectLinked && project\n ? \"Inspector account details\"\n : nothing\n }\n >\n <span class=\"inspector-intelligence-hud-detail-label\">\n Project\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${\n model.projectLinked && project\n ? html`<span>${project.projectName}</span>`\n : \"Not linked\"\n }\n </strong>\n ${\n model.projectLinked && project\n ? html`\n <span\n class=\"inspector-intelligence-hud-detail-subvalue\"\n >\n ${project.organizationName}\n </span>\n `\n : nothing\n }\n </section>\n <section class=\"inspector-intelligence-hud-plan\">\n <div class=\"inspector-intelligence-hud-plan-summary\">\n <span class=\"inspector-intelligence-hud-detail-label\">\n Plan\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${\n project?.planLabel\n ? html`\n <span data-inspector-metadata=\"plan\">\n ${project.planLabel}\n </span>\n `\n : \"No plan\"\n }\n </strong>\n ${\n project\n ? html`\n <span\n class=\"inspector-intelligence-hud-detail-subvalue\"\n >\n License ${project.license}\n </span>\n `\n : nothing\n }\n ${\n action\n ? html`\n <a\n class=\"inspector-intelligence-hud-action inspector-intelligence-hud-plan-action\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n ${action.label} ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n }\n </div>\n <div\n class=\"inspector-intelligence-hud-usage\"\n role=\"group\"\n aria-label=\"Threads usage\"\n >\n <span class=\"inspector-intelligence-hud-detail-label\">\n Threads usage\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${project?.usage?.limitLabel ?? \"Unavailable\"}\n </strong>\n ${\n project?.usage?.ratio !== undefined\n ? html`<span\n class=\"inspector-home-usage-bar\"\n aria-hidden=\"true\"\n ><span\n style=\"width:${Math.min(\n 100,\n Math.round(project.usage.ratio * 100),\n )}%\"\n ></span\n ></span>`\n : nothing\n }\n </div>\n </section>\n </div>\n `\n : nothing\n }\n </section>\n `;\n }\n\n private renderHomeSystemHealth(model: HomeModel) {\n const runtime = model.runtime;\n const health = runtime.health;\n const runtimeDetail = runtime.url ?? \"Runtime URL not configured\";\n const connectionDetail =\n health.liveUpdates.tone === \"success\"\n ? \"New events will appear here.\"\n : health.lastEvent.timestamp !== undefined\n ? `Last activity at ${formatTimestamp(health.lastEvent.timestamp)}`\n : \"Waiting for a connection\";\n const signals: Array<{\n id: \"runtime\" | \"connection\" | \"last-event\";\n label: string;\n value: string;\n detail: string;\n tone: HomeRuntimeHealthTone;\n eventId?: string;\n agentId?: string;\n }> = [\n {\n id: \"runtime\",\n label: \"Runtime\",\n value: health.runtime.label,\n detail: runtimeDetail,\n tone: health.runtime.tone,\n },\n {\n id: \"connection\",\n label: \"Live updates\",\n value: health.liveUpdates.label,\n detail: connectionDetail,\n tone: health.liveUpdates.tone,\n },\n {\n id: \"last-event\",\n label: \"Recent activity\",\n value: health.lastEvent.type ?? health.lastEvent.label,\n detail:\n health.lastEvent.timestamp !== undefined\n ? formatRelativeTimestamp(health.lastEvent.timestamp)\n : \"Waiting for an agent to run.\",\n tone: health.lastEvent.tone,\n eventId: health.lastEvent.id,\n agentId: health.lastEvent.agentId,\n },\n ];\n return html`\n <section\n class=\"inspector-home-section inspector-system-health-section\"\n data-inspector-home-band=\"health\"\n >\n <header\n class=\"inspector-home-section-header inspector-system-health-header\"\n >\n <div class=\"inspector-system-health-heading\">\n <h2 class=\"inspector-home-section-title\">System Health</h2>\n </div>\n <span\n class=\"inspector-system-health-state\"\n data-tone=${health.state === \"healthy\" ? \"success\" : health.state}\n >\n <span aria-hidden=\"true\"></span>\n ${health.label}\n </span>\n </header>\n <dl\n class=\"inspector-system-health\"\n aria-label=\"System Health\"\n data-inspector-home-card=\"runtime\"\n data-health-state=${health.state}\n >\n ${signals.map(\n (signal) => html`\n <div\n class=\"inspector-system-health-signal\"\n data-runtime-health-signal=${signal.id}\n data-tone=${signal.tone}\n >\n <span class=\"inspector-system-health-copy\">\n <dt>${signal.label}</dt>\n <dd title=${signal.value}>\n ${\n signal.eventId\n ? html`\n <button\n type=\"button\"\n class=\"inspector-system-health-event-link\"\n aria-label=\"View ${signal.value.toLowerCase()} in AG-UI Events\"\n @click=${() => {\n if (signal.eventId) {\n this.handleHomeLastEventSelect(\n signal.eventId,\n signal.agentId,\n );\n }\n }}\n >\n <span class=\"inspector-system-health-event-type\"\n >${signal.value}</span\n >\n <small class=\"inspector-system-health-event-meta\">\n <span>${signal.detail}</span>\n <strong>View event</strong>\n </small>\n </button>\n `\n : signal.value\n }\n </dd>\n ${\n signal.eventId\n ? null\n : signal.id === \"runtime\"\n ? html`\n <small\n class=\"inspector-system-health-url\"\n data-full-value=${runtime.url ?? signal.detail}\n aria-label=${signal.detail}\n title=${signal.detail}\n tabindex=\"0\"\n >\n <span>${signal.detail}</span>\n </small>\n `\n : html`<small\n class=\"inspector-system-health-detail\"\n title=${signal.detail}\n >${signal.detail}</small\n >`\n }\n </span>\n </div>\n `,\n )}\n </dl>\n </section>\n `;\n }\n\n private renderEventErrorBanner(key: InspectorEventErrorSource) {\n const error = this.eventErrorDetails[key];\n if (!error) return nothing;\n const guide = EVENT_ERROR_GUIDANCE[key];\n return html`\n <div\n class=\"mx-3 mt-3 flex cursor-pointer items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-3 py-2 text-left text-[11px] text-rose-950\"\n role=\"alert\"\n tabindex=\"0\"\n data-cpk-event-error=${key}\n @click=${this.refocusEventErrorLanding}\n @keydown=${this.handleEventErrorBannerKeydown}\n >\n <span class=\"mt-0.5 shrink-0\">${this.renderIcon(\"TriangleAlert\")}</span>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"font-semibold\">${guide.title}</p>\n ${error.agentId ? html`<p>Agent: ${error.agentId}</p>` : nothing}\n ${error.toolName ? html`<p>Tool: ${error.toolName}</p>` : nothing}\n <p class=\"break-words leading-relaxed\">${error.message}</p>\n ${\n guide.advice\n ? html`<p class=\"leading-relaxed\">${guide.advice}</p>`\n : nothing\n }\n ${\n guide.highlight && this.hasEventErrorHighlight(key)\n ? html`<p class=\"leading-relaxed\">${guide.highlight}</p>`\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private handleEventErrorBannerKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n this.refocusEventErrorLanding(event);\n };\n\n /** Scroll the landing view to the failed tool call or RUN_ERROR again. */\n private refocusEventErrorLanding = (event: Event): void => {\n const key = (event.currentTarget as HTMLElement | null)?.dataset\n .cpkEventError;\n if (!key || !isEventErrorKey(key)) return;\n this.applyEventErrorLanding(key);\n this.requestUpdate();\n };\n\n private handleHomeLastEventSelect(eventId: string, agentId?: string): void {\n this.eventFilterText = \"\";\n this.eventTypeFilter = \"all\";\n this.selectedContext =\n agentId && this.contextOptions.some((option) => option.key === agentId)\n ? agentId\n : \"all-agents\";\n this.expandedRows.clear();\n this.expandedRows.add(eventId);\n this.handleMenuSelect(\"ag-ui-events\");\n\n void this.updateComplete.then(() => {\n const row = Array.from(\n this.activeRoot.querySelectorAll<HTMLElement>(\n \"[data-inspector-event-id]\",\n ),\n ).find((candidate) => candidate.dataset.inspectorEventId === eventId);\n row?.scrollIntoView?.({ block: \"center\" });\n });\n }\n\n private renderHomeFeatures(model: HomeModel) {\n const enabledServices = model.services.filter((service) => service.enabled);\n const disabledServices = model.services.filter(\n (service) => !service.enabled,\n );\n const renderService = (service: HomeModel[\"services\"][number]) => {\n const copyState =\n this.homeFeaturePromptCopyState?.serviceId === service.id\n ? this.homeFeaturePromptCopyState.state\n : \"idle\";\n const stateDescription = `${service.label} is ${\n service.enabled\n ? \"enabled in your runtime\"\n : \"not enabled in your runtime\"\n }`;\n const copyLabel =\n copyState === \"copied\"\n ? \"Copied\"\n : copyState === \"error\"\n ? \"Copy failed\"\n : \"Copy prompt\";\n const copyTitle = copyLabel;\n return html`\n <div\n class=\"inspector-home-feature\"\n data-inspector-service=${service.id}\n data-state=${service.enabled ? \"on\" : \"off\"}\n role=\"listitem\"\n >\n <span\n class=\"inspector-home-feature-status\"\n role=\"img\"\n aria-label=${stateDescription}\n title=${stateDescription}\n >\n <span aria-hidden=\"true\"></span>\n </span>\n <a\n class=\"inspector-home-feature-label\"\n data-inspector-home-feature-docs=${service.id}\n href=${this.appendRefParam(service.docsUrl, \"cpk-inspector-home\")}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Open ${service.label} documentation in a new tab\"\n >\n <span>${service.label}</span>\n <span class=\"inspector-home-feature-label-icon\" aria-hidden=\"true\"\n >${this.renderIcon(\"ArrowUpRight\")}</span\n >\n </a>\n <span class=\"inspector-home-feature-actions\">\n ${\n service.enabled\n ? nothing\n : html`\n <button\n type=\"button\"\n class=\"inspector-home-feature-action inspector-system-health-url\"\n data-inspector-home-feature-prompt=${service.id}\n data-copy-state=${copyState}\n data-full-value=${copyTitle}\n aria-label=\"${copyLabel} for ${service.label}\"\n @click=${(event: Event) =>\n this.handleHomeFeaturePromptCopy(service, event)}\n >\n <span class=\"inspector-home-feature-action-icon\" aria-hidden=\"true\"\n >${this.renderIcon(copyState === \"copied\" ? \"Check\" : \"Bot\")}</span\n >\n <span class=\"inspector-home-feature-action-label\"\n >${copyTitle}</span\n >\n </button>\n `\n }\n ${\n service.enabled\n ? nothing\n : html`\n <span class=\"sr-only\" aria-live=\"polite\">\n ${\n copyState === \"copied\"\n ? `${service.label} implementation prompt copied.`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} implementation prompt.`\n : \"\"\n }\n </span>\n `\n }\n </span>\n </div>\n `;\n };\n return html`\n <section\n class=\"inspector-home-section inspector-home-features\"\n data-inspector-home-card=\"services\"\n >\n <header class=\"inspector-home-section-header\">\n <h2 class=\"inspector-home-section-title\">Features</h2>\n <span>\n ${enabledServices.length} enabled, ${disabledServices.length} available\n </span>\n </header>\n ${\n model.services.length === 0\n ? html`\n <p class=\"inspector-home-features-empty\">\n Feature availability is unavailable for this runtime.\n </p>\n `\n : html`\n <div class=\"inspector-home-feature-groups\">\n <section\n class=\"inspector-home-feature-group\"\n data-feature-state-group=\"active\"\n aria-label=\"Enabled features\"\n >\n <header class=\"inspector-home-feature-group-header\">\n <strong>Enabled</strong>\n <span>${enabledServices.length}</span>\n </header>\n <div class=\"inspector-home-feature-list\" role=\"list\">\n ${\n enabledServices.length > 0\n ? enabledServices.map(renderService)\n : html`\n <p class=\"inspector-home-feature-group-empty\">None enabled</p>\n `\n }\n </div>\n </section>\n <section\n class=\"inspector-home-feature-group\"\n data-feature-state-group=\"available\"\n aria-label=\"Features available to add\"\n >\n <header class=\"inspector-home-feature-group-header\">\n <strong>Available to add</strong>\n <span>${disabledServices.length}</span>\n </header>\n <div class=\"inspector-home-feature-list\" role=\"list\">\n ${\n disabledServices.length > 0\n ? disabledServices.map(renderService)\n : html`\n <p class=\"inspector-home-feature-group-empty\">Everything is active</p>\n `\n }\n </div>\n </section>\n </div>\n `\n }\n </section>\n `;\n }\n\n private showHomeFeaturePromptCopyState(\n serviceId: HomeFeaturePromptId,\n state: Exclude<HomeFeaturePromptCopyState, \"idle\">,\n generation: number,\n ): void {\n if (\n !this.isConnected ||\n generation !== this.homeFeaturePromptCopyGeneration\n )\n return;\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n }\n this.homeFeaturePromptCopyState = { serviceId, state };\n this.requestUpdate();\n this.homeFeaturePromptCopyResetTimeoutId = window.setTimeout(() => {\n if (\n !this.isConnected ||\n generation !== this.homeFeaturePromptCopyGeneration\n )\n return;\n this.homeFeaturePromptCopyState = null;\n this.homeFeaturePromptCopyResetTimeoutId = null;\n this.requestUpdate();\n }, 2_000);\n }\n\n private handleHomeFeaturePromptCopy = async (\n service: HomeFeaturePromptTarget,\n event?: Event,\n ): Promise<void> => {\n const generation = (this.homeFeaturePromptCopyGeneration += 1);\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n this.homeFeaturePromptCopyResetTimeoutId = null;\n }\n this.homeFeaturePromptCopyState = null;\n this.requestUpdate();\n\n const onboardingRunId = createOnboardingRunId();\n if (!this.core?.telemetryDisabled) {\n trackHomeFeaturePromptClicked({\n feature_id: service.id,\n onboarding_run_id: onboardingRunId,\n });\n }\n\n if (\n await this.copyFeaturePromptToClipboard(service, event, onboardingRunId)\n ) {\n this.showHomeFeaturePromptCopyState(service.id, \"copied\", generation);\n } else {\n this.showHomeFeaturePromptCopyState(service.id, \"error\", generation);\n }\n };\n\n private getHomeFeaturePromptTarget(\n serviceId: HomeFeaturePromptId,\n ): HomeFeaturePromptTarget | undefined {\n return this.getHomeModel().services.find(\n (service) => service.id === serviceId,\n );\n }\n\n private renderFeatureSetupPrompt(\n serviceId: HomeFeaturePromptId,\n className: string,\n options?: Readonly<{\n copyState?: HomeFeaturePromptCopyState;\n onClick?: (event: Event) => void;\n }>,\n ): TemplateResult | typeof nothing {\n const service = this.getHomeFeaturePromptTarget(serviceId);\n if (!service) return nothing;\n const copyState =\n options?.copyState ??\n (this.homeFeaturePromptCopyState?.serviceId === service.id\n ? this.homeFeaturePromptCopyState.state\n : \"idle\");\n const label =\n copyState === \"copied\"\n ? \"Copied\"\n : copyState === \"error\"\n ? \"Copy blocked\"\n : \"Copy setup prompt\";\n return html`\n <button\n type=\"button\"\n class=${className}\n data-inspector-feature-setup-prompt=${service.id}\n data-inspector-threads-setup-prompt=${\n service.id === \"threads\" ? \"\" : nothing\n }\n data-copy-state=${copyState}\n aria-label=${\n copyState === \"copied\"\n ? `${service.label} setup prompt copied`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} setup prompt. Try again`\n : `Copy setup prompt for ${service.label}`\n }\n @click=${(event: Event) =>\n options?.onClick\n ? options.onClick(event)\n : this.handleHomeFeaturePromptCopy(service, event)}\n >\n ${this.renderIcon(copyState === \"copied\" ? \"Check\" : \"Copy\")}\n ${label}\n </button>\n <span class=\"sr-only\" aria-live=\"polite\">\n ${\n copyState === \"copied\"\n ? `${service.label} setup prompt copied.`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} setup prompt.`\n : \"\"\n }\n </span>\n `;\n }\n\n private handleHomeHeroCta(action: HomeHeroAction): void {\n if (this.core?.telemetryDisabled) return;\n trackHomeCtaClicked({ action_kind: action.kind });\n }\n\n /**\n * The install row: copy the prompt, or fall back to the signup page.\n *\n * The prompt is primary and the link is secondary, which is the inversion\n * this card exists for. Leaving for a signup page is where developers drop\n * out; pasting into the editor they are already in is not.\n *\n * No third-party coding-agent logos here, unlike the Intelligence app. That\n * app is a private hosted surface; this one is a published npm package\n * embedded in other people's sites, and shipping Anthropic's and OpenAI's\n * marks inside it is a trademark call that is not ours to make quietly. The\n * helper line names the agents in text instead.\n */\n private renderIntelligenceInstallActions(action?: HomeHeroAction) {\n const copied = this.promptCopyState === \"copied\";\n const failed = this.promptCopyState === \"failed\";\n return html`\n <div\n class=\"inspector-intelligence-install\"\n data-copy-state=${this.promptCopyState}\n >\n ${\n // The two actions are two routes to the same outcome — let the coding\n // agent wire it up, or go and do it in the browser — so the\n // secondary names the alternative path rather than promising an\n // explainer. It used to read \"What Intelligence does\", which pointed\n // at intelligence.copilotkit.ai: a product and signup page, not an\n // explanation. Mis-promising a destination is a poor trade right at\n // the moment the card is asking to be trusted.\n //\n // One slot for the secondary message, and its content follows the\n // state: before the press the useful aside is the other route, after\n // it is \"where to put it\". Adding the instruction as a second row\n // instead pushed the action column past the band's 76px and shoved\n // the whole story down at the moment the developer had just acted.\n // Both are single lines, so swapping them cannot change the height.\n //\n // Secondary sits inside the row and the primary at the outer edge:\n // in a right-aligned group the filled button belongs on the outside,\n // not wedged between the heading and a link.\n this.promptCopyState === \"idle\"\n ? action\n ? html`\n <a\n class=\"inspector-intelligence-install-secondary\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Set Intelligence up yourself (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n Set it up yourself ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n : html`\n <p\n class=\"inspector-intelligence-install-hint\"\n data-tone=${failed ? \"error\" : \"success\"}\n role=\"status\"\n >\n ${\n failed\n ? \"Clipboard blocked — copy the prompt below.\"\n : \"Paste it into your coding agent.\"\n }\n </p>\n `\n }\n <button\n type=\"button\"\n class=\"inspector-intelligence-hud-action inspector-intelligence-install-copy\"\n data-inspector-intelligence-copy-prompt\n aria-label=${\n copied\n ? \"Install prompt copied to clipboard. Paste it into your coding agent.\"\n : \"Copy the Intelligence install prompt\"\n }\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleIntelligencePromptCopy}\n >\n ${this.renderIcon(copied ? \"Check\" : \"ClipboardCopy\")}\n ${copied ? \"Prompt copied\" : \"Copy setup prompt\"}\n </button>\n </div>\n `;\n }\n\n /** One run id per element lifetime; minted on first use, never rotated. */\n private getOnboardingRunId(): string {\n this.onboardingRunId ??= createOnboardingRunId();\n return this.onboardingRunId;\n }\n\n private handleIntelligencePromptCopy = async (\n event?: Event,\n ): Promise<void> => {\n // A second press restarts the clock rather than inheriting the first\n // press's countdown.\n this.clearIntelligencePromptReset();\n const runId = this.getOnboardingRunId();\n const clipboard = this.getClipboard(event);\n let outcome: \"copied\" | \"failed\" = \"failed\";\n\n if (clipboard?.writeText) {\n try {\n await clipboard.writeText(createOnboardingPrompt(runId));\n outcome = \"copied\";\n } catch {\n outcome = \"failed\";\n }\n }\n\n if (!this.isConnected) {\n return;\n }\n\n this.promptCopyState = outcome;\n this.requestUpdate();\n\n if (outcome === \"copied\") {\n this.scheduleIntelligencePromptReset();\n }\n\n if (!this.core?.telemetryDisabled) {\n trackHomePromptCopied({ onboarding_run_id: runId, outcome });\n }\n };\n\n /**\n * Return the button and its secondary line to the idle state.\n *\n * Long enough to read six words, short enough that a developer who went to\n * their editor and came back — because the paste went somewhere wrong, or\n * the terminal is gone — finds a button that plainly invites a second press\n * rather than a spent one wearing a checkmark.\n *\n * Only the copied state resets. A failed copy has the prompt on screen for\n * manual selection, and yanking that away mid-drag would be worse than the\n * clipboard failing in the first place.\n */\n private scheduleIntelligencePromptReset(): void {\n this.clearIntelligencePromptReset();\n this.promptCopyResetTimer = setTimeout(() => {\n this.promptCopyResetTimer = null;\n if (!this.isConnected || this.promptCopyState !== \"copied\") {\n return;\n }\n this.promptCopyState = \"idle\";\n this.requestUpdate();\n }, PROMPT_COPY_RESET_MS);\n }\n\n private clearIntelligencePromptReset(): void {\n if (this.promptCopyResetTimer !== null) {\n clearTimeout(this.promptCopyResetTimer);\n this.promptCopyResetTimer = null;\n }\n }\n\n /**\n * The three-beat Intelligence story.\n *\n * Every beat is in the DOM at all times and switched by opacity, so the\n * strip never reflows and screen readers get one stable structure. The\n * caption is the live text; the beats themselves are decorative and hidden\n * from assistive tech, because reading out a mocked code listing helps\n * nobody.\n */\n /**\n * The rotating argument, paired to whatever the picture below is showing.\n *\n * Hidden from assistive tech: a sentence that replaces itself every few\n * seconds is noise in a screen reader, so the stable summary above carries\n * the message there instead. Both sentences are always in the DOM and only\n * their opacity changes, so the block cannot reflow and the card never jumps\n * height mid-loop.\n */\n /**\n * Where a slide sits relative to the one on screen.\n *\n * This is what makes the motion agree with the rail: the rail reads left to\n * right, so a slide that has not been reached yet waits to the right, and one\n * already passed leaves to the left. Deriving it from the indices rather than\n * remembering a direction means clicking backwards through the tabs animates\n * backwards for free, with no state to keep in sync. The loop's wrap from the\n * last tab to the first therefore reads as a rewind, which is what it is.\n */\n private intelligenceSlidePosition(index: number): string {\n if (index === this.intelStoryBeat) return \"active\";\n return index < this.intelStoryBeat ? \"before\" : \"after\";\n }\n\n /** Same rule, addressed by beat id, for the picture halves. */\n private intelligenceBeatPosition(beatId: string): string {\n return this.intelligenceSlidePosition(\n INTELLIGENCE_STORY_BEATS.findIndex((beat) => beat.id === beatId),\n );\n }\n\n private renderIntelligenceStoryCopy() {\n return html`\n <div\n class=\"inspector-intelligence-copy\"\n data-inspector-intelligence-copy\n data-beat=${\n INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? \"threads\"\n }\n aria-hidden=\"true\"\n >\n ${INTELLIGENCE_STORY_BEATS.map(\n (beat, index) => html`\n <div\n class=\"inspector-intelligence-copy-slide\"\n data-beat-id=${beat.id}\n data-active=${index === this.intelStoryBeat}\n data-position=${this.intelligenceSlidePosition(index)}\n >\n <strong>${beat.lead}</strong>\n <span>${beat.support}</span>\n </div>\n `,\n )}\n </div>\n `;\n }\n\n private renderIntelligenceStory() {\n const activeBeat = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];\n return html`\n <section\n class=\"inspector-intelligence-story\"\n data-inspector-intelligence-story\n data-beat=${activeBeat?.id ?? \"threads\"}\n >\n ${this.renderIntelligenceStoryCopy()}\n <div class=\"inspector-intelligence-story-stage\" aria-hidden=\"true\">\n ${this.renderIntelligenceStoryThreads()}\n ${this.renderIntelligenceStoryLearning()}\n ${this.renderIntelligenceStorySkill()}\n ${this.renderIntelligenceStoryReuse()}\n </div>\n <div\n class=\"inspector-intelligence-story-rail\"\n role=\"tablist\"\n aria-label=\"What Intelligence adds\"\n >\n ${INTELLIGENCE_STORY_BEATS.map(\n (beat, index) => html`\n <button\n type=\"button\"\n role=\"tab\"\n class=\"inspector-intelligence-story-tab\"\n aria-selected=${index === this.intelStoryBeat}\n data-active=${index === this.intelStoryBeat}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.pinIntelligenceStoryBeat(index)}\n >\n ${beat.label}\n </button>\n `,\n )}\n </div>\n </section>\n `;\n }\n\n /** Beat 1 — the developer's own users' conversations, one of them broken. */\n private renderIntelligenceStoryThreads() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"threads\"\n data-position=${this.intelligenceBeatPosition(\"threads\")}\n >\n <div class=\"inspector-intelligence-threads\">\n ${INTELLIGENCE_STORY_THREADS.map(\n (thread, index) => html`\n <span\n class=\"inspector-intelligence-thread\"\n data-failed=${thread.failed}\n style=\"--thread-index:${index}\"\n >\n <i></i>\n <strong>${thread.title}</strong>\n <small>${thread.meta}</small>\n </span>\n `,\n )}\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStoryLearning() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"learning\"\n data-position=${this.intelligenceBeatPosition(\"learning\")}\n >\n <div class=\"inspector-intelligence-beat-col\">\n <span class=\"inspector-intelligence-beat-label\">\n Signals from ${INTELLIGENCE_STORY_SIGNALS.length} threads\n </span>\n ${INTELLIGENCE_STORY_SIGNALS.map(\n (signal, index) => html`\n <span\n class=\"inspector-intelligence-signal\"\n style=\"--signal-index:${index}\"\n >${signal}</span\n >\n `,\n )}\n </div>\n <div class=\"inspector-intelligence-beat-flow\">\n ${this.renderIcon(\"ArrowRight\")}\n </div>\n <div class=\"inspector-intelligence-beat-col\">\n <span class=\"inspector-intelligence-beat-label\">\n Reusable pattern\n </span>\n ${INTELLIGENCE_STORY_RULES.map(\n (rule, index) => html`\n <span\n class=\"inspector-intelligence-rule\"\n style=\"--rule-index:${index}\"\n >\n <i>${this.renderIcon(\"Check\")}</i>${rule}\n </span>\n `,\n )}\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStorySkill() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"skill\"\n data-position=${this.intelligenceBeatPosition(\"skill\")}\n >\n <div class=\"inspector-intelligence-skill-file\">\n <header>\n ${this.renderIcon(\"FileText\")}\n <strong>${INTELLIGENCE_STORY_SKILL_FILE}</strong>\n <em>Pending review</em>\n </header>\n <div class=\"inspector-intelligence-skill-code\">\n <span data-line=\"1\"><b># Meeting scheduling</b></span>\n <span data-line=\"2\">When planning a meeting:</span>\n ${INTELLIGENCE_STORY_RULES.map(\n (rule, index) => html`\n <span data-line=${index + 3} style=\"--rule-index:${index}\"\n >${index + 1}. ${rule}</span\n >\n `,\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStoryReuse() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"intelligence\"\n data-position=${this.intelligenceBeatPosition(\"intelligence\")}\n >\n <div class=\"inspector-intelligence-chain\">\n ${INTELLIGENCE_STORY_CHAIN.map(\n (step, index) => html`\n <span\n class=\"inspector-intelligence-chain-step\"\n style=\"--step-index:${index}\"\n >\n <i>${this.renderIcon(step.icon as LucideIconName)}</i>\n <strong>${step.name}</strong>\n <small>${step.detail}</small>\n </span>\n ${\n index === INTELLIGENCE_STORY_CHAIN.length - 1\n ? nothing\n : html`\n <span\n class=\"inspector-intelligence-chain-arrow\"\n style=\"--step-index:${index}\"\n >${this.renderIcon(\"ChevronRight\")}</span\n >\n `\n }\n `,\n )}\n </div>\n <span class=\"inspector-intelligence-chain-proof\">\n ${this.renderIcon(\"Sparkles\")} Next run starts with\n <code>${INTELLIGENCE_STORY_SKILL_FILE}</code>\n </span>\n </div>\n `;\n }\n\n /** A press pins that beat and stops the loop; the developer is now driving. */\n private pinIntelligenceStoryBeat(index: number): void {\n this.intelStoryUserPinned = true;\n this.intelStoryBeat = index;\n this.stopIntelligenceStory();\n this.requestUpdate();\n\n // Reported here and nowhere else: this is the only path a human can take\n // to a beat. The auto-advance in syncIntelligenceStory deliberately stays\n // silent.\n if (!this.core?.telemetryDisabled) {\n const beat = INTELLIGENCE_STORY_BEATS[index];\n if (beat) {\n trackHomeStoryBeatSelected({ beat: beat.id, beat_index: index });\n }\n }\n }\n\n /**\n * Advance the story only while it is actually on screen.\n *\n * Gated on the panel being open, Home being the visible tab, settings being\n * closed and the document being visible. Anything less and a debugging tool\n * would be holding a repeating timer behind a closed panel.\n */\n private syncIntelligenceStory(): void {\n const visible =\n this.isOpen &&\n !this.settingsOpen &&\n this.selectedMenu === \"home\" &&\n !this._core?.intelligence &&\n typeof document !== \"undefined\" &&\n document.visibilityState !== \"hidden\";\n\n if (!visible) {\n // Leaving Home also releases a pinned beat, so coming back later shows a\n // running story rather than a frozen one that reads as broken.\n this.intelStoryUserPinned = false;\n this.stopIntelligenceStory();\n return;\n }\n\n if (this.intelStoryUserPinned || this.prefersReducedMotion()) {\n this.stopIntelligenceStory();\n return;\n }\n\n if (this.intelStoryTimer !== null) {\n return;\n }\n\n const advance = (): void => {\n const current = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];\n this.intelStoryTimer = setTimeout(() => {\n this.intelStoryTimer = null;\n if (!this.isConnected) {\n return;\n }\n this.intelStoryBeat =\n (this.intelStoryBeat + 1) % INTELLIGENCE_STORY_BEATS.length;\n this.requestUpdate();\n advance();\n }, current?.duration ?? 3_800);\n };\n\n advance();\n }\n\n private stopIntelligenceStory(): void {\n if (this.intelStoryTimer !== null) {\n clearTimeout(this.intelStoryTimer);\n this.intelStoryTimer = null;\n }\n }\n\n /**\n * Reduced motion parks the story on the closing beat.\n *\n * That beat is the whole argument in one static frame, so a developer who\n * asked their OS for less motion still gets the point rather than a\n * fragment of it.\n */\n private prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || !window.matchMedia) {\n return false;\n }\n this.intelStoryReducedMotion ??= window.matchMedia(\n \"(prefers-reduced-motion: reduce)\",\n );\n if (this.intelStoryReducedMotion.matches) {\n this.intelStoryBeat = INTELLIGENCE_STORY_BEATS.length - 1;\n return true;\n }\n return false;\n }\n\n private maybeTrackHomeViewed(): void {\n if (this.selectedMenu !== \"home\" || this.settingsOpen || !this.isOpen) {\n return;\n }\n if (!this.homeViewedThisOpen && !this.core?.telemetryDisabled) {\n this.homeViewedThisOpen = true;\n trackHomeViewed();\n }\n }\n\n private renderWindow() {\n const windowState = this.contextState.window;\n const isDocked = this.dockMode !== \"floating\";\n const isPoppedOut = this.isPoppedOut;\n const isTransitioning = this.hasAttribute(\"data-transitioning\");\n const disableDrag = isDocked || isPoppedOut;\n\n const windowStyles = isPoppedOut\n ? {\n position: \"fixed\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n minWidth: \"0\",\n minHeight: \"0\",\n borderRadius: \"0\",\n overflowX: \"hidden\",\n }\n : isDocked\n ? { ...this.getDockedWindowStyles(), overflowX: \"hidden\" }\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 overflowX: \"hidden\",\n };\n\n const hasContextDropdown = this.contextOptions.some(\n (option) => option.key !== \"all-agents\",\n );\n const viewportWidth = isPoppedOut\n ? (this.popOut?.win.innerWidth ?? windowState.size.width)\n : typeof window === \"undefined\"\n ? windowState.size.width\n : window.innerWidth;\n const automaticallyCollapsed = shouldUseIconRail({\n dockedLeft: this.dockMode === \"docked-left\",\n width: viewportWidth,\n });\n const iconRail = this.sidebarCollapsed || automaticallyCollapsed;\n const contextDropdown = hasContextDropdown\n ? this.renderContextDropdown(iconRail)\n : nothing;\n const agentSelector = hasContextDropdown\n ? contextDropdown\n : html`\n <div\n class=\"inspector-agent-placeholder flex items-center gap-2 rounded-md border border-dashed px-2 py-1 text-xs\"\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 data-color-scheme=${this.colorScheme}\n >\n ${\n isDocked && !isPoppedOut\n ? html`\n <div\n class=\"dock-resize-handle pointer-events-auto\"\n data-resize-edge=\"e\"\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 }\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 ${\n disableDrag\n ? \"\"\n : this.isDragging && this.pointerContext === \"window\"\n ? \"cursor-grabbing\"\n : \"cursor-grab\"\n }\"\n data-drag-context=\"window\"\n @pointerdown=${disableDrag ? undefined : this.handlePointerDown}\n @pointermove=${disableDrag ? undefined : this.handlePointerMove}\n @pointerup=${disableDrag ? undefined : this.handlePointerUp}\n @pointercancel=${disableDrag ? undefined : this.handlePointerCancel}\n >\n <div\n class=\"inspector-account-strip flex flex-wrap items-center gap-3 px-3 py-2\"\n data-inspector-account-strip\n style=\"width:100%;min-width:0;color:#010507;\"\n >\n <div class=\"inspector-account-brand flex items-center min-w-0\">\n <img\n src=${inspectorLogoUrl}\n alt=\"CopilotKit\"\n class=\"inspector-account-logo h-6 w-auto\"\n loading=\"lazy\"\n />\n <img\n src=${inspectorLogoUrl}\n alt=\"\"\n aria-hidden=\"true\"\n class=\"inspector-account-logo-accent h-6 w-auto\"\n loading=\"lazy\"\n />\n </div>\n <div class=\"ml-auto flex min-w-0 items-center gap-2\">\n <a\n class=\"inspector-account-cta\"\n data-inspector-thread-cta\n data-motion-paused=${\n this.accountCtaMotionPaused ? \"true\" : \"false\"\n }\n href=${this.getThreadsTalkToEngineerUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Talk to an Engineer (opens in a new tab)\"\n title=\"Talk to an Engineer\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleTalkToEngineerClick}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"MessageCircle\")}</span\n >\n <span class=\"inspector-account-cta-label\"\n >Talk to an Engineer</span\n >\n </a>\n <div class=\"flex items-center gap-1\">\n ${isPoppedOut ? nothing : this.renderWindowLayoutMenu()}\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=${\n this.colorScheme === \"light\"\n ? \"Switch to dark mode\"\n : \"Switch to light mode\"\n }\n aria-pressed=${this.colorScheme === \"dark\"}\n title=${\n this.colorScheme === \"light\" ? \"Dark mode\" : \"Light mode\"\n }\n data-inspector-theme-toggle\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleColorSchemeToggle}\n >\n <span\n class=\"inspector-account-control-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(\n this.colorScheme === \"light\" ? \"Moon\" : \"Sun\",\n )}\n </span>\n </button>\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ${\n this.settingsOpen\n ? \"inspector-account-control-active\"\n : \"\"\n }\"\n type=\"button\"\n aria-label=\"Settings\"\n aria-pressed=${this.settingsOpen}\n title=\"Settings\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleSettingsToggle}\n >\n <span\n class=\"inspector-account-control-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(\"Settings\")}\n </span>\n </button>\n ${\n isPoppedOut\n ? nothing\n : html`\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=\"Close Web Inspector\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerdown=${this.handleClosePointerDown}\n @click=${this.handleCloseClick}\n >\n ${this.renderIcon(\"X\")}\n </button>\n `\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"inspector-shell\">\n ${this.renderInspectorSidebar(\n iconRail,\n automaticallyCollapsed,\n agentSelector,\n )}\n <div class=\"inspector-main\">\n <div id=\"cpk-main-scroll\" class=\"flex-1 overflow-auto\">\n ${this.renderCoreWarningBanner()} ${this.renderMainContent()}\n <slot></slot>\n </div>\n </div>\n </div>\n </div>\n ${\n isPoppedOut\n ? nothing\n : html`\n ${\n isDocked\n ? nothing\n : html`\n <div\n class=\"edge-resize-handle edge-resize-handle-w pointer-events-auto\"\n data-resize-edge=\"w\"\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 <div\n class=\"edge-resize-handle edge-resize-handle-e pointer-events-auto\"\n data-resize-edge=\"e\"\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 <div\n class=\"edge-resize-handle edge-resize-handle-s pointer-events-auto\"\n data-resize-edge=\"s\"\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 }\n <div\n class=\"resize-handle pointer-events-auto absolute bottom-0 right-0 flex h-7 w-7 cursor-nwse-resize items-center justify-center text-gray-600 transition hover:text-gray-900\"\n data-resize-edge=\"se\"\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 `\n }\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 this.hydrateColorSchemePreference(persisted);\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 this.restorePersistedMenu(\n persisted.selectedMenu,\n persisted.hasOpenedInspector === true,\n );\n if (this.isOpen) {\n this.hasOpenedInspector = true;\n }\n if (typeof persisted.sidebarCollapsed === \"boolean\") {\n this.sidebarCollapsed = persisted.sidebarCollapsed;\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 this.hydrateColorSchemePreference(persisted);\n if (!persisted) {\n return;\n }\n\n this.restorePersistedMenu(\n persisted.selectedMenu,\n persisted.hasOpenedInspector === true,\n );\n if (this.isOpen) {\n this.hasOpenedInspector = true;\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 if (typeof persisted.sidebarCollapsed === \"boolean\") {\n this.sidebarCollapsed = persisted.sidebarCollapsed;\n }\n }\n\n /** Follow the OS preference until a person deliberately picks a theme. */\n private hydrateColorSchemePreference(persisted: PersistedState | null): void {\n const preference = persisted?.colorSchemePreference;\n if (preference === \"light\" || preference === \"dark\") {\n this.hasExplicitColorScheme = true;\n this.colorScheme = preference;\n return;\n }\n\n this.hasExplicitColorScheme = false;\n this.colorScheme = this.getSystemColorScheme();\n }\n\n private getSystemColorScheme(): InspectorColorScheme {\n return window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n }\n\n private readonly handleSystemColorSchemeChange = (\n event: MediaQueryListEvent,\n ): void => {\n if (this.hasExplicitColorScheme) {\n return;\n }\n this.colorScheme = event.matches ? \"dark\" : \"light\";\n this.requestUpdate();\n };\n\n private subscribeToSystemColorScheme(): void {\n const mediaQuery = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n if (!mediaQuery || mediaQuery === this.systemColorSchemeMediaQuery) {\n return;\n }\n\n this.unsubscribeFromSystemColorScheme();\n this.systemColorSchemeMediaQuery = mediaQuery;\n mediaQuery.addEventListener?.(\"change\", this.handleSystemColorSchemeChange);\n }\n\n private unsubscribeFromSystemColorScheme(): void {\n this.systemColorSchemeMediaQuery?.removeEventListener?.(\n \"change\",\n this.handleSystemColorSchemeChange,\n );\n this.systemColorSchemeMediaQuery = null;\n }\n\n /** Restore a visible leaf, or open Home for first install and stale state. */\n private restorePersistedMenu(\n value: unknown,\n hasOpenedInspector = this.hasOpenedInspector,\n ): void {\n this.hasOpenedInspector = hasOpenedInspector;\n this.pendingPersistedMenu = null;\n this.briefingRestoreMenu = null;\n\n const storedMenu = isInspectorMenuKey(value) ? value : null;\n const visibleMenu =\n storedMenu && this.menuItems.some((item) => item.key === storedMenu)\n ? storedMenu\n : null;\n\n this.selectedMenu = \"home\";\n this.lastSelectedMenuByGroup.home = \"home\";\n\n if (!hasOpenedInspector) {\n if (visibleMenu && visibleMenu !== \"home\") {\n this.briefingRestoreMenu = visibleMenu;\n this.lastSelectedMenuByGroup[getGroupForMenu(visibleMenu)] =\n visibleMenu;\n } else if (storedMenu && !visibleMenu && !this.hasResolvedCore) {\n this.pendingPersistedMenu = storedMenu;\n }\n return;\n }\n\n if (!storedMenu) {\n return;\n }\n\n if (!visibleMenu) {\n if (!this.hasResolvedCore) {\n this.pendingPersistedMenu = storedMenu;\n }\n return;\n }\n\n this.selectedMenu = visibleMenu;\n this.lastSelectedMenuByGroup[getGroupForMenu(visibleMenu)] = visibleMenu;\n }\n\n /** Resolve a valid stored leaf after the first Core exposes its sources. */\n private resolvePendingPersistedMenu(): void {\n const pendingMenu = this.pendingPersistedMenu;\n if (!pendingMenu) {\n return;\n }\n\n this.pendingPersistedMenu = null;\n this.restorePersistedMenu(pendingMenu, this.hasOpenedInspector);\n this.persistState();\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, a, nav\")) {\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 // Pointer events fire before `click`, so a mouse press opens from here\n // and never reaches handleButtonClick. Both paths must behave the same.\n this.openInspector(\"floating_button\");\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 // Reached by keyboard activation, which fires `click` with no pointer\n // events. A mouse press has already opened from handlePointerUp.\n this.openInspector(\"floating_button\");\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 get isPoppedOut(): boolean {\n return this.popOut !== null && !this.popOut.win.closed;\n }\n\n private get activeRoot(): ParentNode {\n if (this.isPoppedOut) {\n return this.popOut!.win.document;\n }\n return this.renderRoot;\n }\n\n private getPopOutCssTexts(): string[] {\n const fromStatic = WebInspectorElement.styles.map((sheet) =>\n \"cssText\" in sheet ? String(sheet.cssText) : \"\",\n );\n const overlay = `\n html, body { margin: 0; height: 100%; background: #ffffff; }\n .inspector-window {\n position: fixed !important;\n inset: 0 !important;\n width: 100% !important;\n height: 100% !important;\n min-width: 0 !important;\n min-height: 0 !important;\n border-radius: 0 !important;\n }\n `;\n return [...fromStatic.filter(Boolean), overlay];\n }\n\n // Also bound as button.click so a blocked popup throws out of element.click().\n // jsdom swallows errors from click event listeners.\n private getRenderedInspectorWindowSize(): Size {\n const inspectorWindow =\n this.shadowRoot?.querySelector<HTMLElement>(\".inspector-window\");\n if (inspectorWindow) {\n const width = Math.round(Number.parseFloat(inspectorWindow.style.width));\n const height = Math.round(\n Number.parseFloat(inspectorWindow.style.height),\n );\n if (Number.isFinite(width) && Number.isFinite(height)) {\n return { width, height };\n }\n }\n return this.clampWindowSize(this.contextState.window.size);\n }\n\n private requestPopOut = (): void => {\n if (this.isPoppedOut) return;\n this.layoutMenuOpen = false;\n this.requestUpdate();\n const size = this.getRenderedInspectorWindowSize();\n const handle = openPopOutWindow({\n open: window.open.bind(window),\n features: buildPopOutFeatures(size),\n title: \"CopilotKit Inspector\",\n cssTexts: this.getPopOutCssTexts(),\n sourceDocument: document,\n onClose: () => this.handlePopOutClosed(),\n });\n this.popOut = handle;\n try {\n defineWebInspector(handle.win.customElements);\n if (this.dockMode !== \"floating\") {\n this.removeDockStyles();\n }\n handle.win.addEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n this.syncInspectorPortal();\n this.requestUpdate();\n } catch (error) {\n this.popOut = null;\n this.unbindPopOutPointerDown(handle.win);\n handle.close();\n if (this.isConnected && this.isOpen && this.dockMode !== \"floating\") {\n this.applyDockStyles();\n }\n this.requestUpdate();\n throw error;\n }\n };\n\n private unbindPopOutPointerDown(win: Window): void {\n try {\n win.removeEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n } catch {\n // Popup window may already be gone.\n }\n }\n\n private handlePopOutClosed = (): void => {\n const handle = this.popOut;\n if (!handle) return;\n this.popOut = null;\n this.unbindPopOutPointerDown(handle.win);\n this.syncInspectorPortal();\n if (this.isConnected && this.isOpen && this.dockMode !== \"floating\") {\n this.applyDockStyles();\n }\n this.requestUpdate();\n };\n\n private closePopOut(): void {\n const handle = this.popOut;\n if (!handle) return;\n this.handlePopOutClosed();\n handle.close();\n }\n\n private handleAppBeforeUnload = (): void => {\n this.closePopOut();\n };\n\n private syncInspectorPortal(): void {\n if (!this.inspectorPortal) {\n const portal = (this.ownerDocument ?? document).createElement(\"div\");\n portal.dataset.inspectorPortal = \"true\";\n portal.style.display = \"contents\";\n this.inspectorPortal = portal;\n }\n\n if (!this.isOpen) {\n render(nothing, this.inspectorPortal, {\n host: this,\n creationScope: this.ownerDocument ?? document,\n });\n this.inspectorPortal.remove();\n return;\n }\n\n render(this.renderWindow(), this.inspectorPortal, {\n host: this,\n creationScope: this.ownerDocument ?? document,\n });\n\n const target = this.isPoppedOut\n ? this.popOut!.win.document.body\n : this.renderRoot.querySelector<HTMLElement>(\n \"[data-inspector-portal-anchor]\",\n );\n if (target && this.inspectorPortal.parentNode !== target) {\n target.appendChild(this.inspectorPortal);\n }\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 this.resizeInitialPosition = { ...this.contextState.window.position };\n const edge = (event.currentTarget as HTMLElement | null)?.dataset\n .resizeEdge;\n this.resizeEdge =\n edge === \"w\" ||\n edge === \"e\" ||\n edge === \"s\" ||\n edge === \"se\" ||\n edge === \"sw\"\n ? edge\n : \"se\";\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 const edge = this.resizeEdge;\n const growWest = edge === \"w\" || edge === \"sw\";\n const growEast =\n edge === \"e\" || edge === \"se\" || this.dockMode === \"docked-left\";\n const growSouth = edge === \"s\" || edge === \"se\" || edge === \"sw\";\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 const initialSize = this.resizeInitialSize;\n const initialPos = this.resizeInitialPosition ?? { ...state.position };\n let nextWidth = initialSize.width;\n let nextHeight = initialSize.height;\n\n if (growEast) {\n nextWidth = initialSize.width + deltaX;\n } else if (growWest) {\n nextWidth = initialSize.width - deltaX;\n }\n if (growSouth) {\n nextHeight = initialSize.height + deltaY;\n }\n\n state.size = this.clampWindowSize({\n width: nextWidth,\n height: nextHeight,\n });\n\n if (growWest) {\n const right = initialPos.x + initialSize.width;\n state.position = {\n x: right - state.size.width,\n y: initialPos.y,\n };\n }\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 if (this.isPoppedOut) {\n return;\n }\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n\n this.measureContext(\"window\");\n this.contextState.window.size = this.clampWindowSize(\n this.contextState.window.size,\n );\n if (this.hasCustomPosition.window) {\n this.applyAnchorPosition(\"window\");\n } else {\n this.centerContext(\"window\");\n }\n\n this.requestUpdate();\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:\n this.pendingPersistedMenu ??\n (this.briefingRestoreMenu && this.selectedMenu === \"home\"\n ? this.briefingRestoreMenu\n : this.selectedMenu),\n selectedContext: this.selectedContext,\n hasOpenedInspector: this.hasOpenedInspector,\n sidebarCollapsed: this.sidebarCollapsed,\n colorSchemePreference: this.hasExplicitColorScheme\n ? this.colorScheme\n : undefined,\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 = this.clampWindowSize(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 if (this.previousHtmlOverflowX === null) {\n this.previousHtmlOverflowX = document.documentElement.style.overflowX;\n }\n document.documentElement.style.overflowX = \"hidden\";\n }\n\n // Remove transition after animation completes\n if (!this.isResizing && !skipTransition) {\n const id = setTimeout(() => {\n this.bodyTransitionTimeoutIds.delete(id);\n if (typeof document !== \"undefined\" && document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n this.bodyTransitionTimeoutIds.add(id);\n }\n }\n\n private removeDockStyles(skipTransition = false): void {\n if (typeof document === \"undefined\" || !document.body) {\n return;\n }\n\n // Only add transition if not resizing and not skipping\n if (!this.isResizing && !skipTransition) {\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 if (this.previousHtmlOverflowX !== null) {\n document.documentElement.style.overflowX = this.previousHtmlOverflowX;\n this.previousHtmlOverflowX = null;\n }\n\n // Clean up transition after animation completes\n if (!skipTransition) {\n const id = setTimeout(() => {\n this.bodyTransitionTimeoutIds.delete(id);\n if (typeof document !== \"undefined\" && document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n this.bodyTransitionTimeoutIds.add(id);\n } else {\n document.body.style.transition = \"\";\n }\n }\n\n private updateHostTransform(context: ContextKey = this.activeContext): void {\n if (this.isPoppedOut) {\n return;\n }\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.setAttribute(\"data-docked\", \"true\");\n this.style.transform = \"none\";\n } else {\n this.removeAttribute(\"data-docked\");\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 (this.isPoppedOut) {\n return;\n }\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.resizeInitialPosition = null;\n this.resizeEdge = \"se\";\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 public openInspector(\n source: InspectorOpenSource,\n options: InspectorOpenOptions = {},\n ): void {\n if (this.isInspectorDismissed) {\n return;\n }\n if (options.threadId) {\n this.focusThread(options);\n }\n\n if (this.isPoppedOut) {\n return;\n }\n if (this.isOpen) {\n return;\n }\n\n const hadUnseenAnnouncement = this.newsSignalArmed;\n // Captured from the pre-open state, exactly as the unread-announcement\n // property is: after `isOpen` flips there is no launcher, so the question\n // \"was a signal on the launcher when this open happened\" has no answer.\n const activeSignalAtOpen = this.getActiveLauncherSignal();\n const firstOpen = !this.hasOpenedInspector;\n this.hasOpenedInspector = true;\n this.homeViewedThisOpen = false;\n this.closeLauncherHud();\n\n // A press on the launcher is a gesture towards whatever the dot is about,\n // so it lands where that subject is explained. Restoring a persisted-open\n // panel is not a gesture and deliberately does not route through here.\n // A HUD row sets `hudLandingMenu` and wins, so a red dot cannot steal\n // \"Turn on Threads\".\n const hudMenu = this.hudLandingMenu;\n this.hudLandingMenu = null;\n if (hudMenu) {\n // Use the same activation path as sidebar navigation. In particular,\n // Learning must initialize its lazy memory subscription before deciding\n // whether to show the enabled view or the setup gate.\n this.handleMenuSelect(hudMenu);\n } else if (activeSignalAtOpen !== null && source === \"floating_button\") {\n const landing = LAUNCHER_SIGNALS[activeSignalAtOpen].landingTarget;\n this.selectedMenu = landing;\n this.lastSelectedMenuByGroup[getGroupForMenu(landing)] = landing;\n if (landing === \"agents\" || landing === \"ag-ui-events\") {\n if (isEventErrorKey(activeSignalAtOpen)) {\n this.applyEventErrorLanding(activeSignalAtOpen);\n }\n }\n }\n\n this.ensureAnnouncementLoading();\n\n this.isOpen = true;\n if (this.isLearningStatusVisible()) {\n void this.refreshLearningSnapshot({\n preserve: this.learningSnapshot !== null,\n });\n }\n // The launcher is gone, so its gesture is gone with it — and the slot it\n // was holding is free again for whatever beats after the panel closes.\n this.cancelGestureTail();\n this.persistState(); // Save the open state\n\n this.trackOpened(\n source,\n hadUnseenAnnouncement,\n firstOpen,\n activeSignalAtOpen,\n );\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.isPoppedOut) {\n return;\n }\n if (!this.isOpen) {\n return;\n }\n\n this.isOpen = false;\n this.cancelLearningPoll();\n this.cancelLearningRequest();\n this.learningViewedState = null;\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 // Flush point for defer reason 1: there is a launcher again — and only\n // now is it where it belongs. The anchor is applied after the render that\n // would mount the pill, so flushing any earlier makes the pill measure\n // the room around a launcher that has not moved into place yet, and a\n // stale measurement can suppress a pill that had room all along.\n this.flushPendingSignalPulse();\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 renderWindowLayoutMenu() {\n const dockAction =\n this.dockMode === \"floating\"\n ? {\n label: \"Dock to left\",\n icon: \"PanelLeft\" as LucideIconName,\n mode: \"docked-left\" as DockMode,\n }\n : {\n label: \"Float window\",\n icon: \"Maximize2\" as LucideIconName,\n mode: \"floating\" as DockMode,\n };\n\n return html`\n <div\n class=\"inspector-window-layout\"\n data-inspector-window-layout-root=\"true\"\n >\n <button\n class=\"inspector-account-control inspector-window-layout-trigger flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=\"Window layout\"\n aria-haspopup=\"menu\"\n aria-expanded=${this.layoutMenuOpen}\n title=\"Window layout\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleLayoutMenuToggle}\n >\n ${this.renderIcon(\"PanelsTopLeft\")}\n </button>\n ${\n this.layoutMenuOpen\n ? html`\n <div\n class=\"inspector-window-layout-menu\"\n role=\"menu\"\n aria-label=\"Window layout\"\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-label=${dockAction.label}\n @click=${() => this.handleDockClick(dockAction.mode)}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(dockAction.icon)}</span\n >\n <span>${dockAction.label}</span>\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-label=\"Detach Inspector into its own window\"\n data-testid=\"cpk-inspector-pop-out\"\n .click=${this.requestPopOut}\n @click=${this.requestPopOut}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"PictureInPicture2\")}</span\n >\n <span>Open in new window</span>\n </button>\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private handleLayoutMenuToggle = (event: Event): void => {\n event.stopPropagation();\n this.contextMenuOpen = false;\n if (!this.layoutMenuOpen && this.dockMode === \"floating\") {\n this.contextState.window.size = this.getRenderedInspectorWindowSize();\n }\n this.layoutMenuOpen = !this.layoutMenuOpen;\n this.requestUpdate();\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: \"auto\",\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.layoutMenuOpen = false;\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, \"&quot;\")}\"`,\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 const extracted = textFromUnknownContent(content);\n if (extracted) return extracted;\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 toolCallId:\n typeof raw.toolCallId === \"string\" ? raw.toolCallId : undefined,\n activityType:\n typeof raw.activityType === \"string\" ? raw.activityType : undefined,\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 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>&lt;cpk-web-inspector&gt;</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(): CoreStatusSummary {\n if (!this._core) {\n return {\n label: \"Core not attached\",\n state: \"unavailable\",\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 state: \"error\",\n description:\n lastErrorMessage ?? \"CopilotKit runtime reported an error.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connecting) {\n return {\n label: \"Connecting\",\n state: \"connecting\",\n description: \"Waiting for CopilotKit runtime to finish connecting.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connected) {\n return {\n label: \"Connected\",\n state: \"connected\",\n description: \"Live runtime connection established.\",\n };\n }\n\n return {\n label: \"Disconnected\",\n state: \"disconnected\",\n description:\n lastErrorMessage ?? \"Waiting for CopilotKit runtime to connect.\",\n };\n }\n\n private resolvePlaygroundAgentId(preferredAgentId?: string): string | null {\n const agents = this._core?.agents ?? {};\n if (\n preferredAgentId &&\n preferredAgentId !== \"all-agents\" &&\n agents[preferredAgentId]\n ) {\n return preferredAgentId;\n }\n return Object.keys(agents)[0] ?? null;\n }\n\n private teardownPlaygroundAgent(): void {\n this.playgroundAgentUnsubscribe?.();\n this.playgroundAgentUnsubscribe = null;\n if (this.playgroundAgent && this.playgroundIsRunning) {\n this.playgroundAgent.abortRun();\n void this.playgroundAgent.detachActiveRun().catch(() => {});\n }\n this.playgroundAgent = null;\n this.playgroundAgentId = null;\n this.playgroundMessages = [];\n this.playgroundIsRunning = false;\n this.playgroundRunStartedAt = null;\n this.playgroundReasoningDurations.clear();\n }\n\n private syncPlaygroundMessages(): void {\n this.playgroundMessages =\n this.normalizeAgentMessages(this.playgroundAgent?.messages) ?? [];\n this.requestUpdate();\n void this.updateComplete.then(() => {\n const messages = this.activeRoot.querySelector<HTMLElement>(\n \"[data-playground-messages]\",\n );\n if (messages) messages.scrollTop = messages.scrollHeight;\n });\n }\n\n private startPlaygroundSession(\n showEphemeralNotice: boolean,\n seedMessages: Message[] = [],\n seedState: unknown = {},\n preferredAgentId?: string,\n ): void {\n const agentId = this.resolvePlaygroundAgentId(\n preferredAgentId ?? this.selectedContext,\n );\n const sourceAgent = agentId\n ? typeof this._core?.getAgent === \"function\"\n ? this._core.getAgent(agentId)\n : this._core?.agents[agentId]\n : undefined;\n\n this.teardownPlaygroundAgent();\n this.playgroundError = null;\n this.playgroundSourceThreadId = null;\n this.playgroundShowEphemeralNotice =\n showEphemeralNotice && this._core?.runtimeMode !== \"intelligence\";\n\n if (!agentId || !sourceAgent) {\n this.requestUpdate();\n return;\n }\n\n if (this.selectedContext !== agentId) {\n this.selectedContext = agentId;\n }\n\n const playgroundAgent = sourceAgent.clone();\n playgroundAgent.threadId = createPlaygroundThreadId();\n playgroundAgent.setMessages(seedMessages);\n playgroundAgent.setState(seedState);\n const subscriber: AgentSubscriber = {\n onMessagesChanged: () => this.syncPlaygroundMessages(),\n onActivitySnapshotEvent: () => this.syncPlaygroundMessages(),\n onActivityDeltaEvent: () => this.syncPlaygroundMessages(),\n onRunErrorEvent: ({ event }) => {\n this.playgroundError =\n \"message\" in event && typeof event.message === \"string\"\n ? event.message\n : \"The agent run failed.\";\n this.requestUpdate();\n },\n onRunFailed: ({ error }) => {\n this.playgroundError = error.message;\n this.requestUpdate();\n },\n };\n const { unsubscribe } = playgroundAgent.subscribe(subscriber);\n\n this.playgroundAgent = playgroundAgent;\n this.playgroundAgentId = agentId;\n this.playgroundAgentUnsubscribe = unsubscribe;\n this.syncPlaygroundMessages();\n }\n\n private mapThreadMessagesToPlayground(\n messages: ThreadDebuggerMessage[],\n ): Message[] {\n const mapped: Message[] = [];\n for (const message of messages) {\n if (message.role === \"user\") {\n mapped.push({\n id: message.id,\n role: \"user\",\n content: message.content ?? \"\",\n });\n } else if (message.role === \"assistant\") {\n mapped.push({\n id: message.id,\n role: \"assistant\",\n content: message.content ?? \"\",\n ...(message.toolCalls?.length\n ? {\n toolCalls: message.toolCalls.map((toolCall) => ({\n id: toolCall.id,\n type: \"function\" as const,\n function: {\n name: toolCall.name,\n arguments:\n typeof toolCall.args === \"string\"\n ? toolCall.args\n : JSON.stringify(toolCall.args),\n },\n })),\n }\n : {}),\n });\n } else if (message.role === \"tool\" && message.toolCallId) {\n mapped.push({\n id: message.id,\n role: \"tool\",\n content: message.content ?? \"\",\n toolCallId: message.toolCallId,\n });\n }\n }\n return mapped;\n }\n\n private async loadThreadSnapshot(thread: ɵThread): Promise<{\n messages: Message[];\n state: unknown;\n }> {\n const core = this._core;\n if (!core?.runtimeUrl) {\n throw new Error(\"Failed to load thread.\");\n }\n const baseUrl = core.runtimeUrl.replace(/\\/+$/, \"\");\n const encodedThreadId = encodeURIComponent(thread.id);\n const [messagesResponse, stateResponse] = await Promise.all([\n fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, {\n headers: { ...core.headers },\n }),\n fetch(`${baseUrl}/threads/${encodedThreadId}/state`, {\n headers: { ...core.headers },\n }),\n ]);\n if (!messagesResponse.ok) {\n throw new Error(\n `Failed to load thread (HTTP ${messagesResponse.status}).`,\n );\n }\n const messagesBody = (await messagesResponse.json()) as {\n messages?: ThreadDebuggerMessage[];\n };\n const stateBody = stateResponse.ok\n ? ((await stateResponse.json()) as { state?: unknown })\n : { state: {} };\n return {\n messages: this.mapThreadMessagesToPlayground(messagesBody.messages ?? []),\n state: stateBody.state ?? {},\n };\n }\n\n private applyThreadSnapshotToPlayground(\n thread: ɵThread,\n snapshot: { messages: Message[]; state: unknown },\n ): void {\n this.startPlaygroundSession(\n false,\n snapshot.messages,\n snapshot.state,\n thread.agentId,\n );\n this.playgroundSourceThreadId = thread.id;\n }\n\n private handlePlaygroundThreadSourceChange = async (\n event: Event,\n ): Promise<void> => {\n const threadId = (event.currentTarget as HTMLSelectElement).value;\n if (!threadId) {\n this.startPlaygroundSession(false);\n return;\n }\n\n const thread = this._threads.find((candidate) => candidate.id === threadId);\n if (!thread) return;\n\n this.playgroundIsLoadingThread = true;\n this.playgroundError = null;\n this.requestUpdate();\n\n try {\n const snapshot = await this.loadThreadSnapshot(thread);\n this.applyThreadSnapshotToPlayground(thread, snapshot);\n } catch (error) {\n this.playgroundError =\n error instanceof Error ? error.message : \"Failed to load thread.\";\n } finally {\n this.playgroundIsLoadingThread = false;\n this.requestUpdate();\n }\n };\n\n private handleTryFromHere = async (\n threadId: string | null,\n ): Promise<void> => {\n if (!threadId || this.tryFromHereBusy) return;\n const thread =\n this._threads.find((candidate) => candidate.id === threadId) ?? null;\n if (!thread) return;\n\n this.tryFromHereBusy = true;\n this.tryFromHereError = null;\n this.requestUpdate();\n\n const isCurrentTryFromHereRequest = (): boolean =>\n this.selectedThreadId === threadId && this.selectedMenu === \"threads\";\n\n try {\n const snapshot = await this.loadThreadSnapshot(thread);\n // A later thread or pane change owns the UI. Keep the fetch outcome\n // for telemetry, but do not replace Playground or leave Threads.\n if (isCurrentTryFromHereRequest()) {\n this.applyThreadSnapshotToPlayground(thread, snapshot);\n this.handleMenuSelect(\"playground\");\n }\n if (!this.core?.telemetryDisabled) {\n trackThreadsTryFromHereClicked({\n ...this.getThreadsTelemetryProps(),\n outcome: \"success\",\n });\n }\n } catch (error) {\n if (isCurrentTryFromHereRequest()) {\n this.tryFromHereError =\n error instanceof Error ? error.message : \"Failed to load thread.\";\n }\n if (!this.core?.telemetryDisabled) {\n trackThreadsTryFromHereClicked({\n ...this.getThreadsTelemetryProps(),\n outcome: \"failure\",\n });\n }\n } finally {\n this.tryFromHereBusy = false;\n this.requestUpdate();\n }\n };\n\n private runPlaygroundAgent = async (): Promise<void> => {\n const core = this._core;\n const agent = this.playgroundAgent;\n if (!core || !agent || this.playgroundIsRunning) return;\n\n this.playgroundIsRunning = true;\n this.playgroundRunStartedAt = Date.now();\n this.playgroundError = null;\n this.requestUpdate();\n try {\n await core.runAgent({ agent });\n } catch (error) {\n this.playgroundError =\n error instanceof Error ? error.message : \"The agent run failed.\";\n } finally {\n this.playgroundIsRunning = false;\n this.syncPlaygroundMessages();\n let reasoningMessage: InspectorMessage | undefined;\n for (\n let index = this.playgroundMessages.length - 1;\n index >= 0;\n index -= 1\n ) {\n const message = this.playgroundMessages[index];\n if (message?.role === \"reasoning\") {\n reasoningMessage = message;\n break;\n }\n }\n if (reasoningMessage?.id && this.playgroundRunStartedAt !== null) {\n this.playgroundReasoningDurations.set(\n reasoningMessage.id,\n Date.now() - this.playgroundRunStartedAt,\n );\n }\n this.playgroundRunStartedAt = null;\n this.requestUpdate();\n }\n };\n\n private sendPlaygroundMessage(content: string): void {\n if (\n !content ||\n this.playgroundIsRunning ||\n this.playgroundIsLoadingThread\n ) {\n return;\n }\n\n const selectedAgentId = this.resolvePlaygroundAgentId(this.selectedContext);\n if (!this.playgroundAgent || this.playgroundAgentId !== selectedAgentId) {\n this.startPlaygroundSession(false, [], {}, selectedAgentId ?? undefined);\n }\n if (!this.playgroundAgent) return;\n\n this.playgroundAgent.addMessage({\n id: createPlaygroundThreadId(),\n role: \"user\",\n content,\n });\n this.playgroundInput = \"\";\n this.syncPlaygroundMessages();\n void this.runPlaygroundAgent();\n }\n\n private handlePlaygroundSubmit = (event: SubmitEvent): void => {\n event.preventDefault();\n this.sendPlaygroundMessage(this.playgroundInput.trim());\n };\n\n private handlePlaygroundSuggestion = (message: string): void => {\n this.sendPlaygroundMessage(message.trim());\n };\n\n private handlePlaygroundInput = (event: Event): void => {\n const input = event.currentTarget as HTMLTextAreaElement;\n this.playgroundInput = input.value;\n input.style.height = \"auto\";\n input.style.height = `${Math.min(input.scrollHeight, 128)}px`;\n this.requestUpdate();\n };\n\n private handlePlaygroundKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Enter\" || event.shiftKey) return;\n event.preventDefault();\n (event.currentTarget as HTMLTextAreaElement).form?.requestSubmit();\n };\n\n private handlePlaygroundRetry = (): void => {\n const agent = this.playgroundAgent;\n if (!agent || this.playgroundIsRunning) return;\n let lastUserIndex = -1;\n for (let index = agent.messages.length - 1; index >= 0; index -= 1) {\n if (agent.messages[index]?.role === \"user\") {\n lastUserIndex = index;\n break;\n }\n }\n if (lastUserIndex < 0) return;\n agent.setMessages(agent.messages.slice(0, lastUserIndex + 1));\n this.syncPlaygroundMessages();\n void this.runPlaygroundAgent();\n };\n\n private handlePlaygroundStop = (): void => {\n this.playgroundAgent?.abortRun();\n };\n\n private renderPlaygroundComposer(\n agentId: string | null,\n busy: boolean,\n hasRetry: boolean,\n centered = false,\n ) {\n const placeholder = !agentId\n ? \"Waiting for an agent...\"\n : this.playgroundIsLoadingThread\n ? \"Loading thread...\"\n : \"Type a message...\";\n const sendDisabled =\n !agentId ||\n this.playgroundIsLoadingThread ||\n (!this.playgroundIsRunning && !this.playgroundInput.trim());\n\n return html`\n <form\n class=${\n centered\n ? \"cpk-playground-form mt-5 w-full\"\n : \"cpk-playground-form bg-white px-3 pb-3 pt-1.5\"\n }\n @submit=${this.handlePlaygroundSubmit}\n >\n ${\n this.playgroundError\n ? html`<div\n class=\"mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-950\"\n role=\"alert\"\n data-playground-error\n >\n <span class=\"mt-0.5 shrink-0\"\n >${this.renderIcon(\"TriangleAlert\")}</span\n >\n <div class=\"min-w-0 flex-1\">\n <p class=\"font-semibold\">Agent run failed</p>\n <p class=\"mt-0.5 break-words leading-relaxed\">\n ${this.playgroundError}\n </p>\n </div>\n ${\n hasRetry\n ? html`\n <button\n type=\"button\"\n class=\"shrink-0 rounded-md border border-rose-200 bg-white px-2 py-1 font-medium text-rose-700 transition hover:bg-rose-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-300 focus-visible:ring-offset-1 disabled:opacity-50\"\n ?disabled=${busy}\n @click=${this.handlePlaygroundRetry}\n >\n Retry\n </button>\n `\n : nothing\n }\n </div>`\n : nothing\n }\n <div\n class=\"cpk-playground-composer mx-auto flex max-w-3xl items-end gap-1.5 rounded-[28px] bg-white px-2.5 py-1.5 shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] transition-shadow duration-200 focus-within:shadow-[0_6px_18px_0_#00000014,0_0_1px_0_#0000009e]\"\n >\n <textarea\n class=\"cpk-playground-input min-h-[40px] max-h-32 flex-1 resize-none bg-transparent px-2.5 py-2.5 text-[13px] leading-5 text-gray-900 outline-none placeholder:text-gray-500 disabled:cursor-not-allowed disabled:opacity-60\"\n rows=\"1\"\n placeholder=${placeholder}\n aria-label=\"Playground message\"\n .value=${this.playgroundInput}\n ?disabled=${!agentId || busy}\n @input=${this.handlePlaygroundInput}\n @keydown=${this.handlePlaygroundKeyDown}\n ></textarea>\n <button\n type=${this.playgroundIsRunning ? \"button\" : \"submit\"}\n class=${`cpk-playground-send mb-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 [&>svg]:h-[18px] [&>svg]:w-[18px] ${\n sendDisabled\n ? \"cursor-not-allowed bg-[#00000014] text-[rgb(13,13,13)] opacity-50\"\n : \"cursor-pointer bg-black text-white hover:opacity-70 active:opacity-60\"\n }`}\n aria-label=${\n this.playgroundIsRunning\n ? \"Stop agent\"\n : \"Send playground message\"\n }\n ?disabled=${sendDisabled}\n @click=${\n this.playgroundIsRunning ? this.handlePlaygroundStop : nothing\n }\n >\n ${this.renderIcon(this.playgroundIsRunning ? \"Square\" : \"ArrowUp\")}\n </button>\n </div>\n <p\n class=\"mx-auto max-w-3xl px-3 py-2 text-center text-[10px] leading-4 text-gray-500\"\n >\n AI can make mistakes. Please verify important information.\n </p>\n </form>\n `;\n }\n\n private renderMainContent() {\n if (this.settingsOpen) {\n return this.renderSettingsPanel();\n }\n\n if (this.selectedMenu === \"home\") {\n return this.renderHomeView();\n }\n\n if (this.selectedMenu === WHATS_NEW_MENU_KEY) {\n return this.renderWhatsNewView();\n }\n\n if (this.selectedMenu === \"ag-ui-events\") {\n return html`\n <div class=\"flex h-full min-h-0 flex-col\">\n ${this.renderEventErrorBanner(\"run\")}\n <div class=\"min-h-0 flex-1 overflow-hidden\">\n ${this.renderEventsTable()}\n </div>\n </div>\n `;\n }\n\n if (this.selectedMenu === \"playground\") {\n return this.renderPlaygroundView();\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 === \"capabilities\") {\n return this.renderCapabilitiesView();\n }\n\n if (this.selectedMenu === \"agent-context\") {\n return this.renderContextView();\n }\n\n if (this.selectedMenu === \"threads\") {\n return this.renderThreadsView();\n }\n\n if (this.selectedMenu === \"memories\") {\n return this.renderMemoriesView();\n }\n\n return nothing;\n }\n\n private renderPlaygroundView() {\n const agentId = this.resolvePlaygroundAgentId(this.selectedContext);\n const sourceThreads = this._threads.filter(\n (thread) => !agentId || thread.agentId === agentId,\n );\n const visibleMessages = this.playgroundMessages.filter(\n (message) =>\n message.role === \"user\" ||\n message.role === \"assistant\" ||\n message.role === \"reasoning\" ||\n message.role === \"activity\",\n );\n const hasRetry =\n this.playgroundAgent?.messages.some(\n (message) => message.role === \"user\",\n ) ?? false;\n const runtimeMode = this._core?.runtimeMode ?? \"sse\";\n const runtimeLabel = this._core?.runtimeUrl ?? \"Self-managed agent\";\n const busy = this.playgroundIsRunning || this.playgroundIsLoadingThread;\n const suggestions =\n agentId && this._core\n ? this._core.getSuggestions(agentId).suggestions\n : [];\n const lastAssistantIndex = visibleMessages.reduce(\n (last, message, index) => (message.role === \"assistant\" ? index : last),\n -1,\n );\n const lastReasoningIndex = visibleMessages.reduce(\n (last, message, index) => (message.role === \"reasoning\" ? index : last),\n -1,\n );\n const showWelcome =\n !this.playgroundIsLoadingThread && visibleMessages.length === 0;\n\n return html`\n <div\n class=\"cpk-playground-root flex h-full min-h-[420px] flex-col bg-white\"\n >\n <header\n class=\"cpk-playground-header flex flex-wrap items-center gap-2 border-b border-gray-200 bg-white px-3 py-2\"\n >\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex items-center gap-1.5\">\n <h2 class=\"text-xs font-semibold text-gray-900\">Playground</h2>\n <span\n class=\"rounded-full border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[9px] font-medium text-gray-600\"\n >${runtimeMode.toUpperCase()}</span\n >\n </div>\n <div\n class=\"mt-0.5 flex min-w-0 items-center gap-1.5 text-[9px] text-gray-600\"\n >\n <span class=\"truncate\">Agent: ${agentId ?? \"waiting...\"}</span>\n <span\n class=\"h-3 w-px shrink-0 bg-gray-200\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"truncate\" title=${runtimeLabel}\n >${runtimeLabel}</span\n >\n </div>\n </div>\n <div\n class=\"cpk-playground-actions ml-auto flex min-w-0 items-center gap-2\"\n >\n ${\n sourceThreads.length > 0\n ? html`\n <label class=\"sr-only\" for=\"cpk-playground-thread-source\"\n >Start from a thread</label\n >\n <select\n id=\"cpk-playground-thread-source\"\n class=\"cpk-playground-thread-select max-w-[200px] rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] text-gray-700 outline-none transition hover:border-gray-300 focus:border-violet-400 focus:ring-2 focus:ring-violet-100 disabled:cursor-not-allowed disabled:opacity-50\"\n .value=${this.playgroundSourceThreadId ?? \"\"}\n ?disabled=${busy}\n @change=${this.handlePlaygroundThreadSourceChange}\n >\n <option\n value=\"\"\n ?selected=${!this.playgroundSourceThreadId}\n >\n Load a thread...\n </option>\n ${sourceThreads.map(\n (thread) => html`\n <option\n value=${thread.id}\n ?selected=${\n this.playgroundSourceThreadId === thread.id\n }\n >\n ${\n thread.name?.trim() ||\n `Thread ${thread.id.slice(0, 8)}`\n }\n </option>\n `,\n )}\n </select>\n `\n : nothing\n }\n <button\n type=\"button\"\n class=\"inline-flex shrink-0 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:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n ?disabled=${busy || !agentId}\n @click=${() => this.startPlaygroundSession(true)}\n >\n ${this.renderIcon(\"Plus\")} <span>New thread</span>\n </button>\n </div>\n </header>\n\n ${\n this.playgroundShowEphemeralNotice && runtimeMode !== \"intelligence\"\n ? html`\n <div\n role=\"alert\"\n class=\"mx-3 mt-2 flex items-start gap-2 rounded-lg border border-violet-200 bg-violet-50 px-2.5 py-2 text-[10px] text-violet-950\"\n data-playground-ephemeral-notice\n >\n <span class=\"mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n >${this.renderIcon(\"Clock3\")}</span\n >\n <p class=\"min-w-0 flex-1 leading-relaxed\">\n Scratch threads are ephemeral and will be deleted when your\n local session ends. Need durable history?\n <a\n class=\"font-semibold underline decoration-violet-300 underline-offset-2 hover:decoration-violet-700 focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1\"\n href=${this.getThreadsIntelligenceSignupUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >Set up Intelligence</a\n >.\n </p>\n <button\n type=\"button\"\n class=\"rounded p-0.5 text-violet-500 transition hover:bg-violet-100 hover:text-violet-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1\"\n aria-label=\"Dismiss ephemeral thread notice\"\n @click=${() => {\n this.playgroundShowEphemeralNotice = false;\n this.requestUpdate();\n }}\n >\n ${this.renderIcon(\"X\")}\n </button>\n </div>\n `\n : nothing\n }\n\n <div\n class=\"min-h-0 flex-1 overflow-y-auto px-3 py-3\"\n data-playground-messages\n >\n ${\n this.playgroundIsLoadingThread\n ? html`\n <div\n class=\"flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600\"\n >\n <span\n class=\"text-gray-500 [&>svg]:animate-spin\"\n aria-hidden=\"true\"\n >${this.renderIcon(\"LoaderCircle\")}</span\n >\n Loading thread into a scratch session...\n </div>\n `\n : visibleMessages.length === 0\n ? html`\n <div\n class=\"cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center\"\n >\n <p class=\"cpk-playground-welcome-title\">\n How can I help you today?\n </p>\n ${this.renderPlaygroundComposer(\n agentId,\n busy,\n hasRetry,\n true,\n )}\n </div>\n `\n : html`\n <div class=\"mx-auto flex max-w-3xl flex-col pb-5\">\n ${visibleMessages.map((message, index) => {\n const isUser = message.role === \"user\";\n const isReasoning = message.role === \"reasoning\";\n const isActivity = message.role === \"activity\";\n const content = isActivity\n ? (message.activityType ?? \"Agent activity\")\n : message.contentText;\n if (\n !isReasoning &&\n !content &&\n message.toolCalls.length === 0\n ) {\n return nothing;\n }\n if (isReasoning) {\n const isStreaming =\n this.playgroundIsRunning &&\n index === lastReasoningIndex;\n const duration = message.id\n ? this.playgroundReasoningDurations.get(message.id)\n : undefined;\n const durationLabel =\n duration === undefined || duration < 1000\n ? \"a few seconds\"\n : `${Math.round(duration / 1000)} seconds`;\n const label = isStreaming\n ? \"Thinking…\"\n : `Thought for ${durationLabel}`;\n\n if (isStreaming) {\n return html`\n <section\n class=\"cpk-playground-message-enter my-1 text-[11px] text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n <div\n class=\"inline-flex items-center gap-1 py-1 font-medium\"\n >\n <span>${label}</span>\n ${\n content\n ? nothing\n : html`\n <span\n class=\"cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500\"\n aria-hidden=\"true\"\n ></span>\n `\n }\n </div>\n ${\n content\n ? html`<div\n class=\"pb-2 pt-1 leading-5 text-gray-500\"\n >\n ${content}\n </div>`\n : nothing\n }\n </section>\n `;\n }\n\n return content\n ? html`\n <details\n class=\"cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n <summary\n class=\"inline-flex cursor-pointer list-none items-center gap-1 py-1 font-medium transition-colors hover:text-gray-900 focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1\"\n >\n <span>${label}</span>\n <span\n class=\"cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3\"\n >${this.renderIcon(\"ChevronRight\")}</span\n >\n </summary>\n <div class=\"pb-2 pt-1 leading-5 text-gray-500\">\n ${content}\n </div>\n </details>\n `\n : html`\n <div\n class=\"cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n ${label}\n </div>\n `;\n }\n const isMultiline =\n content.includes(\"\\n\") || content.length > 72;\n const copyKey = `playground-message-${\n message.id ?? index\n }`;\n const showToolbar =\n !isUser &&\n !isActivity &&\n Boolean(content) &&\n !(\n this.playgroundIsRunning &&\n index === lastAssistantIndex\n );\n return html`\n <article\n class=${\n isActivity\n ? \"cpk-playground-message-enter mr-auto mt-3 flex max-w-full items-center gap-1.5 rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-1.5 text-[10px] text-gray-600\"\n : isUser\n ? \"cpk-playground-message-enter flex w-full flex-col items-end pt-8\"\n : \"cpk-playground-message-enter w-full\"\n }\n data-playground-message-role=${message.role}\n >\n ${\n isActivity\n ? html`\n <span class=\"text-gray-500\"\n >${this.renderIcon(\"Activity\")}</span\n >\n <span class=\"font-medium text-gray-700\"\n >Activity</span\n >\n <span class=\"truncate\">${content}</span>\n `\n : isUser\n ? html`\n <div\n class=${`max-w-[80%] whitespace-pre-wrap break-words rounded-[16px] bg-gray-100 px-3 text-[13px] leading-5 text-gray-900 ${\n isMultiline ? \"py-2.5\" : \"py-1\"\n }`}\n >\n ${content}\n </div>\n `\n : html`\n <div\n class=\"whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800\"\n >\n ${content}\n </div>\n `\n }\n ${\n !isUser && message.toolCalls.length > 0\n ? this.renderToolCallDetails(message.toolCalls)\n : nothing\n }\n ${\n showToolbar\n ? html`\n <div\n class=\"-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent\"\n data-playground-assistant-toolbar\n >\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n title=\"Copy message\"\n aria-label=\"Copy message\"\n @click=${(event: Event) =>\n this.copyToClipboard(\n content,\n copyKey,\n event,\n )}\n >\n ${\n this.copiedEvents.has(copyKey)\n ? this.renderIcon(\"Check\")\n : this.renderIcon(\"Copy\")\n }\n </button>\n ${\n index === lastAssistantIndex &&\n hasRetry &&\n !busy &&\n !this.playgroundError\n ? html`\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n title=\"Retry last prompt\"\n aria-label=\"Retry last prompt\"\n @click=${this.handlePlaygroundRetry}\n >\n ${this.renderIcon(\"RotateCcw\")}\n </button>\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n </article>\n `;\n })}\n ${\n this.playgroundIsRunning && lastReasoningIndex < 0\n ? html`\n <div\n class=\"cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1\"\n aria-label=\"Agent is working\"\n >\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n </div>\n `\n : nothing\n }\n ${\n !busy && lastAssistantIndex >= 0 && suggestions.length > 0\n ? html`\n <div\n class=\"mt-3 flex flex-wrap items-center gap-1.5\"\n data-playground-suggestions\n >\n ${suggestions.map(\n (suggestion) => html`\n <button\n type=\"button\"\n class=\"inline-flex h-7 items-center gap-1 rounded-full border border-gray-200 bg-white px-2.5 text-[10px] font-medium leading-none text-gray-900 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:text-gray-500\"\n ?disabled=${suggestion.isLoading}\n aria-busy=${\n suggestion.isLoading ? \"true\" : \"false\"\n }\n @click=${() =>\n this.handlePlaygroundSuggestion(\n suggestion.message,\n )}\n >\n ${\n suggestion.isLoading\n ? html`<span\n class=\"[&>svg]:animate-spin\"\n aria-hidden=\"true\"\n >${this.renderIcon(\n \"LoaderCircle\",\n )}</span\n >`\n : nothing\n }\n <span>${suggestion.title}</span>\n </button>\n `,\n )}\n </div>\n `\n : nothing\n }\n </div>\n `\n }\n </div>\n\n ${\n showWelcome\n ? nothing\n : this.renderPlaygroundComposer(agentId, busy, hasRetry)\n }\n </div>\n `;\n }\n\n private renderSettingsPanel() {\n const optedOut = this.core?.telemetryDisabled ?? false;\n const privateContent = [\n \"Message content\",\n \"Agent state\",\n \"Prompts\",\n \"Completions\",\n ];\n return html`\n <div\n class=\"inspector-settings\"\n data-inspector-settings\n data-state=${optedOut ? \"disabled\" : \"enabled\"}\n >\n <header class=\"inspector-settings-header\">\n <h1 class=\"inspector-settings-title\">Settings</h1>\n <p class=\"inspector-settings-subtitle\">\n Understand how the Inspector handles analytics and private content.\n </p>\n </header>\n\n <section\n class=\"inspector-settings-section\"\n aria-labelledby=\"inspector-settings-privacy-title\"\n >\n <div class=\"inspector-settings-section-heading\">\n <span class=\"inspector-settings-section-icon\" aria-hidden=\"true\">\n ${this.renderIcon(optedOut ? \"ShieldOff\" : \"ShieldCheck\")}\n </span>\n <div>\n <h2 id=\"inspector-settings-privacy-title\">Privacy</h2>\n <p>Analytics without access to your agent content.</p>\n </div>\n </div>\n\n <div\n class=\"inspector-settings-privacy\"\n data-state=${optedOut ? \"disabled\" : \"enabled\"}\n >\n <div class=\"inspector-settings-status-row\">\n <div>\n <h3>Anonymous usage analytics</h3>\n <p>\n ${\n optedOut\n ? \"Anonymous Inspector interaction data collection is disabled for this runtime.\"\n : \"CopilotKit collects anonymous Inspector interactions to understand which features people use.\"\n }\n </p>\n </div>\n <span class=\"inspector-settings-status\">\n ${optedOut ? \"Analytics off\" : \"Analytics on\"}\n </span>\n </div>\n\n <div class=\"inspector-settings-private-content\">\n <strong>Content stays private</strong>\n <p>CopilotKit never collects:</p>\n <ul aria-label=\"Content CopilotKit never collects\">\n ${privateContent.map(\n (item) => html`\n <li>\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"Check\")}</span\n >\n ${item}\n </li>\n `,\n )}\n </ul>\n </div>\n\n <a\n class=\"inspector-settings-policy-link\"\n href=${TELEMETRY_DOCS_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Read the telemetry policy\n <span aria-hidden=\"true\">${this.renderIcon(\"ArrowUpRight\")}</span>\n </a>\n </div>\n </section>\n\n <section\n class=\"inspector-settings-section\"\n aria-labelledby=\"inspector-settings-visibility-title\"\n >\n <div class=\"inspector-settings-section-heading\">\n <span class=\"inspector-settings-section-icon\" aria-hidden=\"true\">\n ${this.renderIcon(\"EyeOff\")}\n </span>\n <div>\n <h2 id=\"inspector-settings-visibility-title\">Visibility</h2>\n <p>Temporarily hide the Inspector on this domain.</p>\n </div>\n </div>\n\n <div class=\"inspector-settings-visibility\">\n <div>\n <h3>Take a break from the Inspector</h3>\n <p>\n Hide the Inspector for seven days. It will return automatically\n when the week is over.\n </p>\n </div>\n <button\n type=\"button\"\n class=\"inspector-settings-dismiss\"\n data-cpk-dismiss-inspector=\"week\"\n @click=${() => this.dismissInspectorFor(\"week\")}\n >\n <span aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n Hide Inspector for one week\n </button>\n </div>\n </section>\n </div>\n `;\n }\n\n // Fires `oss.inspector.opened` for a user-initiated open (OSS-566).\n // Restoring a persisted-open panel on mount assigns `isOpen` directly\n // instead of routing through `openInspector`, so page reloads and dev-server\n // hot reloads are not counted as opens.\n private trackOpened(\n source: InspectorOpenSource,\n hadUnseenAnnouncement: boolean,\n firstOpen = false,\n activeSignal: LauncherSignalKey | null = null,\n ): void {\n if (this.core?.telemetryDisabled) return;\n // Two properties rather than one, so an open can be attributed to a red\n // signal *and* to which failure class raised it. The failure message is\n // never included — `error_signal_source` is a closed two-value enum.\n const errorSignal =\n activeSignal !== null && isErrorSignalKey(activeSignal)\n ? activeSignal\n : null;\n // `license_status` and `runtime_mode` come from /info. Before the handshake\n // `licenseStatus` is undefined and `runtimeMode` reads its `sse` default, so\n // recording them would permanently attribute an early open against an\n // Intelligence runtime to SSE. Omitted rather than guessed — an absent\n // dimension is honest, a wrong one is not. `runtime_url_type` is derived\n // from configuration, so it is accurate immediately.\n const handshakeComplete = this.runtimeStatus === \"connected\";\n trackInspectorOpened({\n open_source: source,\n ...(handshakeComplete\n ? {\n license_status: this.core?.licenseStatus ?? undefined,\n runtime_mode: this.core?.runtimeMode ?? undefined,\n }\n : {}),\n runtime_url_type: getRuntimeUrlType(this.core?.runtimeUrl),\n has_unseen_announcement: hadUnseenAnnouncement,\n has_error_signal: errorSignal !== null,\n ...(errorSignal === null ? {} : { error_signal_source: errorSignal }),\n first_open: firstOpen,\n });\n }\n\n private getVisibleInspectorMetadataAction():\n | Readonly<{\n action: InspectorMetadataAction;\n placement: \"threads-footer\" | \"locked\";\n }>\n | undefined {\n const { threadsFooterAction } = this.inspectorMetadataProjection;\n if (\n threadsFooterAction &&\n !this.settingsOpen &&\n this.selectedMenu === \"threads\" &&\n this.areThreadEndpointsAvailable()\n ) {\n return { action: threadsFooterAction, placement: \"threads-footer\" };\n }\n return undefined;\n }\n\n /** Return paired stable navigation keys, or neither for an invalid leaf. */\n private getMetadataTelemetryNavigation(): Readonly<{\n group_key?: InspectorGroupKey;\n leaf_key?: MenuKey;\n }> {\n const selectedLeaf: unknown = this.selectedMenu;\n if (!isInspectorMenuKey(selectedLeaf)) return {};\n return {\n group_key: getGroupForMenu(selectedLeaf),\n leaf_key: selectedLeaf,\n };\n }\n\n /** Build metadata's shared coarse buckets and stable navigation context. */\n private getMetadataTelemetryContext(): Readonly<{\n usage_bucket: ThreadsUsageBucket;\n expiry_bucket: ThreadsExpiryBucket;\n group_key?: InspectorGroupKey;\n leaf_key?: MenuKey;\n }> {\n return {\n usage_bucket: this.getThreadsUsageBucket(),\n expiry_bucket: this.getThreadsExpiryBucket(),\n ...this.getMetadataTelemetryNavigation(),\n };\n }\n\n private trackMetadataModuleIfChanged(\n props: InspectorMetadataModuleViewedTelemetryProps,\n fingerprint: string,\n ): void {\n if (this.metadataTelemetryFingerprints.get(props.module) === fingerprint) {\n return;\n }\n this.metadataTelemetryFingerprints.set(props.module, fingerprint);\n try {\n trackMetadataModuleViewed(props);\n } catch {\n // Telemetry is best-effort and must never break Inspector rendering.\n }\n }\n\n private maybeTrackInspectorMetadataViews(): void {\n if (\n !this.isOpen ||\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n\n const { identity, plan } = this.inspectorMetadataProjection;\n const license_bucket: InspectorMetadataLicenseBucket =\n this.inspectorMetadataProjection.licenseState;\n const telemetryContext = this.getMetadataTelemetryContext();\n const contextFingerprint = [\n telemetryContext.usage_bucket,\n telemetryContext.expiry_bucket,\n telemetryContext.group_key ?? null,\n telemetryContext.leaf_key ?? null,\n ];\n\n if (identity) {\n this.trackMetadataModuleIfChanged(\n { module: \"identity\", license_bucket, ...telemetryContext },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n identity.organizationName,\n identity.projectName,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"identity\");\n }\n\n if (plan) {\n this.trackMetadataModuleIfChanged(\n { module: \"plan\", license_bucket, ...telemetryContext },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n plan.code,\n plan.label,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"plan\");\n }\n\n const visibleAction = this.getVisibleInspectorMetadataAction();\n if (visibleAction) {\n const { action, placement } = visibleAction;\n const action_placement = getMetadataActionPlacement(placement);\n this.trackMetadataModuleIfChanged(\n {\n module: \"action\",\n action_kind: action.kind,\n license_bucket,\n ...telemetryContext,\n action_placement,\n },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n action_placement,\n action.kind,\n action.url,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"action\");\n }\n }\n\n private handleInspectorMetadataActionClick = (\n action: InspectorMetadataAction,\n placement: \"threads-footer\" | \"locked\",\n ): void => {\n if (\n !this.isOpen ||\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n if (action.kind === \"enable_intelligence\") {\n this.handleThreadsIntelligenceSignupClick();\n return;\n }\n try {\n trackMetadataActionClicked({\n action_kind: action.kind,\n license_bucket: this.inspectorMetadataProjection.licenseState,\n ...this.getMetadataTelemetryContext(),\n action_placement: getMetadataActionPlacement(placement),\n });\n } catch {\n // Telemetry is best-effort and must never break action navigation.\n }\n };\n\n // Fires `whats_new_clicked` at most once per `${bannerId}:${cta}` per mount\n // so copy-button retries and accidental multi-clicks don't inflate funnel\n // counts. `body` is the only cta left now that dismissal is gone.\n private trackWhatsNewClickedOnce(opts: { cta: \"body\" }): void {\n if (\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n const id = this.announcementTimestamp;\n if (!id) return;\n const key = `${id}:${opts.cta}`;\n if (this.clickedBannerIds.has(key)) return;\n this.clickedBannerIds.add(key);\n trackWhatsNewClicked({\n banner_id: id,\n cta: opts.cta,\n cta_label: this.announcementCtaLabel ?? undefined,\n });\n }\n\n private handleTalkToEngineerClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackTalkToEngineerClicked(\n this.getThreadsCtaTelemetryProps(\"talk_to_engineer\", \"sidebar_footer\"),\n );\n };\n\n private handleThreadsIntelligenceSignupClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackThreadsIntelligenceSignupClicked(\n this.getThreadsCtaTelemetryProps(\"signup\", \"threads_locked\"),\n );\n };\n\n private handleThreadsTalkToEngineerClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackThreadsTalkToEngineerClicked(\n this.getThreadsCtaTelemetryProps(\"talk_to_engineer\", \"threads_locked\"),\n );\n };\n\n private handleThreadDividerPointerDown = (event: PointerEvent) => {\n this.threadDividerResizing = true;\n this.threadDividerPointerId = event.pointerId;\n this.threadDividerStartX = event.clientX;\n this.threadDividerStartWidth = this.threadListWidth;\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n event.preventDefault();\n };\n\n private handleThreadDividerPointerMove = (event: PointerEvent) => {\n if (\n !this.threadDividerResizing ||\n this.threadDividerPointerId !== event.pointerId\n )\n return;\n const delta = event.clientX - this.threadDividerStartX;\n this.threadListWidth = Math.max(\n 180,\n Math.min(480, this.threadDividerStartWidth + delta),\n );\n this.requestUpdate();\n };\n\n private handleThreadDividerPointerUp = (event: PointerEvent) => {\n if (this.threadDividerPointerId !== event.pointerId) return;\n const target = event.currentTarget as HTMLElement;\n if (target.hasPointerCapture(this.threadDividerPointerId)) {\n target.releasePointerCapture(this.threadDividerPointerId);\n }\n this.threadDividerResizing = false;\n };\n\n private trackThreadsViewStateOnce(\n state: \"locked\" | \"empty_enabled\" | \"enabled\",\n ): void {\n if (this.core?.telemetryDisabled) return;\n const key = `${state}:${this.getThreadServiceStatus()}`;\n if (this.viewedThreadsTelemetryStates.has(key)) return;\n this.viewedThreadsTelemetryStates.add(key);\n const props = this.getThreadsTelemetryProps();\n if (state === \"locked\") {\n trackThreadsLockedViewed(props);\n } else if (state === \"empty_enabled\") {\n trackThreadsEmptyEnabledViewed(props);\n } else {\n trackThreadsEnabledViewed(props);\n }\n }\n\n private shouldRenderExampleThreads(\n displayThreads: ɵThread[],\n threadsErrorMessage: string | null,\n threadsLoading: boolean,\n ): boolean {\n return (\n !threadsErrorMessage && !threadsLoading && displayThreads.length === 0\n );\n }\n\n private isExampleThreadId(threadId: string | null | undefined): boolean {\n return THREADS_EXAMPLE_THREADS.some((thread) => thread.id === threadId);\n }\n\n private getExampleThreadProvider(threadId: string): ThreadDebuggerProvider {\n const cached = this.exampleThreadProviders.get(threadId);\n if (cached) return cached;\n const thread = THREADS_EXAMPLE_THREADS.find((item) => item.id === threadId);\n const details = THREADS_EXAMPLE_DETAILS[threadId];\n const provider: ThreadDebuggerProvider = {\n getThreadMetadata: async () =>\n thread\n ? {\n id: thread.id,\n name: thread.name,\n agentId: thread.agentId,\n endUserId: \"example-user\",\n status: \"completed\",\n createdAt: thread.createdAt,\n updatedAt: thread.updatedAt,\n }\n : null,\n getMessages: async () => details?.messages ?? [],\n getEvents: async () => details?.events ?? [],\n getState: async () => details?.state ?? null,\n };\n this.exampleThreadProviders.set(threadId, provider);\n return provider;\n }\n\n private trackThreadsExampleViewedOnce(): void {\n if (this.core?.telemetryDisabled) return;\n for (const thread of THREADS_EXAMPLE_THREADS) {\n const exampleKind = getExampleKind(thread.id);\n if (!exampleKind || this.viewedExampleKinds.has(exampleKind)) continue;\n this.viewedExampleKinds.add(exampleKind);\n trackThreadsExampleViewed({\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n });\n }\n }\n\n private trackThreadsExampleSelectedOnce(threadId: string): void {\n if (this.core?.telemetryDisabled) return;\n const exampleKind = getExampleKind(threadId);\n if (!exampleKind || this.selectedExampleKinds.has(exampleKind)) return;\n this.selectedExampleKinds.add(exampleKind);\n trackThreadsExampleSelected({\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n });\n }\n\n private subscribeToInspectorThreadBridge(): void {\n this.unsubscribeFromInspectorThreadBridge();\n if (!isInspectorThreadBridgeEnabled()) return;\n this.inspectorBridgeUnsubscribers.push(\n onInspectorActiveThread((payload) => {\n if (payload.requestId !== this.activeViewInAppRequestId) return;\n this.inAppThreadId = payload.threadId;\n this.inAppAgentId = payload.agentId;\n this.inAppSource = payload.source;\n if (payload.source === \"app\") {\n this.activeViewInAppRequestId = null;\n this.viewInAppError = null;\n }\n this.requestUpdate();\n }),\n onInspectorViewThreadResult((payload) => {\n if (payload.requestId !== this.activeViewInAppRequestId) return;\n if (payload.ok) {\n this.viewInAppError = null;\n this.inAppThreadId = payload.threadId;\n this.inAppAgentId = payload.agentId;\n this.inAppSource = \"override\";\n } else {\n this.activeViewInAppRequestId = null;\n this.inAppThreadId = null;\n this.inAppAgentId = null;\n this.inAppSource = null;\n this.viewInAppError =\n \"The app could not load that thread. The previous chat is back.\";\n }\n this.requestUpdate();\n }),\n );\n }\n\n private unsubscribeFromInspectorThreadBridge(): void {\n for (const unsubscribe of this.inspectorBridgeUnsubscribers) {\n unsubscribe();\n }\n this.inspectorBridgeUnsubscribers = [];\n }\n\n private getViewInAppMode(\n thread: ɵThread | null,\n isExample: boolean,\n ): \"hidden\" | \"view\" | \"stop\" {\n if (!isInspectorThreadBridgeEnabled()) return \"hidden\";\n if (!thread || isExample) return \"hidden\";\n if (\n this.activeViewInAppRequestId &&\n this.inAppSource === \"override\" &&\n this.inAppThreadId === thread.id\n ) {\n return \"stop\";\n }\n return \"view\";\n }\n\n private handleViewInApp = (): void => {\n const thread = this.getSelectedRealThread();\n if (!thread) return;\n if (this.activeViewInAppRequestId && this.inAppAgentId) {\n emitInspectorStopViewing({\n requestId: this.activeViewInAppRequestId,\n agentId: this.inAppAgentId,\n });\n }\n this.viewInAppError = null;\n const requestId = createInspectorThreadRequestId();\n this.activeViewInAppRequestId = requestId;\n const handled = emitInspectorViewThread({\n requestId,\n threadId: thread.id,\n agentId: thread.agentId,\n });\n if (!handled) {\n this.activeViewInAppRequestId = null;\n this.inAppThreadId = null;\n this.inAppAgentId = null;\n this.inAppSource = null;\n this.viewInAppError = \"No official chat for this agent is on the page.\";\n }\n this.requestUpdate();\n };\n\n private handleStopViewing = (): void => {\n const requestId = this.activeViewInAppRequestId;\n const agentId = this.inAppAgentId;\n if (!requestId || !agentId) return;\n this.viewInAppError = null;\n emitInspectorStopViewing({ requestId, agentId });\n this.requestUpdate();\n };\n\n private getSelectedRealThread(): ɵThread | null {\n if (!this.selectedThreadId) return null;\n if (this.selectedThreadId === this.selectedLocalExampleThreadId) {\n return null;\n }\n return (\n this.getActiveThreadsState().displayThreads.find(\n (thread) => thread.id === this.selectedThreadId,\n ) ?? null\n );\n }\n\n private getCurrentExampleTourProps():\n | (InspectorThreadTelemetryProps &\n Readonly<{\n example_kind: ExampleKind;\n tour_step: ExampleTourStep;\n tour_tab: ExampleTourTab;\n }>)\n | undefined {\n const exampleKind = this.selectedThreadId\n ? getExampleKind(this.selectedThreadId)\n : undefined;\n const tourPair = getExampleTourTelemetryPair(this.exampleTourStep);\n if (!exampleKind || !tourPair) return undefined;\n return {\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n ...tourPair,\n };\n }\n\n private trackThreadsExampleTourStepViewedOnce(): void {\n if (this.core?.telemetryDisabled || !this.selectedThreadId) return;\n const props = this.getCurrentExampleTourProps();\n if (!props) return;\n const key = `${props.example_kind}:${props.tour_step}`;\n if (this.viewedExampleTourSteps.has(key)) return;\n this.viewedExampleTourSteps.add(key);\n trackThreadsExampleTourStepViewed(props);\n }\n\n private syncExampleTourTab(): void {\n const step =\n THREADS_EXAMPLE_TOUR_STEPS[this.exampleTourStep] ??\n THREADS_EXAMPLE_TOUR_STEPS[0]!;\n if (!step) return;\n void this.updateComplete.then(() => {\n const details = this.activeRoot.querySelector(\"cpk-thread-details\") as\n | (ɵCpkThreadDetails & { selectTab?: (id: ThreadDetailsTab) => void })\n | null;\n details?.selectTab?.(step.tab);\n });\n }\n\n private startExampleTour(autoStarted: boolean): void {\n if (!this.selectedThreadId) return;\n this.exampleTourActive = true;\n this.exampleTourStep = 0;\n if (autoStarted) {\n this.exampleTourAutoShown = true;\n if (!this.core?.telemetryDisabled) {\n const props = this.getCurrentExampleTourProps();\n if (props) trackThreadsExampleTourStarted(props);\n }\n } else if (!this.core?.telemetryDisabled) {\n const props = this.getCurrentExampleTourProps();\n if (props) trackThreadsExampleTourReopened(props);\n }\n this.trackThreadsExampleTourStepViewedOnce();\n this.syncExampleTourTab();\n this.requestUpdate();\n }\n\n private setExampleTourStep(nextStep: number): void {\n const telemetryStepIsValid =\n getExampleTourTelemetryPair(nextStep) !== undefined;\n this.exampleTourStep = Math.max(\n 0,\n Math.min(THREADS_EXAMPLE_TOUR_STEPS.length - 1, nextStep),\n );\n if (telemetryStepIsValid) this.trackThreadsExampleTourStepViewedOnce();\n this.syncExampleTourTab();\n this.requestUpdate();\n }\n\n private dismissExampleTour(method: \"skip\" | \"done\"): void {\n if (!this.selectedThreadId) return;\n this.exampleTourActive = false;\n this.exampleTourDismissed = true;\n this.writeThreadsExampleTourDismissed();\n if (!this.core?.telemetryDisabled) {\n const currentProps = this.getCurrentExampleTourProps();\n if (currentProps) {\n const props = { ...currentProps, dismiss_method: method };\n if (method === \"done\") {\n trackThreadsExampleTourCompleted(props);\n } else {\n trackThreadsExampleTourDismissed(props);\n }\n }\n }\n this.requestUpdate();\n }\n\n private handleThreadsThreadSelected(\n threadId: string,\n showingExamples: boolean,\n ): void {\n this.requestedThreadId = null;\n this.focusedThreadMessageId = null;\n if (\n showingExamples &&\n this.selectedThreadId === threadId &&\n this.selectedLocalExampleThreadId === threadId\n ) {\n this.selectedThreadId = null;\n this.selectedRealThreadIsExplicit = false;\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n this.requestUpdate();\n return;\n }\n\n this.tryFromHereError = null;\n this.selectedThreadId = threadId;\n if (showingExamples && this.isExampleThreadId(threadId)) {\n this.selectedRealThreadIsExplicit = false;\n this.selectedLocalExampleThreadId = threadId;\n this.trackThreadsExampleSelectedOnce(threadId);\n if (!this.exampleTourDismissed && !this.exampleTourAutoShown) {\n this.startExampleTour(true);\n } else {\n this.exampleTourActive = false;\n }\n } else {\n const { displayThreads } = this.getActiveThreadsState();\n this.selectedRealThreadIsExplicit = displayThreads.some(\n (thread) => thread.id === threadId,\n );\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n }\n this.requestUpdate();\n }\n\n private readThreadsExampleTourDismissed(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(THREADS_EXAMPLE_TOUR_STORAGE_KEY);\n if (!raw) return false;\n const value = JSON.parse(raw) as { dismissed?: unknown };\n return value.dismissed === true;\n } catch {\n return false;\n }\n }\n\n private writeThreadsExampleTourDismissed(): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(\n THREADS_EXAMPLE_TOUR_STORAGE_KEY,\n JSON.stringify({ dismissed: true }),\n );\n } catch {\n // Persistence is best-effort; the inspector should keep working without it.\n }\n }\n\n /** Cancels the one deferred gate without disturbing a newer lifecycle. */\n private cancelThreadsExampleOverviewVideoGate(): void {\n if (this.threadsExampleOverviewVideoLoadTimer !== null) {\n if (typeof window !== \"undefined\") {\n window.clearTimeout(this.threadsExampleOverviewVideoLoadTimer);\n }\n this.threadsExampleOverviewVideoLoadTimer = null;\n }\n if (this.threadsExampleOverviewVideoIdleCallbackId !== null) {\n if (\n typeof window !== \"undefined\" &&\n typeof window.cancelIdleCallback === \"function\"\n ) {\n window.cancelIdleCallback(\n this.threadsExampleOverviewVideoIdleCallbackId,\n );\n }\n this.threadsExampleOverviewVideoIdleCallbackId = null;\n }\n }\n\n /** Returns whether media work still belongs to the mounted lifecycle. */\n private isCurrentThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): boolean {\n return (\n this.isConnected &&\n video.isConnected &&\n this.threadsExampleOverviewVideoElement === video &&\n this.threadsExampleOverviewVideoLifecycleGeneration ===\n lifecycleGeneration\n );\n }\n\n /** Invalidates any unresolved play request without exposing another state. */\n private invalidateThreadsExampleOverviewVideoPlay(): void {\n this.threadsExampleOverviewVideoPlayAttemptGeneration += 1;\n this.threadsExampleOverviewVideoPlayPromise = null;\n }\n\n /** Moves a current media lifecycle into its readable failure state. */\n private failThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): void {\n if (\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.threadsExampleOverviewVideoLoaded = false;\n this.threadsExampleOverviewVideoState = \"failed\";\n this.requestUpdate();\n }\n\n /** Settles one guarded play promise and ignores stale completion. */\n private async settleThreadsExampleOverviewVideoPlay(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n playAttemptGeneration: number,\n playback: Promise<void>,\n ): Promise<void> {\n try {\n await playback;\n if (\n this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration) &&\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.threadsExampleOverviewVideoState = \"playing\";\n this.requestUpdate();\n }\n } catch {\n if (\n this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration) &&\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration\n ) {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n } finally {\n if (\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration\n ) {\n this.threadsExampleOverviewVideoPlayPromise = null;\n }\n }\n }\n\n /** Starts at most one play request for the current media lifecycle. */\n private playThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): void {\n if (\n this.threadsExampleOverviewVideoPlayPromise !== null ||\n this.threadsExampleOverviewVideoState === \"deferred\" ||\n this.threadsExampleOverviewVideoState === \"failed\" ||\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n\n const playAttemptGeneration =\n this.threadsExampleOverviewVideoPlayAttemptGeneration + 1;\n this.threadsExampleOverviewVideoPlayAttemptGeneration =\n playAttemptGeneration;\n try {\n const playback = Promise.resolve(video.play());\n this.threadsExampleOverviewVideoPlayPromise =\n this.settleThreadsExampleOverviewVideoPlay(\n video,\n lifecycleGeneration,\n playAttemptGeneration,\n playback,\n );\n } catch {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n }\n\n /** Attaches the sole source for a generation and optionally starts playback. */\n private activateThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n play: boolean,\n ): void {\n if (\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n\n this.threadsExampleOverviewVideoState = \"ready\";\n this.threadsExampleOverviewVideoLoaded = false;\n video.autoplay = !this.threadsExampleOverviewVideoReducedMotion;\n video.setAttribute(\"src\", THREADS_EXAMPLE_OVERVIEW_VIDEO_URL);\n this.requestUpdate();\n if (play) {\n this.playThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n }\n\n /** Schedules exactly one idle or timer gate for the current video. */\n private scheduleThreadsExampleOverviewVideoLoad(): void {\n const video = this.threadsExampleOverviewVideoElement;\n if (\n !video ||\n !this.isConnected ||\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n this.threadsExampleOverviewVideoLoadTimer !== null ||\n this.threadsExampleOverviewVideoIdleCallbackId !== null ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n if (typeof window.requestIdleCallback === \"function\") {\n let idleCallbackId = 0;\n const loadVideo = () => {\n if (this.threadsExampleOverviewVideoIdleCallbackId !== idleCallbackId) {\n return;\n }\n this.threadsExampleOverviewVideoIdleCallbackId = null;\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n !this.threadsExampleOverviewVideoReducedMotion,\n );\n };\n idleCallbackId = window.requestIdleCallback(loadVideo, { timeout: 1200 });\n this.threadsExampleOverviewVideoIdleCallbackId = idleCallbackId;\n return;\n }\n\n const loadTimer = window.setTimeout(() => {\n if (this.threadsExampleOverviewVideoLoadTimer !== loadTimer) {\n return;\n }\n this.threadsExampleOverviewVideoLoadTimer = null;\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n !this.threadsExampleOverviewVideoReducedMotion,\n );\n }, 450);\n this.threadsExampleOverviewVideoLoadTimer = loadTimer;\n }\n\n /** Attaches one generation-scoped media listener set to the stable video. */\n private bindThreadsExampleOverviewVideo(video: HTMLVideoElement): void {\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n const listeners: ThreadsExampleOverviewVideoListeners = {\n loadeddata: () => {\n if (\n !this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) ||\n this.threadsExampleOverviewVideoState === \"deferred\" ||\n this.threadsExampleOverviewVideoState === \"failed\"\n ) {\n return;\n }\n this.threadsExampleOverviewVideoLoaded = true;\n this.requestUpdate();\n },\n play: () => {\n if (\n this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) &&\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.threadsExampleOverviewVideoState = \"playing\";\n this.requestUpdate();\n }\n },\n pause: () => {\n if (\n this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) &&\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.threadsExampleOverviewVideoState = \"ready\";\n this.requestUpdate();\n }\n },\n error: () => {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n },\n };\n this.threadsExampleOverviewVideoElement = video;\n this.threadsExampleOverviewVideoListeners = listeners;\n video.addEventListener(\"loadeddata\", listeners.loadeddata);\n video.addEventListener(\"play\", listeners.play);\n video.addEventListener(\"pause\", listeners.pause);\n video.addEventListener(\"error\", listeners.error);\n video.muted = true;\n video.loop = true;\n video.playsInline = true;\n video.autoplay =\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n !this.threadsExampleOverviewVideoReducedMotion;\n }\n\n /** Tears down gates, listeners, playback, and source in cleanup order. */\n private cleanupThreadsExampleOverviewVideo(): void {\n const video = this.threadsExampleOverviewVideoElement;\n if (video) {\n this.threadsExampleOverviewVideoLifecycleGeneration += 1;\n }\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.cancelThreadsExampleOverviewVideoGate();\n this.threadsExampleOverviewVideoPlayOnNextBind = false;\n\n const listeners = this.threadsExampleOverviewVideoListeners;\n if (video && listeners) {\n video.removeEventListener(\"loadeddata\", listeners.loadeddata);\n video.removeEventListener(\"play\", listeners.play);\n video.removeEventListener(\"pause\", listeners.pause);\n video.removeEventListener(\"error\", listeners.error);\n }\n this.threadsExampleOverviewVideoElement = null;\n this.threadsExampleOverviewVideoListeners = null;\n\n if (video) {\n try {\n video.pause();\n } catch {\n // Some DOM shims expose media methods that throw instead of no-oping.\n }\n video.removeAttribute(\"src\");\n try {\n video.load();\n } catch {\n // Cleanup must stay synchronous and never surface media abort errors.\n }\n }\n this.threadsExampleOverviewVideoLoaded = false;\n this.threadsExampleOverviewVideoState = \"deferred\";\n }\n\n /** Reconciles the rendered media node with its current lifecycle. */\n private syncThreadsExampleOverviewVideo(): void {\n const video = this.activeRoot.querySelector<HTMLVideoElement>(\n \".cpk-threads-overview-video\",\n );\n if (!video) {\n if (\n this.threadsExampleOverviewVideoElement ||\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n this.threadsExampleOverviewVideoLoadTimer !== null ||\n this.threadsExampleOverviewVideoIdleCallbackId !== null ||\n this.threadsExampleOverviewVideoPlayOnNextBind\n ) {\n this.cleanupThreadsExampleOverviewVideo();\n }\n return;\n }\n\n if (this.threadsExampleOverviewVideoElement !== video) {\n if (this.threadsExampleOverviewVideoElement) {\n this.cleanupThreadsExampleOverviewVideo();\n }\n this.bindThreadsExampleOverviewVideo(video);\n }\n if (this.threadsExampleOverviewVideoPlayOnNextBind) {\n this.threadsExampleOverviewVideoPlayOnNextBind = false;\n this.activateThreadsExampleOverviewVideo(\n video,\n this.threadsExampleOverviewVideoLifecycleGeneration,\n true,\n );\n return;\n }\n this.scheduleThreadsExampleOverviewVideoLoad();\n }\n\n /** Handles the external native Play/Pause control. */\n private handleThreadsExampleOverviewVideoControl = (): void => {\n const video = this.threadsExampleOverviewVideoElement;\n if (!video) return;\n\n if (this.threadsExampleOverviewVideoState === \"playing\") {\n this.invalidateThreadsExampleOverviewVideoPlay();\n try {\n video.pause();\n } catch {\n // Keep the visible state usable when a media shim cannot pause.\n }\n this.threadsExampleOverviewVideoState = \"ready\";\n this.requestUpdate();\n return;\n }\n\n if (this.threadsExampleOverviewVideoState === \"failed\") {\n this.cleanupThreadsExampleOverviewVideo();\n if (!this.isConnected || !video.isConnected) return;\n this.threadsExampleOverviewVideoPlayOnNextBind = true;\n this.requestUpdate();\n return;\n }\n\n this.cancelThreadsExampleOverviewVideoGate();\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n if (this.threadsExampleOverviewVideoState === \"deferred\") {\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n true,\n );\n return;\n }\n this.playThreadsExampleOverviewVideo(video, lifecycleGeneration);\n };\n\n private renderThreadsExampleOverviewVideo() {\n const isPlaying = this.threadsExampleOverviewVideoState === \"playing\";\n const sourceIsAttached =\n this.threadsExampleOverviewVideoState !== \"deferred\";\n const video = html`<video\n class=\"cpk-threads-overview-video\"\n data-loaded=${this.threadsExampleOverviewVideoLoaded}\n ?autoplay=${\n sourceIsAttached && !this.threadsExampleOverviewVideoReducedMotion\n }\n .autoplay=${\n sourceIsAttached && !this.threadsExampleOverviewVideoReducedMotion\n }\n loop\n .loop=${true}\n muted\n .muted=${true}\n playsinline\n .playsInline=${true}\n preload=\"metadata\"\n ></video>`;\n // Alternating template identities retire the prior media node after cleanup.\n // The node remains stable for every render within one lifecycle generation.\n const generationScopedVideo =\n this.threadsExampleOverviewVideoLifecycleGeneration % 2 === 0\n ? html`<!-- cpk-video-generation-even -->${video}`\n : html`<!-- cpk-video-generation-odd -->${video}`;\n return html`\n <div class=\"cpk-threads-overview-video-frame\" aria-hidden=\"true\">\n ${generationScopedVideo}\n </div>\n <button\n class=\"cpk-threads-overview-video-control\"\n type=\"button\"\n aria-pressed=${isPlaying ? \"false\" : \"true\"}\n @click=${this.handleThreadsExampleOverviewVideoControl}\n >\n ${isPlaying ? \"Pause demo\" : \"Play demo\"}\n </button>\n ${\n this.threadsExampleOverviewVideoState === \"failed\"\n ? html`\n <p class=\"cpk-threads-overview-video-fallback\" role=\"status\">\n ${THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK}\n </p>\n `\n : nothing\n }\n `;\n }\n\n private renderThreadsExampleOverview() {\n const onboardingAction = this.getThreadsEmptyOnboardingAction();\n return html`\n <div class=\"cpk-threads-overview\">\n <div class=\"cpk-threads-overview-content\">\n <h2 class=\"cpk-threads-overview-title\">\n Threads are persistent, inspectable conversations\n </h2>\n ${this.renderThreadsExampleOverviewVideo()}\n <p class=\"cpk-threads-overview-copy\">\n Take a tour with the example threads in the sidebar. Then, start\n chatting in your app to create the first real thread.\n </p>\n <div class=\"cpk-threads-overview-actions\">\n <a\n href=${this.getThreadsDocsUrl()}\n target=\"_blank\"\n rel=\"noopener\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-primary\"\n >\n Learn how Threads work\n </a>\n <a\n href=${onboardingAction.href}\n target=\"_blank\"\n rel=\"noopener\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-secondary\"\n >\n ${onboardingAction.label}\n </a>\n </div>\n </div>\n </div>\n `;\n }\n\n private renderLockedFeatureOverview({\n serviceId,\n featureName,\n heading,\n description,\n videoUrl,\n videoTitle,\n outlineItems,\n setupPrompt,\n }: {\n serviceId: HomeFeaturePromptId;\n featureName: string;\n heading: string;\n description: string;\n videoUrl: string;\n videoTitle: string;\n outlineItems: ReadonlyArray<LockedFeatureOutlineItem>;\n setupPrompt?: Readonly<{\n serviceId: HomeFeaturePromptId;\n copyState: HomeFeaturePromptCopyState;\n onClick: (event: Event) => void;\n }>;\n }) {\n return html`\n <div\n class=\"cpk-locked-feature\"\n data-inspector-locked-feature=${serviceId}\n >\n <div class=\"cpk-locked-feature-layout\">\n <div class=\"cpk-locked-feature-hero\">\n <div class=\"cpk-locked-feature-copy\">\n <div class=\"cpk-locked-feature-name\">\n <span class=\"cpk-locked-feature-icon\" aria-hidden=\"true\">\n ${\n serviceId === \"threads\"\n ? unsafeHTML(this.customTabIcons.threads)\n : this.renderIcon(\"Brain\")\n }\n </span>\n ${featureName}\n </div>\n <h2 class=\"cpk-locked-feature-title\">${heading}</h2>\n <p class=\"cpk-locked-feature-description\">${description}</p>\n <div class=\"cpk-threads-overview-actions\">\n ${this.renderFeatureSetupPrompt(\n setupPrompt?.serviceId ?? serviceId,\n \"inspector-account-cta cpk-locked-feature-setup-cta\",\n setupPrompt\n ? {\n copyState: setupPrompt.copyState,\n onClick: setupPrompt.onClick,\n }\n : undefined,\n )}\n <a\n data-inspector-locked-feature-talk=${serviceId}\n href=${this.getTalkToEngineerUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Talk to an Engineer (opens in a new tab)\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-secondary\"\n @click=${this.handleThreadsTalkToEngineerClick}\n >\n Talk to an Engineer\n </a>\n </div>\n </div>\n <div class=\"cpk-locked-feature-media\">\n <div class=\"cpk-threads-overview-video-frame cpk-locked-feature-video\">\n <iframe\n class=\"cpk-threads-overview-video-embed\"\n data-inspector-feature-video=${serviceId}\n src=${videoUrl}\n title=${videoTitle}\n loading=\"lazy\"\n allow=\"fullscreen; picture-in-picture\"\n allowfullscreen\n ></iframe>\n </div>\n </div>\n </div>\n <section\n class=\"cpk-locked-feature-outline\"\n data-inspector-feature-outline=${serviceId}\n aria-label=\"${featureName} capabilities\"\n >\n <div class=\"cpk-locked-feature-outline-list\">\n ${outlineItems.map(\n (item) => html`\n <section class=\"cpk-locked-feature-outline-item\">\n <h3>\n <span\n class=\"cpk-locked-feature-outline-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(item.icon)}\n </span>\n ${item.title}\n </h3>\n <p>${item.description}</p>\n </section>\n `,\n )}\n </div>\n </section>\n </div>\n </div>\n `;\n }\n\n private renderThreadsExampleTour() {\n if (\n !this.selectedThreadId ||\n this.selectedThreadId !== this.selectedLocalExampleThreadId\n ) {\n return nothing;\n }\n\n if (!this.exampleTourActive) {\n return html`\n <button\n class=\"cpk-threads-tour-launch\"\n type=\"button\"\n @click=${() => this.startExampleTour(false)}\n >\n Show tour\n </button>\n `;\n }\n\n const step =\n THREADS_EXAMPLE_TOUR_STEPS[this.exampleTourStep] ??\n THREADS_EXAMPLE_TOUR_STEPS[0]!;\n const isFirst = this.exampleTourStep === 0;\n const isLast =\n this.exampleTourStep === THREADS_EXAMPLE_TOUR_STEPS.length - 1;\n\n return html`\n <div\n class=\"cpk-threads-tour\"\n role=\"dialog\"\n aria-label=\"Example thread tour\"\n >\n <div class=\"cpk-threads-tour-step\">\n ${this.exampleTourStep + 1}/${THREADS_EXAMPLE_TOUR_STEPS.length}\n ${step.label}\n </div>\n <div class=\"cpk-threads-tour-title\">${step.title}</div>\n <div class=\"cpk-threads-tour-copy\">${step.body}</div>\n <div class=\"cpk-threads-tour-actions\">\n <button\n class=\"cpk-threads-tour-skip\"\n type=\"button\"\n @click=${() => this.dismissExampleTour(\"skip\")}\n >\n Skip\n </button>\n <div class=\"cpk-threads-tour-nav\">\n <button\n class=\"cpk-threads-tour-button cpk-threads-tour-button-secondary\"\n type=\"button\"\n ?disabled=${isFirst}\n @click=${() => this.setExampleTourStep(this.exampleTourStep - 1)}\n >\n Back\n </button>\n <button\n class=\"cpk-threads-tour-button cpk-threads-tour-button-primary\"\n type=\"button\"\n @click=${() =>\n isLast\n ? this.dismissExampleTour(\"done\")\n : this.setExampleTourStep(this.exampleTourStep + 1)}\n >\n ${isLast ? \"Done\" : \"Next\"}\n </button>\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Renders the realtime-connection indicator in the memory-store header.\n * Only `\"connected\"` shows the live (green-dot) state; `\"connecting\"` shows a\n * muted amber \"reconnecting\" and `\"unavailable\"` a muted grey \"offline\", so\n * the indicator never claims \"live\" over a frozen snapshot once the realtime\n * socket has permanently given up.\n */\n private renderMemoryRealtimeIndicator() {\n const status = this._memoriesRealtimeStatus;\n const connected = status === \"connected\";\n const dotColor = connected\n ? \"#22c55e\"\n : status === \"connecting\"\n ? \"#f59e0b\"\n : \"#9ca3af\";\n const label =\n status === \"connected\"\n ? \"live\"\n : status === \"connecting\"\n ? \"reconnecting\"\n : \"offline\";\n return html`\n <span\n style=\"\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 500;\n color: ${connected ? \"#57575b\" : \"#68686e\"};\n \"\n >\n <span\n style=\"\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${dotColor};\n \"\n ></span>\n ${label}\n </span>\n `;\n }\n\n private renderMemoriesView() {\n const state = deriveLearningViewState({\n supported: this.learningSupported,\n loading: this.learningLoading,\n error: this.learningError,\n snapshot: this.learningSnapshot,\n setupActive: this.isLearningSetupActive(),\n });\n if (state === \"landing\") {\n return this.renderLockedFeatureOverview({\n serviceId: \"memory\",\n featureName: \"Automatic Learning\",\n heading: \"Turn every interaction into reusable context.\",\n description:\n \"Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.\",\n videoUrl: LEARNING_LOCKED_VIDEO_URL,\n videoTitle: \"CopilotKit Learning overview\",\n outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE,\n setupPrompt: {\n serviceId: \"memory\",\n copyState: this.learningPromptCopyState,\n onClick: (event) => void this.handleLearningSetupCopy(event),\n },\n });\n }\n return html`\n <cpk-learning-view\n data-color-scheme=${this.colorScheme}\n .supported=${this.learningSupported}\n .loading=${this.learningLoading}\n .refreshing=${this.learningRefreshing}\n .error=${this.learningError}\n .snapshot=${this.learningSnapshot}\n .setupActive=${this.isLearningSetupActive()}\n .copyState=${this.learningPromptCopyState}\n .recopyState=${this.learningPromptRecopyState}\n .setupPrompt=${createFeatureOnboardingPrompt(\n \"memory\",\n this.getOnboardingRunId(),\n )}\n @learning-retry=${() =>\n this.refreshLearningSnapshot({\n preserve: this.learningSnapshot !== null,\n })}\n @learning-copy-setup=${(event: Event) =>\n this.handleLearningSetupCopy(event)}\n @learning-recopy-setup=${(event: Event) =>\n this.handleLearningSetupCopy(event, true)}\n @learning-go-back=${this.handleLearningGoBack}\n @learning-page=${(event: CustomEvent) =>\n this.handleLearningPage(\n event as CustomEvent<{\n section: \"skills\" | \"insights\";\n page: number;\n }>,\n )}\n @learning-open-evidence=${(event: CustomEvent) =>\n this.handleLearningEvidence(\n event as CustomEvent<{\n threadId: string;\n messageId?: string;\n }>,\n )}\n @learning-evidence-opened=${() => {\n if (!this.core?.telemetryDisabled) trackLearningEvidenceOpened();\n }}\n @learning-skill-toggle=${(\n event: CustomEvent<{ action: \"expanded\" | \"collapsed\" }>,\n ) => {\n if (!this.core?.telemetryDisabled) {\n trackLearningSkillToggled({ action: event.detail.action });\n }\n }}\n @learning-web-link=${(\n event: CustomEvent<{\n category: \"learning\" | \"runs\" | \"candidates\";\n }>,\n ) => {\n if (!this.core?.telemetryDisabled) {\n trackLearningWebAppOpened({ category: event.detail.category });\n }\n }}\n ></cpk-learning-view>\n `;\n }\n\n /** Legacy Memory rendering kept isolated while published Memory APIs remain. */\n private renderLegacyMemoriesView() {\n // Once the user enters Learning, its lazy subscription is the capability\n // probe. Preserve the loading state while that request is in flight, then\n // let an unavailable response fall through to the setup gate.\n const learningEnabled = this.getHomeModel().services.some(\n (service) => service.id === \"memory\" && service.enabled,\n );\n // 1. Locked teaser — use the same entitlement-aware capability decision\n // as Home and the launcher so an unavailable feature always lands on its\n // setup path instead of an enabled-looking empty state.\n if (!learningEnabled) {\n return this.renderLockedFeatureOverview({\n serviceId: \"memory\",\n featureName: \"Automatic Learning\",\n heading: this._memoryStoreUnsupported\n ? \"Upgrade to enable Learning\"\n : \"Turn every interaction into reusable context.\",\n description: this._memoryStoreUnsupported\n ? \"Learning requires a newer version of @copilotkit/core and @copilotkit/react. Copy the setup prompt to upgrade and add long-term memory.\"\n : \"Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.\",\n videoUrl: LEARNING_LOCKED_VIDEO_URL,\n videoTitle: \"CopilotKit Learning overview\",\n outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE,\n });\n }\n\n // 2. Full-screen error — only for a snapshot-LOAD failure (no memories\n // loaded). A mutation failure that arrives while memories are already on\n // screen must NOT blank the list; it is surfaced inline below (step 4).\n if (this._memoriesError && this._memories.length === 0) {\n return html`\n <div\n style=\"\n display: flex;\n height: 100%;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0333a\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span style=\"font-size: 13px; color: #c0333a;\">\n ${MEMORY_LOAD_ERROR_LABEL}\n </span>\n <span\n style=\"\n max-width: 320px;\n text-align: center;\n font-size: 11px;\n line-height: 1.5;\n color: #c0333a;\n \"\n >\n ${this._memoriesError.message}\n </span>\n <span\n style=\"\n max-width: 320px;\n text-align: center;\n font-size: 11px;\n line-height: 1.5;\n color: #c0333a;\n \"\n >\n ${EVENT_ERROR_GUIDANCE.memory.advice}\n </span>\n </div>\n `;\n }\n\n // 3. Initial loading placeholder (no memories yet to show behind it).\n if (this._memoriesLoading && this._memories.length === 0) {\n return html`\n <div\n style=\"\n display: flex;\n height: 100%;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0c0c8\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n <span style=\"font-size: 13px\">Loading learning…</span>\n </div>\n `;\n }\n\n // 4. Content — header + memory list.\n return html`\n <div\n style=\"display:flex;height:100%;overflow:hidden;flex-direction:column;\"\n >\n <div\n class=\"cpk-section-header\"\n style=\"display:flex;align-items:center;justify-content:space-between;\"\n >\n <h4>${LEARNING_VIEW_LABEL}</h4>\n <div style=\"display:flex;align-items:center;gap:6px;\">\n ${this.renderMemoryRealtimeIndicator()}\n <span\n style=\"\n font-size: 11px;\n font-weight: 500;\n color: #57575b;\n background: rgba(0,0,0,0.07);\n border-radius: 9999px;\n padding: 1px 7px;\n \"\n >\n ${this._memories.length}\n </span>\n </div>\n </div>\n ${\n this._memoriesError\n ? html`\n <div\n role=\"alert\"\n style=\"\n display: flex;\n align-items: flex-start;\n gap: 8px;\n flex-shrink: 0;\n border-bottom: 1px solid #f1c7c9;\n background: #fdf3f3;\n padding: 8px 12px;\n color: #c0333a;\n font-size: 12px;\n line-height: 1.45;\n \"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0333a\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"flex-shrink:0;margin-top:1px;\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span>Action failed: ${this._memoriesError.message}</span>\n </div>\n `\n : nothing\n }\n <div style=\"flex:1;min-height:0;overflow:hidden;\">\n <cpk-memory-list\n style=\"height:100%;\"\n data-color-scheme=${this.colorScheme}\n .memories=${this._memories}\n .recallResults=${this._recallResults}\n .recallLoading=${this._recallLoading}\n .recallError=${this._recallError}\n .recallQueryText=${this._recallQuery}\n @recallQueryChanged=${(e: CustomEvent<string>) => {\n this._recallQuery = e.detail;\n }}\n @recallSubmitted=${(e: CustomEvent<string>) => {\n this.runRecall(e.detail);\n }}\n @recallCleared=${() => {\n this.clearRecall();\n }}\n ></cpk-memory-list>\n </div>\n </div>\n `;\n }\n\n /** Renders trusted Threads usage and its independent plan action. */\n private renderThreadsUsageFooter() {\n const { usage, threadsFooterAction } = this.inspectorMetadataProjection;\n if (!usage && !threadsFooterAction) {\n return nothing;\n }\n\n let countLabel: string | undefined;\n let progressMax: number | undefined;\n let progressValue: number | undefined;\n const capacityState = this.getThreadsCapacityState();\n if (usage) {\n if (usage.limit.kind === \"finite\") {\n const overLimit = usage.used > usage.limit.value;\n const visibleUsed = overLimit\n ? `${usage.limit.value}+`\n : String(usage.used);\n countLabel = `${visibleUsed} / ${usage.limit.value} Threads`;\n progressMax = usage.limit.value;\n progressValue = Math.min(usage.used, usage.limit.value);\n } else if (usage.limit.kind === \"unlimited\") {\n countLabel = `${usage.used} Threads · Unlimited`;\n } else {\n countLabel = `${usage.used} Threads · Limit unavailable`;\n }\n }\n\n return html`\n <footer\n class=\"inspector-threads-footer\"\n data-inspector-threads-footer\n role=\"group\"\n aria-label=\"Threads usage\"\n >\n ${\n usage && countLabel\n ? html`\n <div class=\"inspector-threads-usage\">\n <span data-inspector-thread-count>${countLabel}</span>\n ${\n progressMax !== undefined && progressValue !== undefined\n ? html`\n <progress\n class=\"inspector-thread-progress\"\n data-inspector-thread-progress\n data-inspector-thread-capacity=${capacityState}\n max=${progressMax}\n value=${progressValue}\n aria-label=${\n capacityState === \"warning\"\n ? `${countLabel}. Near thread limit.`\n : capacityState === \"critical\"\n ? `${countLabel}. Thread limit reached.`\n : countLabel\n }\n >\n ${countLabel}\n </progress>\n `\n : nothing\n }\n ${\n usage.expiringSoonCount !== undefined\n ? html`\n <span data-inspector-thread-expiry\n >${usage.expiringSoonCount} Expiring Soon</span\n >\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n ${\n threadsFooterAction\n ? this.renderInspectorAction(\n threadsFooterAction,\n \"threads-footer\",\n capacityState === \"warning\" || capacityState === \"critical\"\n ? \"Upgrade Your Plan\"\n : threadsFooterAction.label,\n )\n : nothing\n }\n </footer>\n `;\n }\n\n private renderThreadsView() {\n const { displayThreads, threadsErrorMessage, threadsLoading } =\n this.getActiveThreadsState();\n const ephemeral = !this._core?.intelligence;\n const available = this.areThreadEndpointsAvailable();\n const hasEphemeralThreads =\n ephemeral && available && displayThreads.length > 0;\n if (!ephemeral) this.ephemeralThreadsSetupOpen = false;\n const locked =\n !available ||\n (ephemeral &&\n displayThreads.length === 0 &&\n !threadsLoading &&\n !threadsErrorMessage);\n if (locked || this.ephemeralThreadsSetupOpen) {\n this.trackThreadsViewStateOnce(\"locked\");\n return html`\n ${\n hasEphemeralThreads\n ? html`\n <nav class=\"cpk-threads-setup-navigation\" aria-label=\"Threads setup navigation\">\n <button type=\"button\" class=\"cpk-threads-setup-back\"\n data-inspector-ephemeral-back\n @click=${() => {\n this.ephemeralThreadsSetupOpen = false;\n this.requestUpdate();\n }}>\n <span aria-hidden=\"true\">←</span> Back to your threads\n </button>\n </nav>\n `\n : nothing\n }\n ${this.renderLockedFeatureOverview({\n serviceId: \"threads\",\n featureName: \"Rich Threads\",\n heading: THREADS_LOCKED_COPY.heading,\n description: THREADS_LOCKED_COPY.description,\n videoUrl: THREADS_LOCKED_VIDEO_URL,\n videoTitle: \"Rich Threads overview\",\n outlineItems: THREADS_LOCKED_FEATURE_OUTLINE,\n })}`;\n }\n\n const loadingWithoutRows =\n threadsLoading && !threadsErrorMessage && displayThreads.length === 0;\n\n const showingExamples = this.shouldRenderExampleThreads(\n displayThreads,\n threadsErrorMessage,\n threadsLoading,\n );\n const visibleThreads =\n threadsErrorMessage || loadingWithoutRows\n ? []\n : showingExamples\n ? THREADS_EXAMPLE_THREADS\n : displayThreads;\n if (showingExamples) {\n this.trackThreadsExampleViewedOnce();\n }\n\n const selectedThread =\n this.selectedThreadId != null\n ? (visibleThreads.find((t) => t.id === this.selectedThreadId) ?? null)\n : null;\n const selectedThreadIsLocalExample =\n selectedThread !== null &&\n selectedThread.id === this.selectedLocalExampleThreadId;\n\n if (\n !threadsErrorMessage &&\n (!threadsLoading || displayThreads.length > 0)\n ) {\n this.trackThreadsViewStateOnce(\n displayThreads.length === 0 ? \"empty_enabled\" : \"enabled\",\n );\n }\n\n return html`\n <div\n style=\"display:flex;height:100%;overflow:hidden;flex-direction:column;\"\n >\n <div class=\"inspector-thread-heading\"><strong>Rich Threads</strong><button type=\"button\" class=\"inspector-text-button\" aria-expanded=${!this.threadListCollapsed} @click=${() => {\n this.threadListCollapsed = !this.threadListCollapsed;\n this.requestUpdate();\n }}>${this.threadListCollapsed ? \"Show thread list\" : \"Hide thread list\"}</button></div>\n <div style=\"display:flex;min-height:0;flex:1;overflow:hidden;\">\n <!-- Left sidebar: thread list -->\n <div\n style=\"display:${this.threadListCollapsed ? \"none\" : \"flex\"};width:${\n this.threadListWidth\n }px;flex-shrink:0;overflow:hidden;flex-direction:column;border-right:1px solid #DBDBE5;\"\n >\n ${\n ephemeral\n ? html`\n <button type=\"button\" class=\"cpk-ephemeral-threads-banner\"\n data-inspector-ephemeral-banner data-inspector-ephemeral-upgrade\n aria-label=\"Make threads permanent. Ephemeral history can disappear on restart.\"\n @click=${() => {\n this.ephemeralThreadsSetupOpen = true;\n this.requestUpdate();\n }}>\n <span class=\"cpk-ephemeral-threads-icon\" aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n <span class=\"cpk-ephemeral-threads-copy\">\n <span class=\"cpk-ephemeral-threads-headline\">\n <strong>Keep your threads.</strong>\n </span>\n <span class=\"cpk-ephemeral-threads-description\">Ephemeral history can disappear on restart.</span>\n <span class=\"cpk-ephemeral-threads-upgrade\">Make them permanent <span aria-hidden=\"true\">${this.renderIcon(\"ArrowRight\")}</span></span>\n </span>\n </button>\n `\n : nothing\n }\n <cpk-thread-list\n style=\"min-height:0;flex:1;\"\n data-color-scheme=${this.colorScheme}\n .threads=${visibleThreads}\n .selectedThreadId=${this.selectedThreadId}\n .inAppThreadId=${this.inAppThreadId}\n .errorMessage=${threadsErrorMessage}\n .suppressEmptyState=${loadingWithoutRows}\n @threadSelected=${(e: CustomEvent<string>) => {\n this.handleThreadsThreadSelected(e.detail, showingExamples);\n }}\n ></cpk-thread-list>\n ${this.renderThreadsUsageFooter()}\n </div>\n\n <!-- Resize divider -->\n <div\n style=\"width:4px;flex-shrink:0;cursor:col-resize;background:transparent;position:relative;z-index:1;\"\n @pointerdown=${this.handleThreadDividerPointerDown}\n @pointermove=${this.handleThreadDividerPointerMove}\n @pointerup=${this.handleThreadDividerPointerUp}\n @pointercancel=${this.handleThreadDividerPointerUp}\n ></div>\n\n <!-- Center + right: thread details or empty state -->\n <div\n style=\"flex:1;min-width:0;overflow:hidden;display:flex;position:relative;\"\n >\n ${\n threadsErrorMessage\n ? html`\n <div\n role=\"alert\"\n style=\"\n display: flex;\n flex: 1;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 24px;\n color: #c0333a;\n text-align: center;\n \"\n >\n <strong style=\"font-size:13px;\"\n >Failed to load threads</strong\n >\n <span\n style=\"max-width:440px;font-size:12px;line-height:1.5;\"\n >${threadsErrorMessage}</span\n >\n </div>\n `\n : loadingWithoutRows\n ? html`\n <div\n role=\"status\"\n style=\"\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: center;\n color: #57575b;\n font-size: 13px;\n \"\n >\n Loading threads…\n </div>\n `\n : selectedThread\n ? html`<cpk-thread-details\n style=\"flex:1;min-width:0;\"\n data-color-scheme=${this.colorScheme}\n .threadId=${selectedThread.id}\n .thread=${selectedThread}\n .provider=${\n selectedThreadIsLocalExample\n ? this.getExampleThreadProvider(selectedThread.id)\n : null\n }\n .runtimeUrl=${\n selectedThreadIsLocalExample\n ? \"\"\n : (this._core?.runtimeUrl ?? \"\")\n }\n .headers=${this._core?.headers ?? {}}\n .threadInspectionAvailable=${\n selectedThreadIsLocalExample ||\n (this.areThreadEndpointsAvailable() &&\n this._core?.threadEndpoints?.inspect !== false)\n }\n .liveMessageVersion=${\n this.liveMessageVersion.get(selectedThread.id) ?? 0\n }\n .viewInAppMode=${this.getViewInAppMode(\n selectedThread,\n selectedThreadIsLocalExample,\n )}\n .viewInAppError=${this.viewInAppError}\n @viewInApp=${this.handleViewInApp}\n @stopViewing=${this.handleStopViewing}\n .focusMessageId=${this.focusedThreadMessageId}\n .focusRequestId=${this.threadFocusRequestId}\n .agentStateInput=${this.getLatestStateForAgent(\n selectedThread.agentId,\n )}\n .agentEventsInput=${\n this.agentEvents.get(selectedThread.agentId) ?? []\n }\n .agentMessagesInput=${\n selectedThreadIsLocalExample\n ? EMPTY_INSPECTOR_MESSAGES\n : this.getLiveAgentMessagesForThread(selectedThread)\n }\n .tryFromHereAvailable=${\n !selectedThreadIsLocalExample &&\n this.areThreadEndpointsAvailable() &&\n this._core?.threadEndpoints?.inspect !== false\n }\n .tryFromHereBusy=${this.tryFromHereBusy}\n .tryFromHereError=${this.tryFromHereError}\n @tryFromHere=${(event: CustomEvent<string | null>) => {\n void this.handleTryFromHere(event.detail);\n }}\n ></cpk-thread-details>\n ${\n selectedThreadIsLocalExample\n ? this.renderThreadsExampleTour()\n : nothing\n }`\n : showingExamples\n ? this.renderThreadsExampleOverview()\n : html`\n <div\n style=\"\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0c0c8\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"\n />\n </svg>\n <span style=\"font-size: 13px\"\n >${\n displayThreads.length === 0\n ? \"No threads yet\"\n : \"Select a thread to inspect\"\n }</span\n >\n </div>\n `\n }\n </div>\n </div>\n </div>\n `;\n }\n\n private renderEventsToolbar(\n events: InspectorEvent[],\n filteredEvents: InspectorEvent[],\n options: { showAgentFilter?: boolean } = {},\n ) {\n const showAgentFilter = options.showAgentFilter !== false;\n const selectedLabel =\n this.selectedContext === \"all-agents\"\n ? \"all agents\"\n : `agent ${this.selectedContext}`;\n\n return html`\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 ${\n showAgentFilter\n ? html`\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.selectedContext}\n @change=${this.handleEventAgentChange}\n aria-label=\"Filter events by agent\"\n >\n ${this.contextOptions.map(\n (option) =>\n html`<option value=${option.key}>\n ${option.label}\n </option>`,\n )}\n </select>\n `\n : nothing\n }\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 aria-label=\"Filter events by type\"\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=${\n !this.eventFilterText && this.eventTypeFilter === \"all\"\n }\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}${\n this.selectedContext === \"all-agents\" ? \"\" : ` for ${selectedLabel}`\n }\n </div>\n </div>\n `;\n }\n\n private renderEventsTable(options: { embedded?: boolean } = {}) {\n const events = this.getEventsForSelectedContext();\n const filteredEvents = this.filterEvents(events);\n const embedded = options.embedded === true;\n\n let body;\n if (events.length === 0) {\n body = html`\n <div\n class=\"flex h-full flex-col items-center justify-center gap-2 px-4 py-10 text-center\"\n >\n <div class=\"text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\">\n ${this.renderIcon(\"Zap\")}\n </div>\n <span class=\"text-sm text-gray-600\">No events yet</span>\n <span class=\"max-w-[240px] text-xs leading-snug text-gray-400\"\n >Events are recorded live. Run the agent to see them here.</span\n >\n </div>\n `;\n } else if (filteredEvents.length === 0) {\n body = 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 } else {\n const runError = this.eventErrorDetails.run;\n const failedRunEventId = runError\n ? this.findLatestRunErrorEvent(runError.agentId)?.id\n : undefined;\n body = html`\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 <colgroup>\n <col style=\"width:${this.evtColWidths[0]}px\" />\n <col style=\"width:${this.evtColWidths[1]}px\" />\n <col style=\"width:${this.evtColWidths[2]}px\" />\n <col />\n </colgroup>\n <thead class=\"sticky top-0 z-10\">\n <tr class=\"bg-white\">\n ${[\"Agent\", \"Time\", \"Event Type\"].map(\n (label, col) =>\n html` <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n style=\"position:relative;overflow:hidden;\"\n >\n ${label}\n <div\n style=\"position:absolute;top:0;right:0;width:5px;height:100%;cursor:col-resize;user-select:none;background:transparent;\"\n @pointerdown=${(e: PointerEvent) =>\n this._onEvtColResizeStart(e, col)}\n @pointermove=${(e: PointerEvent) =>\n this._onEvtColResizeMove(e)}\n @pointerup=${() => this._onEvtColResizeEnd()}\n @pointercancel=${() => this._onEvtColResizeEnd()}\n ></div>\n </th>`,\n )}\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 isFailedRunEvent =\n failedRunEventId !== undefined &&\n event.id === failedRunEventId;\n const rowBg = isFailedRunEvent\n ? \"bg-rose-50\"\n : index % 2 === 0\n ? \"bg-white\"\n : \"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 data-inspector-event-id=${event.id}\n data-cpk-failed-run-event=${\n isFailedRunEvent ? event.id : undefined\n }\n @click=${(clickEvent: Event) =>\n this.toggleRowExpansion(event.id, clickEvent)}\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 ${\n isExpanded ? \"\" : \"truncate max-w-xs\"\n }\"\n >\n ${\n isExpanded\n ? html`\n <div class=\"group relative\">\n ${renderHighlightedJsonBlock(extractedEvent)}\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 ${\n this.copiedEvents.has(event.id)\n ? \"bg-green-100 text-green-700\"\n : \"bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900\"\n }\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this.copyToClipboard(\n prettyEvent,\n event.id,\n e,\n );\n }}\n >\n ${\n this.copiedEvents.has(event.id)\n ? html`\n <span>✓ Copied</span>\n `\n : html`\n <span>Copy</span>\n `\n }\n </button>\n </div>\n `\n : inlineEvent\n }\n </td>\n </tr>\n `;\n })}\n </tbody>\n </table>\n </div>\n `;\n }\n\n return html`\n <div\n class=\"${\n embedded\n ? \"flex h-[28rem] min-h-[20rem] flex-col\"\n : \"flex h-full flex-col\"\n }\"\n >\n ${this.renderEventsToolbar(events, filteredEvents, {\n showAgentFilter: !embedded,\n })}\n <div class=\"min-h-0 flex-1 overflow-hidden\">${body}</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 handleEventAgentChange(event: Event): void {\n const target = event.target as HTMLSelectElement | null;\n const value = target?.value;\n if (!value) {\n return;\n }\n this.handleContextOptionSelect(value);\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 _onEvtColResizeStart(e: PointerEvent, col: number): void {\n e.preventDefault();\n e.stopPropagation();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n this._evtColResize = {\n col,\n startX: e.clientX,\n startW: this.evtColWidths[col] ?? 0,\n };\n }\n\n private _onEvtColResizeMove(e: PointerEvent): void {\n if (!this._evtColResize) return;\n const { col, startX, startW } = this._evtColResize;\n this.evtColWidths = this.evtColWidths.map((w, i) =>\n i === col ? Math.max(40, startW + (e.clientX - startX)) : w,\n );\n this.requestUpdate();\n }\n\n private _onEvtColResizeEnd(): void {\n this._evtColResize = null;\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 ${this.renderEventErrorBanner(\"tool\")}\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=\"cpk-agent-view flex flex-col gap-4 p-4 overflow-auto\">\n ${this.renderEventErrorBanner(\"tool\")}\n <!-- Agent Overview Card -->\n <div\n class=\"cpk-agent-overview rounded-lg border border-gray-200 bg-white p-4\"\n >\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 cpk-agent-icon\"\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 ${\n statusColors[status]\n } relative -translate-y-[2px]\"\n >\n <span\n class=\"h-1.5 w-1.5 rounded-full ${\n status === \"running\"\n ? \"bg-emerald-500 animate-pulse\"\n : status === \"error\"\n ? \"bg-rose-500\"\n : \"bg-gray-400\"\n }\"\n ></span>\n ${status.charAt(0).toUpperCase() + status.slice(1)}\n </span>\n </div>\n </div>\n ${\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 }\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 cpk-stat-card\"\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Current State</h4>\n </div>\n <div class=\"overflow-auto p-4\">\n ${\n this.hasRenderableState(state)\n ? renderHighlightedJsonBlock(state, { maxHeight: \"16rem\" })\n : html`\n <div\n class=\"flex h-12 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 }\n </div>\n </div>\n\n <!-- Current Messages Section -->\n <div class=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Current Messages</h4>\n </div>\n <div class=\"overflow-auto\">\n ${\n messages && messages.length > 0\n ? html`\n <div class=\"w-full text-xs\">\n <div class=\"cpk-agent-messages-head flex bg-gray-50\">\n <div\n class=\"w-40 shrink-0 px-4 py-2 font-medium text-gray-700\"\n >\n Role\n </div>\n <div class=\"flex-1 px-4 py-2 font-medium text-gray-700\">\n Content\n </div>\n </div>\n <div class=\"cpk-agent-messages-rows\">\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 const toolError = this.eventErrorDetails.tool;\n const isFailedResult =\n role === \"tool\" &&\n toolError?.toolCallId !== undefined &&\n toolError.toolCallId === msg.toolCallId;\n\n return html`\n <div\n class=${\n isFailedResult\n ? \"cpk-agent-message-row flex items-start bg-rose-50\"\n : \"cpk-agent-message-row flex items-start\"\n }\n data-cpk-failed-tool-result=${\n isFailedResult ? msg.toolCallId : nothing\n }\n >\n <div class=\"w-40 shrink-0 px-4 py-2\">\n <span\n class=\"inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${\n roleColors[role] || roleColors.unknown\n }\"\n >\n ${role}\n </span>\n </div>\n <div class=\"flex-1 px-4 py-2\">\n ${\n hasContent\n ? html`\n <!-- prettier-ignore -->\n <div class=\"whitespace-pre-wrap break-words text-gray-700\">${rawContent}</div>\n `\n : html`<div class=\"italic text-gray-400\">\n ${contentFallback}\n </div>`\n }\n ${\n role === \"assistant\" && toolCalls.length > 0\n ? this.renderToolCallDetails(toolCalls)\n : nothing\n }\n </div>\n </div>\n `;\n })}\n </div>\n </div>\n `\n : html`\n <div\n class=\"flex h-12 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 }\n </div>\n </div>\n\n ${this.renderAgentToolsSection(agentId)}\n\n <div class=\"cpk-section-card overflow-hidden\">\n <div class=\"cpk-section-header\">\n <h4>AG-UI Events</h4>\n </div>\n ${this.renderEventsTable({ embedded: true })}\n </div>\n </div>\n `;\n }\n\n private renderContextDropdown(iconRail = false) {\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 @pointerenter=${\n iconRail ? this.handleIconRailContextPointerEnter : nothing\n }\n @pointerleave=${\n iconRail ? this.handleIconRailContextPointerLeave : nothing\n }\n @focusin=${iconRail ? this.handleIconRailContextFocusIn : nothing}\n @focusout=${iconRail ? this.handleIconRailContextFocusOut : nothing}\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 aria-label=\"Select agent scope: ${selectedLabel}\"\n title=${selectedLabel}\n @pointerdown=${\n iconRail\n ? this.handleIconRailContextPointerDown\n : this.handleContextDropdownToggle\n }\n >\n <span\n class=\"inspector-context-dropdown-icon shrink-0\"\n aria-hidden=\"true\"\n >${this.renderIcon(\"Bot\")}</span\n >\n <span\n class=\"inspector-context-dropdown-label truncate flex-1 text-left\"\n >${selectedLabel}</span\n >\n <span\n class=\"inspector-context-dropdown-chevron shrink-0 text-gray-400\"\n >${this.renderIcon(\"ChevronDown\")}</span\n >\n </button>\n ${\n iconRail || 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 iconRail ? \" inspector-icon-rail-menu\" : \"\"\n }\"\n data-context-dropdown-root=\"true\"\n data-open=${this.contextMenuOpen ? \"true\" : \"false\"}\n aria-hidden=${this.contextMenuOpen ? \"false\" : \"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 ${\n option.key === this.selectedContext\n ? \"text-gray-900 font-medium\"\n : \"text-gray-600\"\n }\"\n >${option.label}</span\n >\n ${\n option.key === this.selectedContext\n ? html`<span class=\"text-gray-500\"\n >${this.renderIcon(\"Check\")}</span\n >`\n : nothing\n }\n </button>\n `,\n )}\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n /**\n * The Agent view is empty on \"All Agents\". Pick the agent that just failed\n * a tool, or the one with the most recent activity.\n */\n private applyEventErrorLanding(key: InspectorEventErrorSource): void {\n const error = this.eventErrorDetails[key];\n if (!error) {\n if (this.selectedMenu === \"agents\") {\n this.focusAgentForView();\n }\n return;\n }\n\n if (\n error.agentId &&\n this.contextOptions.some((option) => option.key === error.agentId)\n ) {\n this.selectedContext = error.agentId;\n } else if (this.selectedMenu === \"agents\") {\n this.focusAgentForView(error);\n }\n\n if (key === \"tool\" && error.toolCallId) {\n this.pendingScrollToToolCallId = error.toolCallId;\n return;\n }\n\n if (key === \"run\") {\n this.eventFilterText = \"\";\n this.eventTypeFilter = \"all\";\n const event = this.findLatestRunErrorEvent(error.agentId);\n if (!event) return;\n this.expandedRows.clear();\n this.expandedRows.add(event.id);\n this.pendingScrollToEventId = event.id;\n }\n }\n\n /**\n * Whether the landing view really carries the item the card points at.\n * Mirrors the two branches of `applyEventErrorLanding` that can bail out.\n */\n private hasEventErrorHighlight(key: InspectorEventErrorSource): boolean {\n const error = this.eventErrorDetails[key];\n if (!error) return false;\n if (key === \"tool\") return error.toolCallId !== undefined;\n if (key === \"run\") {\n return this.findLatestRunErrorEvent(error.agentId) !== undefined;\n }\n return false;\n }\n\n private findLatestRunErrorEvent(\n agentId?: string,\n ): InspectorEvent | undefined {\n const events =\n agentId && agentId !== \"all-agents\"\n ? (this.agentEvents.get(agentId) ?? [])\n : this.flattenedEvents;\n return events.find((event) => event.type === \"RUN_ERROR\");\n }\n\n private flushErrorLandingScroll(): void {\n const eventId = this.pendingScrollToEventId;\n if (eventId) {\n this.pendingScrollToEventId = null;\n const row = Array.from(\n this.activeRoot.querySelectorAll<HTMLElement>(\n \"[data-inspector-event-id]\",\n ),\n ).find((candidate) => candidate.dataset.inspectorEventId === eventId);\n row?.scrollIntoView?.({ block: \"center\" });\n }\n\n const toolCallId = this.pendingScrollToToolCallId;\n if (toolCallId) {\n this.pendingScrollToToolCallId = null;\n const escaped = escapeSelectorValue(toolCallId);\n const card =\n this.activeRoot.querySelector<HTMLElement>(\n `[data-cpk-failed-tool-call=\"${escaped}\"]`,\n ) ??\n this.activeRoot.querySelector<HTMLElement>(\n `[data-cpk-failed-tool-result=\"${escaped}\"]`,\n );\n card?.scrollIntoView?.({ block: \"center\" });\n }\n }\n\n /**\n * The Agent view is empty on \"All Agents\". Pick the agent that just failed\n * a tool, or the one with the most recent activity.\n */\n private focusAgentForView(error?: InspectorEventErrorDetails): void {\n const agentOptions = this.contextOptions.filter(\n (opt) => opt.key !== \"all-agents\",\n );\n if (agentOptions.length === 0) return;\n\n const errorAgentId = error?.agentId;\n if (\n errorAgentId &&\n agentOptions.some((option) => option.key === errorAgentId)\n ) {\n this.selectedContext = errorAgentId;\n return;\n }\n\n if (this.selectedContext !== \"all-agents\") return;\n\n const mostRecent = agentOptions.reduce<{\n key: string;\n ts: number;\n } | null>((best, opt) => {\n const ts = this.getAgentStats(opt.key).lastActivity ?? -1;\n return best === null || ts > best.ts ? { key: opt.key, ts } : best;\n }, null);\n this.selectedContext = mostRecent ? mostRecent.key : agentOptions[0]!.key;\n }\n\n private handleMenuSelect(key: MenuKey): void {\n if (!this.menuItems.some((item) => item.key === key)) {\n return;\n }\n\n const previousMenu = this.selectedMenu;\n this.pendingPersistedMenu = null;\n this.briefingRestoreMenu = null;\n this.selectedMenu = key;\n this.settingsOpen = false;\n this.lastSelectedMenuByGroup[getGroupForMenu(key)] = key;\n\n // If leaving the agents view with multiple agents registered, restore\n // \"all-agents\" so the Events tab isn't silently filtered to one agent.\n if (previousMenu === \"agents\" && key !== \"agents\") {\n const agentCount = this.contextOptions.filter(\n (opt) => opt.key !== \"all-agents\",\n ).length;\n if (agentCount > 1) {\n this.selectedContext = \"all-agents\";\n }\n }\n\n // Deliberately NOT applying an event error's landing here. A landing is an\n // arrival, not a passing-through: it selects the failed agent, clears the\n // event filters and re-expands the failed row, which is help when the\n // reader came *because* of that error and vandalism when they did not.\n // Event-error details outlive being read on purpose, so the how-to-fix\n // card survives while it is being read — which means running this on every\n // visit resets the reader's own filters and agent scope for the rest of\n // the session, and silently undoes the `all-agents` restore eight lines\n // above. The three arrivals that *are* landings keep it: pressing the\n // launcher (`openInspector`), pressing the card (`refocusEventErrorLanding`)\n // and an error arriving while its view is already open (`armEventError`).\n\n if (key === \"threads\") {\n if (previousMenu !== \"threads\" && !this.core?.telemetryDisabled) {\n trackThreadsTabClicked(this.getThreadsTelemetryProps());\n }\n this.autoSelectLatestThread();\n }\n\n if (key === \"playground\" && !this.playgroundAgent) {\n this.startPlaygroundSession(false);\n }\n\n if (key === \"memories\") {\n this.learningSupported = Boolean(this.core?.inspectorLearning);\n if (previousMenu !== \"memories\" || this.learningSnapshot === null) {\n void this.refreshLearningSnapshot({\n preserve: previousMenu === \"memories\",\n });\n }\n if (previousMenu !== \"memories\" && !this.core?.telemetryDisabled) {\n trackMemoriesTabClicked(this.getMemoriesTelemetryProps());\n }\n } else if (previousMenu === \"memories\") {\n this.learningViewedState = null;\n this.cancelLearningPoll();\n this.cancelLearningRequest();\n }\n\n if (key === \"home\" && previousMenu !== \"home\") {\n void this.refreshLearningSnapshot({ preserve: true });\n this.homeViewedThisOpen = false;\n }\n\n if (key === \"ag-ui-events\" || key === \"agents\") {\n const keepErrorLanding =\n this.pendingScrollToEventId !== null ||\n this.pendingScrollToToolCallId !== null;\n if (!keepErrorLanding) {\n requestAnimationFrame(() => {\n const scroller = this.activeRoot.querySelector(\"#cpk-main-scroll\");\n if (scroller) scroller.scrollTop = 0;\n });\n }\n }\n\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private handleContextDropdownToggle(event: PointerEvent): void {\n event.preventDefault();\n event.stopPropagation();\n this.layoutMenuOpen = false;\n this.contextMenuOpen = !this.contextMenuOpen;\n this.requestUpdate();\n }\n\n private clearIconRailContextCloseTimer(): void {\n if (this.iconRailContextCloseTimer === null) {\n return;\n }\n clearTimeout(this.iconRailContextCloseTimer);\n this.iconRailContextCloseTimer = null;\n }\n\n /** Expand the icon-rail agent scope on hover while preserving keyboard access. */\n private handleIconRailContextPointerEnter = (event: PointerEvent): void => {\n if (event.pointerType === \"touch\") {\n return;\n }\n this.clearIconRailContextCloseTimer();\n if (this.contextMenuOpen) {\n return;\n }\n this.layoutMenuOpen = false;\n this.contextMenuOpen = true;\n this.requestUpdate();\n };\n\n private handleIconRailContextPointerLeave = (): void => {\n if (!this.contextMenuOpen) {\n return;\n }\n this.clearIconRailContextCloseTimer();\n this.iconRailContextCloseTimer = setTimeout(() => {\n this.iconRailContextCloseTimer = null;\n this.contextMenuOpen = false;\n this.requestUpdate();\n }, 180);\n };\n\n private handleIconRailContextPointerDown = (event: PointerEvent): void => {\n // A hover-only rail still needs to be operable on touch devices.\n if (event.pointerType === \"touch\") {\n this.handleContextDropdownToggle(event);\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n };\n\n private handleIconRailContextFocusIn = (): void => {\n this.clearIconRailContextCloseTimer();\n if (this.contextMenuOpen) {\n return;\n }\n this.layoutMenuOpen = false;\n this.contextMenuOpen = true;\n this.requestUpdate();\n };\n\n private handleIconRailContextFocusOut = (event: FocusEvent): void => {\n const nextFocus = event.relatedTarget;\n if (\n nextFocus instanceof Node &&\n (event.currentTarget as HTMLElement).contains(nextFocus)\n ) {\n return;\n }\n this.handleIconRailContextPointerLeave();\n };\n\n private handleContextOptionSelect(key: string): void {\n if (!this.contextOptions.some((option) => option.key === key)) {\n return;\n }\n\n this.clearIconRailContextCloseTimer();\n if (this.selectedContext !== key) {\n this.selectedContext = key;\n this.expandedRows.clear();\n this.autoSelectLatestThread();\n if (this.selectedMenu === \"playground\") {\n this.startPlaygroundSession(false);\n } else if (this.isLearningStatusVisible()) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\n }\n\n this.contextMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private renderCapabilitiesView() {\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 const toolRows = buildCapabilityRows(\n this._core as unknown as CapabilityToolSource,\n );\n const catalog = this._core.catalogComponents ?? [];\n const hasCatalog = catalog.length > 0;\n\n if (toolRows.length === 0 && !hasCatalog) {\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(\"SlidersHorizontal\")}\n </div>\n <p class=\"text-sm text-gray-600\">No capabilities registered</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Frontend tools and A2UI catalog components will appear here once\n they are registered on the CopilotKit core.\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 <p class=\"text-xs text-gray-500\">\n Toggle a capability off to omit it from what the agent sees. This\n is a client-side experimentation surface and takes effect\n immediately.\n </p>\n </div>\n\n ${\n toolRows.length > 0\n ? html`\n <div class=\"mt-4 space-y-2\">\n <h3 class=\"text-sm text-slate-500\">Frontend tools</h3>\n <div class=\"space-y-2\">\n ${toolRows.map((row) => this.renderCapabilityRow(row))}\n </div>\n </div>\n `\n : nothing\n }\n ${\n hasCatalog\n ? html`\n <div class=\"mt-6 space-y-2\">\n <h3 class=\"text-sm text-slate-500\">\n A2UI catalog components\n </h3>\n <div class=\"space-y-2\">\n ${catalog.map((component) =>\n this.renderCapabilityRow({\n key: component.name,\n name: component.name,\n description: component.description,\n enabled: this._core!.isCatalogComponentEnabled(\n component.name,\n ),\n }),\n )}\n </div>\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private renderCapabilityRow(row: CapabilityToolRow) {\n // Frontend-tool keys are always `${agentId}:${name}` (agentId may be \"\"),\n // so they contain a \":\"; catalog keys are the bare component name.\n const isTool = row.key.includes(\":\");\n return html`\n <div\n class=\"flex items-center justify-between gap-3 rounded-lg border border-gray-200 bg-white px-4 py-3\"\n >\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex items-center gap-2\">\n <span class=\"font-mono text-sm font-semibold text-gray-900\"\n >${row.name}</span\n >\n ${\n row.agentId\n ? html`<span\n class=\"inline-flex items-center gap-1 text-xs text-gray-500\"\n >\n ${this.renderIcon(\"Bot\")}<span class=\"font-mono\"\n >${row.agentId}</span\n >\n </span>`\n : nothing\n }\n </div>\n ${\n row.description\n ? html`<p class=\"mt-1 text-xs text-gray-600\">${row.description}</p>`\n : nothing\n }\n </div>\n ${this.renderCapabilitySwitch(row.enabled, () =>\n isTool\n ? this.handleToggleTool(row)\n : this.handleToggleCatalogComponent(row.name),\n )}\n </div>\n `;\n }\n\n private renderCapabilitySwitch(enabled: boolean, onToggle: () => void) {\n const track = enabled ? \"bg-emerald-500\" : \"bg-gray-300\";\n const knob = enabled ? \"translate-x-4\" : \"translate-x-0.5\";\n return html`\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked=${enabled ? \"true\" : \"false\"}\n class=\"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-300 ${track}\"\n @click=${onToggle}\n >\n <span\n class=\"inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${knob}\"\n ></span>\n </button>\n `;\n }\n\n private handleToggleTool(row: CapabilityToolRow): void {\n if (!this._core) return;\n const next = !row.enabled;\n // A1 contract: setToolEnabled(name, enabled, agentId?). Pass agentId only\n // when the tool is agent-scoped so global tools toggle globally.\n this._core.setToolEnabled(row.name, next, row.agentId);\n this._capabilitiesVersion += 1;\n this.requestUpdate();\n }\n\n private handleToggleCatalogComponent(name: string): void {\n if (!this._core) return;\n const next = !this._core.isCatalogComponentEnabled(name);\n this._core.setCatalogComponentEnabled(name, next);\n this._capabilitiesVersion += 1;\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 ${\n typeColors[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 ${\n schema.properties.length > 0\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span\n >${schema.properties.length}\n parameter${\n schema.properties.length !== 1 ? \"s\" : \"\"\n }</span\n >\n `\n : nothing\n }\n </div>\n ${\n tool.description\n ? html`<p class=\"mt-2 text-xs text-gray-600\">\n ${tool.description}\n </p>`\n : nothing\n }\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${\n isExpanded ? \"rotate-180\" : \"\"\n }\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${\n isExpanded\n ? html`\n <div class=\"border-t border-gray-200 bg-gray-50/50 px-4 py-3\">\n ${\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 ${\n prop.required\n ? html`\n <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 `\n : html`\n <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 `\n }\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 }\n </div>\n </div>\n ${\n prop.description\n ? html`<p class=\"mt-1 text-xs text-gray-600\">\n ${prop.description}\n </p>`\n : nothing\n }\n ${\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 }\n ${\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 }\n </div>\n `,\n )}\n </div>\n `\n : html`\n <div class=\"flex items-center justify-center py-4 text-xs text-gray-500\">\n <span>No parameters defined</span>\n </div>\n `\n }\n </div>\n `\n : nothing\n }\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 ${\n hasValue\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span class=\"truncate\">${valuePreview}</span>\n `\n : nothing\n }\n </div>\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${\n isExpanded ? \"rotate-180\" : \"\"\n }\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${\n isExpanded\n ? html`\n <div class=\"border-t border-gray-200 px-4 py-3\">\n <div class=\"mb-3\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <h5 class=\"text-xs font-semibold text-gray-700\">ID</h5>\n <button\n type=\"button\"\n class=\"cpk-copy-btn\"\n @click=${(e: Event) => {\n e.stopPropagation();\n void this.copyContextValue(id, `${id}:id`, e);\n }}\n >\n ${\n this.copiedContextItems.has(`${id}:id`)\n ? \"Copied\"\n : \"Copy\"\n }\n </button>\n </div>\n <code\n class=\"block min-w-0 truncate font-mono text-xs font-medium text-gray-800\"\n >${id}</code\n >\n </div>\n ${\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 type=\"button\"\n class=\"cpk-copy-btn\"\n @click=${(e: Event) => {\n e.stopPropagation();\n void this.copyContextValue(context.value, id, e);\n }}\n >\n ${\n this.copiedContextItems.has(id)\n ? \"Copied\"\n : \"Copy JSON\"\n }\n </button>\n </div>\n ${renderHighlightedJsonBlock(context.value, {\n maxHeight: \"180px\",\n })}\n `\n : html`\n <div class=\"flex items-center justify-center py-4 text-xs text-gray-500\">\n <span>No value available</span>\n </div>\n `\n }\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private getContextValuePreview(value: unknown): string {\n const parsed = coerceJsonValue(value);\n\n if (parsed === undefined || parsed === null) {\n return \"—\";\n }\n\n if (typeof parsed === \"string\") {\n return parsed.length > 50 ? `${parsed.slice(0, 50)}...` : parsed;\n }\n\n if (typeof parsed === \"number\" || typeof parsed === \"boolean\") {\n return String(parsed);\n }\n\n if (Array.isArray(parsed)) {\n return `Array(${parsed.length})`;\n }\n\n if (typeof parsed === \"object\") {\n const keys = Object.keys(parsed);\n return `Object with ${keys.length} key${keys.length !== 1 ? \"s\" : \"\"}`;\n }\n\n if (typeof parsed === \"function\") {\n return \"Function\";\n }\n\n return String(parsed);\n }\n\n private getToolsForAgent(agentId: string): InspectorToolDefinition[] {\n this.refreshToolsSnapshot();\n return this.cachedTools.filter(\n (tool) => !tool.agentId || tool.agentId === agentId,\n );\n }\n\n private renderAgentToolsSection(agentId: string) {\n const tools = this.getToolsForAgent(agentId);\n\n return html`\n <div class=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Registered Tools</h4>\n </div>\n <div class=\"overflow-auto p-4\">\n ${\n tools.length > 0\n ? html`<div class=\"space-y-3\">\n ${tools.map((tool) => this.renderToolCard(tool))}\n </div>`\n : html`\n <div\n class=\"flex h-12 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(\"Hammer\")}</span\n >\n <span>No tools registered</span>\n </div>\n </div>\n `\n }\n </div>\n </div>\n `;\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 const pretty = this.formatStateForDisplay(coerceJsonValue(value));\n return pretty.length > 0 ? pretty : String(value);\n }\n\n private async copyContextValue(\n value: unknown,\n contextId: string,\n event?: Event,\n ): Promise<void> {\n const clipboard = this.getClipboard(event);\n if (!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 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 && !this.layoutMenuOpen) {\n return;\n }\n\n const path = event.composedPath();\n const clickedDropdown = path.some((node) => {\n const candidate = node as {\n getAttribute?: (name: string) => string | null;\n };\n return (\n typeof candidate.getAttribute === \"function\" &&\n candidate.getAttribute(\"data-context-dropdown-root\") === \"true\"\n );\n });\n const clickedLayoutMenu = path.some((node) => {\n const candidate = node as {\n getAttribute?: (name: string) => string | null;\n };\n return (\n typeof candidate.getAttribute === \"function\" &&\n candidate.getAttribute(\"data-inspector-window-layout-root\") === \"true\"\n );\n });\n\n let changed = false;\n if (this.contextMenuOpen && !clickedDropdown) {\n this.contextMenuOpen = false;\n changed = true;\n }\n if (this.layoutMenuOpen && !clickedLayoutMenu) {\n this.layoutMenuOpen = false;\n changed = true;\n }\n if (changed) {\n this.requestUpdate();\n }\n };\n\n private toggleRowExpansion(eventId: string, event?: Event): void {\n // Don't toggle if user is selecting text\n const target = event?.currentTarget;\n const ownerDocument =\n target && \"ownerDocument\" in target\n ? (target as Node).ownerDocument\n : this.ownerDocument;\n const selection = ownerDocument?.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 // ── Launcher signals ────────────────────────────────────────────────────\n\n /** Whether a given subject currently has something to say. */\n private isSignalArmed(key: LauncherSignalKey): boolean {\n if (isWiringErrorKey(key)) return this.errorSignalArmed[key];\n if (isEventErrorKey(key)) return this.eventErrorArmed[key];\n return this.newsSignalArmed;\n }\n\n /**\n * The signal that owns the single launcher dot, or null when the launcher is\n * quiet. Precedence rather than replacement: a suppressed signal stays armed\n * and takes the dot as soon as the higher-priority one clears, and its own\n * navigation marker is visible the whole time.\n */\n private getActiveLauncherSignal(): LauncherSignalKey | null {\n for (const key of LAUNCHER_SIGNAL_PRIORITY_ORDER) {\n if (this.isSignalArmed(key)) return key;\n }\n return null;\n }\n\n /**\n * The marker a navigation entry carries, or null for an unmarked entry.\n *\n * Markers are independent of the launcher's single dot, so a suppressed\n * signal is never actually hidden once the panel is open. They also render\n * on the entry that is *currently selected*: for the news signal that never\n * mattered, because its marker clears as soon as the view renders, but a\n * state mirror stays true while it is being read and suppressing it on the\n * active entry would make it reappear on navigating away.\n */\n private getNavigationSignalFor(\n key: MenuKey,\n ): LauncherSignalDefinition | null {\n for (const signalKey of LAUNCHER_SIGNAL_PRIORITY_ORDER) {\n const signal = LAUNCHER_SIGNALS[signalKey];\n if (signal.markerTarget !== key) continue;\n if (!this.isSignalArmed(signalKey)) continue;\n // The announcement's marker waits for the feed, so a still-loading feed\n // cannot mark an entry that has nothing to show yet.\n if (signalKey === NEWS_SIGNAL_ID && !this.announcementLoaded) continue;\n return signal;\n }\n return null;\n }\n\n /** Whether a wiring error source is currently red. */\n private hasArmedErrorSignal(): boolean {\n return WIRING_ERROR_KEYS.some((source) => this.errorSignalArmed[source]);\n }\n\n private armEventErrorFromCode(\n code: CopilotKitCoreErrorCode,\n message: string,\n context?: Record<string, unknown>,\n ): void {\n const key = eventErrorKeyForCode(code);\n if (key === null) return;\n const agentId =\n typeof context?.agentId === \"string\" && context.agentId.length > 0\n ? context.agentId\n : undefined;\n const toolName =\n typeof context?.toolName === \"string\" && context.toolName.length > 0\n ? context.toolName\n : undefined;\n const toolCallId =\n typeof context?.toolCallId === \"string\" && context.toolCallId.length > 0\n ? context.toolCallId\n : undefined;\n this.armEventError(key, message, { agentId, toolName, toolCallId });\n }\n\n private armEventError(\n key: InspectorEventErrorSource,\n message: string,\n extras: {\n agentId?: string;\n toolName?: string;\n toolCallId?: string;\n } = {},\n ): void {\n this.eventErrorDetails[key] = { message, ...extras };\n const wasArmed = this.eventErrorArmed[key];\n this.eventErrorArmed[key] = true;\n if (!wasArmed) {\n this.startSignalPulse(key);\n }\n if (\n this.isOpen &&\n !this.settingsOpen &&\n this.selectedMenu === LAUNCHER_SIGNALS[key].landingTarget\n ) {\n this.applyEventErrorLanding(key);\n }\n this.requestUpdate();\n }\n\n private clearEventError(key: InspectorEventErrorSource): void {\n if (!this.eventErrorArmed[key]) return;\n this.eventErrorArmed[key] = false;\n this.errorSignalViewedSources.delete(key);\n this.retireSignal(key);\n this.requestUpdate();\n }\n\n private clearAllEventErrors(): void {\n for (const key of EVENT_ERROR_KEYS) {\n this.eventErrorDetails[key] = null;\n if (!this.eventErrorArmed[key]) continue;\n this.eventErrorArmed[key] = false;\n this.retireSignal(key);\n }\n }\n\n /**\n * An event error is unread until its landing view is actually on screen.\n * Opening the Inspector for a different leaf must not burn it.\n */\n private maybeCompleteEventErrorView(): void {\n if (!this.isOpen || this.settingsOpen) return;\n for (const key of EVENT_ERROR_KEYS) {\n if (!this.eventErrorArmed[key]) continue;\n if (this.selectedMenu !== LAUNCHER_SIGNALS[key].landingTarget) continue;\n this.clearEventError(key);\n }\n }\n\n private isReducedMotionPreferred(): boolean {\n return (\n typeof window !== \"undefined\" &&\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches === true\n );\n }\n\n // ── What's new launcher signal ──────────────────────────────────────────\n\n private armNewsSignal(options: { pulse: boolean }): void {\n const wasArmed = this.newsSignalArmed;\n this.newsSignalArmed = true;\n if (options.pulse) {\n this.startSignalPulse(NEWS_SIGNAL_ID);\n } else if (!wasArmed) {\n this.requestUpdate();\n }\n }\n\n private clearNewsSignal(): void {\n if (!this.newsSignalArmed) return;\n this.newsSignalArmed = false;\n if (this.announcementTimestamp) {\n saveAnnouncementReadTimestamp(this.announcementTimestamp);\n }\n this.retireSignal(NEWS_SIGNAL_ID);\n this.requestUpdate();\n }\n\n // ── The beat ────────────────────────────────────────────────────────────\n\n /**\n * Requests one beat for a signal, running it now or deferring it.\n *\n * There is a single pending slot and five reasons a beat cannot land. All\n * five are the same situation — \"cannot land now, run later\" — and treating\n * them alike is the point: three separate behaviours for one situation would\n * not survive a third signal.\n *\n * Reason 4 is not cosmetic. Starting a beat while one runs does not restart\n * the animation, because the attribute it binds to does not change value and\n * the pseudo-element selectors match on attribute *presence*; the running\n * beat would merely change colour mid-flight. A failure that arms during an\n * announcement beat must wait for that beat to end, or it would run only as\n * its final fraction.\n *\n * A failure's beat is followed by a pill, and the whole 3.4-second gesture\n * holds this one slot for its full duration. That is not a second scheduling\n * concept: reason 4 already says \"another beat is running\", and a gesture is\n * simply a longer beat.\n */\n private startSignalPulse(key: LauncherSignalKey): void {\n const deferred =\n // 1. The panel is open, so there is no visible launcher. Pop-out is the\n // same case: the host page renders only a portal anchor.\n this.isOpen ||\n // 2. The developer deliberately hid the entire Inspector for a while.\n this.isInspectorDismissed ||\n // 3. Nobody is looking.\n (typeof document !== \"undefined\" &&\n document.visibilityState !== \"visible\") ||\n // 4. Another beat — or the pill that follows it — is already running.\n (this.gestureSlotSignal !== null && this.gestureSlotSignal !== key) ||\n // 5. Another signal currently owns the dot.\n this.getActiveLauncherSignal() !== key;\n\n if (deferred) {\n // One slot, and the more urgent beat keeps it. A lower-priority beat must\n // not evict a nudge about something worse — and it would fail the\n // re-check on the way out anyway, because it is not the active signal.\n // The evicted beat is not lost for good: its once-per-subject token is\n // still unspent, so it is offered again the next time it arms.\n const pending = this.pendingPulseSignal;\n if (\n pending === null ||\n LAUNCHER_SIGNALS[key].priority >= LAUNCHER_SIGNALS[pending].priority\n ) {\n this.pendingPulseSignal = key;\n }\n this.requestUpdate();\n return;\n }\n\n this.stopSignalPulse();\n this.pendingPulseSignal = null;\n this.pulsingSignal = key;\n // The once-per-subject token is written HERE, where the beat actually\n // runs — never when a signal arms. Spending it on arming would burn a\n // deferred beat unfired.\n if (isWiringErrorKey(key)) {\n this.errorBeatSpent = true;\n } else if (this.announcementTimestamp && key === NEWS_SIGNAL_ID) {\n saveAnnouncementPulsedTimestamp(this.announcementTimestamp);\n }\n this.beginGestureTail(key);\n this.requestUpdate();\n if (typeof window === \"undefined\") return;\n this.pulseTimeoutId = setTimeout(() => {\n this.pulseTimeoutId = null;\n this.pulsingSignal = null;\n this.requestUpdate();\n // The beat says *here*; now the pill says *this*.\n if (this.gestureSignal === key && this.pillPhase === \"closed\") {\n this.openPill();\n return;\n }\n // Nothing follows the beat: either this signal opens no pill, or there\n // was no room for one, so the gesture ends with it.\n if (this.gestureSignal === key) {\n this.endGesture();\n return;\n }\n // Reason 4 has just cleared.\n this.flushPendingSignalPulse();\n }, LAUNCHER_SIGNALS[key].cadence);\n }\n\n private stopSignalPulse(): void {\n if (this.pulseTimeoutId !== null) {\n clearTimeout(this.pulseTimeoutId);\n this.pulseTimeoutId = null;\n }\n this.pulsingSignal = null;\n }\n\n /**\n * Runs a deferred beat if it can land now, and drops it if its reason to\n * exist has gone: a nudge about a problem that no longer exists is worse\n * than no nudge at all.\n */\n private flushPendingSignalPulse(): void {\n const key = this.pendingPulseSignal;\n if (key === null) return;\n if (!this.isSignalArmed(key)) {\n this.pendingPulseSignal = null;\n this.requestUpdate();\n return;\n }\n this.startSignalPulse(key);\n }\n\n /**\n * Drops a signal's gesture, pending or running, when the signal goes quiet.\n *\n * The pill closes early: it states a condition, and the condition has\n * stopped being true. The beat is left to finish, because a beat asserts\n * nothing — it says *here*, and \"here\" is still true.\n */\n private retireSignal(key: LauncherSignalKey): void {\n if (this.pendingPulseSignal === key) this.pendingPulseSignal = null;\n if (this.gestureSignal === key) this.closePillEarly();\n // A suppressed signal may now own the dot.\n this.flushPendingSignalPulse();\n }\n\n // ── The pill ────────────────────────────────────────────────────────────\n\n /**\n * The signal holding the single gesture slot: a beat in flight, or the pill\n * and spoken sentence that follow it. One slot, not two — see reason 4 in\n * `startSignalPulse`.\n */\n private get gestureSlotSignal(): LauncherSignalKey | null {\n return this.pulsingSignal ?? this.gestureSignal;\n }\n\n /**\n * Opens the gesture's tail alongside the beat, for a signal that carries a\n * pill. The pill is rendered immediately — clipped to nothing, so it shows\n * nothing — because its full width has to be on the page before the room\n * either side of the launcher can be measured.\n *\n * A signal with no pill label gets no tail at all, so the announcement's\n * gesture is exactly the beat it has always been.\n */\n private beginGestureTail(key: LauncherSignalKey): void {\n this.cancelPillTimeout();\n if (LAUNCHER_SIGNALS[key].pillLabel === undefined) {\n this.gestureSignal = null;\n this.pillPhase = null;\n this.pillDirection = null;\n return;\n }\n this.gestureSignal = key;\n this.pillPhase = \"closed\";\n this.pillDirection = null;\n this.closeLauncherHud();\n }\n\n /**\n * Chooses the side, or suppresses the pill, from the room actually available\n * at gesture start. Measured once, from the DOM, because the launcher is\n * draggable and its position persists: a reader who parked it near the left\n * edge would otherwise get a permanently truncated pill.\n *\n * Where neither side has room there is no pill at all rather than a cut-off\n * one — the dot and the beat still fire, so the signal is intact and only\n * the label is lost. Constraining where the reader may drag the control to\n * protect this animation was considered and rejected: the page is theirs.\n */\n private resolvePillDirection(): void {\n if (this.pillDirection !== null || this.pillPhase === null) return;\n const wrapper = this.activeRoot.querySelector<HTMLElement>(\n \".console-button-wrapper\",\n );\n const button = wrapper?.querySelector<HTMLElement>(\".console-button\");\n const pill = wrapper?.querySelector<HTMLElement>(\".cpk-launcher-pill\");\n if (!button || !pill || typeof window === \"undefined\") return;\n\n const mark = button.getBoundingClientRect();\n // A clip changes what is painted, never the layout box, so this is the\n // pill's full width whichever phase it is in.\n const overhang = Math.max(\n 0,\n pill.getBoundingClientRect().width - mark.width,\n );\n const viewportWidth = window.innerWidth;\n\n if (overhang === 0) {\n // Nothing extends past the mark, so there is nothing to fit.\n this.setPillOutcome(\"left\");\n return;\n }\n if (mark.left - overhang >= EDGE_MARGIN) {\n // Leftwards is the natural direction: away from the launcher's own edge.\n this.setPillOutcome(\"left\");\n return;\n }\n if (mark.right + overhang <= viewportWidth - EDGE_MARGIN) {\n this.setPillOutcome(\"right\");\n return;\n }\n this.setPillOutcome(null);\n }\n\n /** Records the measurement's verdict, and drops the pill when it is null. */\n private setPillOutcome(direction: LauncherPillDirection | null): void {\n if (direction === null) {\n this.pillPhase = null;\n this.pillDirection = null;\n this.pillOutcome = \"suppressed\";\n this.requestUpdate();\n return;\n }\n this.pillDirection = direction;\n this.pillOutcome = \"shown\";\n this.requestUpdate();\n }\n\n /** Runs the pill's three phases in series once the beat has finished. */\n private openPill(): void {\n // Normally already measured during the beat; measured here too so the\n // gesture cannot depend on a render having happened in between.\n this.resolvePillDirection();\n if (this.pillPhase === null) {\n // The measurement found no room after all.\n this.endGesture();\n return;\n }\n this.advancePill(\"opening\", ERROR_GESTURE_MS.open, () => {\n this.advancePill(\"holding\", ERROR_GESTURE_MS.hold, () => {\n this.advancePill(\"closing\", ERROR_GESTURE_MS.close, () => {\n this.endGesture();\n });\n });\n });\n }\n\n private advancePill(\n phase: LauncherPillPhase,\n duration: number,\n next: () => void,\n ): void {\n this.cancelPillTimeout();\n this.pillPhase = phase;\n this.requestUpdate();\n if (typeof window === \"undefined\") return;\n this.pillTimeoutId = setTimeout(() => {\n this.pillTimeoutId = null;\n next();\n }, duration);\n }\n\n /**\n * Closes the pill before its hold is out, because the failure it names has\n * been fixed. A pill that has not opened yet is simply dropped; the beat is\n * never cut short.\n */\n private closePillEarly(): void {\n // No pill in this gesture — there was no room for one — so the tail is\n // only the spoken sentence, and it ends here.\n if (this.pillPhase === null) {\n this.endGesture();\n return;\n }\n // Already on its way out.\n if (this.pillPhase === \"closing\") return;\n // Still inside the beat, so nothing has been asserted on screen yet: the\n // pill is dropped rather than closed, and the beat runs on to its end.\n if (this.pillPhase === \"closed\") {\n this.pillPhase = null;\n this.requestUpdate();\n return;\n }\n this.advancePill(\"closing\", ERROR_GESTURE_MS.close, () => {\n this.endGesture();\n });\n }\n\n /** Releases the slot and leaves the plain mark with its dot behind. */\n private endGesture(): void {\n this.cancelGestureTail();\n this.requestUpdate();\n this.flushPendingSignalPulse();\n }\n\n /**\n * Drops the gesture's tail outright, with no closing animation, for the\n * cases where the launcher itself has gone: the panel opened over it, or the\n * element was removed from the page.\n */\n private cancelGestureTail(): void {\n this.cancelPillTimeout();\n this.gestureSignal = null;\n this.pillPhase = null;\n this.pillDirection = null;\n }\n\n private cancelPillTimeout(): void {\n if (this.pillTimeoutId !== null) {\n clearTimeout(this.pillTimeoutId);\n this.pillTimeoutId = null;\n }\n }\n\n // ── Error signal ────────────────────────────────────────────────────────\n\n /**\n * Whether each error source is currently broken.\n *\n * Only two *wiring* conditions qualify. App errors (runs, tools, memory)\n * are unread events on a different latch — they name themselves on the pill\n * and clear when their landing view is read. Notably absent from *this*\n * latch:\n *\n * - **A failed agent run.** A run is an event. It arms `run`, not this\n * state. The resting wiring dot must not stay red for the rest of a debug\n * hour.\n * - **The core error channel as a wiring source.** Handshake failure already\n * sets the connection state. Other codes arm `run` or `tool`.\n * - **Memory failures before Learning is live.** The memory store is lazy\n * because creating it opens a realtime connection. Once it exists, a load\n * failure arms `memory`.\n * - **Product states.** An unconfigured Intelligence and an unentitled\n * Memory plan are not defects. The signal fires only where wiring is\n * present and the call still fails — which for threads is guaranteed by\n * `_threadsErrorByAgent` only ever being written while the thread\n * endpoints are available.\n *\n * Known limitation: the runtime handshake runs once, on connect. A server\n * that dies *after* the page loaded leaves the connection state at connected\n * and raises nothing; the next page load re-runs the handshake and the\n * signal appears then. The signal reports the wiring state as last\n * established. Closing that gap means a re-probe in the core, which is a\n * runtime concern.\n */\n private isErrorSourceBroken(source: InspectorWiringErrorSource): boolean {\n if (source === \"connection\") {\n const state = this.getCoreStatusSummary().state;\n // The same derivation System Health reads, so the launcher dot is red\n // exactly when System Health says the runtime needs attention.\n if (runtimeConnectionNeedsAttention(state)) return true;\n // A reconnect is not a heal. Stay red through `connecting` so the\n // cards do not flash off between retries.\n return this.errorSignalArmed.connection && state === \"connecting\";\n }\n return this._threadsErrorByAgent.size > 0;\n }\n\n /**\n * Mirrors both error latches onto the live state. Called from `willUpdate`,\n * because every mutation of the underlying state already requests an update,\n * so the resting dot follows the state within the same render.\n */\n private evaluateErrorSignals(): void {\n const wasArmed = this.hasArmedErrorSignal();\n\n for (const source of WIRING_ERROR_KEYS) {\n const broken = this.isErrorSourceBroken(source);\n if (broken) {\n if (this.errorSignalArmed[source]) continue;\n // Arming is immediate, with no window a short failure has to outlive\n // first. That is a decision, not an omission, so here is what it costs\n // and what would change it.\n //\n // `threads` can genuinely flap: the list is refetched on events, at up\n // to one request per `THREAD_LIST_DEBOUNCE_MS`, so a failure followed\n // by a success plays a whole gesture for a blip that is already over.\n // The damage is bounded by machinery that is already here — one\n // pending-beat slot, and a running gesture defers the next — so the\n // ceiling is one gesture per gesture length, never a strobe. And the\n // dot is not lying while it is up: the fetch really did fail.\n //\n // `connection` cannot flap on its own today, because nothing retries\n // the handshake: it goes connecting → connected | error and then waits\n // for something to call connect() again. If a fix for the mid-session\n // gap above adds polling, re-read this: the `connecting` branch in\n // `isErrorSourceBroken` already holds the dot steady across retries,\n // so only genuinely intermittent connectivity would flap, which is\n // exactly what the dot is for.\n //\n // So: revisit if someone reports the launcher going red without a\n // lasting cause, and start with `threads`.\n this.errorSignalArmed[source] = true;\n continue;\n }\n if (!this.errorSignalArmed[source]) continue;\n this.errorSignalArmed[source] = false;\n this.errorSignalViewedSources.delete(source);\n this.retireSignal(source);\n }\n\n this.onErrorSignalsChanged(wasArmed);\n }\n\n /**\n * Applies the rising-edge rule after a latch changed.\n *\n * The beat fires on the transition from \"no failure\" to \"at least one\n * failure\", evaluated globally across the sources and never again while\n * anything is red — one root cause, one nudge.\n */\n private onErrorSignalsChanged(wasArmed: boolean): void {\n const isArmed = this.hasArmedErrorSignal();\n if (!isArmed) {\n // Nothing is red, so the next outage is a new outage — and gets its own\n // beat, its own pill and its own answer about whether there was room.\n this.errorBeatSpent = false;\n this.pillOutcome = null;\n return;\n }\n if (wasArmed || this.errorBeatSpent) return;\n const active = this.getActiveLauncherSignal();\n if (active !== null && isErrorSignalKey(active)) {\n this.startSignalPulse(active);\n }\n }\n\n /**\n * Records `oss.inspector.error_signal_viewed` once per source per outage,\n * when the dot is actually on screen.\n *\n * Unlike the announcement's launcher event this fires immediately rather\n * than waiting for the runtime handshake to report `telemetryDisabled`.\n * The held-queue would never drain for the connection source — a connection\n * failure means the handshake did not complete — so queuing would guarantee\n * zero data for the case this event exists to measure. `trackOpened` already\n * sends on the same terms. Both opt-out layers still gate it: the local\n * opt-out inside `track`, and the runtime's flag once it is known.\n */\n private maybeTrackErrorSignalViewed(): void {\n if (\n this.isOpen ||\n typeof document === \"undefined\" ||\n document.visibilityState !== \"visible\"\n ) {\n return;\n }\n const active = this.getActiveLauncherSignal();\n if (active === null || !isErrorSignalKey(active)) return;\n if (this.errorSignalViewedSources.has(active)) return;\n // Held until this outage's pill has either opened or been suppressed,\n // because `label` IS that answer and the launcher can be on screen a frame\n // before the room around it has been measured. A signal that declares no\n // pill has no answer to wait for.\n if (\n this.pillOutcome === null &&\n LAUNCHER_SIGNALS[active].pillLabel !== undefined\n ) {\n return;\n }\n if (this.core?.telemetryDisabled) return;\n this.errorSignalViewedSources.add(active);\n trackErrorSignalViewed({\n source: active,\n presentation: this.isReducedMotionPreferred()\n ? \"reduced_motion\"\n : \"animated\",\n // Whether this outage's pill actually opened. The design deliberately\n // leaves the no-room case silent, and a degradation whose frequency is\n // unknown is a degradation that gets argued about later. Two fixed\n // values, never free text.\n label: this.pillOutcome ?? \"suppressed\",\n });\n }\n\n private maybeTrackNewsSignalViewed(): void {\n if (\n !this.newsSignalArmed ||\n this.pulsingSignal !== NEWS_SIGNAL_ID ||\n this.isOpen ||\n typeof document === \"undefined\" ||\n document.visibilityState !== \"visible\"\n ) {\n return;\n }\n const id = this.announcementTimestamp;\n if (!id || this.viewedNewsSignalIds.has(id)) return;\n this.viewedNewsSignalIds.add(id);\n this.pendingNewsSignalViewed = {\n banner_id: id,\n surface: \"launcher\",\n presentation:\n typeof window !== \"undefined\" &&\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches\n ? \"reduced_motion\"\n : \"animated\",\n cta_label: this.announcementCtaLabel ?? undefined,\n };\n this.flushPendingWhatsNewTelemetry();\n }\n\n // ── What's new ─────────────────────────────────────────────────────────\n //\n // Built as a self-contained unit — its own render method, its own state,\n // and no dependency on the shape of today's two-level navigation — so the\n // planned sidebar restructuring can relocate it rather than rewrite it.\n\n /** Which of the three What's new states the feed currently supports. */\n private getWhatsNewState(): \"loading\" | \"empty\" | \"content\" {\n if (this.announcementHtml) return \"content\";\n return this.announcementLoaded ? \"empty\" : \"loading\";\n }\n\n /**\n * Which announcement surface is on screen right now, or null when the\n * announcement isn't visible. What's new is the only surface: an impression\n * requires the panel open, that view selected, and content actually\n * rendered — a loading state is not an impression.\n */\n private getVisibleBannerSurface(): WhatsNewSurface | null {\n if (!this.isOpen || this.settingsOpen) return null;\n if (this.selectedMenu !== WHATS_NEW_MENU_KEY) return null;\n return this.announcementHtml ? \"whats_new\" : null;\n }\n\n /**\n * The single condition that retires the news signal: What's new has\n * rendered *with content*.\n *\n * Deliberately not on panel open — the common reason to open the Inspector\n * is AG-UI events, and clearing there would burn a whole announcement\n * silently and turn \"viewed\" into \"opened the Inspector at some point\".\n * Deliberately not behind an acknowledge button, which is a dismiss button\n * under another name. And a loading state does not count, because the feed\n * is asynchronous and a reader who arrived early has seen nothing.\n *\n * The launcher dot and the navigation marker both read the same signal, so\n * the two can never disagree about whether something has been read.\n */\n private maybeCompleteWhatsNewView(): void {\n if (!this.getVisibleBannerSurface()) return;\n this.maybeTrackWhatsNewViewed();\n this.clearNewsSignal();\n }\n\n /**\n * Records a `whats_new_viewed` impression for whichever surface is\n * currently visible, once per announcement per surface.\n */\n private maybeTrackWhatsNewViewed(): void {\n const id = this.announcementTimestamp;\n if (!id) return;\n const surface = this.getVisibleBannerSurface();\n if (!surface) return;\n const key = `${id}:${surface}`;\n if (this.viewedBannerSurfaces.has(key)) return;\n if (this.pendingBannerViewed.length >= MAX_PENDING_BANNER_VIEWED) return;\n this.viewedBannerSurfaces.add(key);\n this.pendingBannerViewed.push({\n banner_id: id,\n surface,\n cta_label: this.announcementCtaLabel ?? undefined,\n });\n this.flushPendingWhatsNewTelemetry();\n }\n\n // Releases held notification telemetry once /info has answered, or discards\n // it when the runtime reports telemetry disabled.\n private flushPendingWhatsNewTelemetry(): void {\n if (\n this.pendingBannerViewed.length === 0 &&\n !this.pendingNewsSignalViewed\n ) {\n return;\n }\n if (this.core?.telemetryDisabled) {\n this.pendingBannerViewed = [];\n this.pendingNewsSignalViewed = null;\n return;\n }\n if (\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected\n ) {\n return;\n }\n const queued = this.pendingBannerViewed;\n this.pendingBannerViewed = [];\n for (const props of queued) trackWhatsNewViewed(props);\n if (this.pendingNewsSignalViewed) {\n const props = this.pendingNewsSignalViewed;\n this.pendingNewsSignalViewed = null;\n trackWhatsNewSignalViewed(props);\n }\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 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 cta_label?: 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 const ctaLabel =\n typeof data?.cta_label === \"string\" ? data.cta_label : null;\n\n if (!timestamp || !markdown) {\n throw new Error(\"Malformed announcement payload\");\n }\n\n this.announcementTimestamp = timestamp;\n this.announcementPreviewText = previewText ?? \"\";\n this.announcementMarkdown = markdown;\n this.announcementCtaLabel = ctaLabel;\n this.announcementHtml = await this.convertMarkdownToHtml(markdown);\n this.announcementLoaded = true;\n\n // The signal arms on a timestamp plus a body that actually renders —\n // anything else would produce a dot that What's new can never clear,\n // because clearing requires content. `previewText` does NOT gate it:\n // that was defensible while the text was the bubble's headline, but it\n // is now just the heading, and gating on it would mean an announcement\n // without preview text produced no dot at all.\n if (\n this.announcementHtml &&\n loadAnnouncementReadTimestamp() !== timestamp\n ) {\n this.armNewsSignal({\n pulse: loadAnnouncementPulsedTimestamp() !== timestamp,\n });\n }\n\n this.requestUpdate();\n } catch (error) {\n // Swallowing here would hide non-network failures (malformed JSON, the\n // explicit \"Malformed announcement payload\" throw above, exceptions\n // from `convertMarkdownToHtml`). At minimum, surface in the console so\n // a stale announcement is debuggable.\n console.warn(\"[CopilotKit Inspector] Failed to load announcement\", 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(\n this.isSafeAnnouncementHref(href ?? \"\")\n ? this.appendRefParam(href ?? \"\")\n : \"#\",\n );\n const titleAttr = title ? ` title=\"${this.escapeHtmlAttr(title)}\"` : \"\";\n return `<a href=\"${safeHref}\" target=\"_blank\" rel=\"noopener\"${titleAttr}>${text}</a>`;\n };\n renderer.html = (html) => escapeHtml(html);\n renderer.code = (code, lang) => {\n const safeLang = (lang ?? \"\").replace(/[^a-z0-9-]/gi, \"\");\n const langClass = safeLang ? ` class=\"language-${safeLang}\"` : \"\";\n const escaped = escapeHtml(code);\n const encoded = this.encodeBase64(code);\n return `<div class=\"announcement-code\"><pre><code${langClass}>${escaped}</code></pre><div class=\"announcement-code__copy-shield\"><button type=\"button\" class=\"announcement-code__copy\" data-copy=\"${encoded}\" aria-label=\"Copy code\">Copy</button></div></div>`;\n };\n return marked.parse(markdown, { renderer, async: false });\n }\n\n private isSafeAnnouncementHref(href: string): boolean {\n try {\n const url = new URL(\n href,\n typeof window !== \"undefined\"\n ? window.location.href\n : \"https://copilotkit.ai\",\n );\n return (\n url.protocol === \"http:\" ||\n url.protocol === \"https:\" ||\n url.protocol === \"mailto:\"\n );\n } catch {\n return false;\n }\n }\n\n private copyResetTimeouts = new WeakMap<HTMLButtonElement, number>();\n\n private encodeBase64(value: string): string {\n if (typeof window === \"undefined\" || typeof window.btoa !== \"function\") {\n return \"\";\n }\n // btoa only accepts Latin-1; round-trip via TextEncoder to keep full UTF-8.\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return window.btoa(binary);\n }\n\n private decodeBase64(value: string): string {\n if (typeof window === \"undefined\" || typeof window.atob !== \"function\") {\n return \"\";\n }\n const decoded = window.atob(value);\n const bytes = new Uint8Array(decoded.length);\n for (let i = 0; i < decoded.length; i++) bytes[i] = decoded.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n }\n\n private handleAnnouncementContentClick = (event: Event): void => {\n const target = event.target as {\n closest?: (selector: string) => Element | null;\n } | null;\n const copyControl =\n typeof target?.closest === \"function\"\n ? target.closest(\".announcement-code__copy\")\n : null;\n const button =\n copyControl?.tagName === \"BUTTON\"\n ? (copyControl as HTMLButtonElement)\n : null;\n if (!button) {\n const link =\n typeof target?.closest === \"function\" ? target.closest(\"a\") : null;\n if (!link) return;\n\n const href = link.getAttribute(\"href\");\n if (href) link.setAttribute(\"href\", this.appendRefParam(href));\n\n // whats_new_clicked fires once per banner per mount. Dedup prevents\n // accidental multi-clicks from inflating the link-follow funnel.\n this.trackWhatsNewClickedOnce({ cta: \"body\" });\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n const encoded = button.getAttribute(\"data-copy\") ?? \"\";\n const code = this.decodeBase64(encoded);\n if (!code) {\n return;\n }\n const showCopied = () => {\n const view = button.ownerDocument.defaultView ?? window;\n const existing = this.copyResetTimeouts.get(button);\n if (existing !== undefined) {\n view.clearTimeout(existing);\n }\n button.setAttribute(\"data-copied\", \"true\");\n button.setAttribute(\"aria-label\", \"Code copied\");\n button.textContent = \"Copied\";\n const id = view.setTimeout(() => {\n button.removeAttribute(\"data-copied\");\n button.setAttribute(\"aria-label\", \"Copy code\");\n button.textContent = \"Copy\";\n this.copyResetTimeouts.delete(button);\n }, 1500);\n this.copyResetTimeouts.set(button, id);\n };\n const clipboard = this.getClipboard(event);\n if (clipboard?.writeText) {\n clipboard.writeText(code).then(showCopied, () => {\n // ignore — clipboard may be unavailable (insecure context, denied\n // permission, focus loss); button silently stays in idle state.\n });\n }\n };\n\n private appendRefParam(href: string, ref = \"cpk-inspector\"): string {\n try {\n const isRootRelative = href.startsWith(\"/\") && !href.startsWith(\"//\");\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\", ref);\n }\n // Propagate the inspector's anonymous distinct-ID so the website /\n // Ops API can call posthog.alias(...) on signup-flow landing and\n // close the whats_new_viewed → whats_new_clicked → signup_attributed\n // funnel. Returns null when the user has opted out, so opt-out\n // suppresses cross-domain ID leaks too.\n if (\n !url.searchParams.has(\"posthog_distinct_id\") &&\n this.runtimeStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected &&\n !this.core?.telemetryDisabled &&\n this.isCopilotKitDestination(url)\n ) {\n const distinctId = getTelemetryDistinctIdForUrl();\n if (distinctId) {\n url.searchParams.append(\"posthog_distinct_id\", distinctId);\n }\n }\n if (isRootRelative) {\n return `${url.pathname}${url.search}${url.hash}`;\n }\n return url.toString();\n } catch {\n return href;\n }\n }\n\n private isCopilotKitDestination(url: URL): boolean {\n const hostname = url.hostname.toLowerCase();\n return hostname === \"copilotkit.ai\" || hostname.endsWith(\".copilotkit.ai\");\n }\n\n private escapeHtmlAttr(value: string): string {\n return escapeHtml(value).replace(/\"/g, \"&quot;\").replace(/'/g, \"&#39;\");\n }\n}\n\n// `customElements` is missing during SSR and in torn-down DOM test\n// environments. Resolve it when this function is called so registration can\n// be retried once a browser registry becomes available.\nexport function defineWebInspector(\n registry: CustomElementRegistry | undefined = globalThis.customElements,\n): void {\n if (!registry) return;\n\n defineElementOnce(registry, \"cpk-thread-list\", CpkThreadList);\n defineElementOnce(registry, THREAD_INSPECTOR_TAG, CpkThreadInspector);\n defineElementOnce(registry, \"cpk-thread-details\", ɵCpkThreadDetails);\n defineElementOnce(registry, \"cpk-memory-list\", CpkMemoryList);\n defineElementOnce(registry, WEB_INSPECTOR_TAG, WebInspectorElement);\n}\n\n/**\n * Bind a host-owned core before an Inspector is connected to the DOM. Disabling\n * auto-attachment first prevents `connectedCallback` from briefly selecting a\n * different global core.\n */\nexport function configureWebInspectorElement(\n inspector: WebInspectorElement,\n core: CopilotKitCore | null,\n): WebInspectorElement {\n inspector.autoAttachCore = false;\n inspector.core = core;\n return inspector;\n}\n\ndefineWebInspector();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"cpk-web-inspector\": WebInspectorElement;\n }\n}\n"],"mappings":"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,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,cAAc;KACd,QAAQ;KACT;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,QAAQ;KACR,cAAc;KACd,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,QAAQ;GACR,cAAc;GACd,YAAY;GACZ,iBAAiB;GAClB;EACF;CACD,0BAA0B;EACxB,UAAU,CACR;GACE,IAAI;GACJ,MAAM;GACN,SAAS;GACV,EACD;GACE,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,QAAQ;KACR,cAAc;KACd,MAAM;KACP;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,MAAM;GACN,eAAe;GACf,aAAa;GACd;EACF;CACD,wBAAwB;EACtB,UAAU,CACR;GACE,IAAI;GACJ,MAAM;GACN,SAAS;GACV,EACD;GACE,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,YAAY;KACZ,UAAU;KACX;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,YAAY;KACZ,OAAO;KACP,aAAa;KACd;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,aAAa;GACb,OAAO;GACP,aAAa;GACb,mBAAmB;GACpB;EACF;CACF;AAED,MA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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAsxCnB,QAAQ,UAAs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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA2hDR,UAAU,uBAAuB,KAAK,CAAC;;;sBAGvC,UAAU,uBAAuB,MAAM,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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"}
1
+ {"version":3,"file":"index.mjs","names":["tailwindStyles","inspectorLogoKiteUrl","inspectorLogoUrl","clampSizeToViewport"],"sources":["../src/index.ts"],"sourcesContent":["import { LitElement, css, html, nothing, render, unsafeCSS } from \"lit\";\nimport type { TemplateResult } from \"lit\";\nimport { marked } from \"marked\";\nimport { styleMap } from \"lit/directives/style-map.js\";\nimport tailwindStyles from \"./styles/generated.css\";\nimport inspectorLogoUrl from \"./assets/inspector-logo.svg\";\nimport inspectorLogoKiteUrl from \"./assets/inspector-logo-kite.svg\";\nimport { unsafeHTML } from \"lit/directives/unsafe-html.js\";\nimport { icons } from \"lucide\";\nimport type { CopilotKitCore } from \"@copilotkit/core\";\nimport {\n CopilotKitCoreErrorCode,\n CopilotKitCoreRuntimeConnectionStatus,\n createInspectorThreadRequestId,\n emitInspectorStopViewing,\n emitInspectorViewThread,\n isInspectorThreadBridgeEnabled,\n onInspectorActiveThread,\n onInspectorViewThreadResult,\n ɵselectThreads,\n ɵselectThreadsIsLoading,\n ɵselectThreadsError,\n ɵcreateThreadStore,\n ɵselectMemories,\n ɵselectMemoriesIsLoading,\n ɵselectMemoriesError,\n ɵselectMemoriesAvailable,\n ɵselectMemoriesRealtimeStatus,\n} from \"@copilotkit/core\";\nimport type {\n CopilotKitCoreSubscriber,\n ɵThreadStore,\n ɵThread,\n Memory,\n MemoryRealtimeStatus,\n RuntimeLicenseStatus,\n} from \"@copilotkit/core\";\nimport type { AbstractAgent, AgentSubscriber, Message } from \"@ag-ui/client\";\nimport type { InspectorLearningSnapshotV1 } from \"@copilotkit/shared\";\nimport { deriveLearningViewState } from \"./components/learning-view.js\";\nimport type { LearningViewState } from \"./components/learning-view.js\";\nimport type {\n Anchor,\n ContextKey,\n ContextState,\n DockMode,\n Position,\n Size,\n} from \"./lib/types.js\";\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.js\";\nimport {\n clearLegacyAnnouncementReadState,\n INSPECTOR_DISMISSAL_MAX_DURATION_MS,\n loadInspectorDismissedUntil,\n loadAnnouncementPulsedTimestamp,\n loadAnnouncementReadTimestamp,\n loadInspectorState,\n saveAnnouncementPulsedTimestamp,\n saveAnnouncementReadTimestamp,\n saveInspectorDismissedUntil,\n saveInspectorState,\n isValidAnchor,\n isValidPosition,\n isValidSize,\n isValidDockMode,\n} from \"./lib/persistence.js\";\nimport type { PersistedState } from \"./lib/persistence.js\";\nimport {\n clearLearningSetupMarker,\n learningSetupMarkerMatches,\n readLearningSetupMarker,\n subscribeToLearningSetupMarker,\n writeLearningSetupMarker,\n} from \"./lib/learning-setup.js\";\nimport type { LearningSetupMarker } from \"./lib/learning-setup.js\";\nimport {\n fetchInspectorLearning,\n InspectorLearningUnsupportedError,\n} from \"./lib/inspector-learning.js\";\nimport {\n buildPopOutFeatures,\n ensureBrandFont,\n openPopOutWindow,\n} from \"./lib/pop-out.js\";\nimport type { PopOutHandle } from \"./lib/pop-out.js\";\nimport { projectInspectorMetadata } from \"./lib/inspector-metadata.js\";\nimport type {\n InspectorMetadataAction,\n InspectorMetadataProjection,\n} from \"./lib/inspector-metadata.js\";\nimport {\n buildHomeModel,\n runtimeConnectionNeedsAttention,\n} from \"./lib/home-briefing.js\";\nimport type {\n HomeHeroAction,\n HomeModel,\n HomeRuntimeHealthTone,\n HomeServiceId,\n} from \"./lib/home-briefing.js\";\nimport {\n INSPECTOR_GROUPS,\n INSPECTOR_NAV_SECTIONS,\n getGroupForMenu,\n isInspectorMenuKey,\n shouldUseIconRail,\n} from \"./lib/inspector-nav.js\";\nimport type { InspectorNavGroupKey, MenuKey } from \"./lib/inspector-nav.js\";\nimport { selectVisibleRealThreadId } from \"./lib/thread-selection.js\";\nimport {\n TELEMETRY_DOCS_URL,\n ensureTelemetryDistinctId,\n getRuntimeUrlType,\n getTelemetryDistinctIdForUrl,\n maybeShowDisclosure,\n trackErrorSignalViewed,\n trackHomeCtaClicked,\n trackHomeFeaturePromptClicked,\n trackHomePromptCopied,\n trackHomeStoryBeatSelected,\n trackHomeViewed,\n trackInspectorOpened,\n learningCountBucket,\n learningDurationBucket,\n trackLearningEvidenceOpened,\n trackLearningPageChanged,\n trackLearningPaneViewed,\n trackLearningSetupPromptClicked,\n trackLearningSkillToggled,\n trackLearningSnapshotLoaded,\n trackLearningWebAppOpened,\n trackMetadataActionClicked,\n trackMetadataModuleViewed,\n trackTalkToEngineerClicked,\n trackThreadsEmptyEnabledViewed,\n trackThreadsEnabledViewed,\n trackThreadsExampleSelected,\n trackThreadsExampleTourCompleted,\n trackThreadsExampleTourDismissed,\n trackThreadsExampleTourReopened,\n trackThreadsExampleTourStarted,\n trackThreadsExampleTourStepViewed,\n trackThreadsExampleViewed,\n trackThreadsIntelligenceSignupClicked,\n trackThreadsLockedViewed,\n trackMemoriesTabClicked,\n trackThreadsTabClicked,\n trackThreadsTalkToEngineerClicked,\n trackThreadsTryFromHereClicked,\n trackWhatsNewClicked,\n trackWhatsNewSignalViewed,\n trackWhatsNewViewed,\n} from \"./lib/telemetry.js\";\nimport {\n createFeatureOnboardingPrompt,\n createOnboardingPrompt,\n createOnboardingRunId,\n} from \"./lib/onboarding-prompt.js\";\nimport type {\n ExampleKind,\n ExampleTourStep,\n ExampleTourTab,\n InspectorGroupKey,\n InspectorMetadataLicenseBucket,\n InspectorMetadataModuleViewedTelemetryProps,\n InspectorMetadataTelemetryModule,\n InspectorMemoryTelemetryProps,\n InspectorErrorSignalSource,\n InspectorEventErrorSource,\n InspectorWiringErrorSource,\n InspectorOpenSource,\n InspectorThreadTelemetryProps,\n MetadataActionPlacement,\n ThreadsExpiryBucket,\n ThreadsUsageBucket,\n WhatsNewSignalPresentation,\n WhatsNewSurface,\n} from \"./lib/telemetry.js\";\n\nexport type { Anchor } from \"./lib/types.js\";\nexport { buildCapabilityRows as ɵbuildCapabilityRows };\nexport type { CapabilityToolRow as ɵCapabilityToolRow };\n\nexport type InspectorOpenOptions = {\n /** Select the thread that contains the message. */\n threadId?: string;\n /** Narrow the Threads view to the agent that owns the thread. */\n agentId?: string;\n /** Scroll the selected thread timeline to this message when available. */\n messageId?: string;\n};\n\nexport const WEB_INSPECTOR_TAG = \"cpk-web-inspector\" as const;\nexport const THREAD_INSPECTOR_TAG = \"cpk-thread-inspector\" as const;\n\n/**\n * User-facing label for the learning view. The legacy menu key stays\n * \"memories\" for persistence and telemetry stability.\n */\nconst LEARNING_VIEW_LABEL = \"Automatic Learning\";\nconst LEARNING_RECOPY_CONFIRMATION_MS = 2_000;\n\n/**\n * User-facing label for the What's new view. Its menu key stays `whats-new`\n * for persistence and telemetry stability, following the `memories`/\"Memory\"\n * precedent above.\n */\nconst WHATS_NEW_VIEW_LABEL = \"What's new\";\n\n/** Menu key of the What's new leaf — the news signal's destination. */\nconst WHATS_NEW_MENU_KEY = \"whats-new\";\n\ntype LucideIconName = keyof typeof icons;\n\ntype MenuItem = {\n key: MenuKey;\n label: string;\n icon: LucideIconName;\n};\n\n// ── Launcher signals ──────────────────────────────────────────────────────\n//\n// There is one dot on the closed launcher and more than one thing that can\n// claim it, so each subject is described once, here, and every call site reads\n// the description rather than hardcoding a subject.\n//\n// The rule for this table is **no field without a second consumer**. That is\n// why there is no lifecycle field (one value was ever used, and \"never\n// persisted\" is expressed by not persisting) and why the two destinations are\n// separate: the news signal genuinely marks one entry and lands on another.\n//\n// This reintroduces a small shared shape where an earlier generic version was\n// removed as speculative. That removal was correct at the time — the\n// abstraction had exactly one user. A second user now exists.\n//\n// **The two subjects beat by different rules, deliberately**: an error beats\n// once per outage, an announcement once per tab per announcement. That follows\n// from a recurring condition versus a one-time publication. Do not harmonise\n// them; harmonising breaks one of them.\n\n/** Tone drives colour only. The launcher treatment is shared by every tone. */\ntype LauncherSignalTone = \"news\" | \"error\";\n\n/**\n * The error keys ARE the telemetry enum, so a source can never be reported\n * under a name the signal table does not describe.\n */\ntype LauncherSignalKey = \"whats-new\" | InspectorErrorSignalSource;\n\ntype LauncherSignalDefinition = Readonly<{\n tone: LauncherSignalTone;\n /** Which navigation entry carries the marker while this signal is armed. */\n markerTarget: MenuKey;\n /** Where a press on the launcher opens while this signal owns the dot. */\n landingTarget: MenuKey;\n /** One beat's duration. Errors beat faster than product news. */\n cadence: number;\n /** Higher wins the single dot. Errors outrank news. */\n priority: number;\n /**\n * Suffix appended to the marked navigation entry's accessible name, and —\n * for error tones only — to the launcher's own accessible name. Never\n * rendered as visible text: the dot says there is something to look at, and\n * the panel says what.\n */\n accessibleLabel: string;\n /**\n * The words the launcher opens sideways to show, and the words spoken once\n * into the polite live region. Absent means this subject opens no pill.\n *\n * Read from the signal rather than from a condition on the tone, so a third\n * signal can carry a pill by declaring one — and whoever declares it owns\n * the width problem that keeps the announcement out. The announcement's feed\n * preview measures 54 characters against a 36-pixel launcher, and the width\n * would be set by a feed we do not control.\n *\n * These are the words the panel already uses, never a paraphrase, so a\n * reader who sees the pill and then opens the panel has nothing to\n * reconcile. The failure *message* is never carried here — for width, and\n * because it can contain prompts, URLs and identifiers.\n */\n pillLabel?: string;\n}>;\n\nconst NEWS_SIGNAL_ID = \"whats-new\" as const;\nconst NEWS_SIGNAL_COLOR = \"#A78BFA\";\n/**\n * The error tone's red. Bright enough to read against the launcher's dark\n * face at the same perceived weight as the news lilac, and in the same family\n * as System Health's error tone (#b32d3b light / #ff9aa0 dark), which is too\n * dark and too pale respectively to use directly on the launcher.\n */\nconst ERROR_SIGNAL_COLOR = \"#F87171\";\n\nconst LAUNCHER_SIGNAL_COLORS: Readonly<Record<LauncherSignalTone, string>> = {\n news: NEWS_SIGNAL_COLOR,\n error: ERROR_SIGNAL_COLOR,\n};\n\n/**\n * The failure gesture, four phases in series:\n *\n * ```\n * beat 400ms → open 250ms → hold 2500ms → close 250ms (3400ms total)\n * ```\n *\n * Sequential rather than simultaneous, deliberately: the beat says *here*, the\n * pill says *this*. The beat is short so the words arrive quickly.\n *\n * **All four durations live here and nowhere else.** The stylesheet reads the\n * two animated phases as custom properties injected from these numbers rather\n * than restating them, because they are taste and will be tuned by eye after\n * the first live look — tuning the feel must be a number, not a refactor.\n */\nconst ERROR_GESTURE_MS = {\n /** Phase 1: one beat, which is also the error signals' cadence. */\n beat: 400,\n /** Phase 2: the sideways reveal. */\n open: 250,\n /** Phase 3: long enough to read three words without hurrying. */\n hold: 2500,\n /** Phase 4: back to the plain mark with its dot. */\n close: 250,\n} as const;\n\n/**\n * The words the pill carries, which are the words the panel already carries.\n *\n * `Runtime error` is the System Health runtime tile's own label, and\n * `Failed to load threads` is the Threads view's own heading. The outside and\n * the inside must agree, so these are shared rather than paraphrased.\n */\nconst RUNTIME_ERROR_LABEL = \"Runtime error\";\nconst THREADS_LOAD_ERROR_LABEL = \"Failed to load threads\";\nconst AGENT_RUN_FAILED_LABEL = \"Agent run failed\";\nconst TOOL_ERROR_LABEL = \"Tool error\";\nconst MEMORY_LOAD_ERROR_LABEL = \"Failed to load learning data\";\n\n/**\n * Copy on the landing view. Titles match the pill.\n *\n * The two fields differ in what they can promise. `advice` is about the\n * reader's next move and is always true. `highlight` is a claim about *this\n * view* — that the failed item is visible below — and the error carries no\n * guarantee of that: a code mapped to `run` can arrive with no run in the\n * buffer at all, and a tool error can arrive without the call id the\n * highlight needs. So it is rendered only once the item is actually there.\n * A card pointing at something the reader cannot find is worse than a card\n * that stays quiet, because it sends them looking.\n */\nconst EVENT_ERROR_GUIDANCE: Readonly<\n Record<\n InspectorEventErrorSource,\n Readonly<{ title: string; advice?: string; highlight?: string }>\n >\n> = {\n run: {\n title: AGENT_RUN_FAILED_LABEL,\n highlight: \"The failed run event is highlighted below.\",\n },\n tool: {\n title: TOOL_ERROR_LABEL,\n highlight: \"The failed tool call is highlighted below.\",\n },\n memory: {\n title: MEMORY_LOAD_ERROR_LABEL,\n advice:\n \"Confirm CopilotKit Intelligence is connected, then retry Learning.\",\n },\n};\n\n/**\n * The pill's second line, shared by every subject that carries a pill.\n *\n * **This is the one string in the feature that exists nowhere else in the\n * product.** Every other word the launcher shows is word-identical to the\n * panel, which is the standing rule; this line is a deliberate, owner-approved\n * exception to it, because the pill became clickable and an invitation that\n * says nothing is not an invitation.\n *\n * It is shown, never spoken: the polite live region carries the failure class\n * alone. A screen-reader user cannot act on an instruction delivered through\n * an announcement, and it would double the spoken length.\n */\nconst PILL_SUBLINE_LABEL = \"Open Inspector for details\";\n\ntype LauncherHudRowId = \"threads\" | \"learning\";\n\nconst HUD_INSPECTOR_LABEL = \"CopilotKit Inspector\";\nconst HUD_ANNOUNCEMENT_TITLE_LIMIT = 80;\nconst HUD_THREADS_LABEL = \"Rich Threads\";\nconst HUD_LEARNING_LABEL = \"Automatic Learning\";\nconst HUD_LEARN_MORE_LABEL = \"Click to learn more\";\n\ntype InspectorDismissalDuration = \"day\" | \"week\";\nconst INSPECTOR_DISMISSAL_MS: Readonly<\n Record<InspectorDismissalDuration, number>\n> = {\n day: 24 * 60 * 60 * 1000,\n week: INSPECTOR_DISMISSAL_MAX_DURATION_MS,\n};\n\ntype HomeFeaturePromptId = HomeServiceId;\ntype HomeFeaturePromptTarget = Readonly<{\n id: HomeFeaturePromptId;\n label: string;\n}>;\n\nconst LAUNCHER_SIGNALS: Readonly<\n Record<LauncherSignalKey, LauncherSignalDefinition>\n> = {\n // Marks What's new, lands on Home: Home carries the preview band that is\n // the way onward. Unchanged from before this table existed.\n \"whats-new\": {\n tone: \"news\",\n markerTarget: WHATS_NEW_MENU_KEY,\n landingTarget: \"home\",\n cadence: 2100,\n priority: 0,\n accessibleLabel: \"new content\",\n },\n // Errors mark and land on the same place, because the place that carries\n // the marker is the place that explains the failure.\n connection: {\n tone: \"error\",\n markerTarget: \"home\",\n landingTarget: \"home\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 5,\n accessibleLabel: \"runtime error\",\n pillLabel: RUNTIME_ERROR_LABEL,\n },\n threads: {\n tone: \"error\",\n markerTarget: \"threads\",\n landingTarget: \"threads\",\n cadence: ERROR_GESTURE_MS.beat,\n // Below the connection signal: a connection failure cascades into thread\n // failures, so when both could be armed the root cause owns the dot.\n priority: 4,\n accessibleLabel: \"thread loading error\",\n pillLabel: THREADS_LOAD_ERROR_LABEL,\n },\n // Unread *events*. They beat and name the failure, then clear when the\n // landing view is read. They lose the launcher dot to wiring state.\n run: {\n tone: \"error\",\n markerTarget: \"ag-ui-events\",\n landingTarget: \"ag-ui-events\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 3,\n accessibleLabel: \"agent run failed\",\n pillLabel: AGENT_RUN_FAILED_LABEL,\n },\n tool: {\n tone: \"error\",\n markerTarget: \"agents\",\n landingTarget: \"agents\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 2,\n accessibleLabel: \"tool error\",\n pillLabel: TOOL_ERROR_LABEL,\n },\n memory: {\n tone: \"error\",\n markerTarget: \"memories\",\n landingTarget: \"memories\",\n cadence: ERROR_GESTURE_MS.beat,\n priority: 1,\n accessibleLabel: \"learning error\",\n pillLabel: MEMORY_LOAD_ERROR_LABEL,\n },\n};\n\n/** Highest priority first, so the winner of the single dot is the head. */\nconst LAUNCHER_SIGNAL_PRIORITY_ORDER: ReadonlyArray<LauncherSignalKey> = (\n Object.keys(LAUNCHER_SIGNALS) as LauncherSignalKey[]\n).sort((a, b) => LAUNCHER_SIGNALS[b].priority - LAUNCHER_SIGNALS[a].priority);\n\n/** Wiring *state* — red until the problem heals. */\nconst WIRING_ERROR_KEYS = [\n \"connection\",\n \"threads\",\n] as const satisfies ReadonlyArray<InspectorWiringErrorSource>;\n\n/** Unread *events* — red until the landing view is read. */\nconst EVENT_ERROR_KEYS = [\n \"run\",\n \"tool\",\n \"memory\",\n] as const satisfies ReadonlyArray<InspectorEventErrorSource>;\n\ntype InspectorEventErrorDetails = Readonly<{\n message: string;\n agentId?: string;\n toolName?: string;\n toolCallId?: string;\n}>;\n\nfunction isWiringErrorKey(\n key: LauncherSignalKey,\n): key is InspectorWiringErrorSource {\n return (WIRING_ERROR_KEYS as readonly string[]).includes(key);\n}\n\n/**\n * Takes a plain string rather than a `LauncherSignalKey`, because one caller\n * reads the subject back out of a `data-` attribute, where the DOM can only\n * offer `string | undefined`. Narrowing untrusted input is what a guard is\n * for; `LauncherSignalKey` still satisfies the parameter, so the callers that\n * already hold one are unaffected.\n */\nfunction isEventErrorKey(key: string): key is InspectorEventErrorSource {\n return (EVENT_ERROR_KEYS as readonly string[]).includes(key);\n}\n\n/** Narrows a signal key to an error source, excluding the announcement. */\nfunction isErrorSignalKey(\n key: LauncherSignalKey,\n): key is InspectorErrorSignalSource {\n return isWiringErrorKey(key) || isEventErrorKey(key);\n}\n\n/**\n * The control range is the point, not an oversight: an attribute selector has\n * to escape those characters too, and CSS.escape — which the fallback below\n * stands in for — escapes them as well. Hoisted so the suppression can sit on\n * the pattern rather than three lines above it.\n */\n// oxlint-disable no-control-regex -- deliberate, see above\nconst SELECTOR_ESCAPE_PATTERN =\n /[\\0-\\x1f\\x7f!\"#$%&'()*+,./:;<=>?@[\\\\\\]^`{|}~]/g;\n// oxlint-enable no-control-regex\n\n/** Attribute selector value. jsdom does not implement CSS.escape. */\nfunction escapeSelectorValue(value: string): string {\n if (typeof CSS !== \"undefined\" && typeof CSS.escape === \"function\") {\n return CSS.escape(value);\n }\n return value.replace(SELECTOR_ESCAPE_PATTERN, \"\\\\$&\");\n}\n\nfunction eventErrorKeyForCode(\n code: CopilotKitCoreErrorCode,\n): InspectorEventErrorSource | null {\n switch (code) {\n case CopilotKitCoreErrorCode.TOOL_NOT_FOUND:\n case CopilotKitCoreErrorCode.TOOL_HANDLER_FAILED:\n case CopilotKitCoreErrorCode.TOOL_ARGUMENT_PARSE_FAILED:\n case CopilotKitCoreErrorCode.AGENT_NOT_FOUND:\n return \"tool\";\n case CopilotKitCoreErrorCode.AGENT_CONNECT_FAILED:\n case CopilotKitCoreErrorCode.AGENT_RUN_FAILED:\n case CopilotKitCoreErrorCode.AGENT_RUN_FAILED_EVENT:\n case CopilotKitCoreErrorCode.AGENT_RUN_ERROR_EVENT:\n return \"run\";\n default:\n return null;\n }\n}\n\n/**\n * Coalesce inspector-owned GET /threads sends. The first refresh goes out\n * at once. Further calls in this window share one trailing request, so a\n * flaky network does not fire a burst of list fetches and error cards.\n */\nconst THREAD_LIST_DEBOUNCE_MS = 300;\n\n/** The launcher's accessible name with nothing wrong. */\nconst LAUNCHER_BASE_LABEL = \"Web Inspector\";\n\n/**\n * Where the pill is in the gesture.\n *\n * `closed` covers the whole beat: the pill is laid out at its full width and\n * clipped to nothing from the first frame, so the room it needs can be\n * measured before anything is shown and the reveal has nothing left to\n * compute.\n */\ntype LauncherPillPhase = \"closed\" | \"opening\" | \"holding\" | \"closing\";\n\n/**\n * Which side the pill grows towards. The launcher is anchored top-right, so\n * the natural direction is leftwards, away from its own edge — but it is\n * draggable and its position persists, so a reader who parked it near the left\n * edge would otherwise get a permanently truncated pill.\n */\ntype LauncherPillDirection = \"left\" | \"right\";\n\n/**\n * Whether the reader actually got a pill. `suppressed` is the honest-degrade\n * case: neither side had room, so the dot and the beat fire alone.\n */\ntype LauncherPillOutcome = \"shown\" | \"suppressed\";\n\ntype CoreStatusSummary = Readonly<{\n label: string;\n state: \"connected\" | \"connecting\" | \"disconnected\" | \"error\" | \"unavailable\";\n description: string;\n}>;\n\ntype InspectorColorScheme = \"light\" | \"dark\";\n\nconst EDGE_MARGIN = 16;\n/** HUD card plus the hover bridge. Used to pick left vs right. */\nconst LAUNCHER_HUD_WIDTH = 258;\n/**\n * One page-load preview of the launcher's feature HUD.\n *\n * The card arrives after the host page has had a beat to settle. Its feature\n * contents then arrive from top to bottom, stay readable, and leave together.\n * Nothing is persisted: a new Inspector element means a new preview.\n */\nconst LAUNCHER_HUD_INTRO_MS = {\n delay: 500,\n duration: 3400,\n waterfallStart: 180,\n waterfallStagger: 170,\n waterfallDuration: 300,\n blockedRetry: 250,\n} as const;\n\n/** Return the staggered reveal delay for one launcher HUD layer. */\nconst launcherHudWaterfallDelay = (introIndex: number): string =>\n `${\n LAUNCHER_HUD_INTRO_MS.waterfallStart +\n introIndex * LAUNCHER_HUD_INTRO_MS.waterfallStagger\n }ms`;\nconst DRAG_THRESHOLD = 6;\nconst MIN_WINDOW_WIDTH = 880;\nconst MIN_WINDOW_WIDTH_DOCKED_LEFT = 640;\nconst MIN_WINDOW_HEIGHT = 480;\nconst INSPECTOR_STORAGE_KEY = \"cpk:inspector:state\";\nconst ANNOUNCEMENT_URL = \"https://cdn.copilotkit.ai/announcements.json\";\n// The launcher keeps its current touch target on compact screens and grows to\n// an exactly 20% larger desktop cap. `box-sizing` makes these OUTER sizes.\nconst LAUNCHER_MIN_SIZE = 51.84;\nconst LAUNCHER_MAX_SIZE = 62.208;\nconst DEFAULT_BUTTON_SIZE: Size = {\n width: LAUNCHER_MIN_SIZE,\n height: LAUNCHER_MIN_SIZE,\n};\nconst DEFAULT_WINDOW_SIZE: Size = { width: 960, height: 740 };\nconst DOCKED_LEFT_WIDTH = 720;\nconst MAX_AGENT_EVENTS = 200;\nconst INTERACTIVE_FOCUS_BASE_STYLE =\n \"outline-style:solid;outline-width:2px;outline-color:transparent;outline-offset:2px;cursor:pointer;\";\n// Cap on banner impressions held while waiting for the runtime handshake, so a\n// runtime that never connects can't accumulate an unbounded queue.\nconst MAX_PENDING_BANNER_VIEWED = 20;\nconst MAX_TOTAL_EVENTS = 500;\nconst INTELLIGENCE_SIGNUP_URL = \"https://intelligence.copilotkit.ai\";\nconst TALK_TO_ENGINEER_URL = \"https://www.copilotkit.ai/talk-to-an-engineer\";\n// Label for the Capabilities tab (client-authoritative dev experimentation\n// surface: toggle frontend tools + A2UI catalog components on/off, enforced\n// immediately via core.setToolEnabled / core.setCatalogComponentEnabled).\n// Renameable — keep the display string in this one place.\nconst CAPABILITIES_TAB_LABEL = \"Capabilities\";\n\nfunction createPlaygroundThreadId(): string {\n return globalThis.crypto?.randomUUID?.() ?? `playground-${Date.now()}`;\n}\n\nconst THREADS_DOCS_URL = \"https://docs.copilotkit.ai/threads\";\nconst SELF_HOSTED_INTELLIGENCE_URL =\n \"https://docs.copilotkit.ai/intelligence/self-hosting\";\n\n// ── The Intelligence story on Home ────────────────────────────────────────\n//\n// A condensed cut of the six-phase animation on the Intelligence home page\n// (`react-shell/src/home/learning-sample*`). Three beats, not six: the two\n// thread beats there open on the agent booking the wrong meeting, which is a\n// poor first frame for a card whose job is to argue for the product, and the\n// handoff beat only bridges between them.\n//\n// What is kept is the machinery a developer cannot hand-roll — many threads\n// collapsing into one pattern — then the artefact it produces, then the loop.\n// `meeting-scheduling.md` recurs in all three on purpose: the same filename\n// appearing in the last beat's badge is what turns the closing diagram from a\n// claim into something checkable.\n//\n// Durations are the shipped values for the corresponding phases upstream, so\n// the pacing stays recognisable to anyone who has seen the original.\n// Each beat owns its own two sentences, and the card shows exactly the pair\n// that belongs to the picture on screen. An earlier version argued for Threads\n// in prose while the animation showed Learning — two half-claims sitting next\n// to each other, neither supporting the other. Bound together they read as one\n// chain: your users' threads → the pattern in them → the file → it applies\n// itself.\n//\n// `lead` is the sentence that has to land on its own. `support` earns it.\n// Nothing else: a third line here is what makes this card feel crowded.\nconst INTELLIGENCE_STORY_BEATS = [\n {\n id: \"threads\",\n label: \"Rich Threads\",\n // Roughly 24 words of copy plus a picture to take in. The upstream timings\n // were written for a page where the animation carried itself; here it has\n // to be read, so every beat gets time for two sentences at a comfortable\n // pace rather than a glance. The rail is there for anyone who wants to\n // move faster.\n duration: 6_500,\n // \"Your users\" means the end users of the developer's app, not the\n // developer. That is what the platform means too: `identifyUser` resolves\n // one `{id, name}` per request from the app, and a thread carries\n // `end_user_id` — a column renamed from `user_id` precisely because the\n // old name \"caused repeated misdiagnosis\" against control-plane users.\n //\n // No count in the claim. A developer wiring this up locally has no users\n // yet, and \"thousands\" would read as a lie on day one while still being\n // true at scale. \"All the others\" holds in both cases.\n lead: \"You only see this session. Your users have all the others.\",\n // \"Rich Threads\" is the product's own name for the durable ones, and the\n // distinction is the sale: the Inspector's Threads tab already lists local\n // ones that die on reload.\n support:\n \"Rich Threads keep every conversation and its state, so you can open the one that broke instead of reproducing it.\",\n },\n {\n id: \"learning\",\n label: \"Automatic Learning\",\n duration: 6_000,\n lead: \"Your users already told you what to fix.\",\n // Insights are a first-class concept in the product, and the evidence link\n // is the credibility hook for a sceptical developer: a claim you can open,\n // not a model's opinion. Learning's own onboarding leads with \"46 evidence\n // refs\" across \"12 Threads\" for exactly this reason.\n support:\n \"Automatic Learning reads the runs behind those threads and finds the patterns — every Insight linked to the messages that back it.\",\n },\n {\n id: \"skill\",\n label: \"Skills\",\n duration: 5_500,\n lead: \"An Insight becomes a skill you own.\",\n // The review step is real (candidates land at pending_review and a human\n // approves), but it is sold as control rather than as reassurance. The\n // earlier wording — \"nothing reaches your agent until you approve it\" —\n // answered a fear the reader had not voiced yet, which reads as a defence\n // and plants the worry it deflects. Ownership is the same fact, stated as\n // a feature: a readable file you review, edit and ship.\n support:\n \"A SKILL.md built from that evidence — yours to review, edit and ship with your project.\",\n },\n {\n id: \"intelligence\",\n // Named after the product, not after the mechanism. The other three tabs\n // are the parts; this one is the whole, so the rail reads \"Threads ·\n // Learning · Skills · Intelligence\" — the pieces, then the thing that\n // unites them. \"Reuse\" named neither a surface nor an outcome.\n label: \"Intelligence\",\n duration: 6_000,\n lead: \"Every round of real use leaves your agent better.\",\n // Deliberately NOT \"Skills apply it for you\". The platform does not apply\n // skills at run time — there is no run-time read of published skills, only\n // a bundle the developer pulls down with `copilotkit skills download`.\n // Claiming automatic application would be a promise the product does not\n // keep, and the first developer to check would stop believing the rest.\n support:\n \"Approve a skill, pull it into your project, and the next run starts from what already worked.\",\n },\n] as const;\n\n/**\n * The threads the first beat shows.\n *\n * One of them failed, because that is the row a developer actually wants and\n * the reason durable threads are worth paying for. It is a user's thread that\n * went wrong, not a demo of our agent failing — the distinction matters for a\n * card that has to argue for the product.\n */\nconst INTELLIGENCE_STORY_THREADS = [\n { title: \"Reschedule the Tuesday sync\", meta: \"2 min ago\", failed: false },\n {\n title: \"Book time with the design team\",\n meta: \"18 min ago\",\n failed: false,\n },\n { title: \"Booked the wrong slot\", meta: \"Needs a look\", failed: true },\n] as const;\n\n/** The three rules the story derives, shown verbatim across all three beats. */\nconst INTELLIGENCE_STORY_RULES = [\n \"Check both calendars.\",\n \"Propose several times.\",\n \"Ask before booking.\",\n] as const;\n\n/**\n * The raw thread signals the first beat collapses into those rules.\n *\n * Kept at real-message length and varied on purpose — these have to read as\n * things people actually typed, not as three tidy bullet points. The longest\n * one truncates in a narrow panel, which is honest: it is an excerpt.\n */\nconst INTELLIGENCE_STORY_SIGNALS = [\n \"Check our calendars and find a time for both of us.\",\n \"Could you share a few options?\",\n \"Ask me before you book it.\",\n] as const;\n\n// A skill really is a directory holding a SKILL.md, so the path shows both the\n// skill's name and the document the platform actually stores.\nconst INTELLIGENCE_STORY_SKILL_FILE = \"meeting-scheduling/SKILL.md\";\n\n/**\n * How long the copied confirmation stands before the button invites a second\n * press. Longer than the 2s the Threads setup prompt uses, because this state\n * also carries an instruction that has to be read, not just an acknowledgement.\n */\nconst PROMPT_COPY_RESET_MS = 4_000;\n\n// The real pipeline, named the way the product names it: threads produce\n// evidence-backed Insights, Insights produce Skill candidates, a human\n// approves, and the approved set is what the project pulls in. `Lightbulb` is\n// Learning's own icon for an Insight, so the two surfaces agree.\nconst INTELLIGENCE_STORY_CHAIN = [\n {\n icon: \"MessagesSquare\",\n name: \"Threads\",\n detail: \"Every conversation\",\n },\n { icon: \"Lightbulb\", name: \"Insights\", detail: \"Backed by evidence\" },\n { icon: \"FileText\", name: \"Skills\", detail: \"You approve\" },\n { icon: \"Wand2\", name: \"Your agent\", detail: \"Starts from what worked\" },\n] as const;\nconst THREADS_EXAMPLE_OVERVIEW_VIDEO_URL =\n \"https://cdn.copilotkit.ai/corp-site/videos/copilotkit-generative-ui-agentic-frontend-demo.webm\";\nconst THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK =\n \"The demo video is unavailable. Use the example threads to explore Conversation, AG-UI Events, and State.\";\nconst THREADS_LOCKED_VIDEO_URL =\n \"https://www.loom.com/embed/79817778d29e490c97225127d2f17b3a?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true\";\nconst LEARNING_LOCKED_VIDEO_URL =\n \"https://www.loom.com/embed/2978fbfe42324e509057ac5fd46b7a70?hide_owner=true&hide_share=true&hide_title=true&hideEmbedTopBar=true&hide_speed=true\";\ntype LockedFeatureOutlineItem = Readonly<{\n icon: LucideIconName;\n title: string;\n description: string;\n}>;\nconst THREADS_LOCKED_FEATURE_OUTLINE = [\n {\n icon: \"MessagesSquare\",\n title: \"The whole conversation comes back\",\n description:\n \"Rich Threads restores the complete interaction, not just a transcript. Messages, tool calls, shared state, generated interfaces, and supported files return together when a user reopens the thread.\",\n },\n {\n icon: \"LayoutGrid\",\n title: \"Generated UI stays in the thread\",\n description:\n \"Cards, charts, A2UI surfaces, MCP Apps, and tool renderers remain part of the conversation. The demo above shows a generated spending chart returning after a reload.\",\n },\n {\n icon: \"RefreshCw\",\n title: \"Return without starting over\",\n description:\n \"Users can move across sessions and devices while thread lists stay synchronized across open tabs. Rich Threads replays missed events and reconnects to work already in progress.\",\n },\n {\n icon: \"Server\",\n title: \"Infrastructure you do not have to rebuild\",\n description:\n \"CopilotKit handles durable event storage, replay, synchronization, lifecycle APIs, and thread locks on one portable AG-UI history model. Use CopilotKit Cloud or deploy Intelligence in your own Kubernetes environment.\",\n },\n] as const satisfies ReadonlyArray<LockedFeatureOutlineItem>;\nconst LEARNING_LOCKED_FEATURE_OUTLINE = [\n {\n icon: \"History\",\n title: \"Memory across sessions\",\n description:\n \"Keep useful facts, preferences, and decisions after the thread closes. Learning gives future conversations the context they need without asking users to repeat themselves.\",\n },\n {\n icon: \"Search\",\n title: \"Recall by meaning\",\n description:\n \"Surface relevant memories by what they mean, not by an exact phrase. Your agent can bring the right context into a new interaction even when the user asks in a completely different way.\",\n },\n {\n icon: \"Layers\",\n title: \"Built-in structure\",\n description:\n \"Turn raw interactions into organized topical, episodic, and operational knowledge. Learning separates enduring facts from individual experiences and useful instructions automatically.\",\n },\n {\n icon: \"Eye\",\n title: \"Full visibility\",\n description:\n \"Inspect exactly what your agent learned and trace each memory back to the threads that shaped it. Review the stored context instead of treating memory like a black box.\",\n },\n] as const satisfies ReadonlyArray<LockedFeatureOutlineItem>;\nconst THREADS_EXAMPLE_TOUR_STORAGE_KEY =\n \"cpk:inspector:threads-example-tour:v1\";\nconst THREADS_EXAMPLE_AGENT_ID = \"threads-feature\";\n\ntype ThreadServiceStatus = \"available\" | \"unavailable\" | \"unknown\" | \"error\";\ntype ThreadsExampleOverviewVideoState =\n | \"deferred\"\n | \"ready\"\n | \"playing\"\n | \"failed\";\ntype HomeFeaturePromptCopyState = \"idle\" | \"copied\" | \"error\";\ntype ThreadsExampleOverviewVideoListeners = Readonly<{\n loadeddata: EventListener;\n play: EventListener;\n pause: EventListener;\n error: EventListener;\n}>;\n\ntype ThreadStoreStatus = Readonly<{\n error: Error | null;\n isLoading: boolean;\n}>;\n\n/** Keep one row per thread id when flattening per-agent stores. */\nfunction uniqueThreadsById(threads: ɵThread[]): ɵThread[] {\n const seen = new Set<string>();\n const unique: ɵThread[] = [];\n for (const thread of threads) {\n if (seen.has(thread.id)) {\n continue;\n }\n seen.add(thread.id);\n unique.push(thread);\n }\n return unique;\n}\n\nfunction flattenThreadsByAgent(\n threadsByAgent: Map<string, ɵThread[]>,\n): ɵThread[] {\n return uniqueThreadsById(Array.from(threadsByAgent.values()).flat());\n}\n\n/**\n * Selects the Thread store status with a stable object identity so loading-only\n * transitions reach one of the Inspector's two existing store subscriptions.\n */\nfunction createThreadStoreStatusSelector(): (\n state: ReturnType<ɵThreadStore[\"getState\"]>,\n) => ThreadStoreStatus {\n let previousError: Error | null | undefined;\n let previousIsLoading: boolean | undefined;\n let previousStatus: ThreadStoreStatus | undefined;\n\n return (state) => {\n const error = ɵselectThreadsError(state);\n const isLoading = ɵselectThreadsIsLoading(state);\n if (\n previousStatus &&\n previousError === error &&\n previousIsLoading === isLoading\n ) {\n return previousStatus;\n }\n\n previousError = error;\n previousIsLoading = isLoading;\n previousStatus = { error, isLoading };\n return previousStatus;\n };\n}\n\ntype InspectorAgentEventType =\n | \"RUN_STARTED\"\n | \"RUN_FINISHED\"\n | \"RUN_ERROR\"\n | \"STEP_STARTED\"\n | \"STEP_FINISHED\"\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 | \"ACTIVITY_SNAPSHOT\"\n | \"ACTIVITY_DELTA\";\n\nconst AGENT_EVENT_TYPES: readonly InspectorAgentEventType[] = [\n \"RUN_STARTED\",\n \"RUN_FINISHED\",\n \"RUN_ERROR\",\n \"STEP_STARTED\",\n \"STEP_FINISHED\",\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 \"ACTIVITY_SNAPSHOT\",\n \"ACTIVITY_DELTA\",\n] as const;\n\nconst THREADS_LOCKED_COPY = {\n heading:\n \"Production-grade chat threads without the complexity. Self hostable.\",\n description:\n \"Chat threads that go beyond text with generative UI and multimodal inputs, built to replay missed events and stay in sync across tabs, sessions, and devices.\",\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 toolCallId?: string;\n /** Populated for role=\"activity\" messages (Generative UI). */\n activityType?: string;\n};\n\nconst EMPTY_INSPECTOR_MESSAGES: InspectorMessage[] = [];\n\nfunction textFromUnknownContent(content: unknown): string {\n if (typeof content === \"string\") return content;\n if (Array.isArray(content)) {\n const parts: string[] = [];\n for (const part of content) {\n if (typeof part === \"string\") {\n parts.push(part);\n continue;\n }\n if (typeof part === \"object\" && part !== null && \"text\" in part) {\n const text = part.text;\n if (typeof text === \"string\") parts.push(text);\n }\n }\n return parts.join(\"\");\n }\n if (typeof content === \"object\" && content !== null && \"text\" in content) {\n const text = content.text;\n if (typeof text === \"string\") return text;\n }\n return \"\";\n}\n\ntype InspectorToolDefinition = {\n agentId: string;\n name: string;\n description?: string;\n parameters?: unknown;\n type: \"handler\" | \"renderer\";\n};\n\n// ─── Capabilities tab view-models ────────────────────────────────────────────\n// A single toggle row. `key` is the stable identity used as a Lit list key; for\n// tools it is `${agentId}:${name}` (agentId \"\" for global tools), for catalog\n// components it is the component name.\ntype CapabilityToolRow = {\n key: string;\n name: string;\n description?: string;\n agentId?: string;\n enabled: boolean;\n};\n\n// Minimal structural view of CopilotKitCore that the pure helper needs, so\n// buildCapabilityRows is trivially unit-testable with a plain object. Method\n// names MUST match the A1 contract exactly.\ntype CapabilityToolSource = {\n tools?: ReadonlyArray<{\n name: string;\n description?: string;\n agentId?: string;\n }>;\n isToolEnabled: (name: string, agentId?: string) => boolean;\n};\n\n/**\n * Map core.tools (the registry INCLUDING disabled tools) into Capabilities-tab\n * frontend-tool rows. Pure: no DOM, no `this`. Reads current on/off state from\n * core.isToolEnabled(name, agentId?) per the A1 contract.\n */\nfunction buildCapabilityRows(core: CapabilityToolSource): CapabilityToolRow[] {\n const rows: CapabilityToolRow[] = [];\n for (const tool of core.tools ?? []) {\n const agentId = tool.agentId ?? \"\";\n const key = `${agentId}:${tool.name}`;\n rows.push({\n key,\n name: tool.name,\n description: tool.description,\n agentId: tool.agentId,\n enabled: core.isToolEnabled(tool.name, tool.agentId),\n });\n }\n return rows.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\ntype InspectorEvent = {\n id: string;\n agentId: string;\n type: InspectorAgentEventType;\n timestamp: number;\n payload: SanitizedValue;\n};\n\n// ─── Thread details types ────────────────────────────────────────────────────\n\nexport type ThreadDebuggerProviderLoadOptions = {\n signal: AbortSignal;\n};\n\nexport type ThreadDebuggerToolCall = {\n id: string;\n name: string;\n args: string | Record<string, unknown>;\n};\n\nexport type ThreadDebuggerMessage = {\n id: string;\n role: string;\n content?: string;\n toolCalls?: ThreadDebuggerToolCall[];\n toolCallId?: string;\n /** Present when role === \"activity\" (Generative UI output). */\n activityType?: string;\n};\n\nexport type ThreadDebuggerEvent = {\n type: string;\n timestamp: string | number;\n payload?: Record<string, unknown>;\n [key: string]: unknown;\n};\n\nexport type ThreadDebuggerMetadata = {\n id: string;\n name?: string | null;\n agentId?: string | null;\n endUserId?: string | null;\n createdById?: string | null;\n status?: string | null;\n createdAt?: string | null;\n updatedAt?: string | null;\n};\n\nexport type ThreadDebuggerProvider = {\n getThreadMetadata?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerMetadata | null>;\n getMessages?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerMessage[]>;\n getEvents?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<ThreadDebuggerEvent[]>;\n getState?: (\n threadId: string,\n options: ThreadDebuggerProviderLoadOptions,\n ) => Promise<Record<string, unknown> | null>;\n};\n\ninterface ConversationUser {\n id: string;\n type: \"user\";\n content: string;\n createdAt: string;\n}\n\ninterface ConversationAssistant {\n id: string;\n type: \"assistant\";\n content: string;\n createdAt: string;\n}\n\ninterface ConversationToolCall {\n id: string;\n type: \"tool_call\";\n toolName: string;\n toolCallId: string;\n arguments: Record<string, unknown>;\n result: Record<string, unknown> | null;\n hasResult: boolean;\n resultUnreadable?: boolean;\n createdAt: string;\n groupId?: string;\n}\n\ninterface ConversationReasoning {\n id: string;\n type: \"reasoning\";\n duration: string;\n createdAt: string;\n}\n\ninterface ConversationStateUpdate {\n id: string;\n type: \"state_update\";\n createdAt: string;\n}\n\ninterface ConversationAgentResponded {\n id: string;\n type: \"agent_responded\";\n createdAt: string;\n}\n\ninterface ConversationGenerativeUIItem {\n id: string;\n type: \"generative-ui\";\n activityType: string;\n createdAt: string;\n}\n\ninterface ToolCallGroup {\n type: \"tool_call_group\";\n id: string;\n items: ConversationToolCall[];\n}\n\ntype ConversationItem =\n | ConversationUser\n | ConversationAssistant\n | ConversationToolCall\n | ConversationReasoning\n | ConversationStateUpdate\n | ConversationAgentResponded\n | ConversationGenerativeUIItem;\n\ntype RenderItem = ConversationItem | ToolCallGroup;\n\ninterface ApiAgentEvent {\n type: string;\n timestamp: string | number;\n payload: Record<string, unknown>;\n sourceIndex?: number;\n rawEvent?: ThreadDebuggerEvent;\n}\n\ntype ThreadDetailsTab = \"timeline\" | \"state\" | \"raw-events\";\ntype ThreadDetailsPanelCacheSlot = ThreadDetailsTab | \"timeline-fallback\";\n\ntype TimelineItemKind =\n | \"message\"\n | \"tool\"\n | \"state\"\n | \"run\"\n | \"event\"\n | \"warning\";\n\ntype TimelineItem = {\n id: string;\n messageId?: string;\n kind: TimelineItemKind;\n title: string;\n body?: string;\n timestamp: string | number;\n sourceIndex: number;\n severity?: \"warning\" | \"error\";\n details?: Record<string, unknown>;\n};\n\ntype RuntimeEventsFetchResult =\n | { status: \"available\"; events: ThreadDebuggerEvent[] }\n | { status: \"not-available\" };\n\ntype RuntimeStateFetchResult =\n | { status: \"available\"; state: Record<string, unknown> | null }\n | { status: \"not-available\" };\n\ntype ExampleThread = ɵThread & { isExample: true };\n\ntype ExampleThreadDetails = {\n messages: ThreadDebuggerMessage[];\n events: ThreadDebuggerEvent[];\n state: Record<string, unknown>;\n};\n\nconst THREADS_EXAMPLE_THREADS: ExampleThread[] = [\n {\n id: \"example-realtime-sync\",\n name: \"Realtime thread sync\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-08T16:00:00.000Z\",\n updatedAt: \"2026-07-08T16:30:00.000Z\",\n isExample: true,\n },\n {\n id: \"example-manage-history\",\n name: \"Manage saved conversations\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-07T17:45:00.000Z\",\n updatedAt: \"2026-07-07T18:15:00.000Z\",\n isExample: true,\n },\n {\n id: \"example-inspect-runs\",\n name: \"Inspect durable run history\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n organizationId: \"example-organization\",\n createdById: \"example-user\",\n archived: false,\n createdAt: \"2026-07-06T20:15:00.000Z\",\n updatedAt: \"2026-07-06T20:45:00.000Z\",\n isExample: true,\n },\n];\n\n/** Map Sam's fixed example IDs to a closed telemetry vocabulary. */\nfunction getExampleKind(threadId: string): ExampleKind | undefined {\n switch (threadId) {\n case \"example-realtime-sync\":\n return \"realtime_sync\";\n case \"example-manage-history\":\n return \"manage_history\";\n case \"example-inspect-runs\":\n return \"inspect_runs\";\n default:\n return undefined;\n }\n}\n\nconst THREADS_EXAMPLE_DETAILS: Record<string, ExampleThreadDetails> = {\n \"example-realtime-sync\": {\n messages: [\n {\n id: \"example-sync-user\",\n role: \"user\",\n content: \"Resume the checkout support thread from yesterday.\",\n },\n {\n id: \"example-sync-assistant\",\n role: \"assistant\",\n content:\n \"I found the saved thread, restored the cart state, and continued from the latest user message.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-08T16:30:00.000Z\",\n payload: {\n threadId: \"example-realtime-sync\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"MESSAGES_SNAPSHOT\",\n timestamp: \"2026-07-08T16:30:01.000Z\",\n payload: {\n messageCount: 6,\n source: \"thread-history\",\n },\n },\n {\n type: \"STATE_SNAPSHOT\",\n timestamp: \"2026-07-08T16:30:02.000Z\",\n payload: {\n cartId: \"cart_demo_42\",\n checkoutStep: \"shipping\",\n resumed: true,\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-08T16:30:04.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n cartId: \"cart_demo_42\",\n checkoutStep: \"shipping\",\n userIntent: \"resume_previous_checkout\",\n persistedThread: true,\n },\n },\n \"example-manage-history\": {\n messages: [\n {\n id: \"example-history-user\",\n role: \"user\",\n content: \"Rename this saved support conversation for the handoff.\",\n },\n {\n id: \"example-history-assistant\",\n role: \"assistant\",\n content:\n \"Renamed the thread and kept the prior messages available for the next session.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-07T18:15:00.000Z\",\n payload: {\n threadId: \"example-manage-history\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"CUSTOM_EVENT\",\n timestamp: \"2026-07-07T18:15:01.000Z\",\n payload: {\n action: \"thread_renamed\",\n previousName: \"Untitled\",\n name: \"Billing escalation handoff\",\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-07T18:15:03.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n name: \"Billing escalation handoff\",\n savedMessages: 14,\n lastHandoff: \"support-team\",\n },\n },\n \"example-inspect-runs\": {\n messages: [\n {\n id: \"example-inspect-user\",\n role: \"user\",\n content: \"Why did the assistant recommend the enterprise plan?\",\n },\n {\n id: \"example-inspect-assistant\",\n role: \"assistant\",\n content:\n \"The recommendation came from the account size, SSO requirement, and audit-log constraint in state.\",\n },\n ],\n events: [\n {\n type: \"RUN_STARTED\",\n timestamp: \"2026-07-06T20:45:00.000Z\",\n payload: {\n threadId: \"example-inspect-runs\",\n agentId: THREADS_EXAMPLE_AGENT_ID,\n },\n },\n {\n type: \"TOOL_CALL_START\",\n timestamp: \"2026-07-06T20:45:01.000Z\",\n payload: {\n toolCallId: \"call_account_lookup\",\n toolName: \"lookupAccount\",\n },\n },\n {\n type: \"TOOL_CALL_RESULT\",\n timestamp: \"2026-07-06T20:45:02.000Z\",\n payload: {\n toolCallId: \"call_account_lookup\",\n seats: 220,\n requiresSso: true,\n },\n },\n {\n type: \"RUN_FINISHED\",\n timestamp: \"2026-07-06T20:45:04.000Z\",\n payload: {\n status: \"completed\",\n },\n },\n ],\n state: {\n accountTier: \"growth\",\n seats: 220,\n requiresSso: true,\n auditLogsRequired: true,\n },\n },\n};\n\nconst THREADS_EXAMPLE_TOUR_STEPS: ReadonlyArray<{\n tab: ThreadDetailsTab;\n label: string;\n title: string;\n body: string;\n}> = [\n {\n tab: \"timeline\",\n label: \"Conversation\",\n title: \"Read the run as a story\",\n body: \"Read messages and tool calls as a conversation. Switch to the event timeline to inspect state changes and run markers.\",\n },\n {\n tab: \"raw-events\",\n label: \"AG-UI Events\",\n title: \"Drop into the protocol payloads\",\n body: \"Raw events show the exact AG-UI stream behind the timeline when you need to verify ordering or payload shape.\",\n },\n {\n tab: \"state\",\n label: \"State\",\n title: \"Check the durable state\",\n body: \"The state tab shows the saved values that make a thread resumable across sessions.\",\n },\n];\n\ntype ExampleTourTelemetryPair = Readonly<{\n tour_step: ExampleTourStep;\n tour_tab: ExampleTourTab;\n}>;\n\n/** Return only the three supported tour step/tab pairs. */\nfunction getExampleTourTelemetryPair(\n index: number,\n): ExampleTourTelemetryPair | undefined {\n switch (index) {\n case 0:\n return { tour_step: 1, tour_tab: \"timeline\" };\n case 1:\n return { tour_step: 2, tour_tab: \"raw-events\" };\n case 2:\n return { tour_step: 3, tour_tab: \"state\" };\n default:\n return undefined;\n }\n}\n\n/** Convert rendered action placement to its stable telemetry key. */\nfunction getMetadataActionPlacement(\n placement: \"threads-footer\" | \"locked\",\n): MetadataActionPlacement {\n return placement === \"threads-footer\" ? \"threads_footer\" : \"threads_locked\";\n}\n\n// ─── JSON syntax highlighter ─────────────────────────────────────────────────\n// Inline-styled so shadow DOM encapsulation preserves colors when the output\n// is injected via unsafeHTML. Only for structured data — never raw user HTML.\n\nfunction escapeHtml(s: string): string {\n return s.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\");\n}\n\n// Memoize highlight output by payload reference. Tab switches cause Lit to\n// re-render the active panel from scratch, and the JSON.stringify + regex\n// pass below is by far the most expensive thing in the events / state\n// panels (potentially MB of agent state). Caching by object reference\n// turns subsequent renders of an unchanged event list into near-zero JS work.\nconst highlightedJsonCache = new WeakMap<object, string>();\n\nfunction highlightedJson(obj: unknown): string {\n if (typeof obj === \"object\" && obj !== null) {\n const cached = highlightedJsonCache.get(obj);\n if (cached !== undefined) return cached;\n }\n const json = JSON.stringify(obj, null, 2);\n if (!json) return \"\";\n const parts: string[] = [];\n let lastIndex = 0;\n const re =\n /(\"(?:\\\\u[a-fA-F0-9]{4}|\\\\[^u]|[^\\\\\"])*\"(?:\\s*:)?|\\b(?:true|false|null)\\b|-?\\d+(?:\\.\\d*)?(?:[eE][+-]?\\d+)?)/g;\n let match: RegExpExecArray | null;\n while ((match = re.exec(json)) !== null) {\n parts.push(escapeHtml(json.slice(lastIndex, match.index)));\n const m = match[0];\n let token = \"num\";\n if (m.startsWith('\"')) {\n token = m.trimEnd().endsWith(\":\") ? \"key\" : \"str\";\n } else if (m === \"true\" || m === \"false\") {\n token = \"bool\";\n } else if (m === \"null\") {\n token = \"nil\";\n }\n parts.push(\n `<span class=\"cpk-json-token cpk-json-token--${token}\">${escapeHtml(m)}</span>`,\n );\n lastIndex = match.index + m.length;\n }\n parts.push(escapeHtml(json.slice(lastIndex)));\n const result = parts.join(\"\");\n if (typeof obj === \"object\" && obj !== null) {\n highlightedJsonCache.set(obj, result);\n }\n return result;\n}\n\nfunction coerceJsonValue(value: unknown): unknown {\n if (typeof value !== \"string\") {\n return value;\n }\n\n const trimmed = value.trim();\n if (trimmed.length === 0) {\n return value;\n }\n\n const looksJson =\n (trimmed.startsWith(\"{\") && trimmed.endsWith(\"}\")) ||\n (trimmed.startsWith(\"[\") && trimmed.endsWith(\"]\"));\n if (!looksJson) {\n return value;\n }\n\n try {\n return JSON.parse(trimmed);\n } catch {\n return value;\n }\n}\n\nfunction renderHighlightedJsonBlock(\n value: unknown,\n options: { maxHeight?: string } = {},\n) {\n const parsed = coerceJsonValue(value);\n const style = options.maxHeight\n ? `max-height:${options.maxHeight}`\n : undefined;\n return html`<pre class=\"cpk-json-block\" style=${style || nothing}>\n${unsafeHTML(highlightedJson(parsed))}</pre\n >`;\n}\n\nfunction humanizeEventType(type: string): string {\n const words = type\n .trim()\n .split(/[_\\s]+/)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n if (words.length === 0) return \"Event\";\n const [first = \"event\", ...rest] = words;\n return [`${first.charAt(0).toUpperCase()}${first.slice(1)}`, ...rest].join(\n \" \",\n );\n}\n\nfunction messageTitle(role: string): string {\n const normalized = role.trim() || \"message\";\n const label = `${normalized.charAt(0).toUpperCase()}${normalized.slice(1).toLowerCase()}`;\n return `${label} message`;\n}\n\nfunction eventCategory(\n type: string,\n): \"message\" | \"tool\" | \"state\" | \"run\" | \"error\" | \"event\" {\n if (type === \"RUN_ERROR\" || type === \"ERROR\") return \"error\";\n if (type.startsWith(\"TEXT_MESSAGE\")) return \"message\";\n if (type.startsWith(\"TOOL_CALL\")) return \"tool\";\n if (type.startsWith(\"STATE\") || type.startsWith(\"MESSAGES\")) return \"state\";\n if (type.startsWith(\"RUN_\") || type.startsWith(\"STEP_\")) return \"run\";\n return \"event\";\n}\n\nfunction formatTimestamp(ts: string | number): string {\n const date = typeof ts === \"number\" ? new Date(ts) : new Date(ts);\n if (Number.isNaN(date.getTime())) return \"\";\n const ms = date.getMilliseconds().toString().padStart(3, \"0\");\n return (\n date.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n }) +\n \".\" +\n ms\n );\n}\n\nfunction formatRelativeTimestamp(ts: string | number): string {\n const date = new Date(ts);\n if (Number.isNaN(date.getTime())) return \"\";\n\n const elapsedSeconds = Math.max(\n 1,\n Math.floor((Date.now() - date.getTime()) / 1_000),\n );\n if (elapsedSeconds < 60) {\n return `${elapsedSeconds} ${elapsedSeconds === 1 ? \"second\" : \"seconds\"} ago`;\n }\n\n const elapsedMinutes = Math.floor(elapsedSeconds / 60);\n return `${elapsedMinutes} ${elapsedMinutes === 1 ? \"minute\" : \"minutes\"} ago`;\n}\n\n/**\n * Lit's constructable stylesheets belong to the document that created them.\n * These child elements move between the app and pop-out documents, so keep\n * their styles as shadow-root style nodes that travel with the live element.\n */\nabstract class PortableLitElement extends LitElement {\n protected override createRenderRoot(): HTMLElement | DocumentFragment {\n const elementClass = this.constructor as unknown as {\n elementStyles: readonly (CSSStyleSheet | { cssText: string })[];\n shadowRootOptions: ShadowRootInit;\n };\n const renderRoot =\n this.shadowRoot ?? this.attachShadow(elementClass.shadowRootOptions);\n\n for (const style of elementClass.elementStyles) {\n const styleElement = this.ownerDocument.createElement(\"style\");\n styleElement.textContent =\n \"cssText\" in style\n ? style.cssText\n : Array.from(style.cssRules, (rule) => rule.cssText).join(\"\");\n renderRoot.append(styleElement);\n }\n\n return renderRoot;\n }\n}\n\n// ─── cpk-thread-list ────────────────────────────────────────────────────────\n\nclass CpkThreadList extends PortableLitElement {\n static properties = {\n threads: { attribute: false },\n selectedThreadId: { attribute: false },\n inAppThreadId: { attribute: false },\n errorMessage: { attribute: false },\n suppressEmptyState: { attribute: false },\n _query: { state: true },\n };\n threads: ɵThread[] = [];\n selectedThreadId: string | null = null;\n inAppThreadId: string | null = null;\n /**\n * Non-null when the underlying thread store reported a load error\n * (REST list rejection, Phoenix subscribe failure, retry exhaustion).\n * Surfaced inline so users see a real error state instead of stale or\n * empty data with no indication of what went wrong.\n */\n errorMessage: string | null = null;\n suppressEmptyState = false;\n private _query = \"\";\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .cpk-tl {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: #f7f7f9;\n }\n\n /* ── Search ── */\n .cpk-tl__search {\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n\n .cpk-tl__search-input {\n width: 100%;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .cpk-tl__search-input:focus {\n border-color: #bec2ff;\n }\n\n /* ── List ── */\n .cpk-tl__list {\n flex: 1;\n overflow-y: auto;\n }\n\n /* ── Thread item ── */\n .cpk-tl__item {\n appearance: none;\n display: block;\n box-sizing: border-box;\n width: 100%;\n margin: 0;\n border: 0;\n border-radius: 0;\n padding: 11px 13px;\n background: transparent;\n color: inherit;\n font: inherit;\n text-align: left;\n cursor: pointer;\n border-bottom: 1px solid #e9e9ef;\n border-left: 3px solid transparent;\n transition: background 0.1s;\n }\n\n .cpk-tl__item:hover {\n background: #ffffff;\n }\n\n .cpk-tl__item--active {\n background: #bec2ff1a;\n border-left-color: #bec2ff;\n }\n\n .cpk-tl__item--active:hover {\n background: #bec2ff33;\n }\n\n .cpk-tl__item:focus-visible {\n outline-color: #5558b2;\n outline-offset: -2px;\n outline-style: solid;\n outline-width: 2px;\n }\n\n .cpk-tl__row1 {\n display: flex;\n align-items: center;\n gap: 8px;\n margin-bottom: 3px;\n }\n\n .cpk-tl__name {\n font-size: 12px;\n font-weight: 500;\n color: #010507;\n flex: 1;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-tl__name--unnamed {\n color: #68686e;\n font-style: italic;\n font-weight: 400;\n }\n\n .cpk-tl__time {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-tl__meta {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n .cpk-tl__pill {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n background: #eee6fe;\n color: #57575b;\n }\n\n .cpk-tl__pill--example {\n background: rgba(133, 236, 206, 0.22);\n color: #087653;\n }\n\n .cpk-tl__pill--in-app {\n background: #bec2ff;\n color: #010507;\n }\n\n /* ── Empty state ── */\n .cpk-tl__empty {\n padding: 32px 16px;\n text-align: center;\n color: #68686e;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .cpk-tl__empty-icon {\n color: #c0c0c8;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl {\n background: #15171e;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__search,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__search-input {\n border-color: #464957;\n background: #191c24;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item:hover {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item--active,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__item--active:hover {\n background: #292b43;\n border-left-color: #8f93df;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__name {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__name--unnamed,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__time,\n :host([data-color-scheme=\"dark\"]) .cpk-tl__empty {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tl__pill {\n background: #302b43;\n color: #d8d9ff;\n }\n `;\n\n private relativeTime(dateStr: string): string {\n const date = new Date(dateStr);\n const diffMs = Date.now() - date.getTime();\n const diffSec = Math.floor(diffMs / 1000);\n if (diffSec < 60) return `${diffSec}s ago`;\n const diffMin = Math.floor(diffSec / 60);\n if (diffMin < 60) return `${diffMin}m ago`;\n const diffH = Math.floor(diffMin / 60);\n if (diffH < 24) return `${diffH}h ago`;\n const diffD = Math.floor(diffH / 24);\n return `${diffD}d ago`;\n }\n\n private get filtered(): ɵThread[] {\n const q = this._query.toLowerCase();\n if (!q) return this.threads;\n return this.threads.filter(\n (t) =>\n (t.name?.toLowerCase().includes(q) ?? false) ||\n t.agentId.toLowerCase().includes(q) ||\n t.id.toLowerCase().includes(q),\n );\n }\n\n private onThreadClick(threadId: string): void {\n this.dispatchEvent(\n new CustomEvent(\"threadSelected\", {\n detail: threadId,\n bubbles: true,\n composed: true,\n }),\n );\n }\n\n private onSearchInput = (event: Event): void => {\n this._query = (event.target as HTMLInputElement).value;\n };\n\n render() {\n const filtered = this.filtered;\n return html`\n <div class=\"cpk-tl\">\n <!-- Search -->\n <div class=\"cpk-tl__search\">\n <input\n type=\"text\"\n placeholder=\"Search threads…\"\n .value=${this._query}\n @input=${this.onSearchInput}\n class=\"cpk-tl__search-input\"\n />\n </div>\n\n <!-- Thread list -->\n <div class=\"cpk-tl__list\">\n ${filtered.map(\n (thread) => html`\n <button\n type=\"button\"\n aria-current=${\n this.selectedThreadId === thread.id ? \"true\" : nothing\n }\n class=\"cpk-tl__item ${\n this.selectedThreadId === thread.id\n ? \"cpk-tl__item--active\"\n : \"\"\n }\"\n @click=${() => this.onThreadClick(thread.id)}\n >\n <span class=\"cpk-tl__row1\">\n <span\n class=\"cpk-tl__name ${\n !thread.name ? \"cpk-tl__name--unnamed\" : \"\"\n }\"\n >${thread.name ?? \"Untitled\"}</span\n >\n <span class=\"cpk-tl__time\"\n >${this.relativeTime(thread.updatedAt)}</span\n >\n </span>\n <span class=\"cpk-tl__meta\">\n <span class=\"cpk-tl__pill\">${thread.agentId}</span>\n ${\n (thread as Partial<ExampleThread>).isExample\n ? html`\n <span class=\"cpk-tl__pill cpk-tl__pill--example\">Example</span>\n `\n : nothing\n }\n ${\n this.inAppThreadId === thread.id\n ? html`\n <span class=\"cpk-tl__pill cpk-tl__pill--in-app\">In app</span>\n `\n : nothing\n }\n </span>\n </button>\n `,\n )}\n ${\n filtered.length === 0 && !this.suppressEmptyState\n ? html`\n <div class=\"cpk-tl__empty\">\n ${\n this.errorMessage\n ? html`\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-tl__empty-icon\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <div>\n Failed to load threads\n <div\n style=\"font-size:11px;margin-top:4px;color:#c0333a;\"\n >\n ${this.errorMessage}\n </div>\n </div>\n `\n : this.threads.length === 0\n ? html`\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-tl__empty-icon\"\n >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n No threads yet\n `\n : html`\n No threads match your search.\n `\n }\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n }\n}\n\n// ─── cpk-thread-inspector ────────────────────────────────────────────────────\n// Renders the selected thread's read-only timeline, state, raw AG-UI events,\n// and compact technical metadata. External hosts provide a ThreadDebuggerProvider;\n// the legacy CopilotKit Inspector wrapper can still pass runtime URL inputs.\nexport class CpkThreadInspector extends PortableLitElement {\n static properties = {\n threadId: { attribute: false },\n showThreadTitle: { type: Boolean, attribute: false },\n provider: { attribute: false },\n thread: { attribute: false },\n runtimeUrl: { attribute: false },\n headers: { attribute: false },\n threadInspectionAvailable: { attribute: false },\n agentStateInput: { attribute: false },\n agentEventsInput: { attribute: false },\n agentMessagesInput: { attribute: false },\n liveMessageVersion: { attribute: false },\n viewInAppMode: { attribute: false },\n viewInAppError: { attribute: false },\n focusMessageId: { attribute: false },\n focusRequestId: { attribute: false },\n tryFromHereAvailable: { attribute: false },\n tryFromHereBusy: { attribute: false },\n tryFromHereError: { attribute: false },\n _tab: { state: true },\n _fetchedMetadata: { state: true },\n _conversation: { state: true },\n _fetchedEvents: { state: true },\n _fetchedState: { state: true },\n _loadingMessages: { state: true },\n _loadingEvents: { state: true },\n _loadingState: { state: true },\n _messagesError: { state: true },\n _messageRefreshError: { state: true },\n _eventsError: { state: true },\n _stateError: { state: true },\n _expandedTools: { state: true },\n _expandedMessages: { state: true },\n _expandedTimelineDetails: { state: true },\n _expandedRawEvents: { state: true },\n _showDetailPanel: { state: true },\n _detailPanelWidth: { state: true },\n _eventsNotAvailable: { state: true },\n _stateNotAvailable: { state: true },\n _panelInitializing: { state: true },\n _activatedTabs: { state: true },\n };\n\n /** Whether to render the viewer title. Set false when the embedding page owns its heading. */\n showThreadTitle = true;\n threadId: string | null = null;\n provider: ThreadDebuggerProvider | null = null;\n thread: ThreadDebuggerMetadata | ɵThread | null = null;\n runtimeUrl = \"\";\n headers: Record<string, string> = {};\n threadInspectionAvailable = false;\n agentStateInput: Record<string, unknown> | null = null;\n agentEventsInput: ApiAgentEvent[] = [];\n agentMessagesInput: ReadonlyArray<{\n id?: string;\n role: string;\n contentText: string;\n }> = EMPTY_INSPECTOR_MESSAGES;\n /**\n * Monotonic per-thread counter the parent inspector ticks every time the\n * agent currently running on this thread emits a message change. When this\n * prop changes for the same `threadId`, we re-fetch `/threads/:id/messages`\n * so the conversation view reflects live streaming output.\n */\n liveMessageVersion = 0;\n viewInAppMode: \"hidden\" | \"view\" | \"stop\" = \"hidden\";\n viewInAppError: string | null = null;\n focusMessageId: string | null = null;\n focusRequestId = 0;\n tryFromHereAvailable = false;\n tryFromHereBusy = false;\n tryFromHereError: string | null = null;\n\n private _tab: ThreadDetailsTab = \"timeline\";\n private _showEventTimeline = false;\n private _fetchedMetadata: ThreadDebuggerMetadata | null = null;\n private _conversation: ConversationItem[] = [];\n private _fetchedEvents: ApiAgentEvent[] | null = null;\n private _fetchedState: Record<string, unknown> | null = null;\n private _loadingMessages = false;\n private _loadingEvents = false;\n private _loadingState = false;\n private _messagesError: string | null = null;\n private _messageRefreshError: string | null = null;\n private _eventsError: string | null = null;\n private _stateError: string | null = null;\n private _expandedTools = new Set<string>();\n private _expandedMessages = new Set<string>();\n private _expandedTimelineDetails = new Set<string>();\n private _expandedRawEvents = new Set<string>();\n private _showDetailPanel = false;\n private _detailPanelWidth = 250;\n /** True when the /events endpoint returned 501 — don't fall back to live data. */\n private _eventsNotAvailable = false;\n /** True when the /state endpoint returned 501 — don't fall back to live data. */\n private _stateNotAvailable = false;\n private _scrolledFocusRequestId = 0;\n private _highlightedFocusRequestId = -1;\n /**\n * Briefly true after a tab switch so the active-tab highlight + a generic\n * \"Loading…\" placeholder paint before the heavy per-tab render runs. Without\n * this, large event/conversation lists block the next paint and the user\n * sees the click as unresponsive for seconds.\n */\n private _panelInitializing = false;\n /**\n * Tabs that have been opened at least once for the current thread. Once a\n * tab is activated, its rendered DOM stays mounted (we hide inactive tabs\n * via display:none) so flipping back to it is just a CSS swap rather than\n * tearing down and rebuilding the entire panel from scratch. Without this,\n * switching back to AG-UI Events on a thread with hundreds of events\n * triggers a multi-second DOM-creation pass each time.\n *\n * Reset to {\"timeline\"} when the selected thread changes.\n */\n private _activatedTabs: Set<ThreadDetailsTab> = new Set([\"timeline\"]);\n /**\n * Memoized per-panel templates keyed by the inputs they render from.\n * When the underlying data hasn't changed (same `_conversation` /\n * `_fetchedState` / events array reference, plus expand-state for the\n * conversation panel), we return the previously built TemplateResult.\n * Lit then sees \"same template, same values\" and skips the diff entirely,\n * so re-rendering on tab switch is near-zero work even when the panel\n * content is large. The key is an opaque tuple compared element-wise by\n * reference; if any element flips, the cache misses and rebuilds.\n */\n private _panelTplCache: Map<\n ThreadDetailsPanelCacheSlot,\n { key: readonly unknown[]; tpl: TemplateResult }\n > = new Map();\n private _timelineItemsCache: {\n events: ApiAgentEvent[];\n conversation: ConversationItem[];\n agentMessages: CpkThreadInspector[\"agentMessagesInput\"];\n items: TimelineItem[];\n } | null = null;\n private _liveEventsWithSourceIndexCache: {\n events: ApiAgentEvent[];\n indexedEvents: ApiAgentEvent[];\n } | null = null;\n /**\n * Tracks whether we've fetched events for the current thread yet. Events\n * fetch lazily on first sub-tab click so a large response's JSON.parse\n * doesn't block the main thread when the user only ever cares about the\n * conversation.\n */\n private _eventsFetched = false;\n /**\n * Tracks whether we've fetched state for the current thread yet. Same\n * lazy-load reasoning as `_eventsFetched`.\n */\n private _stateFetched = false;\n private _lastLoadKey: string | null = null;\n private _lastSeenLiveMessageVersion = 0;\n private _metadataAbort: AbortController | null = null;\n private _messagesAbort: AbortController | null = null;\n private _eventsAbort: AbortController | null = null;\n private _stateAbort: AbortController | null = null;\n private _hasConnectedOnce = false;\n private _dividerResizing = false;\n private _dividerPointerId = -1;\n private _dividerStartX = 0;\n private _dividerStartWidth = 0;\n private static nextDomId = 1;\n private readonly domIdPrefix = `cpk-thread-detail-${CpkThreadInspector.nextDomId++}`;\n\n static readonly COLLAPSE_THRESHOLD = 800;\n static readonly TAB_LIST: ReadonlyArray<{\n id: ThreadDetailsTab;\n label: string;\n }> = [\n { id: \"timeline\", label: \"Conversation\" },\n { id: \"raw-events\", label: \"AG-UI Events\" },\n { id: \"state\", label: \"State\" },\n ];\n\n private static providerIds = new WeakMap<ThreadDebuggerProvider, number>();\n private static nextProviderId = 1;\n\n private static providerLoadKey(\n provider: ThreadDebuggerProvider | null,\n ): string {\n if (!provider) return \"provider:none\";\n let id = CpkThreadInspector.providerIds.get(provider);\n if (!id) {\n id = CpkThreadInspector.nextProviderId;\n CpkThreadInspector.nextProviderId += 1;\n CpkThreadInspector.providerIds.set(provider, id);\n }\n return [\n `provider:${id}`,\n provider.getThreadMetadata ? \"metadata:1\" : \"metadata:0\",\n provider.getMessages ? \"messages:1\" : \"messages:0\",\n provider.getEvents ? \"events:1\" : \"events:0\",\n provider.getState ? \"state:1\" : \"state:0\",\n ].join(\"|\");\n }\n\n /**\n * Build a deterministic signature for runtime fetch headers so auth/CSRF\n * changes invalidate cached thread data even when the selected thread is\n * otherwise unchanged.\n */\n private static headersLoadKey(headers: Record<string, string>): string {\n return JSON.stringify(\n Object.entries(headers).sort(([leftKey], [rightKey]) =>\n leftKey.localeCompare(rightKey),\n ),\n );\n }\n\n private renderConversationActions() {\n return html`<div class=\"cpk-td__timeline-toolbar\">\n <button type=\"button\" class=\"cpk-td__timeline-bulk-toggle\" aria-pressed=${this._showEventTimeline} @click=${() => {\n this._showEventTimeline = !this._showEventTimeline;\n this.requestUpdate();\n }}>${this._showEventTimeline ? \"Show conversation\" : \"Show event timeline\"}</button>\n ${this.renderTryFromHereControl()}\n </div>`;\n }\n\n private renderTabContent(id: ThreadDetailsTab): TemplateResult {\n if (id === \"timeline\") {\n return html`${\n this._messageRefreshError\n ? html`<div class=\"cpk-td__status cpk-td__status--error\" role=\"status\">${this._messageRefreshError}</div>`\n : nothing\n }${\n this._showEventTimeline\n ? html`<div class=\"cpk-td__timeline-toolbar\">${this.renderTimelineBulkButtons()}</div>${this.renderTimeline()}`\n : this._conversation.length ||\n this._loadingMessages ||\n this._messagesError\n ? this.renderConversation()\n : this.renderTimeline()\n }`;\n }\n if (id === \"state\") return this.renderState();\n return this.renderEvents();\n }\n\n /** Returns the stable DOM ID for one tab in this inspector instance. */\n private tabDomId(id: ThreadDetailsTab): string {\n return `${this.domIdPrefix}-tab-${id}`;\n }\n\n /** Returns the stable DOM ID for the panel controlled by one tab. */\n private panelDomId(id: ThreadDetailsTab): string {\n return `${this.domIdPrefix}-panel-${id}`;\n }\n\n /** Selects and focuses the tab targeted by an ARIA tabs navigation key. */\n private handleTabKeyDown(\n event: KeyboardEvent,\n currentId: ThreadDetailsTab,\n ): void {\n const currentIndex = CpkThreadInspector.TAB_LIST.findIndex(\n (tab) => tab.id === currentId,\n );\n if (currentIndex < 0) return;\n\n let targetIndex: number | null = null;\n if (event.key === \"ArrowRight\") {\n targetIndex = (currentIndex + 1) % CpkThreadInspector.TAB_LIST.length;\n } else if (event.key === \"ArrowLeft\") {\n targetIndex =\n (currentIndex - 1 + CpkThreadInspector.TAB_LIST.length) %\n CpkThreadInspector.TAB_LIST.length;\n } else if (event.key === \"Home\") {\n targetIndex = 0;\n } else if (event.key === \"End\") {\n targetIndex = CpkThreadInspector.TAB_LIST.length - 1;\n }\n if (targetIndex === null) return;\n\n const target = CpkThreadInspector.TAB_LIST[targetIndex];\n if (!target) return;\n event.preventDefault();\n this.activateTab(target.id);\n this.shadowRoot\n ?.querySelector<HTMLButtonElement>(`#${this.tabDomId(target.id)}`)\n ?.focus();\n }\n\n private activateTab(id: ThreadDetailsTab): void {\n if (this._tab === id) return;\n const isFirstActivation = !this._activatedTabs.has(id);\n this._tab = id;\n if (isFirstActivation) {\n // First time opening this tab: paint a \"Loading…\" overlay for one\n // frame so the tab highlight + spinner appear before the heavy\n // per-tab render runs (events list, state JSON). The rAF batches\n // mounting the panel into `_activatedTabs` and clearing the spinner\n // into a single subsequent paint. Subsequent activations are pure\n // CSS toggles via display:none on the already-mounted panel — no\n // re-render required.\n this._panelInitializing = true;\n requestAnimationFrame(() => {\n this._activatedTabs = new Set([...this._activatedTabs, id]);\n this._panelInitializing = false;\n });\n }\n this.maybeFetchTabData(id);\n }\n\n selectTab(id: ThreadDetailsTab): void {\n this.activateTab(id);\n }\n\n private maybeFetchTabData(id: ThreadDetailsTab): void {\n // Lazy-trigger the events / state fetches so their (potentially huge)\n // JSON.parse only blocks the main thread after the user has shown\n // intent to view that sub-tab. Without lazy-load, the eager fetch runs\n // as soon as the thread opens and a single large response can stall\n // the entire panel for seconds — including making the tab buttons\n // themselves feel unresponsive.\n if (!this.threadId) return;\n if ((id === \"timeline\" || id === \"raw-events\") && !this._eventsFetched) {\n this._eventsFetched = true;\n void this.fetchEvents(this.threadId);\n } else if (id === \"state\" && !this._stateFetched) {\n this._stateFetched = true;\n void this.fetchState(this.threadId);\n }\n }\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n /* ── Root ────────────────────────────────────────────────────────── */\n :host {\n display: flex;\n flex-direction: row;\n overflow: hidden;\n --cpk-json-key: #3d408f;\n --cpk-json-str: #0b6b4c;\n --cpk-json-num: #8a5900;\n --cpk-json-bool: #c0333a;\n --cpk-json-nil: #57575b;\n }\n\n .cpk-td {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 13px;\n display: flex;\n flex-direction: row;\n width: 100%;\n height: 100%;\n overflow: hidden;\n background: #ffffff;\n }\n\n /* ── Left area ───────────────────────────────────────────────────── */\n .cpk-td__left {\n flex: 1;\n min-width: 0;\n display: flex;\n flex-direction: column;\n overflow: hidden;\n }\n\n /* ── Tab bar header ──────────────────────────────────────────────── */\n .cpk-td__tabs-header {\n /* No top/right padding so tabs and toggle sit flush against the\n top and right edges of the inspector. */\n padding: 0 0 0 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n display: flex;\n align-items: stretch;\n }\n\n .cpk-td__tab-group {\n display: flex;\n gap: 0;\n margin-bottom: -1px;\n /* Allow the tab list to shrink rather than pushing the panel-toggle\n button past the right edge of the inspector when horizontal space\n gets tight (the drawer being open eats noticeably into width). */\n min-width: 0;\n flex-shrink: 1;\n overflow: hidden;\n }\n\n .cpk-td__tab {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 10px 12px;\n border: none;\n border-bottom: 2px solid transparent;\n cursor: pointer;\n background: transparent;\n color: #68686e;\n transition:\n color 0.12s,\n border-color 0.12s;\n white-space: nowrap;\n }\n\n .cpk-td__tab:hover {\n color: #010507;\n }\n\n .cpk-td__tab:focus-visible {\n outline: 2px solid #5558b2;\n outline-offset: -3px;\n border-radius: 5px;\n }\n\n .cpk-td__tab--active {\n color: #010507;\n border-bottom-color: #bec2ff;\n }\n\n /* Toggle is a separate control, not a tab — so it does NOT use the\n tabs' bottom-border active indicator. Instead, a subtle filled\n state communicates \"the drawer is open,\" and a vertical separator\n on the left visually divorces it from the tab group. */\n .cpk-td__panel-toggle {\n margin-left: auto;\n align-self: stretch;\n display: flex;\n align-items: center;\n justify-content: center;\n padding: 0 12px;\n border: none;\n border-left: 1px solid #dbdbe5;\n background: transparent;\n color: #68686e;\n cursor: pointer;\n flex-shrink: 0;\n transition:\n color 0.12s,\n background 0.12s;\n }\n .cpk-td__panel-toggle:hover {\n color: #010507;\n background: #f4f4f9;\n }\n .cpk-td__panel-toggle--active {\n color: #5558b2;\n background: #eee6fe;\n }\n .cpk-td__panel-toggle--active:hover {\n background: #e4d8fc;\n }\n\n /* ── Scrollable content ──────────────────────────────────────────── */\n .cpk-td__content {\n flex: 1;\n overflow-y: auto;\n padding: 16px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* Pin direct children so expanded tool bodies don't get flex-shrunk. */\n .cpk-td__content > * {\n flex-shrink: 0;\n }\n\n .cpk-td__chrome-actions {\n margin-inline-start: auto;\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n justify-content: flex-end;\n gap: 6px;\n padding-inline: 8px;\n min-width: 0;\n }\n\n .cpk-td__chrome-actions + .cpk-td__panel-toggle {\n margin-inline-start: 0;\n }\n\n .cpk-td__thread-header {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 10px 16px;\n padding: 12px 16px;\n flex-shrink: 0;\n border-bottom: 1px solid #dbdbe540;\n }\n .cpk-td__thread-title {\n flex: 1 1 180px;\n min-width: 0;\n overflow-wrap: anywhere;\n font-size: 15px;\n font-weight: 600;\n }\n .cpk-td__pinned-actions {\n margin-left: auto;\n max-width: 100%;\n }\n .cpk-td__pinned-actions .cpk-td__timeline-toolbar {\n justify-content: flex-end;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__bubble-inner--assistant {\n background: transparent;\n color: #e7e7ed;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__bubble-inner--user {\n background: #27272a;\n color: #f4f4f5;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__show-more {\n color: #c5b5ff;\n }\n .cpk-td__timeline-bulk-toggle[aria-pressed=\"true\"] {\n background: #ece7fa;\n color: #51418b;\n }\n .cpk-td__bubble-inner {\n line-height: 1.65;\n overflow-wrap: anywhere;\n }\n .cpk-td__metadata-strip {\n display: flex;\n flex-direction: column;\n gap: 8px;\n padding: 10px 16px;\n border-bottom: 1px solid #e9e9ef;\n background: #fbfbfd;\n flex-shrink: 0;\n }\n\n .cpk-td__metadata-pills {\n display: flex;\n align-items: center;\n gap: 6px;\n width: 100%;\n min-width: 0;\n flex-wrap: nowrap;\n }\n\n .cpk-td__metadata-pill {\n display: inline-flex;\n align-items: center;\n gap: 6px;\n flex: 1 1 0;\n min-width: 0;\n height: 24px;\n padding: 0 8px;\n border: 1px solid #dbdbe5;\n border-radius: 6px;\n background: #ffffff;\n color: #57575b;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n white-space: nowrap;\n }\n\n .cpk-td__metadata-label {\n color: #68686e;\n text-transform: uppercase;\n font-size: 9px;\n }\n\n .cpk-td__metadata-value {\n min-width: 0;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__metadata-value--wrap,\n .cpk-td__metadata-pill--wrap {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__view-in-app {\n appearance: none;\n flex-shrink: 0;\n margin: 0;\n border: 1px solid #5558b2;\n border-radius: 6px;\n background: #5558b2;\n color: #ffffff;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n line-height: 1.2;\n min-height: 24px;\n padding: 3px 8px;\n cursor: pointer;\n transition:\n transform 160ms cubic-bezier(0.23, 1, 0.32, 1),\n background 120ms ease,\n color 120ms ease,\n border-color 120ms ease;\n }\n\n .cpk-td__view-in-app:focus-visible {\n outline: 2px solid #010507;\n outline-offset: 2px;\n }\n\n .cpk-td__view-in-app:active {\n transform: scale(0.96);\n }\n\n .cpk-td__view-in-app--stop {\n background: #ffffff;\n color: #5558b2;\n }\n\n .cpk-td__view-in-app-error {\n flex-basis: 100%;\n color: #c0333a;\n font-size: 11px;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-td__view-in-app {\n transition: none;\n }\n\n .cpk-td__view-in-app:active {\n transform: none;\n }\n }\n\n .cpk-td__try-from-here {\n display: inline-flex;\n align-items: center;\n gap: 4px;\n margin-inline-start: auto;\n padding: 6px 10px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #ffffff;\n color: #36363a;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n cursor: pointer;\n }\n\n .cpk-td__try-from-here-icon {\n display: block;\n flex-shrink: 0;\n }\n\n :host([dir=\"rtl\"]) .cpk-td__try-from-here-icon {\n scale: -1 1;\n }\n\n .cpk-td__try-from-here:hover:not(:disabled) {\n border-color: rgba(85, 88, 178, 0.38);\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__try-from-here:focus-visible {\n outline: 2px solid #a78bfa;\n outline-offset: 1px;\n }\n\n .cpk-td__try-from-here:disabled {\n cursor: not-allowed;\n opacity: 0.55;\n }\n\n .cpk-td__try-from-here-error {\n flex-basis: 100%;\n color: #c0333a;\n font-size: 11px;\n line-height: 1.4;\n }\n\n /*\n * Each tab's content is wrapped in this panel so the keep-mounted\n * inactive panels can be hidden via display:none without disturbing\n * the gap between visible siblings. The flex column + gap gives each\n * conversation item / event row breathing room (the cpk-td__content\n * rule above no longer reaches them now that they are nested inside\n * the per-panel wrapper).\n */\n .cpk-td__panel {\n display: flex;\n flex-direction: column;\n gap: 12px;\n }\n .cpk-td__panel > * {\n flex-shrink: 0;\n }\n\n .cpk-td__panel[hidden] {\n display: none;\n }\n\n /* ── Empty state ─────────────────────────────────────────────────── */\n .cpk-td__empty-state {\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n font-size: 13px;\n padding: 40px 0;\n }\n\n .cpk-td__empty-hint {\n font-size: 11px;\n color: #68686e;\n text-align: center;\n max-width: 220px;\n line-height: 1.5;\n }\n\n /* ── Status messages ─────────────────────────────────────────────── */\n .cpk-td__status {\n padding: 16px;\n font-size: 12px;\n color: #68686e;\n text-align: center;\n }\n\n .cpk-td__status--error {\n color: #c0333a;\n }\n\n @keyframes cpk-td-focus-pulse {\n 0% {\n outline-color: rgba(100, 48, 171, 0);\n box-shadow: 0 0 0 rgba(100, 48, 171, 0);\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n }\n 24%,\n 50% {\n outline-color: rgba(100, 48, 171, 0.78);\n box-shadow: 0 7px 20px rgba(100, 48, 171, 0.2);\n }\n 100% {\n outline-color: rgba(100, 48, 171, 0);\n box-shadow: 0 0 0 rgba(100, 48, 171, 0);\n }\n }\n\n .cpk-td__focus-pulse {\n position: relative;\n z-index: 1;\n outline: 2px solid transparent;\n outline-offset: 3px;\n animation: cpk-td-focus-pulse 760ms linear;\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-td__focus-pulse {\n animation-duration: 320ms;\n }\n }\n\n /* ── Conversation bubbles ────────────────────────────────────────── */\n .cpk-td__bubble {\n display: flex;\n margin-bottom: 10px;\n }\n\n .cpk-td__bubble--user {\n justify-content: flex-end;\n }\n\n .cpk-td__bubble--assistant {\n justify-content: flex-start;\n }\n\n .cpk-td__bubble-inner {\n padding: 10px 16px;\n max-width: 80%;\n font-size: 14px;\n line-height: 1.65;\n }\n\n .cpk-td__bubble-inner--user {\n background: #f4f4f5;\n color: #18181b;\n border-radius: 18px;\n }\n\n .cpk-td__show-more {\n display: inline-block;\n margin-top: 4px;\n font-size: 11px;\n font-weight: 500;\n color: #57575b;\n cursor: pointer;\n text-decoration: underline;\n text-underline-offset: 2px;\n }\n\n .cpk-td__bubble-inner--assistant {\n background: transparent;\n color: #010507;\n max-width: 100%;\n padding: 4px 0;\n border: 0;\n }\n\n /* ── Tool call blocks ────────────────────────────────────────────── */\n .cpk-td__tool-block {\n border: 1px solid #e9e9ef;\n border-radius: 12px;\n overflow: hidden;\n }\n\n .cpk-td__tool-header {\n display: flex;\n align-items: center;\n gap: 6px;\n padding: 12px;\n background: #ffffff;\n color: #71717a;\n cursor: pointer;\n width: 100%;\n border: 0;\n font-family: inherit;\n text-align: left;\n font-size: 11px;\n user-select: none;\n }\n\n .cpk-td__tool-header:focus-visible {\n outline: 2px solid var(--cpk-primary-color, #7076b3);\n outline-offset: -2px;\n }\n\n .cpk-td__tool-header:hover {\n background: #fafafa;\n }\n\n .cpk-td__tool-name {\n font-size: 13px;\n font-weight: 500;\n color: #18181b;\n overflow-wrap: anywhere;\n min-width: 0;\n flex: 1;\n }\n\n .cpk-td__tool-status {\n font-size: 10px;\n font-weight: 500;\n padding: 3px 7px;\n border-radius: 999px;\n background: #d1fae5;\n color: #065f46;\n }\n\n .cpk-td__tool-status--pending {\n background: #fef3c7;\n color: #8a5900;\n }\n\n .cpk-td__tool-chevron {\n color: #68686e;\n font-size: 10px;\n }\n\n .cpk-td__tool-body {\n padding: 8px 10px;\n border-top: 1px solid #e9e9ef;\n background: #ffffff;\n }\n\n .cpk-td__tool-section-label {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n font-weight: 500;\n color: #68686e;\n text-transform: uppercase;\n margin-bottom: 4px;\n letter-spacing: 0.3px;\n }\n\n .cpk-td__tool-pre {\n margin: 0;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n background: #f7f7f9;\n padding: 10px 12px;\n border-radius: 6px;\n overflow-x: auto;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n line-height: 1.65;\n }\n\n /* ── Tool call group ─────────────────────────────────────────────── */\n .cpk-td__tool-group {\n border: 1px solid #e9e9ef;\n border-radius: 7px;\n overflow: hidden;\n }\n\n .cpk-td__tool-group-header {\n padding: 5px 10px;\n background: rgba(133, 236, 206, 0.15);\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n color: #087653;\n text-transform: uppercase;\n font-weight: 500;\n border-bottom: 1px solid #e9e9ef;\n }\n\n .cpk-td__tool-group .cpk-td__tool-block {\n border: none;\n border-bottom: 1px solid #e9e9ef;\n border-radius: 0;\n }\n\n .cpk-td__tool-group .cpk-td__tool-block:last-child {\n border-bottom: none;\n }\n\n /* ── Inline chips (reasoning / state update) ─────────────────────── */\n .cpk-td__inline-chip {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 5px 0;\n color: #68686e;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n text-transform: uppercase;\n }\n\n .cpk-td__inline-chip::before,\n .cpk-td__inline-chip::after {\n content: \"\";\n flex: 1;\n height: 1px;\n background: #e9e9ef;\n }\n\n /* ── Interaction timeline ───────────────────────────────────────── */\n .cpk-td__timeline-item {\n border: 1px solid transparent;\n border-radius: 10px;\n background: transparent;\n overflow: hidden;\n }\n\n .cpk-td__timeline-item--run,\n .cpk-td__timeline-item--state,\n .cpk-td__timeline-item--event,\n .cpk-td__timeline-item--tool,\n .cpk-td__event--run,\n .cpk-td__event--event,\n .cpk-td__event--state,\n .cpk-td__event--message,\n .cpk-td__event--tool {\n border-color: #dbdbe5;\n background: #ffffff;\n }\n\n .cpk-td__timeline-item--message {\n border-color: #dbdbe5;\n background: #ffffff;\n box-shadow: 0 1px 2px #0105070d;\n }\n\n .cpk-td__timeline-item--warning {\n border-color: rgba(250, 95, 103, 0.35);\n background: rgba(250, 95, 103, 0.04);\n }\n\n .cpk-td__timeline-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: transparent;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-header {\n padding: 10px 12px;\n background: #f7f7f9;\n }\n\n .cpk-td__timeline-item--user .cpk-td__timeline-header {\n background: #bec2ff1a;\n }\n\n .cpk-td__timeline-item--assistant .cpk-td__timeline-header {\n background: #85ecce1a;\n }\n\n .cpk-td__timeline-kind {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n border-radius: 999px;\n background: #f0f0f4;\n color: #57575b;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.04em;\n line-height: 1.2;\n text-transform: uppercase;\n flex-shrink: 0;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-kind {\n background: #bec2ff33;\n color: #010507;\n }\n\n .cpk-td__timeline-item--assistant .cpk-td__timeline-kind {\n background: #85ecce4d;\n color: #010507;\n }\n\n .cpk-td__timeline-item--warning .cpk-td__timeline-kind {\n background: rgba(250, 95, 103, 0.16);\n color: #c0333a;\n }\n\n .cpk-td__timeline-title {\n flex: 1;\n min-width: 0;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 500;\n color: #57575b;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-title {\n font-size: 13px;\n font-weight: 600;\n color: #010507;\n }\n\n .cpk-td__timeline-time {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-td__timeline-body {\n margin: 0;\n padding: 0 10px 9px;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n line-height: 1.55;\n color: #57575b;\n white-space: pre-wrap;\n word-break: break-word;\n }\n\n .cpk-td__timeline-item--message .cpk-td__timeline-body {\n padding: 0 12px 12px;\n font-size: 13px;\n color: #010507;\n }\n\n .cpk-td__timeline-toolbar {\n display: flex;\n flex-wrap: wrap;\n align-items: center;\n gap: 6px;\n }\n\n .cpk-td__timeline-bulk-toggle {\n margin: 0;\n padding: 6px 10px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #ffffff;\n color: #36363a;\n cursor: pointer;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n .cpk-td__timeline-bulk-toggle:hover {\n border-color: rgba(85, 88, 178, 0.38);\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__timeline-bulk-toggle:disabled {\n cursor: not-allowed;\n opacity: 0.45;\n }\n\n .cpk-td__source-link {\n margin: 0;\n padding: 0;\n border: none;\n background: transparent;\n color: #5558b2;\n cursor: pointer;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n text-decoration: underline;\n text-underline-offset: 2px;\n flex-shrink: 0;\n }\n\n .cpk-td__source-link:hover {\n color: #010507;\n }\n\n .cpk-td__timeline-details-toggle {\n margin: 0;\n padding: 5px 10px;\n border: none;\n background: #ffffff;\n color: #5558b2;\n cursor: pointer;\n display: inline-flex;\n align-items: center;\n gap: 5px;\n font-family: \"Inter\", sans-serif;\n font-size: 12px;\n font-weight: 600;\n line-height: 1.2;\n width: 100%;\n }\n\n .cpk-td__timeline-details-toggle:hover {\n background: #f7f7ff;\n color: #010507;\n }\n\n .cpk-td__timeline-details-toggle svg {\n width: 12px;\n height: 12px;\n stroke-width: 2;\n }\n\n /* ── Generative UI ──────────────────────────────────────────────── */\n @keyframes cpk-genui-enter {\n from {\n opacity: 0;\n transform: translateY(8px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n }\n\n .cpk-td__genui {\n display: flex;\n flex-direction: column;\n gap: 6px;\n padding: 0;\n animation: cpk-genui-enter 0.25s cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-td__genui-badge {\n display: flex;\n align-items: baseline;\n flex-wrap: wrap;\n gap: 6px;\n padding: 12px;\n min-height: 44px;\n box-sizing: border-box;\n border: 1px solid #e5def5;\n border-radius: 12px;\n background: #f7f4fc;\n color: #57575b;\n font-size: 13px;\n line-height: 20px;\n font-weight: 500;\n }\n\n .cpk-td__genui-card {\n overflow: hidden;\n border-radius: 14px;\n border: 1px solid #e2e8f0;\n background: #fff;\n box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.08);\n }\n\n .cpk-td__genui-component {\n margin-left: 6px;\n font-size: 13px;\n font-weight: 400;\n overflow-wrap: anywhere;\n min-width: 0;\n line-height: inherit;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-badge {\n border-color: #49405f;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header {\n background: #191c24;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-name {\n color: #f4f4f5;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-status {\n background: #17392e;\n color: #6ee7b7;\n }\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-status--pending {\n background: #3d3019;\n color: #fbbf24;\n }\n\n /* ── AG-UI Events ────────────────────────────────────────────────── */\n .cpk-td__event {\n flex-shrink: 0;\n border: 1px solid #dbdbe5;\n border-radius: 10px;\n background: #ffffff;\n overflow: hidden;\n /*\n * content-visibility: auto lets the browser skip layout + paint for\n * off-screen events while keeping them in the DOM (so scroll size\n * stays correct). Without this, switching back to AG-UI Events on a\n * thread with hundreds of events triggers a full layout pass over\n * every event row, which on Martha's intelligence-backed example\n * shows up as a multi-second freeze each time the panel becomes\n * visible. The intrinsic-size hint avoids the visible jump as the\n * browser swaps in real heights when items scroll into view.\n */\n content-visibility: auto;\n contain-intrinsic-size: 0 80px;\n }\n\n .cpk-td__event--error {\n border-color: rgba(250, 95, 103, 0.35);\n background: rgba(250, 95, 103, 0.04);\n }\n\n .cpk-td__event-header {\n display: flex;\n align-items: center;\n gap: 8px;\n padding: 6px 10px;\n background: transparent;\n }\n\n .cpk-td__event-type {\n display: inline-flex;\n align-items: center;\n padding: 4px 8px;\n border-radius: 999px;\n background: #f0f0f4;\n color: #010507;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 600;\n letter-spacing: 0.02em;\n line-height: 1.2;\n }\n\n .cpk-td__event--message .cpk-td__event-type {\n background: #bec2ff33;\n }\n\n .cpk-td__event--tool .cpk-td__event-type {\n background: #85ecce4d;\n }\n\n .cpk-td__event--error .cpk-td__event-type {\n background: rgba(250, 95, 103, 0.16);\n color: #c0333a;\n }\n\n .cpk-td__event-time {\n margin-inline-start: auto;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #68686e;\n flex-shrink: 0;\n }\n\n .cpk-td__event-payload,\n .cpk-td__json-block,\n .cpk-json-block {\n margin: 0;\n padding: 10px 12px;\n border-top: 1px solid #dbdbe5;\n background: #f7f7f9;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n line-height: 1.65;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n overflow: auto;\n }\n\n .cpk-json-token--key {\n color: var(--cpk-json-key);\n }\n\n .cpk-json-token--str {\n color: var(--cpk-json-str);\n }\n\n .cpk-json-token--num {\n color: var(--cpk-json-num);\n }\n\n .cpk-json-token--bool {\n color: var(--cpk-json-bool);\n }\n\n .cpk-json-token--nil {\n color: var(--cpk-json-nil);\n }\n\n /* ── Resize divider ──────────────────────────────────────────────── */\n /* Floats over the drawer's left edge so the toggle and the drawer\n touch directly without a 4px flex-gap between them. The hit zone\n is wider than its visual hint to make it easy to grab. */\n .cpk-td__detail-divider {\n position: absolute;\n top: 0;\n bottom: 0;\n left: -3px;\n width: 7px;\n cursor: col-resize;\n background: transparent;\n z-index: 5;\n }\n\n .cpk-td__detail-divider:hover {\n background: rgba(190, 194, 255, 0.3);\n }\n\n /* ── Right detail panel ──────────────────────────────────────────── */\n .cpk-td__detail {\n flex-shrink: 0;\n overflow: hidden;\n background: #f7f7f9;\n display: flex;\n flex-direction: column;\n gap: 0;\n padding: 0;\n box-sizing: border-box;\n position: relative;\n /* Slide open/closed via width + padding transition. When closed,\n width and padding are 0 so the drawer fully collapses. */\n transition:\n width 220ms cubic-bezier(0.4, 0, 0.2, 1),\n padding 220ms cubic-bezier(0.4, 0, 0.2, 1);\n }\n\n .cpk-td__detail[data-open=\"true\"] {\n overflow-y: auto;\n padding: 16px;\n }\n\n .cpk-tdp__section-title {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 10px;\n font-weight: 500;\n color: #68686e;\n text-transform: uppercase;\n letter-spacing: 0.6px;\n margin-bottom: 8px;\n }\n\n .cpk-tdp__divider {\n height: 1px;\n background: #dbdbe5;\n margin: 14px 0;\n }\n\n .cpk-tdp__row {\n display: flex;\n justify-content: space-between;\n align-items: flex-start;\n padding: 3px 0;\n gap: 8px;\n }\n\n .cpk-tdp__label {\n color: #68686e;\n font-size: 11px;\n white-space: nowrap;\n flex-shrink: 0;\n }\n\n .cpk-tdp__value {\n color: #010507;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 11px;\n text-align: right;\n min-width: 0;\n }\n\n .cpk-tdp__value--truncate {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n max-width: 130px;\n }\n\n .cpk-tdp__value--wrap {\n white-space: normal;\n word-break: break-all;\n text-align: right;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n --cpk-json-key: #bec2ff;\n --cpk-json-str: #85ecce;\n --cpk-json-num: #ffac4d;\n --cpk-json-bool: #fa5f67;\n --cpk-json-nil: #afafb7;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td {\n background: #111319;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tabs-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-strip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-pill,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-block,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-body,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-payload,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-strip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__detail {\n background: #15171e;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-pill,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-block,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-card,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle {\n border-color: #343742;\n background: #191c24;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-body {\n background: #171a22;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-pre {\n background: #111319;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-header:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle:hover {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle--active,\n :host([data-color-scheme=\"dark\"]) .cpk-td__inline-chip,\n :host([data-color-scheme=\"dark\"]) .cpk-td__genui-badge {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--message {\n background: #191c24;\n border-color: #343742;\n box-shadow: none;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--user\n .cpk-td__timeline-header {\n background: #bec2ff1a;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--assistant\n .cpk-td__timeline-header {\n background: #85ecce1a;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--message\n .cpk-td__timeline-kind {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--assistant\n .cpk-td__timeline-kind {\n background: #1a3a32;\n color: #85ecce;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--run,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--state,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-item--tool,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--run,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--event,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--state,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--message,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--tool {\n background: #191c24;\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--run\n .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--event\n .cpk-td__timeline-header,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--state\n .cpk-td__timeline-header {\n background: transparent;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-kind {\n background: #20232d;\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--run\n .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--event\n .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--state\n .cpk-td__timeline-title {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-header {\n background: transparent;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-type {\n background: #20232d;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--message .cpk-td__event-type {\n background: #302b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--tool .cpk-td__event-type {\n background: #1a3a32;\n color: #85ecce;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event--error .cpk-td__event-type {\n background: rgba(250, 95, 103, 0.2);\n color: #fa5f67;\n }\n\n :host([data-color-scheme=\"dark\"])\n .cpk-td__timeline-item--message\n .cpk-td__timeline-body {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab,\n :host([data-color-scheme=\"dark\"]) .cpk-td__panel-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-label,\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-time,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-time,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-body,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__label,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__section-title {\n color: #aeb1bd;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tab--active,\n :host([data-color-scheme=\"dark\"]) .cpk-td__metadata-value,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-name,\n :host([data-color-scheme=\"dark\"]) .cpk-td__tool-pre,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-title,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-bulk-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__timeline-details-toggle,\n :host([data-color-scheme=\"dark\"]) .cpk-td__try-from-here,\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__value {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-td__event-payload,\n :host([data-color-scheme=\"dark\"]) .cpk-td__json-block,\n :host([data-color-scheme=\"dark\"]) .cpk-json-block {\n background: #111319;\n border-top-color: #343742;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-tdp__divider {\n background: #343742;\n }\n `;\n\n updated(_changed: Map<string, unknown>): void {\n if (!this.isConnected) return;\n const loadKey = this.currentLoadKey();\n if (loadKey !== this._lastLoadKey) {\n this._lastLoadKey = loadKey;\n this._lastSeenLiveMessageVersion = this.liveMessageVersion;\n this.resetLoadedThreadData();\n\n if (this.threadId) {\n // Keep fetching events alongside messages so the timeline and raw\n // events views reuse the same response when opened.\n // User messages often never appear as TEXT_MESSAGE events (they are\n // added locally before RUN_STARTED), so also load the conversation.\n void this.fetchMetadata(this.threadId);\n if (this.canFetchEvents()) {\n this._eventsFetched = true;\n void this.fetchEvents(this.threadId);\n }\n if (this.canFetchMessages()) {\n void this.fetchMessages(this.threadId);\n }\n } else {\n this._fetchedMetadata = null;\n this._conversation = [];\n }\n } else if (\n this.threadId &&\n this.liveMessageVersion !== this._lastSeenLiveMessageVersion\n ) {\n // Same thread, but the parent inspector signalled new agent-emitted\n // messages on this thread (via `liveMessageVersion`). Re-fetch the\n // canonical conversation from the runtime so streaming output flows\n // into the view without us reimplementing AG-UI → ConversationItem\n // mapping in the parent. `silent: true` so the loading-state indicator\n // doesn't flash between every streaming chunk and we keep the\n // last-good view on transient fetch errors.\n this._lastSeenLiveMessageVersion = this.liveMessageVersion;\n this._messagesAbort?.abort();\n this._messagesAbort = null;\n void this.fetchMessages(this.threadId, true);\n }\n\n const focusedContentChanged =\n _changed.has(\"_fetchedEvents\") ||\n _changed.has(\"agentEventsInput\") ||\n _changed.has(\"agentMessagesInput\") ||\n _changed.has(\"_conversation\");\n if (\n this.focusMessageId &&\n (this.focusRequestId > this._scrolledFocusRequestId ||\n focusedContentChanged)\n ) {\n if (this._tab !== \"timeline\") {\n this._activatedTabs = new Set([...this._activatedTabs, \"timeline\"]);\n this._tab = \"timeline\";\n this.requestUpdate();\n }\n requestAnimationFrame(() => this.scrollToFocusedMessage());\n }\n }\n\n private scrollToFocusedMessage(): void {\n if (!this.focusMessageId) return;\n const message = Array.from(\n this.shadowRoot?.querySelectorAll<HTMLElement>(\n `#${this.panelDomId(this._tab)}:not([hidden]) [data-message-id]`,\n ) ?? [],\n ).find((candidate) => candidate.dataset.messageId === this.focusMessageId);\n if (!message) return;\n message.scrollIntoView?.({ block: \"center\" });\n this._scrolledFocusRequestId = this.focusRequestId;\n this.pulseFocusedMessage(message);\n }\n\n private pulseFocusedMessage(message: HTMLElement): void {\n if (this.focusRequestId === this._highlightedFocusRequestId) return;\n this._highlightedFocusRequestId = this.focusRequestId;\n message.classList.remove(\"cpk-td__focus-pulse\");\n void message.offsetWidth;\n message.classList.add(\"cpk-td__focus-pulse\");\n message.addEventListener(\n \"animationend\",\n () => message.classList.remove(\"cpk-td__focus-pulse\"),\n { once: true },\n );\n }\n\n connectedCallback(): void {\n super.connectedCallback();\n if (this._hasConnectedOnce) {\n this.requestUpdate();\n }\n this._hasConnectedOnce = true;\n }\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.resetLoadedThreadData();\n this._lastLoadKey = null;\n }\n\n private canFetchMessages(): boolean {\n return (\n !!this.provider?.getMessages ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private canFetchEvents(): boolean {\n return (\n !!this.provider?.getEvents ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private canFetchState(): boolean {\n return (\n !!this.provider?.getState ||\n (!!this.runtimeUrl && this.threadInspectionAvailable)\n );\n }\n\n private currentLoadKey(): string {\n return [\n this.threadId ?? \"thread:none\",\n CpkThreadInspector.providerLoadKey(this.provider),\n `runtime:${this.runtimeUrl}`,\n `headers:${CpkThreadInspector.headersLoadKey(this.headers)}`,\n `inspect:${this.threadInspectionAvailable ? \"1\" : \"0\"}`,\n ].join(\"||\");\n }\n\n private resetLoadedThreadData(): void {\n this._tab = \"timeline\";\n this._activatedTabs = new Set([\"timeline\"]);\n this._panelTplCache = new Map();\n this._timelineItemsCache = null;\n this._liveEventsWithSourceIndexCache = null;\n this._expandedTools = new Set();\n this._expandedMessages = new Set();\n this._expandedTimelineDetails = new Set();\n this._expandedRawEvents = new Set();\n this._metadataAbort?.abort();\n this._metadataAbort = null;\n this._messagesAbort?.abort();\n this._messagesAbort = null;\n this._eventsAbort?.abort();\n this._eventsAbort = null;\n this._stateAbort?.abort();\n this._stateAbort = null;\n // Reset cleared so the next click into events/state triggers a fresh\n // fetch. Eagerly clear fetched data so a provider/runtime swap cannot\n // briefly show the old source's values for the same threadId.\n this._eventsFetched = false;\n this._stateFetched = false;\n this._eventsNotAvailable = false;\n this._stateNotAvailable = false;\n this._loadingMessages = false;\n this._loadingEvents = false;\n this._loadingState = false;\n this._messagesError = null;\n this._messageRefreshError = null;\n this._eventsError = null;\n this._stateError = null;\n this._fetchedMetadata = null;\n this._conversation = [];\n this._fetchedEvents = null;\n this._fetchedState = null;\n }\n\n private async fetchMetadata(threadId: string): Promise<void> {\n if (!this.provider?.getThreadMetadata) return;\n this._metadataAbort?.abort();\n const controller = new AbortController();\n this._metadataAbort = controller;\n try {\n const metadata = await this.provider.getThreadMetadata(threadId, {\n signal: controller.signal,\n });\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._fetchedMetadata = metadata;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._fetchedMetadata = null;\n }\n }\n\n /**\n * Fetch the canonical conversation for `threadId` from the runtime.\n *\n * `silent` is true for live re-fetches triggered by `liveMessageVersion`\n * bumps during streaming. In that mode we never toggle the loading state\n * (which would flash \"Loading messages…\" between every message) and we\n * keep the previous conversation on transient errors instead of blanking\n * it. Initial threadId-change fetches use the default (`silent=false`)\n * so users see an explicit loading indicator on first load.\n */\n private async fetchMessages(\n threadId: string,\n silent: boolean = false,\n ): Promise<void> {\n if (!this.canFetchMessages()) {\n if (!silent) this._conversation = [];\n return;\n }\n this._messagesAbort?.abort();\n const controller = new AbortController();\n this._messagesAbort = controller;\n if (!silent) {\n this._loadingMessages = true;\n this._messagesError = null;\n this._messageRefreshError = null;\n }\n try {\n const messages = this.provider?.getMessages\n ? await this.provider.getMessages(threadId, {\n signal: controller.signal,\n })\n : await this.fetchRuntimeMessages(threadId, controller.signal);\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._conversation = this.mapMessages(messages);\n this._messagesError = null;\n this._messageRefreshError = null;\n } catch (err) {\n if (controller.signal.aborted || this.threadId !== threadId) return;\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (!silent || this._conversation.length === 0) {\n this._messagesError =\n err instanceof Error ? err.message : \"Failed to load messages\";\n this._conversation = [];\n } else {\n this._messageRefreshError =\n \"Could not refresh messages. Showing the last loaded conversation.\";\n }\n } finally {\n // A live refresh can replace the initial request before it finishes.\n if (!controller.signal.aborted && this.threadId === threadId) {\n this._loadingMessages = false;\n }\n }\n }\n\n private async fetchEvents(threadId: string): Promise<void> {\n if (!this.canFetchEvents()) {\n this._fetchedEvents = null;\n return;\n }\n this._eventsAbort?.abort();\n const controller = new AbortController();\n this._eventsAbort = controller;\n this._loadingEvents = true;\n this._eventsError = null;\n try {\n const result = this.provider?.getEvents\n ? {\n status: \"available\" as const,\n events: await this.provider.getEvents(threadId, {\n signal: controller.signal,\n }),\n }\n : await this.fetchRuntimeEvents(threadId, controller.signal);\n // Drop results if a newer fetch superseded this one (thread switched\n // or provider/runtime changed mid-flight). Without this, switching A→B\n // can leave thread B's view showing thread A's events when A's request\n // resolves last.\n if (controller.signal.aborted || this.threadId !== threadId) return;\n if (result.status === \"not-available\") {\n this._eventsNotAvailable = true;\n this._fetchedEvents = [];\n return;\n }\n const mappedEvents = this.mapApiEvents(result.events);\n this._fetchedEvents = mappedEvents;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._eventsError =\n err instanceof Error ? err.message : \"Failed to load events\";\n this._fetchedEvents = [];\n } finally {\n if (!controller.signal.aborted && this.threadId === threadId) {\n this._loadingEvents = false;\n }\n }\n }\n\n private async fetchState(threadId: string): Promise<void> {\n if (!this.canFetchState()) {\n this._fetchedState = null;\n return;\n }\n this._stateAbort?.abort();\n const controller = new AbortController();\n this._stateAbort = controller;\n this._loadingState = true;\n this._stateError = null;\n try {\n const result = this.provider?.getState\n ? {\n status: \"available\" as const,\n state: await this.provider.getState(threadId, {\n signal: controller.signal,\n }),\n }\n : await this.fetchRuntimeState(threadId, controller.signal);\n if (controller.signal.aborted || this.threadId !== threadId) return;\n if (result.status === \"not-available\") {\n this._stateNotAvailable = true;\n this._fetchedState = null;\n return;\n }\n this._fetchedState = result.state ?? null;\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n if (controller.signal.aborted || this.threadId !== threadId) return;\n this._stateError =\n err instanceof Error ? err.message : \"Failed to load state\";\n this._fetchedState = null;\n } finally {\n if (!controller.signal.aborted && this.threadId === threadId) {\n this._loadingState = false;\n }\n }\n }\n\n private async fetchRuntimeMessages(\n threadId: string,\n signal: AbortSignal,\n ): Promise<ThreadDebuggerMessage[]> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"messages\"), {\n headers: { ...this.headers },\n signal,\n });\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as { messages: ThreadDebuggerMessage[] };\n return data.messages;\n }\n\n private async fetchRuntimeEvents(\n threadId: string,\n signal: AbortSignal,\n ): Promise<RuntimeEventsFetchResult> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"events\"), {\n headers: { ...this.headers },\n signal,\n });\n if (res.status === 501) {\n return { status: \"not-available\" };\n }\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as {\n events: ThreadDebuggerEvent[];\n };\n return { status: \"available\", events: data.events };\n }\n\n private async fetchRuntimeState(\n threadId: string,\n signal: AbortSignal,\n ): Promise<RuntimeStateFetchResult> {\n const res = await fetch(this.getThreadInspectionUrl(threadId, \"state\"), {\n headers: { ...this.headers },\n signal,\n });\n if (res.status === 501) {\n return { status: \"not-available\" };\n }\n if (!res.ok) throw new Error(`HTTP ${res.status}`);\n const data = (await res.json()) as {\n state: Record<string, unknown> | null;\n };\n return { status: \"available\", state: data.state ?? null };\n }\n\n private getThreadInspectionUrl(\n threadId: string,\n resource: \"messages\" | \"events\" | \"state\",\n ): string {\n return `${this.runtimeUrl.replace(/\\/+$/, \"\")}/threads/${encodeURIComponent(threadId)}/${resource}`;\n }\n\n private mapMessages(messages: ThreadDebuggerMessage[]): ConversationItem[] {\n const items: ConversationItem[] = [];\n const toolCallMap = new Map<string, ConversationToolCall>();\n for (const msg of messages) {\n if (msg.role === \"user\") {\n const content = textFromUnknownContent(msg.content);\n if (content) {\n items.push({\n id: msg.id,\n type: \"user\",\n content,\n createdAt: \"\",\n });\n }\n } else if (msg.role === \"assistant\") {\n if (msg.toolCalls?.length) {\n for (const tc of msg.toolCalls) {\n let args: Record<string, unknown> = {};\n if (typeof tc.args === \"string\") {\n try {\n args = this.parseToolCallContent(tc.args);\n } catch (err) {\n // Empty content is normalized to `{}` for both tool arguments\n // and results. The inspector still surfaces malformed JSON.\n console.error(\n \"[CopilotKit Inspector] Failed to parse tool-call arguments\",\n { toolCallId: tc.id, raw: tc.args, error: err },\n );\n args = { __parseError: true, __raw: tc.args };\n }\n } else {\n args = tc.args;\n }\n const item: ConversationToolCall = {\n id: tc.id,\n type: \"tool_call\",\n toolName: tc.name,\n toolCallId: tc.id,\n arguments: args,\n result: null,\n hasResult: false,\n createdAt: \"\",\n };\n toolCallMap.set(tc.id, item);\n items.push(item);\n }\n }\n const assistantContent = textFromUnknownContent(msg.content);\n if (assistantContent) {\n items.push({\n id: msg.id,\n type: \"assistant\",\n content: assistantContent,\n createdAt: \"\",\n });\n }\n } else if (msg.role === \"activity\") {\n items.push({\n id: msg.id,\n type: \"generative-ui\",\n activityType: msg.activityType ?? \"unknown\",\n createdAt: \"\",\n });\n } else if (msg.role === \"tool\" && msg.toolCallId) {\n const tc = toolCallMap.get(msg.toolCallId);\n if (tc) {\n tc.hasResult = true;\n tc.resultUnreadable = false;\n try {\n tc.result = this.parseToolCallContent(msg.content);\n } catch (err) {\n // See the comment on the assistant tool-call args parse above —\n // same rationale, same sentinel shape so the renderer can treat\n // both consistently.\n console.error(\n \"[CopilotKit Inspector] Failed to parse tool-call result content\",\n { toolCallId: msg.toolCallId, raw: msg.content, error: err },\n );\n tc.resultUnreadable = true;\n tc.result = { __parseError: true, __raw: msg.content ?? null };\n }\n }\n }\n }\n return items;\n }\n\n private parseToolCallContent(\n content: string | null | undefined,\n ): Record<string, unknown> {\n const normalizedContent = content?.trim();\n if (!normalizedContent) {\n return {};\n }\n\n return JSON.parse(normalizedContent) as Record<string, unknown>;\n }\n\n private mapApiEvents(events: ThreadDebuggerEvent[]): ApiAgentEvent[] {\n return events.map((event, index) => {\n const { type, timestamp, payload, ...rest } = event;\n return {\n type: typeof type === \"string\" ? type : \"UNKNOWN\",\n timestamp:\n typeof timestamp === \"string\" || typeof timestamp === \"number\"\n ? timestamp\n : Date.now(),\n payload: payload ?? rest,\n sourceIndex: index + 1,\n rawEvent: event,\n };\n });\n }\n\n private get activeTimelineItems(): TimelineItem[] {\n return this.timelineItemsForEvents(this.activeEvents);\n }\n\n private timelineItemsForEvents(events: ApiAgentEvent[]): TimelineItem[] {\n const conversation = this._conversation;\n const agentMessages = this.agentMessagesInput;\n if (\n this._timelineItemsCache?.events === events &&\n this._timelineItemsCache.conversation === conversation &&\n this._timelineItemsCache.agentMessages === agentMessages\n ) {\n return this._timelineItemsCache.items;\n }\n const items = this.mergeUserMessagesIntoTimeline(\n this.timelineItemsFromEvents(events),\n );\n this._timelineItemsCache = { events, conversation, agentMessages, items };\n return items;\n }\n\n private conversationUsers(): ConversationUser[] {\n const users: ConversationUser[] = [];\n const seenIds = new Set<string>();\n const seenBodies = new Set<string>();\n const push = (user: ConversationUser) => {\n const body = user.content.trim();\n if (!body) return;\n if (seenIds.has(user.id) || seenBodies.has(body)) return;\n seenIds.add(user.id);\n seenBodies.add(body);\n users.push(user);\n };\n for (const item of this._conversation) {\n if (item.type === \"user\") push(item);\n }\n this.agentMessagesInput.forEach((message, index) => {\n if (message.role !== \"user\") return;\n push({\n id: message.id ?? `live-user-${index}`,\n type: \"user\",\n content: message.contentText,\n createdAt: \"\",\n });\n });\n return users;\n }\n\n private mergeUserMessagesIntoTimeline(items: TimelineItem[]): TimelineItem[] {\n if (items.length === 0) return items;\n const users = this.conversationUsers();\n if (users.length === 0) return items;\n\n const shownIds = new Set<string>();\n const shownBodies = new Set<string>();\n for (const item of items) {\n if (item.kind !== \"message\") continue;\n if (!item.title.toLowerCase().startsWith(\"user\")) continue;\n if (item.messageId) shownIds.add(item.messageId);\n const body = item.body?.trim();\n if (body) shownBodies.add(body);\n }\n\n const missing = users.filter((user) => {\n if (shownIds.has(user.id)) return false;\n if (shownBodies.has(user.content.trim())) return false;\n return true;\n });\n if (missing.length === 0) return items;\n\n const insertAt: number[] = [];\n for (let index = 0; index < items.length; index++) {\n const item = items[index]!;\n if (item.kind === \"run\" && item.title === \"Run started\") {\n insertAt.push(index);\n }\n }\n if (insertAt.length === 0) {\n for (let index = 0; index < items.length; index++) {\n const item = items[index]!;\n if (\n item.kind === \"message\" &&\n item.title.toLowerCase().includes(\"assistant\")\n ) {\n insertAt.push(index);\n }\n }\n }\n\n const merged = [...items];\n for (let index = missing.length - 1; index >= 0; index--) {\n const user = missing[index]!;\n const row: TimelineItem = {\n id: `conversation-user-${user.id}`,\n messageId: user.id,\n kind: \"message\",\n title: \"User message\",\n body: user.content,\n timestamp: user.createdAt || 0,\n sourceIndex: 0,\n };\n merged.splice(insertAt[index] ?? 0, 0, row);\n }\n return merged;\n }\n\n private timelineItemsFromEvents(events: ApiAgentEvent[]): TimelineItem[] {\n if (events.length === 0) return [];\n\n const items: TimelineItem[] = [];\n const messageItems = new Map<string, TimelineItem>();\n const toolItems = new Map<string, TimelineItem & { rawArgs?: string }>();\n\n const readString = (\n payload: Record<string, unknown>,\n keys: string[],\n ): string | null => {\n for (const key of keys) {\n const value = payload[key];\n if (typeof value === \"string\") return value;\n }\n return null;\n };\n\n const sourceIndexFor = (event: ApiAgentEvent): number =>\n event.sourceIndex ?? 0;\n\n const appendWarning = (\n event: ApiAgentEvent,\n title: string,\n body: string,\n severity: \"warning\" | \"error\" = \"warning\",\n ): void => {\n const sourceIndex = sourceIndexFor(event);\n items.push({\n id: `warning-${sourceIndex}-${items.length}`,\n kind: \"warning\",\n title,\n body,\n timestamp: event.timestamp,\n sourceIndex,\n severity,\n });\n };\n\n const ensureMessage = (\n event: ApiAgentEvent,\n role: string,\n ): TimelineItem => {\n const sourceIndex = sourceIndexFor(event);\n const key =\n readString(event.payload, [\"messageId\", \"message_id\", \"id\"]) ??\n `message-${sourceIndex}`;\n let item = messageItems.get(key);\n if (!item) {\n item = {\n id: `message-${key}`,\n messageId: key,\n kind: \"message\",\n title: messageTitle(role || \"message\"),\n body: \"\",\n timestamp: event.timestamp,\n sourceIndex,\n };\n messageItems.set(key, item);\n items.push(item);\n }\n return item;\n };\n\n const ensureTool = (\n event: ApiAgentEvent,\n ): TimelineItem & {\n rawArgs?: string;\n } => {\n const sourceIndex = sourceIndexFor(event);\n const key =\n readString(event.payload, [\n \"toolCallId\",\n \"tool_call_id\",\n \"id\",\n \"callId\",\n ]) ?? `tool-${sourceIndex}`;\n let item = toolItems.get(key);\n if (!item) {\n item = {\n id: `tool-${key}`,\n kind: \"tool\",\n title:\n readString(event.payload, [\n \"toolCallName\",\n \"toolName\",\n \"name\",\n \"functionName\",\n ]) ?? \"Tool call\",\n body: \"\",\n timestamp: event.timestamp,\n sourceIndex,\n };\n toolItems.set(key, item);\n items.push(item);\n }\n return item;\n };\n\n for (const event of events) {\n const { type, payload } = event;\n const sourceIndex = sourceIndexFor(event);\n\n if (type === \"UNKNOWN\") {\n appendWarning(\n event,\n \"Unknown AG-UI event\",\n \"The event is missing a string type and could not be normalized.\",\n );\n continue;\n }\n\n if (type === \"RUN_STARTED\" || type === \"STEP_STARTED\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"run\",\n title: type === \"RUN_STARTED\" ? \"Run started\" : \"Step started\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n if (type === \"RUN_FINISHED\" || type === \"STEP_FINISHED\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"run\",\n title: type === \"RUN_FINISHED\" ? \"Run finished\" : \"Step finished\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n if (type === \"RUN_ERROR\" || type === \"ERROR\") {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"warning\",\n title: \"Run error\",\n body: readString(payload, [\"message\", \"error\", \"description\"]) ?? \"\",\n timestamp: event.timestamp,\n sourceIndex,\n severity: \"error\",\n details: payload,\n });\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_START\") {\n ensureMessage(event, readString(payload, [\"role\"]) ?? \"assistant\");\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_CONTENT\") {\n const item = ensureMessage(\n event,\n readString(payload, [\"role\"]) ?? \"assistant\",\n );\n item.body = `${item.body ?? \"\"}${\n readString(payload, [\"delta\", \"content\", \"text\"]) ?? \"\"\n }`;\n continue;\n }\n\n if (type === \"TEXT_MESSAGE_END\") {\n ensureMessage(event, readString(payload, [\"role\"]) ?? \"assistant\");\n continue;\n }\n\n if (type === \"TOOL_CALL_START\") {\n ensureTool(event);\n continue;\n }\n\n if (type === \"TOOL_CALL_ARGS\") {\n const item = ensureTool(event);\n const chunk =\n readString(payload, [\"args\", \"arguments\", \"delta\"]) ??\n (typeof payload.args === \"object\"\n ? JSON.stringify(payload.args)\n : null);\n if (chunk) {\n item.rawArgs = `${item.rawArgs ?? \"\"}${chunk}`;\n item.body = item.rawArgs;\n }\n continue;\n }\n\n if (type === \"TOOL_CALL_END\") {\n const item = ensureTool(event);\n if (item.rawArgs) {\n try {\n JSON.parse(item.rawArgs);\n } catch {\n appendWarning(\n event,\n \"Could not decode tool call arguments\",\n item.rawArgs,\n );\n }\n }\n continue;\n }\n\n if (type === \"TOOL_CALL_RESULT\") {\n const item = ensureTool(event);\n const result = readString(payload, [\"result\", \"content\", \"delta\"]);\n if (result) {\n item.body = item.body\n ? `${item.body}\\nResult: ${result}`\n : `Result: ${result}`;\n try {\n JSON.parse(result);\n } catch {\n appendWarning(event, \"Could not decode tool result\", result);\n }\n }\n continue;\n }\n\n if (type.startsWith(\"STATE_\")) {\n items.push({\n id: `${type}-${sourceIndex}`,\n kind: \"state\",\n title: type === \"STATE_SNAPSHOT\" ? \"State snapshot\" : \"State delta\",\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n continue;\n }\n\n items.push({\n id: `event-${sourceIndex}`,\n kind: \"event\",\n title: humanizeEventType(type),\n timestamp: event.timestamp,\n sourceIndex,\n details: payload,\n });\n }\n\n return items;\n }\n\n private get renderItems(): RenderItem[] {\n const items = this._conversation;\n const result: RenderItem[] = [];\n const seen = new Set<string>();\n for (const item of items) {\n if (item.type === \"agent_responded\") continue;\n if (item.type !== \"tool_call\" || !item.groupId) {\n result.push(item);\n continue;\n }\n if (seen.has(item.groupId)) continue;\n seen.add(item.groupId);\n const group: ToolCallGroup = {\n type: \"tool_call_group\",\n id: item.groupId,\n items: items.filter(\n (i): i is ConversationToolCall =>\n i.type === \"tool_call\" && i.groupId === item.groupId,\n ),\n };\n result.push(group);\n }\n return result;\n }\n\n private get activityCounts(): {\n messages: number;\n toolCalls: number;\n generativeUi: number;\n } {\n let messages = 0;\n let toolCalls = 0;\n let generativeUi = 0;\n for (const item of this._conversation) {\n if (item.type === \"user\" || item.type === \"assistant\") messages++;\n if (item.type === \"tool_call\") toolCalls++;\n if (item.type === \"generative-ui\") generativeUi++;\n }\n return { messages, toolCalls, generativeUi };\n }\n\n private get duration(): string {\n const t = this.metadata;\n if (!t?.createdAt || !t?.updatedAt) return \"—\";\n const ms =\n new Date(t.updatedAt).getTime() - new Date(t.createdAt).getTime();\n if (ms < 0) return \"—\";\n if (ms < 1000) return `${ms}ms`;\n const s = Math.floor(ms / 1000);\n if (s < 60) return `${s}s`;\n const m = Math.floor(s / 60);\n const rs = s % 60;\n return `${m}m ${rs}s`;\n }\n\n private toggleToolExpand(id: string): void {\n const next = new Set(this._expandedTools);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedTools = next;\n }\n\n private toggleMessageExpand(id: string): void {\n const next = new Set(this._expandedMessages);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedMessages = next;\n }\n\n private toggleTimelineDetails(id: string): void {\n const next = new Set(this._expandedTimelineDetails);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedTimelineDetails = next;\n }\n\n private expandTimelineDetails(ids: string[]): void {\n this._expandedTimelineDetails = new Set([\n ...this._expandedTimelineDetails,\n ...ids,\n ]);\n }\n\n private collapseTimelineDetails(ids: string[]): void {\n const next = new Set(this._expandedTimelineDetails);\n for (const id of ids) next.delete(id);\n this._expandedTimelineDetails = next;\n }\n\n private toggleRawEventDetails(id: string): void {\n const next = new Set(this._expandedRawEvents);\n if (next.has(id)) next.delete(id);\n else next.add(id);\n this._expandedRawEvents = next;\n }\n\n private expandRawEventDetails(ids: string[]): void {\n this._expandedRawEvents = new Set([...this._expandedRawEvents, ...ids]);\n }\n\n private collapseRawEventDetails(ids: string[]): void {\n const next = new Set(this._expandedRawEvents);\n for (const id of ids) next.delete(id);\n this._expandedRawEvents = next;\n }\n\n private rawEventId(event: ApiAgentEvent): string {\n return `raw-event-${event.sourceIndex ?? event.timestamp ?? event.type}`;\n }\n\n private get activeEvents(): ApiAgentEvent[] {\n // When the endpoint explicitly returned 501 we report no events rather\n // than leaking the parent's agent-keyed live events across historical\n // threads (those would render identically for every thread on the same\n // agent and mislead the reader).\n if (this._eventsNotAvailable) return [];\n const events = this._fetchedEvents ?? this.agentEventsInput ?? [];\n if (events.every((event) => event.sourceIndex != null)) return events;\n if (this._liveEventsWithSourceIndexCache?.events === events) {\n return this._liveEventsWithSourceIndexCache.indexedEvents;\n }\n const indexedEvents = events.map((event, index) =>\n event.sourceIndex == null ? { ...event, sourceIndex: index + 1 } : event,\n );\n this._liveEventsWithSourceIndexCache = { events, indexedEvents };\n return indexedEvents;\n }\n\n private get activeState(): Record<string, unknown> | null {\n if (this._stateNotAvailable) return null;\n return this._fetchedState ?? this.agentStateInput ?? null;\n }\n\n private hasRenderableState(): boolean {\n const s = this.activeState;\n return !!s && typeof s === \"object\" && Object.keys(s).length > 0;\n }\n\n private shortId(id: string | null | undefined): string {\n if (!id) return \"—\";\n return id.length > 20 ? id.slice(0, 8) + \"…\" : id;\n }\n\n private get metadata(): ThreadDebuggerMetadata | null {\n return this._fetchedMetadata ?? this.thread ?? null;\n }\n\n private fmtTime(dateStr: string | null | undefined): string {\n if (!dateStr) return \"—\";\n const d = new Date(dateStr);\n if (Number.isNaN(d.getTime())) return \"—\";\n return d.toLocaleTimeString(\"en-US\", {\n hour: \"2-digit\",\n minute: \"2-digit\",\n second: \"2-digit\",\n hour12: false,\n });\n }\n\n private onDetailDividerDown = (event: PointerEvent): void => {\n this._dividerResizing = true;\n this._dividerPointerId = event.pointerId;\n this._dividerStartX = event.clientX;\n this._dividerStartWidth = this._detailPanelWidth;\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n event.preventDefault();\n };\n\n private onDetailDividerMove = (event: PointerEvent): void => {\n if (!this._dividerResizing || this._dividerPointerId !== event.pointerId)\n return;\n const delta = this._dividerStartX - event.clientX;\n this._detailPanelWidth = Math.max(\n 160,\n Math.min(400, this._dividerStartWidth + delta),\n );\n };\n\n private onDetailDividerUp = (event: PointerEvent): void => {\n if (this._dividerPointerId !== event.pointerId) return;\n const target = event.currentTarget as HTMLElement;\n if (target.hasPointerCapture(this._dividerPointerId)) {\n target.releasePointerCapture(this._dividerPointerId);\n }\n this._dividerResizing = false;\n };\n\n render() {\n const viewInApp = this.renderViewInAppAction();\n return html`\n <div class=\"cpk-td\">\n <!-- ── Left area: tabs + content ─────────────────────────────────── -->\n <div class=\"cpk-td__left\">\n <!-- Tab bar -->\n <div class=\"cpk-td__tabs-header\">\n <div\n class=\"cpk-td__tab-group\"\n role=\"tablist\"\n aria-label=\"Thread detail views\"\n >\n ${CpkThreadInspector.TAB_LIST.map(\n (tab) => html`\n <button\n id=${this.tabDomId(tab.id)}\n type=\"button\"\n role=\"tab\"\n aria-controls=${this.panelDomId(tab.id)}\n aria-selected=${this._tab === tab.id ? \"true\" : \"false\"}\n tabindex=${this._tab === tab.id ? \"0\" : \"-1\"}\n class=\"cpk-td__tab ${\n this._tab === tab.id ? \"cpk-td__tab--active\" : \"\"\n }\"\n @click=${() => this.activateTab(tab.id)}\n @keydown=${(event: KeyboardEvent) =>\n this.handleTabKeyDown(event, tab.id)}\n >\n ${tab.label}\n </button>\n `,\n )}\n </div>\n ${\n viewInApp !== nothing\n ? html`<div class=\"cpk-td__chrome-actions\">${viewInApp}</div>`\n : nothing\n }\n ${this.renderPanelToggle()}\n </div>\n <div class=\"cpk-td__thread-header\">\n ${\n this.showThreadTitle\n ? html`<div class=\"cpk-td__thread-title\">${this.metadata?.name || this.thread?.name || \"Rich Thread\"}</div>`\n : nothing\n }\n ${this._tab === \"timeline\" ? html`<div class=\"cpk-td__pinned-actions\">${this.renderConversationActions()}</div>` : nothing}\n </div>\n\n <!-- Scrollable content -->\n <div class=\"cpk-td__content\">\n ${\n this._panelInitializing\n ? html`\n <div class=\"cpk-td__status\">Loading…</div>\n `\n : nothing\n }\n ${CpkThreadInspector.TAB_LIST.map((tab) =>\n this._activatedTabs.has(tab.id)\n ? html`<div\n id=${this.panelDomId(tab.id)}\n class=\"cpk-td__panel\"\n role=\"tabpanel\"\n aria-labelledby=${this.tabDomId(tab.id)}\n ?hidden=${this._tab !== tab.id || this._panelInitializing}\n >\n ${this.renderTabContent(tab.id)}\n </div>`\n : nothing,\n )}\n </div>\n </div>\n\n <!--\n Drawer always rendered so width animates between 0 and its\n target. Divider lives INSIDE the drawer and is absolutely\n positioned over its left edge so the toggle (rightmost of the\n tab row) and the drawer touch with no flex-gap between them.\n -->\n <div\n class=\"cpk-td__detail\"\n data-open=${this._showDetailPanel ? \"true\" : \"false\"}\n style=\"width:${this._showDetailPanel ? this._detailPanelWidth : 0}px\"\n aria-hidden=${this._showDetailPanel ? \"false\" : \"true\"}\n >\n ${\n this._showDetailPanel\n ? html`\n <div\n class=\"cpk-td__detail-divider\"\n @pointerdown=${this.onDetailDividerDown}\n @pointermove=${this.onDetailDividerMove}\n @pointerup=${this.onDetailDividerUp}\n @pointercancel=${this.onDetailDividerUp}\n ></div>\n `\n : nothing\n }\n ${this.renderDetailPanel()}\n </div>\n </div>\n `;\n }\n\n private renderViewInAppAction() {\n if (this.viewInAppMode === \"hidden\") return nothing;\n const isStop = this.viewInAppMode === \"stop\";\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__view-in-app ${isStop ? \"cpk-td__view-in-app--stop\" : \"\"}\"\n data-testid=\"cpk-inspector-view-in-app\"\n aria-label=${\n isStop\n ? \"Stop viewing this thread in the app\"\n : \"View this thread in your app\"\n }\n @click=${() => {\n this.dispatchEvent(\n new CustomEvent(isStop ? \"stopViewing\" : \"viewInApp\", {\n bubbles: true,\n composed: true,\n }),\n );\n }}\n >\n ${isStop ? \"Stop viewing\" : \"View in your app\"}\n </button>\n ${\n this.viewInAppError\n ? html`<span class=\"cpk-td__view-in-app-error\" role=\"alert\"\n >${this.viewInAppError}</span\n >`\n : nothing\n }\n `;\n }\n\n private renderTryFromHereControl() {\n if (!this.tryFromHereAvailable) return nothing;\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__try-from-here\"\n aria-label=\"Try from here\"\n ?disabled=${this.tryFromHereBusy}\n @click=${this.onTryFromHere}\n >\n ${this.tryFromHereBusy ? \"Loading…\" : \"Try from here\"}\n <svg\n class=\"cpk-td__try-from-here-icon\"\n aria-hidden=\"true\"\n width=\"12\"\n height=\"12\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M7 7h10v10\" />\n <path d=\"M7 17 17 7\" />\n </svg>\n </button>\n ${\n this.tryFromHereError\n ? html`<span class=\"cpk-td__try-from-here-error\" role=\"alert\"\n >${this.tryFromHereError}</span\n >`\n : nothing\n }\n `;\n }\n\n private onTryFromHere = (event: Event): void => {\n event.preventDefault();\n if (!this.tryFromHereAvailable || this.tryFromHereBusy) return;\n this.dispatchEvent(\n new CustomEvent(\"tryFromHere\", {\n detail: this.threadId,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private renderTimelineBulkButtons() {\n if (this._eventsNotAvailable) return nothing;\n\n const detailIds = this.timelineItemsForEvents(this.activeEvents)\n .filter((item) => item.details)\n .map((item) => item.id);\n if (detailIds.length <= 1) return nothing;\n\n const allExpanded = detailIds.every((id) =>\n this._expandedTimelineDetails.has(id),\n );\n\n return html`\n <button\n type=\"button\"\n class=\"cpk-td__timeline-bulk-toggle\"\n @click=${() => (allExpanded ? this.collapseTimelineDetails(detailIds) : this.expandTimelineDetails(detailIds))}\n >\n ${allExpanded ? \"Collapse all\" : \"Expand all\"}\n </button>\n `;\n }\n\n private renderRawEventBulkControls() {\n const eventIds = this.activeEvents.map((event) => this.rawEventId(event));\n if (eventIds.length <= 1) return nothing;\n\n const allExpanded = eventIds.every((id) => this._expandedRawEvents.has(id));\n\n return html`<div class=\"cpk-td__timeline-toolbar\">\n <button\n type=\"button\"\n class=\"cpk-td__timeline-bulk-toggle\"\n @click=${() => (allExpanded ? this.collapseRawEventDetails(eventIds) : this.expandRawEventDetails(eventIds))}\n >\n ${allExpanded ? \"Collapse all\" : \"Expand all\"}\n </button>\n </div>`;\n }\n\n private revealSourceEvent(sourceIndex: number): void {\n this._activatedTabs = new Set([...this._activatedTabs, \"raw-events\"]);\n this._tab = \"raw-events\";\n this.requestUpdate();\n requestAnimationFrame(() => {\n const source = this.shadowRoot?.querySelector<HTMLElement>(\n `[data-source-index=\"${sourceIndex}\"]`,\n );\n source?.scrollIntoView?.({ block: \"center\" });\n });\n }\n\n private renderTimeline() {\n if (this._loadingEvents) {\n return html`\n <div class=\"cpk-td__status\">Loading timeline…</div>\n `;\n }\n if (this._eventsError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._eventsError}\n </div>`;\n }\n if (this._eventsNotAvailable) {\n if (this._conversation.length > 0) {\n return this.renderConversation();\n }\n if (this._loadingMessages) {\n return this.renderConversation();\n }\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>Timeline event history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread AG-UI events. Check State for\n the latest snapshot when available.</span\n >\n </div>\n `;\n }\n\n const events = this.activeEvents;\n const cachedTimeline = this.getCachedPanelTpl(\"timeline\", [\n events,\n this._conversation,\n this.agentMessagesInput,\n this._expandedTimelineDetails,\n ]);\n if (cachedTimeline) return cachedTimeline;\n\n const timelineItems = this.timelineItemsForEvents(events);\n if (timelineItems.length === 0) {\n if (this._conversation.length > 0) {\n return this.renderConversation();\n }\n if (this._loadingMessages) {\n return this.renderConversation();\n }\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>No timeline events captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Timeline rows are normalized from AG-UI events. Open AG-UI Events or State\n to inspect the available thread data.</span\n >\n </div>\n `;\n }\n\n return this.cachedPanelTpl(\n \"timeline\",\n [\n events,\n this._conversation,\n this.agentMessagesInput,\n this._expandedTimelineDetails,\n ],\n () => html`${timelineItems.map((item) => this.renderTimelineItem(item))}`,\n );\n }\n\n private timelineItemClass(item: TimelineItem): string {\n const classes = [\n \"cpk-td__timeline-item\",\n `cpk-td__timeline-item--${item.kind}`,\n ];\n if (item.kind === \"warning\" || item.severity === \"error\") {\n classes.push(\"cpk-td__timeline-item--warning\");\n }\n if (item.kind === \"message\") {\n const title = item.title.toLowerCase();\n if (title.startsWith(\"user\")) {\n classes.push(\"cpk-td__timeline-item--user\");\n } else if (title.includes(\"assistant\")) {\n classes.push(\"cpk-td__timeline-item--assistant\");\n }\n }\n return classes.join(\" \");\n }\n\n private renderTimelineItem(item: TimelineItem) {\n const detailsExpanded = this._expandedTimelineDetails.has(item.id);\n return html`\n <div\n class=${this.timelineItemClass(item)}\n data-message-id=${item.messageId ?? nothing}\n >\n <div class=\"cpk-td__timeline-header\">\n <span class=\"cpk-td__timeline-kind\"\n >${item.severity === \"error\" ? \"error\" : item.kind}</span\n >\n <span class=\"cpk-td__timeline-title\">${item.title}</span>\n ${\n item.sourceIndex\n ? html`\n <button\n type=\"button\"\n class=\"cpk-td__source-link\"\n @click=${() => this.revealSourceEvent(item.sourceIndex)}\n >\n Source event #${item.sourceIndex}\n </button>\n `\n : nothing\n }\n <span class=\"cpk-td__timeline-time\"\n >${formatTimestamp(item.timestamp)}</span\n >\n </div>\n ${\n item.details\n ? html`<button\n type=\"button\"\n class=\"cpk-td__timeline-details-toggle\"\n aria-expanded=${detailsExpanded ? \"true\" : \"false\"}\n @click=${() => this.toggleTimelineDetails(item.id)}\n >\n ${\n detailsExpanded\n ? html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n : html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n `\n }\n <span>${detailsExpanded ? \"Hide details\" : \"Show details\"}</span>\n </button>`\n : nothing\n }\n ${\n item.body\n ? html`<div class=\"cpk-td__timeline-body\">${item.body}</div>`\n : nothing\n }\n ${\n item.details && detailsExpanded\n ? renderHighlightedJsonBlock(item.details)\n : nothing\n }\n </div>\n `;\n }\n\n private renderConversation() {\n if (this._loadingMessages) {\n return html`\n <div class=\"cpk-td__status\">Loading messages…</div>\n `;\n }\n if (this._messagesError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._messagesError}\n </div>`;\n }\n if (this._conversation.length === 0) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <path d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\" />\n </svg>\n <span>No messages yet</span>\n </div>\n `;\n }\n const items = this.renderItems;\n const errors = this.conversationRunErrors(items);\n // Event chunks must not rebuild a long conversation. Only the error rows\n // and their placement are relevant to this panel, not the full event list.\n return this.cachedPanelTpl(\n \"timeline-fallback\",\n [\n this._conversation,\n this._expandedTools,\n this._expandedMessages,\n JSON.stringify(errors),\n this._expandedTimelineDetails,\n ],\n () => {\n const errorsAfter = new Map<number, TimelineItem[]>();\n for (const { after, item } of errors) {\n const group = errorsAfter.get(after) ?? [];\n group.push(item);\n errorsAfter.set(after, group);\n }\n const renderErrors = (after: number) =>\n errorsAfter.get(after)?.map((item) => this.renderTimelineItem(item));\n return html`\n ${renderErrors(-1)}\n ${items.map((item, index) => html`${this.renderRenderItem(item)}${renderErrors(index)}`)}\n `;\n },\n );\n }\n\n private conversationRunErrors(items: RenderItem[]) {\n const positions = new Map<string, number>();\n items.forEach((item, index) => {\n positions.set(item.id, index);\n if (item.type === \"tool_call_group\") {\n for (const tool of item.items) positions.set(tool.id, index);\n }\n });\n const errors: Array<{ after: number; item: TimelineItem }> = [];\n let after = -1;\n let hasAnchor = false;\n for (const event of this.activeEvents) {\n const keys = event.type.startsWith(\"TOOL_CALL\")\n ? [\"toolCallId\", \"tool_call_id\", \"callId\", \"id\"]\n : event.type.startsWith(\"TEXT_MESSAGE\") ||\n event.type.startsWith(\"ACTIVITY\")\n ? [\"messageId\", \"message_id\", \"id\"]\n : [];\n const id = keys\n .map((key) => event.payload[key])\n .find((value) => typeof value === \"string\");\n const position = id == null ? undefined : positions.get(id);\n if (position !== undefined) {\n after = Math.max(after, position);\n hasAnchor = true;\n }\n if (event.type === \"RUN_ERROR\" || event.type === \"ERROR\") {\n for (const item of this.timelineItemsFromEvents([event])) {\n errors.push({ after, item });\n }\n }\n }\n // Some runtimes supply errors without message events. Keep those visible\n // after the saved conversation rather than pretending they happened first.\n if (!hasAnchor) {\n for (const error of errors) error.after = items.length - 1;\n }\n return errors;\n }\n\n /**\n * Memoize the rendered TemplateResult for `slot` keyed by tuple\n * element-wise reference equality. The hot path for tab switches: when\n * the underlying data hasn't changed, return the previously built\n * TemplateResult so Lit's diff short-circuits. Each panel's `key` is\n * the tuple of inputs the template reads — pass everything the template\n * depends on, or the cache will return stale output when those inputs\n * change without the listed key flipping.\n */\n private cachedPanelTpl(\n slot: ThreadDetailsPanelCacheSlot,\n key: readonly unknown[],\n build: () => TemplateResult,\n ): TemplateResult {\n const cached = this.getCachedPanelTpl(slot, key);\n if (cached) return cached;\n const tpl = build();\n this._panelTplCache.set(slot, { key, tpl });\n return tpl;\n }\n\n private getCachedPanelTpl(\n slot: ThreadDetailsPanelCacheSlot,\n key: readonly unknown[],\n ): TemplateResult | null {\n const cached = this._panelTplCache.get(slot);\n if (\n cached &&\n cached.key.length === key.length &&\n cached.key.every((v, i) => v === key[i])\n ) {\n return cached.tpl;\n }\n return null;\n }\n\n private renderRenderItem(item: RenderItem) {\n switch (item.type) {\n case \"user\":\n case \"assistant\":\n return this.renderBubble(item);\n case \"tool_call\":\n return this.renderToolBlock(item);\n case \"tool_call_group\":\n return this.renderToolGroup(item);\n case \"reasoning\":\n return html`<div class=\"cpk-td__inline-chip\">\n <span>Reasoned for ${item.duration}</span>\n </div>`;\n case \"state_update\":\n return html`\n <div class=\"cpk-td__inline-chip\">\n <span>Updated agent state</span>\n </div>\n `;\n case \"generative-ui\":\n return this.renderGenerativeUI(item);\n case \"agent_responded\":\n return nothing;\n }\n }\n\n private renderBubble(item: ConversationUser | ConversationAssistant) {\n const isUser = item.type === \"user\";\n const threshold = CpkThreadInspector.COLLAPSE_THRESHOLD;\n const expanded = this._expandedMessages.has(item.id);\n const tooLong = item.content.length > threshold;\n const shown =\n tooLong && !expanded\n ? item.content.slice(0, threshold) + \"…\"\n : item.content;\n return html`\n <div\n class=\"cpk-td__bubble ${\n isUser ? \"cpk-td__bubble--user\" : \"cpk-td__bubble--assistant\"\n }\"\n data-message-id=${item.id}\n role=\"group\"\n aria-label=${isUser ? \"User message\" : \"Assistant message\"}\n >\n <div\n class=\"cpk-td__bubble-inner ${\n isUser\n ? \"cpk-td__bubble-inner--user\"\n : \"cpk-td__bubble-inner--assistant\"\n }\"\n >\n <div style=\"white-space:pre-wrap\">${shown}</div>\n ${\n tooLong\n ? html`<span\n class=\"cpk-td__show-more\"\n @click=${() => this.toggleMessageExpand(item.id)}\n >${expanded ? \"Show less\" : \"Show more\"}</span\n >`\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private renderToolBlock(item: ConversationToolCall) {\n const expanded = this._expandedTools.has(item.id);\n return html`\n <div class=\"cpk-td__tool-block\">\n <button\n type=\"button\"\n class=\"cpk-td__tool-header\"\n aria-expanded=${expanded}\n @click=${() => this.toggleToolExpand(item.id)}\n >\n <svg width=\"14\" height=\"14\" viewBox=\"0 0 24 24\" fill=\"none\" aria-hidden=\"true\">\n <path\n d=\"M14.7 6.3a1 1 0 0 0 0 1.4l1.6 1.6a1 1 0 0 0 1.4 0l3.77-3.77a6 6 0 0 1-7.94 7.94l-6.91 6.91a2.12 2.12 0 0 1-3-3l6.91-6.91a6 6 0 0 1 7.94-7.94z\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n />\n </svg>\n <span class=\"cpk-td__tool-name\">${item.toolName}</span>\n ${\n item.resultUnreadable\n ? html`\n <span class=\"cpk-td__tool-status cpk-td__tool-status--pending\"\n >Result unreadable</span\n >\n `\n : item.hasResult\n ? html`\n <span class=\"cpk-td__tool-status\">Result received</span>\n `\n : html`\n <span class=\"cpk-td__tool-status cpk-td__tool-status--pending\"\n >No result recorded</span\n >\n `\n }\n <span class=\"cpk-td__tool-chevron\">${expanded ? \"▾\" : \"▸\"}</span>\n </button>\n ${\n expanded\n ? html`\n <div class=\"cpk-td__tool-body\">\n <div class=\"cpk-td__tool-section-label\">Arguments</div>\n ${renderHighlightedJsonBlock(item.arguments)}\n ${\n item.hasResult\n ? html`\n <div\n class=\"cpk-td__tool-section-label\"\n style=\"margin-top:8px\"\n >\n Result\n </div>\n ${renderHighlightedJsonBlock(item.result)}\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private renderToolGroup(group: ToolCallGroup) {\n return html`\n <div class=\"cpk-td__tool-group\">\n <div class=\"cpk-td__tool-group-header\">\n ${group.items.length} tool call${group.items.length !== 1 ? \"s\" : \"\"}\n </div>\n ${group.items.map((tc) => this.renderToolBlock(tc))}\n </div>\n `;\n }\n\n private renderGenerativeUI(item: ConversationGenerativeUIItem) {\n return html`\n <div class=\"cpk-td__genui\">\n <div class=\"cpk-td__genui-badge\">\n <svg width=\"9\" height=\"9\" viewBox=\"0 0 24 24\" fill=\"currentColor\">\n <path d=\"M13 2L3 14h9l-1 8 10-12h-9l1-8z\" />\n </svg>\n <span>Generative UI</span>\n <code class=\"cpk-td__genui-component\">${item.activityType}</code>\n </div>\n </div>\n `;\n }\n\n private renderState() {\n if (this._loadingState) {\n return html`\n <div class=\"cpk-td__status\">Loading state…</div>\n `;\n }\n if (this._stateError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._stateError}\n </div>`;\n }\n if (this._stateNotAvailable) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n <span>State history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread agent state. Available when\n running against the in-memory runner.</span\n >\n </div>\n `;\n }\n if (!this.hasRenderableState()) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <svg\n width=\"28\"\n height=\"28\"\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 >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n <span>No state captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Emitted live from STATE_SNAPSHOT events.</span\n >\n </div>\n `;\n }\n const stateValue = this.activeState;\n return this.cachedPanelTpl(\"state\", [stateValue], () => {\n return renderHighlightedJsonBlock(stateValue);\n });\n }\n\n private renderEvents() {\n if (this._loadingEvents) {\n return html`\n <div class=\"cpk-td__status\">Loading events…</div>\n `;\n }\n if (this._eventsError) {\n return html`<div class=\"cpk-td__status cpk-td__status--error\">\n ${this._eventsError}\n </div>`;\n }\n if (this._eventsNotAvailable) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>Event history not available</span>\n <span class=\"cpk-td__empty-hint\"\n >This runtime doesn't yet expose per-thread AG-UI events. Available when\n running against the in-memory runner.</span\n >\n </div>\n `;\n }\n const events = this.activeEvents;\n if (events.length === 0) {\n return html`\n <div class=\"cpk-td__empty-state\">\n <span>No events captured</span>\n <span class=\"cpk-td__empty-hint\"\n >Events are recorded live. Run the agent to see them here.</span\n >\n </div>\n `;\n }\n return this.cachedPanelTpl(\n \"raw-events\",\n [events, this._expandedRawEvents],\n () => {\n return html`${this.renderRawEventBulkControls()}${events.map(\n (event) => {\n const eventId = this.rawEventId(event);\n const detailsExpanded = this._expandedRawEvents.has(eventId);\n return html`\n <div\n class=\"cpk-td__event cpk-td__event--${eventCategory(\n event.type,\n )}\"\n data-source-index=${event.sourceIndex}\n >\n <div class=\"cpk-td__event-header\">\n <span class=\"cpk-td__event-type\" title=${event.type}\n >${humanizeEventType(event.type)}</span\n >\n <span class=\"cpk-td__event-time\"\n >${formatTimestamp(event.timestamp)}</span\n >\n </div>\n <button\n type=\"button\"\n class=\"cpk-td__timeline-details-toggle\"\n aria-expanded=${detailsExpanded ? \"true\" : \"false\"}\n @click=${() => this.toggleRawEventDetails(eventId)}\n >\n ${\n detailsExpanded\n ? html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m6 9 6 6 6-6\" />\n </svg>\n `\n : html`\n <svg\n aria-hidden=\"true\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"m9 18 6-6-6-6\" />\n </svg>\n `\n }\n <span\n >${detailsExpanded ? \"Hide details\" : \"Show details\"}</span\n >\n </button>\n ${\n detailsExpanded\n ? renderHighlightedJsonBlock(event.rawEvent ?? event)\n : nothing\n }\n </div>\n `;\n },\n )}`;\n },\n );\n }\n\n private renderPanelToggle() {\n return html`\n <button\n class=\"cpk-td__panel-toggle ${\n this._showDetailPanel ? \"cpk-td__panel-toggle--active\" : \"\"\n }\"\n @click=${() => {\n this._showDetailPanel = !this._showDetailPanel;\n }}\n title=\"Toggle thread details\"\n type=\"button\"\n >\n <svg\n width=\"14\"\n height=\"14\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"currentColor\"\n stroke-width=\"2\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <rect x=\"3\" y=\"3\" width=\"18\" height=\"18\" rx=\"2\" />\n <line x1=\"15\" y1=\"3\" x2=\"15\" y2=\"21\" />\n </svg>\n </button>\n `;\n }\n\n private renderDetailPanel() {\n const counts = this.activityCounts;\n const metadata = this.metadata;\n return html`\n <!-- Thread -->\n <div class=\"cpk-tdp__section-title\">Thread</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">ID</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--wrap\"\n >${metadata?.id ?? this.threadId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Name</span>\n <span class=\"cpk-tdp__value\">${metadata?.name ?? \"—\"}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Agent</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.agentId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">End user</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.endUserId ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Created by</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.createdById ?? \"—\"}</span\n >\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Status</span>\n <span class=\"cpk-tdp__value cpk-tdp__value--truncate\"\n >${metadata?.status ?? \"—\"}</span\n >\n </div>\n\n <div class=\"cpk-tdp__divider\"></div>\n\n <!-- Timestamps -->\n <div class=\"cpk-tdp__section-title\">Timestamps</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Created</span>\n <span class=\"cpk-tdp__value\">${this.fmtTime(metadata?.createdAt)}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Updated</span>\n <span class=\"cpk-tdp__value\">${this.fmtTime(metadata?.updatedAt)}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Duration</span>\n <span class=\"cpk-tdp__value\">${this.duration}</span>\n </div>\n\n <div class=\"cpk-tdp__divider\"></div>\n\n <!-- Activity -->\n <div class=\"cpk-tdp__section-title\">Activity</div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Messages</span>\n <span class=\"cpk-tdp__value\">${counts.messages}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">Tool calls</span>\n <span class=\"cpk-tdp__value\">${counts.toolCalls}</span>\n </div>\n <div class=\"cpk-tdp__row\">\n <span class=\"cpk-tdp__label\">AG-UI events</span>\n <span class=\"cpk-tdp__value\">${this.activeEvents.length}</span>\n </div>\n `;\n }\n}\n\n// ─── memory recall relevance helpers ─────────────────────────────────────────\n\n/**\n * Normalizes a memory's raw recall score to a 0..1 relevance ratio relative to\n * the strongest result in the same result set. Recall scores are RRF scores\n * (relative), so a bar is only meaningful against the set max. Returns\n * `undefined` when no meaningful ranking exists (empty set, non-positive max,\n * missing score) so the caller renders no bar.\n */\nfunction normalizeRelevance(\n score: number | undefined,\n maxScore: number,\n): number | undefined {\n if (maxScore <= 0) return undefined;\n if (score === undefined || !Number.isFinite(score)) return undefined;\n const ratio = score / maxScore;\n if (ratio <= 0) return 0;\n return ratio > 1 ? 1 : ratio;\n}\n\n/** Largest finite `score` across a result set, or 0 when none present. */\nfunction maxRecallScore(memories: readonly Memory[]): number {\n let max = 0;\n for (const m of memories) {\n const s = m.score;\n if (typeof s === \"number\" && Number.isFinite(s) && s > max) max = s;\n }\n return max;\n}\n\n/**\n * Percent width for a relevance bar. Mirrors the banking reference\n * (`max(6, round(rel*100))%`) so a matched-but-weak result still shows a sliver.\n * Returns a whole number in [6, 100].\n */\nfunction relevanceBarWidth(relevance: number): number {\n return Math.max(6, Math.min(100, Math.round(relevance * 100)));\n}\n\nexport {\n normalizeRelevance as ɵnormalizeRelevance,\n maxRecallScore as ɵmaxRecallScore,\n relevanceBarWidth as ɵrelevanceBarWidth,\n};\n\n// ─── cpk-memory-list ─────────────────────────────────────────────────────────\n\n/** Memory kind values including the \"all\" sentinel used by the filter UI. */\ntype MemoryKindFilter = \"all\" | \"topical\" | \"episodic\" | \"operational\";\n\nclass CpkMemoryList extends PortableLitElement {\n static properties = {\n memories: { attribute: false },\n recallResults: { attribute: false },\n recallLoading: { attribute: false },\n recallError: { attribute: false },\n recallQueryText: { attribute: false },\n search: { state: true },\n kind: { state: true },\n };\n\n /** Ordered (newest-first) list of memories supplied by the parent. */\n memories: Memory[] = [];\n /** Semantic-recall results. `null` = no recall run (section hidden); `[]` = ran, no matches. */\n recallResults: Memory[] | null = null;\n /** True while a recall request is in flight. */\n recallLoading = false;\n /** Error message from the most recent recall attempt, or null. */\n recallError: string | null = null;\n /** The recall input text (owned by the parent). */\n recallQueryText = \"\";\n private search = \"\";\n private kind: MemoryKindFilter = \"all\";\n\n static styles = css`\n @import url(\"https://fonts.googleapis.com/css2?family=Plus+Jakarta+Sans:wght@400;500;600&family=Spline+Sans+Mono:wght@400;500&display=swap\");\n\n :host {\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n }\n\n .cpk-ml {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n display: flex;\n flex-direction: column;\n height: 100%;\n overflow: hidden;\n background: #f7f7f9;\n }\n\n /* ── Search ── */\n .cpk-ml__search {\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n\n .cpk-ml__search-input {\n width: 100%;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n\n .cpk-ml__search-input:focus {\n border-color: #bec2ff;\n }\n\n /* ── Kind filter ── */\n .cpk-ml__filter {\n display: flex;\n gap: 4px;\n padding: 8px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n flex-wrap: wrap;\n }\n\n .cpk-ml__filter-seg {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 11px;\n font-weight: 500;\n padding: 3px 9px;\n border-radius: 6px;\n border: 1px solid #dbdbe5;\n background: #ffffff;\n color: #57575b;\n cursor: pointer;\n transition:\n background 0.1s,\n border-color 0.1s,\n color 0.1s;\n user-select: none;\n }\n\n .cpk-ml__filter-seg:hover {\n background: #f0f0f5;\n }\n\n .cpk-ml__filter-seg--active {\n background: #bec2ff1a;\n border-color: #bec2ff;\n color: #010507;\n }\n\n .cpk-ml__filter-count {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n margin-left: 4px;\n color: #68686e;\n }\n\n /* ── List ── */\n .cpk-ml__list {\n flex: 1;\n overflow-y: auto;\n padding: 8px 12px;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n\n /* ── Card ── */\n .cpk-ml__card {\n background: #ffffff;\n border: 1px solid #e9e9ef;\n border-radius: 10px;\n padding: 10px 12px;\n display: flex;\n flex-direction: column;\n gap: 6px;\n }\n\n .cpk-ml__card-badges {\n display: flex;\n gap: 6px;\n align-items: center;\n flex-wrap: wrap;\n }\n\n /* Kind badge — color per kind */\n .cpk-ml__kind-badge {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n }\n\n .cpk-ml__kind-badge--topical {\n background: #eee6fe;\n color: #57575b;\n }\n\n .cpk-ml__kind-badge--episodic {\n background: #e6f4fe;\n color: #2d5f80;\n }\n\n .cpk-ml__kind-badge--operational {\n background: #e6feee;\n color: #2d6645;\n }\n\n /* Scope badge */\n .cpk-ml__scope-badge {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n padding: 1px 7px;\n border-radius: 5px;\n text-transform: uppercase;\n font-weight: 500;\n white-space: nowrap;\n background: #f0f0f5;\n color: #68686e;\n }\n\n /* Content */\n .cpk-ml__content {\n font-size: 12px;\n color: #010507;\n line-height: 1.5;\n word-break: break-word;\n }\n\n /* Footer */\n .cpk-ml__footer {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n margin-top: 2px;\n }\n\n .cpk-ml__footer-threads {\n font-size: 10px;\n color: #68686e;\n }\n\n .cpk-ml__footer-id {\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 9px;\n color: #c0c0c8;\n }\n\n /* ── Empty state ── */\n .cpk-ml__empty {\n padding: 32px 16px;\n text-align: center;\n color: #68686e;\n font-size: 12px;\n display: flex;\n flex-direction: column;\n align-items: center;\n gap: 8px;\n }\n\n .cpk-ml__empty-icon {\n color: #c0c0c8;\n }\n\n /* ── Recall ── */\n .cpk-ml__recall {\n display: flex;\n gap: 6px;\n padding: 10px 12px;\n border-bottom: 1px solid #dbdbe5;\n flex-shrink: 0;\n }\n .cpk-ml__recall-input {\n flex: 1;\n box-sizing: border-box;\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n padding: 7px 10px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #fff;\n color: #010507;\n outline: none;\n transition: border-color 0.15s;\n }\n .cpk-ml__recall-input:focus {\n border-color: #bec2ff;\n }\n .cpk-ml__recall-btn {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 500;\n padding: 7px 12px;\n border-radius: 7px;\n border: 1px solid #dbdbe5;\n background: #fff;\n color: #010507;\n cursor: pointer;\n transition: background 0.1s;\n }\n .cpk-ml__recall-btn:hover:not(:disabled) {\n background: #f0f0f5;\n }\n .cpk-ml__recall-btn:disabled {\n opacity: 0.4;\n cursor: default;\n }\n .cpk-ml__recall-section {\n flex-shrink: 0;\n max-height: 45%;\n overflow-y: auto;\n padding: 8px 12px;\n border-bottom: 1px solid #dbdbe5;\n background: #fbfbfd;\n display: flex;\n flex-direction: column;\n gap: 8px;\n }\n .cpk-ml__recall-header {\n display: flex;\n align-items: center;\n justify-content: space-between;\n gap: 8px;\n }\n .cpk-ml__recall-title {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 12px;\n font-weight: 600;\n color: #010507;\n }\n .cpk-ml__recall-clear {\n font-family: \"Plus Jakarta Sans\", sans-serif;\n font-size: 10px;\n color: #68686e;\n background: none;\n border: none;\n cursor: pointer;\n padding: 0;\n }\n .cpk-ml__recall-clear:hover {\n color: #010507;\n }\n .cpk-ml__recall-msg {\n font-size: 11px;\n color: #68686e;\n line-height: 1.45;\n }\n .cpk-ml__recall-msg--error {\n color: #c0333a;\n }\n\n /* ── Relevance bar ── */\n .cpk-ml__relevance {\n height: 4px;\n width: 100%;\n overflow: hidden;\n border-radius: 9999px;\n background: #f0f0f5;\n }\n .cpk-ml__relevance-fill {\n height: 100%;\n border-radius: 9999px;\n background: #6366f1;\n }\n\n /* ── Scope badge variants ── */\n .cpk-ml__scope-badge--user {\n background: #f0f0f5;\n color: #68686e;\n }\n .cpk-ml__scope-badge--project {\n background: #fef3c7;\n color: #92660c;\n }\n\n :host([data-color-scheme=\"dark\"]) {\n color-scheme: dark;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml {\n background: #15171e;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__search,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-section,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__card {\n border-color: #343742;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__search-input,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-input,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-btn,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__card {\n border-color: #464957;\n background: #191c24;\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-section {\n background: #171a22;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg:hover,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-btn:hover:not(:disabled) {\n background: #20232d;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-seg--active {\n border-color: #777aae;\n background: #292b43;\n color: #d8d9ff;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__content,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-title {\n color: #f3f4f8;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-ml__filter-count,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__footer-threads,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__footer-id,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__empty,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-clear,\n :host([data-color-scheme=\"dark\"]) .cpk-ml__recall-msg {\n color: #aeb1bd;\n }\n `;\n\n /** Memories that pass the current text search (before kind filter). */\n private get searchFiltered(): Memory[] {\n const q = this.search.trim().toLowerCase();\n if (!q) return this.memories;\n return this.memories.filter((m) => m.content.toLowerCase().includes(q));\n }\n\n /** Memories that pass both search and kind filter. */\n private get filtered(): Memory[] {\n const searched = this.searchFiltered;\n if (this.kind === \"all\") return searched;\n return searched.filter((m) => m.kind === this.kind);\n }\n\n /** Count of search-filtered memories for a given kind (for segment labels). */\n private countForKind(kind: Exclude<MemoryKindFilter, \"all\">): number {\n return this.searchFiltered.filter((m) => m.kind === kind).length;\n }\n\n private onSearchInput = (event: Event): void => {\n this.search = (event.target as HTMLInputElement).value;\n };\n\n private onKindClick = (event: Event): void => {\n const seg = (event.target as HTMLElement).closest(\"[data-kind]\");\n if (!seg) return;\n const k = (seg as HTMLElement).dataset[\"kind\"] as MemoryKindFilter;\n this.kind = k;\n };\n\n /** Truncate an id to first-4…last-4 characters. */\n private shortId(id: string): string {\n if (id.length <= 12) return id;\n return `${id.slice(0, 4)}…${id.slice(-4)}`;\n }\n\n private renderKindBadge(kind: string): TemplateResult {\n return html`<span class=\"cpk-ml__kind-badge cpk-ml__kind-badge--${kind}\"\n >${kind}</span\n >`;\n }\n\n private renderScopeBadge(scope: string): TemplateResult {\n const variant = scope === \"project\" ? \"project\" : \"user\";\n return html`<span\n class=\"cpk-ml__scope-badge cpk-ml__scope-badge--${variant}\"\n >${scope}</span\n >`;\n }\n\n /**\n * Renders one memory card. `relevance` (0..1) is supplied only for recall\n * results — when present a relevance bar is drawn; the full list omits it.\n */\n private renderCard(m: Memory, relevance?: number): TemplateResult {\n const threads = m.sourceThreadIds.length;\n return html`\n <div class=\"cpk-ml__card\">\n <div class=\"cpk-ml__card-badges\">\n ${this.renderKindBadge(m.kind)}${this.renderScopeBadge(m.scope)}\n </div>\n <div class=\"cpk-ml__content\">${m.content}</div>\n ${\n relevance !== undefined\n ? html`<div class=\"cpk-ml__relevance\">\n <div\n class=\"cpk-ml__relevance-fill\"\n style=\"width:${relevanceBarWidth(relevance)}%;\"\n ></div>\n </div>`\n : nothing\n }\n <div class=\"cpk-ml__footer\">\n <span class=\"cpk-ml__footer-threads\"\n >${threads} source thread${threads === 1 ? \"\" : \"s\"}</span\n >\n <span class=\"cpk-ml__footer-id\">${this.shortId(m.id)}</span>\n </div>\n </div>\n `;\n }\n\n private onRecallInput = (event: Event): void => {\n const value = (event.target as HTMLInputElement).value;\n this.recallQueryText = value;\n this.dispatchEvent(\n new CustomEvent<string>(\"recallQueryChanged\", {\n detail: value,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private onRecallSubmit = (event: Event): void => {\n event.preventDefault();\n const query = this.recallQueryText.trim();\n if (query.length === 0 || this.recallLoading) return;\n this.dispatchEvent(\n new CustomEvent<string>(\"recallSubmitted\", {\n detail: query,\n bubbles: true,\n composed: true,\n }),\n );\n };\n\n private onRecallClear = (): void => {\n this.dispatchEvent(\n new CustomEvent(\"recallCleared\", { bubbles: true, composed: true }),\n );\n };\n\n private renderRecallForm(): TemplateResult {\n const disabled =\n this.recallLoading || this.recallQueryText.trim().length === 0;\n return html`\n <form class=\"cpk-ml__recall\" @submit=${this.onRecallSubmit}>\n <input\n type=\"text\"\n placeholder=\"Recall by meaning…\"\n aria-label=\"Recall learning records by meaning\"\n class=\"cpk-ml__recall-input\"\n .value=${this.recallQueryText}\n @input=${this.onRecallInput}\n />\n <button type=\"submit\" class=\"cpk-ml__recall-btn\" ?disabled=${disabled}>\n ${this.recallLoading ? \"…\" : \"Recall\"}\n </button>\n </form>\n `;\n }\n\n private renderRecallSection(): TemplateResult {\n const results = this.recallResults;\n if (results === null) return html``;\n const max = maxRecallScore(results);\n return html`\n <section\n class=\"cpk-ml__recall-section\"\n aria-label=\"Semantic recall results\"\n >\n <div class=\"cpk-ml__recall-header\">\n <span class=\"cpk-ml__recall-title\"\n >Semantic recall (${results.length})</span\n >\n <button\n type=\"button\"\n class=\"cpk-ml__recall-clear\"\n @click=${this.onRecallClear}\n >\n Clear\n </button>\n </div>\n ${\n this.recallError\n ? html`<p class=\"cpk-ml__recall-msg cpk-ml__recall-msg--error\">\n Recall failed: ${this.recallError}\n </p>`\n : results.length === 0\n ? html`\n <p class=\"cpk-ml__recall-msg\">No learning records matched that query.</p>\n `\n : results.map((m) =>\n this.renderCard(m, normalizeRelevance(m.score, max)),\n )\n }\n </section>\n `;\n }\n\n private renderEmpty(): TemplateResult {\n const q = this.search.trim();\n if (this.memories.length === 0) {\n return html`\n <div class=\"cpk-ml__empty\">\n <svg\n width=\"24\"\n height=\"24\"\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=\"cpk-ml__empty-icon\"\n >\n <ellipse cx=\"12\" cy=\"5\" rx=\"9\" ry=\"3\" />\n <path d=\"M21 12c0 1.66-4 3-9 3s-9-1.34-9-3\" />\n <path d=\"M3 5v14c0 1.66 4 3 9 3s9-1.34 9-3V5\" />\n </svg>\n No learning records yet — tell the agent a durable fact and watch it appear.\n </div>\n `;\n }\n if (q) {\n return html`\n <div class=\"cpk-ml__empty\">\n No learning records match &ldquo;${q}&rdquo;.\n </div>\n `;\n }\n return html`\n <div class=\"cpk-ml__empty\">No ${this.kind} learning records yet.</div>\n `;\n }\n\n render() {\n const filtered = this.filtered;\n const kinds: Array<Exclude<MemoryKindFilter, \"all\">> = [\n \"topical\",\n \"episodic\",\n \"operational\",\n ];\n\n return html`\n <div class=\"cpk-ml\">\n <!-- Semantic recall -->\n ${this.renderRecallForm()} ${this.renderRecallSection()}\n\n <!-- Search -->\n <div class=\"cpk-ml__search\">\n <input\n type=\"text\"\n placeholder=\"Search learning…\"\n .value=${this.search}\n @input=${this.onSearchInput}\n class=\"cpk-ml__search-input\"\n />\n </div>\n\n <!-- Kind filter -->\n <div class=\"cpk-ml__filter\" @click=${this.onKindClick}>\n <button\n class=\"cpk-ml__filter-seg ${\n this.kind === \"all\" ? \"cpk-ml__filter-seg--active\" : \"\"\n }\"\n data-kind=\"all\"\n >\n All<span class=\"cpk-ml__filter-count\"\n >${this.searchFiltered.length}</span\n >\n </button>\n ${kinds.map(\n (k) => html`\n <button\n class=\"cpk-ml__filter-seg ${\n this.kind === k ? \"cpk-ml__filter-seg--active\" : \"\"\n }\"\n data-kind=\"${k}\"\n >\n ${k}<span class=\"cpk-ml__filter-count\"\n >${this.countForKind(k)}</span\n >\n </button>\n `,\n )}\n </div>\n\n <!-- Memory list -->\n <div class=\"cpk-ml__list\">\n ${filtered.map((m) => this.renderCard(m))}\n ${filtered.length === 0 ? this.renderEmpty() : nothing}\n </div>\n </div>\n `;\n }\n}\n\n// Backwards-compatible internal element name used by the full CopilotKit\n// Inspector shell. Keep this class thin so the public body remains the single\n// implementation.\nexport class ɵCpkThreadDetails extends CpkThreadInspector {}\n\nfunction defineElementOnce(\n registry: CustomElementRegistry,\n tag: string,\n ctor: CustomElementConstructor,\n): void {\n if (!registry.get(tag)) {\n registry.define(tag, ctor);\n }\n}\n\nexport class WebInspectorElement extends LitElement {\n static properties = {\n core: { attribute: false },\n autoAttachCore: { type: Boolean, attribute: \"auto-attach-core\" },\n _capabilitiesVersion: { state: true },\n } as const;\n\n private _core: CopilotKitCore | null = null;\n private coreSubscriber: CopilotKitCoreSubscriber | null = null;\n private coreUnsubscribe: (() => void) | null = null;\n private _memories: Memory[] = [];\n private _memoriesLoading = false;\n private _memoriesError: Error | null = null;\n private _memoriesAvailable = true;\n // Realtime-connection health, independent of `_memoriesAvailable` (the REST\n // list route). Drives the \"live\" indicator: only \"connected\" shows \"live\".\n private _memoriesRealtimeStatus: MemoryRealtimeStatus = \"connecting\";\n private _memoryUnsub: (() => void) | null = null;\n // Lazy-subscription guard. The memory store is created + started + opens\n // realtime the first time `core.getMemoryStore()` is called, so we defer\n // that call until the user actually activates the Memories tab (see\n // `ensureMemorySubscription`). This flag prevents a repeated tab click from\n // double-subscribing; `detachFromCore` resets it so a later attach + tab\n // activation re-subscribes cleanly.\n private _memorySubscribed = false;\n // True when the attached core predates `getMemoryStore` (older @copilotkit\n // SDK). Distinct from `_memoriesAvailable` (memory not enabled on an\n // otherwise-current deployment) so the teaser can show upgrade-the-SDK copy.\n private _memoryStoreUnsupported = false;\n private learningSnapshot: InspectorLearningSnapshotV1 | null = null;\n private learningSnapshotScope: string | null = null;\n private learningProjectIdentity: string | null = null;\n private learningLoading = false;\n private learningRefreshing = false;\n private learningError: string | null = null;\n private learningSupported = false;\n private learningRequestGeneration = 0;\n private learningAbortController: AbortController | null = null;\n private learningPollTimer: ReturnType<typeof setTimeout> | null = null;\n private learningPollFailureCount = 0;\n private learningSetupMarker: LearningSetupMarker | null = null;\n private learningSetupCopyRequest = 0;\n private learningSetupUnsubscribe: (() => void) | null = null;\n private learningPromptCopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n private learningPromptRecopyState: \"idle\" | \"copied\" | \"error\" = \"idle\";\n private learningPromptRecopyTimer: ReturnType<typeof setTimeout> | null =\n null;\n private learningViewedState: LearningViewState | null = null;\n // ── Semantic recall (B3) ──────────────────────────────────────────────\n // `null` = no recall run yet (section hidden). `[]` = ran, no matches.\n private _recallResults: Memory[] | null = null;\n private _recallLoading = false;\n private _recallError: string | null = null;\n private _recallQuery = \"\";\n // Monotonic token so a slow recall resolving after a newer one / Clear /\n // detach is ignored — last-write-wins without racing state.\n private _recallSeq = 0;\n private runtimeStatus: CopilotKitCoreRuntimeConnectionStatus | null = null;\n private inspectorMetadataValue: unknown;\n private inspectorMetadataProjection: InspectorMetadataProjection =\n projectInspectorMetadata(undefined, undefined);\n // The last *visible* local fingerprint for each metadata module. This is a\n // map rather than a cumulative set so A → B → A produces three impressions,\n // while close/reopen with unchanged metadata produces only one. Fingerprint\n // values can contain local labels and URLs because the map never leaves the\n // browser; outbound helpers rebuild a coarse allowlisted payload.\n private metadataTelemetryFingerprints: Map<\n InspectorMetadataTelemetryModule,\n string\n > = new Map();\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 // Per-thread monotonic version that ticks every time an agent currently\n // running on that thread emits a message change. `cpk-thread-details`\n // watches this prop and re-fetches `/threads/:id/messages` when it changes,\n // which is how live updates flow into the conversation view without\n // duplicating the runtime's message-shape conversion in the inspector.\n private liveMessageVersion: Map<string, number> = 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 accountCtaMotionPaused = false;\n private draggedDuringInteraction = false;\n private ignoreNextButtonClick = false;\n private selectedMenu: MenuKey = \"home\";\n private pendingPersistedMenu: MenuKey | null = null;\n private hasOpenedInspector = false;\n private sidebarCollapsed = false;\n private sidebarRailTooltip: { label: string; top: number } | null = null;\n private colorScheme: InspectorColorScheme = \"light\";\n private hasExplicitColorScheme = false;\n private systemColorSchemeMediaQuery: MediaQueryList | null = null;\n private briefingRestoreMenu: MenuKey | null = null;\n private homeViewedThisOpen = false;\n\n // ── Intelligence install prompt (Home) ──────────────────────────────────\n //\n // One run id per element lifetime, minted on first copy. The CLI treats the\n // id as one onboarding journey, so a developer who copies twice because they\n // switched editors must not look like two journeys.\n private onboardingRunId: string | null = null;\n /**\n * `copied` reverts after {@link PROMPT_COPY_RESET_MS}; `failed` does not.\n *\n * The instruction only has to survive long enough to be read. Keeping it\n * forever left a button wearing a checkmark and reading as spent, which is\n * the wrong signal for the likeliest reason someone comes back to this card:\n * to copy again. A failed copy is the opposite case — the prompt itself is\n * on screen to be selected by hand, so it stays until acted on.\n */\n private promptCopyState: \"idle\" | \"copied\" | \"failed\" = \"idle\";\n private promptCopyResetTimer: ReturnType<typeof setTimeout> | null = null;\n\n // ── Intelligence story (Home) ───────────────────────────────────────────\n //\n // Three beats condensed from the six-phase animation on the Intelligence\n // home page. Runs only while Home is the visible tab AND the document is\n // visible: this is a debugging tool, and a permanent timer behind a closed\n // panel is exactly the kind of thing a developer would find in a profile and\n // rightly complain about.\n private intelStoryBeat = 0;\n private intelStoryUserPinned = false;\n private intelStoryTimer: ReturnType<typeof setTimeout> | null = null;\n private intelStoryReducedMotion: MediaQueryList | null = null;\n private hasResolvedCore = false;\n private settingsOpen = false;\n private readonly lastSelectedMenuByGroup: Record<\n InspectorNavGroupKey,\n MenuKey\n > = {\n home: \"home\",\n workbench: \"threads\",\n inspect: \"ag-ui-events\",\n };\n private lastScrolledAgentNavigationLayout: string | null = null;\n private selectedThreadId: string | null = null;\n private ephemeralThreadsSetupOpen = false;\n private inAppThreadId: string | null = null;\n private inAppAgentId: string | null = null;\n private inAppSource: \"app\" | \"override\" | null = null;\n private activeViewInAppRequestId: string | null = null;\n private viewInAppError: string | null = null;\n private inspectorBridgeUnsubscribers: Array<() => void> = [];\n private selectedRealThreadIsExplicit = false;\n private selectedLocalExampleThreadId: string | null = null;\n private requestedThreadId: string | null = null;\n private focusedThreadMessageId: string | null = null;\n private threadFocusRequestId = 0;\n private threadListWidth = 240;\n private threadListCollapsed = false;\n private threadDividerResizing = false;\n private threadDividerPointerId = -1;\n private threadDividerStartX = 0;\n private threadDividerStartWidth = 0;\n private _threads: ɵThread[] = [];\n private _threadStoreSubscriptions: Map<string, () => void> = new Map();\n private _threadsByAgent: Map<string, ɵThread[]> = new Map();\n private threadUsageSignature = \"\";\n private threadUsageRefreshTimer: ReturnType<typeof setTimeout> | null = null;\n // Error from each agent's thread store (REST list rejection, Phoenix\n // subscribe failure, retry exhaustion). When non-empty for the active\n // selection, the threads view renders an error state instead of stale\n // data with no indication.\n private _threadsErrorByAgent: Map<string, Error> = new Map();\n private _threadsLoadingByAgent: Map<string, boolean> = new Map();\n // Thread stores created and owned by the inspector (keyed by agentId)\n private _ownedThreadStores: Map<string, ɵThreadStore> = new Map();\n private playgroundAgent: AbstractAgent | null = null;\n private playgroundAgentId: string | null = null;\n private playgroundAgentUnsubscribe: (() => void) | null = null;\n private playgroundMessages: InspectorMessage[] = [];\n private playgroundInput = \"\";\n private playgroundIsRunning = false;\n private playgroundRunStartedAt: number | null = null;\n private playgroundReasoningDurations: Map<string, number> = new Map();\n private playgroundIsLoadingThread = false;\n private playgroundError: string | null = null;\n private playgroundSourceThreadId: string | null = null;\n private playgroundShowEphemeralNotice = false;\n private tryFromHereBusy = false;\n private tryFromHereError: string | null = null;\n private threadCapabilityEnabled: boolean | null = null;\n private threadCapabilityGeneration = 0;\n private contextMenuOpen = false;\n private iconRailContextCloseTimer: ReturnType<typeof setTimeout> | null =\n null;\n private layoutMenuOpen = false;\n private dockMode: DockMode = \"floating\";\n private popOut: PopOutHandle | null = null;\n private inspectorPortal: HTMLDivElement | null = null;\n private previousBodyMargins: { left: string; bottom: string } | null = null;\n private previousHtmlOverflowX: string | null = null;\n private transitionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private bodyTransitionTimeoutIds: Set<ReturnType<typeof setTimeout>> =\n new Set();\n private pendingSelectedContext: string | null = null;\n public autoAttachCore = true;\n private attemptedAutoAttach = false;\n private cachedTools: InspectorToolDefinition[] = [];\n private toolSignature = \"\";\n // Bumped after every core.setToolEnabled / core.setCatalogComponentEnabled\n // call so the Capabilities tab re-paints from the fresh isToolEnabled /\n // isCatalogComponentEnabled getters. There is no core subscriber for\n // enablement changes — the inspector itself drives the toggle, so we force\n // the re-render locally.\n private _capabilitiesVersion = 0;\n private eventFilterText = \"\";\n private eventTypeFilter: InspectorAgentEventType | \"all\" = \"all\";\n // Column widths for the AG-UI events table (agent, time, event-type; last col is auto)\n private evtColWidths = [100, 80, 150];\n private _evtColResize: {\n col: number;\n startX: number;\n startW: number;\n } | null = null;\n\n private announcementHtml: string | null = null;\n private announcementMarkdown: string | null = null;\n private announcementTimestamp: string | null = null;\n private announcementPreviewText: string | null = null;\n // Forward-compat for an optional `cta_label` field on the announcement\n // CDN payload (e.g. \"Try threads\", \"New feature\"). The current schema\n // ({timestamp, previewText, announcement}) doesn't carry it, so this is\n // null in production today; we read it defensively in fetchAnnouncement\n // so a future CDN-side schema bump lights up `cta_label` on\n // whats_new_clicked without an inspector release.\n private announcementCtaLabel: string | null = null;\n private announcementLoaded = false;\n private announcementPromise: Promise<void> | null = null;\n private newsSignalArmed = false;\n /** Which signal's beat is in flight, or null between beats. */\n private pulsingSignal: LauncherSignalKey | null = null;\n /**\n * The single pending-beat slot. A beat that cannot land is deferred, never\n * discarded — see `startSignalPulse` for the five reasons it cannot land.\n */\n private pendingPulseSignal: LauncherSignalKey | null = null;\n private pulseTimeoutId: ReturnType<typeof setTimeout> | null = null;\n /**\n * Per-source latches for the error signal, fed from the subscriptions that\n * already exist rather than from the event history: the event buffer is\n * bounded per agent and in total and evicts entries, so counting events\n * could silently lose a live failure.\n */\n private readonly errorSignalArmed: Record<\n InspectorWiringErrorSource,\n boolean\n > = { connection: false, threads: false };\n /** Unread app errors. Cleared when the landing view is read. */\n private readonly eventErrorArmed: Record<InspectorEventErrorSource, boolean> =\n { run: false, tool: false, memory: false };\n /** Latest detail for each event source, retained after that source is read. */\n private readonly eventErrorDetails: Record<\n InspectorEventErrorSource,\n InspectorEventErrorDetails | null\n > = { run: null, tool: null, memory: null };\n private pendingScrollToEventId: string | null = null;\n private pendingScrollToToolCallId: string | null = null;\n /** Last time an inspector-owned /threads refresh left this host, per agent. */\n private readonly threadRefreshLastSentAt: Map<string, number> = new Map();\n /** Trailing /threads refresh timers, one per agent. */\n private readonly threadRefreshTrailingTimers: Map<\n string,\n ReturnType<typeof setTimeout>\n > = new Map();\n /**\n * Whether this outage has already had its beat. Global rather than\n * per-source: a connection failure cascades into thread failures, so one\n * root cause must not produce two nudges. Reset when nothing is red, which\n * is what makes a resolved-then-recurring failure beat again.\n */\n private errorBeatSpent = false;\n /** Per-outage dedup for `oss.inspector.error_signal_viewed`. */\n private readonly errorSignalViewedSources: Set<InspectorErrorSignalSource> =\n new Set();\n /**\n * The signal whose gesture is running its tail — the pill on screen and the\n * sentence in the live region, both of which outlive the beat.\n *\n * Together with `pulsingSignal` this IS the single pending-beat slot, not a\n * second scheduling concept: `startSignalPulse` defers while either is set,\n * so the third deferral reason simply covers a longer beat. Null for the\n * announcement, which has no tail and therefore behaves exactly as before.\n */\n private gestureSignal: LauncherSignalKey | null = null;\n /** Where the running gesture's pill is, or null when it has none. */\n private pillPhase: LauncherPillPhase | null = null;\n /**\n * Which side the pill opens from, or null before the room has been measured.\n * Decided once, at gesture start, and never revisited mid-gesture.\n */\n private pillDirection: LauncherPillDirection | null = null;\n private pillTimeoutId: ReturnType<typeof setTimeout> | null = null;\n /** Hover/focus menu on the closed launcher. */\n private launcherHudOpen = false;\n private launcherHudSide: \"left\" | \"right\" = \"left\";\n private launcherHudCloseTimer: ReturnType<typeof setTimeout> | null = null;\n private launcherHudIntro = false;\n private launcherHudIntroStartTimer: ReturnType<typeof setTimeout> | null =\n null;\n private launcherHudIntroEndTimer: ReturnType<typeof setTimeout> | null = null;\n /** Host-wide deadline that suppresses both the Inspector and its launcher. */\n private inspectorDismissedUntil: number | null = null;\n private lastReportedInspectorVisibility: boolean | null = null;\n private inspectorDismissalTimer: ReturnType<typeof setTimeout> | null = null;\n /**\n * Leaf a HUD row asked for. Consumed by `openInspector` so a red dot on\n * the circle cannot steal \"Turn on Threads\". Not a public open option.\n */\n private hudLandingMenu: MenuKey | null = null;\n /**\n * Whether this outage's pill actually opened. Per outage rather than per\n * phase, so a second source arming behind the first reports the same answer\n * the reader actually got. Reset with `errorBeatSpent`.\n */\n private pillOutcome: LauncherPillOutcome | null = null;\n private viewedNewsSignalIds: Set<string> = new Set();\n private pendingNewsSignalViewed: {\n banner_id: string;\n surface: \"launcher\";\n presentation: WhatsNewSignalPresentation;\n cta_label?: string;\n } | null = null;\n // Per-instance dedup for `oss.inspector.whats_new_viewed`, keyed by\n // `${timestamp}:${surface}` so the event fires at most once per\n // announcement per surface per inspector mount. Plan calls for \"de-dup per\n // timestamp per session\"; instance-scoping is closer to per-mount than\n // per-tab (sessionStorage), but for the inspector the distinction is\n // academic — inspector instances rarely outlive the page. The surface stays\n // part of the key so a second announcement surface would get its own\n // impression rather than being swallowed by the first one's.\n private viewedBannerSurfaces: Set<string> = new Set();\n // Impressions wait for the runtime handshake before going out: the runtime's\n // opt-out arrives in the /info response, and `telemetryDisabled` reads `false`\n // until then, so sending directly would post on a placeholder. This deferral\n // predates the surface split — preserved here, widened from a single slot to a\n // queue because opening the panel reveals the second surface and can happen\n // before the first impression has flushed.\n private pendingBannerViewed: Array<{\n banner_id: string;\n surface: WhatsNewSurface;\n cta_label?: string;\n }> = [];\n // Per-instance dedup for `oss.inspector.whats_new_clicked` (keyed by\n // `${bannerId}:${cta}`) so copy-button retries and accidental multi-clicks\n // don't inflate funnel counts beyond one signal per intent type per banner.\n private clickedBannerIds: Set<string> = new Set();\n private viewedThreadsTelemetryStates: Set<string> = new Set();\n private viewedExampleKinds: Set<ExampleKind> = new Set();\n private selectedExampleKinds: Set<ExampleKind> = new Set();\n private viewedExampleTourSteps: Set<string> = new Set();\n private exampleThreadProviders: Map<string, ThreadDebuggerProvider> =\n new Map();\n private exampleTourDismissed = false;\n private exampleTourActive = false;\n private exampleTourStep = 0;\n private exampleTourAutoShown = false;\n private threadsExampleOverviewVideoState: ThreadsExampleOverviewVideoState =\n \"deferred\";\n private threadsExampleOverviewVideoLoaded = false;\n private threadsExampleOverviewVideoReducedMotion = false;\n private threadsExampleOverviewVideoLoadTimer: number | null = null;\n private threadsExampleOverviewVideoIdleCallbackId: number | null = null;\n private threadsExampleOverviewVideoElement: HTMLVideoElement | null = null;\n private threadsExampleOverviewVideoListeners: ThreadsExampleOverviewVideoListeners | null =\n null;\n private threadsExampleOverviewVideoLifecycleGeneration = 0;\n private threadsExampleOverviewVideoPlayAttemptGeneration = 0;\n private threadsExampleOverviewVideoPlayPromise: Promise<void> | null = null;\n private threadsExampleOverviewVideoPlayOnNextBind = false;\n private homeFeaturePromptCopyState: {\n serviceId: HomeFeaturePromptId;\n state: HomeFeaturePromptCopyState;\n } | null = null;\n private homeFeaturePromptCopyResetTimeoutId: number | null = null;\n private homeFeaturePromptCopyGeneration = 0;\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 const hadResolvedCore = this.hasResolvedCore;\n this.ephemeralThreadsSetupOpen = false;\n this._core = value ?? null;\n if (this._core) {\n this.hasResolvedCore = true;\n }\n\n if (!hadResolvedCore && this._core) {\n this.resolvePendingPersistedMenu();\n } else if (hadResolvedCore) {\n this.reconcileSelectedMenuVisibility();\n }\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 resizeInitialPosition: Position | null = null;\n private resizeEdge: \"e\" | \"w\" | \"s\" | \"se\" | \"sw\" = \"se\";\n private isResizing = false;\n\n private readonly customTabIcons: Record<string, string> = {\n threads: `<svg class=\"h-3.5 w-3.5\" width=\"15\" height=\"15\" viewBox=\"0 0 15 15\" fill=\"none\" xmlns=\"http://www.w3.org/2000/svg\"><path d=\"M9.04167 15C8.29167 15 7.65972 14.7431 7.14583 14.2292C6.63194 13.7153 6.375 13.0972 6.375 12.375C6.375 11.3194 6.80208 10.3646 7.65625 9.51042C8.51042 8.65625 9.57639 8.125 10.8542 7.91667C10.8125 7.41667 10.6875 7.03819 10.4792 6.78125C10.2708 6.52431 9.98611 6.39583 9.625 6.39583C9.20833 6.39583 8.75694 6.56944 8.27083 6.91667C7.78472 7.26389 7.20833 7.83333 6.54167 8.625C5.45833 9.91667 4.66319 10.7569 4.15625 11.1458C3.64931 11.5347 3.10417 11.7292 2.52083 11.7292C1.8125 11.7292 1.21528 11.4653 0.729167 10.9375C0.243056 10.4097 0 9.77083 0 9.02083C0 8.27083 0.163194 7.50347 0.489583 6.71875C0.815972 5.93403 1.36806 4.99306 2.14583 3.89583C2.40972 3.53472 2.60417 3.22917 2.72917 2.97917C2.85417 2.72917 2.91667 2.52778 2.91667 2.375C2.91667 2.27778 2.89931 2.20486 2.86458 2.15625C2.82986 2.10764 2.77778 2.08333 2.70833 2.08333C2.56944 2.08333 2.39583 2.17014 2.1875 2.34375C1.97917 2.51736 1.73611 2.78472 1.45833 3.14583L0 1.66667C0.444444 1.125 0.895833 0.711806 1.35417 0.427083C1.8125 0.142361 2.26389 0 2.70833 0C3.34722 0 3.88889 0.222222 4.33333 0.666667C4.77778 1.11111 5 1.66667 5 2.33333C5 2.73611 4.89583 3.18056 4.6875 3.66667C4.47917 4.15278 4.13194 4.73611 3.64583 5.41667C3.11806 6.16667 2.72569 6.82639 2.46875 7.39583C2.21181 7.96528 2.08333 8.46528 2.08333 8.89583C2.08333 9.13194 2.12153 9.31597 2.19792 9.44792C2.27431 9.57986 2.38194 9.64583 2.52083 9.64583C2.65972 9.64583 2.78125 9.60764 2.88542 9.53125C2.98958 9.45486 3.18056 9.27083 3.45833 8.97917C3.63889 8.78472 3.85417 8.54514 4.10417 8.26042C4.35417 7.97569 4.65972 7.625 5.02083 7.20833C5.89583 6.16667 6.6875 5.42361 7.39583 4.97917C8.10417 4.53472 8.84722 4.3125 9.625 4.3125C10.5556 4.3125 11.3194 4.625 11.9167 5.25C12.5139 5.875 12.8542 6.72917 12.9375 7.8125H15V9.89583H12.9375C12.8264 11.4514 12.4201 12.691 11.7188 13.6146C11.0174 14.5382 10.125 15 9.04167 15ZM9.08333 12.9167C9.52778 12.9167 9.90278 12.6632 10.2083 12.1562C10.5139 11.6493 10.7222 10.9444 10.8333 10.0417C10.1944 10.1944 9.63889 10.4965 9.16667 10.9479C8.69444 11.3993 8.45833 11.8472 8.45833 12.2917C8.45833 12.4861 8.51389 12.6389 8.625 12.75C8.73611 12.8611 8.88889 12.9167 9.08333 12.9167Z\" fill=\"currentColor\"/></svg>`,\n };\n\n private get menuItems(): MenuItem[] {\n const hasFrontendTools = (this._core?.tools?.length ?? 0) > 0;\n const hasCatalog = (this._core?.catalogComponents?.length ?? 0) > 0;\n // Capabilities is the A2UI catalog + tool toggle surface. If the only\n // live data is frontend tools, Frontend Tools already lists them, so\n // showing Capabilities as well is a duplicate leaf.\n const hasCapabilities = hasCatalog;\n return [\n { key: \"home\", label: \"Home\", icon: \"Home\" as LucideIconName },\n {\n key: \"whats-new\",\n label: \"What's New\",\n icon: \"Megaphone\" as LucideIconName,\n },\n {\n key: WHATS_NEW_MENU_KEY,\n label: WHATS_NEW_VIEW_LABEL,\n icon: \"Megaphone\" as LucideIconName,\n },\n {\n key: \"playground\",\n label: \"Playground\",\n icon: \"MessageCircle\" as LucideIconName,\n },\n {\n key: \"ag-ui-events\",\n label: \"AG-UI Events\",\n icon: \"Zap\" as LucideIconName,\n },\n { key: \"agents\", label: \"Agent\", icon: \"Bot\" as LucideIconName },\n ...(hasFrontendTools\n ? [\n {\n key: \"frontend-tools\" as const,\n label: \"Frontend Tools\",\n icon: \"Hammer\" as LucideIconName,\n },\n ]\n : []),\n ...(hasCapabilities\n ? [\n {\n key: \"capabilities\" as const,\n label: CAPABILITIES_TAB_LABEL,\n icon: \"SlidersHorizontal\" as LucideIconName,\n },\n ]\n : []),\n {\n key: \"agent-context\",\n label: \"Context\",\n icon: \"FileText\" as LucideIconName,\n },\n {\n key: \"threads\",\n label: \"Rich Threads\",\n icon: \"MessageSquare\" as LucideIconName,\n },\n {\n key: \"memories\",\n label: LEARNING_VIEW_LABEL,\n icon: \"Brain\" as LucideIconName,\n },\n ];\n }\n\n /** Return only currently visible leaves owned by a group. */\n private getVisibleMenuItemsForGroup(group: InspectorNavGroupKey): MenuItem[] {\n return INSPECTOR_GROUPS[group].flatMap((menuKey) => {\n const item = this.menuItems.find(\n (candidate) => candidate.key === menuKey,\n );\n return item ? [item] : [];\n });\n }\n\n /** Resolve a group's last visible leaf, falling back to its first leaf. */\n private getMenuForGroup(group: InspectorNavGroupKey): MenuKey {\n const visibleItems = this.getVisibleMenuItemsForGroup(group);\n const rememberedMenu = this.lastSelectedMenuByGroup[group];\n return (\n visibleItems.find((item) => item.key === rememberedMenu)?.key ??\n visibleItems[0]?.key ??\n \"home\"\n );\n }\n\n /** Replace a leaf that became hidden with its group's first visible leaf. */\n private reconcileSelectedMenuVisibility(): void {\n if (this.menuItems.some((item) => item.key === this.selectedMenu)) {\n return;\n }\n\n const group = getGroupForMenu(this.selectedMenu);\n const fallbackMenu = this.getVisibleMenuItemsForGroup(group)[0]?.key;\n this.selectedMenu = fallbackMenu ?? \"home\";\n this.lastSelectedMenuByGroup[group] = this.selectedMenu;\n this.persistState();\n }\n\n /** Open a sidebar group at its last currently visible leaf. */\n private handleGroupSelect(group: InspectorNavGroupKey): void {\n this.handleMenuSelect(this.getMenuForGroup(group));\n }\n\n /** Toggle Settings without replacing or persisting the active legacy leaf. */\n private handleSettingsToggle(): void {\n this.settingsOpen = !this.settingsOpen;\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.requestUpdate();\n }\n\n private getThreadServiceStatus(): ThreadServiceStatus {\n if (!this._core) return \"unknown\";\n if (!this._core.threadEndpoints) return \"unknown\";\n return this._core.threadEndpoints?.list === false\n ? \"unavailable\"\n : \"available\";\n }\n\n private areThreadEndpointsAvailable(): boolean {\n const endpoints = this._core?.threadEndpoints;\n return (\n endpoints !== null &&\n typeof endpoints === \"object\" &&\n endpoints.list !== false\n );\n }\n\n private synchronizeThreadCapability(): void {\n const enabled = this.areThreadEndpointsAvailable();\n if (this.threadCapabilityEnabled === enabled) return;\n\n this.threadCapabilityEnabled = enabled;\n this.threadCapabilityGeneration += 1;\n\n if (enabled) {\n const core = this.core;\n if (!core) return;\n\n const threadStores =\n typeof core.getThreadStores === \"function\"\n ? core.getThreadStores()\n : {};\n for (const [agentId, store] of Object.entries(threadStores)) {\n this.subscribeToThreadStore(agentId, store);\n }\n for (const agent of Object.values(core.agents)) {\n if (agent?.agentId) {\n this.ensureOwnedThreadStore(agent.agentId);\n }\n }\n return;\n }\n\n this.teardownThreadStoreSubscriptions();\n this.teardownOwnedThreadStores();\n if (this.selectedThreadId !== this.selectedLocalExampleThreadId) {\n this.selectedThreadId = null;\n this.selectedLocalExampleThreadId = null;\n }\n this.selectedRealThreadIsExplicit = false;\n this.requestUpdate();\n }\n\n private getActiveThreadsState(): {\n displayThreads: ɵThread[];\n threadsErrorMessage: string | null;\n threadsLoading: boolean;\n } {\n const displayThreads =\n this.selectedContext === \"all-agents\"\n ? this._threads\n : (this._threadsByAgent.get(this.selectedContext) ?? []);\n\n // Surface a thread-store load error inline. For \"all-agents\" we report\n // the first error encountered across all agents (good enough for a\n // debugging surface — the per-agent context filter narrows down the\n // culprit). For a specific agent we use that agent's error directly.\n let threadsErrorMessage: string | null = null;\n if (this.selectedContext === \"all-agents\") {\n const firstError = this._threadsErrorByAgent.values().next().value;\n threadsErrorMessage = firstError?.message ?? null;\n } else {\n threadsErrorMessage =\n this._threadsErrorByAgent.get(this.selectedContext)?.message ?? null;\n }\n\n const threadsLoading =\n this.selectedContext === \"all-agents\"\n ? Array.from(this._threadsLoadingByAgent.values()).some(Boolean)\n : (this._threadsLoadingByAgent.get(this.selectedContext) ?? false);\n\n return { displayThreads, threadsErrorMessage, threadsLoading };\n }\n\n /** Bucket trusted usage without retaining exact counts or limits. */\n private getThreadsUsageBucket(): ThreadsUsageBucket {\n const usage = this.inspectorMetadataProjection.usage;\n if (!usage) return \"absent\";\n if (usage.used === 0) return \"empty\";\n if (usage.limit.kind === \"finite\") {\n return usage.used < usage.limit.value\n ? \"within_limit\"\n : \"at_or_over_limit\";\n }\n if (usage.limit.kind === \"unlimited\") return \"unlimited\";\n return \"unknown_limit\";\n }\n\n /** Classify finite usage for render-only capacity copy and color. */\n private getThreadsCapacityState():\n | \"normal\"\n | \"warning\"\n | \"critical\"\n | undefined {\n const usage = this.inspectorMetadataProjection.usage;\n if (!usage || usage.limit.kind !== \"finite\") return undefined;\n if (usage.used >= usage.limit.value) return \"critical\";\n\n const warningThreshold =\n usage.limit.value - Math.floor(usage.limit.value / 10);\n return usage.used >= warningThreshold ? \"warning\" : \"normal\";\n }\n\n /** Bucket trusted expiry data independently from the usage-limit bucket. */\n private getThreadsExpiryBucket(): ThreadsExpiryBucket {\n const usage = this.inspectorMetadataProjection.usage;\n if (\n !usage ||\n !Object.prototype.hasOwnProperty.call(usage, \"expiringSoonCount\")\n ) {\n return \"unavailable\";\n }\n if (usage.expiringSoonCount === 0) return \"zero\";\n return typeof usage.expiringSoonCount === \"number\" &&\n usage.expiringSoonCount > 0\n ? \"positive\"\n : \"unavailable\";\n }\n\n /** Report only real rows visible in the active, settled Threads view. */\n private hasActiveVisibleThreads(): boolean {\n if (\n this.selectedMenu !== \"threads\" ||\n this.settingsOpen ||\n this.ephemeralThreadsSetupOpen ||\n !this.areThreadEndpointsAvailable()\n ) {\n return false;\n }\n const { displayThreads, threadsErrorMessage, threadsLoading } =\n this.getActiveThreadsState();\n return !threadsErrorMessage && !threadsLoading && displayThreads.length > 0;\n }\n\n /** Build the closed common property set shared by all Thread events. */\n private getThreadsTelemetryProps(): InspectorThreadTelemetryProps {\n const threadServiceStatus = this.getThreadServiceStatus();\n return {\n intelligence_status:\n threadServiceStatus === \"available\"\n ? \"intelligence_enabled\"\n : threadServiceStatus === \"unavailable\"\n ? \"intelligence_not_enabled\"\n : \"unknown\",\n thread_service_status: threadServiceStatus,\n license_status: this.core?.licenseStatus ?? undefined,\n runtime_mode: this.core?.runtimeMode ?? undefined,\n runtime_url_type: getRuntimeUrlType(this.core?.runtimeUrl),\n telemetry_disabled: false,\n has_threads: this.hasActiveVisibleThreads(),\n usage_bucket: this.getThreadsUsageBucket(),\n expiry_bucket: this.getThreadsExpiryBucket(),\n group_key: \"workbench\",\n leaf_key: \"threads\",\n };\n }\n\n /** Add the frozen CTA leaves and anonymous URL attribution when allowed. */\n private getThreadsCtaTelemetryProps(\n cta: \"signup\" | \"talk_to_engineer\",\n ctaSurface: \"threads_locked\" | \"threads_header\" | \"sidebar_footer\",\n ): InspectorThreadTelemetryProps {\n const distinctId = getTelemetryDistinctIdForUrl();\n return {\n ...this.getThreadsTelemetryProps(),\n cta,\n cta_surface: ctaSurface,\n posthog_distinct_id: distinctId ?? undefined,\n };\n }\n\n private getMemoriesTelemetryProps(): InspectorMemoryTelemetryProps {\n const distinctId = !this.core?.telemetryDisabled\n ? getTelemetryDistinctIdForUrl()\n : null;\n return {\n posthog_distinct_id: distinctId ?? undefined,\n memory_count: this._memories.length,\n available: this._memoriesAvailable,\n };\n }\n\n private getIntelligenceSignupUrl(): string {\n return this.appendRefParam(INTELLIGENCE_SIGNUP_URL, \"cpk-inspector\");\n }\n\n private getTalkToEngineerUrl(): string {\n return this.appendRefParam(TALK_TO_ENGINEER_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsTalkToEngineerUrl(): string {\n return this.appendRefParam(TALK_TO_ENGINEER_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsDocsUrl(): string {\n return this.appendRefParam(THREADS_DOCS_URL, \"cpk-inspector-threads\");\n }\n\n private getThreadsIntelligenceSignupUrl(): string {\n return this.appendRefParam(\n INTELLIGENCE_SIGNUP_URL,\n \"cpk-inspector-threads\",\n );\n }\n\n private getSelfHostedIntelligenceUrl(): string {\n return this.appendRefParam(\n SELF_HOSTED_INTELLIGENCE_URL,\n \"cpk-inspector-threads\",\n );\n }\n\n /** Selects the onboarding path for an enabled runtime with no saved Threads. */\n private getThreadsEmptyOnboardingAction(): Readonly<{\n href: string;\n label: \"Sign up for Intelligence\" | \"Explore self-hosted Intelligence\";\n }> {\n const planCode = this.inspectorMetadataProjection.plan?.code\n .trim()\n .toLowerCase();\n if (planCode === \"team_self_hosted\" || planCode === \"team-self-hosted\") {\n return {\n href: this.getSelfHostedIntelligenceUrl(),\n label: \"Explore self-hosted Intelligence\",\n };\n }\n return {\n href: this.getThreadsIntelligenceSignupUrl(),\n label: \"Sign up for Intelligence\",\n };\n }\n\n private subscribeToThreadStore(agentId: string, store: ɵThreadStore): void {\n if (!this.areThreadEndpointsAvailable()) return;\n if (this._threadStoreSubscriptions.has(agentId)) return;\n const capabilityGeneration = this.threadCapabilityGeneration;\n const threadsSub = store.select(ɵselectThreads).subscribe((threads) => {\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n this._threadsByAgent.set(agentId, threads as ɵThread[]);\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n if (\n this.selectedMenu === \"memories\" &&\n this.shouldPollLearningSetup() &&\n !this.learningLoading &&\n !this.learningRefreshing\n ) {\n void this.refreshLearningSnapshot({ preserve: true });\n }\n this.requestUpdate();\n });\n const statusSub = store\n .select(createThreadStoreStatusSelector())\n .subscribe(({ error, isLoading }) => {\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n if (error) {\n this._threadsErrorByAgent.set(agentId, error);\n } else if (!isLoading) {\n this._threadsErrorByAgent.delete(agentId);\n }\n this._threadsLoadingByAgent.set(agentId, isLoading);\n this.requestUpdate();\n });\n this._threadStoreSubscriptions.set(agentId, () => {\n threadsSub.unsubscribe();\n statusSub.unsubscribe();\n });\n // Populate immediately from current state\n if (\n capabilityGeneration !== this.threadCapabilityGeneration ||\n !this.areThreadEndpointsAvailable()\n ) {\n return;\n }\n const initialState = store.getState();\n this._threadsByAgent.set(agentId, ɵselectThreads(initialState));\n this._threadsLoadingByAgent.set(\n agentId,\n ɵselectThreadsIsLoading(initialState),\n );\n const initialError = ɵselectThreadsError(initialState);\n if (initialError) {\n this._threadsErrorByAgent.set(agentId, initialError);\n } else if (!ɵselectThreadsIsLoading(initialState)) {\n this._threadsErrorByAgent.delete(agentId);\n }\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n }\n\n private rebuildFlattenedThreads(): void {\n this._threads = flattenThreadsByAgent(this._threadsByAgent);\n this.scheduleInspectorUsageRefresh();\n }\n\n private scheduleInspectorUsageRefresh(): void {\n const signature = this._threads\n .map((thread) => thread.id)\n .sort()\n .join(\",\");\n if (signature === this.threadUsageSignature) {\n return;\n }\n this.threadUsageSignature = signature;\n if (this.threadUsageRefreshTimer !== null) {\n clearTimeout(this.threadUsageRefreshTimer);\n }\n this.threadUsageRefreshTimer = setTimeout(() => {\n this.threadUsageRefreshTimer = null;\n const core = this.core;\n if (core && typeof core.refreshInspectorMetadata === \"function\") {\n void core.refreshInspectorMetadata();\n }\n }, 300);\n }\n\n private clearInspectorUsageRefresh(): void {\n if (this.threadUsageRefreshTimer !== null) {\n clearTimeout(this.threadUsageRefreshTimer);\n this.threadUsageRefreshTimer = null;\n }\n this.threadUsageSignature = \"\";\n }\n\n private autoSelectLatestThread(): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const { displayThreads } = this.getActiveThreadsState();\n const previousSelectedThreadId = this.selectedThreadId;\n\n if (this.requestedThreadId !== null) {\n this.selectedThreadId = this.requestedThreadId;\n this.selectedRealThreadIsExplicit = true;\n if (\n displayThreads.some((thread) => thread.id === this.requestedThreadId)\n ) {\n this.requestedThreadId = null;\n }\n return;\n }\n\n if (\n this.selectedLocalExampleThreadId !== null &&\n previousSelectedThreadId === this.selectedLocalExampleThreadId &&\n displayThreads.length === 0\n ) {\n this.selectedRealThreadIsExplicit = false;\n return;\n }\n\n if (this.selectedLocalExampleThreadId !== null) {\n this.exampleTourActive = false;\n }\n this.selectedLocalExampleThreadId = null;\n const explicitSelectedThreadId = this.selectedRealThreadIsExplicit\n ? previousSelectedThreadId\n : null;\n const nextSelectedThreadId = selectVisibleRealThreadId({\n threads: displayThreads,\n selectedThreadId: explicitSelectedThreadId,\n });\n this.selectedThreadId = nextSelectedThreadId;\n this.selectedRealThreadIsExplicit =\n explicitSelectedThreadId !== null &&\n nextSelectedThreadId === explicitSelectedThreadId;\n }\n\n private teardownThreadStoreSubscriptions(): void {\n for (const unsub of this._threadStoreSubscriptions.values()) {\n unsub();\n }\n this._threadStoreSubscriptions.clear();\n this._threadsByAgent.clear();\n this._threadsErrorByAgent.clear();\n this._threadsLoadingByAgent.clear();\n this._threads = [];\n this.clearInspectorUsageRefresh();\n }\n\n private ensureOwnedThreadStore(agentId: string): void {\n if (!this.areThreadEndpointsAvailable()) return;\n if (this._ownedThreadStores.has(agentId)) return;\n // Don't overwrite a store already registered by useThreads() or another external caller\n if (this.core?.getThreadStore(agentId)) return;\n const core = this.core;\n if (!core?.runtimeUrl) return;\n\n const runtimeFetch =\n typeof core.ɵruntimeFetch === \"function\"\n ? core.ɵruntimeFetch\n : globalThis.fetch;\n const store = ɵcreateThreadStore({ fetch: runtimeFetch });\n store.start();\n store.setContext({\n runtimeUrl: core.runtimeUrl,\n headers: { ...core.headers },\n wsUrl: core.intelligence?.wsUrl,\n agentId,\n });\n this._ownedThreadStores.set(agentId, store);\n // Subscribe directly so threads render even before the registry callback\n // fires (some published-core code paths land on the subscriber after\n // registerThreadStore returns).\n this.subscribeToThreadStore(agentId, store);\n core.registerThreadStore(agentId, store);\n }\n\n private refreshOwnedThreadStore(agentId: string): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const store = this._ownedThreadStores.get(agentId);\n if (!store) return;\n\n const now = Date.now();\n const lastSentAt = this.threadRefreshLastSentAt.get(agentId) ?? 0;\n const waitMs = THREAD_LIST_DEBOUNCE_MS - (now - lastSentAt);\n if (waitMs <= 0) {\n this.sendOwnedThreadRefresh(agentId, store, now);\n return;\n }\n if (this.threadRefreshTrailingTimers.has(agentId)) return;\n this.threadRefreshTrailingTimers.set(\n agentId,\n setTimeout(() => {\n this.threadRefreshTrailingTimers.delete(agentId);\n const current = this._ownedThreadStores.get(agentId);\n if (!current) return;\n this.sendOwnedThreadRefresh(agentId, current, Date.now());\n }, waitMs),\n );\n }\n\n private sendOwnedThreadRefresh(\n agentId: string,\n store: ɵThreadStore,\n sentAt: number,\n ): void {\n this.threadRefreshLastSentAt.set(agentId, sentAt);\n // refresh() re-fetches without resetting threads to [] first, so the list\n // stays visible while new data loads and survives transient fetch failures.\n store.refresh();\n }\n\n private cancelThreadRefreshDebounce(): void {\n for (const timer of this.threadRefreshTrailingTimers.values()) {\n clearTimeout(timer);\n }\n this.threadRefreshTrailingTimers.clear();\n }\n\n // Keep inspector-owned thread stores in sync when the host updates headers\n // at runtime (e.g. a refreshed auth/CSRF token via core.setHeaders). Mirrors\n // useThreads(), which re-dispatches the context whenever core.headers change,\n // so the owned stores' /threads requests stay authorized.\n private updateOwnedThreadStoreHeaders(\n headers: Readonly<Record<string, string>>,\n ): void {\n if (!this.areThreadEndpointsAvailable()) return;\n const core = this.core;\n if (!core?.runtimeUrl) return;\n for (const [agentId, store] of this._ownedThreadStores) {\n store.setContext({\n runtimeUrl: core.runtimeUrl,\n headers: { ...headers },\n wsUrl: core.intelligence?.wsUrl,\n agentId,\n });\n }\n }\n\n private removeOwnedThreadStore(agentId: string): void {\n const store = this._ownedThreadStores.get(agentId);\n if (!store) return;\n this._ownedThreadStores.delete(agentId);\n store.stop();\n if (this.core?.getThreadStore(agentId) === store) {\n this.core.unregisterThreadStore(agentId);\n }\n }\n\n private teardownOwnedThreadStores(): void {\n const ownedThreadStores = Array.from(this._ownedThreadStores);\n this._ownedThreadStores.clear();\n for (const [agentId, store] of ownedThreadStores) {\n store.stop();\n if (this.core?.getThreadStore(agentId) === store) {\n this.core.unregisterThreadStore(agentId);\n }\n }\n }\n\n private coreSupportsInspectorMetadata(core: CopilotKitCore): boolean {\n try {\n return \"inspectorMetadata\" in core;\n } catch {\n return false;\n }\n }\n\n private readCoreInspectorMetadata(core: CopilotKitCore): unknown {\n if (!this.coreSupportsInspectorMetadata(core)) {\n return undefined;\n }\n\n try {\n return core.inspectorMetadata;\n } catch {\n return undefined;\n }\n }\n\n private updateInspectorMetadataProjection(value: unknown): void {\n this.inspectorMetadataValue = value;\n let runtimeLicense: RuntimeLicenseStatus | undefined;\n try {\n runtimeLicense = this._core?.licenseStatus;\n } catch {\n runtimeLicense = undefined;\n }\n this.inspectorMetadataProjection = projectInspectorMetadata(\n value,\n runtimeLicense,\n );\n }\n\n private attachToCore(core: CopilotKitCore): void {\n this.runtimeStatus = core.runtimeConnectionStatus;\n this.coreProperties = core.properties;\n this.lastCoreError = null;\n this.clearAllEventErrors();\n const supportsInspectorMetadata = this.coreSupportsInspectorMetadata(core);\n this.updateInspectorMetadataProjection(\n this.readCoreInspectorMetadata(core),\n );\n this.learningSupported = core.inspectorLearning;\n this.learningProjectIdentity = JSON.stringify(\n this.inspectorMetadataProjection.identity ?? null,\n );\n\n this.coreSubscriber = {\n onRuntimeConnectionStatusChanged: ({ status }) => {\n this.runtimeStatus = status;\n this.updateInspectorMetadataProjection(this.inspectorMetadataValue);\n const threadCapabilityWasEnabled =\n this.threadCapabilityEnabled === true;\n this.synchronizeThreadCapability();\n if (status === \"connected\") {\n this.learningSupported = core.inspectorLearning;\n if (!core.telemetryDisabled) {\n ensureTelemetryDistinctId();\n maybeShowDisclosure();\n }\n this.flushPendingWhatsNewTelemetry();\n if (this.isLearningStatusVisible()) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\n if (\n threadCapabilityWasEnabled &&\n this.areThreadEndpointsAvailable()\n ) {\n for (const agentId of this._ownedThreadStores.keys()) {\n this.refreshOwnedThreadStore(agentId);\n }\n }\n } else {\n // Clear stale thread data immediately when the server goes away\n this._threadsByAgent.clear();\n this._threads = [];\n this.clearInspectorUsageRefresh();\n this.clearLearningSnapshot();\n }\n this.requestUpdate();\n },\n onPropertiesChanged: ({ properties }) => {\n this.coreProperties = properties;\n this.requestUpdate();\n },\n onHeadersChanged: ({ headers }) => {\n this.updateOwnedThreadStoreHeaders(headers);\n this.requestUpdate();\n },\n ...(supportsInspectorMetadata\n ? {\n onInspectorMetadataChanged: ({ inspectorMetadata }) => {\n if (this._core !== core) {\n return;\n }\n this.updateInspectorMetadataProjection(inspectorMetadata);\n const identity = JSON.stringify(\n this.inspectorMetadataProjection.identity ?? null,\n );\n if (identity !== this.learningProjectIdentity) {\n this.learningProjectIdentity = identity;\n this.clearLearningSnapshot();\n if (this.isLearningStatusVisible()) {\n void this.refreshLearningSnapshot({ preserve: false });\n }\n }\n this.requestUpdate();\n },\n }\n : {}),\n onError: ({ code, error, context }) => {\n this.lastCoreError = { code, message: error.message };\n this.armEventErrorFromCode(code, error.message, context);\n this.requestUpdate();\n },\n onAgentsChanged: ({ agents }) => {\n this.processAgentsChanged(agents);\n },\n onAgentRunStarted: ({ agent }) => {\n // Per-thread clones (from useAgent) are not in the agent registry, so\n // onAgentsChanged never fires for them. Subscribe to the running\n // instance here so its AG-UI events reach the event timeline.\n if (agent?.agentId) {\n this.subscribeToAgent(agent);\n }\n },\n onContextChanged: ({ context }) => {\n this.contextStore = this.normalizeContextStore(context);\n this.requestUpdate();\n },\n onSuggestionsChanged: () => this.requestUpdate(),\n onSuggestionsStartedLoading: () => this.requestUpdate(),\n onSuggestionsFinishedLoading: () => this.requestUpdate(),\n onSuggestionsConfigChanged: () => this.requestUpdate(),\n onThreadStoreRegistered: ({ agentId, store }) => {\n if (!this.areThreadEndpointsAvailable()) return;\n this.subscribeToThreadStore(agentId, store);\n this.requestUpdate();\n },\n onThreadStoreUnregistered: ({ agentId, prevStore }) => {\n const unsub = this._threadStoreSubscriptions.get(agentId);\n if (unsub) {\n unsub();\n this._threadStoreSubscriptions.delete(agentId);\n }\n if (this._ownedThreadStores.get(agentId) === prevStore) {\n this._ownedThreadStores.delete(agentId);\n prevStore.stop();\n }\n this._threadsByAgent.delete(agentId);\n this._threadsErrorByAgent.delete(agentId);\n this._threadsLoadingByAgent.delete(agentId);\n this.rebuildFlattenedThreads();\n this.autoSelectLatestThread();\n this.requestUpdate();\n },\n } satisfies CopilotKitCoreSubscriber;\n\n this.coreUnsubscribe = core.subscribe(this.coreSubscriber).unsubscribe;\n this.processAgentsChanged(core.agents);\n\n if (core.runtimeConnectionStatus === \"connected\") {\n if (!core.telemetryDisabled) {\n ensureTelemetryDistinctId();\n maybeShowDisclosure();\n }\n this.flushPendingWhatsNewTelemetry();\n }\n\n // Subscribe to any already-registered thread stores. `getThreadStores` was\n // added in the same release as this inspector; guard so consumers still on\n // an older @copilotkit/core don't throw when assigning `inspector.core`.\n const threadStores =\n typeof core.getThreadStores === \"function\" ? core.getThreadStores() : {};\n if (this.areThreadEndpointsAvailable()) {\n for (const [agentId, store] of Object.entries(threadStores)) {\n this.subscribeToThreadStore(agentId, store);\n }\n }\n\n // Initialize context from core\n if (core.context) {\n this.contextStore = this.normalizeContextStore(core.context);\n }\n\n // NOTE: the memory store is intentionally NOT touched here. Calling\n // `core.getMemoryStore()` lazily creates + `.start()`s the store and opens\n // a realtime connection, so merely attaching the inspector would spin up a\n // memory store + realtime even in apps that never use memory. Instead, the\n // store is created + subscribed on first Memories-tab activation via\n // `ensureMemorySubscription` (user-initiated, acceptable). Attaching the\n // inspector creates nothing.\n //\n // Exception: if the Memories tab is ALREADY the active tab when core is\n // wired (e.g. core attaches after `firstUpdated` restored a persisted\n // `selectedMenu: \"memories\"`), subscribe now so the live store + realtime\n // status paint instead of the stuck defaults. This preserves INSP-1 (no\n // unconditional subscribe on attach) because it is gated on the active tab,\n // and is safe to call when already subscribed — `ensureMemorySubscription`\n // early-returns on `_memorySubscribed`.\n if (this.selectedMenu === \"memories\") {\n this.ensureMemorySubscription();\n }\n }\n\n /**\n * Lazily subscribes to the singleton memory store the first time the user\n * activates the Memories tab. This is deferred out of `attachToCore` because\n * `core.getMemoryStore()` is what creates + starts the store and opens\n * realtime — doing it on attach would start memory for apps that never use\n * it. Idempotent: repeated tab activations are guarded by\n * `_memorySubscribed`. On an older @copilotkit/core without `getMemoryStore`,\n * records the unsupported state so the teaser can guide an SDK upgrade.\n */\n private ensureMemorySubscription(): void {\n if (this._memorySubscribed) {\n return;\n }\n const core = this._core;\n if (!core) {\n return;\n }\n\n // Guard like getThreadStores: older @copilotkit/core has no getMemoryStore.\n // When absent, flag the unsupported state so the teaser shows upgrade copy\n // instead of throwing a TypeError that would break the entire inspector.\n if (typeof core.getMemoryStore !== \"function\") {\n this._memoryStoreUnsupported = true;\n this._memoriesAvailable = false;\n this.requestUpdate();\n return;\n }\n\n this._memorySubscribed = true;\n this._memoryStoreUnsupported = false;\n\n // First touch of getMemoryStore() — creates + starts the store, opens realtime.\n const memoryStore = core.getMemoryStore();\n const ms = memoryStore.getState();\n this._memories = ɵselectMemories(ms);\n this._memoriesLoading = ɵselectMemoriesIsLoading(ms);\n this._memoriesError = ɵselectMemoriesError(ms);\n this._memoriesAvailable = ɵselectMemoriesAvailable(ms);\n this._memoriesRealtimeStatus = ɵselectMemoriesRealtimeStatus(ms);\n const memSubs = [\n memoryStore.select(ɵselectMemories).subscribe((v) => {\n this._memories = v;\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesIsLoading).subscribe((v) => {\n this._memoriesLoading = v;\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesError).subscribe((v) => {\n this._memoriesError = v;\n if (v) {\n this.armEventError(\"memory\", v.message);\n }\n this.requestUpdate();\n }),\n memoryStore.select(ɵselectMemoriesAvailable).subscribe((v) => {\n this._memoriesAvailable = v;\n this.requestUpdate();\n }),\n // Group E — realtime connection health.\n memoryStore.select(ɵselectMemoriesRealtimeStatus).subscribe((v) => {\n this._memoriesRealtimeStatus = v;\n this.requestUpdate();\n }),\n ];\n this._memoryUnsub = () => memSubs.forEach((s) => s.unsubscribe());\n this.requestUpdate();\n }\n\n /**\n * Runs a semantic recall via the memory store (`core.getMemoryStore().recall`,\n * from B2) and stores ranked results. Guarded by a monotonic sequence token\n * so a stale request cannot overwrite a newer result / Clear / detach. Only\n * reachable from the Intelligence-gated memory view, so it inherits the gate.\n */\n private runRecall(query: string): void {\n const trimmed = query.trim();\n if (trimmed.length === 0) return;\n const store = this._core?.getMemoryStore?.();\n if (!store || typeof store.recall !== \"function\") {\n this._recallResults = [];\n this._recallError = \"Recall is not supported by this SDK version.\";\n this._recallLoading = false;\n this.requestUpdate();\n return;\n }\n\n const seq = ++this._recallSeq;\n this._recallLoading = true;\n this._recallError = null;\n this.requestUpdate();\n\n store\n .recall(trimmed)\n .then((results) => {\n if (seq !== this._recallSeq) return;\n this._recallResults = results;\n this._recallError = null;\n this._recallLoading = false;\n this.requestUpdate();\n })\n .catch((error: unknown) => {\n if (seq !== this._recallSeq) return;\n this._recallResults = [];\n this._recallError =\n error instanceof Error ? error.message : \"unknown error\";\n this._recallLoading = false;\n this.requestUpdate();\n });\n }\n\n /** Clears recall results/section and cancels any in-flight recall. */\n private clearRecall(): void {\n this._recallSeq += 1;\n this._recallResults = null;\n this._recallError = null;\n this._recallLoading = false;\n this._recallQuery = \"\";\n this.requestUpdate();\n }\n\n private getLearningAgentId(): string | null {\n if (\n this.selectedContext !== \"all-agents\" &&\n this.core?.agents[this.selectedContext]\n ) {\n return this.selectedContext;\n }\n // `all-agents` is intentionally unscoped. Choosing the first object key\n // silently binds Learning to whichever agent happened to be enumerated\n // first and can select the wrong container. Omit agentId so Intelligence\n // applies its deterministic sole-container / selection-required rules.\n return null;\n }\n\n /** Whether a visible surface needs the current Learning connection status. */\n private isLearningStatusVisible(): boolean {\n return (\n this.launcherHudOpen ||\n (this.isOpen &&\n (this.selectedMenu === \"home\" || this.selectedMenu === \"memories\"))\n );\n }\n\n private isLearningSetupActive(): boolean {\n const runtimeUrl = this.core?.runtimeUrl;\n if (!runtimeUrl) return false;\n return learningSetupMarkerMatches(\n this.learningSetupMarker,\n runtimeUrl,\n this.getLearningAgentId(),\n );\n }\n\n private trackLearningViewState(): void {\n if (\n !this.isOpen ||\n this.selectedMenu !== \"memories\" ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n const state = deriveLearningViewState({\n supported: this.learningSupported,\n loading: this.learningLoading,\n error: this.learningError,\n snapshot: this.learningSnapshot,\n setupActive: this.isLearningSetupActive(),\n });\n if (state === this.learningViewedState) return;\n this.learningViewedState = state;\n trackLearningPaneViewed({ state });\n }\n\n private cancelLearningPoll(): void {\n if (this.learningPollTimer !== null) {\n clearTimeout(this.learningPollTimer);\n this.learningPollTimer = null;\n }\n }\n\n private shouldPollLearningSetup(): boolean {\n if (\n !this.isOpen ||\n this.selectedMenu !== \"memories\" ||\n document.visibilityState !== \"visible\" ||\n !this.learningSupported\n ) {\n return false;\n }\n const snapshot = this.learningSnapshot;\n if (!snapshot) return this.isLearningSetupActive();\n if (snapshot.configuration.state === \"not_configured\") {\n return this.isLearningSetupActive();\n }\n return (\n snapshot.configuration.state === \"configured\" &&\n !snapshot.run.hasEverSucceeded &&\n !snapshot.run.hasActiveRun &&\n snapshot.pendingThreadCount === 0 &&\n snapshot.skillsPage.total === 0 &&\n snapshot.insightsPage.total === 0\n );\n }\n\n private scheduleLearningPoll(): void {\n this.cancelLearningPoll();\n if (!this.shouldPollLearningSetup()) return;\n const delay =\n this.learningPollFailureCount === 0\n ? 5_000\n : this.learningPollFailureCount === 1\n ? 10_000\n : 30_000;\n this.learningPollTimer = setTimeout(() => {\n this.learningPollTimer = null;\n void this.refreshLearningSnapshot({ preserve: true });\n }, delay);\n }\n\n private clearLearningSnapshot(): void {\n this.cancelLearningRequest();\n this.learningSnapshot = null;\n this.learningSnapshotScope = null;\n this.learningError = null;\n this.learningLoading = false;\n this.learningRefreshing = false;\n this.cancelLearningPoll();\n }\n\n private cancelLearningRequest(): void {\n this.learningRequestGeneration += 1;\n this.learningAbortController?.abort();\n this.learningAbortController = null;\n }\n\n private refreshLearningSnapshot = async (\n options: {\n preserve?: boolean;\n skillsPage?: number;\n insightsPage?: number;\n } = {},\n ): Promise<void> => {\n const core = this.core;\n const runtimeUrl = core?.runtimeUrl;\n this.learningSupported = Boolean(core?.inspectorLearning);\n if (!core || !runtimeUrl || !this.learningSupported) {\n this.clearLearningSnapshot();\n this.requestUpdate();\n this.trackLearningViewState();\n return;\n }\n this.cancelLearningPoll();\n const startedAt = performance.now();\n let loadOutcome: \"success\" | \"unsupported\" | \"failure\" = \"failure\";\n let loadedSkills = 0;\n let loadedInsights = 0;\n let loadedPendingThreads = 0;\n let resetSkillsPage = false;\n let resetInsightsPage = false;\n const previousSnapshot = this.learningSnapshot;\n const agentId = this.getLearningAgentId();\n const requestContext = `${runtimeUrl.replace(/\\/+$/u, \"\")}|${agentId ?? \"\"}`;\n if (\n this.learningSnapshotScope &&\n !this.learningSnapshotScope.startsWith(`${requestContext}|`)\n ) {\n this.clearLearningSnapshot();\n }\n const generation = ++this.learningRequestGeneration;\n this.learningAbortController?.abort();\n const controller = new AbortController();\n this.learningAbortController = controller;\n const preserve =\n options.preserve === true && this.learningSnapshot !== null;\n this.learningLoading = !preserve;\n this.learningRefreshing = preserve;\n this.learningError = null;\n this.requestUpdate();\n try {\n const snapshot = await fetchInspectorLearning({\n runtimeUrl,\n runtimeTransport: core.runtimeTransport,\n request: {\n ...(agentId ? { agentId } : {}),\n skillsPage:\n options.skillsPage ?? this.learningSnapshot?.skillsPage.page ?? 1,\n insightsPage:\n options.insightsPage ??\n this.learningSnapshot?.insightsPage.page ??\n 1,\n },\n fetch: core.ɵruntimeFetch,\n headers: core.headers,\n credentials: core.credentials,\n signal: controller.signal,\n });\n if (generation !== this.learningRequestGeneration) return;\n if (\n (snapshot.pendingThreadCount > 0 && !snapshot.links.runs) ||\n (snapshot.pendingCandidateCount > 0 && !snapshot.links.candidates)\n ) {\n throw new Error(\n \"Learning snapshot is missing a required web-app link.\",\n );\n }\n const containerId =\n snapshot.configuration.state === \"configured\"\n ? snapshot.configuration.container.id\n : \"\";\n const previousContainerId =\n previousSnapshot?.configuration.state === \"configured\"\n ? previousSnapshot.configuration.container.id\n : \"\";\n const scopeChanged =\n previousSnapshot !== null &&\n (previousSnapshot.projectKey !== snapshot.projectKey ||\n previousContainerId !== containerId);\n const isBackgroundRefresh =\n options.skillsPage === undefined && options.insightsPage === undefined;\n resetSkillsPage = Boolean(\n isBackgroundRefresh &&\n previousSnapshot &&\n previousSnapshot.skillsPage.page > 1 &&\n (scopeChanged ||\n JSON.stringify([\n previousSnapshot.skillsPage.total,\n previousSnapshot.skillsPage.items.map((skill) => [\n skill.id,\n skill.revision,\n ]),\n ]) !==\n JSON.stringify([\n snapshot.skillsPage.total,\n snapshot.skillsPage.items.map((skill) => [\n skill.id,\n skill.revision,\n ]),\n ])),\n );\n resetInsightsPage = Boolean(\n isBackgroundRefresh &&\n previousSnapshot &&\n previousSnapshot.insightsPage.page > 1 &&\n (scopeChanged ||\n JSON.stringify([\n previousSnapshot.insightsPage.total,\n previousSnapshot.insightsPage.items.map((insight) => insight.id),\n ]) !==\n JSON.stringify([\n snapshot.insightsPage.total,\n snapshot.insightsPage.items.map((insight) => insight.id),\n ])),\n );\n this.learningSnapshot = snapshot;\n loadOutcome = \"success\";\n loadedSkills = snapshot.skillsPage.total;\n loadedInsights = snapshot.insightsPage.total;\n loadedPendingThreads = snapshot.pendingThreadCount;\n this.learningSnapshotScope = `${requestContext}|${snapshot.projectKey}|${containerId}`;\n this.learningError = null;\n this.learningPollFailureCount = 0;\n if (snapshot.configuration.state === \"configured\") {\n clearLearningSetupMarker();\n this.learningSetupMarker = null;\n }\n } catch (error) {\n if (\n generation !== this.learningRequestGeneration ||\n controller.signal.aborted\n )\n return;\n if (error instanceof InspectorLearningUnsupportedError) {\n loadOutcome = \"unsupported\";\n this.learningSupported = false;\n this.learningSnapshot = null;\n } else {\n this.learningError =\n error instanceof Error\n ? error.message\n : \"Learning data is unavailable.\";\n this.learningPollFailureCount += 1;\n }\n } finally {\n if (generation === this.learningRequestGeneration) {\n this.learningLoading = false;\n this.learningRefreshing = false;\n this.learningAbortController = null;\n if (!core.telemetryDisabled) {\n trackLearningSnapshotLoaded({\n outcome: loadOutcome,\n duration_bucket: learningDurationBucket(\n performance.now() - startedAt,\n ),\n skills_bucket: learningCountBucket(loadedSkills),\n insights_bucket: learningCountBucket(loadedInsights),\n pending_threads_bucket: learningCountBucket(loadedPendingThreads),\n });\n }\n this.scheduleLearningPoll();\n this.requestUpdate();\n this.trackLearningViewState();\n if (resetSkillsPage || resetInsightsPage) {\n void this.refreshLearningSnapshot({\n preserve: true,\n ...(resetSkillsPage ? { skillsPage: 1 } : {}),\n ...(resetInsightsPage ? { insightsPage: 1 } : {}),\n });\n }\n }\n }\n };\n\n private copyFeaturePromptToClipboard = async (\n service: HomeFeaturePromptTarget,\n event?: Event,\n onboardingRunId = createOnboardingRunId(),\n ): Promise<boolean> => {\n const clipboard = this.getClipboard(event);\n if (!clipboard?.writeText) return false;\n try {\n await clipboard.writeText(\n createFeatureOnboardingPrompt(service.id, onboardingRunId),\n );\n return true;\n } catch {\n return false;\n }\n };\n\n private handleLearningSetupCopy = async (\n event?: Event,\n recopy = false,\n ): Promise<void> => {\n // The Learning tile, not the Threads one. This pane borrowed the Threads\n // target, so its button copied a Threads prompt and announced itself as\n // \"Threads setup prompt copied\" under a Learning heading (OSS-1151).\n //\n // Learning does not need the Threads feature first. A runtime mounted\n // `mode: \"single-route\"` serves no thread route at all and still binds\n // Containers, because the binding happens server-side while a run starts;\n // and `learningOn` reads the `memory` tile independently of `threadsOn`.\n // `add-learning` inspects its own prerequisites and refuses through\n // `feature/stop` when one is missing, which is why the route decides that\n // rather than this pane.\n const service = this.getHomeFeaturePromptTarget(\"memory\");\n if (!service || !this.core?.runtimeUrl) return;\n const request = ++this.learningSetupCopyRequest;\n const copied = await this.copyFeaturePromptToClipboard(\n service,\n event,\n this.getOnboardingRunId(),\n );\n if (request !== this.learningSetupCopyRequest) return;\n if (!this.core.telemetryDisabled) {\n trackLearningSetupPromptClicked({\n outcome: copied ? \"success\" : \"failure\",\n });\n }\n if (!copied) {\n if (recopy) {\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"error\";\n } else {\n this.learningPromptCopyState = \"error\";\n }\n this.requestUpdate();\n return;\n }\n if (recopy) {\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"copied\";\n this.learningPromptRecopyTimer = setTimeout(() => {\n this.learningPromptRecopyTimer = null;\n this.learningPromptRecopyState = \"idle\";\n this.requestUpdate();\n }, LEARNING_RECOPY_CONFIRMATION_MS);\n } else {\n this.learningPromptCopyState = \"copied\";\n }\n this.learningSetupMarker = writeLearningSetupMarker({\n runtimeUrl: this.core.runtimeUrl,\n agentId: this.getLearningAgentId(),\n });\n this.selectedMenu = \"memories\";\n this.persistState();\n this.requestUpdate();\n void this.refreshLearningSnapshot({ preserve: false });\n };\n\n private cancelLearningPromptRecopyReset(): void {\n if (this.learningPromptRecopyTimer !== null) {\n clearTimeout(this.learningPromptRecopyTimer);\n this.learningPromptRecopyTimer = null;\n }\n }\n\n private handleLearningGoBack = (): void => {\n this.learningSetupCopyRequest += 1;\n this.cancelLearningPromptRecopyReset();\n clearLearningSetupMarker();\n this.learningSetupMarker = null;\n this.learningPromptCopyState = \"idle\";\n this.learningPromptRecopyState = \"idle\";\n this.cancelLearningPoll();\n this.requestUpdate();\n this.trackLearningViewState();\n };\n\n private handleLearningPage = (\n event: CustomEvent<{\n section: \"skills\" | \"insights\";\n page: number;\n }>,\n ): void => {\n const { section, page } = event.detail;\n const currentPage =\n section === \"skills\"\n ? (this.learningSnapshot?.skillsPage.page ?? 1)\n : (this.learningSnapshot?.insightsPage.page ?? 1);\n if (!this.core?.telemetryDisabled) {\n trackLearningPageChanged({\n section,\n direction: page < currentPage ? \"previous\" : \"next\",\n });\n }\n void this.refreshLearningSnapshot({\n preserve: true,\n ...(section === \"skills\" ? { skillsPage: page } : { insightsPage: page }),\n });\n };\n\n private handleLearningEvidence = (\n event: CustomEvent<{\n threadId: string;\n messageId?: string;\n }>,\n ): void => {\n this.focusThread({\n threadId: event.detail.threadId,\n ...(event.detail.messageId ? { messageId: event.detail.messageId } : {}),\n });\n };\n\n private detachFromCore(): void {\n this.threadCapabilityGeneration += 1;\n this.threadCapabilityEnabled = null;\n if (this.selectedThreadId !== this.selectedLocalExampleThreadId) {\n this.selectedThreadId = null;\n this.selectedLocalExampleThreadId = null;\n }\n this.selectedRealThreadIsExplicit = false;\n if (this.coreUnsubscribe) {\n this.coreUnsubscribe();\n this.coreUnsubscribe = null;\n }\n this._memoryUnsub?.();\n this._memoryUnsub = null;\n this._memories = [];\n this._memoriesLoading = false;\n this._memoriesError = null;\n this._memoriesAvailable = true;\n this._memoriesRealtimeStatus = \"connecting\";\n // Reset the lazy-subscription guards so a later attach + Memories-tab\n // activation re-subscribes (and re-evaluates SDK support) cleanly.\n this._memorySubscribed = false;\n this._memoryStoreUnsupported = false;\n this.cancelLearningPromptRecopyReset();\n this.learningPromptRecopyState = \"idle\";\n // Reset recall state and bump the sequence token so any in-flight recall\n // resolving after detach is ignored.\n this._recallSeq += 1;\n this._recallResults = null;\n this._recallLoading = false;\n this._recallError = null;\n this._recallQuery = \"\";\n this.clearLearningSnapshot();\n this.learningSupported = false;\n this.coreSubscriber = null;\n this.runtimeStatus = null;\n this.cancelThreadRefreshDebounce();\n this.inspectorMetadataValue = undefined;\n this.inspectorMetadataProjection = projectInspectorMetadata(\n undefined,\n undefined,\n );\n this.metadataTelemetryFingerprints.clear();\n this.lastCoreError = null;\n this.clearAllEventErrors();\n this.coreProperties = {};\n this.cachedTools = [];\n this.toolSignature = \"\";\n this.teardownAgentSubscriptions();\n this.teardownPlaygroundAgent();\n this.teardownThreadStoreSubscriptions();\n this.teardownOwnedThreadStores();\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 previousLearningAgentId = this.getLearningAgentId();\n this.synchronizeThreadCapability();\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 this.ensureOwnedThreadStore(agent.agentId);\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 // Do NOT remove owned thread stores here — they are independent of\n // whether the agent appears in core.agents (published cores discover\n // agents asynchronously so agents may be empty on first fire). Stores\n // are torn down in teardownOwnedThreadStores() when the core detaches.\n }\n }\n\n this.updateContextOptions(seenAgentIds);\n const learningAgentId = this.getLearningAgentId();\n if (\n learningAgentId &&\n this.core?.runtimeUrl &&\n this.learningSetupMarker?.agentId === null &&\n learningSetupMarkerMatches(\n this.learningSetupMarker,\n this.core.runtimeUrl,\n null,\n )\n ) {\n this.learningSetupMarker = writeLearningSetupMarker({\n runtimeUrl: this.core.runtimeUrl,\n agentId: learningAgentId,\n });\n }\n if (\n previousLearningAgentId !== learningAgentId &&\n this.isLearningStatusVisible()\n ) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\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: (params) => {\n this.recordAgentEvent(agentId, \"RUN_FINISHED\", {\n event: params.event,\n result: \"result\" in params ? params.result : undefined,\n });\n if (this.areThreadEndpointsAvailable()) {\n this.refreshOwnedThreadStore(agentId);\n }\n },\n onRunErrorEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"RUN_ERROR\", event);\n },\n onStepStartedEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STEP_STARTED\", event);\n },\n onStepFinishedEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"STEP_FINISHED\", 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 onStateChanged: () => {\n this.syncAgentState(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 onActivitySnapshotEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"ACTIVITY_SNAPSHOT\", event);\n this.syncAgentMessages(agent);\n },\n onActivityDeltaEvent: ({ event }) => {\n this.recordAgentEvent(agentId, \"ACTIVITY_DELTA\", event);\n this.syncAgentMessages(agent);\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 mapMessagesToConversation(\n messages: InspectorMessage[] | null,\n ): { id: string; type: string; content: string; createdAt: string }[] | null {\n if (!messages) return null;\n return messages\n .filter(\n (m) =>\n m.role === \"user\" || m.role === \"assistant\" || m.role === \"activity\",\n )\n .map((m, i) => ({\n id: m.id ?? `msg-${i}`,\n type:\n m.role === \"user\"\n ? \"user\"\n : m.role === \"activity\"\n ? \"generative-ui\"\n : \"assistant\",\n // For activity messages, store the activityType as a label so the\n // renderer has something meaningful to display.\n // TODO: render activity payload once available.\n content:\n m.role === \"activity\" ? (m.activityType ?? \"unknown\") : m.contentText,\n createdAt: \"\",\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 try {\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 // Bump the live-message version for whichever thread this agent is\n // currently running on. cpk-thread-details watches this for the\n // selected thread and re-fetches `/threads/:id/messages` when it ticks,\n // so the conversation view stays in sync with the streaming agent\n // without the parent re-implementing AG-UI → ConversationItem mapping.\n const runThreadId = this.readAgentThreadId(agent);\n if (runThreadId) {\n this.liveMessageVersion.set(\n runThreadId,\n (this.liveMessageVersion.get(runThreadId) ?? 0) + 1,\n );\n }\n\n this.requestUpdate();\n } catch (error) {\n console.error(\n `[CopilotKit Inspector] Failed to sync messages for agent \"${agent.agentId}\":`,\n error,\n );\n }\n }\n\n private syncAgentState(agent: AbstractAgent): void {\n if (!agent?.agentId) {\n return;\n }\n\n try {\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 } catch (error) {\n console.error(\n `[CopilotKit Inspector] Failed to sync state for agent \"${agent.agentId}\":`,\n error,\n );\n }\n }\n\n private updateContextOptions(agentIds: Set<string>): void {\n let selectedContextChanged = false;\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 // Only restore a specific-agent selection when there is exactly one\n // agent registered. With multiple agents, fall back to \"all-agents\" so\n // events from any agent are visible regardless of what was persisted.\n const shouldRestore =\n isPendingAvailable &&\n (pendingContext === \"all-agents\" || agentIds.size === 1);\n if (shouldRestore) {\n if (this.selectedContext !== pendingContext) {\n this.selectedContext = pendingContext;\n selectedContextChanged = true;\n this.expandedRows.clear();\n }\n this.pendingSelectedContext = null;\n } else if (agentIds.size > 0) {\n // Persisted selection is unavailable or inappropriate for multiple\n // agents — reset to \"all-agents\" so nothing is silently filtered.\n if (this.selectedContext !== \"all-agents\") {\n this.selectedContext = \"all-agents\";\n selectedContextChanged = true;\n this.expandedRows.clear();\n }\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 // When there is exactly one agent, auto-select it so the view is\n // immediately focused. When multiple agents are registered (e.g. \"default\"\n // + \"openai\"), keep \"all-agents\" so events from any agent are visible.\n let nextSelected: string = \"all-agents\";\n\n if (agentIds.size === 1) {\n nextSelected = Array.from(agentIds)[0]!;\n }\n\n if (this.selectedContext !== nextSelected) {\n this.selectedContext = nextSelected;\n selectedContextChanged = true;\n this.expandedRows.clear();\n this.persistState();\n }\n }\n\n if (selectedContextChanged) {\n this.autoSelectLatestThread();\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 focusThread(options: InspectorOpenOptions): void {\n if (!options.threadId) return;\n this.pendingPersistedMenu = null;\n this.selectedMenu = \"threads\";\n this.settingsOpen = false;\n this.lastSelectedMenuByGroup.workbench = \"threads\";\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n this.selectedContext =\n options.agentId &&\n this.contextOptions.some((option) => option.key === options.agentId)\n ? options.agentId\n : \"all-agents\";\n this.requestedThreadId = options.threadId;\n this.selectedThreadId = options.threadId;\n this.selectedRealThreadIsExplicit = true;\n this.focusedThreadMessageId = options.messageId ?? null;\n this.threadFocusRequestId += 1;\n\n const { displayThreads } = this.getActiveThreadsState();\n if (displayThreads.some((thread) => thread.id === options.threadId)) {\n this.requestedThreadId = null;\n }\n\n this.persistState();\n this.requestUpdate();\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 readAgentThreadId(agent: AbstractAgent): string | undefined {\n if (!(\"threadId\" in agent)) return undefined;\n const threadId = agent.threadId;\n return typeof threadId === \"string\" ? threadId : undefined;\n }\n\n private getLiveAgentMessagesForThread(thread: ɵThread): InspectorMessage[] {\n const messages =\n this.agentMessages.get(thread.agentId) ?? EMPTY_INSPECTOR_MESSAGES;\n const core = this._core;\n if (!core || typeof core.getAgent !== \"function\") return messages;\n const agent = core.getAgent(thread.agentId);\n if (!agent) return EMPTY_INSPECTOR_MESSAGES;\n if (this.readAgentThreadId(agent) !== thread.id) {\n return EMPTY_INSPECTOR_MESSAGES;\n }\n return messages;\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 const toolError = this.eventErrorDetails.tool;\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 const isFailedCall =\n toolError?.toolCallId !== undefined &&\n toolError.toolCallId === callId;\n return html`\n <div\n class=${\n isFailedCall\n ? \"rounded-md border border-rose-300 bg-rose-50 p-3 text-xs text-gray-900\"\n : \"rounded-md border border-gray-200 bg-gray-50 p-3 text-xs text-gray-700\"\n }\n data-cpk-failed-tool-call=${isFailedCall ? callId : undefined}\n >\n <div\n class=\"flex flex-wrap items-center justify-between gap-1 font-medium text-gray-900\"\n >\n <span>${functionName}${isFailedCall ? \" failed\" : \"\"}</span>\n <span class=\"text-[10px] text-gray-600\">ID: ${callId}</span>\n </div>\n ${\n isFailedCall && toolError?.message\n ? html`<p\n class=\"mt-2 break-words leading-relaxed text-gray-800\"\n >\n ${toolError.message}\n </p>`\n : nothing\n }\n ${\n argsString\n ? html`<div class=\"mt-2\">\n ${renderHighlightedJsonBlock(\n coerceJsonValue(call.function?.arguments),\n )}\n </div>`\n : nothing\n }\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-semibold inline-flex items-center rounded-sm px-1.5 py-0.5 border\";\n\n if (type === \"RUN_ERROR\") {\n return `${base} bg-rose-50 text-rose-800 border-rose-200`;\n }\n\n if (type.startsWith(\"TEXT_MESSAGE\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n if (type.startsWith(\"TOOL_CALL\")) {\n return `${base} bg-emerald-50 text-gray-900 border-emerald-200`;\n }\n\n if (type.startsWith(\"RUN_\") || type.startsWith(\"STEP_\")) {\n return `${base} bg-gray-100 text-gray-900 border-gray-200`;\n }\n\n if (type.startsWith(\"REASONING\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n if (type.startsWith(\"STATE\") || type.startsWith(\"MESSAGES\")) {\n return `${base} bg-violet-50 text-gray-900 border-violet-200`;\n }\n\n return `${base} bg-gray-100 text-gray-900 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 /** Prefer the window that owns the UI: the popup while popped out. */\n private getClipboard(event?: Event): Clipboard | undefined {\n if (this.isPoppedOut) {\n const popped = this.popOut?.win.navigator.clipboard;\n if (popped) {\n return popped;\n }\n }\n const view = event && \"view\" in event ? (event as UIEvent).view : null;\n const viewClipboard = view?.navigator.clipboard;\n if (viewClipboard) {\n return viewClipboard;\n }\n // Clipboard is required on Navigator in lib.dom, but missing in some runtimes.\n if (typeof navigator !== \"undefined\" && \"clipboard\" in navigator) {\n return navigator.clipboard;\n }\n return undefined;\n }\n\n private async copyToClipboard(\n text: string,\n eventId: string,\n event?: Event,\n ): Promise<void> {\n const clipboard = this.getClipboard(event);\n if (!clipboard) {\n console.error(\n \"Failed to copy to clipboard:\",\n \"Clipboard API is not available\",\n );\n return;\n }\n try {\n await 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 --cpk-inspector-shell-radius: 5px;\n --cpk-inspector-surface-dark: #111319;\n --cpk-json-key: #3d408f;\n --cpk-json-str: #0b6b4c;\n --cpk-json-num: #8a5900;\n --cpk-json-bool: #c0333a;\n --cpk-json-nil: #57575b;\n position: fixed;\n top: 0;\n left: 0;\n z-index: 2147483646;\n display: block;\n will-change: transform;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n }\n\n :host([data-color-scheme=\"dark\"]),\n .inspector-window[data-color-scheme=\"dark\"] {\n --cpk-json-key: #bec2ff;\n --cpk-json-str: #85ecce;\n --cpk-json-num: #ffac4d;\n --cpk-json-bool: #fa5f67;\n --cpk-json-nil: #afafb7;\n }\n\n .cpk-json-token--key {\n color: var(--cpk-json-key);\n }\n\n .cpk-json-token--str {\n color: var(--cpk-json-str);\n }\n\n .cpk-json-token--num {\n color: var(--cpk-json-num);\n }\n\n .cpk-json-token--bool {\n color: var(--cpk-json-bool);\n }\n\n .cpk-json-token--nil {\n color: var(--cpk-json-nil);\n }\n\n .cpk-json-block {\n margin: 0;\n padding: 10px 12px;\n border: 1px solid #dbdbe5;\n border-radius: 8px;\n background: #f7f7f9;\n font-family: \"Spline Sans Mono\", monospace;\n font-size: 12px;\n line-height: 1.65;\n white-space: pre-wrap;\n overflow-wrap: anywhere;\n word-break: normal;\n color: #010507;\n overflow: auto;\n }\n\n :host([data-color-scheme=\"dark\"]) .cpk-json-block,\n .inspector-window[data-color-scheme=\"dark\"] .cpk-json-block {\n background: #111319;\n border-color: #343742;\n color: #f3f4f8;\n }\n\n @keyframes cpk-playground-message-enter {\n from {\n opacity: 0;\n filter: blur(2px);\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n filter: blur(0);\n transform: translateY(0);\n }\n }\n\n @keyframes cpk-playground-thinking {\n 0%,\n 60%,\n 100% {\n opacity: 0.28;\n transform: translateY(0);\n }\n 30% {\n opacity: 1;\n transform: translateY(-2px);\n }\n }\n\n .cpk-playground-root {\n container-type: inline-size;\n background: #fbfbfd !important;\n }\n\n .cpk-playground-header {\n min-height: 58px;\n background: #f7f6fd !important;\n }\n\n .cpk-playground-welcome {\n max-width: 560px;\n padding: 24px;\n }\n\n .cpk-playground-welcome-title {\n color: #24242b;\n font-size: 15px;\n font-weight: 600;\n letter-spacing: -0.015em;\n }\n\n .cpk-playground-composer {\n border: 1px solid #dcdce8;\n box-shadow:\n 0 8px 22px rgba(31, 23, 57, 0.08),\n 0 1px 2px rgba(31, 23, 57, 0.1);\n }\n\n .cpk-playground-composer:focus-within {\n border-color: #aaa4d4;\n box-shadow:\n 0 10px 26px rgba(86, 53, 155, 0.13),\n 0 0 0 3px rgba(190, 194, 255, 0.3);\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-root,\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-header {\n background: #15171e !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"]\n .cpk-playground-welcome-title {\n color: #f3f4f8 !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-playground-composer {\n border-color: #464957;\n background: #15171e !important;\n box-shadow:\n 0 8px 22px rgba(0, 0, 0, 0.26),\n 0 1px 2px rgba(0, 0, 0, 0.36);\n }\n\n .inspector-window[data-color-scheme=\"dark\"]\n .cpk-playground-composer:focus-within {\n border-color: #777aae;\n box-shadow:\n 0 10px 26px rgba(0, 0, 0, 0.34),\n 0 0 0 3px rgba(102, 106, 158, 0.3);\n }\n\n .cpk-playground-message-enter {\n animation: cpk-playground-message-enter 0.24s\n cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-playground-thinking-dot {\n animation: cpk-playground-thinking 1.2s ease-in-out infinite;\n }\n\n .cpk-playground-thinking-dot:nth-child(2) {\n animation-delay: 0.12s;\n }\n\n .cpk-playground-thinking-dot:nth-child(3) {\n animation-delay: 0.24s;\n }\n\n .cpk-playground-reasoning summary::-webkit-details-marker {\n display: none;\n }\n\n .cpk-playground-reasoning[open] .cpk-playground-reasoning-chevron {\n transform: rotate(90deg);\n }\n\n @container (max-width: 560px) {\n .cpk-playground-header {\n align-items: stretch;\n }\n\n .cpk-playground-actions {\n width: 100%;\n }\n\n .cpk-playground-thread-select {\n min-width: 0;\n max-width: none;\n flex: 1;\n }\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-playground-message-enter,\n .cpk-playground-thinking-dot {\n animation: none;\n }\n }\n\n .rounded-sm {\n border-radius: 3px;\n }\n\n .rounded-md {\n border-radius: 7px;\n }\n\n .rounded-lg {\n border-radius: 10px;\n }\n\n .rounded-xl {\n border-radius: 14px;\n }\n\n :host([data-docked=\"true\"]) {\n top: 0;\n left: 0;\n bottom: 0;\n transform: none !important;\n will-change: auto;\n }\n\n :host([data-transitioning=\"true\"]) {\n transition: transform 300ms ease;\n }\n\n .console-button-wrapper {\n position: relative;\n display: inline-flex;\n /* The launcher's surface and edge, shared by the button and the pill so\n the two cannot drift apart. A dark grey rather than near-black: the\n launcher sits on a customer's page, and 1,5,7 against white is a\n harder edge than this surface needs. */\n --cpk-launcher-face: rgba(24, 28, 31, 0.95);\n --cpk-launcher-face-solid: rgb(24, 28, 31);\n --cpk-launcher-edge: rgba(190, 194, 255, 0.25);\n /* The launcher's own size, exposed so the signal dot can be placed\n against the OUTER rim with a length rather than a percentage.\n Percentages resolve against the padding box, which the 1px border\n insets, and the dot would land inside the rim.\n\n Declared on the wrapper rather than on the button so the pill, which\n is the button's sibling, can clear the mark by the same length. */\n --cpk-launcher-size: clamp(\n ${LAUNCHER_MIN_SIZE}px,\n 7vw,\n ${LAUNCHER_MAX_SIZE}px\n );\n }\n\n .console-button {\n width: var(--cpk-launcher-size);\n height: var(--cpk-launcher-size);\n /* Keep the 1px border inside the declared outer size. */\n box-sizing: border-box;\n transition:\n transform 300ms cubic-bezier(0.34, 1.56, 0.64, 1),\n scale 300ms cubic-bezier(0.34, 1.56, 0.64, 1),\n background-color 200ms ease,\n border-color 200ms ease,\n box-shadow 200ms ease,\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 top: 0 !important;\n left: 0 !important;\n bottom: 0 !important;\n height: auto !important;\n max-height: none !important;\n }\n\n .resize-handle {\n touch-action: none;\n user-select: none;\n z-index: 60;\n background: transparent;\n }\n\n .edge-resize-handle {\n position: absolute;\n z-index: 55;\n touch-action: none;\n user-select: none;\n background: transparent;\n }\n\n .edge-resize-handle-e {\n top: 48px;\n right: 0;\n width: 8px;\n height: calc(100% - 48px);\n cursor: ew-resize;\n }\n\n .edge-resize-handle-w {\n top: 48px;\n left: 0;\n width: 8px;\n height: calc(100% - 48px);\n cursor: ew-resize;\n }\n\n .edge-resize-handle-s {\n left: 0;\n bottom: 0;\n width: 100%;\n height: 8px;\n cursor: ns-resize;\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(1, 5, 7, 0.95);\n color: white;\n padding: 4px 8px;\n border-radius: 7px;\n font-size: 10px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n line-height: 1.2;\n box-shadow: 0 4px 10px rgba(1, 5, 7, 0.18);\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 /* ── Agent tab section cards ─────────────────────────────────────── */\n .cpk-section-card {\n border-radius: 10px;\n background: #ffffff;\n overflow: hidden;\n }\n\n /* ── Agent icon bubble ───────────────────────────────────────────── */\n .cpk-agent-icon {\n background-color: #f0f0f4 !important;\n color: #57575b !important;\n }\n\n /* ── Agent stat cards ────────────────────────────────────────────── */\n .cpk-stat-card {\n background-color: #ffffff !important;\n border: 1px solid #dbdbe5 !important;\n }\n button.cpk-stat-card:hover {\n background-color: #f7f7f9 !important;\n }\n\n /* ── Circle chevron (Frontend Tools + Context) ──────────────────── */\n .cpk-chevron-circle {\n display: inline-flex;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 50%;\n background-color: #f0f0f4;\n color: #68686e;\n flex-shrink: 0;\n transition: transform 0.2s;\n }\n .cpk-chevron-circle svg {\n width: 14px !important;\n height: 14px !important;\n }\n .cpk-chevron-circle--open {\n transform: rotate(180deg);\n }\n\n /* ── Inline copy button ─────────────────────────────────────────── */\n .cpk-copy-btn {\n font-size: 10px;\n font-weight: 500;\n color: #57575b;\n background: #ffffff;\n border: 1px solid #dbdbe5;\n cursor: pointer;\n padding: 2px 8px;\n border-radius: 5px;\n flex-shrink: 0;\n transition:\n background-color 0.15s,\n border-color 0.15s,\n color 0.15s;\n }\n .cpk-copy-btn:hover {\n background-color: #f0f0f4;\n border-color: #afafb7;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-copy-btn {\n background: #191c24;\n border-color: #3a3d49;\n color: #f3f4f8;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .cpk-copy-btn:hover {\n background: #20232d;\n border-color: #57575b;\n }\n\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-sidebar-agent-scope\n [data-context-dropdown-root=\"true\"]\n > div {\n left: 100%;\n margin-inline-start: 8px;\n }\n\n .inspector-icon-rail-menu {\n transform-origin: left center;\n opacity: 0;\n visibility: hidden;\n pointer-events: none;\n transform: translateX(-8px) scale(0.96);\n transition:\n opacity 180ms ease,\n transform 180ms ease,\n visibility 180ms ease;\n }\n\n .inspector-icon-rail-menu[data-open=\"true\"] {\n opacity: 1;\n visibility: visible;\n pointer-events: auto;\n transform: translateX(0) scale(1);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .inspector-icon-rail-menu {\n transition: none;\n }\n }\n\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-sidebar-agent-scope\n [data-context-dropdown-root=\"true\"]\n > div::before {\n content: \"\";\n position: absolute;\n inset-block: 0;\n inset-inline-end: 100%;\n width: 12px;\n }\n\n .cpk-section-header {\n background: #e8edf5;\n border-bottom: 1px solid rgba(0, 0, 0, 0.08);\n padding: 10px 16px;\n }\n .inspector-window[data-color-scheme=\"dark\"] .cpk-section-header {\n border-bottom-color: #3a3d49;\n }\n .cpk-section-header h4 {\n font-size: 11px;\n font-weight: 600;\n color: #181c1f;\n margin: 0;\n }\n\n /* Inputs/selects inside the lavender header need an explicit white bg */\n .cpk-section-header input,\n .cpk-section-header select {\n background-color: #ffffff !important;\n box-shadow: none !important;\n }\n .cpk-section-header select {\n padding-right: 24px !important;\n }\n /* Events table column headers */\n table thead th {\n font-weight: 600 !important;\n }\n\n .announcement-content {\n color: #1f2230;\n font-size: 13px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n line-height: 1.55;\n }\n\n .announcement-content h1,\n .announcement-content h2,\n .announcement-content h3 {\n color: #010507;\n font-weight: 700;\n line-height: 1.3;\n margin: 0.9rem 0 0.4rem;\n }\n .announcement-content > h1:first-child,\n .announcement-content > h2:first-child,\n .announcement-content > h3:first-child {\n margin-top: 0;\n }\n\n .announcement-content h1 {\n font-size: 1.15rem;\n letter-spacing: -0.01em;\n }\n .announcement-content h2 {\n font-size: 1rem;\n }\n .announcement-content h3 {\n font-size: 0.9rem;\n text-transform: none;\n }\n\n .announcement-content p {\n margin: 0.45rem 0;\n }\n\n .announcement-content strong {\n color: #010507;\n font-weight: 700;\n }\n\n .announcement-content ul {\n list-style: disc;\n padding-left: 1.25rem;\n margin: 0.45rem 0;\n }\n\n .announcement-content ol {\n list-style: decimal;\n padding-left: 1.25rem;\n margin: 0.45rem 0;\n }\n\n .announcement-content li + li {\n margin-top: 0.15rem;\n }\n\n .announcement-content a {\n color: #5558b2;\n text-decoration: underline;\n }\n\n .announcement-content :not(pre) > code {\n background: #f3f3f7;\n border: 1px solid #e4e4ec;\n border-radius: 5px;\n padding: 1px 5px;\n font-size: 0.85em;\n color: #4a3a8a;\n }\n\n .announcement-code {\n position: relative;\n margin: 0.6rem 0;\n }\n\n .announcement-code pre {\n background: #0f1117;\n color: #e6e8f2;\n border-radius: 10px;\n padding: 10px 12px;\n overflow-x: auto;\n font-size: 12px;\n line-height: 1.5;\n white-space: pre;\n }\n\n .announcement-code pre code::after {\n content: \"\";\n display: inline-block;\n width: 80px;\n }\n\n .announcement-code__copy-shield {\n position: absolute;\n top: 4px;\n right: 4px;\n padding: 4px 4px 4px 24px;\n border-top-right-radius: 10px;\n background: linear-gradient(\n to right,\n rgba(15, 17, 23, 0) 0%,\n rgba(15, 17, 23, 0.95) 40%,\n #0f1117 100%\n );\n pointer-events: none;\n }\n\n .announcement-code pre code {\n background: transparent;\n border: none;\n padding: 0;\n color: inherit;\n font-size: inherit;\n }\n\n .announcement-code pre::-webkit-scrollbar {\n height: 6px;\n }\n .announcement-code pre::-webkit-scrollbar-track {\n background: transparent;\n }\n .announcement-code pre::-webkit-scrollbar-thumb {\n background: rgba(255, 255, 255, 0.2);\n border-radius: 4px;\n }\n\n .announcement-code__copy {\n position: relative;\n pointer-events: auto;\n padding: 3px 8px;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 11px;\n font-weight: 600;\n color: #e6e8f2;\n background: #1f222d;\n border: 1px solid rgba(255, 255, 255, 0.15);\n border-radius: 6px;\n cursor: pointer;\n transition:\n background 0.12s ease,\n color 0.12s ease;\n }\n .announcement-code__copy:hover {\n background: #2a2e3c;\n }\n .announcement-code__copy[data-copied=\"true\"] {\n background: #eee6fe;\n color: #6430ab;\n border-color: transparent;\n }\n\n /* ── What's new ──────────────────────────────────────────────── */\n .whats-new {\n display: block;\n padding: 16px;\n }\n\n .whats-new__heading {\n margin: 0 0 10px;\n color: #010507;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 15px;\n font-weight: 700;\n line-height: 1.35;\n letter-spacing: -0.01em;\n }\n\n .whats-new__status {\n display: flex;\n align-items: center;\n gap: 8px;\n color: #57575b;\n font-family: \"Plus Jakarta Sans\", system-ui, sans-serif;\n font-size: 13px;\n }\n\n .whats-new__status-icon {\n display: inline-flex;\n flex: none;\n align-items: center;\n justify-content: center;\n width: 24px;\n height: 24px;\n border-radius: 6px;\n background: #eee6fe;\n color: #5558b2;\n }\n\n /* ── Brand typography ────────────────────────────────────────── */\n /* Override Tailwind font-mono stack → Spline Sans Mono */\n .font-mono,\n pre,\n code {\n font-family:\n \"Spline Sans Mono\", ui-monospace, \"Cascadia Code\", monospace;\n }\n\n /* ── Floating button ─────────────────────────────────────────── */\n .console-button {\n background-color: var(--cpk-launcher-face) !important;\n border-color: var(--cpk-launcher-edge) !important;\n /* One hairline, not two. The border above is it; a second ring used to\n sit 1px outside as a box-shadow and hardcoded the lilac instead of\n reading the --cpk-launcher-edge token, so it could not follow it.\n What replaces it is a one-pixel light edge along the top, which is\n what keeps the face from reading flat without drawing a frame.\n\n The border is not decoration: the face is #181C1F, which against a\n dark host page (GitHub dark 1.10:1, Tailwind slate-900 1.04:1) is\n indistinguishable from the page. It is the only thing that gives the\n launcher an outline there, so it stays. */\n box-shadow:\n inset 0 1px 0 rgba(255, 255, 255, 0.07),\n 0 4px 14px rgba(1, 5, 7, 0.28) !important;\n /* Promotes the launcher to its own compositing layer, which the\n backdrop-filter this replaces used to do as a side effect. Without\n a layer the hover scale re-rasterises the mark every frame and it\n visibly jitters; with one, the compositor scales it as a texture. */\n will-change: transform;\n }\n .console-button:hover {\n background-color: var(--cpk-launcher-face-solid) !important;\n border-color: rgba(190, 194, 255, 0.45) !important;\n transform: scale(1.05);\n }\n .console-button:focus-visible {\n outline-color: #bec2ff !important;\n }\n\n /* ── Launcher signal: water ripple + internal wash + dot ────── */\n /*\n * Two rings leave the rim in sequence, like ripples spreading from a\n * drop's point of impact. They share one keyframe but the second begins\n * 180ms later, so the first is already farther from the source.\n *\n * ONLY opacity and transform animate. This component is permanently\n * mounted on top of a customer's application, so animating anything\n * that forces a repaint every frame is not acceptable.\n */\n .console-button[data-cpk-signal] {\n isolation: isolate;\n }\n\n /*\n * The mark sits above the ripples. Both ring layers are absolutely\n * positioned, so without a stacking position of its own the mark — an\n * ordinary in-flow child — would paint under them. Keeping the centre\n * readable is the reason the motion begins at the rim.\n */\n .cpk-launcher-mark {\n position: relative;\n z-index: 2;\n width: auto;\n height: calc(var(--cpk-launcher-size) / 1.8);\n }\n\n .console-button[data-cpk-signal]::before,\n .console-button[data-cpk-signal]::after {\n content: \"\";\n position: absolute;\n inset: 0;\n z-index: 0;\n box-sizing: border-box;\n border-radius: 50%;\n border: 2px solid\n color-mix(in srgb, var(--cpk-launcher-signal) 68%, transparent);\n box-shadow: 0 0 8px\n color-mix(in srgb, var(--cpk-launcher-signal) 38%, transparent);\n pointer-events: none;\n opacity: 0;\n transform: scale(1);\n }\n\n .cpk-launcher-signal-wash {\n position: absolute;\n inset: 0;\n z-index: 1;\n overflow: hidden;\n border-radius: 50%;\n pointer-events: none;\n opacity: 0;\n background: radial-gradient(\n circle at 50% 50%,\n transparent 26%,\n color-mix(in srgb, var(--cpk-launcher-signal) 78%, transparent) 63%,\n color-mix(in srgb, var(--cpk-launcher-signal) 30%, transparent) 84%,\n transparent 100%\n );\n }\n\n @keyframes cpk-launcher-ripple {\n 0% {\n opacity: 0.95;\n transform: scale(1);\n }\n 100% {\n opacity: 0;\n transform: scale(1.5);\n }\n }\n\n @keyframes cpk-launcher-wash {\n 0%,\n 100% {\n opacity: 0;\n }\n 45% {\n opacity: 1;\n }\n }\n\n /* Both ripples finish inside the existing one-beat pulse window. */\n .console-button[data-cpk-signal-pulsing=\"true\"]::before,\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation: cpk-launcher-ripple calc(var(--cpk-launcher-cadence) - 180ms)\n cubic-bezier(0.16, 1, 0.3, 1) 1 forwards;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation-delay: 180ms;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]\n .cpk-launcher-signal-wash {\n animation: cpk-launcher-wash var(--cpk-launcher-cadence) ease-in-out 1\n both;\n }\n\n /*\n * The dot's centre sits exactly ON the button's outer rim at 45°, where\n * 0.35355 is 0.5 x cos45. Lengths rather than percentage offsets:\n * percentages resolve against the padding box, which the border insets,\n * and the dot would land a pixel inside the rim.\n */\n .cpk-launcher-signal-dot {\n position: absolute;\n z-index: 3;\n left: 50%;\n top: 50%;\n transform: translate(-50%, -50%)\n translate(\n calc(var(--cpk-launcher-size) * 0.35355),\n calc(var(--cpk-launcher-size) * -0.35355)\n );\n width: 19%;\n height: 19%;\n border-radius: 50%;\n /* Lit from the upper left and shaded at the lower right, so the dot\n reads as a lens rather than a flat disc. Both stops are derived from\n the signal colour, so a new tone needs no new values. */\n background: radial-gradient(\n circle at 32% 28%,\n color-mix(in srgb, var(--cpk-launcher-signal), white 40%) 0%,\n var(--cpk-launcher-signal) 60%,\n color-mix(in srgb, var(--cpk-launcher-signal), black 20%) 100%\n );\n /* Replaces an opaque 1.5px collar in the launcher's own face. That\n collar was 21% of the dot's footprint, and because the dot's centre\n sits *on* the rim, its outer half painted a hard dark crescent onto\n the host page rather than onto the launcher. A hairline plus a soft\n drop does the same separating job without the hard edge. */\n box-shadow:\n 0 0 0 0.5px rgba(1, 5, 7, 0.4),\n 0 1px 2.5px rgba(1, 5, 7, 0.5);\n }\n\n /* ── Launcher pill: the launcher opens sideways and says what ─── */\n /*\n * The pill is laid out at its FULL width from the first frame and\n * revealed by animating a rectangular clip. Nothing is scaled and\n * nothing is resized.\n *\n * That is not a stylistic choice. This component is permanently mounted\n * on top of a customer's application, so no property that forces a\n * layout on every frame is acceptable — and animating \"width\" does\n * exactly that, sixty times a second, on someone else's page. A clip\n * leaves the element's geometry constant and changes only the visible\n * region, which the compositor handles. Animating a horizontal scale\n * was the other candidate and squashes the mark itself, not merely the\n * rounded end, so the logo would need counter-scaling and the dot and\n * halo would become ellipses.\n *\n * The launcher's own face and border are repeated here so the two form\n * one capsule: the button paints last and therefore on top, with no\n * z-index needed. The mark's own ring and shadow are deliberately left\n * alone for the whole gesture — the circle's outline staying visible\n * inside the open pill was looked at against the alternative and kept.\n *\n * A column, not a row: the pill carries a heading and a subline stacked,\n * centred against a height that does not change. \"justify-content\"\n * centres the pair vertically and \"align-items\" keeps both lines flush\n * left, so the pill never grows taller than the launcher it opens from.\n */\n .cpk-launcher-pill {\n position: absolute;\n top: 50%;\n margin-top: calc(var(--cpk-launcher-size) / -2);\n height: var(--cpk-launcher-size);\n display: inline-flex;\n flex-direction: column;\n justify-content: center;\n align-items: flex-start;\n gap: 1px;\n box-sizing: border-box;\n border-radius: 999px;\n border: 1px solid var(--cpk-launcher-edge);\n background: var(--cpk-launcher-face);\n color: #ffffff;\n white-space: nowrap;\n pointer-events: none;\n opacity: 0;\n }\n\n /* The failure class, word-identical to the panel's own wording. */\n .cpk-launcher-pill__heading {\n font-size: 12px;\n font-weight: 600;\n line-height: 1.2;\n }\n\n /*\n * The one line of copy in this feature that exists nowhere else in the\n * product. The heading above is word-identical to the panel, which is\n * the standing rule; this line is a deliberate, owner-approved exception\n * to it, because the pill is now clickable and has to say so.\n *\n * It is NOT spoken. A screen-reader user cannot act on an instruction\n * delivered through an announcement, and it would double the spoken\n * length — so the live region carries the failure class alone.\n */\n .cpk-launcher-pill__subline {\n font-size: 10.5px;\n font-weight: 500;\n line-height: 1.2;\n opacity: 0.72;\n }\n\n /*\n * Two directions, one animation with the inset on the other side. The\n * padding on the launcher's side clears the mark, so the words never sit\n * under it. The text-side padding is derived from the capsule's radius\n * (half the launcher size), NOT a bare literal: padding is measured from\n * the bounding box, but the first half-height of that side is the rounded\n * cap. Half the size lands the text exactly where the cap ends and the\n * straight edge begins. A literal 14px put it 16px inside the curve at the\n * production launcher size, which is itself a clamp on the viewport.\n */\n .cpk-launcher-pill[data-cpk-pill-direction=\"left\"] {\n right: 0;\n padding: 0 calc(var(--cpk-launcher-size) + 12px) 0\n calc(var(--cpk-launcher-size) / 2);\n clip-path: inset(0 0 0 calc(100% - var(--cpk-launcher-size)));\n }\n .cpk-launcher-pill[data-cpk-pill-direction=\"right\"] {\n left: 0;\n padding: 0 calc(var(--cpk-launcher-size) / 2) 0\n calc(var(--cpk-launcher-size) + 12px);\n clip-path: inset(0 calc(100% - var(--cpk-launcher-size)) 0 0);\n }\n\n /*\n * \"round\" on both stops, so the revealing edge is the capsule's own\n * rounded end travelling sideways rather than a straight vertical line\n * wiping across it. An unrounded inset reads as a wipe; this reads as an\n * opening. It adds no animated property: the clip is still the clip.\n */\n @keyframes cpk-launcher-pill-left {\n 0% {\n opacity: 0;\n clip-path: inset(\n 0 0 0 calc(100% - var(--cpk-launcher-size)) round 999px\n );\n }\n 100% {\n opacity: 1;\n clip-path: inset(0 0 0 0 round 999px);\n }\n }\n\n @keyframes cpk-launcher-pill-right {\n 0% {\n opacity: 0;\n clip-path: inset(\n 0 calc(100% - var(--cpk-launcher-size)) 0 0 round 999px\n );\n }\n 100% {\n opacity: 1;\n clip-path: inset(0 0 0 0 round 999px);\n }\n }\n\n /*\n * The pill takes the pointer exactly while it is on screen, so the\n * instruction it now carries is honest: a click on it opens the\n * Inspector, the same action as pressing the mark. During the beat the\n * clip covers only the mark itself, and a click target nobody can see\n * over someone else's page is not something to ship — so the base rule\n * keeps \"pointer-events: none\" and only the three visible phases take it\n * back.\n * The button paints last and therefore wins the pointer where the two\n * overlap, so dragging the launcher is unaffected throughout.\n */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n pointer-events: auto;\n cursor: pointer;\n }\n\n /* Closing is the same animation played backwards, so the two phases can\n never drift apart. */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation-timing-function: cubic-bezier(0.16, 1, 0.3, 1);\n animation-iteration-count: 1;\n animation-fill-mode: forwards;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"] {\n animation-duration: var(--cpk-launcher-pill-open);\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation-duration: var(--cpk-launcher-pill-close);\n animation-direction: reverse;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"][data-cpk-pill-direction=\"left\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"][data-cpk-pill-direction=\"left\"] {\n animation-name: cpk-launcher-pill-left;\n }\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"][data-cpk-pill-direction=\"right\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"][data-cpk-pill-direction=\"right\"] {\n animation-name: cpk-launcher-pill-right;\n }\n\n /* The hold is the end state of the reveal, held. */\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"] {\n opacity: 1;\n clip-path: inset(0 0 0 0);\n }\n\n /*\n * Reduced motion: the halo is held statically rather than animated, so\n * the information arrives without the movement.\n */\n @media (prefers-reduced-motion: reduce) {\n /*\n * The pill is shown by opacity alone, with no clip animation and the\n * same hold. The instruction is to reduce motion, not to withhold\n * information, and this reader needs the label as much as anyone.\n */\n .cpk-launcher-pill[data-cpk-pill-phase=\"opening\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"holding\"],\n .cpk-launcher-pill[data-cpk-pill-phase=\"closing\"] {\n animation: none !important;\n opacity: 1;\n clip-path: inset(0 0 0 0);\n }\n .cpk-launcher-signal-wash {\n opacity: 0.85;\n }\n .console-button[data-cpk-signal]::before {\n opacity: 0.5;\n }\n .console-button[data-cpk-signal]::after {\n opacity: 0;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]::before,\n .console-button[data-cpk-signal-pulsing=\"true\"]::after {\n animation: none !important;\n }\n .console-button[data-cpk-signal-pulsing=\"true\"]\n .cpk-launcher-signal-wash {\n animation: none !important;\n }\n .console-button {\n transition: opacity 160ms ease;\n }\n .console-button:hover {\n transform: none;\n }\n }\n\n /* ── Launcher HUD: hover menu, quieter than the error island ── */\n .console-button-wrapper[data-cpk-hud=\"open\"] .cpk-launcher-hud {\n pointer-events: auto;\n opacity: 1;\n transform: none;\n visibility: visible;\n }\n\n .cpk-launcher-hud {\n --hud-fill: var(--cpk-inspector-surface-dark);\n --hud-line: rgb(190 194 255 / 0.38);\n --hud-accent: #b8adf5;\n --hud-accent-soft: rgb(184 173 245 / 0.13);\n --hud-hover-fill: #252231;\n --hud-blur: blur(12px) saturate(1.2);\n --hud-card-gap: 8px;\n --hud-dismiss-day-height: 32px;\n position: absolute;\n z-index: 4;\n width: 258px;\n pointer-events: none;\n opacity: 0;\n visibility: hidden;\n transition:\n opacity 160ms ease,\n transform 200ms cubic-bezier(0.16, 1, 0.3, 1);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"top\"] {\n top: 0;\n bottom: auto;\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"] {\n top: auto;\n bottom: 0;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] {\n right: 100%;\n left: auto;\n padding-right: 14px;\n transform: translateX(8px);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] {\n left: 100%;\n right: auto;\n padding-left: 14px;\n transform: translateX(-8px);\n }\n\n .console-button-wrapper[data-cpk-hud=\"open\"] .cpk-launcher-hud {\n transform: none;\n }\n\n .cpk-launcher-hud__card {\n position: relative;\n display: grid;\n width: 244px;\n gap: var(--hud-card-gap);\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] {\n --hud-fill: #fff;\n --hud-line: #ddd6f4;\n --hud-accent: #6757b0;\n --hud-accent-soft: #f1edff;\n --hud-hover-fill: #f1edff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__card {\n color: #010507;\n }\n\n .cpk-launcher-hud__arrow {\n position: absolute;\n top: calc(var(--cpk-launcher-size) / 2);\n z-index: 2;\n width: 10px;\n height: 10px;\n border: 0;\n background: var(--hud-fill);\n transform: rotate(45deg);\n transition: background 120ms ease;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] .cpk-launcher-hud__arrow {\n right: 9px;\n border-top: 1px solid var(--hud-line);\n border-right: 1px solid var(--hud-line);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] .cpk-launcher-hud__arrow {\n left: 9px;\n border-bottom: 1px solid var(--hud-line);\n border-left: 1px solid var(--hud-line);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"top\"] .cpk-launcher-hud__arrow {\n top: calc(var(--cpk-launcher-size) / 2 - 5px);\n }\n\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"]\n .cpk-launcher-hud__arrow {\n top: auto;\n bottom: calc(var(--cpk-launcher-size) / 2 - 5px);\n }\n\n /* A bottom-anchored HUD can end with the narrower dismissal bubble.\n Keep the pointer attached to the full-width feature panel instead of\n letting it float in the empty space beside that final action. */\n .cpk-launcher-hud[data-cpk-hud-vertical=\"bottom\"]:has(\n .cpk-launcher-hud__dismiss-day\n )\n .cpk-launcher-hud__arrow {\n bottom: calc(\n var(--hud-dismiss-day-height) + var(--hud-card-gap) + 2px\n );\n }\n\n /* With no news or setup actions, the dismissal is the whole HUD. */\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] {\n --hud-dismiss-day-height: 36px;\n width: max-content;\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only][data-cpk-hud-vertical=\"top\"] {\n top: calc((var(--cpk-launcher-size) - var(--hud-dismiss-day-height)) / 2);\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only][data-cpk-hud-vertical=\"bottom\"] {\n bottom: calc((var(--cpk-launcher-size) - var(--hud-dismiss-day-height)) / 2);\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] .cpk-launcher-hud__card {\n width: max-content;\n }\n\n .cpk-launcher-hud__list {\n margin: 0;\n padding: 0;\n list-style: none;\n }\n\n .cpk-launcher-hud__masthead {\n position: relative;\n z-index: 1;\n margin-top: 6px;\n padding: 0;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n backdrop-filter: var(--hud-blur);\n -webkit-backdrop-filter: var(--hud-blur);\n box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);\n transition: background 120ms ease;\n }\n\n .cpk-launcher-hud__news-wrap {\n position: relative;\n margin: 0;\n }\n\n .cpk-launcher-hud__news {\n position: relative;\n display: flex;\n width: 100%;\n min-width: 0;\n flex-direction: column;\n align-items: flex-start;\n padding: 18px 12px 11px;\n border: 0;\n border-radius: calc(var(--cpk-inspector-shell-radius) - 1px);\n background: transparent;\n color: #fff;\n font-family: inherit;\n line-height: 1;\n text-align: start;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__news:hover,\n .cpk-launcher-hud__news:focus-visible {\n background: transparent;\n }\n\n .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:hover),\n .cpk-launcher-hud__masthead:has(.cpk-launcher-hud__news:focus-visible),\n .cpk-launcher-hud:has(.cpk-launcher-hud__news:hover)\n .cpk-launcher-hud__arrow,\n .cpk-launcher-hud:has(.cpk-launcher-hud__news:focus-visible)\n .cpk-launcher-hud__arrow {\n background: var(--hud-hover-fill);\n }\n\n .cpk-launcher-hud__news:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__news-title {\n display: block;\n font-size: 12px;\n font-weight: 650;\n line-height: 1.32;\n overflow-wrap: anywhere;\n white-space: normal;\n }\n\n .cpk-launcher-hud__news-label {\n position: absolute;\n top: -9px;\n left: 12px;\n display: inline-flex;\n min-height: 20px;\n align-items: center;\n padding: 3px 8px;\n border-radius: 6px;\n background: #7563c7;\n color: #fff;\n box-shadow: 0 3px 8px rgb(46 37 91 / 0.18);\n font-size: 9px;\n font-weight: 700;\n line-height: 1;\n }\n\n .cpk-launcher-hud__news-dismiss {\n position: absolute;\n top: -1px;\n right: 2px;\n z-index: 2;\n display: inline-flex;\n width: 20px;\n height: 20px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n border-radius: 4px;\n background: transparent;\n color: rgb(255 255 255 / 0.68);\n cursor: pointer;\n }\n\n .cpk-launcher-hud__news-dismiss:hover,\n .cpk-launcher-hud__news-dismiss:focus-visible {\n background: var(--hud-accent-soft);\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss {\n color: #6e697c;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__news-dismiss:focus-visible {\n color: #27233a;\n }\n\n .cpk-launcher-hud__news-dismiss:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__news-dismiss svg {\n width: 7px;\n height: 7px;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__news {\n color: #17131f;\n }\n\n .cpk-launcher-hud__dismiss-day {\n position: relative;\n z-index: 1;\n display: flex;\n width: auto;\n min-height: var(--hud-dismiss-day-height);\n align-items: center;\n justify-content: center;\n justify-self: center;\n gap: 6px;\n margin: 0;\n padding: 7px 13px;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n color: #c9cad3;\n box-shadow: 0 8px 20px rgb(17 14 29 / 0.18);\n font-family: inherit;\n font-size: 10px;\n font-weight: 650;\n line-height: 1.2;\n cursor: pointer;\n transition:\n border-color 120ms ease,\n background 120ms ease,\n color 120ms ease;\n }\n\n .cpk-launcher-hud[data-cpk-hud-dismiss-only] .cpk-launcher-hud__dismiss-day {\n font-size: 11px;\n white-space: nowrap;\n }\n\n .cpk-launcher-hud__dismiss-day:hover,\n .cpk-launcher-hud__dismiss-day:focus-visible {\n border-color: var(--hud-accent);\n background: var(--hud-hover-fill);\n color: #f3f4f8;\n }\n\n .cpk-launcher-hud__dismiss-day:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__dismiss-day svg {\n width: 12px;\n height: 12px;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day {\n box-shadow: 0 8px 20px rgb(46 37 91 / 0.12);\n color: #5f6068;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__dismiss-day:focus-visible {\n color: #36373d;\n }\n\n .cpk-launcher-hud__feature-list {\n position: relative;\n z-index: 1;\n padding: 5px;\n border: 1px solid var(--hud-line);\n border-radius: var(--cpk-inspector-shell-radius);\n background: var(--hud-fill);\n backdrop-filter: var(--hud-blur);\n -webkit-backdrop-filter: var(--hud-blur);\n box-shadow: 0 10px 28px rgb(46 37 91 / 0.16);\n }\n\n .cpk-launcher-hud__row {\n position: relative;\n display: grid;\n grid-template-columns: minmax(0, 1fr) auto;\n align-items: center;\n min-height: 54px;\n border-radius: 9px;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__row + .cpk-launcher-hud__row {\n border-top: 1px solid var(--hud-line);\n border-radius: 0 0 9px 9px;\n }\n\n .cpk-launcher-hud__row:hover,\n .cpk-launcher-hud__row:focus-within {\n background: rgb(255 255 255 / 0.06);\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__row:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__row:focus-within {\n background: #f7f5ff;\n }\n\n .cpk-launcher-hud__primary {\n position: relative;\n display: flex;\n min-width: 0;\n }\n\n .cpk-launcher-hud__action {\n display: flex;\n width: 100%;\n gap: 8px;\n min-height: 52px;\n align-items: center;\n padding: 7px 4px;\n border: 0;\n border-radius: 9px;\n background: transparent;\n color: #fff;\n font-family: inherit;\n font-size: 12px;\n font-weight: 600;\n text-align: start;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__label {\n min-width: 0;\n }\n\n .cpk-launcher-hud__feature-icon {\n display: inline-flex;\n width: 28px;\n height: 32px;\n flex: none;\n align-items: center;\n justify-content: center;\n background: transparent;\n color: var(--hud-accent);\n }\n\n .cpk-launcher-hud__feature-icon svg {\n width: 17px;\n height: 17px;\n stroke-width: 1.8;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"] .cpk-launcher-hud__action {\n color: #010507;\n }\n\n /* Stretch the row action over the whole tab. The icon controls sit\n above this layer and keep their own focused interactions. */\n .cpk-launcher-hud__action::after {\n content: \"\";\n position: absolute;\n inset: 0;\n }\n\n .cpk-launcher-hud__controls {\n position: relative;\n z-index: 1;\n display: flex;\n gap: 0;\n align-items: center;\n padding-right: 5px;\n }\n\n .cpk-launcher-hud__learn-more {\n display: inline-flex;\n width: 24px;\n height: 44px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n background: transparent;\n color: rgb(190 194 255 / 0.72);\n cursor: pointer;\n }\n\n .cpk-launcher-hud__learn-more:hover,\n .cpk-launcher-hud__learn-more:focus-visible {\n color: #fff;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more {\n color: #777080;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more:hover,\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__learn-more:focus-visible {\n color: #4b416b;\n }\n\n .cpk-launcher-hud__learn-more svg {\n width: 16px;\n height: 16px;\n stroke-width: 1.8;\n }\n\n .cpk-launcher-hud__toggle {\n display: inline-flex;\n width: 38px;\n height: 44px;\n align-items: center;\n justify-content: center;\n padding: 0;\n border: 0;\n background: transparent;\n color: rgb(255 255 255 / 0.78);\n font-size: 12px;\n font-weight: 600;\n cursor: pointer;\n }\n\n .cpk-launcher-hud__toggle:disabled {\n cursor: not-allowed;\n opacity: 1;\n }\n\n .cpk-launcher-hud__toggle-track {\n position: relative;\n display: block;\n width: 34px;\n height: 20px;\n border: 1px solid rgb(190 194 255 / 0.38);\n border-radius: 999px;\n background: rgb(255 255 255 / 0.08);\n transition:\n border-color 120ms ease,\n background 120ms ease;\n }\n\n .cpk-launcher-hud__toggle-track::after {\n content: \"\";\n position: absolute;\n top: 2px;\n left: 2px;\n width: 14px;\n height: 14px;\n border-radius: 50%;\n background: #8c8e99;\n transition:\n background 120ms ease,\n transform 120ms ease;\n }\n\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #087653;\n background: #087653;\n }\n\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #fff;\n transform: translateX(14px);\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #c9c9d2;\n background: #e7e7ec;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #777780;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track {\n border-color: #087653;\n background: #087653;\n }\n\n .cpk-launcher-hud[data-color-scheme=\"light\"]\n .cpk-launcher-hud__toggle[data-enabled=\"true\"]\n .cpk-launcher-hud__toggle-track::after {\n background: #fff;\n }\n\n .cpk-launcher-hud__toggle:focus-visible,\n .cpk-launcher-hud__learn-more:focus-visible,\n .cpk-launcher-hud__action:focus-visible {\n outline: 2px solid #bec2ff;\n outline-offset: 1px;\n }\n\n .cpk-launcher-hud__tooltip {\n position: absolute;\n top: 50%;\n z-index: 30;\n width: max-content;\n max-width: min(220px, 52vw);\n padding: 7px 9px;\n border: 1px solid #3a3d49;\n border-radius: 4px;\n background: #15171e;\n color: #f3f4f8;\n box-shadow: 0 8px 20px rgb(1 5 7 / 0.18);\n font-size: 10px;\n font-weight: 500;\n line-height: 1.45;\n opacity: 0;\n pointer-events: none;\n transform: translate(3px, -50%);\n white-space: normal;\n transition:\n opacity 120ms ease,\n transform 120ms ease;\n }\n\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)\n .cpk-launcher-hud__tooltip,\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)\n .cpk-launcher-hud__tooltip {\n opacity: 1;\n transform: translate(0, -50%);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"left\"] .cpk-launcher-hud__tooltip {\n right: calc(100% + 8px);\n left: auto;\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"] .cpk-launcher-hud__tooltip {\n right: auto;\n left: calc(100% + 8px);\n transform: translate(-3px, -50%);\n }\n\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"]\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:hover)\n .cpk-launcher-hud__tooltip,\n .cpk-launcher-hud[data-cpk-hud-side=\"right\"]\n .cpk-launcher-hud__row:has(.cpk-launcher-hud__learn-more:focus-visible)\n .cpk-launcher-hud__tooltip {\n transform: translate(0, -50%);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-launcher-hud,\n .cpk-launcher-hud__tooltip {\n transition: none;\n }\n }\n\n /*\n * On mount, borrow the hover HUD for one short introduction. The card\n * establishes the destination first; notification, features, and hide\n * action then fall into place from top to bottom. Only opacity and\n * transform move.\n */\n @keyframes cpk-launcher-hud-intro {\n 0% {\n opacity: 0;\n transform: translateY(-4px);\n }\n 8%,\n 88% {\n opacity: 1;\n transform: none;\n }\n 100% {\n opacity: 0;\n transform: translateY(3px);\n }\n }\n\n @keyframes cpk-launcher-hud-waterfall {\n from {\n opacity: 0;\n transform: translateY(-8px);\n }\n to {\n opacity: 1;\n transform: none;\n }\n }\n\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"] {\n animation: cpk-launcher-hud-intro var(--cpk-launcher-hud-intro-duration)\n cubic-bezier(0.16, 1, 0.3, 1) both;\n }\n\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"]\n :is(\n .cpk-launcher-hud__masthead,\n .cpk-launcher-hud__feature-list,\n .cpk-launcher-hud__row,\n .cpk-launcher-hud__dismiss-day\n ) {\n animation: cpk-launcher-hud-waterfall\n var(--cpk-launcher-hud-waterfall-duration)\n cubic-bezier(0.16, 1, 0.3, 1) both;\n animation-delay: var(--cpk-hud-waterfall-delay);\n }\n\n @media (prefers-reduced-motion: reduce) {\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"],\n .cpk-launcher-hud[data-cpk-hud-intro=\"true\"]\n :is(\n .cpk-launcher-hud__masthead,\n .cpk-launcher-hud__feature-list,\n .cpk-launcher-hud__row,\n .cpk-launcher-hud__dismiss-day\n ) {\n animation: none !important;\n opacity: 1;\n transform: none;\n }\n }\n\n /*\n * Marker on the navigation entry, which is what keeps a signal alive\n * once the panel is open and the launcher is hidden. Static by design:\n * the beat belongs to the launcher, and movement here would compete with\n * the live event stream a developer is actually watching.\n *\n * Tone-selected rather than tone-agnostic, because the marker has to\n * agree with the dot that sent the reader here. Same shape, same\n * placement, one declaration different — as on the launcher, where the\n * treatment is shared and only the injected colour changes.\n */\n .inspector-nav-signal-dot {\n display: inline-block;\n flex: none;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${unsafeCSS(LAUNCHER_SIGNAL_COLORS.news)};\n }\n .inspector-nav-signal-dot[data-cpk-signal-tone=\"error\"] {\n background: ${unsafeCSS(LAUNCHER_SIGNAL_COLORS.error)};\n }\n\n /* ── Inspector window ────────────────────────────────────────── */\n .inspector-window {\n border: 1px solid #d8d8e8 !important;\n border-radius: var(--cpk-inspector-shell-radius) !important;\n box-shadow: none !important;\n }\n\n /* ── Header drag area ────────────────────────────────────────── */\n .drag-handle {\n border-bottom-color: #d8d8e8 !important;\n background-color: #f7f6fd !important;\n }\n\n .inspector-account-strip {\n background: #f7f6fd !important;\n color: #010507 !important;\n }\n\n .inspector-window[data-color-scheme=\"dark\"] .drag-handle,\n .inspector-window[data-color-scheme=\"dark\"] .inspector-account-strip {\n background: #15171e !important;\n }\n\n /* ── Tab buttons ─────────────────────────────────────────────── */\n /*\n * Named classes owned by this component — no Tailwind conflict.\n * Active: brand surface/surfaceContainerActive (lilac tint) +\n * border/borderActionEnabled underline.\n * Dark fill is for primary action buttons only, not nav tabs.\n */\n .cpk-tab-active {\n background-color: rgba(190, 194, 255, 0.18);\n color: #010507;\n font-weight: 600;\n }\n .cpk-tab-icon {\n display: inline-flex;\n flex-shrink: 0;\n align-items: center;\n }\n .cpk-tab-active .cpk-tab-icon {\n color: #5558b2;\n }\n .cpk-tab-inactive {\n background-color: transparent;\n color: #2b2b2b;\n }\n .cpk-tab-inactive .cpk-tab-icon {\n color: #68686e;\n }\n .cpk-tab-inactive:hover {\n background-color: rgba(190, 194, 255, 0.08);\n color: #010507;\n cursor: pointer;\n }\n .cpk-tab-active {\n cursor: pointer;\n }\n .cpk-threads-overview-video-frame {\n position: relative;\n display: block;\n width: 100%;\n max-width: 440px;\n aspect-ratio: 16 / 9;\n margin: 0 0 14px;\n overflow: hidden;\n border: 1px solid #dbdbe5;\n border-radius: 10px;\n background:\n linear-gradient(\n 135deg,\n rgba(190, 194, 255, 0.18),\n rgba(133, 236, 206, 0.12)\n ),\n #ffffff;\n box-shadow: 0 8px 20px rgba(1, 5, 7, 0.08);\n }\n .cpk-threads-overview-video {\n width: 100%;\n height: 100%;\n object-fit: cover;\n }\n .cpk-threads-overview-video-embed {\n width: 100%;\n height: 100%;\n border: 0;\n }\n\n /* ── Header controls on the branded account strip ──────────── */\n .drag-handle > div[data-inspector-account-strip] button {\n color: #57575b !important;\n cursor: pointer;\n }\n .drag-handle > div[data-inspector-account-strip] button,\n .inspector-nav-control,\n [data-inspector-thread-cta] {\n outline: 2px solid transparent;\n outline-offset: 2px;\n }\n .drag-handle > div[data-inspector-account-strip] button:hover {\n background-color: rgba(100, 48, 171, 0.09) !important;\n color: #3f176f !important;\n }\n .drag-handle > div[data-inspector-account-strip] button:focus-visible {\n outline: 2px solid #bec2ff !important;\n outline-offset: 2px;\n }\n .inspector-nav-control:focus-visible,\n [data-inspector-thread-cta]:focus-visible,\n [data-inspector-action-placement=\"threads-footer\"]:focus-visible {\n outline: 2px solid #6430ab !important;\n outline-offset: 2px;\n }\n .inspector-sidebar .inspector-nav-control,\n .inspector-sidebar .inspector-sidebar-control,\n .inspector-sidebar .inspector-sidebar-label {\n display: flex !important;\n justify-content: flex-start !important;\n text-align: left !important;\n outline-offset: -2px;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-control,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-control,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-toggle {\n box-sizing: border-box !important;\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n justify-content: center !important;\n align-items: center !important;\n gap: 0 !important;\n padding: 0 !important;\n overflow: visible !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-icon,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-icon svg,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-icon,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-icon\n svg,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-placeholder\n svg {\n width: 18px !important;\n height: 18px !important;\n overflow: visible !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"] {\n display: flex !important;\n flex: none !important;\n width: 36px !important;\n min-width: 36px !important;\n max-width: 36px !important;\n justify-content: center !important;\n align-items: center !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-agent-placeholder {\n display: flex !important;\n width: 36px !important;\n height: 36px !important;\n min-width: 36px !important;\n min-height: 36px !important;\n max-width: 36px !important;\n align-items: center !important;\n justify-content: center !important;\n gap: 0 !important;\n padding: 0 !important;\n transition:\n background-color 180ms ease,\n border-color 180ms ease,\n color 180ms ease !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-label,\n .inspector-sidebar[data-icon-rail=\"true\"]\n .inspector-context-dropdown-chevron {\n display: none !important;\n width: 0 !important;\n min-width: 0 !important;\n flex: none !important;\n overflow: hidden !important;\n }\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-nav-label,\n .inspector-sidebar[data-icon-rail=\"true\"] .inspector-sidebar-label {\n display: none !important;\n }\n .inspector-sidebar .inspector-nav-control:focus-visible,\n .inspector-sidebar .inspector-sidebar-label:focus-visible,\n .inspector-sidebar .inspector-sidebar-toggle:focus-visible {\n outline-offset: -2px !important;\n }\n\n /* ── Agent/context dropdown ──────────────────────────────────── */\n [data-context-dropdown-root=\"true\"] > button {\n border-color: #dbdbe5 !important;\n color: #010507 !important;\n }\n [data-context-dropdown-root=\"true\"] > button:hover {\n border-color: #bec2ff !important;\n background-color: #f7f7f9 !important;\n }\n [data-context-dropdown-root=\"true\"] > button > span:last-child {\n color: #68686e !important;\n }\n [data-context-dropdown-root=\"true\"] > div {\n border-color: #dbdbe5 !important;\n box-shadow: 0 4px 12px rgba(1, 5, 7, 0.08) !important;\n }\n [data-context-dropdown-root=\"true\"] > div button:hover,\n [data-context-dropdown-root=\"true\"] > div button:focus {\n background-color: #eceafa !important;\n color: #2f1664 !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button {\n border-color: #d8d8e8 !important;\n background-color: rgba(255, 255, 255, 0.7) !important;\n color: #010507 !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button:hover {\n border-color: #a5a9ee !important;\n background-color: #ffffff !important;\n }\n .inspector-sidebar\n .inspector-agent-selector\n > [data-context-dropdown-root=\"true\"]\n > button\n > span:last-child {\n color: #68686e !important;\n }\n\n /* ── Resize handle ───────────────────────────────────────────── */\n .resize-handle {\n color: #68686e !important;\n }\n .resize-handle:hover {\n color: #57575b !important;\n }\n\n /* ── AG-UI Events tab ────────────────────────────────────────── */\n /* Row hover: replace blue tint with brand lilac */\n tr:hover td {\n background-color: rgba(190, 194, 255, 0.08) !important;\n }\n /* Reset/dark action button */\n button[class*=\"bg-gray-900\"] {\n background-color: #010507 !important;\n }\n button[class*=\"bg-gray-800\"] {\n background-color: #2b2b2b !important;\n }\n /* Copy \"copied\" state: generic green → brand mint */\n button[class*=\"bg-green-100\"] {\n background-color: rgba(133, 236, 206, 0.2) !important;\n color: #087653 !important;\n }\n\n /* ── Agents tab ──────────────────────────────────────────────── */\n /* Agent icon bubble: blue → lilac */\n span[class*=\"bg-blue-100\"]:not([class*=\"text-blue-800\"]) {\n background-color: rgba(190, 194, 255, 0.15) !important;\n }\n span[class*=\"text-blue-600\"] {\n color: #5558b2 !important;\n }\n /* Running badge: emerald → mint */\n span[class*=\"bg-emerald-50\"] {\n background-color: rgba(133, 236, 206, 0.15) !important;\n }\n span[class*=\"text-emerald-700\"] {\n color: #087653 !important;\n }\n /* Running status dot */\n span[class*=\"bg-emerald-500\"] {\n background-color: #85ecce !important;\n }\n /* Idle dot */\n span[class*=\"bg-gray-400\"] {\n background-color: #afafb7 !important;\n }\n /* User role badge (blue → lilac) */\n span[class*=\"bg-blue-100\"][class*=\"text-blue-800\"] {\n background-color: rgba(190, 194, 255, 0.22) !important;\n border: 1px solid rgba(190, 194, 255, 0.45) !important;\n color: #57575b !important;\n }\n /* Assistant role badge (green → mint) */\n span[class*=\"bg-green-100\"][class*=\"text-green-800\"] {\n background-color: rgba(133, 236, 206, 0.18) !important;\n border: 1px solid rgba(133, 236, 206, 0.4) !important;\n color: #087653 !important;\n }\n /* Tool role badge (amber → orange brand) */\n span[class*=\"bg-amber-100\"][class*=\"text-amber-800\"] {\n background-color: rgba(255, 172, 77, 0.15) !important;\n color: #57575b !important;\n }\n\n /* ── Frontend Tools tab ──────────────────────────────────────── */\n /* Handler badge (blue → lilac) */\n span[class*=\"bg-blue-50\"][class*=\"text-blue-700\"] {\n background-color: rgba(190, 194, 255, 0.12) !important;\n border-color: rgba(190, 194, 255, 0.3) !important;\n color: #010507 !important;\n }\n /* Renderer badge (purple → lilac-adjacent) */\n span[class*=\"bg-purple-50\"][class*=\"text-purple-700\"] {\n background-color: rgba(190, 194, 255, 0.12) !important;\n border-color: rgba(190, 194, 255, 0.3) !important;\n color: #57575b !important;\n }\n /* Required badge (rose → brand red) */\n span[class*=\"bg-rose-50\"][class*=\"text-rose-700\"] {\n background-color: rgba(250, 95, 103, 0.1) !important;\n border-color: rgba(250, 95, 103, 0.25) !important;\n color: #fa5f67 !important;\n }\n /* Code/default value blocks */\n code[class*=\"bg-gray-100\"],\n span[class*=\"bg-gray-100\"] {\n background-color: #f0f0f4 !important;\n }\n\n /* ── Connected status bar: match threads header mint (#5BE4BB) ──── */\n /* Outer strip bg + top border + text when connected badge is present */\n .inspector-window\n > div\n > div:last-child\n > div:last-child:has(div[class*=\"bg-emerald-50\"]) {\n background-color: rgba(91, 228, 187, 0.08) !important;\n border-top-color: rgba(91, 228, 187, 0.3) !important;\n color: #087653 !important;\n }\n /* Inner badge — slightly more opaque on the mint bg */\n div[class*=\"bg-emerald-50\"][class*=\"border-emerald-200\"] {\n background-color: rgba(91, 228, 187, 0.12) !important;\n border-color: rgba(91, 228, 187, 0.4) !important;\n color: #087653 !important;\n }\n div[class*=\"bg-emerald-50\"][class*=\"border-emerald-200\"]\n span[class*=\"opacity-80\"] {\n opacity: 1 !important;\n }\n /* Icon bubble inside connected badge → mint tint */\n div[class*=\"bg-emerald-50\"] span[class*=\"bg-white\"] {\n background-color: rgba(91, 228, 187, 0.3) !important;\n }\n\n /* ── Announcement panel ──────────────────────────────────────── */\n div[class*=\"border-slate-200\"][class*=\"bg-white\"] {\n border-color: #dbdbe5 !important;\n }\n /* Announcement icon bubble: black → brand light lavender + lilac icon */\n span[class*=\"bg-slate-900\"],\n div[class*=\"bg-slate-900\"] {\n background-color: #eee6fe !important;\n color: #5558b2 !important;\n }\n span[class*=\"text-slate-800\"],\n div[class*=\"text-slate-800\"] {\n color: #010507 !important;\n }\n `,\n ];\n\n connectedCallback(): void {\n super.connectedCallback();\n if (typeof window !== \"undefined\") {\n this.accountCtaMotionPaused = document.visibilityState !== \"visible\";\n this.threadsExampleOverviewVideoReducedMotion =\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches ??\n false;\n this.ensureBrandFonts();\n window.addEventListener(\"resize\", this.handleResize);\n window.addEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n window.addEventListener(\"beforeunload\", this.handleAppBeforeUnload);\n document.addEventListener(\n \"visibilitychange\",\n this.handleDocumentVisibilityChange,\n );\n const viteHot = (\n import.meta as ImportMeta & {\n hot?: { on: (event: string, handler: () => void) => void };\n }\n ).hot;\n if (viteHot) {\n viteHot.on(\"vite:beforeUpdate\", this.handleAppBeforeUnload);\n }\n\n // Load state early (before first render) so menu selection is correct\n this.hydrateStateFromStorageEarly();\n this.learningSetupMarker = readLearningSetupMarker();\n this.learningSetupUnsubscribe = subscribeToLearningSetupMarker(\n (marker) => {\n this.learningSetupMarker = marker;\n this.requestUpdate();\n this.scheduleLearningPoll();\n },\n );\n this.refreshInspectorDismissalState();\n this.subscribeToSystemColorScheme();\n this.exampleTourDismissed = this.readThreadsExampleTourDismissed();\n // The superseded, origin-scoped read state is discarded rather than\n // migrated: every existing user is re-armed exactly once so they\n // discover the surface that replaced the announcement bubble. Deleting\n // the key rather than leaving it means nothing can fall back to it.\n clearLegacyAnnouncementReadState();\n this.tryAutoAttachCore();\n if (!this.isInspectorDismissed) {\n this.ensureAnnouncementLoading();\n }\n this.subscribeToInspectorThreadBridge();\n }\n this.requestUpdate();\n }\n\n private ensureBrandFonts(): void {\n ensureBrandFont(document);\n }\n\n private handleDocumentVisibilityChange = (): void => {\n this.accountCtaMotionPaused = document.visibilityState !== \"visible\";\n this.refreshInspectorDismissalState();\n // Flush point for defer reason 3: somebody is looking again.\n if (\n document.visibilityState === \"visible\" &&\n !this.isOpen &&\n !this.isInspectorDismissed\n ) {\n this.flushPendingSignalPulse();\n }\n if (\n document.visibilityState === \"visible\" &&\n this.isOpen &&\n this.selectedMenu === \"memories\"\n ) {\n void this.refreshLearningSnapshot({ preserve: true });\n } else {\n this.cancelLearningPoll();\n }\n this.requestUpdate();\n };\n\n disconnectedCallback(): void {\n super.disconnectedCallback();\n this.closePopOut();\n if (typeof window !== \"undefined\") {\n this.unsubscribeFromSystemColorScheme();\n window.removeEventListener(\"resize\", this.handleResize);\n window.removeEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n window.removeEventListener(\"beforeunload\", this.handleAppBeforeUnload);\n document.removeEventListener(\n \"visibilitychange\",\n this.handleDocumentVisibilityChange,\n );\n }\n // Clear pending body-transition timers to prevent post-teardown errors\n for (const id of this.bodyTransitionTimeoutIds) {\n clearTimeout(id);\n }\n this.bodyTransitionTimeoutIds.clear();\n if (this.transitionTimeoutId !== null) {\n clearTimeout(this.transitionTimeoutId);\n this.transitionTimeoutId = null;\n }\n this.clearIconRailContextCloseTimer();\n this.unsubscribeFromInspectorThreadBridge();\n this.learningSetupUnsubscribe?.();\n this.learningSetupUnsubscribe = null;\n this.clearLearningSnapshot();\n this.stopIntelligenceStory();\n this.clearIntelligencePromptReset();\n this.homeFeaturePromptCopyGeneration += 1;\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n this.homeFeaturePromptCopyResetTimeoutId = null;\n }\n this.homeFeaturePromptCopyState = null;\n this.stopSignalPulse();\n this.cancelGestureTail();\n this.cancelLauncherHudIntro();\n this.clearInspectorDismissalTimer();\n this.cancelThreadRefreshDebounce();\n this.clearInspectorUsageRefresh();\n this.cleanupThreadsExampleOverviewVideo();\n this.removeDockStyles(true); // Clean up any docking styles, skip transition\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 this.contextState.window.size = this.clampWindowSize(\n this.contextState.window.size,\n );\n\n // `hydrateStateFromStorage` may have restored `selectedMenu: \"memories\"`.\n // The memory subscription is normally created on a Memories-tab CLICK via\n // `handleMenuSelect`, which never fires when the tab boots already active —\n // leaving the realtime indicator stuck on the default \"connecting\" and the\n // list empty until the user toggles tabs. Subscribe now when the Memories\n // tab is the active tab. Gated on the active tab to preserve INSP-1 (no\n // unconditional subscribe), and safe if core is not yet attached or already\n // subscribed — `ensureMemorySubscription` early-returns in both cases.\n if (this.selectedMenu === \"memories\") {\n this.ensureMemorySubscription();\n }\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 if (this.isInspectorDismissed) {\n // The close action persists this immediately. This branch also covers a\n // different localhost port whose own Inspector state was still open.\n this.persistState();\n } else {\n this.ensureAnnouncementLoading();\n }\n\n this.updateHostTransform(this.isOpen ? \"window\" : \"button\");\n if (!this.isInspectorDismissed) {\n this.scheduleLauncherHudIntro();\n }\n }\n\n render() {\n if (this.isInspectorDismissed) return nothing;\n return this.isOpen\n ? html`\n <div data-inspector-portal-anchor></div>\n `\n : this.renderButton();\n }\n\n protected willUpdate(): void {\n // Before the render that paints the dot: every mutation of the underlying\n // connection / thread state already requests an update, so mirroring the\n // latches here keeps the resting dot in step with the state it reports.\n this.evaluateErrorSignals();\n this.reconcileSelectedMenuVisibility();\n if (this.isOpen && this.dockMode === \"docked-left\") {\n this.setAttribute(\"data-docked\", \"true\");\n } else {\n this.removeAttribute(\"data-docked\");\n }\n }\n\n protected updated(): void {\n // Host message shortcuts follow the actual Inspector, including persisted\n // dismissals and their expiry. Closing the panel still leaves it available.\n const visible = !this.isInspectorDismissed;\n if (visible !== this.lastReportedInspectorVisibility) {\n this.lastReportedInspectorVisibility = visible;\n this.dispatchEvent(\n new CustomEvent(\"cpk-inspector-visibility-change\", {\n detail: { visible },\n }),\n );\n }\n this.syncInspectorPortal();\n this.syncThreadsExampleOverviewVideo();\n this.maybeTrackInspectorMetadataViews();\n this.maybeTrackNewsSignalViewed();\n // The pill's full width is only measurable once it has been laid out, and\n // the answer decides both the direction and the telemetry label below, so\n // this runs before the visibility event rather than after it.\n this.resolvePillDirection();\n this.maybeTrackErrorSignalViewed();\n // \"Rendered with content\" is a property of the finished render, so the\n // news signal is retired here rather than from a render method.\n this.maybeCompleteWhatsNewView();\n this.maybeCompleteEventErrorView();\n this.flushErrorLandingScroll();\n this.maybeTrackHomeViewed();\n this.syncIntelligenceStory();\n\n if (!this.isOpen) {\n this.lastScrolledAgentNavigationLayout = null;\n return;\n }\n\n const navigation = this.activeRoot.querySelector<HTMLElement>(\n 'nav[aria-label=\"Inspector\"]',\n );\n if (!navigation) {\n return;\n }\n\n const activeControl = navigation.querySelector<HTMLElement>(\n '[aria-current=\"page\"]',\n );\n if (!activeControl) {\n return;\n }\n\n const layoutKey = [\n this.selectedMenu,\n this.dockMode,\n Math.round(this.contextState.window.size.width),\n typeof window === \"undefined\" ? 0 : window.innerWidth,\n navigation.clientWidth,\n navigation.scrollWidth,\n ].join(\":\");\n if (this.lastScrolledAgentNavigationLayout === layoutKey) {\n return;\n }\n\n if (typeof activeControl.scrollIntoView === \"function\") {\n activeControl.scrollIntoView({ block: \"nearest\", inline: \"nearest\" });\n }\n this.lastScrolledAgentNavigationLayout = layoutKey;\n }\n\n private renderButton() {\n // `.console-button` owns the launcher dimensions and publishes the same\n // number as `--cpk-launcher-size` for the signal dot's rim placement.\n // Tailwind scan tokens retained for generated-sheet stability: ease-in-out\n // ease-out\n const buttonClasses = [\n \"console-button\",\n \"group\",\n \"relative\",\n \"pointer-events-auto\",\n \"inline-flex\",\n // Kept as Tailwind scan tokens so the generated sheet stays stable;\n // the later `.console-button` rule owns the responsive dimensions.\n \"h-9\",\n \"w-9\",\n \"items-center\",\n \"justify-center\",\n \"rounded-full\",\n \"border\",\n \"text-xs\",\n \"font-medium\",\n \"text-white\",\n \"focus-visible:outline\",\n \"focus-visible:outline-2\",\n \"focus-visible:outline-offset-2\",\n \"focus-visible:outline-[#BEC2FF]\",\n \"touch-none\",\n \"select-none\",\n this.isDragging ? \"cursor-grabbing\" : \"cursor-pointer\",\n ].join(\" \");\n\n // One dot, and the highest-priority armed signal owns it. Everything the\n // launcher paints comes from that signal's description.\n const activeSignal = this.getActiveLauncherSignal();\n const signal = activeSignal ? LAUNCHER_SIGNALS[activeSignal] : null;\n const signalStyles = signal\n ? {\n \"--cpk-launcher-signal\": LAUNCHER_SIGNAL_COLORS[signal.tone],\n \"--cpk-launcher-cadence\": `${signal.cadence}ms`,\n }\n : {};\n\n return html`\n <div\n class=\"console-button-wrapper\"\n data-cpk-hud=${this.launcherHudOpen ? \"open\" : \"closed\"}\n @pointerenter=${this.handleLauncherHudEnter}\n @pointerleave=${this.handleLauncherHudLeave}\n @focusin=${this.handleLauncherHudFocusIn}\n @focusout=${this.handleLauncherHudFocusOut}\n @keydown=${this.handleLauncherHudKeydown}\n >\n ${this.renderLauncherPill()}\n <button\n class=${buttonClasses}\n type=\"button\"\n aria-expanded=${this.launcherHudOpen ? \"true\" : \"false\"}\n aria-controls=${this.launcherHudOpen ? \"cpk-launcher-hud\" : nothing}\n aria-label=${\n // The dot is decorative and hidden from assistive technology, and\n // the accessible signal for an announcement lives on its\n // navigation entry. A broken setup has no such entry until the\n // panel is open, so the launcher itself has to name the failure\n // class — otherwise a screen-reader user is the only user with no\n // signal outside the panel.\n signal && signal.tone === \"error\"\n ? `${LAUNCHER_BASE_LABEL}, ${signal.accessibleLabel}`\n : LAUNCHER_BASE_LABEL\n }\n title=${HUD_INSPECTOR_LABEL}\n data-drag-context=\"button\"\n data-cpk-signal=${signal ? signal.tone : nothing}\n data-cpk-signal-pulsing=${\n activeSignal !== null && this.pulsingSignal === activeSignal\n ? \"true\"\n : nothing\n }\n style=${styleMap(signalStyles)}\n data-dragging=${\n this.isDragging && this.pointerContext === \"button\"\n ? \"true\"\n : \"false\"\n }\n @pointerdown=${this.handlePointerDown}\n @pointermove=${this.handlePointerMove}\n @pointerup=${this.handlePointerUp}\n @pointercancel=${this.handlePointerCancel}\n @click=${this.handleButtonClick}\n >\n <img\n src=${inspectorLogoKiteUrl}\n alt=\"Inspector logo\"\n class=\"cpk-launcher-mark h-6 w-auto\"\n loading=\"lazy\"\n />\n ${\n // Purely decorative: the button is the target, it carries the\n // stable hover hint and the accessible name, and an unread\n // announcement is announced by its navigation entry, which is\n // where a keyboard user arrives.\n activeSignal !== null\n ? html`<span\n class=\"cpk-launcher-signal-wash\"\n aria-hidden=\"true\"\n ></span>\n <span\n class=\"cpk-launcher-signal-dot\"\n data-cpk-signal-dot=${activeSignal}\n aria-hidden=\"true\"\n ></span>`\n : nothing\n }\n </button>\n ${\n // The pill is a sighted-only surface, so the failure is also spoken\n // once per outage — otherwise the reader who was given the failure\n // class in the launcher's accessible name in the companion change is\n // excluded again, since a changed name is only read on focus.\n //\n // POLITE, never assertive. Speech is serial: it occupies the channel\n // the reader is using to operate their own software, and interrupting\n // that mid-sentence is out of the question for a development tool.\n //\n // It is rendered whenever the launcher is, empty and with no visual\n // footprint, because a live region has to exist on the page before\n // its content lands to be announced reliably.\n html`<span\n class=\"sr-only\"\n data-cpk-launcher-announcement\n role=\"status\"\n aria-live=\"polite\"\n >${this.getGestureLabel() ?? \"\"}</span\n >`\n }\n ${this.renderLauncherHud()}\n </div>\n `;\n }\n\n /**\n * The words the running gesture carries, or null when the launcher is quiet.\n *\n * Read from the signal's own description rather than from a condition on the\n * tone, so a third signal can carry a pill by declaring a label.\n */\n private getGestureLabel(): string | null {\n if (this.gestureSignal === null) return null;\n return LAUNCHER_SIGNALS[this.gestureSignal].pillLabel ?? null;\n }\n\n /**\n * The pill, laid out at its full width and clipped, for the whole gesture.\n *\n * It renders from the first frame of the beat — clipped to nothing, so it\n * shows nothing — because the room it needs cannot be measured until it has\n * been laid out, and the direction is decided at gesture start.\n */\n private renderLauncherPill(): TemplateResult | typeof nothing {\n const key = this.gestureSignal;\n if (key === null || this.pillPhase === null) return nothing;\n const signal = LAUNCHER_SIGNALS[key];\n const label = signal.pillLabel;\n if (label === undefined) return nothing;\n return html`\n <span\n class=\"cpk-launcher-pill\"\n data-cpk-launcher-pill=${key}\n data-cpk-pill-phase=${this.pillPhase}\n data-cpk-pill-direction=${\n // Before the measurement the pill is laid out as if it were opening\n // left, which is width-identical to the other side and shows nothing\n // either way while the clip is closed.\n this.pillDirection ?? \"left\"\n }\n style=${styleMap({\n \"--cpk-launcher-signal\": LAUNCHER_SIGNAL_COLORS[signal.tone],\n \"--cpk-launcher-pill-open\": `${ERROR_GESTURE_MS.open}ms`,\n \"--cpk-launcher-pill-close\": `${ERROR_GESTURE_MS.close}ms`,\n })}\n aria-hidden=\"true\"\n @click=${this.handlePillClick}\n >\n <span class=\"cpk-launcher-pill__heading\" data-cpk-pill-heading\n >${label}</span\n >\n <span class=\"cpk-launcher-pill__subline\" data-cpk-pill-subline\n >${PILL_SUBLINE_LABEL}</span\n >\n </span>\n `;\n }\n\n /**\n * A click on the pill opens the Inspector, exactly as pressing the mark\n * does — reusing the launcher's own open source, so the telemetry catalogue\n * is untouched and the two paths cannot be told apart downstream.\n *\n * Deliberately NOT focusable and deliberately not in the tab order: the\n * launcher beside it is already a focusable control for this same action,\n * and a second tab stop for one action is a regression. The pill stays\n * `aria-hidden` and this handler is a pointer affordance only.\n *\n * The gesture ends with the open, because `openInspector` cancels the tail —\n * the panel is over the launcher, so there is nothing left to reveal.\n */\n private handlePillClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.openInspector(\"floating_button\");\n };\n\n /** Whether a persisted temporary dismissal is still active. */\n private get isInspectorDismissed(): boolean {\n return (\n this.inspectorDismissedUntil !== null &&\n this.inspectorDismissedUntil > Date.now()\n );\n }\n\n /** Cancel the timer that restores Inspector after a temporary dismissal. */\n private clearInspectorDismissalTimer(): void {\n if (this.inspectorDismissalTimer === null) return;\n clearTimeout(this.inspectorDismissalTimer);\n this.inspectorDismissalTimer = null;\n }\n\n /** Schedule Inspector to return just after its persisted deadline. */\n private scheduleInspectorDismissalExpiry(): void {\n this.clearInspectorDismissalTimer();\n if (this.inspectorDismissedUntil === null) return;\n const delay = Math.max(0, this.inspectorDismissedUntil - Date.now() + 25);\n this.inspectorDismissalTimer = setTimeout(() => {\n this.inspectorDismissalTimer = null;\n this.refreshInspectorDismissalState();\n }, delay);\n }\n\n /** Reconcile this tab with host-scoped dismissal state from other ports. */\n private refreshInspectorDismissalState(): void {\n const hadDismissal = this.inspectorDismissedUntil !== null;\n this.inspectorDismissedUntil = loadInspectorDismissedUntil();\n this.clearInspectorDismissalTimer();\n\n if (this.inspectorDismissedUntil !== null) {\n this.closePopOut();\n this.closeInspector();\n this.scheduleInspectorDismissalExpiry();\n if (!hadDismissal) this.requestUpdate();\n return;\n }\n\n if (!hadDismissal || !this.isConnected) return;\n this.ensureAnnouncementLoading();\n this.requestUpdate();\n void this.updateComplete.then(() => {\n if (!this.isConnected || this.isInspectorDismissed) return;\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n this.scheduleLauncherHudIntro();\n this.flushPendingSignalPulse();\n });\n }\n\n /** Hide Inspector for a supported duration and persist it for this host. */\n private dismissInspectorFor(duration: InspectorDismissalDuration): void {\n const now = Date.now();\n const until = now + INSPECTOR_DISMISSAL_MS[duration];\n saveInspectorDismissedUntil(until, now);\n this.inspectorDismissedUntil = until;\n this.scheduleInspectorDismissalExpiry();\n this.settingsOpen = false;\n this.closeLauncherHud();\n this.stopSignalPulse();\n this.cancelGestureTail();\n this.cancelLauncherHudIntro();\n this.closePopOut();\n\n if (this.isOpen) {\n this.closeInspector();\n return;\n }\n\n this.persistState();\n this.requestUpdate();\n }\n\n private isLauncherHudBlocked(): boolean {\n return this.gestureSignal !== null || this.isInspectorDismissed;\n }\n\n private scheduleLauncherHudIntro(\n delay: number = LAUNCHER_HUD_INTRO_MS.delay,\n ): void {\n if (this.isInspectorDismissed) return;\n if (this.launcherHudIntroStartTimer !== null) {\n clearTimeout(this.launcherHudIntroStartTimer);\n }\n this.launcherHudIntroStartTimer = setTimeout(() => {\n this.launcherHudIntroStartTimer = null;\n if (!this.isConnected || this.isOpen || this.isInspectorDismissed) return;\n if (this.isLauncherHudBlocked()) {\n this.scheduleLauncherHudIntro(LAUNCHER_HUD_INTRO_MS.blockedRetry);\n return;\n }\n\n this.resolveLauncherHudSide();\n this.launcherHudIntro = true;\n this.launcherHudOpen = true;\n void this.refreshLearningSnapshot({ preserve: true });\n this.requestUpdate();\n this.launcherHudIntroEndTimer = setTimeout(() => {\n this.launcherHudIntroEndTimer = null;\n this.launcherHudIntro = false;\n this.launcherHudOpen = false;\n this.requestUpdate();\n }, LAUNCHER_HUD_INTRO_MS.duration);\n }, delay);\n }\n\n private cancelLauncherHudIntro(): void {\n if (this.launcherHudIntroStartTimer !== null) {\n clearTimeout(this.launcherHudIntroStartTimer);\n this.launcherHudIntroStartTimer = null;\n }\n if (this.launcherHudIntroEndTimer !== null) {\n clearTimeout(this.launcherHudIntroEndTimer);\n this.launcherHudIntroEndTimer = null;\n }\n if (!this.launcherHudIntro) return;\n this.launcherHudIntro = false;\n if (this.isConnected) {\n this.requestUpdate();\n }\n }\n\n private resolveLauncherHudSide(): void {\n if (typeof window === \"undefined\") {\n this.launcherHudSide = \"left\";\n return;\n }\n const button =\n this.activeRoot.querySelector<HTMLElement>(\".console-button\");\n if (!button) {\n this.launcherHudSide = \"left\";\n return;\n }\n const mark = button.getBoundingClientRect();\n if (mark.left - LAUNCHER_HUD_WIDTH >= EDGE_MARGIN) {\n this.launcherHudSide = \"left\";\n return;\n }\n this.launcherHudSide = \"right\";\n }\n\n private openLauncherHud(): void {\n if (this.isLauncherHudBlocked() || this.isOpen) return;\n this.resolveLauncherHudSide();\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n this.launcherHudCloseTimer = null;\n }\n if (this.launcherHudOpen) return;\n this.launcherHudOpen = true;\n void this.refreshLearningSnapshot({ preserve: true });\n this.requestUpdate();\n }\n\n private closeLauncherHud(): void {\n this.cancelLauncherHudIntro();\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n this.launcherHudCloseTimer = null;\n }\n if (!this.launcherHudOpen) return;\n this.launcherHudOpen = false;\n this.requestUpdate();\n }\n\n private handleLauncherHudEnter = (): void => {\n this.cancelLauncherHudIntro();\n this.openLauncherHud();\n };\n\n private handleLauncherHudLeave = (): void => {\n if (this.launcherHudCloseTimer !== null) {\n clearTimeout(this.launcherHudCloseTimer);\n }\n this.launcherHudCloseTimer = setTimeout(() => {\n this.launcherHudCloseTimer = null;\n this.closeLauncherHud();\n }, 160);\n };\n\n private handleLauncherHudFocusIn = (): void => {\n this.cancelLauncherHudIntro();\n this.openLauncherHud();\n };\n\n private handleLauncherHudFocusOut = (event: FocusEvent): void => {\n const next = event.relatedTarget;\n const wrapper = event.currentTarget;\n if (\n next instanceof Node &&\n wrapper instanceof Node &&\n wrapper.contains(next)\n ) {\n return;\n }\n this.closeLauncherHud();\n };\n\n private handleLauncherHudKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"Escape\") return;\n if (!this.launcherHudOpen) return;\n event.preventDefault();\n event.stopPropagation();\n this.closeLauncherHud();\n this.activeRoot\n .querySelector<HTMLButtonElement>(\".console-button\")\n ?.focus();\n };\n\n private handleHudActionClick = (\n event: Event,\n row: LauncherHudRowId,\n ): void => {\n event.preventDefault();\n event.stopPropagation();\n this.hudLandingMenu =\n row === \"threads\" ? \"threads\" : row === \"learning\" ? \"memories\" : \"home\";\n this.closeLauncherHud();\n this.openInspector(\"floating_button\");\n };\n\n private handleHudRowClick = (event: Event, row: LauncherHudRowId): void => {\n const target = event.target;\n if (\n target instanceof Element &&\n target.closest(\".cpk-launcher-hud__controls, [data-cpk-hud-action]\")\n ) {\n return;\n }\n this.handleHudActionClick(event, row);\n };\n\n private handleHudNewsClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.hudLandingMenu = WHATS_NEW_MENU_KEY;\n this.closeLauncherHud();\n this.openInspector(\"floating_button\");\n };\n\n private handleHudNewsDismissClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.clearNewsSignal();\n this.activeRoot\n .querySelector<HTMLButtonElement>(\".console-button\")\n ?.focus({ preventScroll: true });\n };\n\n /** Apply the launcher HUD's one-day dismissal without opening Inspector. */\n private handleHudDismissDayClick = (event: Event): void => {\n event.preventDefault();\n event.stopPropagation();\n this.dismissInspectorFor(\"day\");\n };\n\n private getUnreadAnnouncementTitle(): string | null {\n if (!this.newsSignalArmed || !this.announcementLoaded) return null;\n const title = this.announcementPreviewText?.trim() || \"New in CopilotKit\";\n const titleCharacters = Array.from(title);\n return titleCharacters.length > HUD_ANNOUNCEMENT_TITLE_LIMIT\n ? `${titleCharacters\n .slice(0, HUD_ANNOUNCEMENT_TITLE_LIMIT)\n .join(\"\")\n .trimEnd()}...`\n : title;\n }\n\n private renderHudRow(args: {\n id: LauncherHudRowId;\n label: string;\n icon: LucideIconName;\n connected?: boolean;\n introIndex: number;\n }): TemplateResult | typeof nothing {\n if (args.connected) return nothing;\n const detailId = `cpk-hud-detail-${args.id}`;\n return html`\n <li\n class=\"cpk-launcher-hud__row\"\n data-cpk-hud-row=${args.id}\n data-cpk-hud-action-kind=\"navigate\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n args.introIndex,\n ),\n })}\n @click=${(event: Event) => this.handleHudRowClick(event, args.id)}\n >\n <span class=\"cpk-launcher-hud__primary\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__action\"\n data-cpk-hud-action\n aria-label=${`Open ${args.label} in Inspector`}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__feature-icon\"\n data-cpk-hud-icon=${args.id}\n aria-hidden=\"true\"\n >${this.renderIcon(args.icon)}</span\n >\n <span class=\"cpk-launcher-hud__label\">${args.label}</span>\n </button>\n <span\n class=\"cpk-launcher-hud__tooltip\"\n id=${detailId}\n role=\"tooltip\"\n >${HUD_LEARN_MORE_LABEL}</span\n >\n </span>\n <span class=\"cpk-launcher-hud__controls\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__learn-more\"\n data-cpk-hud-learn-more=${args.id}\n aria-label=${`Learn more about ${args.label}`}\n aria-describedby=${detailId}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n ${this.renderIcon(\"CircleHelp\")}\n </button>\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__toggle\"\n data-cpk-hud-toggle=${args.id}\n data-enabled=${args.connected ? \"true\" : \"false\"}\n aria-label=${\n args.connected\n ? `${args.label} is enabled`\n : `Open ${args.label} in Inspector`\n }\n ?disabled=${args.connected}\n @click=${(event: Event) =>\n this.handleHudActionClick(event, args.id)}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__toggle-track\"\n aria-hidden=\"true\"\n ></span>\n </button>\n </span>\n </li>\n `;\n }\n\n private renderLauncherHud(): TemplateResult | typeof nothing {\n if (!this.launcherHudOpen) return nothing;\n // The launcher must agree with Home about feature availability. Raw\n // transport flags can be present for a runtime that is not entitled to use\n // Intelligence, which previously made the HUD show every service as on.\n const homeModel = this.getHomeModel();\n const threadsOn = homeModel.services.some(\n (service) => service.id === \"threads\" && service.enabled,\n );\n const learningOn = homeModel.services.some(\n (service) => service.id === \"memory\" && service.enabled,\n );\n const announcementTitle = this.getUnreadAnnouncementTitle();\n const featureBlockIntroIndex = announcementTitle ? 1 : 0;\n const dismissOnly = !announcementTitle && threadsOn && learningOn;\n return html`\n <div\n class=\"cpk-launcher-hud\"\n id=\"cpk-launcher-hud\"\n data-cpk-launcher-hud\n ?data-cpk-hud-dismiss-only=${dismissOnly}\n data-cpk-hud-side=${this.launcherHudSide}\n data-cpk-hud-vertical=${this.contextState.button.anchor.vertical}\n data-cpk-hud-intro=${this.launcherHudIntro ? \"true\" : nothing}\n data-color-scheme=${this.colorScheme}\n style=${styleMap({\n \"--cpk-launcher-hud-intro-duration\": `${LAUNCHER_HUD_INTRO_MS.duration}ms`,\n \"--cpk-launcher-hud-waterfall-duration\": `${LAUNCHER_HUD_INTRO_MS.waterfallDuration}ms`,\n })}\n >\n ${\n dismissOnly\n ? nothing\n : html`\n <span class=\"cpk-launcher-hud__arrow\" aria-hidden=\"true\"></span>\n `\n }\n <div class=\"cpk-launcher-hud__card\">\n ${\n announcementTitle\n ? html`\n <div\n class=\"cpk-launcher-hud__masthead\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(0),\n })}\n >\n <div class=\"cpk-launcher-hud__news-wrap\">\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__news\"\n data-cpk-hud-news\n aria-label=${`Open new notification: ${announcementTitle}`}\n @click=${this.handleHudNewsClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span\n class=\"cpk-launcher-hud__news-label\"\n data-cpk-hud-news-label\n aria-hidden=\"true\"\n >New</span\n >\n <span class=\"cpk-launcher-hud__news-title\"\n >${announcementTitle}</span\n >\n </button>\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__news-dismiss\"\n data-cpk-hud-news-dismiss\n aria-label=\"Dismiss notification\"\n @click=${this.handleHudNewsDismissClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n ${this.renderIcon(\"X\")}\n </button>\n </div>\n </div>\n `\n : nothing\n }\n ${\n threadsOn && learningOn\n ? nothing\n : html`\n <ul\n class=\"cpk-launcher-hud__list cpk-launcher-hud__feature-list\"\n role=\"list\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n featureBlockIntroIndex,\n ),\n })}\n >\n ${this.renderHudRow({\n id: \"threads\",\n label: HUD_THREADS_LABEL,\n icon: \"MessageSquare\",\n connected: threadsOn,\n introIndex: featureBlockIntroIndex + 1,\n })}\n ${this.renderHudRow({\n id: \"learning\",\n label: HUD_LEARNING_LABEL,\n icon: \"Brain\",\n connected: learningOn,\n introIndex: featureBlockIntroIndex + (threadsOn ? 1 : 2),\n })}\n </ul>\n `\n }\n <button\n type=\"button\"\n class=\"cpk-launcher-hud__dismiss-day\"\n data-cpk-dismiss-inspector=\"day\"\n style=${styleMap({\n \"--cpk-hud-waterfall-delay\": launcherHudWaterfallDelay(\n dismissOnly\n ? 0\n : featureBlockIntroIndex +\n Number(!threadsOn) +\n Number(!learningOn) +\n 1,\n ),\n })}\n @click=${this.handleHudDismissDayClick}\n @pointerdown=${(event: Event) => event.stopPropagation()}\n >\n <span aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n Hide Inspector for a day\n </button>\n </div>\n </div>\n `;\n }\n\n /** Render a trusted action with optional context-specific copy. */\n private renderInspectorAction(\n action: InspectorMetadataAction,\n placement: \"threads-footer\" | \"locked\",\n displayLabel:\n | InspectorMetadataAction[\"label\"]\n | \"Upgrade Your Plan\" = action.label,\n ) {\n const actionIntent =\n displayLabel === \"Upgrade Your Plan\" ? \"upgrade\" : undefined;\n return html`\n <a\n data-inspector-action-placement=${placement}\n data-inspector-action-intent=${actionIntent ?? nothing}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${displayLabel} (opens in a new tab)\"\n style=${\n placement === \"threads-footer\"\n ? \"\"\n : \"display:inline-flex;min-height:34px;align-items:center;justify-content:center;gap:6px;border:1px solid #dbdbe5;border-radius:7px;background:#ffffff;padding:8px 12px;color:#57575b;font-size:12px;font-weight:600;text-decoration:none;outline-style:solid;outline-width:2px;outline-color:transparent;outline-offset:2px;cursor:pointer;\"\n }\n @click=${() =>\n this.handleInspectorMetadataActionClick(action, placement)}\n >\n ${displayLabel}\n </a>\n `;\n }\n\n private renderInspectorSidebar(\n iconRail: boolean,\n automaticallyCollapsed: boolean,\n agentSelector: TemplateResult | typeof nothing,\n ) {\n const homeModel = this.getHomeModel();\n return html`\n <aside\n class=\"inspector-sidebar\"\n data-icon-rail=${iconRail ? \"true\" : \"false\"}\n >\n ${\n iconRail && this.sidebarRailTooltip\n ? html`\n <span\n class=\"inspector-sidebar-rail-tooltip\"\n role=\"tooltip\"\n style=${`top: ${this.sidebarRailTooltip.top}px`}\n >${this.sidebarRailTooltip.label}</span\n >\n `\n : nothing\n }\n <div\n class=\"inspector-sidebar-agent-scope\"\n data-inspector-sidebar-agent-selector\n >\n <div class=\"inspector-agent-selector\">${agentSelector}</div>\n </div>\n <nav class=\"inspector-sidebar-nav\" aria-label=\"Inspector\">\n ${INSPECTOR_NAV_SECTIONS.map(({ group, label }) => {\n const items = this.getVisibleMenuItemsForGroup(group);\n if (items.length === 0) {\n return nothing;\n }\n return html`\n <div\n class=\"inspector-sidebar-section\"\n data-inspector-section=${group}\n >\n ${\n label\n ? html`<button\n type=\"button\"\n class=\"inspector-sidebar-label\"\n data-inspector-group=${group}\n aria-label=${label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleGroupSelect(group)}\n >\n ${label}\n </button>`\n : nothing\n }\n ${items.map((item) => {\n const isSelected = this.selectedMenu === item.key;\n const marker = this.getNavigationSignalFor(item.key);\n return html`\n <button\n type=\"button\"\n class=\"inspector-nav-control inspector-sidebar-control ${\n isSelected ? \"inspector-nav-control-active\" : \"\"\n }\"\n data-inspector-group=${group}\n data-inspector-menu-key=${item.key}\n aria-current=${isSelected ? \"page\" : nothing}\n aria-label=${\n marker\n ? `${item.label}, ${marker.accessibleLabel}`\n : item.label\n }\n data-inspector-tooltip=${item.label}\n title=${iconRail ? nothing : item.label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerenter=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @pointerleave=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @focus=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @blur=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @click=${() => this.handleMenuSelect(item.key)}\n >\n <span class=\"inspector-nav-icon\" aria-hidden=\"true\">\n ${\n item.key === \"threads\"\n ? unsafeHTML(this.customTabIcons.threads)\n : this.renderIcon(item.icon)\n }\n </span>\n <span class=\"inspector-nav-label\">${item.label}</span>\n ${\n marker\n ? html`\n <span\n class=\"inspector-nav-signal-dot\"\n data-cpk-signal-tone=${marker.tone}\n aria-hidden=\"true\"\n ></span>\n `\n : nothing\n }\n </button>\n `;\n })}\n </div>\n `;\n })}\n </nav>\n ${\n automaticallyCollapsed\n ? nothing\n : html`\n <div class=\"inspector-sidebar-footer\">\n ${\n iconRail\n ? nothing\n : html`\n <div class=\"inspector-sidebar-status-list\">\n ${this.renderSidebarIntelligenceStatus(homeModel)}\n </div>\n `\n }\n <button\n type=\"button\"\n class=\"inspector-sidebar-toggle\"\n data-inspector-sidebar-toggle\n aria-label=${iconRail ? \"Expand sidebar\" : \"Collapse sidebar\"}\n aria-expanded=${iconRail ? \"false\" : \"true\"}\n data-inspector-tooltip=${\n iconRail ? \"Expand sidebar\" : nothing\n }\n title=${iconRail ? nothing : \"Collapse sidebar\"}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerenter=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @pointerleave=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @focus=${\n iconRail ? this.handleSidebarRailTooltipShow : nothing\n }\n @blur=${\n iconRail ? this.handleSidebarRailTooltipHide : nothing\n }\n @click=${this.handleSidebarToggle}\n >\n <span class=\"inspector-nav-icon\" aria-hidden=\"true\">\n ${this.renderIcon(\n iconRail ? \"ChevronRight\" : \"ChevronLeft\",\n )}\n </span>\n <span class=\"inspector-nav-label\"\n >${iconRail ? \"Expand\" : \"Collapse\"}</span\n >\n </button>\n </div>\n `\n }\n </aside>\n `;\n }\n\n private renderSidebarIntelligenceStatus(model: HomeModel) {\n const connected = model.hero.connection === \"connected\";\n const organizationName = model.project?.organizationName;\n const planLabel = model.project?.planLabel;\n const action = model.hero.action;\n const renewing = action?.kind === \"renew\";\n if (!connected && action) {\n const stateLabel = renewing\n ? \"Intelligence plan expired\"\n : \"Intelligence is off\";\n const setupLabel = renewing\n ? \"Renew to restore access\"\n : \"Connect Intelligence\";\n return html`\n <a\n class=\"inspector-sidebar-status-card inspector-sidebar-intelligence inspector-sidebar-intelligence-setup\"\n data-inspector-sidebar-intelligence\n data-inspector-sidebar-intelligence-action=${action.kind}\n data-state=\"disconnected\"\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} to enable Rich Threads and Automatic Learning (opens in a new tab)\"\n title=${action.label}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n <span class=\"inspector-sidebar-status-copy\">\n <strong>${stateLabel}</strong>\n <span>${setupLabel}</span>\n </span>\n <span class=\"inspector-sidebar-setup-arrow\" aria-hidden=\"true\">\n ${this.renderIcon(\"ArrowUpRight\")}\n </span>\n </a>\n `;\n }\n\n const primaryLabel = connected\n ? (organizationName ?? \"Intelligence\")\n : \"Intelligence unavailable\";\n const secondaryLabel = connected\n ? planLabel\n ? `${planLabel} plan`\n : \"Connected\"\n : \"Rich Threads and Automatic Learning are off\";\n const label = connected\n ? `${primaryLabel}, ${secondaryLabel}, Intelligence connected`\n : \"Connect Intelligence\";\n const actionLabel = action?.label;\n const description = connected\n ? `${secondaryLabel} · Intelligence connected`\n : \"Rich Threads and Automatic Learning need Intelligence.\";\n return html`\n <section\n class=\"inspector-sidebar-status-card inspector-sidebar-intelligence\"\n data-inspector-sidebar-intelligence\n data-state=${connected ? \"connected\" : \"disconnected\"}\n aria-label=${label}\n title=${description}\n >\n <span class=\"inspector-sidebar-status-copy\">\n <strong>${primaryLabel}</strong>\n <span>${secondaryLabel}</span>\n </span>\n ${\n action\n ? html`\n <a\n class=\"inspector-sidebar-status-action\"\n data-inspector-sidebar-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${actionLabel} (opens in a new tab)\"\n title=${actionLabel}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n <span class=\"inspector-sidebar-status-action-label\"\n >${actionLabel}</span\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"ArrowUpRight\")}</span\n >\n </a>\n `\n : nothing\n }\n </section>\n `;\n }\n\n private handleSidebarToggle = (): void => {\n this.sidebarRailTooltip = null;\n this.sidebarCollapsed = !this.sidebarCollapsed;\n this.persistState();\n this.requestUpdate();\n };\n\n private handleSidebarRailTooltipShow = (event: Event): void => {\n const target = event.currentTarget;\n if (!(target instanceof HTMLElement)) {\n return;\n }\n\n const label = target.dataset.inspectorTooltip;\n const sidebar = target.closest<HTMLElement>(\".inspector-sidebar\");\n if (!label || !sidebar) {\n return;\n }\n\n const targetBounds = target.getBoundingClientRect();\n const sidebarBounds = sidebar.getBoundingClientRect();\n this.sidebarRailTooltip = {\n label,\n top: targetBounds.top - sidebarBounds.top + targetBounds.height / 2,\n };\n this.requestUpdate();\n };\n\n private handleSidebarRailTooltipHide = (): void => {\n if (this.sidebarRailTooltip === null) {\n return;\n }\n this.sidebarRailTooltip = null;\n this.requestUpdate();\n };\n\n private handleColorSchemeToggle = (): void => {\n this.colorScheme = this.colorScheme === \"light\" ? \"dark\" : \"light\";\n this.hasExplicitColorScheme = true;\n this.persistState();\n this.requestUpdate();\n };\n\n private getHomeModel(): HomeModel {\n const lastRuntimeEvent = this.flattenedEvents[0];\n return buildHomeModel({\n intelligenceConnected: Boolean(this._core?.intelligence),\n threadsAvailable: this.areThreadEndpointsAvailable(),\n metadata: this.inspectorMetadataProjection,\n runtimeUrl: this._core?.runtimeUrl,\n runtimeConnectionState: this.getCoreStatusSummary().state,\n lastRuntimeEvent: lastRuntimeEvent\n ? {\n id: lastRuntimeEvent.id,\n agentId: lastRuntimeEvent.agentId,\n type: lastRuntimeEvent.type,\n timestamp: lastRuntimeEvent.timestamp,\n }\n : undefined,\n // A capability advertises the endpoint, not a configured Learning\n // container. Use its successful snapshot for Home and launcher status.\n learningOn:\n this.learningSupported &&\n this.learningError === null &&\n this.learningSnapshot?.configuration.state === \"configured\",\n a2uiOn: this._core?.a2uiEnabled === true,\n openGenUiOn: this._core?.openGenerativeUIEnabled === true,\n suggestionsOn: this._core?.suggestions === true,\n audioOn: this._core?.audioFileTranscriptionEnabled === true,\n websocketUrl: this._core?.intelligence?.wsUrl,\n announcementPreviewText: this.announcementPreviewText ?? undefined,\n announcementMarkdown: this.announcementMarkdown ?? undefined,\n announcementHtml: this.announcementHtml ?? undefined,\n intelligenceSignupUrl: this.getIntelligenceSignupUrl(),\n });\n }\n\n private renderHomeView() {\n const model = this.getHomeModel();\n const connected = model.hero.connection === \"connected\";\n return html`\n <div\n class=\"inspector-home\"\n data-inspector-home\n data-inspector-home-state=${connected ? \"connected\" : \"disconnected\"}\n >\n ${this.renderHomeWhatsNewPreview(model.news)}\n ${this.renderHomeSystemHealth(model)}\n ${this.renderHomeIntelligenceHud(model)}\n ${this.renderHomeFeatures(model)}\n </div>\n `;\n }\n\n private renderHomeWhatsNewPreview(news: HomeModel[\"news\"]) {\n const unread = this.newsSignalArmed && this.announcementLoaded;\n if (news.empty || !unread) {\n return nothing;\n }\n\n return html`\n <section\n class=\"inspector-whats-new-preview\"\n data-inspector-home-band=\"news\"\n data-unread=\"true\"\n role=\"note\"\n aria-label=\"New CopilotKit update\"\n >\n <button\n type=\"button\"\n class=\"inspector-whats-new-preview-body\"\n data-inspector-whats-new-preview\n aria-label=\"Open What's New\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleMenuSelect(WHATS_NEW_MENU_KEY)}\n >\n <span class=\"inspector-whats-new-preview-copy\">\n <span class=\"inspector-whats-new-preview-title\">\n <span class=\"inspector-home-story-unread\">New</span>\n <strong>${news.title}</strong>\n </span>\n <span>${news.previewText}</span>\n </span>\n <span class=\"inspector-whats-new-preview-action\">\n View update ${this.renderIcon(\"ArrowRight\")}\n </span>\n </button>\n </section>\n `;\n }\n\n private renderWhatsNewView() {\n const state = this.getWhatsNewState();\n const news = this.getHomeModel().news;\n const updatedAt = this.announcementTimestamp\n ? new Date(this.announcementTimestamp)\n : null;\n const updatedLabel =\n updatedAt && !Number.isNaN(updatedAt.getTime())\n ? new Intl.DateTimeFormat(undefined, {\n month: \"long\",\n day: \"numeric\",\n year: \"numeric\",\n }).format(updatedAt)\n : null;\n return html`\n <div\n class=\"inspector-home inspector-whats-new\"\n data-inspector-whats-new\n data-cpk-whats-new\n data-cpk-whats-new-state=${state}\n >\n <header class=\"inspector-whats-new-header\">\n <h1 class=\"inspector-home-title\">What's New</h1>\n ${\n updatedLabel\n ? html`\n <p class=\"inspector-whats-new-updated\">\n Updated\n <time datetime=${updatedAt?.toISOString()}\n >${updatedLabel}</time\n >\n </p>\n `\n : nothing\n }\n </header>\n <section class=\"inspector-home-news\" aria-label=\"CopilotKit updates\">\n ${\n news.empty || !news.documentHtml\n ? html`\n <article class=\"inspector-whats-new-empty\">\n <h2 class=\"inspector-home-card-title\">${news.title}</h2>\n <p class=\"inspector-home-card-copy\">${news.previewText}</p>\n </article>\n `\n : html`\n <article class=\"inspector-whats-new-document\">\n <div\n class=\"announcement-content\"\n @click=${this.handleAnnouncementContentClick}\n >\n ${unsafeHTML(news.documentHtml)}\n </div>\n </article>\n `\n }\n </section>\n </div>\n `;\n }\n\n private renderHomeIntelligenceHud(model: HomeModel) {\n const project = model.project;\n const connected = model.hero.connection === \"connected\";\n const action = model.hero.action;\n const renewing = action?.kind === \"renew\";\n // Three distinct jobs, not two. A lapsed plan needs a renewal link, not an\n // install prompt and an explainer — that developer already knows what\n // Intelligence is. Only the never-connected case gets the full pitch.\n const installing = !connected && !renewing;\n return html`\n <section\n class=\"inspector-home-section inspector-intelligence-hud\"\n data-inspector-home-card=\"intelligence\"\n data-state=${connected ? \"connected\" : \"disconnected\"}\n data-mode=${connected ? \"connected\" : renewing ? \"renew\" : \"install\"}\n aria-label=\"Intelligence ${\n connected ? \"connected\" : renewing ? \"plan expired\" : \"not enabled\"\n }\"\n >\n <header class=\"inspector-intelligence-hud-header\">\n <div class=\"inspector-intelligence-hud-heading\">\n <h2 class=\"inspector-home-section-title\">\n ${\n // The brand mark makes this read as a product lockup rather\n // than another status heading. Inside the h2 so it stays on\n // the same line, with an empty alt so the accessible name is\n // still just the product's name.\n installing\n ? html`\n <img\n class=\"inspector-intelligence-mark\"\n src=${inspectorLogoKiteUrl}\n alt=\"\"\n aria-hidden=\"true\"\n />\n `\n : nothing\n }\n ${connected ? \"Intelligence\" : model.hero.title}\n </h2>\n ${\n connected\n ? nothing\n : installing\n ? html`\n <p class=\"inspector-intelligence-sr-summary\">\n ${model.hero.body}\n </p>\n `\n : html`\n <p class=\"inspector-intelligence-hud-description\">\n ${model.hero.body}\n </p>\n `\n }\n </div>\n <div class=\"inspector-intelligence-hud-header-actions\">\n ${\n connected || renewing\n ? html`\n <span\n class=\"inspector-intelligence-hud-state\"\n data-tone=${connected ? \"success\" : \"checking\"}\n >\n <span aria-hidden=\"true\"></span>\n ${connected ? \"Connected\" : \"Plan expired\"}\n </span>\n `\n : nothing\n }\n ${\n renewing && action\n ? html`\n <a\n class=\"inspector-intelligence-hud-action inspector-intelligence-hud-connect-action\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n ${action.label} ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n }\n ${\n installing\n ? this.renderIntelligenceInstallActions(action)\n : nothing\n }\n </div>\n </header>\n\n ${\n // Exceptional state, so it gets its own full-width strip between the\n // bands rather than being squeezed into the header's action column.\n installing && this.promptCopyState === \"failed\"\n ? html`\n <code\n class=\"inspector-intelligence-install-fallback\"\n tabindex=\"0\"\n >${createOnboardingPrompt(this.getOnboardingRunId())}</code\n >\n `\n : nothing\n }\n ${installing ? this.renderIntelligenceStory() : nothing}\n ${\n connected\n ? html`\n <div\n class=\"inspector-intelligence-hud-details\"\n role=\"group\"\n aria-label=\"Intelligence account details\"\n >\n <section\n class=\"inspector-intelligence-hud-project\"\n data-inspector-metadata=${\n model.projectLinked && project ? \"identity\" : nothing\n }\n aria-label=${\n model.projectLinked && project\n ? \"Inspector account details\"\n : nothing\n }\n >\n <span class=\"inspector-intelligence-hud-detail-label\">\n Project\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${\n model.projectLinked && project\n ? html`<span>${project.projectName}</span>`\n : \"Not linked\"\n }\n </strong>\n ${\n model.projectLinked && project\n ? html`\n <span\n class=\"inspector-intelligence-hud-detail-subvalue\"\n >\n ${project.organizationName}\n </span>\n `\n : nothing\n }\n </section>\n <section class=\"inspector-intelligence-hud-plan\">\n <div class=\"inspector-intelligence-hud-plan-summary\">\n <span class=\"inspector-intelligence-hud-detail-label\">\n Plan\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${\n project?.planLabel\n ? html`\n <span data-inspector-metadata=\"plan\">\n ${project.planLabel}\n </span>\n `\n : \"No plan\"\n }\n </strong>\n ${\n project\n ? html`\n <span\n class=\"inspector-intelligence-hud-detail-subvalue\"\n >\n License ${project.license}\n </span>\n `\n : nothing\n }\n ${\n action\n ? html`\n <a\n class=\"inspector-intelligence-hud-action inspector-intelligence-hud-plan-action\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"${action.label} (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n ${action.label} ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n }\n </div>\n <div\n class=\"inspector-intelligence-hud-usage\"\n role=\"group\"\n aria-label=\"Threads usage\"\n >\n <span class=\"inspector-intelligence-hud-detail-label\">\n Threads usage\n </span>\n <strong class=\"inspector-intelligence-hud-detail-value\">\n ${project?.usage?.limitLabel ?? \"Unavailable\"}\n </strong>\n ${\n project?.usage?.ratio !== undefined\n ? html`<span\n class=\"inspector-home-usage-bar\"\n aria-hidden=\"true\"\n ><span\n style=\"width:${Math.min(\n 100,\n Math.round(project.usage.ratio * 100),\n )}%\"\n ></span\n ></span>`\n : nothing\n }\n </div>\n </section>\n </div>\n `\n : nothing\n }\n </section>\n `;\n }\n\n private renderHomeSystemHealth(model: HomeModel) {\n const runtime = model.runtime;\n const health = runtime.health;\n const runtimeDetail = runtime.url ?? \"Runtime URL not configured\";\n const connectionDetail =\n health.liveUpdates.tone === \"success\"\n ? \"New events will appear here.\"\n : health.lastEvent.timestamp !== undefined\n ? `Last activity at ${formatTimestamp(health.lastEvent.timestamp)}`\n : \"Waiting for a connection\";\n const signals: Array<{\n id: \"runtime\" | \"connection\" | \"last-event\";\n label: string;\n value: string;\n detail: string;\n tone: HomeRuntimeHealthTone;\n eventId?: string;\n agentId?: string;\n }> = [\n {\n id: \"runtime\",\n label: \"Runtime\",\n value: health.runtime.label,\n detail: runtimeDetail,\n tone: health.runtime.tone,\n },\n {\n id: \"connection\",\n label: \"Live updates\",\n value: health.liveUpdates.label,\n detail: connectionDetail,\n tone: health.liveUpdates.tone,\n },\n {\n id: \"last-event\",\n label: \"Recent activity\",\n value: health.lastEvent.type ?? health.lastEvent.label,\n detail:\n health.lastEvent.timestamp !== undefined\n ? formatRelativeTimestamp(health.lastEvent.timestamp)\n : \"Waiting for an agent to run.\",\n tone: health.lastEvent.tone,\n eventId: health.lastEvent.id,\n agentId: health.lastEvent.agentId,\n },\n ];\n return html`\n <section\n class=\"inspector-home-section inspector-system-health-section\"\n data-inspector-home-band=\"health\"\n >\n <header\n class=\"inspector-home-section-header inspector-system-health-header\"\n >\n <div class=\"inspector-system-health-heading\">\n <h2 class=\"inspector-home-section-title\">System Health</h2>\n </div>\n <span\n class=\"inspector-system-health-state\"\n data-tone=${health.state === \"healthy\" ? \"success\" : health.state}\n >\n <span aria-hidden=\"true\"></span>\n ${health.label}\n </span>\n </header>\n <dl\n class=\"inspector-system-health\"\n aria-label=\"System Health\"\n data-inspector-home-card=\"runtime\"\n data-health-state=${health.state}\n >\n ${signals.map(\n (signal) => html`\n <div\n class=\"inspector-system-health-signal\"\n data-runtime-health-signal=${signal.id}\n data-tone=${signal.tone}\n >\n <span class=\"inspector-system-health-copy\">\n <dt>${signal.label}</dt>\n <dd title=${signal.value}>\n ${\n signal.eventId\n ? html`\n <button\n type=\"button\"\n class=\"inspector-system-health-event-link\"\n aria-label=\"View ${signal.value.toLowerCase()} in AG-UI Events\"\n @click=${() => {\n if (signal.eventId) {\n this.handleHomeLastEventSelect(\n signal.eventId,\n signal.agentId,\n );\n }\n }}\n >\n <span class=\"inspector-system-health-event-type\"\n >${signal.value}</span\n >\n <small class=\"inspector-system-health-event-meta\">\n <span>${signal.detail}</span>\n <strong>View event</strong>\n </small>\n </button>\n `\n : signal.value\n }\n </dd>\n ${\n signal.eventId\n ? null\n : signal.id === \"runtime\"\n ? html`\n <small\n class=\"inspector-system-health-url\"\n data-full-value=${runtime.url ?? signal.detail}\n aria-label=${signal.detail}\n title=${signal.detail}\n tabindex=\"0\"\n >\n <span>${signal.detail}</span>\n </small>\n `\n : html`<small\n class=\"inspector-system-health-detail\"\n title=${signal.detail}\n >${signal.detail}</small\n >`\n }\n </span>\n </div>\n `,\n )}\n </dl>\n </section>\n `;\n }\n\n private renderEventErrorBanner(key: InspectorEventErrorSource) {\n const error = this.eventErrorDetails[key];\n if (!error) return nothing;\n const guide = EVENT_ERROR_GUIDANCE[key];\n return html`\n <div\n class=\"mx-3 mt-3 flex cursor-pointer items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-3 py-2 text-left text-[11px] text-rose-950\"\n role=\"alert\"\n tabindex=\"0\"\n data-cpk-event-error=${key}\n @click=${this.refocusEventErrorLanding}\n @keydown=${this.handleEventErrorBannerKeydown}\n >\n <span class=\"mt-0.5 shrink-0\">${this.renderIcon(\"TriangleAlert\")}</span>\n <div class=\"min-w-0 flex-1 space-y-1\">\n <p class=\"font-semibold\">${guide.title}</p>\n ${error.agentId ? html`<p>Agent: ${error.agentId}</p>` : nothing}\n ${error.toolName ? html`<p>Tool: ${error.toolName}</p>` : nothing}\n <p class=\"break-words leading-relaxed\">${error.message}</p>\n ${\n guide.advice\n ? html`<p class=\"leading-relaxed\">${guide.advice}</p>`\n : nothing\n }\n ${\n guide.highlight && this.hasEventErrorHighlight(key)\n ? html`<p class=\"leading-relaxed\">${guide.highlight}</p>`\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private handleEventErrorBannerKeydown = (event: KeyboardEvent): void => {\n if (event.key !== \"Enter\" && event.key !== \" \") return;\n event.preventDefault();\n this.refocusEventErrorLanding(event);\n };\n\n /** Scroll the landing view to the failed tool call or RUN_ERROR again. */\n private refocusEventErrorLanding = (event: Event): void => {\n const key = (event.currentTarget as HTMLElement | null)?.dataset\n .cpkEventError;\n if (!key || !isEventErrorKey(key)) return;\n this.applyEventErrorLanding(key);\n this.requestUpdate();\n };\n\n private handleHomeLastEventSelect(eventId: string, agentId?: string): void {\n this.eventFilterText = \"\";\n this.eventTypeFilter = \"all\";\n this.selectedContext =\n agentId && this.contextOptions.some((option) => option.key === agentId)\n ? agentId\n : \"all-agents\";\n this.expandedRows.clear();\n this.expandedRows.add(eventId);\n this.handleMenuSelect(\"ag-ui-events\");\n\n void this.updateComplete.then(() => {\n const row = Array.from(\n this.activeRoot.querySelectorAll<HTMLElement>(\n \"[data-inspector-event-id]\",\n ),\n ).find((candidate) => candidate.dataset.inspectorEventId === eventId);\n row?.scrollIntoView?.({ block: \"center\" });\n });\n }\n\n private renderHomeFeatures(model: HomeModel) {\n const enabledServices = model.services.filter((service) => service.enabled);\n const disabledServices = model.services.filter(\n (service) => !service.enabled,\n );\n const renderService = (service: HomeModel[\"services\"][number]) => {\n const copyState =\n this.homeFeaturePromptCopyState?.serviceId === service.id\n ? this.homeFeaturePromptCopyState.state\n : \"idle\";\n const stateDescription = `${service.label} is ${\n service.enabled\n ? \"enabled in your runtime\"\n : \"not enabled in your runtime\"\n }`;\n const copyLabel =\n copyState === \"copied\"\n ? \"Copied\"\n : copyState === \"error\"\n ? \"Copy failed\"\n : \"Copy prompt\";\n const copyTitle = copyLabel;\n return html`\n <div\n class=\"inspector-home-feature\"\n data-inspector-service=${service.id}\n data-state=${service.enabled ? \"on\" : \"off\"}\n role=\"listitem\"\n >\n <span\n class=\"inspector-home-feature-status\"\n role=\"img\"\n aria-label=${stateDescription}\n title=${stateDescription}\n >\n <span aria-hidden=\"true\"></span>\n </span>\n <a\n class=\"inspector-home-feature-label\"\n data-inspector-home-feature-docs=${service.id}\n href=${this.appendRefParam(service.docsUrl, \"cpk-inspector-home\")}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Open ${service.label} documentation in a new tab\"\n >\n <span>${service.label}</span>\n <span class=\"inspector-home-feature-label-icon\" aria-hidden=\"true\"\n >${this.renderIcon(\"ArrowUpRight\")}</span\n >\n </a>\n <span class=\"inspector-home-feature-actions\">\n ${\n service.enabled\n ? nothing\n : html`\n <button\n type=\"button\"\n class=\"inspector-home-feature-action inspector-system-health-url\"\n data-inspector-home-feature-prompt=${service.id}\n data-copy-state=${copyState}\n data-full-value=${copyTitle}\n aria-label=\"${copyLabel} for ${service.label}\"\n @click=${(event: Event) =>\n this.handleHomeFeaturePromptCopy(service, event)}\n >\n <span class=\"inspector-home-feature-action-icon\" aria-hidden=\"true\"\n >${this.renderIcon(copyState === \"copied\" ? \"Check\" : \"Bot\")}</span\n >\n <span class=\"inspector-home-feature-action-label\"\n >${copyTitle}</span\n >\n </button>\n `\n }\n ${\n service.enabled\n ? nothing\n : html`\n <span class=\"sr-only\" aria-live=\"polite\">\n ${\n copyState === \"copied\"\n ? `${service.label} implementation prompt copied.`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} implementation prompt.`\n : \"\"\n }\n </span>\n `\n }\n </span>\n </div>\n `;\n };\n return html`\n <section\n class=\"inspector-home-section inspector-home-features\"\n data-inspector-home-card=\"services\"\n >\n <header class=\"inspector-home-section-header\">\n <h2 class=\"inspector-home-section-title\">Features</h2>\n <span>\n ${enabledServices.length} enabled, ${disabledServices.length} available\n </span>\n </header>\n ${\n model.services.length === 0\n ? html`\n <p class=\"inspector-home-features-empty\">\n Feature availability is unavailable for this runtime.\n </p>\n `\n : html`\n <div class=\"inspector-home-feature-groups\">\n <section\n class=\"inspector-home-feature-group\"\n data-feature-state-group=\"active\"\n aria-label=\"Enabled features\"\n >\n <header class=\"inspector-home-feature-group-header\">\n <strong>Enabled</strong>\n <span>${enabledServices.length}</span>\n </header>\n <div class=\"inspector-home-feature-list\" role=\"list\">\n ${\n enabledServices.length > 0\n ? enabledServices.map(renderService)\n : html`\n <p class=\"inspector-home-feature-group-empty\">None enabled</p>\n `\n }\n </div>\n </section>\n <section\n class=\"inspector-home-feature-group\"\n data-feature-state-group=\"available\"\n aria-label=\"Features available to add\"\n >\n <header class=\"inspector-home-feature-group-header\">\n <strong>Available to add</strong>\n <span>${disabledServices.length}</span>\n </header>\n <div class=\"inspector-home-feature-list\" role=\"list\">\n ${\n disabledServices.length > 0\n ? disabledServices.map(renderService)\n : html`\n <p class=\"inspector-home-feature-group-empty\">Everything is active</p>\n `\n }\n </div>\n </section>\n </div>\n `\n }\n </section>\n `;\n }\n\n private showHomeFeaturePromptCopyState(\n serviceId: HomeFeaturePromptId,\n state: Exclude<HomeFeaturePromptCopyState, \"idle\">,\n generation: number,\n ): void {\n if (\n !this.isConnected ||\n generation !== this.homeFeaturePromptCopyGeneration\n )\n return;\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n }\n this.homeFeaturePromptCopyState = { serviceId, state };\n this.requestUpdate();\n this.homeFeaturePromptCopyResetTimeoutId = window.setTimeout(() => {\n if (\n !this.isConnected ||\n generation !== this.homeFeaturePromptCopyGeneration\n )\n return;\n this.homeFeaturePromptCopyState = null;\n this.homeFeaturePromptCopyResetTimeoutId = null;\n this.requestUpdate();\n }, 2_000);\n }\n\n private handleHomeFeaturePromptCopy = async (\n service: HomeFeaturePromptTarget,\n event?: Event,\n ): Promise<void> => {\n const generation = (this.homeFeaturePromptCopyGeneration += 1);\n if (this.homeFeaturePromptCopyResetTimeoutId !== null) {\n window.clearTimeout(this.homeFeaturePromptCopyResetTimeoutId);\n this.homeFeaturePromptCopyResetTimeoutId = null;\n }\n this.homeFeaturePromptCopyState = null;\n this.requestUpdate();\n\n const onboardingRunId = createOnboardingRunId();\n if (!this.core?.telemetryDisabled) {\n trackHomeFeaturePromptClicked({\n feature_id: service.id,\n onboarding_run_id: onboardingRunId,\n });\n }\n\n if (\n await this.copyFeaturePromptToClipboard(service, event, onboardingRunId)\n ) {\n this.showHomeFeaturePromptCopyState(service.id, \"copied\", generation);\n } else {\n this.showHomeFeaturePromptCopyState(service.id, \"error\", generation);\n }\n };\n\n private getHomeFeaturePromptTarget(\n serviceId: HomeFeaturePromptId,\n ): HomeFeaturePromptTarget | undefined {\n return this.getHomeModel().services.find(\n (service) => service.id === serviceId,\n );\n }\n\n private renderFeatureSetupPrompt(\n serviceId: HomeFeaturePromptId,\n className: string,\n options?: Readonly<{\n copyState?: HomeFeaturePromptCopyState;\n onClick?: (event: Event) => void;\n }>,\n ): TemplateResult | typeof nothing {\n const service = this.getHomeFeaturePromptTarget(serviceId);\n if (!service) return nothing;\n const copyState =\n options?.copyState ??\n (this.homeFeaturePromptCopyState?.serviceId === service.id\n ? this.homeFeaturePromptCopyState.state\n : \"idle\");\n const label =\n copyState === \"copied\"\n ? \"Copied\"\n : copyState === \"error\"\n ? \"Copy blocked\"\n : \"Copy setup prompt\";\n return html`\n <button\n type=\"button\"\n class=${className}\n data-inspector-feature-setup-prompt=${service.id}\n data-inspector-threads-setup-prompt=${\n service.id === \"threads\" ? \"\" : nothing\n }\n data-copy-state=${copyState}\n aria-label=${\n copyState === \"copied\"\n ? `${service.label} setup prompt copied`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} setup prompt. Try again`\n : `Copy setup prompt for ${service.label}`\n }\n @click=${(event: Event) =>\n options?.onClick\n ? options.onClick(event)\n : this.handleHomeFeaturePromptCopy(service, event)}\n >\n ${this.renderIcon(copyState === \"copied\" ? \"Check\" : \"Copy\")}\n ${label}\n </button>\n <span class=\"sr-only\" aria-live=\"polite\">\n ${\n copyState === \"copied\"\n ? `${service.label} setup prompt copied.`\n : copyState === \"error\"\n ? `Could not copy the ${service.label} setup prompt.`\n : \"\"\n }\n </span>\n `;\n }\n\n private handleHomeHeroCta(action: HomeHeroAction): void {\n if (this.core?.telemetryDisabled) return;\n trackHomeCtaClicked({ action_kind: action.kind });\n }\n\n /**\n * The install row: copy the prompt, or fall back to the signup page.\n *\n * The prompt is primary and the link is secondary, which is the inversion\n * this card exists for. Leaving for a signup page is where developers drop\n * out; pasting into the editor they are already in is not.\n *\n * No third-party coding-agent logos here, unlike the Intelligence app. That\n * app is a private hosted surface; this one is a published npm package\n * embedded in other people's sites, and shipping Anthropic's and OpenAI's\n * marks inside it is a trademark call that is not ours to make quietly. The\n * helper line names the agents in text instead.\n */\n private renderIntelligenceInstallActions(action?: HomeHeroAction) {\n const copied = this.promptCopyState === \"copied\";\n const failed = this.promptCopyState === \"failed\";\n return html`\n <div\n class=\"inspector-intelligence-install\"\n data-copy-state=${this.promptCopyState}\n >\n ${\n // The two actions are two routes to the same outcome — let the coding\n // agent wire it up, or go and do it in the browser — so the\n // secondary names the alternative path rather than promising an\n // explainer. It used to read \"What Intelligence does\", which pointed\n // at intelligence.copilotkit.ai: a product and signup page, not an\n // explanation. Mis-promising a destination is a poor trade right at\n // the moment the card is asking to be trusted.\n //\n // One slot for the secondary message, and its content follows the\n // state: before the press the useful aside is the other route, after\n // it is \"where to put it\". Adding the instruction as a second row\n // instead pushed the action column past the band's 76px and shoved\n // the whole story down at the moment the developer had just acted.\n // Both are single lines, so swapping them cannot change the height.\n //\n // Secondary sits inside the row and the primary at the outer edge:\n // in a right-aligned group the filled button belongs on the outside,\n // not wedged between the heading and a link.\n this.promptCopyState === \"idle\"\n ? action\n ? html`\n <a\n class=\"inspector-intelligence-install-secondary\"\n data-inspector-home-intelligence-action=${action.kind}\n href=${action.url}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Set Intelligence up yourself (opens in a new tab)\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.handleHomeHeroCta(action)}\n >\n Set it up yourself ${this.renderIcon(\"ArrowUpRight\")}\n </a>\n `\n : nothing\n : html`\n <p\n class=\"inspector-intelligence-install-hint\"\n data-tone=${failed ? \"error\" : \"success\"}\n role=\"status\"\n >\n ${\n failed\n ? \"Clipboard blocked — copy the prompt below.\"\n : \"Paste it into your coding agent.\"\n }\n </p>\n `\n }\n <button\n type=\"button\"\n class=\"inspector-intelligence-hud-action inspector-intelligence-install-copy\"\n data-inspector-intelligence-copy-prompt\n aria-label=${\n copied\n ? \"Install prompt copied to clipboard. Paste it into your coding agent.\"\n : \"Copy the Intelligence install prompt\"\n }\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleIntelligencePromptCopy}\n >\n ${this.renderIcon(copied ? \"Check\" : \"ClipboardCopy\")}\n ${copied ? \"Prompt copied\" : \"Copy setup prompt\"}\n </button>\n </div>\n `;\n }\n\n /** One run id per element lifetime; minted on first use, never rotated. */\n private getOnboardingRunId(): string {\n this.onboardingRunId ??= createOnboardingRunId();\n return this.onboardingRunId;\n }\n\n private handleIntelligencePromptCopy = async (\n event?: Event,\n ): Promise<void> => {\n // A second press restarts the clock rather than inheriting the first\n // press's countdown.\n this.clearIntelligencePromptReset();\n const runId = this.getOnboardingRunId();\n const clipboard = this.getClipboard(event);\n let outcome: \"copied\" | \"failed\" = \"failed\";\n\n if (clipboard?.writeText) {\n try {\n await clipboard.writeText(createOnboardingPrompt(runId));\n outcome = \"copied\";\n } catch {\n outcome = \"failed\";\n }\n }\n\n if (!this.isConnected) {\n return;\n }\n\n this.promptCopyState = outcome;\n this.requestUpdate();\n\n if (outcome === \"copied\") {\n this.scheduleIntelligencePromptReset();\n }\n\n if (!this.core?.telemetryDisabled) {\n trackHomePromptCopied({ onboarding_run_id: runId, outcome });\n }\n };\n\n /**\n * Return the button and its secondary line to the idle state.\n *\n * Long enough to read six words, short enough that a developer who went to\n * their editor and came back — because the paste went somewhere wrong, or\n * the terminal is gone — finds a button that plainly invites a second press\n * rather than a spent one wearing a checkmark.\n *\n * Only the copied state resets. A failed copy has the prompt on screen for\n * manual selection, and yanking that away mid-drag would be worse than the\n * clipboard failing in the first place.\n */\n private scheduleIntelligencePromptReset(): void {\n this.clearIntelligencePromptReset();\n this.promptCopyResetTimer = setTimeout(() => {\n this.promptCopyResetTimer = null;\n if (!this.isConnected || this.promptCopyState !== \"copied\") {\n return;\n }\n this.promptCopyState = \"idle\";\n this.requestUpdate();\n }, PROMPT_COPY_RESET_MS);\n }\n\n private clearIntelligencePromptReset(): void {\n if (this.promptCopyResetTimer !== null) {\n clearTimeout(this.promptCopyResetTimer);\n this.promptCopyResetTimer = null;\n }\n }\n\n /**\n * The three-beat Intelligence story.\n *\n * Every beat is in the DOM at all times and switched by opacity, so the\n * strip never reflows and screen readers get one stable structure. The\n * caption is the live text; the beats themselves are decorative and hidden\n * from assistive tech, because reading out a mocked code listing helps\n * nobody.\n */\n /**\n * The rotating argument, paired to whatever the picture below is showing.\n *\n * Hidden from assistive tech: a sentence that replaces itself every few\n * seconds is noise in a screen reader, so the stable summary above carries\n * the message there instead. Both sentences are always in the DOM and only\n * their opacity changes, so the block cannot reflow and the card never jumps\n * height mid-loop.\n */\n /**\n * Where a slide sits relative to the one on screen.\n *\n * This is what makes the motion agree with the rail: the rail reads left to\n * right, so a slide that has not been reached yet waits to the right, and one\n * already passed leaves to the left. Deriving it from the indices rather than\n * remembering a direction means clicking backwards through the tabs animates\n * backwards for free, with no state to keep in sync. The loop's wrap from the\n * last tab to the first therefore reads as a rewind, which is what it is.\n */\n private intelligenceSlidePosition(index: number): string {\n if (index === this.intelStoryBeat) return \"active\";\n return index < this.intelStoryBeat ? \"before\" : \"after\";\n }\n\n /** Same rule, addressed by beat id, for the picture halves. */\n private intelligenceBeatPosition(beatId: string): string {\n return this.intelligenceSlidePosition(\n INTELLIGENCE_STORY_BEATS.findIndex((beat) => beat.id === beatId),\n );\n }\n\n private renderIntelligenceStoryCopy() {\n return html`\n <div\n class=\"inspector-intelligence-copy\"\n data-inspector-intelligence-copy\n data-beat=${\n INTELLIGENCE_STORY_BEATS[this.intelStoryBeat]?.id ?? \"threads\"\n }\n aria-hidden=\"true\"\n >\n ${INTELLIGENCE_STORY_BEATS.map(\n (beat, index) => html`\n <div\n class=\"inspector-intelligence-copy-slide\"\n data-beat-id=${beat.id}\n data-active=${index === this.intelStoryBeat}\n data-position=${this.intelligenceSlidePosition(index)}\n >\n <strong>${beat.lead}</strong>\n <span>${beat.support}</span>\n </div>\n `,\n )}\n </div>\n `;\n }\n\n private renderIntelligenceStory() {\n const activeBeat = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];\n return html`\n <section\n class=\"inspector-intelligence-story\"\n data-inspector-intelligence-story\n data-beat=${activeBeat?.id ?? \"threads\"}\n >\n ${this.renderIntelligenceStoryCopy()}\n <div class=\"inspector-intelligence-story-stage\" aria-hidden=\"true\">\n ${this.renderIntelligenceStoryThreads()}\n ${this.renderIntelligenceStoryLearning()}\n ${this.renderIntelligenceStorySkill()}\n ${this.renderIntelligenceStoryReuse()}\n </div>\n <div\n class=\"inspector-intelligence-story-rail\"\n role=\"tablist\"\n aria-label=\"What Intelligence adds\"\n >\n ${INTELLIGENCE_STORY_BEATS.map(\n (beat, index) => html`\n <button\n type=\"button\"\n role=\"tab\"\n class=\"inspector-intelligence-story-tab\"\n aria-selected=${index === this.intelStoryBeat}\n data-active=${index === this.intelStoryBeat}\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${() => this.pinIntelligenceStoryBeat(index)}\n >\n ${beat.label}\n </button>\n `,\n )}\n </div>\n </section>\n `;\n }\n\n /** Beat 1 — the developer's own users' conversations, one of them broken. */\n private renderIntelligenceStoryThreads() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"threads\"\n data-position=${this.intelligenceBeatPosition(\"threads\")}\n >\n <div class=\"inspector-intelligence-threads\">\n ${INTELLIGENCE_STORY_THREADS.map(\n (thread, index) => html`\n <span\n class=\"inspector-intelligence-thread\"\n data-failed=${thread.failed}\n style=\"--thread-index:${index}\"\n >\n <i></i>\n <strong>${thread.title}</strong>\n <small>${thread.meta}</small>\n </span>\n `,\n )}\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStoryLearning() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"learning\"\n data-position=${this.intelligenceBeatPosition(\"learning\")}\n >\n <div class=\"inspector-intelligence-beat-col\">\n <span class=\"inspector-intelligence-beat-label\">\n Signals from ${INTELLIGENCE_STORY_SIGNALS.length} threads\n </span>\n ${INTELLIGENCE_STORY_SIGNALS.map(\n (signal, index) => html`\n <span\n class=\"inspector-intelligence-signal\"\n style=\"--signal-index:${index}\"\n >${signal}</span\n >\n `,\n )}\n </div>\n <div class=\"inspector-intelligence-beat-flow\">\n ${this.renderIcon(\"ArrowRight\")}\n </div>\n <div class=\"inspector-intelligence-beat-col\">\n <span class=\"inspector-intelligence-beat-label\">\n Reusable pattern\n </span>\n ${INTELLIGENCE_STORY_RULES.map(\n (rule, index) => html`\n <span\n class=\"inspector-intelligence-rule\"\n style=\"--rule-index:${index}\"\n >\n <i>${this.renderIcon(\"Check\")}</i>${rule}\n </span>\n `,\n )}\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStorySkill() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"skill\"\n data-position=${this.intelligenceBeatPosition(\"skill\")}\n >\n <div class=\"inspector-intelligence-skill-file\">\n <header>\n ${this.renderIcon(\"FileText\")}\n <strong>${INTELLIGENCE_STORY_SKILL_FILE}</strong>\n <em>Pending review</em>\n </header>\n <div class=\"inspector-intelligence-skill-code\">\n <span data-line=\"1\"><b># Meeting scheduling</b></span>\n <span data-line=\"2\">When planning a meeting:</span>\n ${INTELLIGENCE_STORY_RULES.map(\n (rule, index) => html`\n <span data-line=${index + 3} style=\"--rule-index:${index}\"\n >${index + 1}. ${rule}</span\n >\n `,\n )}\n </div>\n </div>\n </div>\n `;\n }\n\n private renderIntelligenceStoryReuse() {\n return html`\n <div\n class=\"inspector-intelligence-beat\"\n data-beat-id=\"intelligence\"\n data-position=${this.intelligenceBeatPosition(\"intelligence\")}\n >\n <div class=\"inspector-intelligence-chain\">\n ${INTELLIGENCE_STORY_CHAIN.map(\n (step, index) => html`\n <span\n class=\"inspector-intelligence-chain-step\"\n style=\"--step-index:${index}\"\n >\n <i>${this.renderIcon(step.icon as LucideIconName)}</i>\n <strong>${step.name}</strong>\n <small>${step.detail}</small>\n </span>\n ${\n index === INTELLIGENCE_STORY_CHAIN.length - 1\n ? nothing\n : html`\n <span\n class=\"inspector-intelligence-chain-arrow\"\n style=\"--step-index:${index}\"\n >${this.renderIcon(\"ChevronRight\")}</span\n >\n `\n }\n `,\n )}\n </div>\n <span class=\"inspector-intelligence-chain-proof\">\n ${this.renderIcon(\"Sparkles\")} Next run starts with\n <code>${INTELLIGENCE_STORY_SKILL_FILE}</code>\n </span>\n </div>\n `;\n }\n\n /** A press pins that beat and stops the loop; the developer is now driving. */\n private pinIntelligenceStoryBeat(index: number): void {\n this.intelStoryUserPinned = true;\n this.intelStoryBeat = index;\n this.stopIntelligenceStory();\n this.requestUpdate();\n\n // Reported here and nowhere else: this is the only path a human can take\n // to a beat. The auto-advance in syncIntelligenceStory deliberately stays\n // silent.\n if (!this.core?.telemetryDisabled) {\n const beat = INTELLIGENCE_STORY_BEATS[index];\n if (beat) {\n trackHomeStoryBeatSelected({ beat: beat.id, beat_index: index });\n }\n }\n }\n\n /**\n * Advance the story only while it is actually on screen.\n *\n * Gated on the panel being open, Home being the visible tab, settings being\n * closed and the document being visible. Anything less and a debugging tool\n * would be holding a repeating timer behind a closed panel.\n */\n private syncIntelligenceStory(): void {\n const visible =\n this.isOpen &&\n !this.settingsOpen &&\n this.selectedMenu === \"home\" &&\n !this._core?.intelligence &&\n typeof document !== \"undefined\" &&\n document.visibilityState !== \"hidden\";\n\n if (!visible) {\n // Leaving Home also releases a pinned beat, so coming back later shows a\n // running story rather than a frozen one that reads as broken.\n this.intelStoryUserPinned = false;\n this.stopIntelligenceStory();\n return;\n }\n\n if (this.intelStoryUserPinned || this.prefersReducedMotion()) {\n this.stopIntelligenceStory();\n return;\n }\n\n if (this.intelStoryTimer !== null) {\n return;\n }\n\n const advance = (): void => {\n const current = INTELLIGENCE_STORY_BEATS[this.intelStoryBeat];\n this.intelStoryTimer = setTimeout(() => {\n this.intelStoryTimer = null;\n if (!this.isConnected) {\n return;\n }\n this.intelStoryBeat =\n (this.intelStoryBeat + 1) % INTELLIGENCE_STORY_BEATS.length;\n this.requestUpdate();\n advance();\n }, current?.duration ?? 3_800);\n };\n\n advance();\n }\n\n private stopIntelligenceStory(): void {\n if (this.intelStoryTimer !== null) {\n clearTimeout(this.intelStoryTimer);\n this.intelStoryTimer = null;\n }\n }\n\n /**\n * Reduced motion parks the story on the closing beat.\n *\n * That beat is the whole argument in one static frame, so a developer who\n * asked their OS for less motion still gets the point rather than a\n * fragment of it.\n */\n private prefersReducedMotion(): boolean {\n if (typeof window === \"undefined\" || !window.matchMedia) {\n return false;\n }\n this.intelStoryReducedMotion ??= window.matchMedia(\n \"(prefers-reduced-motion: reduce)\",\n );\n if (this.intelStoryReducedMotion.matches) {\n this.intelStoryBeat = INTELLIGENCE_STORY_BEATS.length - 1;\n return true;\n }\n return false;\n }\n\n private maybeTrackHomeViewed(): void {\n if (this.selectedMenu !== \"home\" || this.settingsOpen || !this.isOpen) {\n return;\n }\n if (!this.homeViewedThisOpen && !this.core?.telemetryDisabled) {\n this.homeViewedThisOpen = true;\n trackHomeViewed();\n }\n }\n\n private renderWindow() {\n const windowState = this.contextState.window;\n const isDocked = this.dockMode !== \"floating\";\n const isPoppedOut = this.isPoppedOut;\n const isTransitioning = this.hasAttribute(\"data-transitioning\");\n const disableDrag = isDocked || isPoppedOut;\n\n const windowStyles = isPoppedOut\n ? {\n position: \"fixed\",\n inset: \"0\",\n width: \"100%\",\n height: \"100%\",\n minWidth: \"0\",\n minHeight: \"0\",\n borderRadius: \"0\",\n overflowX: \"hidden\",\n }\n : isDocked\n ? { ...this.getDockedWindowStyles(), overflowX: \"hidden\" }\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 overflowX: \"hidden\",\n };\n\n const hasContextDropdown = this.contextOptions.some(\n (option) => option.key !== \"all-agents\",\n );\n const viewportWidth = isPoppedOut\n ? (this.popOut?.win.innerWidth ?? windowState.size.width)\n : typeof window === \"undefined\"\n ? windowState.size.width\n : window.innerWidth;\n const automaticallyCollapsed = shouldUseIconRail({\n dockedLeft: this.dockMode === \"docked-left\",\n width: viewportWidth,\n });\n const iconRail = this.sidebarCollapsed || automaticallyCollapsed;\n const contextDropdown = hasContextDropdown\n ? this.renderContextDropdown(iconRail)\n : nothing;\n const agentSelector = hasContextDropdown\n ? contextDropdown\n : html`\n <div\n class=\"inspector-agent-placeholder flex items-center gap-2 rounded-md border border-dashed px-2 py-1 text-xs\"\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 data-color-scheme=${this.colorScheme}\n >\n ${\n isDocked && !isPoppedOut\n ? html`\n <div\n class=\"dock-resize-handle pointer-events-auto\"\n data-resize-edge=\"e\"\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 }\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 ${\n disableDrag\n ? \"\"\n : this.isDragging && this.pointerContext === \"window\"\n ? \"cursor-grabbing\"\n : \"cursor-grab\"\n }\"\n data-drag-context=\"window\"\n @pointerdown=${disableDrag ? undefined : this.handlePointerDown}\n @pointermove=${disableDrag ? undefined : this.handlePointerMove}\n @pointerup=${disableDrag ? undefined : this.handlePointerUp}\n @pointercancel=${disableDrag ? undefined : this.handlePointerCancel}\n >\n <div\n class=\"inspector-account-strip flex flex-wrap items-center gap-3 px-3 py-2\"\n data-inspector-account-strip\n style=\"width:100%;min-width:0;color:#010507;\"\n >\n <div class=\"inspector-account-brand flex items-center min-w-0\">\n <img\n src=${inspectorLogoUrl}\n alt=\"CopilotKit\"\n class=\"inspector-account-logo h-6 w-auto\"\n loading=\"lazy\"\n />\n <img\n src=${inspectorLogoUrl}\n alt=\"\"\n aria-hidden=\"true\"\n class=\"inspector-account-logo-accent h-6 w-auto\"\n loading=\"lazy\"\n />\n </div>\n <div class=\"ml-auto flex min-w-0 items-center gap-2\">\n <a\n class=\"inspector-account-cta\"\n data-inspector-thread-cta\n data-motion-paused=${\n this.accountCtaMotionPaused ? \"true\" : \"false\"\n }\n href=${this.getThreadsTalkToEngineerUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Talk to an Engineer (opens in a new tab)\"\n title=\"Talk to an Engineer\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleTalkToEngineerClick}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"MessageCircle\")}</span\n >\n <span class=\"inspector-account-cta-label\"\n >Talk to an Engineer</span\n >\n </a>\n <div class=\"flex items-center gap-1\">\n ${isPoppedOut ? nothing : this.renderWindowLayoutMenu()}\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=${\n this.colorScheme === \"light\"\n ? \"Switch to dark mode\"\n : \"Switch to light mode\"\n }\n aria-pressed=${this.colorScheme === \"dark\"}\n title=${\n this.colorScheme === \"light\" ? \"Dark mode\" : \"Light mode\"\n }\n data-inspector-theme-toggle\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleColorSchemeToggle}\n >\n <span\n class=\"inspector-account-control-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(\n this.colorScheme === \"light\" ? \"Moon\" : \"Sun\",\n )}\n </span>\n </button>\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 ${\n this.settingsOpen\n ? \"inspector-account-control-active\"\n : \"\"\n }\"\n type=\"button\"\n aria-label=\"Settings\"\n aria-pressed=${this.settingsOpen}\n title=\"Settings\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleSettingsToggle}\n >\n <span\n class=\"inspector-account-control-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(\"Settings\")}\n </span>\n </button>\n ${\n isPoppedOut\n ? nothing\n : html`\n <button\n class=\"inspector-account-control flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=\"Close Web Inspector\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @pointerdown=${this.handleClosePointerDown}\n @click=${this.handleCloseClick}\n >\n ${this.renderIcon(\"X\")}\n </button>\n `\n }\n </div>\n </div>\n </div>\n </div>\n <div class=\"inspector-shell\">\n ${this.renderInspectorSidebar(\n iconRail,\n automaticallyCollapsed,\n agentSelector,\n )}\n <div class=\"inspector-main\">\n <div id=\"cpk-main-scroll\" class=\"flex-1 overflow-auto\">\n ${this.renderCoreWarningBanner()} ${this.renderMainContent()}\n <slot></slot>\n </div>\n </div>\n </div>\n </div>\n ${\n isPoppedOut\n ? nothing\n : html`\n ${\n isDocked\n ? nothing\n : html`\n <div\n class=\"edge-resize-handle edge-resize-handle-w pointer-events-auto\"\n data-resize-edge=\"w\"\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 <div\n class=\"edge-resize-handle edge-resize-handle-e pointer-events-auto\"\n data-resize-edge=\"e\"\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 <div\n class=\"edge-resize-handle edge-resize-handle-s pointer-events-auto\"\n data-resize-edge=\"s\"\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 }\n <div\n class=\"resize-handle pointer-events-auto absolute bottom-0 right-0 flex h-7 w-7 cursor-nwse-resize items-center justify-center text-gray-600 transition hover:text-gray-900\"\n data-resize-edge=\"se\"\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 `\n }\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 this.hydrateColorSchemePreference(persisted);\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 this.restorePersistedMenu(\n persisted.selectedMenu,\n persisted.hasOpenedInspector === true,\n );\n if (this.isOpen) {\n this.hasOpenedInspector = true;\n }\n if (typeof persisted.sidebarCollapsed === \"boolean\") {\n this.sidebarCollapsed = persisted.sidebarCollapsed;\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 this.hydrateColorSchemePreference(persisted);\n if (!persisted) {\n return;\n }\n\n this.restorePersistedMenu(\n persisted.selectedMenu,\n persisted.hasOpenedInspector === true,\n );\n if (this.isOpen) {\n this.hasOpenedInspector = true;\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 if (typeof persisted.sidebarCollapsed === \"boolean\") {\n this.sidebarCollapsed = persisted.sidebarCollapsed;\n }\n }\n\n /** Follow the OS preference until a person deliberately picks a theme. */\n private hydrateColorSchemePreference(persisted: PersistedState | null): void {\n const preference = persisted?.colorSchemePreference;\n if (preference === \"light\" || preference === \"dark\") {\n this.hasExplicitColorScheme = true;\n this.colorScheme = preference;\n return;\n }\n\n this.hasExplicitColorScheme = false;\n this.colorScheme = this.getSystemColorScheme();\n }\n\n private getSystemColorScheme(): InspectorColorScheme {\n return window.matchMedia?.(\"(prefers-color-scheme: dark)\").matches\n ? \"dark\"\n : \"light\";\n }\n\n private readonly handleSystemColorSchemeChange = (\n event: MediaQueryListEvent,\n ): void => {\n if (this.hasExplicitColorScheme) {\n return;\n }\n this.colorScheme = event.matches ? \"dark\" : \"light\";\n this.requestUpdate();\n };\n\n private subscribeToSystemColorScheme(): void {\n const mediaQuery = window.matchMedia?.(\"(prefers-color-scheme: dark)\");\n if (!mediaQuery || mediaQuery === this.systemColorSchemeMediaQuery) {\n return;\n }\n\n this.unsubscribeFromSystemColorScheme();\n this.systemColorSchemeMediaQuery = mediaQuery;\n mediaQuery.addEventListener?.(\"change\", this.handleSystemColorSchemeChange);\n }\n\n private unsubscribeFromSystemColorScheme(): void {\n this.systemColorSchemeMediaQuery?.removeEventListener?.(\n \"change\",\n this.handleSystemColorSchemeChange,\n );\n this.systemColorSchemeMediaQuery = null;\n }\n\n /** Restore a visible leaf, or open Home for first install and stale state. */\n private restorePersistedMenu(\n value: unknown,\n hasOpenedInspector = this.hasOpenedInspector,\n ): void {\n this.hasOpenedInspector = hasOpenedInspector;\n this.pendingPersistedMenu = null;\n this.briefingRestoreMenu = null;\n\n const storedMenu = isInspectorMenuKey(value) ? value : null;\n const visibleMenu =\n storedMenu && this.menuItems.some((item) => item.key === storedMenu)\n ? storedMenu\n : null;\n\n this.selectedMenu = \"home\";\n this.lastSelectedMenuByGroup.home = \"home\";\n\n if (!hasOpenedInspector) {\n if (visibleMenu && visibleMenu !== \"home\") {\n this.briefingRestoreMenu = visibleMenu;\n this.lastSelectedMenuByGroup[getGroupForMenu(visibleMenu)] =\n visibleMenu;\n } else if (storedMenu && !visibleMenu && !this.hasResolvedCore) {\n this.pendingPersistedMenu = storedMenu;\n }\n return;\n }\n\n if (!storedMenu) {\n return;\n }\n\n if (!visibleMenu) {\n if (!this.hasResolvedCore) {\n this.pendingPersistedMenu = storedMenu;\n }\n return;\n }\n\n this.selectedMenu = visibleMenu;\n this.lastSelectedMenuByGroup[getGroupForMenu(visibleMenu)] = visibleMenu;\n }\n\n /** Resolve a valid stored leaf after the first Core exposes its sources. */\n private resolvePendingPersistedMenu(): void {\n const pendingMenu = this.pendingPersistedMenu;\n if (!pendingMenu) {\n return;\n }\n\n this.pendingPersistedMenu = null;\n this.restorePersistedMenu(pendingMenu, this.hasOpenedInspector);\n this.persistState();\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, a, nav\")) {\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 // Pointer events fire before `click`, so a mouse press opens from here\n // and never reaches handleButtonClick. Both paths must behave the same.\n this.openInspector(\"floating_button\");\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 // Reached by keyboard activation, which fires `click` with no pointer\n // events. A mouse press has already opened from handlePointerUp.\n this.openInspector(\"floating_button\");\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 get isPoppedOut(): boolean {\n return this.popOut !== null && !this.popOut.win.closed;\n }\n\n private get activeRoot(): ParentNode {\n if (this.isPoppedOut) {\n return this.popOut!.win.document;\n }\n return this.renderRoot;\n }\n\n private getPopOutCssTexts(): string[] {\n const fromStatic = WebInspectorElement.styles.map((sheet) =>\n \"cssText\" in sheet ? String(sheet.cssText) : \"\",\n );\n const overlay = `\n html, body { margin: 0; height: 100%; background: #ffffff; }\n .inspector-window {\n position: fixed !important;\n inset: 0 !important;\n width: 100% !important;\n height: 100% !important;\n min-width: 0 !important;\n min-height: 0 !important;\n border-radius: 0 !important;\n }\n `;\n return [...fromStatic.filter(Boolean), overlay];\n }\n\n // Also bound as button.click so a blocked popup throws out of element.click().\n // jsdom swallows errors from click event listeners.\n private getRenderedInspectorWindowSize(): Size {\n const inspectorWindow =\n this.shadowRoot?.querySelector<HTMLElement>(\".inspector-window\");\n if (inspectorWindow) {\n const width = Math.round(Number.parseFloat(inspectorWindow.style.width));\n const height = Math.round(\n Number.parseFloat(inspectorWindow.style.height),\n );\n if (Number.isFinite(width) && Number.isFinite(height)) {\n return { width, height };\n }\n }\n return this.clampWindowSize(this.contextState.window.size);\n }\n\n private requestPopOut = (): void => {\n if (this.isPoppedOut) return;\n this.layoutMenuOpen = false;\n this.requestUpdate();\n const size = this.getRenderedInspectorWindowSize();\n const handle = openPopOutWindow({\n open: window.open.bind(window),\n features: buildPopOutFeatures(size),\n title: \"CopilotKit Inspector\",\n cssTexts: this.getPopOutCssTexts(),\n sourceDocument: document,\n onClose: () => this.handlePopOutClosed(),\n });\n this.popOut = handle;\n try {\n defineWebInspector(handle.win.customElements);\n if (this.dockMode !== \"floating\") {\n this.removeDockStyles();\n }\n handle.win.addEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n this.syncInspectorPortal();\n this.requestUpdate();\n } catch (error) {\n this.popOut = null;\n this.unbindPopOutPointerDown(handle.win);\n handle.close();\n if (this.isConnected && this.isOpen && this.dockMode !== \"floating\") {\n this.applyDockStyles();\n }\n this.requestUpdate();\n throw error;\n }\n };\n\n private unbindPopOutPointerDown(win: Window): void {\n try {\n win.removeEventListener(\n \"pointerdown\",\n this.handleGlobalPointerDown as EventListener,\n );\n } catch {\n // Popup window may already be gone.\n }\n }\n\n private handlePopOutClosed = (): void => {\n const handle = this.popOut;\n if (!handle) return;\n this.popOut = null;\n this.unbindPopOutPointerDown(handle.win);\n this.syncInspectorPortal();\n if (this.isConnected && this.isOpen && this.dockMode !== \"floating\") {\n this.applyDockStyles();\n }\n this.requestUpdate();\n };\n\n private closePopOut(): void {\n const handle = this.popOut;\n if (!handle) return;\n this.handlePopOutClosed();\n handle.close();\n }\n\n private handleAppBeforeUnload = (): void => {\n this.closePopOut();\n };\n\n private syncInspectorPortal(): void {\n if (!this.inspectorPortal) {\n const portal = (this.ownerDocument ?? document).createElement(\"div\");\n portal.dataset.inspectorPortal = \"true\";\n portal.style.display = \"contents\";\n this.inspectorPortal = portal;\n }\n\n if (!this.isOpen) {\n render(nothing, this.inspectorPortal, {\n host: this,\n creationScope: this.ownerDocument ?? document,\n });\n this.inspectorPortal.remove();\n return;\n }\n\n render(this.renderWindow(), this.inspectorPortal, {\n host: this,\n creationScope: this.ownerDocument ?? document,\n });\n\n const target = this.isPoppedOut\n ? this.popOut!.win.document.body\n : this.renderRoot.querySelector<HTMLElement>(\n \"[data-inspector-portal-anchor]\",\n );\n if (target && this.inspectorPortal.parentNode !== target) {\n target.appendChild(this.inspectorPortal);\n }\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 this.resizeInitialPosition = { ...this.contextState.window.position };\n const edge = (event.currentTarget as HTMLElement | null)?.dataset\n .resizeEdge;\n this.resizeEdge =\n edge === \"w\" ||\n edge === \"e\" ||\n edge === \"s\" ||\n edge === \"se\" ||\n edge === \"sw\"\n ? edge\n : \"se\";\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 const edge = this.resizeEdge;\n const growWest = edge === \"w\" || edge === \"sw\";\n const growEast =\n edge === \"e\" || edge === \"se\" || this.dockMode === \"docked-left\";\n const growSouth = edge === \"s\" || edge === \"se\" || edge === \"sw\";\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 const initialSize = this.resizeInitialSize;\n const initialPos = this.resizeInitialPosition ?? { ...state.position };\n let nextWidth = initialSize.width;\n let nextHeight = initialSize.height;\n\n if (growEast) {\n nextWidth = initialSize.width + deltaX;\n } else if (growWest) {\n nextWidth = initialSize.width - deltaX;\n }\n if (growSouth) {\n nextHeight = initialSize.height + deltaY;\n }\n\n state.size = this.clampWindowSize({\n width: nextWidth,\n height: nextHeight,\n });\n\n if (growWest) {\n const right = initialPos.x + initialSize.width;\n state.position = {\n x: right - state.size.width,\n y: initialPos.y,\n };\n }\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 if (this.isPoppedOut) {\n return;\n }\n this.measureContext(\"button\");\n this.applyAnchorPosition(\"button\");\n\n this.measureContext(\"window\");\n this.contextState.window.size = this.clampWindowSize(\n this.contextState.window.size,\n );\n if (this.hasCustomPosition.window) {\n this.applyAnchorPosition(\"window\");\n } else {\n this.centerContext(\"window\");\n }\n\n this.requestUpdate();\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:\n this.pendingPersistedMenu ??\n (this.briefingRestoreMenu && this.selectedMenu === \"home\"\n ? this.briefingRestoreMenu\n : this.selectedMenu),\n selectedContext: this.selectedContext,\n hasOpenedInspector: this.hasOpenedInspector,\n sidebarCollapsed: this.sidebarCollapsed,\n colorSchemePreference: this.hasExplicitColorScheme\n ? this.colorScheme\n : undefined,\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 = this.clampWindowSize(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 if (this.previousHtmlOverflowX === null) {\n this.previousHtmlOverflowX = document.documentElement.style.overflowX;\n }\n document.documentElement.style.overflowX = \"hidden\";\n }\n\n // Remove transition after animation completes\n if (!this.isResizing && !skipTransition) {\n const id = setTimeout(() => {\n this.bodyTransitionTimeoutIds.delete(id);\n if (typeof document !== \"undefined\" && document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n this.bodyTransitionTimeoutIds.add(id);\n }\n }\n\n private removeDockStyles(skipTransition = false): void {\n if (typeof document === \"undefined\" || !document.body) {\n return;\n }\n\n // Only add transition if not resizing and not skipping\n if (!this.isResizing && !skipTransition) {\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 if (this.previousHtmlOverflowX !== null) {\n document.documentElement.style.overflowX = this.previousHtmlOverflowX;\n this.previousHtmlOverflowX = null;\n }\n\n // Clean up transition after animation completes\n if (!skipTransition) {\n const id = setTimeout(() => {\n this.bodyTransitionTimeoutIds.delete(id);\n if (typeof document !== \"undefined\" && document.body) {\n document.body.style.transition = \"\";\n }\n }, 300);\n this.bodyTransitionTimeoutIds.add(id);\n } else {\n document.body.style.transition = \"\";\n }\n }\n\n private updateHostTransform(context: ContextKey = this.activeContext): void {\n if (this.isPoppedOut) {\n return;\n }\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.setAttribute(\"data-docked\", \"true\");\n this.style.transform = \"none\";\n } else {\n this.removeAttribute(\"data-docked\");\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 (this.isPoppedOut) {\n return;\n }\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.resizeInitialPosition = null;\n this.resizeEdge = \"se\";\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 public openInspector(\n source: InspectorOpenSource,\n options: InspectorOpenOptions = {},\n ): void {\n if (this.isInspectorDismissed) {\n return;\n }\n if (options.threadId) {\n this.focusThread(options);\n }\n\n if (this.isPoppedOut) {\n return;\n }\n if (this.isOpen) {\n return;\n }\n\n const hadUnseenAnnouncement = this.newsSignalArmed;\n // Captured from the pre-open state, exactly as the unread-announcement\n // property is: after `isOpen` flips there is no launcher, so the question\n // \"was a signal on the launcher when this open happened\" has no answer.\n const activeSignalAtOpen = this.getActiveLauncherSignal();\n const firstOpen = !this.hasOpenedInspector;\n this.hasOpenedInspector = true;\n this.homeViewedThisOpen = false;\n this.closeLauncherHud();\n\n // A press on the launcher is a gesture towards whatever the dot is about,\n // so it lands where that subject is explained. Restoring a persisted-open\n // panel is not a gesture and deliberately does not route through here.\n // A HUD row sets `hudLandingMenu` and wins, so a red dot cannot steal\n // \"Turn on Threads\".\n const hudMenu = this.hudLandingMenu;\n this.hudLandingMenu = null;\n if (hudMenu) {\n // Use the same activation path as sidebar navigation. In particular,\n // Learning must initialize its lazy memory subscription before deciding\n // whether to show the enabled view or the setup gate.\n this.handleMenuSelect(hudMenu);\n } else if (activeSignalAtOpen !== null && source === \"floating_button\") {\n const landing = LAUNCHER_SIGNALS[activeSignalAtOpen].landingTarget;\n this.selectedMenu = landing;\n this.lastSelectedMenuByGroup[getGroupForMenu(landing)] = landing;\n if (landing === \"agents\" || landing === \"ag-ui-events\") {\n if (isEventErrorKey(activeSignalAtOpen)) {\n this.applyEventErrorLanding(activeSignalAtOpen);\n }\n }\n }\n\n this.ensureAnnouncementLoading();\n\n this.isOpen = true;\n if (this.isLearningStatusVisible()) {\n void this.refreshLearningSnapshot({\n preserve: this.learningSnapshot !== null,\n });\n }\n // The launcher is gone, so its gesture is gone with it — and the slot it\n // was holding is free again for whatever beats after the panel closes.\n this.cancelGestureTail();\n this.persistState(); // Save the open state\n\n this.trackOpened(\n source,\n hadUnseenAnnouncement,\n firstOpen,\n activeSignalAtOpen,\n );\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.isPoppedOut) {\n return;\n }\n if (!this.isOpen) {\n return;\n }\n\n this.isOpen = false;\n this.cancelLearningPoll();\n this.cancelLearningRequest();\n this.learningViewedState = null;\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 // Flush point for defer reason 1: there is a launcher again — and only\n // now is it where it belongs. The anchor is applied after the render that\n // would mount the pill, so flushing any earlier makes the pill measure\n // the room around a launcher that has not moved into place yet, and a\n // stale measurement can suppress a pill that had room all along.\n this.flushPendingSignalPulse();\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 renderWindowLayoutMenu() {\n const dockAction =\n this.dockMode === \"floating\"\n ? {\n label: \"Dock to left\",\n icon: \"PanelLeft\" as LucideIconName,\n mode: \"docked-left\" as DockMode,\n }\n : {\n label: \"Float window\",\n icon: \"Maximize2\" as LucideIconName,\n mode: \"floating\" as DockMode,\n };\n\n return html`\n <div\n class=\"inspector-window-layout\"\n data-inspector-window-layout-root=\"true\"\n >\n <button\n class=\"inspector-account-control inspector-window-layout-trigger flex h-8 w-8 items-center justify-center rounded-md focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2\"\n type=\"button\"\n aria-label=\"Window layout\"\n aria-haspopup=\"menu\"\n aria-expanded=${this.layoutMenuOpen}\n title=\"Window layout\"\n style=${INTERACTIVE_FOCUS_BASE_STYLE}\n @click=${this.handleLayoutMenuToggle}\n >\n ${this.renderIcon(\"PanelsTopLeft\")}\n </button>\n ${\n this.layoutMenuOpen\n ? html`\n <div\n class=\"inspector-window-layout-menu\"\n role=\"menu\"\n aria-label=\"Window layout\"\n >\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-label=${dockAction.label}\n @click=${() => this.handleDockClick(dockAction.mode)}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(dockAction.icon)}</span\n >\n <span>${dockAction.label}</span>\n </button>\n <button\n type=\"button\"\n role=\"menuitem\"\n aria-label=\"Detach Inspector into its own window\"\n data-testid=\"cpk-inspector-pop-out\"\n .click=${this.requestPopOut}\n @click=${this.requestPopOut}\n >\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"PictureInPicture2\")}</span\n >\n <span>Open in new window</span>\n </button>\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private handleLayoutMenuToggle = (event: Event): void => {\n event.stopPropagation();\n this.contextMenuOpen = false;\n if (!this.layoutMenuOpen && this.dockMode === \"floating\") {\n this.contextState.window.size = this.getRenderedInspectorWindowSize();\n }\n this.layoutMenuOpen = !this.layoutMenuOpen;\n this.requestUpdate();\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: \"auto\",\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.layoutMenuOpen = false;\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, \"&quot;\")}\"`,\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 const extracted = textFromUnknownContent(content);\n if (extracted) return extracted;\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 toolCallId:\n typeof raw.toolCallId === \"string\" ? raw.toolCallId : undefined,\n activityType:\n typeof raw.activityType === \"string\" ? raw.activityType : undefined,\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 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>&lt;cpk-web-inspector&gt;</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(): CoreStatusSummary {\n if (!this._core) {\n return {\n label: \"Core not attached\",\n state: \"unavailable\",\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 state: \"error\",\n description:\n lastErrorMessage ?? \"CopilotKit runtime reported an error.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connecting) {\n return {\n label: \"Connecting\",\n state: \"connecting\",\n description: \"Waiting for CopilotKit runtime to finish connecting.\",\n };\n }\n\n if (status === CopilotKitCoreRuntimeConnectionStatus.Connected) {\n return {\n label: \"Connected\",\n state: \"connected\",\n description: \"Live runtime connection established.\",\n };\n }\n\n return {\n label: \"Disconnected\",\n state: \"disconnected\",\n description:\n lastErrorMessage ?? \"Waiting for CopilotKit runtime to connect.\",\n };\n }\n\n private resolvePlaygroundAgentId(preferredAgentId?: string): string | null {\n const agents = this._core?.agents ?? {};\n if (\n preferredAgentId &&\n preferredAgentId !== \"all-agents\" &&\n agents[preferredAgentId]\n ) {\n return preferredAgentId;\n }\n return Object.keys(agents)[0] ?? null;\n }\n\n private teardownPlaygroundAgent(): void {\n this.playgroundAgentUnsubscribe?.();\n this.playgroundAgentUnsubscribe = null;\n if (this.playgroundAgent && this.playgroundIsRunning) {\n this.playgroundAgent.abortRun();\n void this.playgroundAgent.detachActiveRun().catch(() => {});\n }\n this.playgroundAgent = null;\n this.playgroundAgentId = null;\n this.playgroundMessages = [];\n this.playgroundIsRunning = false;\n this.playgroundRunStartedAt = null;\n this.playgroundReasoningDurations.clear();\n }\n\n private syncPlaygroundMessages(): void {\n this.playgroundMessages =\n this.normalizeAgentMessages(this.playgroundAgent?.messages) ?? [];\n this.requestUpdate();\n void this.updateComplete.then(() => {\n const messages = this.activeRoot.querySelector<HTMLElement>(\n \"[data-playground-messages]\",\n );\n if (messages) messages.scrollTop = messages.scrollHeight;\n });\n }\n\n private startPlaygroundSession(\n showEphemeralNotice: boolean,\n seedMessages: Message[] = [],\n seedState: unknown = {},\n preferredAgentId?: string,\n ): void {\n const agentId = this.resolvePlaygroundAgentId(\n preferredAgentId ?? this.selectedContext,\n );\n const sourceAgent = agentId\n ? typeof this._core?.getAgent === \"function\"\n ? this._core.getAgent(agentId)\n : this._core?.agents[agentId]\n : undefined;\n\n this.teardownPlaygroundAgent();\n this.playgroundError = null;\n this.playgroundSourceThreadId = null;\n this.playgroundShowEphemeralNotice =\n showEphemeralNotice && this._core?.runtimeMode !== \"intelligence\";\n\n if (!agentId || !sourceAgent) {\n this.requestUpdate();\n return;\n }\n\n if (this.selectedContext !== agentId) {\n this.selectedContext = agentId;\n }\n\n const playgroundAgent = sourceAgent.clone();\n playgroundAgent.threadId = createPlaygroundThreadId();\n playgroundAgent.setMessages(seedMessages);\n playgroundAgent.setState(seedState);\n const subscriber: AgentSubscriber = {\n onMessagesChanged: () => this.syncPlaygroundMessages(),\n onActivitySnapshotEvent: () => this.syncPlaygroundMessages(),\n onActivityDeltaEvent: () => this.syncPlaygroundMessages(),\n onRunErrorEvent: ({ event }) => {\n this.playgroundError =\n \"message\" in event && typeof event.message === \"string\"\n ? event.message\n : \"The agent run failed.\";\n this.requestUpdate();\n },\n onRunFailed: ({ error }) => {\n this.playgroundError = error.message;\n this.requestUpdate();\n },\n };\n const { unsubscribe } = playgroundAgent.subscribe(subscriber);\n\n this.playgroundAgent = playgroundAgent;\n this.playgroundAgentId = agentId;\n this.playgroundAgentUnsubscribe = unsubscribe;\n this.syncPlaygroundMessages();\n }\n\n private mapThreadMessagesToPlayground(\n messages: ThreadDebuggerMessage[],\n ): Message[] {\n const mapped: Message[] = [];\n for (const message of messages) {\n if (message.role === \"user\") {\n mapped.push({\n id: message.id,\n role: \"user\",\n content: message.content ?? \"\",\n });\n } else if (message.role === \"assistant\") {\n mapped.push({\n id: message.id,\n role: \"assistant\",\n content: message.content ?? \"\",\n ...(message.toolCalls?.length\n ? {\n toolCalls: message.toolCalls.map((toolCall) => ({\n id: toolCall.id,\n type: \"function\" as const,\n function: {\n name: toolCall.name,\n arguments:\n typeof toolCall.args === \"string\"\n ? toolCall.args\n : JSON.stringify(toolCall.args),\n },\n })),\n }\n : {}),\n });\n } else if (message.role === \"tool\" && message.toolCallId) {\n mapped.push({\n id: message.id,\n role: \"tool\",\n content: message.content ?? \"\",\n toolCallId: message.toolCallId,\n });\n }\n }\n return mapped;\n }\n\n private async loadThreadSnapshot(thread: ɵThread): Promise<{\n messages: Message[];\n state: unknown;\n }> {\n const core = this._core;\n if (!core?.runtimeUrl) {\n throw new Error(\"Failed to load thread.\");\n }\n const baseUrl = core.runtimeUrl.replace(/\\/+$/, \"\");\n const encodedThreadId = encodeURIComponent(thread.id);\n const [messagesResponse, stateResponse] = await Promise.all([\n fetch(`${baseUrl}/threads/${encodedThreadId}/messages`, {\n headers: { ...core.headers },\n }),\n fetch(`${baseUrl}/threads/${encodedThreadId}/state`, {\n headers: { ...core.headers },\n }),\n ]);\n if (!messagesResponse.ok) {\n throw new Error(\n `Failed to load thread (HTTP ${messagesResponse.status}).`,\n );\n }\n const messagesBody = (await messagesResponse.json()) as {\n messages?: ThreadDebuggerMessage[];\n };\n const stateBody = stateResponse.ok\n ? ((await stateResponse.json()) as { state?: unknown })\n : { state: {} };\n return {\n messages: this.mapThreadMessagesToPlayground(messagesBody.messages ?? []),\n state: stateBody.state ?? {},\n };\n }\n\n private applyThreadSnapshotToPlayground(\n thread: ɵThread,\n snapshot: { messages: Message[]; state: unknown },\n ): void {\n this.startPlaygroundSession(\n false,\n snapshot.messages,\n snapshot.state,\n thread.agentId,\n );\n this.playgroundSourceThreadId = thread.id;\n }\n\n private handlePlaygroundThreadSourceChange = async (\n event: Event,\n ): Promise<void> => {\n const threadId = (event.currentTarget as HTMLSelectElement).value;\n if (!threadId) {\n this.startPlaygroundSession(false);\n return;\n }\n\n const thread = this._threads.find((candidate) => candidate.id === threadId);\n if (!thread) return;\n\n this.playgroundIsLoadingThread = true;\n this.playgroundError = null;\n this.requestUpdate();\n\n try {\n const snapshot = await this.loadThreadSnapshot(thread);\n this.applyThreadSnapshotToPlayground(thread, snapshot);\n } catch (error) {\n this.playgroundError =\n error instanceof Error ? error.message : \"Failed to load thread.\";\n } finally {\n this.playgroundIsLoadingThread = false;\n this.requestUpdate();\n }\n };\n\n private handleTryFromHere = async (\n threadId: string | null,\n ): Promise<void> => {\n if (!threadId || this.tryFromHereBusy) return;\n const thread =\n this._threads.find((candidate) => candidate.id === threadId) ?? null;\n if (!thread) return;\n\n this.tryFromHereBusy = true;\n this.tryFromHereError = null;\n this.requestUpdate();\n\n const isCurrentTryFromHereRequest = (): boolean =>\n this.selectedThreadId === threadId && this.selectedMenu === \"threads\";\n\n try {\n const snapshot = await this.loadThreadSnapshot(thread);\n // A later thread or pane change owns the UI. Keep the fetch outcome\n // for telemetry, but do not replace Playground or leave Threads.\n if (isCurrentTryFromHereRequest()) {\n this.applyThreadSnapshotToPlayground(thread, snapshot);\n this.handleMenuSelect(\"playground\");\n }\n if (!this.core?.telemetryDisabled) {\n trackThreadsTryFromHereClicked({\n ...this.getThreadsTelemetryProps(),\n outcome: \"success\",\n });\n }\n } catch (error) {\n if (isCurrentTryFromHereRequest()) {\n this.tryFromHereError =\n error instanceof Error ? error.message : \"Failed to load thread.\";\n }\n if (!this.core?.telemetryDisabled) {\n trackThreadsTryFromHereClicked({\n ...this.getThreadsTelemetryProps(),\n outcome: \"failure\",\n });\n }\n } finally {\n this.tryFromHereBusy = false;\n this.requestUpdate();\n }\n };\n\n private runPlaygroundAgent = async (): Promise<void> => {\n const core = this._core;\n const agent = this.playgroundAgent;\n if (!core || !agent || this.playgroundIsRunning) return;\n\n this.playgroundIsRunning = true;\n this.playgroundRunStartedAt = Date.now();\n this.playgroundError = null;\n this.requestUpdate();\n try {\n await core.runAgent({ agent });\n } catch (error) {\n this.playgroundError =\n error instanceof Error ? error.message : \"The agent run failed.\";\n } finally {\n this.playgroundIsRunning = false;\n this.syncPlaygroundMessages();\n let reasoningMessage: InspectorMessage | undefined;\n for (\n let index = this.playgroundMessages.length - 1;\n index >= 0;\n index -= 1\n ) {\n const message = this.playgroundMessages[index];\n if (message?.role === \"reasoning\") {\n reasoningMessage = message;\n break;\n }\n }\n if (reasoningMessage?.id && this.playgroundRunStartedAt !== null) {\n this.playgroundReasoningDurations.set(\n reasoningMessage.id,\n Date.now() - this.playgroundRunStartedAt,\n );\n }\n this.playgroundRunStartedAt = null;\n this.requestUpdate();\n }\n };\n\n private sendPlaygroundMessage(content: string): void {\n if (\n !content ||\n this.playgroundIsRunning ||\n this.playgroundIsLoadingThread\n ) {\n return;\n }\n\n const selectedAgentId = this.resolvePlaygroundAgentId(this.selectedContext);\n if (!this.playgroundAgent || this.playgroundAgentId !== selectedAgentId) {\n this.startPlaygroundSession(false, [], {}, selectedAgentId ?? undefined);\n }\n if (!this.playgroundAgent) return;\n\n this.playgroundAgent.addMessage({\n id: createPlaygroundThreadId(),\n role: \"user\",\n content,\n });\n this.playgroundInput = \"\";\n this.syncPlaygroundMessages();\n void this.runPlaygroundAgent();\n }\n\n private handlePlaygroundSubmit = (event: SubmitEvent): void => {\n event.preventDefault();\n this.sendPlaygroundMessage(this.playgroundInput.trim());\n };\n\n private handlePlaygroundSuggestion = (message: string): void => {\n this.sendPlaygroundMessage(message.trim());\n };\n\n private handlePlaygroundInput = (event: Event): void => {\n const input = event.currentTarget as HTMLTextAreaElement;\n this.playgroundInput = input.value;\n input.style.height = \"auto\";\n input.style.height = `${Math.min(input.scrollHeight, 128)}px`;\n this.requestUpdate();\n };\n\n private handlePlaygroundKeyDown = (event: KeyboardEvent): void => {\n if (event.key !== \"Enter\" || event.shiftKey) return;\n event.preventDefault();\n (event.currentTarget as HTMLTextAreaElement).form?.requestSubmit();\n };\n\n private handlePlaygroundRetry = (): void => {\n const agent = this.playgroundAgent;\n if (!agent || this.playgroundIsRunning) return;\n let lastUserIndex = -1;\n for (let index = agent.messages.length - 1; index >= 0; index -= 1) {\n if (agent.messages[index]?.role === \"user\") {\n lastUserIndex = index;\n break;\n }\n }\n if (lastUserIndex < 0) return;\n agent.setMessages(agent.messages.slice(0, lastUserIndex + 1));\n this.syncPlaygroundMessages();\n void this.runPlaygroundAgent();\n };\n\n private handlePlaygroundStop = (): void => {\n this.playgroundAgent?.abortRun();\n };\n\n private renderPlaygroundComposer(\n agentId: string | null,\n busy: boolean,\n hasRetry: boolean,\n centered = false,\n ) {\n const placeholder = !agentId\n ? \"Waiting for an agent...\"\n : this.playgroundIsLoadingThread\n ? \"Loading thread...\"\n : \"Type a message...\";\n const sendDisabled =\n !agentId ||\n this.playgroundIsLoadingThread ||\n (!this.playgroundIsRunning && !this.playgroundInput.trim());\n\n return html`\n <form\n class=${\n centered\n ? \"cpk-playground-form mt-5 w-full\"\n : \"cpk-playground-form bg-white px-3 pb-3 pt-1.5\"\n }\n @submit=${this.handlePlaygroundSubmit}\n >\n ${\n this.playgroundError\n ? html`<div\n class=\"mx-auto mb-2 flex max-w-3xl items-start gap-2 rounded-lg border border-rose-200 bg-rose-50 px-2.5 py-2 text-[10px] text-rose-950\"\n role=\"alert\"\n data-playground-error\n >\n <span class=\"mt-0.5 shrink-0\"\n >${this.renderIcon(\"TriangleAlert\")}</span\n >\n <div class=\"min-w-0 flex-1\">\n <p class=\"font-semibold\">Agent run failed</p>\n <p class=\"mt-0.5 break-words leading-relaxed\">\n ${this.playgroundError}\n </p>\n </div>\n ${\n hasRetry\n ? html`\n <button\n type=\"button\"\n class=\"shrink-0 rounded-md border border-rose-200 bg-white px-2 py-1 font-medium text-rose-700 transition hover:bg-rose-100 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-rose-300 focus-visible:ring-offset-1 disabled:opacity-50\"\n ?disabled=${busy}\n @click=${this.handlePlaygroundRetry}\n >\n Retry\n </button>\n `\n : nothing\n }\n </div>`\n : nothing\n }\n <div\n class=\"cpk-playground-composer mx-auto flex max-w-3xl items-end gap-1.5 rounded-[28px] bg-white px-2.5 py-1.5 shadow-[0_4px_4px_0_#0000000a,0_0_1px_0_#0000009e] transition-shadow duration-200 focus-within:shadow-[0_6px_18px_0_#00000014,0_0_1px_0_#0000009e]\"\n >\n <textarea\n class=\"cpk-playground-input min-h-[40px] max-h-32 flex-1 resize-none bg-transparent px-2.5 py-2.5 text-[13px] leading-5 text-gray-900 outline-none placeholder:text-gray-500 disabled:cursor-not-allowed disabled:opacity-60\"\n rows=\"1\"\n placeholder=${placeholder}\n aria-label=\"Playground message\"\n .value=${this.playgroundInput}\n ?disabled=${!agentId || busy}\n @input=${this.handlePlaygroundInput}\n @keydown=${this.handlePlaygroundKeyDown}\n ></textarea>\n <button\n type=${this.playgroundIsRunning ? \"button\" : \"submit\"}\n class=${`cpk-playground-send mb-0.5 flex h-9 w-9 shrink-0 items-center justify-center rounded-full transition-colors duration-200 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-2 [&>svg]:h-[18px] [&>svg]:w-[18px] ${\n sendDisabled\n ? \"cursor-not-allowed bg-[#00000014] text-[rgb(13,13,13)] opacity-50\"\n : \"cursor-pointer bg-black text-white hover:opacity-70 active:opacity-60\"\n }`}\n aria-label=${\n this.playgroundIsRunning\n ? \"Stop agent\"\n : \"Send playground message\"\n }\n ?disabled=${sendDisabled}\n @click=${\n this.playgroundIsRunning ? this.handlePlaygroundStop : nothing\n }\n >\n ${this.renderIcon(this.playgroundIsRunning ? \"Square\" : \"ArrowUp\")}\n </button>\n </div>\n <p\n class=\"mx-auto max-w-3xl px-3 py-2 text-center text-[10px] leading-4 text-gray-500\"\n >\n AI can make mistakes. Please verify important information.\n </p>\n </form>\n `;\n }\n\n private renderMainContent() {\n if (this.settingsOpen) {\n return this.renderSettingsPanel();\n }\n\n if (this.selectedMenu === \"home\") {\n return this.renderHomeView();\n }\n\n if (this.selectedMenu === WHATS_NEW_MENU_KEY) {\n return this.renderWhatsNewView();\n }\n\n if (this.selectedMenu === \"ag-ui-events\") {\n return html`\n <div class=\"flex h-full min-h-0 flex-col\">\n ${this.renderEventErrorBanner(\"run\")}\n <div class=\"min-h-0 flex-1 overflow-hidden\">\n ${this.renderEventsTable()}\n </div>\n </div>\n `;\n }\n\n if (this.selectedMenu === \"playground\") {\n return this.renderPlaygroundView();\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 === \"capabilities\") {\n return this.renderCapabilitiesView();\n }\n\n if (this.selectedMenu === \"agent-context\") {\n return this.renderContextView();\n }\n\n if (this.selectedMenu === \"threads\") {\n return this.renderThreadsView();\n }\n\n if (this.selectedMenu === \"memories\") {\n return this.renderMemoriesView();\n }\n\n return nothing;\n }\n\n private renderPlaygroundView() {\n const agentId = this.resolvePlaygroundAgentId(this.selectedContext);\n const sourceThreads = this._threads.filter(\n (thread) => !agentId || thread.agentId === agentId,\n );\n const visibleMessages = this.playgroundMessages.filter(\n (message) =>\n message.role === \"user\" ||\n message.role === \"assistant\" ||\n message.role === \"reasoning\" ||\n message.role === \"activity\",\n );\n const hasRetry =\n this.playgroundAgent?.messages.some(\n (message) => message.role === \"user\",\n ) ?? false;\n const runtimeMode = this._core?.runtimeMode ?? \"sse\";\n const runtimeLabel = this._core?.runtimeUrl ?? \"Self-managed agent\";\n const busy = this.playgroundIsRunning || this.playgroundIsLoadingThread;\n const suggestions =\n agentId && this._core\n ? this._core.getSuggestions(agentId).suggestions\n : [];\n const lastAssistantIndex = visibleMessages.reduce(\n (last, message, index) => (message.role === \"assistant\" ? index : last),\n -1,\n );\n const lastReasoningIndex = visibleMessages.reduce(\n (last, message, index) => (message.role === \"reasoning\" ? index : last),\n -1,\n );\n const showWelcome =\n !this.playgroundIsLoadingThread && visibleMessages.length === 0;\n\n return html`\n <div\n class=\"cpk-playground-root flex h-full min-h-[420px] flex-col bg-white\"\n >\n <header\n class=\"cpk-playground-header flex flex-wrap items-center gap-2 border-b border-gray-200 bg-white px-3 py-2\"\n >\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex items-center gap-1.5\">\n <h2 class=\"text-xs font-semibold text-gray-900\">Playground</h2>\n <span\n class=\"rounded-full border border-gray-200 bg-gray-50 px-1.5 py-0.5 text-[9px] font-medium text-gray-600\"\n >${runtimeMode.toUpperCase()}</span\n >\n </div>\n <div\n class=\"mt-0.5 flex min-w-0 items-center gap-1.5 text-[9px] text-gray-600\"\n >\n <span class=\"truncate\">Agent: ${agentId ?? \"waiting...\"}</span>\n <span\n class=\"h-3 w-px shrink-0 bg-gray-200\"\n aria-hidden=\"true\"\n ></span>\n <span class=\"truncate\" title=${runtimeLabel}\n >${runtimeLabel}</span\n >\n </div>\n </div>\n <div\n class=\"cpk-playground-actions ml-auto flex min-w-0 items-center gap-2\"\n >\n ${\n sourceThreads.length > 0\n ? html`\n <label class=\"sr-only\" for=\"cpk-playground-thread-source\"\n >Start from a thread</label\n >\n <select\n id=\"cpk-playground-thread-source\"\n class=\"cpk-playground-thread-select max-w-[200px] rounded-md border border-gray-200 bg-white px-2 py-1 text-[10px] text-gray-700 outline-none transition hover:border-gray-300 focus:border-violet-400 focus:ring-2 focus:ring-violet-100 disabled:cursor-not-allowed disabled:opacity-50\"\n .value=${this.playgroundSourceThreadId ?? \"\"}\n ?disabled=${busy}\n @change=${this.handlePlaygroundThreadSourceChange}\n >\n <option\n value=\"\"\n ?selected=${!this.playgroundSourceThreadId}\n >\n Load a thread...\n </option>\n ${sourceThreads.map(\n (thread) => html`\n <option\n value=${thread.id}\n ?selected=${\n this.playgroundSourceThreadId === thread.id\n }\n >\n ${\n thread.name?.trim() ||\n `Thread ${thread.id.slice(0, 8)}`\n }\n </option>\n `,\n )}\n </select>\n `\n : nothing\n }\n <button\n type=\"button\"\n class=\"inline-flex shrink-0 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:border-gray-300 hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 disabled:cursor-not-allowed disabled:opacity-50 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n ?disabled=${busy || !agentId}\n @click=${() => this.startPlaygroundSession(true)}\n >\n ${this.renderIcon(\"Plus\")} <span>New thread</span>\n </button>\n </div>\n </header>\n\n ${\n this.playgroundShowEphemeralNotice && runtimeMode !== \"intelligence\"\n ? html`\n <div\n role=\"alert\"\n class=\"mx-3 mt-2 flex items-start gap-2 rounded-lg border border-violet-200 bg-violet-50 px-2.5 py-2 text-[10px] text-violet-950\"\n data-playground-ephemeral-notice\n >\n <span class=\"mt-0.5 text-violet-600 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n >${this.renderIcon(\"Clock3\")}</span\n >\n <p class=\"min-w-0 flex-1 leading-relaxed\">\n Scratch threads are ephemeral and will be deleted when your\n local session ends. Need durable history?\n <a\n class=\"font-semibold underline decoration-violet-300 underline-offset-2 hover:decoration-violet-700 focus-visible:rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1\"\n href=${this.getThreadsIntelligenceSignupUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >Set up Intelligence</a\n >.\n </p>\n <button\n type=\"button\"\n class=\"rounded p-0.5 text-violet-500 transition hover:bg-violet-100 hover:text-violet-800 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-400 focus-visible:ring-offset-1\"\n aria-label=\"Dismiss ephemeral thread notice\"\n @click=${() => {\n this.playgroundShowEphemeralNotice = false;\n this.requestUpdate();\n }}\n >\n ${this.renderIcon(\"X\")}\n </button>\n </div>\n `\n : nothing\n }\n\n <div\n class=\"min-h-0 flex-1 overflow-y-auto px-3 py-3\"\n data-playground-messages\n >\n ${\n this.playgroundIsLoadingThread\n ? html`\n <div\n class=\"flex h-full items-center justify-center gap-1.5 text-[10px] text-gray-600\"\n >\n <span\n class=\"text-gray-500 [&>svg]:animate-spin\"\n aria-hidden=\"true\"\n >${this.renderIcon(\"LoaderCircle\")}</span\n >\n Loading thread into a scratch session...\n </div>\n `\n : visibleMessages.length === 0\n ? html`\n <div\n class=\"cpk-playground-welcome mx-auto flex h-full w-full flex-col items-center justify-center text-center\"\n >\n <p class=\"cpk-playground-welcome-title\">\n How can I help you today?\n </p>\n ${this.renderPlaygroundComposer(\n agentId,\n busy,\n hasRetry,\n true,\n )}\n </div>\n `\n : html`\n <div class=\"mx-auto flex max-w-3xl flex-col pb-5\">\n ${visibleMessages.map((message, index) => {\n const isUser = message.role === \"user\";\n const isReasoning = message.role === \"reasoning\";\n const isActivity = message.role === \"activity\";\n const content = isActivity\n ? (message.activityType ?? \"Agent activity\")\n : message.contentText;\n if (\n !isReasoning &&\n !content &&\n message.toolCalls.length === 0\n ) {\n return nothing;\n }\n if (isReasoning) {\n const isStreaming =\n this.playgroundIsRunning &&\n index === lastReasoningIndex;\n const duration = message.id\n ? this.playgroundReasoningDurations.get(message.id)\n : undefined;\n const durationLabel =\n duration === undefined || duration < 1000\n ? \"a few seconds\"\n : `${Math.round(duration / 1000)} seconds`;\n const label = isStreaming\n ? \"Thinking…\"\n : `Thought for ${durationLabel}`;\n\n if (isStreaming) {\n return html`\n <section\n class=\"cpk-playground-message-enter my-1 text-[11px] text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n <div\n class=\"inline-flex items-center gap-1 py-1 font-medium\"\n >\n <span>${label}</span>\n ${\n content\n ? nothing\n : html`\n <span\n class=\"cpk-playground-thinking-dot ml-1 h-1.5 w-1.5 rounded-full bg-gray-500\"\n aria-hidden=\"true\"\n ></span>\n `\n }\n </div>\n ${\n content\n ? html`<div\n class=\"pb-2 pt-1 leading-5 text-gray-500\"\n >\n ${content}\n </div>`\n : nothing\n }\n </section>\n `;\n }\n\n return content\n ? html`\n <details\n class=\"cpk-playground-message-enter cpk-playground-reasoning my-1 text-[11px] text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n <summary\n class=\"inline-flex cursor-pointer list-none items-center gap-1 py-1 font-medium transition-colors hover:text-gray-900 focus-visible:rounded focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1\"\n >\n <span>${label}</span>\n <span\n class=\"cpk-playground-reasoning-chevron transition-transform duration-200 [&>svg]:h-3 [&>svg]:w-3\"\n >${this.renderIcon(\"ChevronRight\")}</span\n >\n </summary>\n <div class=\"pb-2 pt-1 leading-5 text-gray-500\">\n ${content}\n </div>\n </details>\n `\n : html`\n <div\n class=\"cpk-playground-message-enter my-1 py-1 text-[11px] font-medium text-gray-500\"\n data-playground-message-role=\"reasoning\"\n >\n ${label}\n </div>\n `;\n }\n const isMultiline =\n content.includes(\"\\n\") || content.length > 72;\n const copyKey = `playground-message-${\n message.id ?? index\n }`;\n const showToolbar =\n !isUser &&\n !isActivity &&\n Boolean(content) &&\n !(\n this.playgroundIsRunning &&\n index === lastAssistantIndex\n );\n return html`\n <article\n class=${\n isActivity\n ? \"cpk-playground-message-enter mr-auto mt-3 flex max-w-full items-center gap-1.5 rounded-lg border border-gray-200 bg-gray-50 px-2.5 py-1.5 text-[10px] text-gray-600\"\n : isUser\n ? \"cpk-playground-message-enter flex w-full flex-col items-end pt-8\"\n : \"cpk-playground-message-enter w-full\"\n }\n data-playground-message-role=${message.role}\n >\n ${\n isActivity\n ? html`\n <span class=\"text-gray-500\"\n >${this.renderIcon(\"Activity\")}</span\n >\n <span class=\"font-medium text-gray-700\"\n >Activity</span\n >\n <span class=\"truncate\">${content}</span>\n `\n : isUser\n ? html`\n <div\n class=${`max-w-[80%] whitespace-pre-wrap break-words rounded-[16px] bg-gray-100 px-3 text-[13px] leading-5 text-gray-900 ${\n isMultiline ? \"py-2.5\" : \"py-1\"\n }`}\n >\n ${content}\n </div>\n `\n : html`\n <div\n class=\"whitespace-pre-wrap break-words py-3 text-[13px] leading-[22px] text-gray-800\"\n >\n ${content}\n </div>\n `\n }\n ${\n !isUser && message.toolCalls.length > 0\n ? this.renderToolCallDetails(message.toolCalls)\n : nothing\n }\n ${\n showToolbar\n ? html`\n <div\n class=\"-ml-1 flex min-h-7 w-full items-center gap-1 bg-transparent\"\n data-playground-assistant-toolbar\n >\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n title=\"Copy message\"\n aria-label=\"Copy message\"\n @click=${(event: Event) =>\n this.copyToClipboard(\n content,\n copyKey,\n event,\n )}\n >\n ${\n this.copiedEvents.has(copyKey)\n ? this.renderIcon(\"Check\")\n : this.renderIcon(\"Copy\")\n }\n </button>\n ${\n index === lastAssistantIndex &&\n hasRetry &&\n !busy &&\n !this.playgroundError\n ? html`\n <button\n type=\"button\"\n class=\"flex h-7 w-7 items-center justify-center rounded-md text-gray-500 transition hover:bg-gray-100 hover:text-gray-900 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-1 [&>svg]:h-3.5 [&>svg]:w-3.5\"\n title=\"Retry last prompt\"\n aria-label=\"Retry last prompt\"\n @click=${this.handlePlaygroundRetry}\n >\n ${this.renderIcon(\"RotateCcw\")}\n </button>\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n </article>\n `;\n })}\n ${\n this.playgroundIsRunning && lastReasoningIndex < 0\n ? html`\n <div\n class=\"cpk-playground-message-enter mt-3 flex items-center gap-1 px-1 py-1\"\n aria-label=\"Agent is working\"\n >\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n <span\n class=\"cpk-playground-thinking-dot h-1.5 w-1.5 rounded-full bg-gray-500\"\n ></span>\n </div>\n `\n : nothing\n }\n ${\n !busy && lastAssistantIndex >= 0 && suggestions.length > 0\n ? html`\n <div\n class=\"mt-3 flex flex-wrap items-center gap-1.5\"\n data-playground-suggestions\n >\n ${suggestions.map(\n (suggestion) => html`\n <button\n type=\"button\"\n class=\"inline-flex h-7 items-center gap-1 rounded-full border border-gray-200 bg-white px-2.5 text-[10px] font-medium leading-none text-gray-900 transition-colors hover:bg-gray-50 focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-violet-300 focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:text-gray-500\"\n ?disabled=${suggestion.isLoading}\n aria-busy=${\n suggestion.isLoading ? \"true\" : \"false\"\n }\n @click=${() =>\n this.handlePlaygroundSuggestion(\n suggestion.message,\n )}\n >\n ${\n suggestion.isLoading\n ? html`<span\n class=\"[&>svg]:animate-spin\"\n aria-hidden=\"true\"\n >${this.renderIcon(\n \"LoaderCircle\",\n )}</span\n >`\n : nothing\n }\n <span>${suggestion.title}</span>\n </button>\n `,\n )}\n </div>\n `\n : nothing\n }\n </div>\n `\n }\n </div>\n\n ${\n showWelcome\n ? nothing\n : this.renderPlaygroundComposer(agentId, busy, hasRetry)\n }\n </div>\n `;\n }\n\n private renderSettingsPanel() {\n const optedOut = this.core?.telemetryDisabled ?? false;\n const privateContent = [\n \"Message content\",\n \"Agent state\",\n \"Prompts\",\n \"Completions\",\n ];\n return html`\n <div\n class=\"inspector-settings\"\n data-inspector-settings\n data-state=${optedOut ? \"disabled\" : \"enabled\"}\n >\n <header class=\"inspector-settings-header\">\n <h1 class=\"inspector-settings-title\">Settings</h1>\n <p class=\"inspector-settings-subtitle\">\n Understand how the Inspector handles analytics and private content.\n </p>\n </header>\n\n <section\n class=\"inspector-settings-section\"\n aria-labelledby=\"inspector-settings-privacy-title\"\n >\n <div class=\"inspector-settings-section-heading\">\n <span class=\"inspector-settings-section-icon\" aria-hidden=\"true\">\n ${this.renderIcon(optedOut ? \"ShieldOff\" : \"ShieldCheck\")}\n </span>\n <div>\n <h2 id=\"inspector-settings-privacy-title\">Privacy</h2>\n <p>Analytics without access to your agent content.</p>\n </div>\n </div>\n\n <div\n class=\"inspector-settings-privacy\"\n data-state=${optedOut ? \"disabled\" : \"enabled\"}\n >\n <div class=\"inspector-settings-status-row\">\n <div>\n <h3>Anonymous usage analytics</h3>\n <p>\n ${\n optedOut\n ? \"Anonymous Inspector interaction data collection is disabled for this runtime.\"\n : \"CopilotKit collects anonymous Inspector interactions to understand which features people use.\"\n }\n </p>\n </div>\n <span class=\"inspector-settings-status\">\n ${optedOut ? \"Analytics off\" : \"Analytics on\"}\n </span>\n </div>\n\n <div class=\"inspector-settings-private-content\">\n <strong>Content stays private</strong>\n <p>CopilotKit never collects:</p>\n <ul aria-label=\"Content CopilotKit never collects\">\n ${privateContent.map(\n (item) => html`\n <li>\n <span aria-hidden=\"true\"\n >${this.renderIcon(\"Check\")}</span\n >\n ${item}\n </li>\n `,\n )}\n </ul>\n </div>\n\n <a\n class=\"inspector-settings-policy-link\"\n href=${TELEMETRY_DOCS_URL}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n >\n Read the telemetry policy\n <span aria-hidden=\"true\">${this.renderIcon(\"ArrowUpRight\")}</span>\n </a>\n </div>\n </section>\n\n <section\n class=\"inspector-settings-section\"\n aria-labelledby=\"inspector-settings-visibility-title\"\n >\n <div class=\"inspector-settings-section-heading\">\n <span class=\"inspector-settings-section-icon\" aria-hidden=\"true\">\n ${this.renderIcon(\"EyeOff\")}\n </span>\n <div>\n <h2 id=\"inspector-settings-visibility-title\">Visibility</h2>\n <p>Temporarily hide the Inspector on this domain.</p>\n </div>\n </div>\n\n <div class=\"inspector-settings-visibility\">\n <div>\n <h3>Take a break from the Inspector</h3>\n <p>\n Hide the Inspector for seven days. It will return automatically\n when the week is over.\n </p>\n </div>\n <button\n type=\"button\"\n class=\"inspector-settings-dismiss\"\n data-cpk-dismiss-inspector=\"week\"\n @click=${() => this.dismissInspectorFor(\"week\")}\n >\n <span aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n Hide Inspector for one week\n </button>\n </div>\n </section>\n </div>\n `;\n }\n\n // Fires `oss.inspector.opened` for a user-initiated open (OSS-566).\n // Restoring a persisted-open panel on mount assigns `isOpen` directly\n // instead of routing through `openInspector`, so page reloads and dev-server\n // hot reloads are not counted as opens.\n private trackOpened(\n source: InspectorOpenSource,\n hadUnseenAnnouncement: boolean,\n firstOpen = false,\n activeSignal: LauncherSignalKey | null = null,\n ): void {\n if (this.core?.telemetryDisabled) return;\n // Two properties rather than one, so an open can be attributed to a red\n // signal *and* to which failure class raised it. The failure message is\n // never included — `error_signal_source` is a closed two-value enum.\n const errorSignal =\n activeSignal !== null && isErrorSignalKey(activeSignal)\n ? activeSignal\n : null;\n // `license_status` and `runtime_mode` come from /info. Before the handshake\n // `licenseStatus` is undefined and `runtimeMode` reads its `sse` default, so\n // recording them would permanently attribute an early open against an\n // Intelligence runtime to SSE. Omitted rather than guessed — an absent\n // dimension is honest, a wrong one is not. `runtime_url_type` is derived\n // from configuration, so it is accurate immediately.\n const handshakeComplete = this.runtimeStatus === \"connected\";\n trackInspectorOpened({\n open_source: source,\n ...(handshakeComplete\n ? {\n license_status: this.core?.licenseStatus ?? undefined,\n runtime_mode: this.core?.runtimeMode ?? undefined,\n }\n : {}),\n runtime_url_type: getRuntimeUrlType(this.core?.runtimeUrl),\n has_unseen_announcement: hadUnseenAnnouncement,\n has_error_signal: errorSignal !== null,\n ...(errorSignal === null ? {} : { error_signal_source: errorSignal }),\n first_open: firstOpen,\n });\n }\n\n private getVisibleInspectorMetadataAction():\n | Readonly<{\n action: InspectorMetadataAction;\n placement: \"threads-footer\" | \"locked\";\n }>\n | undefined {\n const { threadsFooterAction } = this.inspectorMetadataProjection;\n if (\n threadsFooterAction &&\n !this.settingsOpen &&\n this.selectedMenu === \"threads\" &&\n this.areThreadEndpointsAvailable()\n ) {\n return { action: threadsFooterAction, placement: \"threads-footer\" };\n }\n return undefined;\n }\n\n /** Return paired stable navigation keys, or neither for an invalid leaf. */\n private getMetadataTelemetryNavigation(): Readonly<{\n group_key?: InspectorGroupKey;\n leaf_key?: MenuKey;\n }> {\n const selectedLeaf: unknown = this.selectedMenu;\n if (!isInspectorMenuKey(selectedLeaf)) return {};\n return {\n group_key: getGroupForMenu(selectedLeaf),\n leaf_key: selectedLeaf,\n };\n }\n\n /** Build metadata's shared coarse buckets and stable navigation context. */\n private getMetadataTelemetryContext(): Readonly<{\n usage_bucket: ThreadsUsageBucket;\n expiry_bucket: ThreadsExpiryBucket;\n group_key?: InspectorGroupKey;\n leaf_key?: MenuKey;\n }> {\n return {\n usage_bucket: this.getThreadsUsageBucket(),\n expiry_bucket: this.getThreadsExpiryBucket(),\n ...this.getMetadataTelemetryNavigation(),\n };\n }\n\n private trackMetadataModuleIfChanged(\n props: InspectorMetadataModuleViewedTelemetryProps,\n fingerprint: string,\n ): void {\n if (this.metadataTelemetryFingerprints.get(props.module) === fingerprint) {\n return;\n }\n this.metadataTelemetryFingerprints.set(props.module, fingerprint);\n try {\n trackMetadataModuleViewed(props);\n } catch {\n // Telemetry is best-effort and must never break Inspector rendering.\n }\n }\n\n private maybeTrackInspectorMetadataViews(): void {\n if (\n !this.isOpen ||\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n\n const { identity, plan } = this.inspectorMetadataProjection;\n const license_bucket: InspectorMetadataLicenseBucket =\n this.inspectorMetadataProjection.licenseState;\n const telemetryContext = this.getMetadataTelemetryContext();\n const contextFingerprint = [\n telemetryContext.usage_bucket,\n telemetryContext.expiry_bucket,\n telemetryContext.group_key ?? null,\n telemetryContext.leaf_key ?? null,\n ];\n\n if (identity) {\n this.trackMetadataModuleIfChanged(\n { module: \"identity\", license_bucket, ...telemetryContext },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n identity.organizationName,\n identity.projectName,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"identity\");\n }\n\n if (plan) {\n this.trackMetadataModuleIfChanged(\n { module: \"plan\", license_bucket, ...telemetryContext },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n plan.code,\n plan.label,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"plan\");\n }\n\n const visibleAction = this.getVisibleInspectorMetadataAction();\n if (visibleAction) {\n const { action, placement } = visibleAction;\n const action_placement = getMetadataActionPlacement(placement);\n this.trackMetadataModuleIfChanged(\n {\n module: \"action\",\n action_kind: action.kind,\n license_bucket,\n ...telemetryContext,\n action_placement,\n },\n JSON.stringify([\n license_bucket,\n ...contextFingerprint,\n action_placement,\n action.kind,\n action.url,\n ]),\n );\n } else {\n this.metadataTelemetryFingerprints.delete(\"action\");\n }\n }\n\n private handleInspectorMetadataActionClick = (\n action: InspectorMetadataAction,\n placement: \"threads-footer\" | \"locked\",\n ): void => {\n if (\n !this.isOpen ||\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n if (action.kind === \"enable_intelligence\") {\n this.handleThreadsIntelligenceSignupClick();\n return;\n }\n try {\n trackMetadataActionClicked({\n action_kind: action.kind,\n license_bucket: this.inspectorMetadataProjection.licenseState,\n ...this.getMetadataTelemetryContext(),\n action_placement: getMetadataActionPlacement(placement),\n });\n } catch {\n // Telemetry is best-effort and must never break action navigation.\n }\n };\n\n // Fires `whats_new_clicked` at most once per `${bannerId}:${cta}` per mount\n // so copy-button retries and accidental multi-clicks don't inflate funnel\n // counts. `body` is the only cta left now that dismissal is gone.\n private trackWhatsNewClickedOnce(opts: { cta: \"body\" }): void {\n if (\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected ||\n this.core?.telemetryDisabled\n ) {\n return;\n }\n const id = this.announcementTimestamp;\n if (!id) return;\n const key = `${id}:${opts.cta}`;\n if (this.clickedBannerIds.has(key)) return;\n this.clickedBannerIds.add(key);\n trackWhatsNewClicked({\n banner_id: id,\n cta: opts.cta,\n cta_label: this.announcementCtaLabel ?? undefined,\n });\n }\n\n private handleTalkToEngineerClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackTalkToEngineerClicked(\n this.getThreadsCtaTelemetryProps(\"talk_to_engineer\", \"sidebar_footer\"),\n );\n };\n\n private handleThreadsIntelligenceSignupClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackThreadsIntelligenceSignupClicked(\n this.getThreadsCtaTelemetryProps(\"signup\", \"threads_locked\"),\n );\n };\n\n private handleThreadsTalkToEngineerClick = (): void => {\n if (this.core?.telemetryDisabled) return;\n trackThreadsTalkToEngineerClicked(\n this.getThreadsCtaTelemetryProps(\"talk_to_engineer\", \"threads_locked\"),\n );\n };\n\n private handleThreadDividerPointerDown = (event: PointerEvent) => {\n this.threadDividerResizing = true;\n this.threadDividerPointerId = event.pointerId;\n this.threadDividerStartX = event.clientX;\n this.threadDividerStartWidth = this.threadListWidth;\n (event.currentTarget as HTMLElement).setPointerCapture(event.pointerId);\n event.preventDefault();\n };\n\n private handleThreadDividerPointerMove = (event: PointerEvent) => {\n if (\n !this.threadDividerResizing ||\n this.threadDividerPointerId !== event.pointerId\n )\n return;\n const delta = event.clientX - this.threadDividerStartX;\n this.threadListWidth = Math.max(\n 180,\n Math.min(480, this.threadDividerStartWidth + delta),\n );\n this.requestUpdate();\n };\n\n private handleThreadDividerPointerUp = (event: PointerEvent) => {\n if (this.threadDividerPointerId !== event.pointerId) return;\n const target = event.currentTarget as HTMLElement;\n if (target.hasPointerCapture(this.threadDividerPointerId)) {\n target.releasePointerCapture(this.threadDividerPointerId);\n }\n this.threadDividerResizing = false;\n };\n\n private trackThreadsViewStateOnce(\n state: \"locked\" | \"empty_enabled\" | \"enabled\",\n ): void {\n if (this.core?.telemetryDisabled) return;\n const key = `${state}:${this.getThreadServiceStatus()}`;\n if (this.viewedThreadsTelemetryStates.has(key)) return;\n this.viewedThreadsTelemetryStates.add(key);\n const props = this.getThreadsTelemetryProps();\n if (state === \"locked\") {\n trackThreadsLockedViewed(props);\n } else if (state === \"empty_enabled\") {\n trackThreadsEmptyEnabledViewed(props);\n } else {\n trackThreadsEnabledViewed(props);\n }\n }\n\n private shouldRenderExampleThreads(\n displayThreads: ɵThread[],\n threadsErrorMessage: string | null,\n threadsLoading: boolean,\n ): boolean {\n return (\n !threadsErrorMessage && !threadsLoading && displayThreads.length === 0\n );\n }\n\n private isExampleThreadId(threadId: string | null | undefined): boolean {\n return THREADS_EXAMPLE_THREADS.some((thread) => thread.id === threadId);\n }\n\n private getExampleThreadProvider(threadId: string): ThreadDebuggerProvider {\n const cached = this.exampleThreadProviders.get(threadId);\n if (cached) return cached;\n const thread = THREADS_EXAMPLE_THREADS.find((item) => item.id === threadId);\n const details = THREADS_EXAMPLE_DETAILS[threadId];\n const provider: ThreadDebuggerProvider = {\n getThreadMetadata: async () =>\n thread\n ? {\n id: thread.id,\n name: thread.name,\n agentId: thread.agentId,\n endUserId: \"example-user\",\n status: \"completed\",\n createdAt: thread.createdAt,\n updatedAt: thread.updatedAt,\n }\n : null,\n getMessages: async () => details?.messages ?? [],\n getEvents: async () => details?.events ?? [],\n getState: async () => details?.state ?? null,\n };\n this.exampleThreadProviders.set(threadId, provider);\n return provider;\n }\n\n private trackThreadsExampleViewedOnce(): void {\n if (this.core?.telemetryDisabled) return;\n for (const thread of THREADS_EXAMPLE_THREADS) {\n const exampleKind = getExampleKind(thread.id);\n if (!exampleKind || this.viewedExampleKinds.has(exampleKind)) continue;\n this.viewedExampleKinds.add(exampleKind);\n trackThreadsExampleViewed({\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n });\n }\n }\n\n private trackThreadsExampleSelectedOnce(threadId: string): void {\n if (this.core?.telemetryDisabled) return;\n const exampleKind = getExampleKind(threadId);\n if (!exampleKind || this.selectedExampleKinds.has(exampleKind)) return;\n this.selectedExampleKinds.add(exampleKind);\n trackThreadsExampleSelected({\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n });\n }\n\n private subscribeToInspectorThreadBridge(): void {\n this.unsubscribeFromInspectorThreadBridge();\n if (!isInspectorThreadBridgeEnabled()) return;\n this.inspectorBridgeUnsubscribers.push(\n onInspectorActiveThread((payload) => {\n if (payload.requestId !== this.activeViewInAppRequestId) return;\n this.inAppThreadId = payload.threadId;\n this.inAppAgentId = payload.agentId;\n this.inAppSource = payload.source;\n if (payload.source === \"app\") {\n this.activeViewInAppRequestId = null;\n this.viewInAppError = null;\n }\n this.requestUpdate();\n }),\n onInspectorViewThreadResult((payload) => {\n if (payload.requestId !== this.activeViewInAppRequestId) return;\n if (payload.ok) {\n this.viewInAppError = null;\n this.inAppThreadId = payload.threadId;\n this.inAppAgentId = payload.agentId;\n this.inAppSource = \"override\";\n } else {\n this.activeViewInAppRequestId = null;\n this.inAppThreadId = null;\n this.inAppAgentId = null;\n this.inAppSource = null;\n this.viewInAppError =\n \"The app could not load that thread. The previous chat is back.\";\n }\n this.requestUpdate();\n }),\n );\n }\n\n private unsubscribeFromInspectorThreadBridge(): void {\n for (const unsubscribe of this.inspectorBridgeUnsubscribers) {\n unsubscribe();\n }\n this.inspectorBridgeUnsubscribers = [];\n }\n\n private getViewInAppMode(\n thread: ɵThread | null,\n isExample: boolean,\n ): \"hidden\" | \"view\" | \"stop\" {\n if (!isInspectorThreadBridgeEnabled()) return \"hidden\";\n if (!thread || isExample) return \"hidden\";\n if (\n this.activeViewInAppRequestId &&\n this.inAppSource === \"override\" &&\n this.inAppThreadId === thread.id\n ) {\n return \"stop\";\n }\n return \"view\";\n }\n\n private handleViewInApp = (): void => {\n const thread = this.getSelectedRealThread();\n if (!thread) return;\n if (this.activeViewInAppRequestId && this.inAppAgentId) {\n emitInspectorStopViewing({\n requestId: this.activeViewInAppRequestId,\n agentId: this.inAppAgentId,\n });\n }\n this.viewInAppError = null;\n const requestId = createInspectorThreadRequestId();\n this.activeViewInAppRequestId = requestId;\n const handled = emitInspectorViewThread({\n requestId,\n threadId: thread.id,\n agentId: thread.agentId,\n });\n if (!handled) {\n this.activeViewInAppRequestId = null;\n this.inAppThreadId = null;\n this.inAppAgentId = null;\n this.inAppSource = null;\n this.viewInAppError = \"No official chat for this agent is on the page.\";\n }\n this.requestUpdate();\n };\n\n private handleStopViewing = (): void => {\n const requestId = this.activeViewInAppRequestId;\n const agentId = this.inAppAgentId;\n if (!requestId || !agentId) return;\n this.viewInAppError = null;\n emitInspectorStopViewing({ requestId, agentId });\n this.requestUpdate();\n };\n\n private getSelectedRealThread(): ɵThread | null {\n if (!this.selectedThreadId) return null;\n if (this.selectedThreadId === this.selectedLocalExampleThreadId) {\n return null;\n }\n return (\n this.getActiveThreadsState().displayThreads.find(\n (thread) => thread.id === this.selectedThreadId,\n ) ?? null\n );\n }\n\n private getCurrentExampleTourProps():\n | (InspectorThreadTelemetryProps &\n Readonly<{\n example_kind: ExampleKind;\n tour_step: ExampleTourStep;\n tour_tab: ExampleTourTab;\n }>)\n | undefined {\n const exampleKind = this.selectedThreadId\n ? getExampleKind(this.selectedThreadId)\n : undefined;\n const tourPair = getExampleTourTelemetryPair(this.exampleTourStep);\n if (!exampleKind || !tourPair) return undefined;\n return {\n ...this.getThreadsTelemetryProps(),\n example_kind: exampleKind,\n ...tourPair,\n };\n }\n\n private trackThreadsExampleTourStepViewedOnce(): void {\n if (this.core?.telemetryDisabled || !this.selectedThreadId) return;\n const props = this.getCurrentExampleTourProps();\n if (!props) return;\n const key = `${props.example_kind}:${props.tour_step}`;\n if (this.viewedExampleTourSteps.has(key)) return;\n this.viewedExampleTourSteps.add(key);\n trackThreadsExampleTourStepViewed(props);\n }\n\n private syncExampleTourTab(): void {\n const step =\n THREADS_EXAMPLE_TOUR_STEPS[this.exampleTourStep] ??\n THREADS_EXAMPLE_TOUR_STEPS[0]!;\n if (!step) return;\n void this.updateComplete.then(() => {\n const details = this.activeRoot.querySelector(\"cpk-thread-details\") as\n | (ɵCpkThreadDetails & { selectTab?: (id: ThreadDetailsTab) => void })\n | null;\n details?.selectTab?.(step.tab);\n });\n }\n\n private startExampleTour(autoStarted: boolean): void {\n if (!this.selectedThreadId) return;\n this.exampleTourActive = true;\n this.exampleTourStep = 0;\n if (autoStarted) {\n this.exampleTourAutoShown = true;\n if (!this.core?.telemetryDisabled) {\n const props = this.getCurrentExampleTourProps();\n if (props) trackThreadsExampleTourStarted(props);\n }\n } else if (!this.core?.telemetryDisabled) {\n const props = this.getCurrentExampleTourProps();\n if (props) trackThreadsExampleTourReopened(props);\n }\n this.trackThreadsExampleTourStepViewedOnce();\n this.syncExampleTourTab();\n this.requestUpdate();\n }\n\n private setExampleTourStep(nextStep: number): void {\n const telemetryStepIsValid =\n getExampleTourTelemetryPair(nextStep) !== undefined;\n this.exampleTourStep = Math.max(\n 0,\n Math.min(THREADS_EXAMPLE_TOUR_STEPS.length - 1, nextStep),\n );\n if (telemetryStepIsValid) this.trackThreadsExampleTourStepViewedOnce();\n this.syncExampleTourTab();\n this.requestUpdate();\n }\n\n private dismissExampleTour(method: \"skip\" | \"done\"): void {\n if (!this.selectedThreadId) return;\n this.exampleTourActive = false;\n this.exampleTourDismissed = true;\n this.writeThreadsExampleTourDismissed();\n if (!this.core?.telemetryDisabled) {\n const currentProps = this.getCurrentExampleTourProps();\n if (currentProps) {\n const props = { ...currentProps, dismiss_method: method };\n if (method === \"done\") {\n trackThreadsExampleTourCompleted(props);\n } else {\n trackThreadsExampleTourDismissed(props);\n }\n }\n }\n this.requestUpdate();\n }\n\n private handleThreadsThreadSelected(\n threadId: string,\n showingExamples: boolean,\n ): void {\n this.requestedThreadId = null;\n this.focusedThreadMessageId = null;\n if (\n showingExamples &&\n this.selectedThreadId === threadId &&\n this.selectedLocalExampleThreadId === threadId\n ) {\n this.selectedThreadId = null;\n this.selectedRealThreadIsExplicit = false;\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n this.requestUpdate();\n return;\n }\n\n this.tryFromHereError = null;\n this.selectedThreadId = threadId;\n if (showingExamples && this.isExampleThreadId(threadId)) {\n this.selectedRealThreadIsExplicit = false;\n this.selectedLocalExampleThreadId = threadId;\n this.trackThreadsExampleSelectedOnce(threadId);\n if (!this.exampleTourDismissed && !this.exampleTourAutoShown) {\n this.startExampleTour(true);\n } else {\n this.exampleTourActive = false;\n }\n } else {\n const { displayThreads } = this.getActiveThreadsState();\n this.selectedRealThreadIsExplicit = displayThreads.some(\n (thread) => thread.id === threadId,\n );\n this.selectedLocalExampleThreadId = null;\n this.exampleTourActive = false;\n }\n this.requestUpdate();\n }\n\n private readThreadsExampleTourDismissed(): boolean {\n if (typeof window === \"undefined\") return false;\n try {\n const raw = window.localStorage.getItem(THREADS_EXAMPLE_TOUR_STORAGE_KEY);\n if (!raw) return false;\n const value = JSON.parse(raw) as { dismissed?: unknown };\n return value.dismissed === true;\n } catch {\n return false;\n }\n }\n\n private writeThreadsExampleTourDismissed(): void {\n if (typeof window === \"undefined\") return;\n try {\n window.localStorage.setItem(\n THREADS_EXAMPLE_TOUR_STORAGE_KEY,\n JSON.stringify({ dismissed: true }),\n );\n } catch {\n // Persistence is best-effort; the inspector should keep working without it.\n }\n }\n\n /** Cancels the one deferred gate without disturbing a newer lifecycle. */\n private cancelThreadsExampleOverviewVideoGate(): void {\n if (this.threadsExampleOverviewVideoLoadTimer !== null) {\n if (typeof window !== \"undefined\") {\n window.clearTimeout(this.threadsExampleOverviewVideoLoadTimer);\n }\n this.threadsExampleOverviewVideoLoadTimer = null;\n }\n if (this.threadsExampleOverviewVideoIdleCallbackId !== null) {\n if (\n typeof window !== \"undefined\" &&\n typeof window.cancelIdleCallback === \"function\"\n ) {\n window.cancelIdleCallback(\n this.threadsExampleOverviewVideoIdleCallbackId,\n );\n }\n this.threadsExampleOverviewVideoIdleCallbackId = null;\n }\n }\n\n /** Returns whether media work still belongs to the mounted lifecycle. */\n private isCurrentThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): boolean {\n return (\n this.isConnected &&\n video.isConnected &&\n this.threadsExampleOverviewVideoElement === video &&\n this.threadsExampleOverviewVideoLifecycleGeneration ===\n lifecycleGeneration\n );\n }\n\n /** Invalidates any unresolved play request without exposing another state. */\n private invalidateThreadsExampleOverviewVideoPlay(): void {\n this.threadsExampleOverviewVideoPlayAttemptGeneration += 1;\n this.threadsExampleOverviewVideoPlayPromise = null;\n }\n\n /** Moves a current media lifecycle into its readable failure state. */\n private failThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): void {\n if (\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.threadsExampleOverviewVideoLoaded = false;\n this.threadsExampleOverviewVideoState = \"failed\";\n this.requestUpdate();\n }\n\n /** Settles one guarded play promise and ignores stale completion. */\n private async settleThreadsExampleOverviewVideoPlay(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n playAttemptGeneration: number,\n playback: Promise<void>,\n ): Promise<void> {\n try {\n await playback;\n if (\n this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration) &&\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.threadsExampleOverviewVideoState = \"playing\";\n this.requestUpdate();\n }\n } catch {\n if (\n this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration) &&\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration\n ) {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n } finally {\n if (\n this.threadsExampleOverviewVideoPlayAttemptGeneration ===\n playAttemptGeneration\n ) {\n this.threadsExampleOverviewVideoPlayPromise = null;\n }\n }\n }\n\n /** Starts at most one play request for the current media lifecycle. */\n private playThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n ): void {\n if (\n this.threadsExampleOverviewVideoPlayPromise !== null ||\n this.threadsExampleOverviewVideoState === \"deferred\" ||\n this.threadsExampleOverviewVideoState === \"failed\" ||\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n\n const playAttemptGeneration =\n this.threadsExampleOverviewVideoPlayAttemptGeneration + 1;\n this.threadsExampleOverviewVideoPlayAttemptGeneration =\n playAttemptGeneration;\n try {\n const playback = Promise.resolve(video.play());\n this.threadsExampleOverviewVideoPlayPromise =\n this.settleThreadsExampleOverviewVideoPlay(\n video,\n lifecycleGeneration,\n playAttemptGeneration,\n playback,\n );\n } catch {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n }\n\n /** Attaches the sole source for a generation and optionally starts playback. */\n private activateThreadsExampleOverviewVideo(\n video: HTMLVideoElement,\n lifecycleGeneration: number,\n play: boolean,\n ): void {\n if (\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n !this.isCurrentThreadsExampleOverviewVideo(video, lifecycleGeneration)\n ) {\n return;\n }\n\n this.threadsExampleOverviewVideoState = \"ready\";\n this.threadsExampleOverviewVideoLoaded = false;\n video.autoplay = !this.threadsExampleOverviewVideoReducedMotion;\n video.setAttribute(\"src\", THREADS_EXAMPLE_OVERVIEW_VIDEO_URL);\n this.requestUpdate();\n if (play) {\n this.playThreadsExampleOverviewVideo(video, lifecycleGeneration);\n }\n }\n\n /** Schedules exactly one idle or timer gate for the current video. */\n private scheduleThreadsExampleOverviewVideoLoad(): void {\n const video = this.threadsExampleOverviewVideoElement;\n if (\n !video ||\n !this.isConnected ||\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n this.threadsExampleOverviewVideoLoadTimer !== null ||\n this.threadsExampleOverviewVideoIdleCallbackId !== null ||\n typeof window === \"undefined\"\n ) {\n return;\n }\n\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n if (typeof window.requestIdleCallback === \"function\") {\n let idleCallbackId = 0;\n const loadVideo = () => {\n if (this.threadsExampleOverviewVideoIdleCallbackId !== idleCallbackId) {\n return;\n }\n this.threadsExampleOverviewVideoIdleCallbackId = null;\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n !this.threadsExampleOverviewVideoReducedMotion,\n );\n };\n idleCallbackId = window.requestIdleCallback(loadVideo, { timeout: 1200 });\n this.threadsExampleOverviewVideoIdleCallbackId = idleCallbackId;\n return;\n }\n\n const loadTimer = window.setTimeout(() => {\n if (this.threadsExampleOverviewVideoLoadTimer !== loadTimer) {\n return;\n }\n this.threadsExampleOverviewVideoLoadTimer = null;\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n !this.threadsExampleOverviewVideoReducedMotion,\n );\n }, 450);\n this.threadsExampleOverviewVideoLoadTimer = loadTimer;\n }\n\n /** Attaches one generation-scoped media listener set to the stable video. */\n private bindThreadsExampleOverviewVideo(video: HTMLVideoElement): void {\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n const listeners: ThreadsExampleOverviewVideoListeners = {\n loadeddata: () => {\n if (\n !this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) ||\n this.threadsExampleOverviewVideoState === \"deferred\" ||\n this.threadsExampleOverviewVideoState === \"failed\"\n ) {\n return;\n }\n this.threadsExampleOverviewVideoLoaded = true;\n this.requestUpdate();\n },\n play: () => {\n if (\n this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) &&\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.threadsExampleOverviewVideoState = \"playing\";\n this.requestUpdate();\n }\n },\n pause: () => {\n if (\n this.isCurrentThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n ) &&\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n this.threadsExampleOverviewVideoState !== \"failed\"\n ) {\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.threadsExampleOverviewVideoState = \"ready\";\n this.requestUpdate();\n }\n },\n error: () => {\n this.failThreadsExampleOverviewVideo(video, lifecycleGeneration);\n },\n };\n this.threadsExampleOverviewVideoElement = video;\n this.threadsExampleOverviewVideoListeners = listeners;\n video.addEventListener(\"loadeddata\", listeners.loadeddata);\n video.addEventListener(\"play\", listeners.play);\n video.addEventListener(\"pause\", listeners.pause);\n video.addEventListener(\"error\", listeners.error);\n video.muted = true;\n video.loop = true;\n video.playsInline = true;\n video.autoplay =\n this.threadsExampleOverviewVideoState !== \"deferred\" &&\n !this.threadsExampleOverviewVideoReducedMotion;\n }\n\n /** Tears down gates, listeners, playback, and source in cleanup order. */\n private cleanupThreadsExampleOverviewVideo(): void {\n const video = this.threadsExampleOverviewVideoElement;\n if (video) {\n this.threadsExampleOverviewVideoLifecycleGeneration += 1;\n }\n this.invalidateThreadsExampleOverviewVideoPlay();\n this.cancelThreadsExampleOverviewVideoGate();\n this.threadsExampleOverviewVideoPlayOnNextBind = false;\n\n const listeners = this.threadsExampleOverviewVideoListeners;\n if (video && listeners) {\n video.removeEventListener(\"loadeddata\", listeners.loadeddata);\n video.removeEventListener(\"play\", listeners.play);\n video.removeEventListener(\"pause\", listeners.pause);\n video.removeEventListener(\"error\", listeners.error);\n }\n this.threadsExampleOverviewVideoElement = null;\n this.threadsExampleOverviewVideoListeners = null;\n\n if (video) {\n try {\n video.pause();\n } catch {\n // Some DOM shims expose media methods that throw instead of no-oping.\n }\n video.removeAttribute(\"src\");\n try {\n video.load();\n } catch {\n // Cleanup must stay synchronous and never surface media abort errors.\n }\n }\n this.threadsExampleOverviewVideoLoaded = false;\n this.threadsExampleOverviewVideoState = \"deferred\";\n }\n\n /** Reconciles the rendered media node with its current lifecycle. */\n private syncThreadsExampleOverviewVideo(): void {\n const video = this.activeRoot.querySelector<HTMLVideoElement>(\n \".cpk-threads-overview-video\",\n );\n if (!video) {\n if (\n this.threadsExampleOverviewVideoElement ||\n this.threadsExampleOverviewVideoState !== \"deferred\" ||\n this.threadsExampleOverviewVideoLoadTimer !== null ||\n this.threadsExampleOverviewVideoIdleCallbackId !== null ||\n this.threadsExampleOverviewVideoPlayOnNextBind\n ) {\n this.cleanupThreadsExampleOverviewVideo();\n }\n return;\n }\n\n if (this.threadsExampleOverviewVideoElement !== video) {\n if (this.threadsExampleOverviewVideoElement) {\n this.cleanupThreadsExampleOverviewVideo();\n }\n this.bindThreadsExampleOverviewVideo(video);\n }\n if (this.threadsExampleOverviewVideoPlayOnNextBind) {\n this.threadsExampleOverviewVideoPlayOnNextBind = false;\n this.activateThreadsExampleOverviewVideo(\n video,\n this.threadsExampleOverviewVideoLifecycleGeneration,\n true,\n );\n return;\n }\n this.scheduleThreadsExampleOverviewVideoLoad();\n }\n\n /** Handles the external native Play/Pause control. */\n private handleThreadsExampleOverviewVideoControl = (): void => {\n const video = this.threadsExampleOverviewVideoElement;\n if (!video) return;\n\n if (this.threadsExampleOverviewVideoState === \"playing\") {\n this.invalidateThreadsExampleOverviewVideoPlay();\n try {\n video.pause();\n } catch {\n // Keep the visible state usable when a media shim cannot pause.\n }\n this.threadsExampleOverviewVideoState = \"ready\";\n this.requestUpdate();\n return;\n }\n\n if (this.threadsExampleOverviewVideoState === \"failed\") {\n this.cleanupThreadsExampleOverviewVideo();\n if (!this.isConnected || !video.isConnected) return;\n this.threadsExampleOverviewVideoPlayOnNextBind = true;\n this.requestUpdate();\n return;\n }\n\n this.cancelThreadsExampleOverviewVideoGate();\n const lifecycleGeneration =\n this.threadsExampleOverviewVideoLifecycleGeneration;\n if (this.threadsExampleOverviewVideoState === \"deferred\") {\n this.activateThreadsExampleOverviewVideo(\n video,\n lifecycleGeneration,\n true,\n );\n return;\n }\n this.playThreadsExampleOverviewVideo(video, lifecycleGeneration);\n };\n\n private renderThreadsExampleOverviewVideo() {\n const isPlaying = this.threadsExampleOverviewVideoState === \"playing\";\n const sourceIsAttached =\n this.threadsExampleOverviewVideoState !== \"deferred\";\n const video = html`<video\n class=\"cpk-threads-overview-video\"\n data-loaded=${this.threadsExampleOverviewVideoLoaded}\n ?autoplay=${\n sourceIsAttached && !this.threadsExampleOverviewVideoReducedMotion\n }\n .autoplay=${\n sourceIsAttached && !this.threadsExampleOverviewVideoReducedMotion\n }\n loop\n .loop=${true}\n muted\n .muted=${true}\n playsinline\n .playsInline=${true}\n preload=\"metadata\"\n ></video>`;\n // Alternating template identities retire the prior media node after cleanup.\n // The node remains stable for every render within one lifecycle generation.\n const generationScopedVideo =\n this.threadsExampleOverviewVideoLifecycleGeneration % 2 === 0\n ? html`<!-- cpk-video-generation-even -->${video}`\n : html`<!-- cpk-video-generation-odd -->${video}`;\n return html`\n <div class=\"cpk-threads-overview-video-frame\" aria-hidden=\"true\">\n ${generationScopedVideo}\n </div>\n <button\n class=\"cpk-threads-overview-video-control\"\n type=\"button\"\n aria-pressed=${isPlaying ? \"false\" : \"true\"}\n @click=${this.handleThreadsExampleOverviewVideoControl}\n >\n ${isPlaying ? \"Pause demo\" : \"Play demo\"}\n </button>\n ${\n this.threadsExampleOverviewVideoState === \"failed\"\n ? html`\n <p class=\"cpk-threads-overview-video-fallback\" role=\"status\">\n ${THREADS_EXAMPLE_OVERVIEW_VIDEO_FALLBACK}\n </p>\n `\n : nothing\n }\n `;\n }\n\n private renderThreadsExampleOverview() {\n const onboardingAction = this.getThreadsEmptyOnboardingAction();\n return html`\n <div class=\"cpk-threads-overview\">\n <div class=\"cpk-threads-overview-content\">\n <h2 class=\"cpk-threads-overview-title\">\n Threads are persistent, inspectable conversations\n </h2>\n ${this.renderThreadsExampleOverviewVideo()}\n <p class=\"cpk-threads-overview-copy\">\n Take a tour with the example threads in the sidebar. Then, start\n chatting in your app to create the first real thread.\n </p>\n <div class=\"cpk-threads-overview-actions\">\n <a\n href=${this.getThreadsDocsUrl()}\n target=\"_blank\"\n rel=\"noopener\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-primary\"\n >\n Learn how Threads work\n </a>\n <a\n href=${onboardingAction.href}\n target=\"_blank\"\n rel=\"noopener\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-secondary\"\n >\n ${onboardingAction.label}\n </a>\n </div>\n </div>\n </div>\n `;\n }\n\n private renderLockedFeatureOverview({\n serviceId,\n featureName,\n heading,\n description,\n videoUrl,\n videoTitle,\n outlineItems,\n setupPrompt,\n }: {\n serviceId: HomeFeaturePromptId;\n featureName: string;\n heading: string;\n description: string;\n videoUrl: string;\n videoTitle: string;\n outlineItems: ReadonlyArray<LockedFeatureOutlineItem>;\n setupPrompt?: Readonly<{\n serviceId: HomeFeaturePromptId;\n copyState: HomeFeaturePromptCopyState;\n onClick: (event: Event) => void;\n }>;\n }) {\n return html`\n <div\n class=\"cpk-locked-feature\"\n data-inspector-locked-feature=${serviceId}\n >\n <div class=\"cpk-locked-feature-layout\">\n <div class=\"cpk-locked-feature-hero\">\n <div class=\"cpk-locked-feature-copy\">\n <div class=\"cpk-locked-feature-name\">\n <span class=\"cpk-locked-feature-icon\" aria-hidden=\"true\">\n ${\n serviceId === \"threads\"\n ? unsafeHTML(this.customTabIcons.threads)\n : this.renderIcon(\"Brain\")\n }\n </span>\n ${featureName}\n </div>\n <h2 class=\"cpk-locked-feature-title\">${heading}</h2>\n <p class=\"cpk-locked-feature-description\">${description}</p>\n <div class=\"cpk-threads-overview-actions\">\n ${this.renderFeatureSetupPrompt(\n setupPrompt?.serviceId ?? serviceId,\n \"inspector-account-cta cpk-locked-feature-setup-cta\",\n setupPrompt\n ? {\n copyState: setupPrompt.copyState,\n onClick: setupPrompt.onClick,\n }\n : undefined,\n )}\n <a\n data-inspector-locked-feature-talk=${serviceId}\n href=${this.getTalkToEngineerUrl()}\n target=\"_blank\"\n rel=\"noopener noreferrer\"\n aria-label=\"Talk to an Engineer (opens in a new tab)\"\n class=\"cpk-threads-overview-action cpk-threads-overview-action-secondary\"\n @click=${this.handleThreadsTalkToEngineerClick}\n >\n Talk to an Engineer\n </a>\n </div>\n </div>\n <div class=\"cpk-locked-feature-media\">\n <div class=\"cpk-threads-overview-video-frame cpk-locked-feature-video\">\n <iframe\n class=\"cpk-threads-overview-video-embed\"\n data-inspector-feature-video=${serviceId}\n src=${videoUrl}\n title=${videoTitle}\n loading=\"lazy\"\n allow=\"fullscreen; picture-in-picture\"\n allowfullscreen\n ></iframe>\n </div>\n </div>\n </div>\n <section\n class=\"cpk-locked-feature-outline\"\n data-inspector-feature-outline=${serviceId}\n aria-label=\"${featureName} capabilities\"\n >\n <div class=\"cpk-locked-feature-outline-list\">\n ${outlineItems.map(\n (item) => html`\n <section class=\"cpk-locked-feature-outline-item\">\n <h3>\n <span\n class=\"cpk-locked-feature-outline-icon\"\n aria-hidden=\"true\"\n >\n ${this.renderIcon(item.icon)}\n </span>\n ${item.title}\n </h3>\n <p>${item.description}</p>\n </section>\n `,\n )}\n </div>\n </section>\n </div>\n </div>\n `;\n }\n\n private renderThreadsExampleTour() {\n if (\n !this.selectedThreadId ||\n this.selectedThreadId !== this.selectedLocalExampleThreadId\n ) {\n return nothing;\n }\n\n if (!this.exampleTourActive) {\n return html`\n <button\n class=\"cpk-threads-tour-launch\"\n type=\"button\"\n @click=${() => this.startExampleTour(false)}\n >\n Show tour\n </button>\n `;\n }\n\n const step =\n THREADS_EXAMPLE_TOUR_STEPS[this.exampleTourStep] ??\n THREADS_EXAMPLE_TOUR_STEPS[0]!;\n const isFirst = this.exampleTourStep === 0;\n const isLast =\n this.exampleTourStep === THREADS_EXAMPLE_TOUR_STEPS.length - 1;\n\n return html`\n <div\n class=\"cpk-threads-tour\"\n role=\"dialog\"\n aria-label=\"Example thread tour\"\n >\n <div class=\"cpk-threads-tour-step\">\n ${this.exampleTourStep + 1}/${THREADS_EXAMPLE_TOUR_STEPS.length}\n ${step.label}\n </div>\n <div class=\"cpk-threads-tour-title\">${step.title}</div>\n <div class=\"cpk-threads-tour-copy\">${step.body}</div>\n <div class=\"cpk-threads-tour-actions\">\n <button\n class=\"cpk-threads-tour-skip\"\n type=\"button\"\n @click=${() => this.dismissExampleTour(\"skip\")}\n >\n Skip\n </button>\n <div class=\"cpk-threads-tour-nav\">\n <button\n class=\"cpk-threads-tour-button cpk-threads-tour-button-secondary\"\n type=\"button\"\n ?disabled=${isFirst}\n @click=${() => this.setExampleTourStep(this.exampleTourStep - 1)}\n >\n Back\n </button>\n <button\n class=\"cpk-threads-tour-button cpk-threads-tour-button-primary\"\n type=\"button\"\n @click=${() =>\n isLast\n ? this.dismissExampleTour(\"done\")\n : this.setExampleTourStep(this.exampleTourStep + 1)}\n >\n ${isLast ? \"Done\" : \"Next\"}\n </button>\n </div>\n </div>\n </div>\n `;\n }\n\n /**\n * Renders the realtime-connection indicator in the memory-store header.\n * Only `\"connected\"` shows the live (green-dot) state; `\"connecting\"` shows a\n * muted amber \"reconnecting\" and `\"unavailable\"` a muted grey \"offline\", so\n * the indicator never claims \"live\" over a frozen snapshot once the realtime\n * socket has permanently given up.\n */\n private renderMemoryRealtimeIndicator() {\n const status = this._memoriesRealtimeStatus;\n const connected = status === \"connected\";\n const dotColor = connected\n ? \"#22c55e\"\n : status === \"connecting\"\n ? \"#f59e0b\"\n : \"#9ca3af\";\n const label =\n status === \"connected\"\n ? \"live\"\n : status === \"connecting\"\n ? \"reconnecting\"\n : \"offline\";\n return html`\n <span\n style=\"\n display: inline-flex;\n align-items: center;\n gap: 4px;\n font-size: 10px;\n font-weight: 500;\n color: ${connected ? \"#57575b\" : \"#68686e\"};\n \"\n >\n <span\n style=\"\n display: inline-block;\n width: 6px;\n height: 6px;\n border-radius: 50%;\n background: ${dotColor};\n \"\n ></span>\n ${label}\n </span>\n `;\n }\n\n private renderMemoriesView() {\n const state = deriveLearningViewState({\n supported: this.learningSupported,\n loading: this.learningLoading,\n error: this.learningError,\n snapshot: this.learningSnapshot,\n setupActive: this.isLearningSetupActive(),\n });\n if (state === \"landing\") {\n return this.renderLockedFeatureOverview({\n serviceId: \"memory\",\n featureName: \"Automatic Learning\",\n heading: \"Turn every interaction into reusable context.\",\n description:\n \"Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.\",\n videoUrl: LEARNING_LOCKED_VIDEO_URL,\n videoTitle: \"CopilotKit Learning overview\",\n outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE,\n setupPrompt: {\n serviceId: \"memory\",\n copyState: this.learningPromptCopyState,\n onClick: (event) => void this.handleLearningSetupCopy(event),\n },\n });\n }\n return html`\n <cpk-learning-view\n data-color-scheme=${this.colorScheme}\n .supported=${this.learningSupported}\n .loading=${this.learningLoading}\n .refreshing=${this.learningRefreshing}\n .error=${this.learningError}\n .snapshot=${this.learningSnapshot}\n .setupActive=${this.isLearningSetupActive()}\n .copyState=${this.learningPromptCopyState}\n .recopyState=${this.learningPromptRecopyState}\n .setupPrompt=${createFeatureOnboardingPrompt(\n \"memory\",\n this.getOnboardingRunId(),\n )}\n @learning-retry=${() =>\n this.refreshLearningSnapshot({\n preserve: this.learningSnapshot !== null,\n })}\n @learning-copy-setup=${(event: Event) =>\n this.handleLearningSetupCopy(event)}\n @learning-recopy-setup=${(event: Event) =>\n this.handleLearningSetupCopy(event, true)}\n @learning-go-back=${this.handleLearningGoBack}\n @learning-page=${(event: CustomEvent) =>\n this.handleLearningPage(\n event as CustomEvent<{\n section: \"skills\" | \"insights\";\n page: number;\n }>,\n )}\n @learning-open-evidence=${(event: CustomEvent) =>\n this.handleLearningEvidence(\n event as CustomEvent<{\n threadId: string;\n messageId?: string;\n }>,\n )}\n @learning-evidence-opened=${() => {\n if (!this.core?.telemetryDisabled) trackLearningEvidenceOpened();\n }}\n @learning-skill-toggle=${(\n event: CustomEvent<{ action: \"expanded\" | \"collapsed\" }>,\n ) => {\n if (!this.core?.telemetryDisabled) {\n trackLearningSkillToggled({ action: event.detail.action });\n }\n }}\n @learning-web-link=${(\n event: CustomEvent<{\n category: \"learning\" | \"runs\" | \"candidates\";\n }>,\n ) => {\n if (!this.core?.telemetryDisabled) {\n trackLearningWebAppOpened({ category: event.detail.category });\n }\n }}\n ></cpk-learning-view>\n `;\n }\n\n /** Legacy Memory rendering kept isolated while published Memory APIs remain. */\n private renderLegacyMemoriesView() {\n // Once the user enters Learning, its lazy subscription is the capability\n // probe. Preserve the loading state while that request is in flight, then\n // let an unavailable response fall through to the setup gate.\n const learningEnabled = this.getHomeModel().services.some(\n (service) => service.id === \"memory\" && service.enabled,\n );\n // 1. Locked teaser — use the same entitlement-aware capability decision\n // as Home and the launcher so an unavailable feature always lands on its\n // setup path instead of an enabled-looking empty state.\n if (!learningEnabled) {\n return this.renderLockedFeatureOverview({\n serviceId: \"memory\",\n featureName: \"Automatic Learning\",\n heading: this._memoryStoreUnsupported\n ? \"Upgrade to enable Learning\"\n : \"Turn every interaction into reusable context.\",\n description: this._memoryStoreUnsupported\n ? \"Learning requires a newer version of @copilotkit/core and @copilotkit/react. Copy the setup prompt to upgrade and add long-term memory.\"\n : \"Learning captures durable information from agent interactions and brings it back when it matters, so your product gets more useful over time.\",\n videoUrl: LEARNING_LOCKED_VIDEO_URL,\n videoTitle: \"CopilotKit Learning overview\",\n outlineItems: LEARNING_LOCKED_FEATURE_OUTLINE,\n });\n }\n\n // 2. Full-screen error — only for a snapshot-LOAD failure (no memories\n // loaded). A mutation failure that arrives while memories are already on\n // screen must NOT blank the list; it is surfaced inline below (step 4).\n if (this._memoriesError && this._memories.length === 0) {\n return html`\n <div\n style=\"\n display: flex;\n height: 100%;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0333a\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span style=\"font-size: 13px; color: #c0333a;\">\n ${MEMORY_LOAD_ERROR_LABEL}\n </span>\n <span\n style=\"\n max-width: 320px;\n text-align: center;\n font-size: 11px;\n line-height: 1.5;\n color: #c0333a;\n \"\n >\n ${this._memoriesError.message}\n </span>\n <span\n style=\"\n max-width: 320px;\n text-align: center;\n font-size: 11px;\n line-height: 1.5;\n color: #c0333a;\n \"\n >\n ${EVENT_ERROR_GUIDANCE.memory.advice}\n </span>\n </div>\n `;\n }\n\n // 3. Initial loading placeholder (no memories yet to show behind it).\n if (this._memoriesLoading && this._memories.length === 0) {\n return html`\n <div\n style=\"\n display: flex;\n height: 100%;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"24\"\n height=\"24\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0c0c8\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path d=\"M21 12a9 9 0 1 1-6.219-8.56\" />\n </svg>\n <span style=\"font-size: 13px\">Loading learning…</span>\n </div>\n `;\n }\n\n // 4. Content — header + memory list.\n return html`\n <div\n style=\"display:flex;height:100%;overflow:hidden;flex-direction:column;\"\n >\n <div\n class=\"cpk-section-header\"\n style=\"display:flex;align-items:center;justify-content:space-between;\"\n >\n <h4>${LEARNING_VIEW_LABEL}</h4>\n <div style=\"display:flex;align-items:center;gap:6px;\">\n ${this.renderMemoryRealtimeIndicator()}\n <span\n style=\"\n font-size: 11px;\n font-weight: 500;\n color: #57575b;\n background: rgba(0,0,0,0.07);\n border-radius: 9999px;\n padding: 1px 7px;\n \"\n >\n ${this._memories.length}\n </span>\n </div>\n </div>\n ${\n this._memoriesError\n ? html`\n <div\n role=\"alert\"\n style=\"\n display: flex;\n align-items: flex-start;\n gap: 8px;\n flex-shrink: 0;\n border-bottom: 1px solid #f1c7c9;\n background: #fdf3f3;\n padding: 8px 12px;\n color: #c0333a;\n font-size: 12px;\n line-height: 1.45;\n \"\n >\n <svg\n width=\"16\"\n height=\"16\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0333a\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n style=\"flex-shrink:0;margin-top:1px;\"\n >\n <circle cx=\"12\" cy=\"12\" r=\"10\" />\n <line x1=\"12\" y1=\"8\" x2=\"12\" y2=\"12\" />\n <line x1=\"12\" y1=\"16\" x2=\"12.01\" y2=\"16\" />\n </svg>\n <span>Action failed: ${this._memoriesError.message}</span>\n </div>\n `\n : nothing\n }\n <div style=\"flex:1;min-height:0;overflow:hidden;\">\n <cpk-memory-list\n style=\"height:100%;\"\n data-color-scheme=${this.colorScheme}\n .memories=${this._memories}\n .recallResults=${this._recallResults}\n .recallLoading=${this._recallLoading}\n .recallError=${this._recallError}\n .recallQueryText=${this._recallQuery}\n @recallQueryChanged=${(e: CustomEvent<string>) => {\n this._recallQuery = e.detail;\n }}\n @recallSubmitted=${(e: CustomEvent<string>) => {\n this.runRecall(e.detail);\n }}\n @recallCleared=${() => {\n this.clearRecall();\n }}\n ></cpk-memory-list>\n </div>\n </div>\n `;\n }\n\n /** Renders trusted Threads usage and its independent plan action. */\n private renderThreadsUsageFooter() {\n const { usage, threadsFooterAction } = this.inspectorMetadataProjection;\n if (!usage && !threadsFooterAction) {\n return nothing;\n }\n\n let countLabel: string | undefined;\n let progressMax: number | undefined;\n let progressValue: number | undefined;\n const capacityState = this.getThreadsCapacityState();\n if (usage) {\n if (usage.limit.kind === \"finite\") {\n const overLimit = usage.used > usage.limit.value;\n const visibleUsed = overLimit\n ? `${usage.limit.value}+`\n : String(usage.used);\n countLabel = `${visibleUsed} / ${usage.limit.value} Threads`;\n progressMax = usage.limit.value;\n progressValue = Math.min(usage.used, usage.limit.value);\n } else if (usage.limit.kind === \"unlimited\") {\n countLabel = `${usage.used} Threads · Unlimited`;\n } else {\n countLabel = `${usage.used} Threads · Limit unavailable`;\n }\n }\n\n return html`\n <footer\n class=\"inspector-threads-footer\"\n data-inspector-threads-footer\n role=\"group\"\n aria-label=\"Threads usage\"\n >\n ${\n usage && countLabel\n ? html`\n <div class=\"inspector-threads-usage\">\n <span data-inspector-thread-count>${countLabel}</span>\n ${\n progressMax !== undefined && progressValue !== undefined\n ? html`\n <progress\n class=\"inspector-thread-progress\"\n data-inspector-thread-progress\n data-inspector-thread-capacity=${capacityState}\n max=${progressMax}\n value=${progressValue}\n aria-label=${\n capacityState === \"warning\"\n ? `${countLabel}. Near thread limit.`\n : capacityState === \"critical\"\n ? `${countLabel}. Thread limit reached.`\n : countLabel\n }\n >\n ${countLabel}\n </progress>\n `\n : nothing\n }\n ${\n usage.expiringSoonCount !== undefined\n ? html`\n <span data-inspector-thread-expiry\n >${usage.expiringSoonCount} Expiring Soon</span\n >\n `\n : nothing\n }\n </div>\n `\n : nothing\n }\n ${\n threadsFooterAction\n ? this.renderInspectorAction(\n threadsFooterAction,\n \"threads-footer\",\n capacityState === \"warning\" || capacityState === \"critical\"\n ? \"Upgrade Your Plan\"\n : threadsFooterAction.label,\n )\n : nothing\n }\n </footer>\n `;\n }\n\n private renderThreadsView() {\n const { displayThreads, threadsErrorMessage, threadsLoading } =\n this.getActiveThreadsState();\n const ephemeral = !this._core?.intelligence;\n const available = this.areThreadEndpointsAvailable();\n const hasEphemeralThreads =\n ephemeral && available && displayThreads.length > 0;\n if (!ephemeral) this.ephemeralThreadsSetupOpen = false;\n const locked =\n !available ||\n (ephemeral &&\n displayThreads.length === 0 &&\n !threadsLoading &&\n !threadsErrorMessage);\n if (locked || this.ephemeralThreadsSetupOpen) {\n this.trackThreadsViewStateOnce(\"locked\");\n return html`\n ${\n hasEphemeralThreads\n ? html`\n <nav class=\"cpk-threads-setup-navigation\" aria-label=\"Threads setup navigation\">\n <button type=\"button\" class=\"cpk-threads-setup-back\"\n data-inspector-ephemeral-back\n @click=${() => {\n this.ephemeralThreadsSetupOpen = false;\n this.requestUpdate();\n }}>\n <span aria-hidden=\"true\">←</span> Back to your threads\n </button>\n </nav>\n `\n : nothing\n }\n ${this.renderLockedFeatureOverview({\n serviceId: \"threads\",\n featureName: \"Rich Threads\",\n heading: THREADS_LOCKED_COPY.heading,\n description: THREADS_LOCKED_COPY.description,\n videoUrl: THREADS_LOCKED_VIDEO_URL,\n videoTitle: \"Rich Threads overview\",\n outlineItems: THREADS_LOCKED_FEATURE_OUTLINE,\n })}`;\n }\n\n const loadingWithoutRows =\n threadsLoading && !threadsErrorMessage && displayThreads.length === 0;\n\n const showingExamples = this.shouldRenderExampleThreads(\n displayThreads,\n threadsErrorMessage,\n threadsLoading,\n );\n const visibleThreads =\n threadsErrorMessage || loadingWithoutRows\n ? []\n : showingExamples\n ? THREADS_EXAMPLE_THREADS\n : displayThreads;\n if (showingExamples) {\n this.trackThreadsExampleViewedOnce();\n }\n\n const selectedThread =\n this.selectedThreadId != null\n ? (visibleThreads.find((t) => t.id === this.selectedThreadId) ?? null)\n : null;\n const selectedThreadIsLocalExample =\n selectedThread !== null &&\n selectedThread.id === this.selectedLocalExampleThreadId;\n\n if (\n !threadsErrorMessage &&\n (!threadsLoading || displayThreads.length > 0)\n ) {\n this.trackThreadsViewStateOnce(\n displayThreads.length === 0 ? \"empty_enabled\" : \"enabled\",\n );\n }\n\n return html`\n <div\n style=\"display:flex;height:100%;overflow:hidden;flex-direction:column;\"\n >\n <div class=\"inspector-thread-heading\"><strong>Rich Threads</strong><button type=\"button\" class=\"inspector-text-button\" aria-expanded=${!this.threadListCollapsed} @click=${() => {\n this.threadListCollapsed = !this.threadListCollapsed;\n this.requestUpdate();\n }}>${this.threadListCollapsed ? \"Show thread list\" : \"Hide thread list\"}</button></div>\n <div style=\"display:flex;min-height:0;flex:1;overflow:hidden;\">\n <!-- Left sidebar: thread list -->\n <div\n style=\"display:${this.threadListCollapsed ? \"none\" : \"flex\"};width:${\n this.threadListWidth\n }px;flex-shrink:0;overflow:hidden;flex-direction:column;border-right:1px solid #DBDBE5;\"\n >\n ${\n ephemeral\n ? html`\n <button type=\"button\" class=\"cpk-ephemeral-threads-banner\"\n data-inspector-ephemeral-banner data-inspector-ephemeral-upgrade\n aria-label=\"Make threads permanent. Ephemeral history can disappear on restart.\"\n @click=${() => {\n this.ephemeralThreadsSetupOpen = true;\n this.requestUpdate();\n }}>\n <span class=\"cpk-ephemeral-threads-icon\" aria-hidden=\"true\">${this.renderIcon(\"Clock\")}</span>\n <span class=\"cpk-ephemeral-threads-copy\">\n <span class=\"cpk-ephemeral-threads-headline\">\n <strong>Keep your threads.</strong>\n </span>\n <span class=\"cpk-ephemeral-threads-description\">Ephemeral history can disappear on restart.</span>\n <span class=\"cpk-ephemeral-threads-upgrade\">Make them permanent <span aria-hidden=\"true\">${this.renderIcon(\"ArrowRight\")}</span></span>\n </span>\n </button>\n `\n : nothing\n }\n <cpk-thread-list\n style=\"min-height:0;flex:1;\"\n data-color-scheme=${this.colorScheme}\n .threads=${visibleThreads}\n .selectedThreadId=${this.selectedThreadId}\n .inAppThreadId=${this.inAppThreadId}\n .errorMessage=${threadsErrorMessage}\n .suppressEmptyState=${loadingWithoutRows}\n @threadSelected=${(e: CustomEvent<string>) => {\n this.handleThreadsThreadSelected(e.detail, showingExamples);\n }}\n ></cpk-thread-list>\n ${this.renderThreadsUsageFooter()}\n </div>\n\n <!-- Resize divider -->\n <div\n style=\"width:4px;flex-shrink:0;cursor:col-resize;background:transparent;position:relative;z-index:1;\"\n @pointerdown=${this.handleThreadDividerPointerDown}\n @pointermove=${this.handleThreadDividerPointerMove}\n @pointerup=${this.handleThreadDividerPointerUp}\n @pointercancel=${this.handleThreadDividerPointerUp}\n ></div>\n\n <!-- Center + right: thread details or empty state -->\n <div\n style=\"flex:1;min-width:0;overflow:hidden;display:flex;position:relative;\"\n >\n ${\n threadsErrorMessage\n ? html`\n <div\n role=\"alert\"\n style=\"\n display: flex;\n flex: 1;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 6px;\n padding: 24px;\n color: #c0333a;\n text-align: center;\n \"\n >\n <strong style=\"font-size:13px;\"\n >Failed to load threads</strong\n >\n <span\n style=\"max-width:440px;font-size:12px;line-height:1.5;\"\n >${threadsErrorMessage}</span\n >\n </div>\n `\n : loadingWithoutRows\n ? html`\n <div\n role=\"status\"\n style=\"\n display: flex;\n flex: 1;\n align-items: center;\n justify-content: center;\n color: #57575b;\n font-size: 13px;\n \"\n >\n Loading threads…\n </div>\n `\n : selectedThread\n ? html`<cpk-thread-details\n style=\"flex:1;min-width:0;\"\n data-color-scheme=${this.colorScheme}\n .threadId=${selectedThread.id}\n .thread=${selectedThread}\n .provider=${\n selectedThreadIsLocalExample\n ? this.getExampleThreadProvider(selectedThread.id)\n : null\n }\n .runtimeUrl=${\n selectedThreadIsLocalExample\n ? \"\"\n : (this._core?.runtimeUrl ?? \"\")\n }\n .headers=${this._core?.headers ?? {}}\n .threadInspectionAvailable=${\n selectedThreadIsLocalExample ||\n (this.areThreadEndpointsAvailable() &&\n this._core?.threadEndpoints?.inspect !== false)\n }\n .liveMessageVersion=${\n this.liveMessageVersion.get(selectedThread.id) ?? 0\n }\n .viewInAppMode=${this.getViewInAppMode(\n selectedThread,\n selectedThreadIsLocalExample,\n )}\n .viewInAppError=${this.viewInAppError}\n @viewInApp=${this.handleViewInApp}\n @stopViewing=${this.handleStopViewing}\n .focusMessageId=${this.focusedThreadMessageId}\n .focusRequestId=${this.threadFocusRequestId}\n .agentStateInput=${this.getLatestStateForAgent(\n selectedThread.agentId,\n )}\n .agentEventsInput=${\n this.agentEvents.get(selectedThread.agentId) ?? []\n }\n .agentMessagesInput=${\n selectedThreadIsLocalExample\n ? EMPTY_INSPECTOR_MESSAGES\n : this.getLiveAgentMessagesForThread(selectedThread)\n }\n .tryFromHereAvailable=${\n !selectedThreadIsLocalExample &&\n this.areThreadEndpointsAvailable() &&\n this._core?.threadEndpoints?.inspect !== false\n }\n .tryFromHereBusy=${this.tryFromHereBusy}\n .tryFromHereError=${this.tryFromHereError}\n @tryFromHere=${(event: CustomEvent<string | null>) => {\n void this.handleTryFromHere(event.detail);\n }}\n ></cpk-thread-details>\n ${\n selectedThreadIsLocalExample\n ? this.renderThreadsExampleTour()\n : nothing\n }`\n : showingExamples\n ? this.renderThreadsExampleOverview()\n : html`\n <div\n style=\"\n flex: 1;\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n gap: 8px;\n color: #68686e;\n \"\n >\n <svg\n width=\"32\"\n height=\"32\"\n viewBox=\"0 0 24 24\"\n fill=\"none\"\n stroke=\"#c0c0c8\"\n stroke-width=\"1.5\"\n stroke-linecap=\"round\"\n stroke-linejoin=\"round\"\n >\n <path\n d=\"M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z\"\n />\n </svg>\n <span style=\"font-size: 13px\"\n >${\n displayThreads.length === 0\n ? \"No threads yet\"\n : \"Select a thread to inspect\"\n }</span\n >\n </div>\n `\n }\n </div>\n </div>\n </div>\n `;\n }\n\n private renderEventsToolbar(\n events: InspectorEvent[],\n filteredEvents: InspectorEvent[],\n options: { showAgentFilter?: boolean } = {},\n ) {\n const showAgentFilter = options.showAgentFilter !== false;\n const selectedLabel =\n this.selectedContext === \"all-agents\"\n ? \"all agents\"\n : `agent ${this.selectedContext}`;\n\n return html`\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 ${\n showAgentFilter\n ? html`\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.selectedContext}\n @change=${this.handleEventAgentChange}\n aria-label=\"Filter events by agent\"\n >\n ${this.contextOptions.map(\n (option) =>\n html`<option value=${option.key}>\n ${option.label}\n </option>`,\n )}\n </select>\n `\n : nothing\n }\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 aria-label=\"Filter events by type\"\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=${\n !this.eventFilterText && this.eventTypeFilter === \"all\"\n }\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}${\n this.selectedContext === \"all-agents\" ? \"\" : ` for ${selectedLabel}`\n }\n </div>\n </div>\n `;\n }\n\n private renderEventsTable(options: { embedded?: boolean } = {}) {\n const events = this.getEventsForSelectedContext();\n const filteredEvents = this.filterEvents(events);\n const embedded = options.embedded === true;\n\n let body;\n if (events.length === 0) {\n body = html`\n <div\n class=\"flex h-full flex-col items-center justify-center gap-2 px-4 py-10 text-center\"\n >\n <div class=\"text-gray-300 [&>svg]:!h-8 [&>svg]:!w-8\">\n ${this.renderIcon(\"Zap\")}\n </div>\n <span class=\"text-sm text-gray-600\">No events yet</span>\n <span class=\"max-w-[240px] text-xs leading-snug text-gray-400\"\n >Events are recorded live. Run the agent to see them here.</span\n >\n </div>\n `;\n } else if (filteredEvents.length === 0) {\n body = 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 } else {\n const runError = this.eventErrorDetails.run;\n const failedRunEventId = runError\n ? this.findLatestRunErrorEvent(runError.agentId)?.id\n : undefined;\n body = html`\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 <colgroup>\n <col style=\"width:${this.evtColWidths[0]}px\" />\n <col style=\"width:${this.evtColWidths[1]}px\" />\n <col style=\"width:${this.evtColWidths[2]}px\" />\n <col />\n </colgroup>\n <thead class=\"sticky top-0 z-10\">\n <tr class=\"bg-white\">\n ${[\"Agent\", \"Time\", \"Event Type\"].map(\n (label, col) =>\n html` <th\n class=\"border-b border-gray-200 bg-white px-3 py-2 text-left font-medium text-gray-900\"\n style=\"position:relative;overflow:hidden;\"\n >\n ${label}\n <div\n style=\"position:absolute;top:0;right:0;width:5px;height:100%;cursor:col-resize;user-select:none;background:transparent;\"\n @pointerdown=${(e: PointerEvent) =>\n this._onEvtColResizeStart(e, col)}\n @pointermove=${(e: PointerEvent) =>\n this._onEvtColResizeMove(e)}\n @pointerup=${() => this._onEvtColResizeEnd()}\n @pointercancel=${() => this._onEvtColResizeEnd()}\n ></div>\n </th>`,\n )}\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 isFailedRunEvent =\n failedRunEventId !== undefined &&\n event.id === failedRunEventId;\n const rowBg = isFailedRunEvent\n ? \"bg-rose-50\"\n : index % 2 === 0\n ? \"bg-white\"\n : \"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 data-inspector-event-id=${event.id}\n data-cpk-failed-run-event=${\n isFailedRunEvent ? event.id : undefined\n }\n @click=${(clickEvent: Event) =>\n this.toggleRowExpansion(event.id, clickEvent)}\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 ${\n isExpanded ? \"\" : \"truncate max-w-xs\"\n }\"\n >\n ${\n isExpanded\n ? html`\n <div class=\"group relative\">\n ${renderHighlightedJsonBlock(extractedEvent)}\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 ${\n this.copiedEvents.has(event.id)\n ? \"bg-green-100 text-green-700\"\n : \"bg-gray-100 text-gray-600 hover:bg-gray-200 hover:text-gray-900\"\n }\"\n @click=${(e: Event) => {\n e.stopPropagation();\n this.copyToClipboard(\n prettyEvent,\n event.id,\n e,\n );\n }}\n >\n ${\n this.copiedEvents.has(event.id)\n ? html`\n <span>✓ Copied</span>\n `\n : html`\n <span>Copy</span>\n `\n }\n </button>\n </div>\n `\n : inlineEvent\n }\n </td>\n </tr>\n `;\n })}\n </tbody>\n </table>\n </div>\n `;\n }\n\n return html`\n <div\n class=\"${\n embedded\n ? \"flex h-[28rem] min-h-[20rem] flex-col\"\n : \"flex h-full flex-col\"\n }\"\n >\n ${this.renderEventsToolbar(events, filteredEvents, {\n showAgentFilter: !embedded,\n })}\n <div class=\"min-h-0 flex-1 overflow-hidden\">${body}</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 handleEventAgentChange(event: Event): void {\n const target = event.target as HTMLSelectElement | null;\n const value = target?.value;\n if (!value) {\n return;\n }\n this.handleContextOptionSelect(value);\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 _onEvtColResizeStart(e: PointerEvent, col: number): void {\n e.preventDefault();\n e.stopPropagation();\n (e.currentTarget as HTMLElement).setPointerCapture(e.pointerId);\n this._evtColResize = {\n col,\n startX: e.clientX,\n startW: this.evtColWidths[col] ?? 0,\n };\n }\n\n private _onEvtColResizeMove(e: PointerEvent): void {\n if (!this._evtColResize) return;\n const { col, startX, startW } = this._evtColResize;\n this.evtColWidths = this.evtColWidths.map((w, i) =>\n i === col ? Math.max(40, startW + (e.clientX - startX)) : w,\n );\n this.requestUpdate();\n }\n\n private _onEvtColResizeEnd(): void {\n this._evtColResize = null;\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 ${this.renderEventErrorBanner(\"tool\")}\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=\"cpk-agent-view flex flex-col gap-4 p-4 overflow-auto\">\n ${this.renderEventErrorBanner(\"tool\")}\n <!-- Agent Overview Card -->\n <div\n class=\"cpk-agent-overview rounded-lg border border-gray-200 bg-white p-4\"\n >\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 cpk-agent-icon\"\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 ${\n statusColors[status]\n } relative -translate-y-[2px]\"\n >\n <span\n class=\"h-1.5 w-1.5 rounded-full ${\n status === \"running\"\n ? \"bg-emerald-500 animate-pulse\"\n : status === \"error\"\n ? \"bg-rose-500\"\n : \"bg-gray-400\"\n }\"\n ></span>\n ${status.charAt(0).toUpperCase() + status.slice(1)}\n </span>\n </div>\n </div>\n ${\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 }\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 cpk-stat-card\"\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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\n class=\"rounded-md bg-gray-50 px-3 py-2 overflow-hidden cpk-stat-card\"\n >\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=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Current State</h4>\n </div>\n <div class=\"overflow-auto p-4\">\n ${\n this.hasRenderableState(state)\n ? renderHighlightedJsonBlock(state, { maxHeight: \"16rem\" })\n : html`\n <div\n class=\"flex h-12 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 }\n </div>\n </div>\n\n <!-- Current Messages Section -->\n <div class=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Current Messages</h4>\n </div>\n <div class=\"overflow-auto\">\n ${\n messages && messages.length > 0\n ? html`\n <div class=\"w-full text-xs\">\n <div class=\"cpk-agent-messages-head flex bg-gray-50\">\n <div\n class=\"w-40 shrink-0 px-4 py-2 font-medium text-gray-700\"\n >\n Role\n </div>\n <div class=\"flex-1 px-4 py-2 font-medium text-gray-700\">\n Content\n </div>\n </div>\n <div class=\"cpk-agent-messages-rows\">\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 const toolError = this.eventErrorDetails.tool;\n const isFailedResult =\n role === \"tool\" &&\n toolError?.toolCallId !== undefined &&\n toolError.toolCallId === msg.toolCallId;\n\n return html`\n <div\n class=${\n isFailedResult\n ? \"cpk-agent-message-row flex items-start bg-rose-50\"\n : \"cpk-agent-message-row flex items-start\"\n }\n data-cpk-failed-tool-result=${\n isFailedResult ? msg.toolCallId : nothing\n }\n >\n <div class=\"w-40 shrink-0 px-4 py-2\">\n <span\n class=\"inline-flex rounded px-2 py-0.5 text-[10px] font-medium ${\n roleColors[role] || roleColors.unknown\n }\"\n >\n ${role}\n </span>\n </div>\n <div class=\"flex-1 px-4 py-2\">\n ${\n hasContent\n ? html`\n <!-- prettier-ignore -->\n <div class=\"whitespace-pre-wrap break-words text-gray-700\">${rawContent}</div>\n `\n : html`<div class=\"italic text-gray-400\">\n ${contentFallback}\n </div>`\n }\n ${\n role === \"assistant\" && toolCalls.length > 0\n ? this.renderToolCallDetails(toolCalls)\n : nothing\n }\n </div>\n </div>\n `;\n })}\n </div>\n </div>\n `\n : html`\n <div\n class=\"flex h-12 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 }\n </div>\n </div>\n\n ${this.renderAgentToolsSection(agentId)}\n\n <div class=\"cpk-section-card overflow-hidden\">\n <div class=\"cpk-section-header\">\n <h4>AG-UI Events</h4>\n </div>\n ${this.renderEventsTable({ embedded: true })}\n </div>\n </div>\n `;\n }\n\n private renderContextDropdown(iconRail = false) {\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 @pointerenter=${\n iconRail ? this.handleIconRailContextPointerEnter : nothing\n }\n @pointerleave=${\n iconRail ? this.handleIconRailContextPointerLeave : nothing\n }\n @focusin=${iconRail ? this.handleIconRailContextFocusIn : nothing}\n @focusout=${iconRail ? this.handleIconRailContextFocusOut : nothing}\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 aria-label=\"Select agent scope: ${selectedLabel}\"\n title=${selectedLabel}\n @pointerdown=${\n iconRail\n ? this.handleIconRailContextPointerDown\n : this.handleContextDropdownToggle\n }\n >\n <span\n class=\"inspector-context-dropdown-icon shrink-0\"\n aria-hidden=\"true\"\n >${this.renderIcon(\"Bot\")}</span\n >\n <span\n class=\"inspector-context-dropdown-label truncate flex-1 text-left\"\n >${selectedLabel}</span\n >\n <span\n class=\"inspector-context-dropdown-chevron shrink-0 text-gray-400\"\n >${this.renderIcon(\"ChevronDown\")}</span\n >\n </button>\n ${\n iconRail || 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 iconRail ? \" inspector-icon-rail-menu\" : \"\"\n }\"\n data-context-dropdown-root=\"true\"\n data-open=${this.contextMenuOpen ? \"true\" : \"false\"}\n aria-hidden=${this.contextMenuOpen ? \"false\" : \"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 ${\n option.key === this.selectedContext\n ? \"text-gray-900 font-medium\"\n : \"text-gray-600\"\n }\"\n >${option.label}</span\n >\n ${\n option.key === this.selectedContext\n ? html`<span class=\"text-gray-500\"\n >${this.renderIcon(\"Check\")}</span\n >`\n : nothing\n }\n </button>\n `,\n )}\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n /**\n * The Agent view is empty on \"All Agents\". Pick the agent that just failed\n * a tool, or the one with the most recent activity.\n */\n private applyEventErrorLanding(key: InspectorEventErrorSource): void {\n const error = this.eventErrorDetails[key];\n if (!error) {\n if (this.selectedMenu === \"agents\") {\n this.focusAgentForView();\n }\n return;\n }\n\n if (\n error.agentId &&\n this.contextOptions.some((option) => option.key === error.agentId)\n ) {\n this.selectedContext = error.agentId;\n } else if (this.selectedMenu === \"agents\") {\n this.focusAgentForView(error);\n }\n\n if (key === \"tool\" && error.toolCallId) {\n this.pendingScrollToToolCallId = error.toolCallId;\n return;\n }\n\n if (key === \"run\") {\n this.eventFilterText = \"\";\n this.eventTypeFilter = \"all\";\n const event = this.findLatestRunErrorEvent(error.agentId);\n if (!event) return;\n this.expandedRows.clear();\n this.expandedRows.add(event.id);\n this.pendingScrollToEventId = event.id;\n }\n }\n\n /**\n * Whether the landing view really carries the item the card points at.\n * Mirrors the two branches of `applyEventErrorLanding` that can bail out.\n */\n private hasEventErrorHighlight(key: InspectorEventErrorSource): boolean {\n const error = this.eventErrorDetails[key];\n if (!error) return false;\n if (key === \"tool\") return error.toolCallId !== undefined;\n if (key === \"run\") {\n return this.findLatestRunErrorEvent(error.agentId) !== undefined;\n }\n return false;\n }\n\n private findLatestRunErrorEvent(\n agentId?: string,\n ): InspectorEvent | undefined {\n const events =\n agentId && agentId !== \"all-agents\"\n ? (this.agentEvents.get(agentId) ?? [])\n : this.flattenedEvents;\n return events.find((event) => event.type === \"RUN_ERROR\");\n }\n\n private flushErrorLandingScroll(): void {\n const eventId = this.pendingScrollToEventId;\n if (eventId) {\n this.pendingScrollToEventId = null;\n const row = Array.from(\n this.activeRoot.querySelectorAll<HTMLElement>(\n \"[data-inspector-event-id]\",\n ),\n ).find((candidate) => candidate.dataset.inspectorEventId === eventId);\n row?.scrollIntoView?.({ block: \"center\" });\n }\n\n const toolCallId = this.pendingScrollToToolCallId;\n if (toolCallId) {\n this.pendingScrollToToolCallId = null;\n const escaped = escapeSelectorValue(toolCallId);\n const card =\n this.activeRoot.querySelector<HTMLElement>(\n `[data-cpk-failed-tool-call=\"${escaped}\"]`,\n ) ??\n this.activeRoot.querySelector<HTMLElement>(\n `[data-cpk-failed-tool-result=\"${escaped}\"]`,\n );\n card?.scrollIntoView?.({ block: \"center\" });\n }\n }\n\n /**\n * The Agent view is empty on \"All Agents\". Pick the agent that just failed\n * a tool, or the one with the most recent activity.\n */\n private focusAgentForView(error?: InspectorEventErrorDetails): void {\n const agentOptions = this.contextOptions.filter(\n (opt) => opt.key !== \"all-agents\",\n );\n if (agentOptions.length === 0) return;\n\n const errorAgentId = error?.agentId;\n if (\n errorAgentId &&\n agentOptions.some((option) => option.key === errorAgentId)\n ) {\n this.selectedContext = errorAgentId;\n return;\n }\n\n if (this.selectedContext !== \"all-agents\") return;\n\n const mostRecent = agentOptions.reduce<{\n key: string;\n ts: number;\n } | null>((best, opt) => {\n const ts = this.getAgentStats(opt.key).lastActivity ?? -1;\n return best === null || ts > best.ts ? { key: opt.key, ts } : best;\n }, null);\n this.selectedContext = mostRecent ? mostRecent.key : agentOptions[0]!.key;\n }\n\n private handleMenuSelect(key: MenuKey): void {\n if (!this.menuItems.some((item) => item.key === key)) {\n return;\n }\n\n const previousMenu = this.selectedMenu;\n this.pendingPersistedMenu = null;\n this.briefingRestoreMenu = null;\n this.selectedMenu = key;\n this.settingsOpen = false;\n this.lastSelectedMenuByGroup[getGroupForMenu(key)] = key;\n\n // If leaving the agents view with multiple agents registered, restore\n // \"all-agents\" so the Events tab isn't silently filtered to one agent.\n if (previousMenu === \"agents\" && key !== \"agents\") {\n const agentCount = this.contextOptions.filter(\n (opt) => opt.key !== \"all-agents\",\n ).length;\n if (agentCount > 1) {\n this.selectedContext = \"all-agents\";\n }\n }\n\n // Deliberately NOT applying an event error's landing here. A landing is an\n // arrival, not a passing-through: it selects the failed agent, clears the\n // event filters and re-expands the failed row, which is help when the\n // reader came *because* of that error and vandalism when they did not.\n // Event-error details outlive being read on purpose, so the how-to-fix\n // card survives while it is being read — which means running this on every\n // visit resets the reader's own filters and agent scope for the rest of\n // the session, and silently undoes the `all-agents` restore eight lines\n // above. The three arrivals that *are* landings keep it: pressing the\n // launcher (`openInspector`), pressing the card (`refocusEventErrorLanding`)\n // and an error arriving while its view is already open (`armEventError`).\n\n if (key === \"threads\") {\n if (previousMenu !== \"threads\" && !this.core?.telemetryDisabled) {\n trackThreadsTabClicked(this.getThreadsTelemetryProps());\n }\n this.autoSelectLatestThread();\n }\n\n if (key === \"playground\" && !this.playgroundAgent) {\n this.startPlaygroundSession(false);\n }\n\n if (key === \"memories\") {\n this.learningSupported = Boolean(this.core?.inspectorLearning);\n if (previousMenu !== \"memories\" || this.learningSnapshot === null) {\n void this.refreshLearningSnapshot({\n preserve: previousMenu === \"memories\",\n });\n }\n if (previousMenu !== \"memories\" && !this.core?.telemetryDisabled) {\n trackMemoriesTabClicked(this.getMemoriesTelemetryProps());\n }\n } else if (previousMenu === \"memories\") {\n this.learningViewedState = null;\n this.cancelLearningPoll();\n this.cancelLearningRequest();\n }\n\n if (key === \"home\" && previousMenu !== \"home\") {\n void this.refreshLearningSnapshot({ preserve: true });\n this.homeViewedThisOpen = false;\n }\n\n if (key === \"ag-ui-events\" || key === \"agents\") {\n const keepErrorLanding =\n this.pendingScrollToEventId !== null ||\n this.pendingScrollToToolCallId !== null;\n if (!keepErrorLanding) {\n requestAnimationFrame(() => {\n const scroller = this.activeRoot.querySelector(\"#cpk-main-scroll\");\n if (scroller) scroller.scrollTop = 0;\n });\n }\n }\n\n this.contextMenuOpen = false;\n this.layoutMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private handleContextDropdownToggle(event: PointerEvent): void {\n event.preventDefault();\n event.stopPropagation();\n this.layoutMenuOpen = false;\n this.contextMenuOpen = !this.contextMenuOpen;\n this.requestUpdate();\n }\n\n private clearIconRailContextCloseTimer(): void {\n if (this.iconRailContextCloseTimer === null) {\n return;\n }\n clearTimeout(this.iconRailContextCloseTimer);\n this.iconRailContextCloseTimer = null;\n }\n\n /** Expand the icon-rail agent scope on hover while preserving keyboard access. */\n private handleIconRailContextPointerEnter = (event: PointerEvent): void => {\n if (event.pointerType === \"touch\") {\n return;\n }\n this.clearIconRailContextCloseTimer();\n if (this.contextMenuOpen) {\n return;\n }\n this.layoutMenuOpen = false;\n this.contextMenuOpen = true;\n this.requestUpdate();\n };\n\n private handleIconRailContextPointerLeave = (): void => {\n if (!this.contextMenuOpen) {\n return;\n }\n this.clearIconRailContextCloseTimer();\n this.iconRailContextCloseTimer = setTimeout(() => {\n this.iconRailContextCloseTimer = null;\n this.contextMenuOpen = false;\n this.requestUpdate();\n }, 180);\n };\n\n private handleIconRailContextPointerDown = (event: PointerEvent): void => {\n // A hover-only rail still needs to be operable on touch devices.\n if (event.pointerType === \"touch\") {\n this.handleContextDropdownToggle(event);\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n };\n\n private handleIconRailContextFocusIn = (): void => {\n this.clearIconRailContextCloseTimer();\n if (this.contextMenuOpen) {\n return;\n }\n this.layoutMenuOpen = false;\n this.contextMenuOpen = true;\n this.requestUpdate();\n };\n\n private handleIconRailContextFocusOut = (event: FocusEvent): void => {\n const nextFocus = event.relatedTarget;\n if (\n nextFocus instanceof Node &&\n (event.currentTarget as HTMLElement).contains(nextFocus)\n ) {\n return;\n }\n this.handleIconRailContextPointerLeave();\n };\n\n private handleContextOptionSelect(key: string): void {\n if (!this.contextOptions.some((option) => option.key === key)) {\n return;\n }\n\n this.clearIconRailContextCloseTimer();\n if (this.selectedContext !== key) {\n this.selectedContext = key;\n this.expandedRows.clear();\n this.autoSelectLatestThread();\n if (this.selectedMenu === \"playground\") {\n this.startPlaygroundSession(false);\n } else if (this.isLearningStatusVisible()) {\n this.clearLearningSnapshot();\n void this.refreshLearningSnapshot({ preserve: false });\n }\n }\n\n this.contextMenuOpen = false;\n this.persistState();\n this.requestUpdate();\n }\n\n private renderCapabilitiesView() {\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 const toolRows = buildCapabilityRows(\n this._core as unknown as CapabilityToolSource,\n );\n const catalog = this._core.catalogComponents ?? [];\n const hasCatalog = catalog.length > 0;\n\n if (toolRows.length === 0 && !hasCatalog) {\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(\"SlidersHorizontal\")}\n </div>\n <p class=\"text-sm text-gray-600\">No capabilities registered</p>\n <p class=\"mt-2 text-xs text-gray-500\">\n Frontend tools and A2UI catalog components will appear here once\n they are registered on the CopilotKit core.\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 <p class=\"text-xs text-gray-500\">\n Toggle a capability off to omit it from what the agent sees. This\n is a client-side experimentation surface and takes effect\n immediately.\n </p>\n </div>\n\n ${\n toolRows.length > 0\n ? html`\n <div class=\"mt-4 space-y-2\">\n <h3 class=\"text-sm text-slate-500\">Frontend tools</h3>\n <div class=\"space-y-2\">\n ${toolRows.map((row) => this.renderCapabilityRow(row))}\n </div>\n </div>\n `\n : nothing\n }\n ${\n hasCatalog\n ? html`\n <div class=\"mt-6 space-y-2\">\n <h3 class=\"text-sm text-slate-500\">\n A2UI catalog components\n </h3>\n <div class=\"space-y-2\">\n ${catalog.map((component) =>\n this.renderCapabilityRow({\n key: component.name,\n name: component.name,\n description: component.description,\n enabled: this._core!.isCatalogComponentEnabled(\n component.name,\n ),\n }),\n )}\n </div>\n </div>\n `\n : nothing\n }\n </div>\n </div>\n `;\n }\n\n private renderCapabilityRow(row: CapabilityToolRow) {\n // Frontend-tool keys are always `${agentId}:${name}` (agentId may be \"\"),\n // so they contain a \":\"; catalog keys are the bare component name.\n const isTool = row.key.includes(\":\");\n return html`\n <div\n class=\"flex items-center justify-between gap-3 rounded-lg border border-gray-200 bg-white px-4 py-3\"\n >\n <div class=\"min-w-0 flex-1\">\n <div class=\"flex items-center gap-2\">\n <span class=\"font-mono text-sm font-semibold text-gray-900\"\n >${row.name}</span\n >\n ${\n row.agentId\n ? html`<span\n class=\"inline-flex items-center gap-1 text-xs text-gray-500\"\n >\n ${this.renderIcon(\"Bot\")}<span class=\"font-mono\"\n >${row.agentId}</span\n >\n </span>`\n : nothing\n }\n </div>\n ${\n row.description\n ? html`<p class=\"mt-1 text-xs text-gray-600\">${row.description}</p>`\n : nothing\n }\n </div>\n ${this.renderCapabilitySwitch(row.enabled, () =>\n isTool\n ? this.handleToggleTool(row)\n : this.handleToggleCatalogComponent(row.name),\n )}\n </div>\n `;\n }\n\n private renderCapabilitySwitch(enabled: boolean, onToggle: () => void) {\n const track = enabled ? \"bg-emerald-500\" : \"bg-gray-300\";\n const knob = enabled ? \"translate-x-4\" : \"translate-x-0.5\";\n return html`\n <button\n type=\"button\"\n role=\"switch\"\n aria-checked=${enabled ? \"true\" : \"false\"}\n class=\"relative inline-flex h-5 w-9 shrink-0 items-center rounded-full transition-colors focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-gray-300 ${track}\"\n @click=${onToggle}\n >\n <span\n class=\"inline-block h-4 w-4 transform rounded-full bg-white shadow transition-transform ${knob}\"\n ></span>\n </button>\n `;\n }\n\n private handleToggleTool(row: CapabilityToolRow): void {\n if (!this._core) return;\n const next = !row.enabled;\n // A1 contract: setToolEnabled(name, enabled, agentId?). Pass agentId only\n // when the tool is agent-scoped so global tools toggle globally.\n this._core.setToolEnabled(row.name, next, row.agentId);\n this._capabilitiesVersion += 1;\n this.requestUpdate();\n }\n\n private handleToggleCatalogComponent(name: string): void {\n if (!this._core) return;\n const next = !this._core.isCatalogComponentEnabled(name);\n this._core.setCatalogComponentEnabled(name, next);\n this._capabilitiesVersion += 1;\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 ${\n typeColors[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 ${\n schema.properties.length > 0\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span\n >${schema.properties.length}\n parameter${\n schema.properties.length !== 1 ? \"s\" : \"\"\n }</span\n >\n `\n : nothing\n }\n </div>\n ${\n tool.description\n ? html`<p class=\"mt-2 text-xs text-gray-600\">\n ${tool.description}\n </p>`\n : nothing\n }\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${\n isExpanded ? \"rotate-180\" : \"\"\n }\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${\n isExpanded\n ? html`\n <div class=\"border-t border-gray-200 bg-gray-50/50 px-4 py-3\">\n ${\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 ${\n prop.required\n ? html`\n <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 `\n : html`\n <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 `\n }\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 }\n </div>\n </div>\n ${\n prop.description\n ? html`<p class=\"mt-1 text-xs text-gray-600\">\n ${prop.description}\n </p>`\n : nothing\n }\n ${\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 }\n ${\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 }\n </div>\n `,\n )}\n </div>\n `\n : html`\n <div class=\"flex items-center justify-center py-4 text-xs text-gray-500\">\n <span>No parameters defined</span>\n </div>\n `\n }\n </div>\n `\n : nothing\n }\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 ${\n hasValue\n ? html`\n <span class=\"text-gray-300\">•</span>\n <span class=\"truncate\">${valuePreview}</span>\n `\n : nothing\n }\n </div>\n </div>\n <span\n class=\"shrink-0 text-gray-400 transition ${\n isExpanded ? \"rotate-180\" : \"\"\n }\"\n >\n ${this.renderIcon(\"ChevronDown\")}\n </span>\n </div>\n </button>\n\n ${\n isExpanded\n ? html`\n <div class=\"border-t border-gray-200 px-4 py-3\">\n <div class=\"mb-3\">\n <div class=\"mb-1 flex items-center justify-between gap-2\">\n <h5 class=\"text-xs font-semibold text-gray-700\">ID</h5>\n <button\n type=\"button\"\n class=\"cpk-copy-btn\"\n @click=${(e: Event) => {\n e.stopPropagation();\n void this.copyContextValue(id, `${id}:id`, e);\n }}\n >\n ${\n this.copiedContextItems.has(`${id}:id`)\n ? \"Copied\"\n : \"Copy\"\n }\n </button>\n </div>\n <code\n class=\"block min-w-0 truncate font-mono text-xs font-medium text-gray-800\"\n >${id}</code\n >\n </div>\n ${\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 type=\"button\"\n class=\"cpk-copy-btn\"\n @click=${(e: Event) => {\n e.stopPropagation();\n void this.copyContextValue(context.value, id, e);\n }}\n >\n ${\n this.copiedContextItems.has(id)\n ? \"Copied\"\n : \"Copy JSON\"\n }\n </button>\n </div>\n ${renderHighlightedJsonBlock(context.value, {\n maxHeight: \"180px\",\n })}\n `\n : html`\n <div class=\"flex items-center justify-center py-4 text-xs text-gray-500\">\n <span>No value available</span>\n </div>\n `\n }\n </div>\n `\n : nothing\n }\n </div>\n `;\n }\n\n private getContextValuePreview(value: unknown): string {\n const parsed = coerceJsonValue(value);\n\n if (parsed === undefined || parsed === null) {\n return \"—\";\n }\n\n if (typeof parsed === \"string\") {\n return parsed.length > 50 ? `${parsed.slice(0, 50)}...` : parsed;\n }\n\n if (typeof parsed === \"number\" || typeof parsed === \"boolean\") {\n return String(parsed);\n }\n\n if (Array.isArray(parsed)) {\n return `Array(${parsed.length})`;\n }\n\n if (typeof parsed === \"object\") {\n const keys = Object.keys(parsed);\n return `Object with ${keys.length} key${keys.length !== 1 ? \"s\" : \"\"}`;\n }\n\n if (typeof parsed === \"function\") {\n return \"Function\";\n }\n\n return String(parsed);\n }\n\n private getToolsForAgent(agentId: string): InspectorToolDefinition[] {\n this.refreshToolsSnapshot();\n return this.cachedTools.filter(\n (tool) => !tool.agentId || tool.agentId === agentId,\n );\n }\n\n private renderAgentToolsSection(agentId: string) {\n const tools = this.getToolsForAgent(agentId);\n\n return html`\n <div class=\"cpk-section-card\">\n <div class=\"cpk-section-header\">\n <h4>Registered Tools</h4>\n </div>\n <div class=\"overflow-auto p-4\">\n ${\n tools.length > 0\n ? html`<div class=\"space-y-3\">\n ${tools.map((tool) => this.renderToolCard(tool))}\n </div>`\n : html`\n <div\n class=\"flex h-12 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(\"Hammer\")}</span\n >\n <span>No tools registered</span>\n </div>\n </div>\n `\n }\n </div>\n </div>\n `;\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 const pretty = this.formatStateForDisplay(coerceJsonValue(value));\n return pretty.length > 0 ? pretty : String(value);\n }\n\n private async copyContextValue(\n value: unknown,\n contextId: string,\n event?: Event,\n ): Promise<void> {\n const clipboard = this.getClipboard(event);\n if (!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 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 && !this.layoutMenuOpen) {\n return;\n }\n\n const path = event.composedPath();\n const clickedDropdown = path.some((node) => {\n const candidate = node as {\n getAttribute?: (name: string) => string | null;\n };\n return (\n typeof candidate.getAttribute === \"function\" &&\n candidate.getAttribute(\"data-context-dropdown-root\") === \"true\"\n );\n });\n const clickedLayoutMenu = path.some((node) => {\n const candidate = node as {\n getAttribute?: (name: string) => string | null;\n };\n return (\n typeof candidate.getAttribute === \"function\" &&\n candidate.getAttribute(\"data-inspector-window-layout-root\") === \"true\"\n );\n });\n\n let changed = false;\n if (this.contextMenuOpen && !clickedDropdown) {\n this.contextMenuOpen = false;\n changed = true;\n }\n if (this.layoutMenuOpen && !clickedLayoutMenu) {\n this.layoutMenuOpen = false;\n changed = true;\n }\n if (changed) {\n this.requestUpdate();\n }\n };\n\n private toggleRowExpansion(eventId: string, event?: Event): void {\n // Don't toggle if user is selecting text\n const target = event?.currentTarget;\n const ownerDocument =\n target && \"ownerDocument\" in target\n ? (target as Node).ownerDocument\n : this.ownerDocument;\n const selection = ownerDocument?.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 // ── Launcher signals ────────────────────────────────────────────────────\n\n /** Whether a given subject currently has something to say. */\n private isSignalArmed(key: LauncherSignalKey): boolean {\n if (isWiringErrorKey(key)) return this.errorSignalArmed[key];\n if (isEventErrorKey(key)) return this.eventErrorArmed[key];\n return this.newsSignalArmed;\n }\n\n /**\n * The signal that owns the single launcher dot, or null when the launcher is\n * quiet. Precedence rather than replacement: a suppressed signal stays armed\n * and takes the dot as soon as the higher-priority one clears, and its own\n * navigation marker is visible the whole time.\n */\n private getActiveLauncherSignal(): LauncherSignalKey | null {\n for (const key of LAUNCHER_SIGNAL_PRIORITY_ORDER) {\n if (this.isSignalArmed(key)) return key;\n }\n return null;\n }\n\n /**\n * The marker a navigation entry carries, or null for an unmarked entry.\n *\n * Markers are independent of the launcher's single dot, so a suppressed\n * signal is never actually hidden once the panel is open. They also render\n * on the entry that is *currently selected*: for the news signal that never\n * mattered, because its marker clears as soon as the view renders, but a\n * state mirror stays true while it is being read and suppressing it on the\n * active entry would make it reappear on navigating away.\n */\n private getNavigationSignalFor(\n key: MenuKey,\n ): LauncherSignalDefinition | null {\n for (const signalKey of LAUNCHER_SIGNAL_PRIORITY_ORDER) {\n const signal = LAUNCHER_SIGNALS[signalKey];\n if (signal.markerTarget !== key) continue;\n if (!this.isSignalArmed(signalKey)) continue;\n // The announcement's marker waits for the feed, so a still-loading feed\n // cannot mark an entry that has nothing to show yet.\n if (signalKey === NEWS_SIGNAL_ID && !this.announcementLoaded) continue;\n return signal;\n }\n return null;\n }\n\n /** Whether a wiring error source is currently red. */\n private hasArmedErrorSignal(): boolean {\n return WIRING_ERROR_KEYS.some((source) => this.errorSignalArmed[source]);\n }\n\n private armEventErrorFromCode(\n code: CopilotKitCoreErrorCode,\n message: string,\n context?: Record<string, unknown>,\n ): void {\n const key = eventErrorKeyForCode(code);\n if (key === null) return;\n const agentId =\n typeof context?.agentId === \"string\" && context.agentId.length > 0\n ? context.agentId\n : undefined;\n const toolName =\n typeof context?.toolName === \"string\" && context.toolName.length > 0\n ? context.toolName\n : undefined;\n const toolCallId =\n typeof context?.toolCallId === \"string\" && context.toolCallId.length > 0\n ? context.toolCallId\n : undefined;\n this.armEventError(key, message, { agentId, toolName, toolCallId });\n }\n\n private armEventError(\n key: InspectorEventErrorSource,\n message: string,\n extras: {\n agentId?: string;\n toolName?: string;\n toolCallId?: string;\n } = {},\n ): void {\n this.eventErrorDetails[key] = { message, ...extras };\n const wasArmed = this.eventErrorArmed[key];\n this.eventErrorArmed[key] = true;\n if (!wasArmed) {\n this.startSignalPulse(key);\n }\n if (\n this.isOpen &&\n !this.settingsOpen &&\n this.selectedMenu === LAUNCHER_SIGNALS[key].landingTarget\n ) {\n this.applyEventErrorLanding(key);\n }\n this.requestUpdate();\n }\n\n private clearEventError(key: InspectorEventErrorSource): void {\n if (!this.eventErrorArmed[key]) return;\n this.eventErrorArmed[key] = false;\n this.errorSignalViewedSources.delete(key);\n this.retireSignal(key);\n this.requestUpdate();\n }\n\n private clearAllEventErrors(): void {\n for (const key of EVENT_ERROR_KEYS) {\n this.eventErrorDetails[key] = null;\n if (!this.eventErrorArmed[key]) continue;\n this.eventErrorArmed[key] = false;\n this.retireSignal(key);\n }\n }\n\n /**\n * An event error is unread until its landing view is actually on screen.\n * Opening the Inspector for a different leaf must not burn it.\n */\n private maybeCompleteEventErrorView(): void {\n if (!this.isOpen || this.settingsOpen) return;\n for (const key of EVENT_ERROR_KEYS) {\n if (!this.eventErrorArmed[key]) continue;\n if (this.selectedMenu !== LAUNCHER_SIGNALS[key].landingTarget) continue;\n this.clearEventError(key);\n }\n }\n\n private isReducedMotionPreferred(): boolean {\n return (\n typeof window !== \"undefined\" &&\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches === true\n );\n }\n\n // ── What's new launcher signal ──────────────────────────────────────────\n\n private armNewsSignal(options: { pulse: boolean }): void {\n const wasArmed = this.newsSignalArmed;\n this.newsSignalArmed = true;\n if (options.pulse) {\n this.startSignalPulse(NEWS_SIGNAL_ID);\n } else if (!wasArmed) {\n this.requestUpdate();\n }\n }\n\n private clearNewsSignal(): void {\n if (!this.newsSignalArmed) return;\n this.newsSignalArmed = false;\n if (this.announcementTimestamp) {\n saveAnnouncementReadTimestamp(this.announcementTimestamp);\n }\n this.retireSignal(NEWS_SIGNAL_ID);\n this.requestUpdate();\n }\n\n // ── The beat ────────────────────────────────────────────────────────────\n\n /**\n * Requests one beat for a signal, running it now or deferring it.\n *\n * There is a single pending slot and five reasons a beat cannot land. All\n * five are the same situation — \"cannot land now, run later\" — and treating\n * them alike is the point: three separate behaviours for one situation would\n * not survive a third signal.\n *\n * Reason 4 is not cosmetic. Starting a beat while one runs does not restart\n * the animation, because the attribute it binds to does not change value and\n * the pseudo-element selectors match on attribute *presence*; the running\n * beat would merely change colour mid-flight. A failure that arms during an\n * announcement beat must wait for that beat to end, or it would run only as\n * its final fraction.\n *\n * A failure's beat is followed by a pill, and the whole 3.4-second gesture\n * holds this one slot for its full duration. That is not a second scheduling\n * concept: reason 4 already says \"another beat is running\", and a gesture is\n * simply a longer beat.\n */\n private startSignalPulse(key: LauncherSignalKey): void {\n const deferred =\n // 1. The panel is open, so there is no visible launcher. Pop-out is the\n // same case: the host page renders only a portal anchor.\n this.isOpen ||\n // 2. The developer deliberately hid the entire Inspector for a while.\n this.isInspectorDismissed ||\n // 3. Nobody is looking.\n (typeof document !== \"undefined\" &&\n document.visibilityState !== \"visible\") ||\n // 4. Another beat — or the pill that follows it — is already running.\n (this.gestureSlotSignal !== null && this.gestureSlotSignal !== key) ||\n // 5. Another signal currently owns the dot.\n this.getActiveLauncherSignal() !== key;\n\n if (deferred) {\n // One slot, and the more urgent beat keeps it. A lower-priority beat must\n // not evict a nudge about something worse — and it would fail the\n // re-check on the way out anyway, because it is not the active signal.\n // The evicted beat is not lost for good: its once-per-subject token is\n // still unspent, so it is offered again the next time it arms.\n const pending = this.pendingPulseSignal;\n if (\n pending === null ||\n LAUNCHER_SIGNALS[key].priority >= LAUNCHER_SIGNALS[pending].priority\n ) {\n this.pendingPulseSignal = key;\n }\n this.requestUpdate();\n return;\n }\n\n this.stopSignalPulse();\n this.pendingPulseSignal = null;\n this.pulsingSignal = key;\n // The once-per-subject token is written HERE, where the beat actually\n // runs — never when a signal arms. Spending it on arming would burn a\n // deferred beat unfired.\n if (isWiringErrorKey(key)) {\n this.errorBeatSpent = true;\n } else if (this.announcementTimestamp && key === NEWS_SIGNAL_ID) {\n saveAnnouncementPulsedTimestamp(this.announcementTimestamp);\n }\n this.beginGestureTail(key);\n this.requestUpdate();\n if (typeof window === \"undefined\") return;\n this.pulseTimeoutId = setTimeout(() => {\n this.pulseTimeoutId = null;\n this.pulsingSignal = null;\n this.requestUpdate();\n // The beat says *here*; now the pill says *this*.\n if (this.gestureSignal === key && this.pillPhase === \"closed\") {\n this.openPill();\n return;\n }\n // Nothing follows the beat: either this signal opens no pill, or there\n // was no room for one, so the gesture ends with it.\n if (this.gestureSignal === key) {\n this.endGesture();\n return;\n }\n // Reason 4 has just cleared.\n this.flushPendingSignalPulse();\n }, LAUNCHER_SIGNALS[key].cadence);\n }\n\n private stopSignalPulse(): void {\n if (this.pulseTimeoutId !== null) {\n clearTimeout(this.pulseTimeoutId);\n this.pulseTimeoutId = null;\n }\n this.pulsingSignal = null;\n }\n\n /**\n * Runs a deferred beat if it can land now, and drops it if its reason to\n * exist has gone: a nudge about a problem that no longer exists is worse\n * than no nudge at all.\n */\n private flushPendingSignalPulse(): void {\n const key = this.pendingPulseSignal;\n if (key === null) return;\n if (!this.isSignalArmed(key)) {\n this.pendingPulseSignal = null;\n this.requestUpdate();\n return;\n }\n this.startSignalPulse(key);\n }\n\n /**\n * Drops a signal's gesture, pending or running, when the signal goes quiet.\n *\n * The pill closes early: it states a condition, and the condition has\n * stopped being true. The beat is left to finish, because a beat asserts\n * nothing — it says *here*, and \"here\" is still true.\n */\n private retireSignal(key: LauncherSignalKey): void {\n if (this.pendingPulseSignal === key) this.pendingPulseSignal = null;\n if (this.gestureSignal === key) this.closePillEarly();\n // A suppressed signal may now own the dot.\n this.flushPendingSignalPulse();\n }\n\n // ── The pill ────────────────────────────────────────────────────────────\n\n /**\n * The signal holding the single gesture slot: a beat in flight, or the pill\n * and spoken sentence that follow it. One slot, not two — see reason 4 in\n * `startSignalPulse`.\n */\n private get gestureSlotSignal(): LauncherSignalKey | null {\n return this.pulsingSignal ?? this.gestureSignal;\n }\n\n /**\n * Opens the gesture's tail alongside the beat, for a signal that carries a\n * pill. The pill is rendered immediately — clipped to nothing, so it shows\n * nothing — because its full width has to be on the page before the room\n * either side of the launcher can be measured.\n *\n * A signal with no pill label gets no tail at all, so the announcement's\n * gesture is exactly the beat it has always been.\n */\n private beginGestureTail(key: LauncherSignalKey): void {\n this.cancelPillTimeout();\n if (LAUNCHER_SIGNALS[key].pillLabel === undefined) {\n this.gestureSignal = null;\n this.pillPhase = null;\n this.pillDirection = null;\n return;\n }\n this.gestureSignal = key;\n this.pillPhase = \"closed\";\n this.pillDirection = null;\n this.closeLauncherHud();\n }\n\n /**\n * Chooses the side, or suppresses the pill, from the room actually available\n * at gesture start. Measured once, from the DOM, because the launcher is\n * draggable and its position persists: a reader who parked it near the left\n * edge would otherwise get a permanently truncated pill.\n *\n * Where neither side has room there is no pill at all rather than a cut-off\n * one — the dot and the beat still fire, so the signal is intact and only\n * the label is lost. Constraining where the reader may drag the control to\n * protect this animation was considered and rejected: the page is theirs.\n */\n private resolvePillDirection(): void {\n if (this.pillDirection !== null || this.pillPhase === null) return;\n const wrapper = this.activeRoot.querySelector<HTMLElement>(\n \".console-button-wrapper\",\n );\n const button = wrapper?.querySelector<HTMLElement>(\".console-button\");\n const pill = wrapper?.querySelector<HTMLElement>(\".cpk-launcher-pill\");\n if (!button || !pill || typeof window === \"undefined\") return;\n\n const mark = button.getBoundingClientRect();\n // A clip changes what is painted, never the layout box, so this is the\n // pill's full width whichever phase it is in.\n const overhang = Math.max(\n 0,\n pill.getBoundingClientRect().width - mark.width,\n );\n const viewportWidth = window.innerWidth;\n\n if (overhang === 0) {\n // Nothing extends past the mark, so there is nothing to fit.\n this.setPillOutcome(\"left\");\n return;\n }\n if (mark.left - overhang >= EDGE_MARGIN) {\n // Leftwards is the natural direction: away from the launcher's own edge.\n this.setPillOutcome(\"left\");\n return;\n }\n if (mark.right + overhang <= viewportWidth - EDGE_MARGIN) {\n this.setPillOutcome(\"right\");\n return;\n }\n this.setPillOutcome(null);\n }\n\n /** Records the measurement's verdict, and drops the pill when it is null. */\n private setPillOutcome(direction: LauncherPillDirection | null): void {\n if (direction === null) {\n this.pillPhase = null;\n this.pillDirection = null;\n this.pillOutcome = \"suppressed\";\n this.requestUpdate();\n return;\n }\n this.pillDirection = direction;\n this.pillOutcome = \"shown\";\n this.requestUpdate();\n }\n\n /** Runs the pill's three phases in series once the beat has finished. */\n private openPill(): void {\n // Normally already measured during the beat; measured here too so the\n // gesture cannot depend on a render having happened in between.\n this.resolvePillDirection();\n if (this.pillPhase === null) {\n // The measurement found no room after all.\n this.endGesture();\n return;\n }\n this.advancePill(\"opening\", ERROR_GESTURE_MS.open, () => {\n this.advancePill(\"holding\", ERROR_GESTURE_MS.hold, () => {\n this.advancePill(\"closing\", ERROR_GESTURE_MS.close, () => {\n this.endGesture();\n });\n });\n });\n }\n\n private advancePill(\n phase: LauncherPillPhase,\n duration: number,\n next: () => void,\n ): void {\n this.cancelPillTimeout();\n this.pillPhase = phase;\n this.requestUpdate();\n if (typeof window === \"undefined\") return;\n this.pillTimeoutId = setTimeout(() => {\n this.pillTimeoutId = null;\n next();\n }, duration);\n }\n\n /**\n * Closes the pill before its hold is out, because the failure it names has\n * been fixed. A pill that has not opened yet is simply dropped; the beat is\n * never cut short.\n */\n private closePillEarly(): void {\n // No pill in this gesture — there was no room for one — so the tail is\n // only the spoken sentence, and it ends here.\n if (this.pillPhase === null) {\n this.endGesture();\n return;\n }\n // Already on its way out.\n if (this.pillPhase === \"closing\") return;\n // Still inside the beat, so nothing has been asserted on screen yet: the\n // pill is dropped rather than closed, and the beat runs on to its end.\n if (this.pillPhase === \"closed\") {\n this.pillPhase = null;\n this.requestUpdate();\n return;\n }\n this.advancePill(\"closing\", ERROR_GESTURE_MS.close, () => {\n this.endGesture();\n });\n }\n\n /** Releases the slot and leaves the plain mark with its dot behind. */\n private endGesture(): void {\n this.cancelGestureTail();\n this.requestUpdate();\n this.flushPendingSignalPulse();\n }\n\n /**\n * Drops the gesture's tail outright, with no closing animation, for the\n * cases where the launcher itself has gone: the panel opened over it, or the\n * element was removed from the page.\n */\n private cancelGestureTail(): void {\n this.cancelPillTimeout();\n this.gestureSignal = null;\n this.pillPhase = null;\n this.pillDirection = null;\n }\n\n private cancelPillTimeout(): void {\n if (this.pillTimeoutId !== null) {\n clearTimeout(this.pillTimeoutId);\n this.pillTimeoutId = null;\n }\n }\n\n // ── Error signal ────────────────────────────────────────────────────────\n\n /**\n * Whether each error source is currently broken.\n *\n * Only two *wiring* conditions qualify. App errors (runs, tools, memory)\n * are unread events on a different latch — they name themselves on the pill\n * and clear when their landing view is read. Notably absent from *this*\n * latch:\n *\n * - **A failed agent run.** A run is an event. It arms `run`, not this\n * state. The resting wiring dot must not stay red for the rest of a debug\n * hour.\n * - **The core error channel as a wiring source.** Handshake failure already\n * sets the connection state. Other codes arm `run` or `tool`.\n * - **Memory failures before Learning is live.** The memory store is lazy\n * because creating it opens a realtime connection. Once it exists, a load\n * failure arms `memory`.\n * - **Product states.** An unconfigured Intelligence and an unentitled\n * Memory plan are not defects. The signal fires only where wiring is\n * present and the call still fails — which for threads is guaranteed by\n * `_threadsErrorByAgent` only ever being written while the thread\n * endpoints are available.\n *\n * Known limitation: the runtime handshake runs once, on connect. A server\n * that dies *after* the page loaded leaves the connection state at connected\n * and raises nothing; the next page load re-runs the handshake and the\n * signal appears then. The signal reports the wiring state as last\n * established. Closing that gap means a re-probe in the core, which is a\n * runtime concern.\n */\n private isErrorSourceBroken(source: InspectorWiringErrorSource): boolean {\n if (source === \"connection\") {\n const state = this.getCoreStatusSummary().state;\n // The same derivation System Health reads, so the launcher dot is red\n // exactly when System Health says the runtime needs attention.\n if (runtimeConnectionNeedsAttention(state)) return true;\n // A reconnect is not a heal. Stay red through `connecting` so the\n // cards do not flash off between retries.\n return this.errorSignalArmed.connection && state === \"connecting\";\n }\n return this._threadsErrorByAgent.size > 0;\n }\n\n /**\n * Mirrors both error latches onto the live state. Called from `willUpdate`,\n * because every mutation of the underlying state already requests an update,\n * so the resting dot follows the state within the same render.\n */\n private evaluateErrorSignals(): void {\n const wasArmed = this.hasArmedErrorSignal();\n\n for (const source of WIRING_ERROR_KEYS) {\n const broken = this.isErrorSourceBroken(source);\n if (broken) {\n if (this.errorSignalArmed[source]) continue;\n // Arming is immediate, with no window a short failure has to outlive\n // first. That is a decision, not an omission, so here is what it costs\n // and what would change it.\n //\n // `threads` can genuinely flap: the list is refetched on events, at up\n // to one request per `THREAD_LIST_DEBOUNCE_MS`, so a failure followed\n // by a success plays a whole gesture for a blip that is already over.\n // The damage is bounded by machinery that is already here — one\n // pending-beat slot, and a running gesture defers the next — so the\n // ceiling is one gesture per gesture length, never a strobe. And the\n // dot is not lying while it is up: the fetch really did fail.\n //\n // `connection` cannot flap on its own today, because nothing retries\n // the handshake: it goes connecting → connected | error and then waits\n // for something to call connect() again. If a fix for the mid-session\n // gap above adds polling, re-read this: the `connecting` branch in\n // `isErrorSourceBroken` already holds the dot steady across retries,\n // so only genuinely intermittent connectivity would flap, which is\n // exactly what the dot is for.\n //\n // So: revisit if someone reports the launcher going red without a\n // lasting cause, and start with `threads`.\n this.errorSignalArmed[source] = true;\n continue;\n }\n if (!this.errorSignalArmed[source]) continue;\n this.errorSignalArmed[source] = false;\n this.errorSignalViewedSources.delete(source);\n this.retireSignal(source);\n }\n\n this.onErrorSignalsChanged(wasArmed);\n }\n\n /**\n * Applies the rising-edge rule after a latch changed.\n *\n * The beat fires on the transition from \"no failure\" to \"at least one\n * failure\", evaluated globally across the sources and never again while\n * anything is red — one root cause, one nudge.\n */\n private onErrorSignalsChanged(wasArmed: boolean): void {\n const isArmed = this.hasArmedErrorSignal();\n if (!isArmed) {\n // Nothing is red, so the next outage is a new outage — and gets its own\n // beat, its own pill and its own answer about whether there was room.\n this.errorBeatSpent = false;\n this.pillOutcome = null;\n return;\n }\n if (wasArmed || this.errorBeatSpent) return;\n const active = this.getActiveLauncherSignal();\n if (active !== null && isErrorSignalKey(active)) {\n this.startSignalPulse(active);\n }\n }\n\n /**\n * Records `oss.inspector.error_signal_viewed` once per source per outage,\n * when the dot is actually on screen.\n *\n * Unlike the announcement's launcher event this fires immediately rather\n * than waiting for the runtime handshake to report `telemetryDisabled`.\n * The held-queue would never drain for the connection source — a connection\n * failure means the handshake did not complete — so queuing would guarantee\n * zero data for the case this event exists to measure. `trackOpened` already\n * sends on the same terms. Both opt-out layers still gate it: the local\n * opt-out inside `track`, and the runtime's flag once it is known.\n */\n private maybeTrackErrorSignalViewed(): void {\n if (\n this.isOpen ||\n typeof document === \"undefined\" ||\n document.visibilityState !== \"visible\"\n ) {\n return;\n }\n const active = this.getActiveLauncherSignal();\n if (active === null || !isErrorSignalKey(active)) return;\n if (this.errorSignalViewedSources.has(active)) return;\n // Held until this outage's pill has either opened or been suppressed,\n // because `label` IS that answer and the launcher can be on screen a frame\n // before the room around it has been measured. A signal that declares no\n // pill has no answer to wait for.\n if (\n this.pillOutcome === null &&\n LAUNCHER_SIGNALS[active].pillLabel !== undefined\n ) {\n return;\n }\n if (this.core?.telemetryDisabled) return;\n this.errorSignalViewedSources.add(active);\n trackErrorSignalViewed({\n source: active,\n presentation: this.isReducedMotionPreferred()\n ? \"reduced_motion\"\n : \"animated\",\n // Whether this outage's pill actually opened. The design deliberately\n // leaves the no-room case silent, and a degradation whose frequency is\n // unknown is a degradation that gets argued about later. Two fixed\n // values, never free text.\n label: this.pillOutcome ?? \"suppressed\",\n });\n }\n\n private maybeTrackNewsSignalViewed(): void {\n if (\n !this.newsSignalArmed ||\n this.pulsingSignal !== NEWS_SIGNAL_ID ||\n this.isOpen ||\n typeof document === \"undefined\" ||\n document.visibilityState !== \"visible\"\n ) {\n return;\n }\n const id = this.announcementTimestamp;\n if (!id || this.viewedNewsSignalIds.has(id)) return;\n this.viewedNewsSignalIds.add(id);\n this.pendingNewsSignalViewed = {\n banner_id: id,\n surface: \"launcher\",\n presentation:\n typeof window !== \"undefined\" &&\n window.matchMedia?.(\"(prefers-reduced-motion: reduce)\").matches\n ? \"reduced_motion\"\n : \"animated\",\n cta_label: this.announcementCtaLabel ?? undefined,\n };\n this.flushPendingWhatsNewTelemetry();\n }\n\n // ── What's new ─────────────────────────────────────────────────────────\n //\n // Built as a self-contained unit — its own render method, its own state,\n // and no dependency on the shape of today's two-level navigation — so the\n // planned sidebar restructuring can relocate it rather than rewrite it.\n\n /** Which of the three What's new states the feed currently supports. */\n private getWhatsNewState(): \"loading\" | \"empty\" | \"content\" {\n if (this.announcementHtml) return \"content\";\n return this.announcementLoaded ? \"empty\" : \"loading\";\n }\n\n /**\n * Which announcement surface is on screen right now, or null when the\n * announcement isn't visible. What's new is the only surface: an impression\n * requires the panel open, that view selected, and content actually\n * rendered — a loading state is not an impression.\n */\n private getVisibleBannerSurface(): WhatsNewSurface | null {\n if (!this.isOpen || this.settingsOpen) return null;\n if (this.selectedMenu !== WHATS_NEW_MENU_KEY) return null;\n return this.announcementHtml ? \"whats_new\" : null;\n }\n\n /**\n * The single condition that retires the news signal: What's new has\n * rendered *with content*.\n *\n * Deliberately not on panel open — the common reason to open the Inspector\n * is AG-UI events, and clearing there would burn a whole announcement\n * silently and turn \"viewed\" into \"opened the Inspector at some point\".\n * Deliberately not behind an acknowledge button, which is a dismiss button\n * under another name. And a loading state does not count, because the feed\n * is asynchronous and a reader who arrived early has seen nothing.\n *\n * The launcher dot and the navigation marker both read the same signal, so\n * the two can never disagree about whether something has been read.\n */\n private maybeCompleteWhatsNewView(): void {\n if (!this.getVisibleBannerSurface()) return;\n this.maybeTrackWhatsNewViewed();\n this.clearNewsSignal();\n }\n\n /**\n * Records a `whats_new_viewed` impression for whichever surface is\n * currently visible, once per announcement per surface.\n */\n private maybeTrackWhatsNewViewed(): void {\n const id = this.announcementTimestamp;\n if (!id) return;\n const surface = this.getVisibleBannerSurface();\n if (!surface) return;\n const key = `${id}:${surface}`;\n if (this.viewedBannerSurfaces.has(key)) return;\n if (this.pendingBannerViewed.length >= MAX_PENDING_BANNER_VIEWED) return;\n this.viewedBannerSurfaces.add(key);\n this.pendingBannerViewed.push({\n banner_id: id,\n surface,\n cta_label: this.announcementCtaLabel ?? undefined,\n });\n this.flushPendingWhatsNewTelemetry();\n }\n\n // Releases held notification telemetry once /info has answered, or discards\n // it when the runtime reports telemetry disabled.\n private flushPendingWhatsNewTelemetry(): void {\n if (\n this.pendingBannerViewed.length === 0 &&\n !this.pendingNewsSignalViewed\n ) {\n return;\n }\n if (this.core?.telemetryDisabled) {\n this.pendingBannerViewed = [];\n this.pendingNewsSignalViewed = null;\n return;\n }\n if (\n this.runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected\n ) {\n return;\n }\n const queued = this.pendingBannerViewed;\n this.pendingBannerViewed = [];\n for (const props of queued) trackWhatsNewViewed(props);\n if (this.pendingNewsSignalViewed) {\n const props = this.pendingNewsSignalViewed;\n this.pendingNewsSignalViewed = null;\n trackWhatsNewSignalViewed(props);\n }\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 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 cta_label?: 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 const ctaLabel =\n typeof data?.cta_label === \"string\" ? data.cta_label : null;\n\n if (!timestamp || !markdown) {\n throw new Error(\"Malformed announcement payload\");\n }\n\n this.announcementTimestamp = timestamp;\n this.announcementPreviewText = previewText ?? \"\";\n this.announcementMarkdown = markdown;\n this.announcementCtaLabel = ctaLabel;\n this.announcementHtml = await this.convertMarkdownToHtml(markdown);\n this.announcementLoaded = true;\n\n // The signal arms on a timestamp plus a body that actually renders —\n // anything else would produce a dot that What's new can never clear,\n // because clearing requires content. `previewText` does NOT gate it:\n // that was defensible while the text was the bubble's headline, but it\n // is now just the heading, and gating on it would mean an announcement\n // without preview text produced no dot at all.\n if (\n this.announcementHtml &&\n loadAnnouncementReadTimestamp() !== timestamp\n ) {\n this.armNewsSignal({\n pulse: loadAnnouncementPulsedTimestamp() !== timestamp,\n });\n }\n\n this.requestUpdate();\n } catch (error) {\n // Swallowing here would hide non-network failures (malformed JSON, the\n // explicit \"Malformed announcement payload\" throw above, exceptions\n // from `convertMarkdownToHtml`). At minimum, surface in the console so\n // a stale announcement is debuggable.\n console.warn(\"[CopilotKit Inspector] Failed to load announcement\", 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(\n this.isSafeAnnouncementHref(href ?? \"\")\n ? this.appendRefParam(href ?? \"\")\n : \"#\",\n );\n const titleAttr = title ? ` title=\"${this.escapeHtmlAttr(title)}\"` : \"\";\n return `<a href=\"${safeHref}\" target=\"_blank\" rel=\"noopener\"${titleAttr}>${text}</a>`;\n };\n renderer.html = (html) => escapeHtml(html);\n renderer.code = (code, lang) => {\n const safeLang = (lang ?? \"\").replace(/[^a-z0-9-]/gi, \"\");\n const langClass = safeLang ? ` class=\"language-${safeLang}\"` : \"\";\n const escaped = escapeHtml(code);\n const encoded = this.encodeBase64(code);\n return `<div class=\"announcement-code\"><pre><code${langClass}>${escaped}</code></pre><div class=\"announcement-code__copy-shield\"><button type=\"button\" class=\"announcement-code__copy\" data-copy=\"${encoded}\" aria-label=\"Copy code\">Copy</button></div></div>`;\n };\n return marked.parse(markdown, { renderer, async: false });\n }\n\n private isSafeAnnouncementHref(href: string): boolean {\n try {\n const url = new URL(\n href,\n typeof window !== \"undefined\"\n ? window.location.href\n : \"https://copilotkit.ai\",\n );\n return (\n url.protocol === \"http:\" ||\n url.protocol === \"https:\" ||\n url.protocol === \"mailto:\"\n );\n } catch {\n return false;\n }\n }\n\n private copyResetTimeouts = new WeakMap<HTMLButtonElement, number>();\n\n private encodeBase64(value: string): string {\n if (typeof window === \"undefined\" || typeof window.btoa !== \"function\") {\n return \"\";\n }\n // btoa only accepts Latin-1; round-trip via TextEncoder to keep full UTF-8.\n const bytes = new TextEncoder().encode(value);\n let binary = \"\";\n for (const b of bytes) binary += String.fromCharCode(b);\n return window.btoa(binary);\n }\n\n private decodeBase64(value: string): string {\n if (typeof window === \"undefined\" || typeof window.atob !== \"function\") {\n return \"\";\n }\n const decoded = window.atob(value);\n const bytes = new Uint8Array(decoded.length);\n for (let i = 0; i < decoded.length; i++) bytes[i] = decoded.charCodeAt(i);\n return new TextDecoder().decode(bytes);\n }\n\n private handleAnnouncementContentClick = (event: Event): void => {\n const target = event.target as {\n closest?: (selector: string) => Element | null;\n } | null;\n const copyControl =\n typeof target?.closest === \"function\"\n ? target.closest(\".announcement-code__copy\")\n : null;\n const button =\n copyControl?.tagName === \"BUTTON\"\n ? (copyControl as HTMLButtonElement)\n : null;\n if (!button) {\n const link =\n typeof target?.closest === \"function\" ? target.closest(\"a\") : null;\n if (!link) return;\n\n const href = link.getAttribute(\"href\");\n if (href) link.setAttribute(\"href\", this.appendRefParam(href));\n\n // whats_new_clicked fires once per banner per mount. Dedup prevents\n // accidental multi-clicks from inflating the link-follow funnel.\n this.trackWhatsNewClickedOnce({ cta: \"body\" });\n return;\n }\n event.preventDefault();\n event.stopPropagation();\n const encoded = button.getAttribute(\"data-copy\") ?? \"\";\n const code = this.decodeBase64(encoded);\n if (!code) {\n return;\n }\n const showCopied = () => {\n const view = button.ownerDocument.defaultView ?? window;\n const existing = this.copyResetTimeouts.get(button);\n if (existing !== undefined) {\n view.clearTimeout(existing);\n }\n button.setAttribute(\"data-copied\", \"true\");\n button.setAttribute(\"aria-label\", \"Code copied\");\n button.textContent = \"Copied\";\n const id = view.setTimeout(() => {\n button.removeAttribute(\"data-copied\");\n button.setAttribute(\"aria-label\", \"Copy code\");\n button.textContent = \"Copy\";\n this.copyResetTimeouts.delete(button);\n }, 1500);\n this.copyResetTimeouts.set(button, id);\n };\n const clipboard = this.getClipboard(event);\n if (clipboard?.writeText) {\n clipboard.writeText(code).then(showCopied, () => {\n // ignore — clipboard may be unavailable (insecure context, denied\n // permission, focus loss); button silently stays in idle state.\n });\n }\n };\n\n private appendRefParam(href: string, ref = \"cpk-inspector\"): string {\n try {\n const isRootRelative = href.startsWith(\"/\") && !href.startsWith(\"//\");\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\", ref);\n }\n // Propagate the inspector's anonymous distinct-ID so the website /\n // Ops API can call posthog.alias(...) on signup-flow landing and\n // close the whats_new_viewed → whats_new_clicked → signup_attributed\n // funnel. Returns null when the user has opted out, so opt-out\n // suppresses cross-domain ID leaks too.\n if (\n !url.searchParams.has(\"posthog_distinct_id\") &&\n this.runtimeStatus ===\n CopilotKitCoreRuntimeConnectionStatus.Connected &&\n !this.core?.telemetryDisabled &&\n this.isCopilotKitDestination(url)\n ) {\n const distinctId = getTelemetryDistinctIdForUrl();\n if (distinctId) {\n url.searchParams.append(\"posthog_distinct_id\", distinctId);\n }\n }\n if (isRootRelative) {\n return `${url.pathname}${url.search}${url.hash}`;\n }\n return url.toString();\n } catch {\n return href;\n }\n }\n\n private isCopilotKitDestination(url: URL): boolean {\n const hostname = url.hostname.toLowerCase();\n return hostname === \"copilotkit.ai\" || hostname.endsWith(\".copilotkit.ai\");\n }\n\n private escapeHtmlAttr(value: string): string {\n return escapeHtml(value).replace(/\"/g, \"&quot;\").replace(/'/g, \"&#39;\");\n }\n}\n\n// `customElements` is missing during SSR and in torn-down DOM test\n// environments. Resolve it when this function is called so registration can\n// be retried once a browser registry becomes available.\nexport function defineWebInspector(\n registry: CustomElementRegistry | undefined = globalThis.customElements,\n): void {\n if (!registry) return;\n\n defineElementOnce(registry, \"cpk-thread-list\", CpkThreadList);\n defineElementOnce(registry, THREAD_INSPECTOR_TAG, CpkThreadInspector);\n defineElementOnce(registry, \"cpk-thread-details\", ɵCpkThreadDetails);\n defineElementOnce(registry, \"cpk-memory-list\", CpkMemoryList);\n defineElementOnce(registry, WEB_INSPECTOR_TAG, WebInspectorElement);\n}\n\n/**\n * Bind a host-owned core before an Inspector is connected to the DOM. Disabling\n * auto-attachment first prevents `connectedCallback` from briefly selecting a\n * different global core.\n */\nexport function configureWebInspectorElement(\n inspector: WebInspectorElement,\n core: CopilotKitCore | null,\n): WebInspectorElement {\n inspector.autoAttachCore = false;\n inspector.core = core;\n return inspector;\n}\n\ndefineWebInspector();\n\ndeclare global {\n interface HTMLElementTagNameMap {\n \"cpk-web-inspector\": WebInspectorElement;\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AAwMA,MAAa,oBAAoB;AACjC,MAAa,uBAAuB;;;;;AAMpC,MAAM,sBAAsB;AAC5B,MAAM,kCAAkC;;;;;;AAOxC,MAAM,uBAAuB;;AAG7B,MAAM,qBAAqB;AA0E3B,MAAM,iBAAiB;AAUvB,MAAM,yBAAuE;CAC3E,MAVwB;CAWxB,OAJyB;CAK1B;;;;;;;;;;;;;;;;AAiBD,MAAM,mBAAmB;CAEvB,MAAM;CAEN,MAAM;CAEN,MAAM;CAEN,OAAO;CACR;;;;;;;;AASD,MAAM,sBAAsB;AAC5B,MAAM,2BAA2B;AACjC,MAAM,yBAAyB;AAC/B,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;;;;;;;;;;;;;AAchC,MAAM,uBAKF;CACF,KAAK;EACH,OAAO;EACP,WAAW;EACZ;CACD,MAAM;EACJ,OAAO;EACP,WAAW;EACZ;CACD,QAAQ;EACN,OAAO;EACP,QACE;EACH;CACF;;;;;;;;;;;;;;AAeD,MAAM,qBAAqB;AAI3B,MAAM,sBAAsB;AAC5B,MAAM,+BAA+B;AACrC,MAAM,oBAAoB;AAC1B,MAAM,qBAAqB;AAC3B,MAAM,uBAAuB;AAG7B,MAAM,yBAEF;CACF,KAAK,OAAU,KAAK;CACpB,MAAM;CACP;AAQD,MAAM,mBAEF;CAGF,aAAa;EACX,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS;EACT,UAAU;EACV,iBAAiB;EAClB;CAGD,YAAY;EACV,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS,iBAAiB;EAC1B,UAAU;EACV,iBAAiB;EACjB,WAAW;EACZ;CACD,SAAS;EACP,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS,iBAAiB;EAG1B,UAAU;EACV,iBAAiB;EACjB,WAAW;EACZ;CAGD,KAAK;EACH,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS,iBAAiB;EAC1B,UAAU;EACV,iBAAiB;EACjB,WAAW;EACZ;CACD,MAAM;EACJ,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS,iBAAiB;EAC1B,UAAU;EACV,iBAAiB;EACjB,WAAW;EACZ;CACD,QAAQ;EACN,MAAM;EACN,cAAc;EACd,eAAe;EACf,SAAS,iBAAiB;EAC1B,UAAU;EACV,iBAAiB;EACjB,WAAW;EACZ;CACF;;AAGD,MAAM,iCACJ,OAAO,KAAK,iBAAiB,CAC7B,MAAM,GAAG,MAAM,iBAAiB,GAAG,WAAW,iBAAiB,GAAG,SAAS;;AAG7E,MAAM,oBAAoB,CACxB,cACA,UACD;;AAGD,MAAM,mBAAmB;CACvB;CACA;CACA;CACD;AASD,SAAS,iBACP,KACmC;AACnC,QAAQ,kBAAwC,SAAS,IAAI;;;;;;;;;AAU/D,SAAS,gBAAgB,KAA+C;AACtE,QAAQ,iBAAuC,SAAS,IAAI;;;AAI9D,SAAS,iBACP,KACmC;AACnC,QAAO,iBAAiB,IAAI,IAAI,gBAAgB,IAAI;;;;;;;;AAUtD,MAAM,0BACJ;;AAIF,SAAS,oBAAoB,OAAuB;AAClD,KAAI,OAAO,QAAQ,eAAe,OAAO,IAAI,WAAW,WACtD,QAAO,IAAI,OAAO,MAAM;AAE1B,QAAO,MAAM,QAAQ,yBAAyB,OAAO;;AAGvD,SAAS,qBACP,MACkC;AAClC,SAAQ,MAAR;EACE,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB,gBAC3B,QAAO;EACT,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB;EAC7B,KAAK,wBAAwB,sBAC3B,QAAO;EACT,QACE,QAAO;;;;;;;;AASb,MAAM,0BAA0B;;AAGhC,MAAM,sBAAsB;AAkC5B,MAAM,cAAc;;AAEpB,MAAM,qBAAqB;;;;;;;;AAQ3B,MAAM,wBAAwB;CAC5B,OAAO;CACP,UAAU;CACV,gBAAgB;CAChB,kBAAkB;CAClB,mBAAmB;CACnB,cAAc;CACf;;AAGD,MAAM,6BAA6B,eACjC,GACE,sBAAsB,iBACtB,aAAa,sBAAsB,iBACpC;AACH,MAAM,iBAAiB;AACvB,MAAM,mBAAmB;AACzB,MAAM,+BAA+B;AACrC,MAAM,oBAAoB;AAC1B,MAAM,wBAAwB;AAC9B,MAAM,mBAAmB;AAGzB,MAAM,oBAAoB;AAC1B,MAAM,oBAAoB;AAC1B,MAAM,sBAA4B;CAChC,OAAO;CACP,QAAQ;CACT;AACD,MAAM,sBAA4B;CAAE,OAAO;CAAK,QAAQ;CAAK;AAC7D,MAAM,oBAAoB;AAC1B,MAAM,mBAAmB;AACzB,MAAM,+BACJ;AAGF,MAAM,4BAA4B;AAClC,MAAM,mBAAmB;AACzB,MAAM,0BAA0B;AAChC,MAAM,uBAAuB;AAK7B,MAAM,yBAAyB;AAE/B,SAAS,2BAAmC;AAC1C,QAAO,WAAW,QAAQ,cAAc,IAAI,cAAc,KAAK,KAAK;;AAGtE,MAAM,mBAAmB;AACzB,MAAM,+BACJ;AA2BF,MAAM,2BAA2B;CAC/B;EACE,IAAI;EACJ,OAAO;EAMP,UAAU;EAUV,MAAM;EAIN,SACE;EACH;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,MAAM;EAKN,SACE;EACH;CACD;EACE,IAAI;EACJ,OAAO;EACP,UAAU;EACV,MAAM;EAON,SACE;EACH;CACD;EACE,IAAI;EAKJ,OAAO;EACP,UAAU;EACV,MAAM;EAMN,SACE;EACH;CACF;;;;;;;;;AAUD,MAAM,6BAA6B;CACjC;EAAE,OAAO;EAA+B,MAAM;EAAa,QAAQ;EAAO;CAC1E;EACE,OAAO;EACP,MAAM;EACN,QAAQ;EACT;CACD;EAAE,OAAO;EAAyB,MAAM;EAAgB,QAAQ;EAAM;CACvE;;AAGD,MAAM,2BAA2B;CAC/B;CACA;CACA;CACD;;;;;;;;AASD,MAAM,6BAA6B;CACjC;CACA;CACA;CACD;AAID,MAAM,gCAAgC;;;;;;AAOtC,MAAM,uBAAuB;AAM7B,MAAM,2BAA2B;CAC/B;EACE,MAAM;EACN,MAAM;EACN,QAAQ;EACT;CACD;EAAE,MAAM;EAAa,MAAM;EAAY,QAAQ;EAAsB;CACrE;EAAE,MAAM;EAAY,MAAM;EAAU,QAAQ;EAAe;CAC3D;EAAE,MAAM;EAAS,MAAM;EAAc,QAAQ;EAA2B;CACzE;AACD,MAAM,qCACJ;AACF,MAAM,0CACJ;AACF,MAAM,2BACJ;AACF,MAAM,4BACJ;AAMF,MAAM,iCAAiC;CACrC;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACF;AACD,MAAM,kCAAkC;CACtC;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACD;EACE,MAAM;EACN,OAAO;EACP,aACE;EACH;CACF;AACD,MAAM,mCACJ;AACF,MAAM,2BAA2B;;AAsBjC,SAAS,kBAAkB,SAA+B;CACxD,MAAM,uBAAO,IAAI,KAAa;CAC9B,MAAM,SAAoB,EAAE;AAC5B,MAAK,MAAM,UAAU,SAAS;AAC5B,MAAI,KAAK,IAAI,OAAO,GAAG,CACrB;AAEF,OAAK,IAAI,OAAO,GAAG;AACnB,SAAO,KAAK,OAAO;;AAErB,QAAO;;AAGT,SAAS,sBACP,gBACW;AACX,QAAO,kBAAkB,MAAM,KAAK,eAAe,QAAQ,CAAC,CAAC,MAAM,CAAC;;;;;;AAOtE,SAAS,kCAEc;CACrB,IAAI;CACJ,IAAI;CACJ,IAAI;AAEJ,SAAQ,UAAU;EAChB,MAAM,QAAQ,oBAAoB,MAAM;EACxC,MAAM,YAAY,wBAAwB,MAAM;AAChD,MACE,kBACA,kBAAkB,SAClB,sBAAsB,UAEtB,QAAO;AAGT,kBAAgB;AAChB,sBAAoB;AACpB,mBAAiB;GAAE;GAAO;GAAW;AACrC,SAAO;;;AA+BX,MAAM,oBAAwD;CAC5D;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACA;CACD;AAED,MAAM,sBAAsB;CAC1B,SACE;CACF,aACE;CACH;AA+BD,MAAM,2BAA+C,EAAE;AAEvD,SAAS,uBAAuB,SAA0B;AACxD,KAAI,OAAO,YAAY,SAAU,QAAO;AACxC,KAAI,MAAM,QAAQ,QAAQ,EAAE;EAC1B,MAAM,QAAkB,EAAE;AAC1B,OAAK,MAAM,QAAQ,SAAS;AAC1B,OAAI,OAAO,SAAS,UAAU;AAC5B,UAAM,KAAK,KAAK;AAChB;;AAEF,OAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,UAAU,MAAM;IAC/D,MAAM,OAAO,KAAK;AAClB,QAAI,OAAO,SAAS,SAAU,OAAM,KAAK,KAAK;;;AAGlD,SAAO,MAAM,KAAK,GAAG;;AAEvB,KAAI,OAAO,YAAY,YAAY,YAAY,QAAQ,UAAU,SAAS;EACxE,MAAM,OAAO,QAAQ;AACrB,MAAI,OAAO,SAAS,SAAU,QAAO;;AAEvC,QAAO;;;;;;;AAwCT,SAAS,oBAAoB,MAAiD;CAC5E,MAAM,OAA4B,EAAE;AACpC,MAAK,MAAM,QAAQ,KAAK,SAAS,EAAE,EAAE;EAEnC,MAAM,MAAM,GADI,KAAK,WAAW,GACT,GAAG,KAAK;AAC/B,OAAK,KAAK;GACR;GACA,MAAM,KAAK;GACX,aAAa,KAAK;GAClB,SAAS,KAAK;GACd,SAAS,KAAK,cAAc,KAAK,MAAM,KAAK,QAAQ;GACrD,CAAC;;AAEJ,QAAO,KAAK,MAAM,GAAG,MAAM;EACzB,MAAM,gBAAgB,EAAE,WAAW,IAAI,cAAc,EAAE,WAAW,GAAG;AACrE,MAAI,iBAAiB,EAAG,QAAO;AAC/B,SAAO,EAAE,KAAK,cAAc,EAAE,KAAK;GACnC;;AA2LJ,MAAM,0BAA2C;CAC/C;EACE,IAAI;EACJ,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,aAAa;EACb,UAAU;EACV,WAAW;EACX,WAAW;EACX,WAAW;EACZ;CACD;EACE,IAAI;EACJ,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,aAAa;EACb,UAAU;EACV,WAAW;EACX,WAAW;EACX,WAAW;EACZ;CACD;EACE,IAAI;EACJ,MAAM;EACN,SAAS;EACT,gBAAgB;EAChB,aAAa;EACb,UAAU;EACV,WAAW;EACX,WAAW;EACX,WAAW;EACZ;CACF;;AAGD,SAAS,eAAe,UAA2C;AACjE,SAAQ,UAAR;EACE,KAAK,wBACH,QAAO;EACT,KAAK,yBACH,QAAO;EACT,KAAK,uBACH,QAAO;EACT,QACE;;;AAIN,MAAM,0BAAgE;CACpE,yBAAyB;EACvB,UAAU,CACR;GACE,IAAI;GACJ,MAAM;GACN,SAAS;GACV,EACD;GACE,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,cAAc;KACd,QAAQ;KACT;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,QAAQ;KACR,cAAc;KACd,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,QAAQ;GACR,cAAc;GACd,YAAY;GACZ,iBAAiB;GAClB;EACF;CACD,0BAA0B;EACxB,UAAU,CACR;GACE,IAAI;GACJ,MAAM;GACN,SAAS;GACV,EACD;GACE,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,QAAQ;KACR,cAAc;KACd,MAAM;KACP;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,MAAM;GACN,eAAe;GACf,aAAa;GACd;EACF;CACD,wBAAwB;EACtB,UAAU,CACR;GACE,IAAI;GACJ,MAAM;GACN,SAAS;GACV,EACD;GACE,IAAI;GACJ,MAAM;GACN,SACE;GACH,CACF;EACD,QAAQ;GACN;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,UAAU;KACV,SAAS;KACV;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,YAAY;KACZ,UAAU;KACX;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS;KACP,YAAY;KACZ,OAAO;KACP,aAAa;KACd;IACF;GACD;IACE,MAAM;IACN,WAAW;IACX,SAAS,EACP,QAAQ,aACT;IACF;GACF;EACD,OAAO;GACL,aAAa;GACb,OAAO;GACP,aAAa;GACb,mBAAmB;GACpB;EACF;CACF;AAED,MA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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;sBA2hDR,UAAU,uBAAuB,KAAK,CAAC;;;sBAGvC,UAAU,uBAAuB,MAAM,CAAC;;;;;;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"}