import { createComponent as _$createComponent } from "opentui:runtime-module:%40opentui%2Fsolid";
import { createTextNode as _$createTextNode } from "opentui:runtime-module:%40opentui%2Fsolid";
import { memo as _$memo } from "opentui:runtime-module:%40opentui%2Fsolid";
import { effect as _$effect } from "opentui:runtime-module:%40opentui%2Fsolid";
import { insertNode as _$insertNode } from "opentui:runtime-module:%40opentui%2Fsolid";
import { insert as _$insert } from "opentui:runtime-module:%40opentui%2Fsolid";
import { setProp as _$setProp } from "opentui:runtime-module:%40opentui%2Fsolid";
import { createElement as _$createElement } from "opentui:runtime-module:%40opentui%2Fsolid";
/** @jsxImportSource @opentui/solid */
// @ts-nocheck

// AFT sidebar slot. Header with "AFT" badge + version, then live status of search and semantic
// indexes plus their on-disk size. Refreshes on mount/session change and on
// server-pushed status invalidations with a small debounce, so the panel stays
// current without polling.

import { canonicalizeProjectRoot } from "@cortexkit/aft-bridge";
import { createEffect, createMemo, createSignal, on, onCleanup } from "opentui:runtime-module:solid-js";
import { AftRpcClient } from "../shared/rpc-client";
import { coerceAftStatus, formatSemanticIndexStatus, formatSemanticRefreshing, worktreeCacheRoleNote } from "../shared/status";
import { resolveCortexKitStorageRoot } from "../shared/storage-paths";
import { badgeTextColor } from "./badge-contrast";
import { createDebouncedStatusRefresh, refreshAftTuiSocketScope, subscribeStatusInvalidations } from "./notification-socket";
import { computeEffectiveOrder, DEFAULT_PREFS, DEFAULT_SLOT_ORDER, PLUGIN_KEY, persistCollapsedIfEnabled, readTuiPreferencesFile, resolveAftPrefs, seedCollapsedFromPrefs, watchTuiPreferences } from "./preferences";
const SINGLE_BORDER = {
  type: "single"
};
const REFRESH_DEBOUNCE_MS = 200;
function formatBytes(n) {
  if (!Number.isFinite(n) || n <= 0) return "—";
  if (n >= 1_073_741_824) return `${(n / 1_073_741_824).toFixed(1)} GB`;
  if (n >= 1_048_576) return `${(n / 1_048_576).toFixed(1)} MB`;
  if (n >= 1_024) return `${Math.round(n / 1_024)} KB`;
  return `${n} B`;
}
function formatCount(n) {
  if (n == null || !Number.isFinite(n)) return "—";
  if (n >= 1_000_000) return `${(n / 1_000_000).toFixed(1)}M`;
  if (n >= 1_000) return `${Math.round(n / 1_000)}K`;
  return String(n);
}

/** Tagged rows for the Compression section. Each scope (Session / Project)
 * emits a "scope" header followed by two "stat" rows — Tokens Saved and
 * Compression Ratio — so the renderer can use the same StatRow layout as
 * Search Index / Semantic Index above. Pi's monospace overlay and the
 * OpenCode TUI dialog/sidebar all consume this same shape. */

function appendScope(rows, label, scope) {
  const savings = scope.savings_tokens;
  const pct = scope.original_tokens > 0 ? Math.round(savings / scope.original_tokens * 100) : 0;
  rows.push({
    kind: "scope",
    label
  });
  rows.push({
    kind: "stat",
    label: "Tokens Saved",
    value: savings.toLocaleString("en-US")
  });
  rows.push({
    kind: "stat",
    label: "Compression Ratio",
    value: `${pct}%`
  });
}
export function formatCompressionSidebarRows(compression) {
  if (!compression || compression.project.events <= 0) return [];
  const rows = [];
  if (compression.session.events > 0) {
    appendScope(rows, "Session", compression.session);
  }
  appendScope(rows, "Project", compression.project);
  return rows;
}

