wsb-daemon 0.275.7622

wsb's daemon: the workbench, the GitHub mirror's schedule and peer continuity, for every workspace on the machine
<script lang="ts">
  import { applyHighlight, escapeHTML } from "../../utils/highlight.js";

  interface Props {
    content: string;
    highlightQuery?: string;
    isCurrentHighlight?: boolean;
  }

  let { content, highlightQuery = "", isCurrentHighlight = false }: Props = $props();
  let userCollapsed: boolean = $state(true);
  let userOverride: boolean = $state(false);
  let searchExpanded: boolean = $state(false);
  let prevQuery: string = "";

  // Auto-expand when a search match exists in this block.
  // Only reset the user override when the query itself changes,
  // not when content updates (e.g. during streaming).
  $effect(() => {
    const q = highlightQuery;
    const hasMatch =
      q.trim() !== "" &&
      content.toLowerCase().includes(q.toLowerCase());
    searchExpanded = hasMatch;
    if (q !== prevQuery) {
      userOverride = false;
      prevQuery = q;
    }
  });

  let collapsed = $derived(
    userOverride ? userCollapsed
      : searchExpanded ? false
      : userCollapsed,
  );
</script>

<div class="thinking-block">
  <button
    class="thinking-header"
    onclick={() => { userCollapsed = !userCollapsed; userOverride = true; }}
  >
    <span class="thinking-chevron" class:open={!collapsed}>
      &#9656;
    </span>
    <span class="thinking-label">Thinking</span>
  </button>
  {#if !collapsed}
    <div
      class="thinking-content"
      use:applyHighlight={{ q: highlightQuery, current: isCurrentHighlight, content }}
    >{@html escapeHTML(content)}</div>
  {/if}
</div>

<style>
  .thinking-block {
    border-left: 2px solid var(--vscode-textPreformat-foreground);
    background: var(--wb-thinking-bg);
    border-radius: 0 var(--wsb-radius-sm) var(--wsb-radius-sm) 0;
    margin: 0;
  }

  .thinking-header {
    display: flex;
    align-items: center;
    gap: var(--wb-spacing-6);
    padding: var(--wb-spacing-6) var(--wb-spacing-10);
    width: 100%;
    text-align: left;
    font-size: var(--wb-font-size-12);
    font-weight: 600;
    color: var(--vscode-textPreformat-foreground);
    letter-spacing: 0.01em;
    border-radius: 0 var(--wsb-radius-sm) var(--wsb-radius-sm) 0;
    transition: background 0.1s;
  }

  .thinking-header:hover {
    background: var(--vscode-list-hoverBackground);
  }

  .thinking-chevron {
    display: inline-block;
    font-size: var(--wb-font-size-10);
    transition: transform 0.15s;
    color: var(--vscode-disabledForeground);
  }

  .thinking-chevron.open {
    transform: rotate(90deg);
  }

  .thinking-content {
    padding: var(--wb-spacing-8) var(--wb-spacing-14) var(--wb-spacing-12);
    font-size: var(--wb-font-size-13);
    font-style: italic;
    color: var(--vscode-foreground);
    white-space: pre-wrap;
    word-wrap: break-word;
    line-height: 1.65;
    border-top: 1px solid var(--vscode-widget-border);
  }
</style>