feat: add shared runtime and PI datasource handlers
This commit is contained in:
@@ -0,0 +1,45 @@
|
|||||||
|
import streamDeck from "@elgato/streamdeck";
|
||||||
|
import { fetchMetrics, fetchModels } from "./llamaswap";
|
||||||
|
import { gpuInfos, parseGpuMetrics } from "./metrics-parser";
|
||||||
|
import { cfgFromSettings, type CfgSettings } from "./util";
|
||||||
|
|
||||||
|
interface DataSourceItem {
|
||||||
|
label: string;
|
||||||
|
value: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function registerDataSources(): void {
|
||||||
|
streamDeck.ui.onSendToPlugin(async (ev) => {
|
||||||
|
const request = ev.payload as { event?: string } | undefined;
|
||||||
|
const event = request?.event;
|
||||||
|
if (!event) return;
|
||||||
|
const settings = await ev.action.getSettings<CfgSettings>();
|
||||||
|
|
||||||
|
if (event === "models") {
|
||||||
|
let items: DataSourceItem[] = [];
|
||||||
|
try {
|
||||||
|
const models = await fetchModels(cfgFromSettings(settings));
|
||||||
|
items = models.map((m) => ({ label: `${m.id} (${m.status})`, value: m.id }));
|
||||||
|
} catch {
|
||||||
|
items = [];
|
||||||
|
}
|
||||||
|
await streamDeck.ui.sendToPropertyInspector({ event, items });
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event === "gpus") {
|
||||||
|
let items: DataSourceItem[] = [];
|
||||||
|
try {
|
||||||
|
const text = await fetchMetrics(cfgFromSettings(settings));
|
||||||
|
const gpus = gpuInfos(parseGpuMetrics(text));
|
||||||
|
items = [
|
||||||
|
{ label: "All GPUs", value: "all" },
|
||||||
|
...gpus.map((g) => ({ label: `GPU ${g.id} · ${g.name}`, value: g.id })),
|
||||||
|
];
|
||||||
|
} catch {
|
||||||
|
items = [{ label: "All GPUs", value: "all" }];
|
||||||
|
}
|
||||||
|
await streamDeck.ui.sendToPropertyInspector({ event, items });
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -0,0 +1,48 @@
|
|||||||
|
import { EventFeed } from "./event-feed";
|
||||||
|
import { InflightTracker } from "./inflight-tracker";
|
||||||
|
import { MetricsPoller } from "./metrics-poller";
|
||||||
|
import { type LlamaSwapConfig } from "./util";
|
||||||
|
|
||||||
|
class Runtime {
|
||||||
|
readonly tracker = new InflightTracker();
|
||||||
|
offline = true;
|
||||||
|
private feed?: EventFeed;
|
||||||
|
private poller?: MetricsPoller;
|
||||||
|
private listeners = new Set<() => void>();
|
||||||
|
|
||||||
|
ensureConnections(cfg: LlamaSwapConfig): void {
|
||||||
|
if (!this.feed) {
|
||||||
|
this.feed = new EventFeed(cfg, (ev) => {
|
||||||
|
this.tracker.apply(ev);
|
||||||
|
this.emit();
|
||||||
|
});
|
||||||
|
this.feed.setStatusHandler((connected) => {
|
||||||
|
this.offline = !connected;
|
||||||
|
this.emit();
|
||||||
|
});
|
||||||
|
this.feed.start();
|
||||||
|
}
|
||||||
|
if (!this.poller) {
|
||||||
|
this.poller = new MetricsPoller(cfg);
|
||||||
|
this.poller.on(() => this.emit());
|
||||||
|
this.poller.start();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
get pollerInstance(): MetricsPoller | undefined {
|
||||||
|
return this.poller;
|
||||||
|
}
|
||||||
|
|
||||||
|
subscribe(listener: () => void): () => void {
|
||||||
|
this.listeners.add(listener);
|
||||||
|
return () => {
|
||||||
|
this.listeners.delete(listener);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private emit(): void {
|
||||||
|
for (const listener of this.listeners) listener();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export const runtime = new Runtime();
|
||||||
Reference in New Issue
Block a user