// Map index status → (label, theme color name). The label is what we want
// the user to see; the color encodes severity so the eye lands on warnings.
function statusDisplay(status) {
  switch (status) {
    case "ready":
      return {
        label: "ready",
        tone: "ok"
      };
    case "loading":
    case "building":
      return {
        label: status,
        tone: "warn"
      };
    case "failed":
    case "error":
      return {
        label: status,
        tone: "err"
      };
    case "disabled":
      return {
        label: "disabled",
        tone: "muted"
      };
    default:
      return {
        label: status || "unknown",
        tone: "muted"
      };
  }
}
const StatRow = props => {
  const fg = createMemo(() => {
    switch (props.tone) {
      case "ok":
        return props.theme.success ?? props.theme.accent;
      case "warn":
        return props.theme.warning;
      case "err":
        return props.theme.error;
      case "muted":
        return props.theme.textMuted;
      case "accent":
        return props.theme.accent;
      default:
        return props.theme.text;
    }
  });
  return (() => {
    var _el$ = _$createElement("box"),
      _el$2 = _$createElement("text"),
      _el$3 = _$createElement("text"),
      _el$4 = _$createElement("b");
    _$insertNode(_el$, _el$2);
    _$insertNode(_el$, _el$3);
    _$setProp(_el$, "width", "100%");
    _$setProp(_el$, "flexDirection", "row");
    _$setProp(_el$, "justifyContent", "space-between");
    _$insert(_el$2, () => props.label);
    _$insertNode(_el$3, _el$4);
    _$insert(_el$4, () => props.value);
    _$effect(_p$ => {
      var _v$ = props.theme.textMuted,
        _v$2 = fg();
      _v$ !== _p$.e && (_p$.e = _$setProp(_el$2, "fg", _v$, _p$.e));
      _v$2 !== _p$.t && (_p$.t = _$setProp(_el$3, "fg", _v$2, _p$.t));
      return _p$;
    }, {
      e: undefined,
      t: undefined
    });
    return _el$;
  })();
};
const SectionHeader = props => (() => {
  var _el$5 = _$createElement("box"),
    _el$6 = _$createElement("text"),
    _el$7 = _$createElement("b");
  _$insertNode(_el$5, _el$6);
  _$setProp(_el$5, "width", "100%");
  _$insertNode(_el$6, _el$7);
  _$insert(_el$7, () => props.title);
  _$effect(_p$ => {
    var _v$3 = props.marginTop ?? 1,
      _v$4 = props.theme.text;
    _v$3 !== _p$.e && (_p$.e = _$setProp(_el$5, "marginTop", _v$3, _p$.e));
    _v$4 !== _p$.t && (_p$.t = _$setProp(_el$6, "fg", _v$4, _p$.t));
    return _p$;
  }, {
    e: undefined,
    t: undefined
  });
  return _el$5;
})();

// Map a status tone to a theme color — used for the collapsed-view status dots.
function toneColor(theme, tone) {
  switch (tone) {
    case "ok":
      return theme.success ?? theme.accent;
    case "warn":
      return theme.warning;
    case "err":
      return theme.error;
    default:
      return theme.textMuted;
  }
}

// Collapsed-view row: label on the left, a status dot (or compact value) on the
// right. Mirrors the expanded StatRow layout so the columns line up.
const CollapsedRow = props => (() => {
  var _el$8 = _$createElement("box"),
    _el$9 = _$createElement("text");
  _$insertNode(_el$8, _el$9);
  _$setProp(_el$8, "width", "100%");
  _$setProp(_el$8, "flexDirection", "row");
  _$setProp(_el$8, "justifyContent", "space-between");
  _$insert(_el$9, () => props.label);
  _$insert(_el$8, () => props.children, null);
  _$effect(_$p => _$setProp(_el$9, "fg", props.theme.textMuted, _$p));
  return _el$8;
})();

// Compact "saved / ratio" string for the collapsed Compression row — e.g.
// "7.6M / 64%". Uses the local `formatCount` (not the aft-bridge token
// formatter) so the TUI bundle doesn't pull the bridge barrel, which exports
// URL-fetch helpers unsuitable for Bun's TUI runtime. Returns null when no
// compression has been recorded yet.
export function collapsedCompressionValue(compression) {
  if (!compression || compression.project.events <= 0) return null;
  const {
    savings_tokens,
    original_tokens
  } = compression.project;
  const pct = original_tokens > 0 ? Math.round(savings_tokens / original_tokens * 100) : 0;
  return `${formatCount(savings_tokens)} / ${pct}%`;
}
// Degraded-mode reason → human-readable hint. Distinct strings per reason
// because the UX direction is different: "home_root" tells the user to open a
// real project subdirectory, "search_too_many_files" tells them the tree is too
// big for full indexing, and "watcher_unavailable" is an honest soft
// degradation (AFT continues without live external-change invalidation).
export function degradedReasonLabel(reason) {
  if (reason === "home_root") {
    return "project root is your home directory";
  }
  if (reason.startsWith("search_too_many_files:")) {
    const threshold = reason.split(":")[1] ?? "20000";
    return `project exceeds ${threshold} files`;
  }
  if (reason === "watcher_unavailable") {
    return "file watcher unavailable; continuing without live external-change invalidation";
  }
  return reason; // unknown reason — surface verbatim so users can grep logs
}
// Missing categories are intentionally muted: a green light requires an
// explicit zero for every category that feeds that light.
export function collapsedHealthLights(statusBar) {
  if (!statusBar) return null;
  const diagnostics = statusBar.errors !== undefined && statusBar.errors > 0 ? "err" : statusBar.warnings !== undefined && statusBar.warnings > 0 ? "warn" : statusBar.errors === 0 && statusBar.warnings === 0 ? "ok" : "muted";
  const codeValues = [statusBar.dead_code, statusBar.unused_exports, statusBar.duplicates];
  const code = codeValues.some(value => value !== undefined && value > 0) ? "warn" : codeValues.every(value => value === 0) ? "ok" : "muted";
  const todos = statusBar.todos === undefined ? "muted" : statusBar.todos > 0 ? "warn" : "ok";
  return {
    diagnostics,
    code,
    todos
  };
}

