File size: 2,650 Bytes
e8a6c67
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
<script lang="ts">
  import type { TraceNode } from '$lib/types/trace';
  import TraceRow from './TraceRow.svelte';

  interface Props { root: TraceNode; }
  let { root }: Props = $props();

  let collapsed = $state(false);

  // Walk the tree to gather leaf specialist nodes — anything that isn't
  // a structural grouping (fan / merge). This handles the TTM parent
  // node introduced for foundation-model grouping: its three TTM
  // children still count toward fired/silent/errors.
  function collectLeaves(n: TraceNode, out: TraceNode[]): void {
    if (n.status === 'fan' || n.status === 'merge') {
      for (const c of n.children ?? []) collectLeaves(c, out);
      return;
    }
    out.push(n);
    for (const c of n.children ?? []) collectLeaves(c, out);
  }
  let leafSteps = $derived.by(() => {
    const acc: TraceNode[] = [];
    for (const c of root.children ?? []) collectLeaves(c, acc);
    return acc;
  });
  let totalMs = $derived(
    root.ms > 0 ? root.ms : leafSteps.reduce((s, n) => s + (n.ms || 0), 0)
  );
  let totalSecs = $derived((totalMs / 1000).toFixed(2));
  let fired = $derived(leafSteps.filter((n) => n.status === 'ok').length);
  let silent = $derived(leafSteps.filter((n) => n.status === 'silent').length);
  let errors = $derived(leafSteps.filter((n) => n.status === 'error').length);
</script>

<section class="trace-ui" class:is-collapsed={collapsed} aria-label="Run trace">
  <header class="trace-head">
    <div class="trace-head-left">
      <span class="section-label">Run trace</span>
      <span class="trace-head-meta">
        <span class="trace-head-stat">{totalSecs}s total</span>
        <span class="trace-head-sep">·</span>
        <span class="trace-head-stat">{fired} fired</span>
        <span class="trace-head-sep">·</span>
        <span class="trace-head-stat trace-head-silent">{silent} silent</span>
        <span class="trace-head-sep">·</span>
        <span class="trace-head-stat">{errors} errors</span>
      </span>
    </div>
    <button
      type="button"
      class="trace-collapse-btn"
      onclick={() => (collapsed = !collapsed)}
      aria-expanded={!collapsed}
    >
      {collapsed ? 'Expand ▾' : 'Collapse ▴'}
    </button>
  </header>
  {#if !collapsed}
    <div class="trace-body">
      <div class="trace-col-heads">
        <span></span><span></span>
        <span class="trace-col-head">action</span>
        <span class="trace-col-head">elapsed</span>
        <span class="trace-col-head">tier</span>
      </div>
      <div class="trace-tree" role="tree">
        <TraceRow node={root} defaultOpen={true} />
      </div>
    </div>
  {/if}
</section>