omp-throughput

内容来源:README.md(说明文档) · 原始地址 · 查看安装指南

原始内容

omp-throughput

A live throughput (tokens-per-second) meter for omp. It renders a small, permanent panel above the editor that shows how fast your model is streaming, a session-level TPS history, and one row per running task subagent.

  • Zero configuration. Drop it in and it runs.
  • Zero disk I/O. All state lives in process memory and is discarded when the process exits.
  • O(1) stats. Mean and p95 are maintained incrementally (a P² streaming sketch), not recomputed per frame.
  • Task-subagent aware. One row per in-flight worker, tagged with its agent type (scout / task / designer / reviewer / librarian / sonic).

Works on vanilla pi too. The extension is written against the vanilla pi extension API, so in pi the main-agent throughput (gauge, sparkline, μ, p95) works fully. The task-subagent rows and agent badges are omp-specific (the task tool and agent roster are not in vanilla pi), so they simply do not appear there — nothing breaks.


What it looks like

The panel has one header line (the session summary) and one row per active participant.

Idle — a fresh session, nothing streamed yet:

omp-throughput idle

Main agent streaming — the header carries live aggregates and the main row shows a live gauge:

omp-throughput main streaming

Task subagents running — once the main agent has completed at least one response the header carries the session fingerprint (sparkline of the last 12 completed responses + mean μ + p95), and each worker gets a row with its agent-type badge and live gauge:

omp-throughput subagents running

On vanilla pi — main-agent panel only (no subagent rows or badges):

omp-throughput on vanilla pi

Row anatomy

 ⠴ IndexPools     task      zai/glm-5.2:max   ▕█████████▏ 42 tps · 780 tok
 ↑ ↑              ↑         ↑                 ↑            ↑
 │ │              │         │                 │            └─ tokens for this message/session
 │ │              │         │                 └─ live TPS gauge (fills relative to the fastest row)
 │ │              │         └─ model + thinking level
 │ │              └─ agent-type badge (scout / task / design / review / libr / sonic)
 │ └─ worker name (the task name)
 └─ phase icon: ⠴ streaming · ◇ in a tool · ✓ done · · waiting

Header anatomy

 Throughput ··········█▁ 75 tps · μ 77 · p95 80 · 3 active · 2 streaming · 90 tps total · 1.7k tok
           ↑                      ↑    ↑    ↑    ↑           ↑              ↑              ↑
           sparkline (last 12)    last  mean p95  active count streaming cnt  sum of live TPS  sum of tokens

The sparkline / μ / p95 group appears only once the main agent has completed at least one response.


Install

omp (recommended):

omp install omp-throughput

Restart omp (or run /reload) and confirm:

omp plugin list      # → omp-throughput, enabled
omp plugin doctor    # → plugin:omp-throughput  ok

Vanilla pi:

pi install npm:omp-throughput

Confirm with pi list. The extension requires @earendil-works/pi-coding-agent >= 3.0.0 as an optional peer dependency (both omp and pi already provide it).

From source / dev:

git clone git@github.com:kajeagentspi/omp-throughput.git
omp plugin link ./omp-throughput     # omp — live symlink for development
pi install ./omp-throughput          # vanilla pi

How it works

  • In-memory registry. All sessions (main + workers) register in a single Map stored on globalThis[Symbol.for("omp.throughput.registry.v1")]. Because task subagents run in-process with the main, they share this registry. Nothing is written to disk.
  • Main stats are incremental. Each completed main response records its TPS into:
    • a 12-sample ring (the sparkline),
    • a running sum + count (the mean μ),
    • a P² streaming quantile sketch (the p95). Stats update once per completed message — never per render frame — so the 200 ms UI tick is O(1).
  • Agent badges are read from the task tool's own input: a tool_call listener reads input.tasks[].name + input.tasks[].agent and maps each worker name to its agent type.
  • Pruning. Completed workers stay visible for 3 s, then drop off; stale workers (>10 min) are removed.

Why a P² sketch for p95?

An exact p95 needs the full sorted history. The P² algorithm (Jain & Chlamtac, 1985) estimates a quantile from a stream in O(1) time and constant memory using five markers. This implementation bootstraps from the first 64 samples (exact p95 over the buffer) and then streams, giving:

  • N ≤ 64: exact (0% error),
  • N ≥ 100: typically < 5%,
  • N ≥ 1000: typically < 1.5%.

Files

omp-throughput/
├── extensions/
│   └── throughput.ts     # the extension (single file, ~700 lines)
├── docs/
│   ├── img/              # README screenshots
│   └── render_shots.py   # regenerates the screenshots
├── LICENSE
├── package.json
└── README.md

No build step is required — omp loads the TypeScript extension directly via Bun.

Notes

  • The panel renders every 200 ms while anything is active. When fully idle it still shows the header line (with the session sparkline once there is history).
  • If you ever see the same row twice or a doubled total, restart the window — an [omp-tp-anomaly] line will appear in the omp debug log with the registry contents.