// Keep the TUI on the bridge's shared resolver so its root matches the
// configure payload used by the plugin and binary.
export function resolveTuiStorageDir() {
  return resolveCortexKitStorageRoot();
}

// One RPC client per project directory — same pattern as the /aft-status
// dialog handler in tui/index.tsx. Sharing the map avoids opening a second
// connection just for the sidebar.
const sidebarClients = new Map();
function getClient(directory) {
  let client = sidebarClients.get(directory);
  if (client) return client;
  client = new AftRpcClient(resolveTuiStorageDir(), directory);
  sidebarClients.set(directory, client);
  return client;
}
export function scopedSidebarSnapshot(scoped, directory, sessionID) {
  if (!scoped) return null;
  if (scoped.directory !== directory || scoped.sessionID !== sessionID) return null;
  return scoped.snapshot;
}

/**
 * Stale-while-revalidate guard. A transient `not_initialized` snapshot (bridge
 * mid-respawn after a binary swap, or a momentary session-dir key miss) arrives
 * over RPC as `success: true`, so a naive `setStatus` would overwrite a good
 * snapshot and collapse the panel to the lazy-bridge placeholder — the blank
 * flicker that recovers on the next refresh. Suppress the downgrade only when we
 * already hold initialized data for the same context; never blocks the first
 * real snapshot, and a genuine context switch clears separately.
 */
export function shouldSuppressUninitializedDowngrade(incomingCacheRole, haveInitializedForContext) {
  return incomingCacheRole === "not_initialized" && haveInitializedForContext;
}

/**
 * Cross-project contamination belt. The RPC layer can hand back a snapshot
 * describing a DIFFERENT project than the one this sidebar asked about — a
 * multi-project host (Desktop / `opencode serve`) whose status handler
 * resolved another project's warm bridge, including long-lived processes
 * still running pre-fix plugin code. Rendering it shows another repo's
 * indexes/health in this window.
 *
 * A mismatched project_root is acceptable ONLY when the serving handler says
 * it resolved that directory DELIBERATELY: new servers attach
 * `served_directory` (their own cwd, or the SDK-verified `opencode -s` resume
 * directory) to every status response. That marker is handler-attached
 * provenance — it cannot be faked by snapshot contents. We explicitly do NOT
 * use `snapshot.session.id` here: Rust echoes the REQUESTED session id into
 * the snapshot, so it matches even when the data came from another project's
 * bridge (the hole that let contamination through this belt's first version).
 *
 * Rules:
 *  - placeholder/synthetic snapshots (no project_root) → accept (not data)
 *  - project_root (or canonical_root) matches the sidebar directory → accept
 *  - mismatched root AND served_directory matches a snapshot root → accept
 *    (deliberate, SDK-verified resume serve from a new server)
 *  - otherwise → reject (stray; includes everything old servers cross-serve)
 */
