Files
pi-statusline/modules/basic.ts

107 lines
3.6 KiB
TypeScript

import { homedir } from "node:os";
import type { ModuleContext, RenderedModule } from "../types";
function formatTokens(count: number): string {
if (count < 1000) return count.toString();
if (count < 10000) return `${(count / 1000).toFixed(1)}k`;
if (count < 1000000) return `${Math.round(count / 1000)}k`;
if (count < 10000000) return `${(count / 1000000).toFixed(1)}M`;
return `${Math.round(count / 1000000)}M`;
}
function sessionEntries(ctx: any): any[] {
try {
return ctx.sessionManager?.getEntries?.() ?? [];
} catch {
return [];
}
}
function totalCost(ctx: any): number {
return sessionEntries(ctx).reduce((total, entry) => {
const cost =
entry?.type === "message" && entry.message?.role === "assistant"
? entry.message.usage?.cost?.total
: undefined;
return (
total + (typeof cost === "number" && Number.isFinite(cost) ? cost : 0)
);
}, 0);
}
function isUsingSubscription(ctx: any): boolean {
const provider = ctx.model?.provider;
if (!provider) return false;
try {
return Boolean(ctx.modelRegistry?.isUsingOAuth?.(ctx.model));
} catch {
return provider === "anthropic" || provider === "openai-codex";
}
}
export function directoryModule(moduleCtx: ModuleContext): RenderedModule {
const cwd = moduleCtx.ctx.sessionManager?.getCwd?.() ?? process.cwd();
const home = homedir();
let text = home && cwd.startsWith(home) ? `~${cwd.slice(home.length)}` : cwd;
// Git And Session Name
const options = moduleCtx.config.modules.directory;
if (options?.showGitBranch) {
const branch = moduleCtx.footerData?.getGitBranch?.();
if (branch) text = `${text} (${branch})`;
}
if (options?.showSessionName) {
const sessionName = moduleCtx.ctx.sessionManager?.getSessionName?.();
if (sessionName) text = `${text}${sessionName}`;
}
return { text };
}
export function contextModule(moduleCtx: ModuleContext): RenderedModule {
const usage = moduleCtx.ctx.getContextUsage?.();
const contextWindow =
usage?.contextWindow ?? moduleCtx.ctx.model?.contextWindow ?? 0;
const percent = usage?.percent;
const showWindow = moduleCtx.config.modules.context?.showWindow ?? false;
const value =
percent === null || percent === undefined
? "?"
: `${Number(percent).toFixed(1)}%`;
return {
text: showWindow ? `${value} / ${formatTokens(contextWindow)}` : `${value}`,
};
}
export function modelModule(moduleCtx: ModuleContext): RenderedModule {
const model = moduleCtx.ctx.model;
if (!model) return { text: "no-model" };
// Model Label
const options = moduleCtx.config.modules.model;
const provider = options?.showProvider ? `(${model.provider}) ` : "";
let text = `${provider}${model.id}`;
if (options?.showThinking && model.reasoning) {
const thinking = moduleCtx.state.thinkingLevel ?? "off";
text = thinking === "off" ? `${text} thinking off` : `${text} ${thinking}`;
}
return { text };
}
export function thinkingModule(moduleCtx: ModuleContext): RenderedModule {
if (!moduleCtx.ctx.model?.reasoning) return { text: "" };
const level = moduleCtx.state.thinkingLevel ?? "off";
if (level === "off" && moduleCtx.config.modules.thinking?.hideWhenOff)
return { text: "" };
return { text: `think ${level}` };
}
export function costModule(moduleCtx: ModuleContext): RenderedModule {
const cost = totalCost(moduleCtx.ctx);
const subscription = isUsingSubscription(moduleCtx.ctx);
if (!cost && !subscription) return { text: "" };
if (subscription && moduleCtx.config.modules.cost?.showSubscription !== false)
return { text: cost ? `$${cost.toFixed(3)} sub` : "sub" };
return { text: `$${cost.toFixed(3)}` };
}