feat: add usage-stats display mode to In-Flight Monitor action

This commit is contained in:
c4ch3c4d3
2026-08-14 12:56:45 -06:00
parent 4c4ec0e8fd
commit e585992087
4 changed files with 68 additions and 8 deletions
@@ -11,6 +11,20 @@
<sdpi-item label="API Key">
<sdpi-password setting="apiKey" placeholder="Optional" />
</sdpi-item>
<sdpi-item label="Display">
<sdpi-select setting="display" default="count" placeholder="Select a display mode">
<option value="count">Request count + activity</option>
<option value="usage">Usage stats</option>
</sdpi-select>
</sdpi-item>
<sdpi-item label="Primary stat (usage view)">
<sdpi-select setting="primaryStat" default="requests" placeholder="Select a primary stat">
<option value="requests">Requests</option>
<option value="input_tokens">Processed tokens</option>
<option value="output_tokens">Generated tokens</option>
<option value="gen_p95">Generation speed P95</option>
</sdpi-select>
</sdpi-item>
<sdpi-item label="Model">
<sdpi-select setting="modelId" datasource="models" loading="Loading models…" hot-reload placeholder="Select a model" />
</sdpi-item>
+51 -5
View File
@@ -7,18 +7,21 @@ import streamDeck, {
type WillAppearEvent,
type WillDisappearEvent,
} from "@elgato/streamdeck";
import { renderInflight, svgDataUrl } from "../lib/render";
import { renderInflight, renderUsage, svgDataUrl } from "../lib/render";
import { runtime } from "../lib/runtime";
import { cfgFromSettings, type CfgSettings } from "../lib/util";
type InflightSettings = CfgSettings & {
modelId?: string;
display?: "count" | "usage";
primaryStat?: "requests" | "input_tokens" | "output_tokens" | "gen_p95";
};
type InflightState = {
settings: InflightSettings;
action?: KeyAction<InflightSettings>;
unsubscribe?: () => void;
unwatchStats?: () => void;
history: number[];
sampler?: ReturnType<typeof setInterval>;
};
@@ -45,7 +48,11 @@ export class InflightMonitor extends SingletonAction<InflightSettings> {
state.action = ev.action;
runtime.ensureConnections(cfgFromSettings(state.settings));
state.unsubscribe = runtime.subscribe(() => this.render(state));
if (this.displayOf(state) === "usage") {
state.unwatchStats = runtime.watchStats(this.modelKeyOf(state));
} else {
state.sampler = setInterval(() => this.sample(state), 1000);
}
this.render(state);
}
@@ -53,6 +60,8 @@ export class InflightMonitor extends SingletonAction<InflightSettings> {
const state = this.states.get(ev.action.id);
if (!state) return;
state.unsubscribe?.();
state.unwatchStats?.();
state.unwatchStats = undefined;
if (state.sampler) clearInterval(state.sampler);
state.sampler = undefined;
this.states.delete(ev.action.id);
@@ -65,6 +74,13 @@ export class InflightMonitor extends SingletonAction<InflightSettings> {
state.action = ev.action;
state.history = [];
runtime.ensureConnections(cfgFromSettings(state.settings));
state.unwatchStats?.();
state.unwatchStats = undefined;
if (this.displayOf(state) === "usage") {
state.unwatchStats = runtime.watchStats(this.modelKeyOf(state));
} else if (!state.sampler) {
state.sampler = setInterval(() => this.sample(state), 1000);
}
this.render(state);
}
@@ -72,17 +88,47 @@ export class InflightMonitor extends SingletonAction<InflightSettings> {
void streamDeck.system.openUrl(`${cfgFromSettings(ev.payload.settings).baseUrl}/ui`);
}
private displayOf(state: InflightState): "count" | "usage" {
return state.settings.display ?? "count";
}
private modelKeyOf(state: InflightState): string {
const modelId = state.settings.modelId ?? "";
return modelId === "" ? "all" : modelId;
}
private primaryStatOf(state: InflightState): "requests" | "input_tokens" | "output_tokens" | "gen_p95" {
return state.settings.primaryStat ?? "requests";
}
private render(state: InflightState): void {
const action = state.action;
if (!action) return;
if (this.displayOf(state) === "usage") {
const modelKey = this.modelKeyOf(state);
const offline = runtime.offline;
void action.setImage(
svgDataUrl(
renderUsage({
modelName: modelKey,
stats: runtime.getStats(modelKey),
primaryStat: this.primaryStatOf(state),
offline,
}),
),
);
return;
}
const modelId = state.settings.modelId ?? "";
const trackerState = runtime.tracker.state(modelId);
const count = runtime.tracker.count(modelId);
const trackerState = modelId === "all" ? "ready" : runtime.tracker.state(modelId);
const count = modelId === "all" ? runtime.tracker.total() : runtime.tracker.count(modelId);
const offline = runtime.offline && modelId.length > 0;
const modelName = modelId === "" ? "unset" : modelId;
void action.setImage(
svgDataUrl(
renderInflight({
modelName: modelId.length > 0 ? modelId : "unset",
modelName,
state: trackerState,
count,
offline,
@@ -94,7 +140,7 @@ export class InflightMonitor extends SingletonAction<InflightSettings> {
private sample(state: InflightState): void {
const modelId = state.settings.modelId ?? "";
state.history.push(runtime.tracker.count(modelId));
state.history.push(modelId === "all" ? runtime.tracker.total() : runtime.tracker.count(modelId));
if (state.history.length > HISTORY_LIMIT) state.history.shift();
this.render(state);
}
+1 -1
View File
@@ -17,7 +17,7 @@ export function registerDataSources(): void {
let items: DataSourceItem[] = [];
try {
const models = await fetchModels(cfgFromSettings(settings));
items = models.map((m) => ({ label: `${m.id} (${m.status})`, value: m.id }));
items = [{ label: "All models", value: "all" }, ...models.map((m) => ({ label: `${m.id} (${m.status})`, value: m.id }))];
} catch {
items = [];
}
+1 -1
View File
@@ -24,7 +24,7 @@ export interface InflightRenderOptions {
}
export function renderInflight(opts: InflightRenderOptions): string {
const name = escapeXml(shorten(opts.modelName));
const name = escapeXml(shorten(opts.modelName === "all" ? "ALL MODELS" : opts.modelName));
if (opts.offline) {
return frame("#10131a", [