export const MODEL_INFO_CHANNEL = "dashboard:model-info"; export const GIT_INFO_CHANNEL = "dashboard:git-info"; export const REFRESH_CHANNEL = "dashboard:refresh"; export interface ModelInfoState { provider: string; modelId: string; modelName: string; thinking: string; contextTokens: number | null; contextWindow: number; contextPercent: number | null; cachePercent: number | null; cost: number; tokensPerSecond: number | null; generating: boolean; } export interface PullRequestInfo { number: number; url: string; isDraft: boolean; } export interface GitInfoState { isRepository: boolean; branch: string | null; changedFiles: number; pullRequest: PullRequestInfo | null; } export function emptyModelInfoState(): ModelInfoState { return { provider: "", modelId: "no-model", modelName: "No model", thinking: "off", contextTokens: null, contextWindow: 0, contextPercent: null, cachePercent: null, cost: 0, tokensPerSecond: null, generating: false, }; } export function emptyGitInfoState(): GitInfoState { return { isRepository: false, branch: null, changedFiles: 0, pullRequest: null, }; } function isRecord(value: unknown): value is Record { return typeof value === "object" && value !== null; } function isNullableNumber(value: unknown) { return value === null || typeof value === "number"; } export function isModelInfoState(value: unknown): value is ModelInfoState { if (!isRecord(value)) return false; return ( typeof value.provider === "string" && typeof value.modelId === "string" && typeof value.modelName === "string" && typeof value.thinking === "string" && isNullableNumber(value.contextTokens) && typeof value.contextWindow === "number" && isNullableNumber(value.contextPercent) && isNullableNumber(value.cachePercent) && typeof value.cost === "number" && isNullableNumber(value.tokensPerSecond) && typeof value.generating === "boolean" ); } function isPullRequestInfo(value: unknown): value is PullRequestInfo { if (!isRecord(value)) return false; return ( typeof value.number === "number" && typeof value.url === "string" && typeof value.isDraft === "boolean" ); } export function isGitInfoState(value: unknown): value is GitInfoState { if (!isRecord(value)) return false; return ( typeof value.isRepository === "boolean" && (value.branch === null || typeof value.branch === "string") && typeof value.changedFiles === "number" && (value.pullRequest === null || isPullRequestInfo(value.pullRequest)) ); }