trusty-memory 0.1.60

MCP server (stdio + HTTP/SSE) for trusty-memory
Documentation
<script>
  /*
   * Why: The dream cycle is trusty-memory's background memory-maintenance
   * pass (merge near-duplicates, prune stale drawers, compact closets).
   * Operators want to trigger it on demand after a bulk ingest and see the
   * resulting counts.
   * What: A "Trigger Dream Cycle" button → `POST /api/v1/dream/run`, the
   * latest persisted aggregate from `GET /api/v1/dream/status`, and a
   * session-local history table of runs triggered from this browser tab.
   * Test: open #/dream, click Trigger, confirm a result row appears with
   * merged / pruned / compacted counts.
   */
  import { onMount } from 'svelte';
  import { api } from '../api.js';

  let lastStatus = $state(null);
  let statusError = $state(null);
  let running = $state(false);
  let runError = $state(null);
  // Session-local history: each entry is { at, merged, pruned, compacted,
  // closets_updated, duration_ms }. The daemon does not expose a run-history
  // endpoint, so this records runs triggered from this tab.
  let history = $state([]);

  onMount(loadStatus);

  async function loadStatus() {
    try {
      lastStatus = await api.dreamStatus();
      statusError = null;
    } catch (e) {
      statusError = e.message || String(e);
    }
  }

  /**
   * Why: a dream cycle can take noticeable time on large palaces; we disable
   * the button and surface the aggregate result when it returns.
   * What: POSTs `/api/v1/dream/run`, prepends the result to the session
   * history, and refreshes the persisted status snapshot.
   * Test: click Trigger, confirm the history table gains a row.
   */
  async function triggerDream() {
    running = true;
    runError = null;
    try {
      const stats = await api.dreamRun();
      history = [
        {
          at: new Date(),
          merged: stats.merged ?? 0,
          pruned: stats.pruned ?? 0,
          compacted: stats.compacted ?? 0,
          closets_updated: stats.closets_updated ?? 0,
          duration_ms: stats.duration_ms ?? 0
        },
        ...history
      ];
      lastStatus = stats;
    } catch (e) {
      runError = e.message || String(e);
    } finally {
      running = false;
    }
  }

  /**
   * Why: ISO timestamps are precise but not glanceable.
   * What: localised date-time, or "never" when null.
   * Test: humanTime(null) === "never".
   */
  function humanTime(value) {
    if (!value) return 'never';
    const d = value instanceof Date ? value : new Date(value);
    if (Number.isNaN(d.getTime())) return String(value);
    return d.toLocaleString();
  }
</script>

<h1 class="page-title">Dream</h1>

<div class="card mb-4">
  <div class="card-body dream-action">
    <div>
      <div class="text-sm text-secondary">
        Run a dream cycle across every palace — merges near-duplicate drawers,
        prunes stale memories, and compacts closets.
      </div>
      <div class="text-xs text-muted mt-3">
        Endpoint: <code>POST /api/v1/dream/run</code>
      </div>
    </div>
    <button class="btn btn-primary" onclick={triggerDream} disabled={running}>
      {running ? 'Dreaming…' : 'Trigger Dream Cycle'}
    </button>
  </div>
  {#if runError}
    <div class="dream-error">{runError}</div>
  {/if}
</div>

<div class="stat-grid">
  <div class="stat">
    <div class="stat-label">Merged</div>
    <div class="stat-value">{(lastStatus?.merged ?? 0).toLocaleString()}</div>
    <div class="stat-meta">duplicate drawers</div>
  </div>
  <div class="stat">
    <div class="stat-label">Pruned</div>
    <div class="stat-value">{(lastStatus?.pruned ?? 0).toLocaleString()}</div>
    <div class="stat-meta">stale drawers</div>
  </div>
  <div class="stat">
    <div class="stat-label">Compacted</div>
    <div class="stat-value">{(lastStatus?.compacted ?? 0).toLocaleString()}</div>
    <div class="stat-meta">closets</div>
  </div>
  <div class="stat">
    <div class="stat-label">Last run</div>
    <div class="stat-value" style="font-size: var(--trusty-fs-md)">
      {humanTime(lastStatus?.last_run_at)}
    </div>
    <div class="stat-meta">persisted aggregate</div>
  </div>
</div>

<div class="card">
  <div class="card-header">Run history (this session)</div>
  <div class="card-body" style="padding: 0">
    {#if statusError}
      <div class="dream-error">{statusError}</div>
    {/if}
    {#if history.length === 0}
      <div class="empty">
        No dream cycles triggered from this tab yet. The daemon does not expose
        a persisted run-history endpoint — runs you trigger here are listed
        below.
      </div>
    {:else}
      <table class="table">
        <thead>
          <tr>
            <th>Triggered at</th>
            <th>Merged</th>
            <th>Pruned</th>
            <th>Compacted</th>
            <th>Closets</th>
            <th>Duration</th>
          </tr>
        </thead>
        <tbody>
          {#each history as run, i (i)}
            <tr>
              <td class="text-sm">{humanTime(run.at)}</td>
              <td>{run.merged.toLocaleString()}</td>
              <td>{run.pruned.toLocaleString()}</td>
              <td>{run.compacted.toLocaleString()}</td>
              <td>{run.closets_updated.toLocaleString()}</td>
              <td>{run.duration_ms.toLocaleString()} ms</td>
            </tr>
          {/each}
        </tbody>
      </table>
    {/if}
  </div>
</div>

<style>
  .page-title {
    font-size: var(--trusty-fs-xl);
    margin: 0 0 var(--trusty-space-5) 0;
    font-weight: 600;
  }
  .dream-action {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: var(--trusty-space-4);
    flex-wrap: wrap;
  }
  .text-secondary {
    color: var(--trusty-text-secondary);
  }
  .dream-error {
    padding: var(--trusty-space-3) var(--trusty-space-5);
    color: var(--trusty-danger);
    background: var(--trusty-danger-soft);
    font-size: var(--trusty-fs-sm);
  }
</style>