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)}` }; }