Files
letta-code/src/cli/helpers/subagentDisplay.ts
2026-03-10 18:36:37 -07:00

80 lines
2.4 KiB
TypeScript

/**
* Shared utilities for subagent display components
*
* Used by both SubagentGroupDisplay (live) and SubagentGroupStatic (frozen).
*/
import { getModelShortName, resolveModel } from "../../agent/model";
import { OPENAI_CODEX_PROVIDER_NAME } from "../../providers/openai-codex-provider";
import { formatCompact } from "./format";
/**
* Format tool count and token statistics for display
*
* @param toolCount - Number of tool calls
* @param totalTokens - Total tokens used (0 or undefined means no data available)
* @param isRunning - If true, shows "—" for tokens (since usage is only available at end)
*/
export function formatStats(
toolCount: number,
totalTokens: number,
isRunning = false,
): string {
const toolStr = `${toolCount} tool use${toolCount !== 1 ? "s" : ""}`;
// Only show token count if we have actual data (not running and totalTokens > 0)
const hasTokenData = !isRunning && totalTokens > 0;
if (!hasTokenData) {
return toolStr;
}
return `${toolStr} · ${formatCompact(totalTokens)} tokens`;
}
/**
* Get tree-drawing characters for hierarchical display
*
* @param isLast - Whether this is the last item in the list
* @returns Object with treeChar (branch connector) and continueChar (continuation line)
*/
export function getTreeChars(isLast: boolean): {
treeChar: string;
continueChar: string;
} {
return {
treeChar: isLast ? "└─" : "├─",
continueChar: isLast ? " " : "│ ",
};
}
export interface SubagentModelDisplay {
label: string;
isByokProvider: boolean;
isOpenAICodexProvider: boolean;
}
/**
* Format a subagent model identifier using the same logic as the input footer:
* short label (if known) + provider-based BYOK marker eligibility.
*/
export function getSubagentModelDisplay(
model: string | undefined,
): SubagentModelDisplay | null {
if (!model) return null;
// Normalize model IDs (e.g. "haiku") to handles before formatting.
const normalized = resolveModel(model) ?? model;
const slashIndex = normalized.indexOf("/");
const provider =
slashIndex >= 0 ? normalized.slice(0, slashIndex) : normalized;
const isOpenAICodexProvider = provider === OPENAI_CODEX_PROVIDER_NAME;
const isByokProvider = provider.startsWith("lc-") || isOpenAICodexProvider;
const label =
getModelShortName(normalized) ?? normalized.split("/").pop() ?? normalized;
return {
label,
isByokProvider,
isOpenAICodexProvider,
};
}