export function isSnapshotForContext(snapshot, directory, servedDirectory) {
  // Canonicalize both sides through the SAME canonicalizer the bridge routes
  // by, so a symlinked / `/var`-vs-`/private/var` / trailing-slash spelling of
  // the sidebar directory still matches Rust's canonical_root. A raw stripSlash
  // compare (the old behavior) rejected legitimate snapshots whenever the TUI
  // directory and Rust's root were different spellings of the same location,
  // leaving the sidebar blank on aliased roots.
  const canon = p => canonicalizeProjectRoot(p);
  const roots = [snapshot.project_root, snapshot.canonical_root].filter(r => typeof r === "string" && r.length > 0);
  if (roots.length === 0) return true; // placeholder / synthetic
  const dir = canon(directory);
  if (roots.some(r => canon(r) === dir)) return true;
  if (typeof servedDirectory === "string" && servedDirectory.length > 0) {
    const served = canon(servedDirectory);
    return roots.some(r => canon(r) === served);
  }
  return false;
}
const SidebarContent = props => {
  const [status, setStatus] = createSignal(null);
  const [prefs, setPrefs] = createSignal(structuredClone(DEFAULT_PREFS));
  const [collapsed, setCollapsed] = createSignal(seedCollapsedFromPrefs(DEFAULT_PREFS));
  let inflight = null;
  let generation = 0;
  const currentDirectory = () => props.api.state.path.directory ?? "";
  const requestRender = () => {
    try {
      props.api.renderer.requestRender();
    } catch {
      // renderer may not be available during teardown; safe to ignore
    }
  };
  const abortInflight = () => {
    if (!inflight) return;
    inflight.controller.abort();
    inflight = null;
  };
  const clearStatusForContext = (directory, sessionID) => {
    const current = status();
    if (!current) return;
    if (current.directory === directory && current.sessionID === sessionID) return;
    setStatus(null);
    requestRender();
  };
  const refresh = async () => {
    const sid = props.sessionID();
    const directory = currentDirectory();
    if (!sid || !directory) {
      generation++;
      abortInflight();
      if (status()) {
        setStatus(null);
        requestRender();
      }
      return;
    }
    clearStatusForContext(directory, sid);
    if (inflight) {
      if (inflight.directory === directory && inflight.sessionID === sid) return;
      generation++;
      abortInflight();
    }
    const requestGeneration = ++generation;
    const controller = new AbortController();
    inflight = {
      controller,
      generation: requestGeneration,
      directory,
      sessionID: sid
    };
    try {
      const client = getClient(directory);
      const response = await client.call("status", {
        sessionID: sid
      }, {
        signal: controller.signal,
        // With several RPC servers alive for this project hash, a stray
        // warm response (another project's bridge) must not beat the right
        // server or the placeholder — skip it at the port-scan level.
        accept: result => {
          const rec = result;
          if (rec?.success === false) return true; // errors handled below
          return isSnapshotForContext(coerceAftStatus(rec), directory, rec?.served_directory);
        }
      });
      if (controller.signal.aborted || requestGeneration !== generation) return;
      if (currentDirectory() !== directory || props.sessionID() !== sid) return;
      if (response && response.success !== false) {
        const snapshot = coerceAftStatus(response);
        // Belt: never render a snapshot describing another project (see
        // isSnapshotForContext). Keep whatever we currently show instead.
        const servedDirectory = response.served_directory;
        if (!isSnapshotForContext(snapshot, directory, servedDirectory)) return;
        // Stale-while-revalidate: keep the last-good snapshot instead of
        // flickering to the lazy-bridge placeholder on a transient
        // not_initialized. See shouldSuppressUninitializedDowngrade.
        const current = status();
        const haveGoodForContext = current !== null && current.directory === directory && current.sessionID === sid && current.snapshot.cache_role !== "not_initialized";
        if (shouldSuppressUninitializedDowngrade(snapshot.cache_role, haveGoodForContext)) return;
        // Equality gate: a pushed invalidation can still produce the same
        // snapshot (for example, a session-scoped status frame that does not
        // affect this sidebar's visible fields). Minting a new status object
        // would run SolidJS reactivity and schedule a host frame for no visible
        // change. Skip the update when the freshly-fetched snapshot is
        // byte-identical to what we already show for this exact context.
        // JSON.stringify is sound here because the snapshot is a plain object
        // coerced from the status RPC's JSON.
        if (current !== null && current.directory === directory && current.sessionID === sid && JSON.stringify(current.snapshot) === JSON.stringify(snapshot)) {
          return;
        }
        setStatus({
          directory,
          sessionID: sid,
          snapshot
        });
        requestRender();
      }
    } catch {
      if (controller.signal.aborted || requestGeneration !== generation) return;
      // RPC server may not be ready yet, or the bridge may be respawning
      // after a binary swap. Keep the previous snapshot only when it belongs
      // to the current project/session; mismatched snapshots were cleared above.
    } finally {
      if (inflight?.generation === requestGeneration) inflight = null;
    }
  };
  const statusDebouncer = createDebouncedStatusRefresh(refresh, REFRESH_DEBOUNCE_MS);
  const scheduleRefresh = () => statusDebouncer.schedule();
  const reloadPrefs = async () => {
    const root = await readTuiPreferencesFile();
    const next = resolveAftPrefs(root);
    setPrefs(next);
    setCollapsed(seedCollapsedFromPrefs(next));
    requestRender();
  };
  void reloadPrefs();
  const unwatchPrefs = watchTuiPreferences(() => {
    void reloadPrefs();
  });
  onCleanup(() => {
    unwatchPrefs();
    generation++;
    abortInflight();
    statusDebouncer.dispose();
  });

  // Refresh on session id change + initial load
  createEffect(on(props.sessionID, () => {
    refreshAftTuiSocketScope();
    void refresh();
  }));

  // Wire live updates: the server pushes a lightweight invalidation whenever
  // the bridge reports a status change. The sidebar coalesces bursts into one
  // trailing status fetch and stays completely idle when no backend state changes.
  createEffect(on(props.sessionID, sessionID => {
    if (!sessionID) return;
    const unsubscribe = subscribeStatusInvalidations(event => {
      if (event.sessionId && event.sessionId !== props.sessionID()) return;
      scheduleRefresh();
    });
    onCleanup(() => {
      unsubscribe();
      generation++;
      abortInflight();
    });
  }, {
    defer: false
  }));
  const s = () => scopedSidebarSnapshot(status(), currentDirectory(), props.sessionID());

  // Lazy-bridge: while AFT has no live bridge yet, the RPC server returns a
  // synthetic snapshot with `cache_role === "not_initialized"`. In that state
  // every metric is unknown by design — not "disabled" — so we hide the
  // version line and the entire Search Index / Semantic Index / Compression
  // grid until a first tool call warms the bridge. Users were reading the
  // pre-init `vunknown` + `Status: unknown` rows as broken state instead of
  // "AFT has not been used yet for this project".
  const notInitialized = () => s()?.cache_role === "not_initialized";

  // Pre-compute display values so the JSX stays readable. createMemo for
  // each derived field would be overkill — these are cheap derivations.
  const searchStatus = () => statusDisplay(s()?.search_index?.status ?? "disabled");
  const semanticStatus = () => {
    const rawStatus = s()?.semantic_index?.status ?? "disabled";
    const display = statusDisplay(rawStatus);
    return {
      ...display,
      label: formatSemanticIndexStatus(rawStatus, s()?.semantic_index?.stage)
    };
  };
  const semanticRefreshing = () => formatSemanticRefreshing(s()?.semantic_index?.refreshing_count ?? 0);
  const trigramBytes = () => s()?.disk?.trigram_disk_bytes ?? 0;
  const semanticBytes = () => s()?.disk?.semantic_disk_bytes ?? 0;
  const compressionRows = () => formatCompressionSidebarRows(s()?.compression);
  const statusBar = () => s()?.status_bar;
  const degradedSummary = () => {
    const snap = s();
    if (!snap?.degraded) return null;
    const reasons = snap.degraded_reasons ?? [];
    if (reasons.length === 0) return null;
    return reasons.map(degradedReasonLabel).join("; ");
  };

  // Worktree borrow is a shared-index arrangement, not a degraded_reasons
  // entry. Keep this muted and separate from the DEGRADED badge above.
  const worktreeNote = () => worktreeCacheRoleNote(s()?.cache_role);
  return (() => {
    var _el$0 = _$createElement("box"),
      _el$1 = _$createElement("box"),
      _el$10 = _$createElement("box"),
      _el$11 = _$createElement("box"),
      _el$12 = _$createElement("text"),
      _el$13 = _$createElement("b");
    _$insertNode(_el$0, _el$1);
    _$setProp(_el$0, "width", "100%");
    _$setProp(_el$0, "flexDirection", "column");
    _$setProp(_el$0, "border", SINGLE_BORDER);
    _$setProp(_el$0, "paddingTop", 1);
    _$setProp(_el$0, "paddingBottom", 1);
    _$setProp(_el$0, "paddingLeft", 1);
    _$setProp(_el$0, "paddingRight", 1);
    _$insertNode(_el$1, _el$10);
    _$setProp(_el$1, "flexDirection", "row");
    _$setProp(_el$1, "justifyContent", "space-between");
    _$setProp(_el$1, "alignItems", "center");
    _$setProp(_el$1, "onMouseDown", () => {
      if (notInitialized()) return;
      setCollapsed(x => {
        const next = !x;
        persistCollapsedIfEnabled(prefs(), next);
        return next;
      });
    });
    _$insertNode(_el$10, _el$11);
    _$setProp(_el$10, "flexDirection", "row");
    _$setProp(_el$10, "alignItems", "center");
    _$insertNode(_el$11, _el$12);
    _$setProp(_el$11, "paddingLeft", 1);
    _$setProp(_el$11, "paddingRight", 1);
    _$insertNode(_el$12, _el$13);
    _$insert(_el$13, (() => {
      var _c$ = _$memo(() => !!notInitialized());
      return () => _c$() ? "" : collapsed() ? "▶ " : "▼ ";
    })(), null);
    _$insert(_el$13, () => prefs().header.label, null);
    _$insert(_el$10, (() => {
      var _c$2 = _$memo(() => !!s()?.degraded);
      return () => _c$2() && (() => {
        var _el$14 = _$createElement("box"),
          _el$15 = _$createElement("text"),
          _el$16 = _$createElement("b");
        _$insertNode(_el$14, _el$15);
        _$setProp(_el$14, "paddingLeft", 1);
        _$setProp(_el$14, "paddingRight", 1);
        _$setProp(_el$14, "marginLeft", 1);
        _$insertNode(_el$15, _el$16);
        _$insertNode(_el$16, _$createTextNode(`DEGRADED`));
        _$effect(_p$ => {
          var _v$8 = props.theme.warning,
            _v$9 = badgeTextColor(props.theme.warning, props.theme.background);
          _v$8 !== _p$.e && (_p$.e = _$setProp(_el$14, "backgroundColor", _v$8, _p$.e));
          _v$9 !== _p$.t && (_p$.t = _$setProp(_el$15, "fg", _v$9, _p$.t));
          return _p$;
        }, {
          e: undefined,
          t: undefined
        });
        return _el$14;
      })();
    })(), null);
    _$insert(_el$1, (() => {
      var _c$3 = _$memo(() => !!(!notInitialized() && prefs().header.showVersion));
      return () => _c$3() && (() => {
        var _el$18 = _$createElement("text"),
          _el$19 = _$createTextNode(`v`);
        _$insertNode(_el$18, _el$19);
        _$insert(_el$18, () => s()?.version ?? props.pluginVersion, null);
        _$effect(_$p => _$setProp(_el$18, "fg", props.theme.textMuted, _$p));
        return _el$18;
      })();
    })(), null);
    _$insert(_el$0, (() => {
      var _c$4 = _$memo(() => !!(s()?.degraded && degradedSummary()));
      return () => _c$4() && (() => {
        var _el$20 = _$createElement("box"),
          _el$21 = _$createElement("text"),
          _el$22 = _$createTextNode(`⚠ `);
        _$insertNode(_el$20, _el$21);
        _$setProp(_el$20, "marginTop", 1);
        _$setProp(_el$20, "width", "100%");
        _$insertNode(_el$21, _el$22);
        _$insert(_el$21, degradedSummary, null);
        _$effect(_$p => _$setProp(_el$21, "fg", props.theme.warning, _$p));
        return _el$20;
      })();
    })(), null);
    _$insert(_el$0, (() => {
      var _c$5 = _$memo(() => !!(!notInitialized() && worktreeNote()));
      return () => _c$5() && (() => {
        var _el$23 = _$createElement("box"),
          _el$24 = _$createElement("text");
        _$insertNode(_el$23, _el$24);
        _$setProp(_el$23, "marginTop", 1);
        _$setProp(_el$23, "width", "100%");
        _$insert(_el$24, worktreeNote);
        _$effect(_$p => _$setProp(_el$24, "fg", props.theme.textMuted, _$p));
        return _el$23;
      })();
    })(), null);
    _$insert(_el$0, (() => {
      var _c$6 = _$memo(() => !!notInitialized());
      return () => _c$6() && (() => {
        var _el$25 = _$createElement("box"),
          _el$26 = _$createElement("text");
        _$insertNode(_el$25, _el$26);
        _$setProp(_el$25, "marginTop", 1);
        _$setProp(_el$25, "width", "100%");
        _$insert(_el$26, () => s().message || "AFT bridge is now spawned lazily, information here will be populated after first tool call.");
        _$effect(_$p => _$setProp(_el$26, "fg", props.theme.textMuted, _$p));
        return _el$25;
      })();
    })(), null);
    _$insert(_el$0, (() => {
      var _c$7 = _$memo(() => !!(!notInitialized() && collapsed()));
      return () => _c$7() && (() => {
        var _el$27 = _$createElement("box");
        _$setProp(_el$27, "width", "100%");
        _$setProp(_el$27, "flexDirection", "column");
        _$insert(_el$27, (() => {
          var _c$9 = _$memo(() => !!prefs().sections.searchIndex);
          return () => _c$9() && _$createComponent(CollapsedRow, {
            get theme() {
              return props.theme;
            },
            label: "Search Index",
            get children() {
              var _el$28 = _$createElement("text");
              _$insertNode(_el$28, _$createTextNode(`●`));
              _$effect(_$p => _$setProp(_el$28, "fg", toneColor(props.theme, searchStatus().tone), _$p));
              return _el$28;
            }
          });
        })(), null);
        _$insert(_el$27, (() => {
          var _c$0 = _$memo(() => !!prefs().sections.semanticIndex);
          return () => _c$0() && _$createComponent(CollapsedRow, {
            get theme() {
              return props.theme;
            },
            label: "Semantic Index",
            get children() {
              var _el$30 = _$createElement("text");
              _$insertNode(_el$30, _$createTextNode(`●`));
              _$effect(_$p => _$setProp(_el$30, "fg", toneColor(props.theme, semanticStatus().tone), _$p));
              return _el$30;
            }
          });
        })(), null);
        _$insert(_el$27, (() => {
          var _c$1 = _$memo(() => !!(prefs().sections.codeHealth && collapsedHealthLights(statusBar())));
          return () => _c$1() && _$createComponent(CollapsedRow, {
            get theme() {
              return props.theme;
            },
            label: "Code Health",
            get children() {
              var _el$32 = _$createElement("box"),
                _el$33 = _$createElement("text"),
                _el$35 = _$createElement("text"),
                _el$37 = _$createElement("text");
              _$insertNode(_el$32, _el$33);
              _$insertNode(_el$32, _el$35);
              _$insertNode(_el$32, _el$37);
              _$setProp(_el$32, "flexDirection", "row");
              _$setProp(_el$32, "gap", 1);
              _$insertNode(_el$33, _$createTextNode(`●`));
              _$insertNode(_el$35, _$createTextNode(`●`));
              _$insertNode(_el$37, _$createTextNode(`●`));
              _$effect(_p$ => {
                var _v$0 = toneColor(props.theme, collapsedHealthLights(statusBar()).diagnostics),
                  _v$1 = toneColor(props.theme, collapsedHealthLights(statusBar()).code),
                  _v$10 = toneColor(props.theme, collapsedHealthLights(statusBar()).todos);
                _v$0 !== _p$.e && (_p$.e = _$setProp(_el$33, "fg", _v$0, _p$.e));
                _v$1 !== _p$.t && (_p$.t = _$setProp(_el$35, "fg", _v$1, _p$.t));
                _v$10 !== _p$.a && (_p$.a = _$setProp(_el$37, "fg", _v$10, _p$.a));
                return _p$;
              }, {
                e: undefined,
                t: undefined,
                a: undefined
              });
              return _el$32;
            }
          });
        })(), null);
        _$insert(_el$27, (() => {
          var _c$10 = _$memo(() => !!(prefs().sections.compression && collapsedCompressionValue(s()?.compression)));
          return () => _c$10() && _$createComponent(CollapsedRow, {
            get theme() {
              return props.theme;
            },
            label: "Compression",
            get children() {
              var _el$39 = _$createElement("text"),
                _el$40 = _$createElement("b");
              _$insertNode(_el$39, _el$40);
              _$insert(_el$40, () => collapsedCompressionValue(s()?.compression));
              _$effect(_$p => _$setProp(_el$39, "fg", props.theme.textMuted, _$p));
              return _el$39;
            }
          });
        })(), null);
        return _el$27;
      })();
    })(), null);
    _$insert(_el$0, (() => {
      var _c$8 = _$memo(() => !!(!notInitialized() && !collapsed()));
      return () => _c$8() && [_$memo(() => _$memo(() => !!prefs().sections.searchIndex)() && [_$createComponent(SectionHeader, {
        get theme() {
          return props.theme;
        },
        title: "Search Index"
      }), _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Status",
        get value() {
          return searchStatus().label;
        },
        get tone() {
          return searchStatus().tone;
        }
      }), _$memo(() => _$memo(() => (s()?.search_index?.files ?? null) != null)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Files",
        get value() {
          return formatCount(s().search_index.files);
        },
        tone: "muted"
      })), _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Disk",
        get value() {
          return formatBytes(trigramBytes());
        },
        tone: "muted"
      })]), _$memo(() => _$memo(() => !!prefs().sections.semanticIndex)() && [_$createComponent(SectionHeader, {
        get theme() {
          return props.theme;
        },
        title: "Semantic Index"
      }), _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Status",
        get value() {
          return semanticStatus().label;
        },
        get tone() {
          return semanticStatus().tone;
        }
      }), _$memo(() => _$memo(() => !!semanticRefreshing())() && (() => {
        var _el$41 = _$createElement("box"),
          _el$42 = _$createElement("text");
        _$insertNode(_el$41, _el$42);
        _$setProp(_el$41, "width", "100%");
        _$insert(_el$42, semanticRefreshing);
        _$effect(_$p => _$setProp(_el$42, "fg", props.theme.textMuted, _$p));
        return _el$41;
      })()), _$memo(() => _$memo(() => !!(s()?.semantic_index?.status === "loading" && s()?.semantic_index?.entries_total != null && s().semantic_index.entries_total > 0))() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Progress",
        get value() {
          return `${formatCount(s().semantic_index.entries_done)} / ${formatCount(s().semantic_index.entries_total)}`;
        },
        tone: "warn"
      })), _$memo(() => _$memo(() => (s()?.semantic_index?.entries ?? null) != null)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Entries",
        get value() {
          return formatCount(s().semantic_index.entries);
        },
        tone: "muted"
      })), _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Disk",
        get value() {
          return formatBytes(semanticBytes());
        },
        tone: "muted"
      })]), _$memo(() => _$memo(() => !!(prefs().sections.codeHealth && statusBar()))() && [_$createComponent(SectionHeader, {
        get theme() {
          return props.theme;
        },
        get title() {
          return statusBar().tier2_stale ? "Code Health ~" : "Code Health";
        }
      }), _$memo(() => _$memo(() => statusBar().errors !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Errors",
        get value() {
          return formatCount(statusBar().errors);
        },
        get tone() {
          return statusBar().errors > 0 ? "err" : "muted";
        }
      })), _$memo(() => _$memo(() => statusBar().warnings !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Warnings",
        get value() {
          return formatCount(statusBar().warnings);
        },
        get tone() {
          return statusBar().warnings > 0 ? "warn" : "muted";
        }
      })), _$memo(() => _$memo(() => statusBar().dead_code !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Dead Code",
        get value() {
          return formatCount(statusBar().dead_code);
        },
        tone: "muted"
      })), _$memo(() => _$memo(() => statusBar().unused_exports !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Unused Exports",
        get value() {
          return formatCount(statusBar().unused_exports);
        },
        tone: "muted"
      })), _$memo(() => _$memo(() => statusBar().duplicates !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "Duplicates",
        get value() {
          return formatCount(statusBar().duplicates);
        },
        tone: "muted"
      })), _$memo(() => _$memo(() => statusBar().todos !== undefined)() && _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        label: "TODOs",
        get value() {
          return formatCount(statusBar().todos);
        },
        tone: "muted"
      }))]), _$memo(() => _$memo(() => !!(prefs().sections.compression && compressionRows().length > 0))() && [_$createComponent(SectionHeader, {
        get theme() {
          return props.theme;
        },
        title: "Compression"
      }), _$memo(() => compressionRows().map(row => row.kind === "scope" ? (() => {
        var _el$43 = _$createElement("box"),
          _el$44 = _$createElement("text");
        _$insertNode(_el$43, _el$44);
        _$setProp(_el$43, "width", "100%");
        _$insert(_el$44, () => row.label);
        _$effect(_$p => _$setProp(_el$44, "fg", props.theme.text, _$p));
        return _el$43;
      })() : _$createComponent(StatRow, {
        get theme() {
          return props.theme;
        },
        get label() {
          return row.label;
        },
        get value() {
          return row.value;
        },
        tone: "muted"
      })))]), _$memo(() => _$memo(() => !!(s()?.semantic_index?.status === "failed" && s()?.semantic_index?.error))() && (() => {
        var _el$45 = _$createElement("box"),
          _el$46 = _$createElement("text"),
          _el$47 = _$createTextNode(`⚠ `);
        _$insertNode(_el$45, _el$46);
        _$setProp(_el$45, "marginTop", 1);
        _$setProp(_el$45, "width", "100%");
        _$insertNode(_el$46, _el$47);
        _$insert(_el$46, () => s().semantic_index.error, null);
        _$effect(_$p => _$setProp(_el$46, "fg", props.theme.error, _$p));
        return _el$45;
      })())];
    })(), null);
    _$effect(_p$ => {
      var _v$5 = props.theme.borderActive,
        _v$6 = props.theme.accent,
        _v$7 = badgeTextColor(props.theme.accent, props.theme.background);
      _v$5 !== _p$.e && (_p$.e = _$setProp(_el$0, "borderColor", _v$5, _p$.e));
      _v$6 !== _p$.t && (_p$.t = _$setProp(_el$11, "backgroundColor", _v$6, _p$.t));
      _v$7 !== _p$.a && (_p$.a = _$setProp(_el$12, "fg", _v$7, _p$.a));
      return _p$;
    }, {
      e: undefined,
      t: undefined,
      a: undefined
    });
    return _el$0;
  })();
};
export async function createAftSidebarSlot(api, pluginVersion) {
  const root = await readTuiPreferencesFile();
  const order = computeEffectiveOrder(root, PLUGIN_KEY, DEFAULT_SLOT_ORDER);
  return {
    // DEFAULT_SLOT_ORDER (180) is AFT's coordinated default in the shared
    // tui-preferences ladder (anthropic-auth 160, AFT 180, magic-context 200).
    // Override via `order` or `forceToTop` in tui-preferences.jsonc.
    order,
    slots: {
      sidebar_content: (ctx, value) => {
        const theme = createMemo(() => ctx.theme.current);
        return _$createComponent(SidebarContent, {
          api: api,
          sessionID: () => value.session_id,
          get theme() {
            return theme();
          },
          pluginVersion: pluginVersion
        });
      }
    }
  };
}