57 lines
1.7 KiB
TypeScript
57 lines
1.7 KiB
TypeScript
/**
|
||
* Format a byte count into a human-readable string.
|
||
*
|
||
* @example formatBytes(1536) // '1.5 KB'
|
||
* @example formatBytes(0) // '0 B'
|
||
*/
|
||
export function formatBytes(bytes: number): string {
|
||
if (bytes <= 0) return '0 B';
|
||
const k = 1024;
|
||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB'];
|
||
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
||
return `${parseFloat((bytes / Math.pow(k, i)).toFixed(1))} ${sizes[i]}`;
|
||
}
|
||
|
||
/**
|
||
* Approximate token count for a text string.
|
||
*
|
||
* Uses a word-count × 1.3 heuristic (typical for English text with LLM tokenizers).
|
||
*/
|
||
export function estimateTokens(text: string): number {
|
||
const trimmed = text.trim();
|
||
if (!trimmed) return 0;
|
||
return Math.ceil(trimmed.split(/\s+/).length * 1.3);
|
||
}
|
||
|
||
/**
|
||
* Best-effort model context window lookup based on model name.
|
||
*
|
||
* Checks for common context window markers in the model name string.
|
||
* Falls back to 4096 if no marker is found.
|
||
*/
|
||
export function getModelContextWindow(modelName: string): number {
|
||
const n = modelName.toLowerCase();
|
||
if (n.includes('128k')) return 128_000;
|
||
if (n.includes('64k')) return 64_000;
|
||
if (n.includes('32k')) return 32_000;
|
||
if (n.includes('16k')) return 16_000;
|
||
if (n.includes('8k')) return 8_000;
|
||
return 4_096;
|
||
}
|
||
|
||
/**
|
||
* Format a duration in seconds to a human-readable uptime string.
|
||
*
|
||
* @example formatUptime(90061) // '1d 1h 1m'
|
||
* @example formatUptime(3661) // '1h 1m'
|
||
* @example formatUptime(120) // '2m'
|
||
*/
|
||
export function formatUptime(seconds: number): string {
|
||
const d = Math.floor(seconds / 86400);
|
||
const h = Math.floor((seconds % 86400) / 3600);
|
||
const m = Math.floor((seconds % 3600) / 60);
|
||
if (d > 0) return `${d}d ${h}h ${m}m`;
|
||
if (h > 0) return `${h}h ${m}m`;
|
||
return `${m}m`;
|
||
}
|