capsule-ai-cli
Version:
The AI Model Orchestrator - Intelligent multi-model workflows with device-locked licensing
73 lines • 2.77 kB
JavaScript
import chalk from 'chalk';
import path from 'path';
import os from 'os';
export class StatusBar {
info;
constructor(info = {}) {
this.info = {
currentDir: process.cwd(),
model: 'gpt-4o',
provider: 'openai',
contextUsage: 0,
maxContext: 4096,
sandboxMode: false,
...info
};
}
render() {
const terminalWidth = process.stdout.columns || 80;
const dirDisplay = this.truncatePath(this.info.currentDir, 30);
const leftSection = chalk.cyan(dirDisplay);
const centerSection = this.info.sandboxMode
? chalk.red(' no sandbox ')
: '';
const contextPercent = Math.round((this.info.contextUsage / this.info.maxContext) * 100);
const contextColor = contextPercent > 80 ? 'red' : contextPercent > 60 ? 'yellow' : 'green';
const rightSection = chalk.gray('(') +
chalk.blue(this.info.model) +
chalk.gray(' | ') +
chalk[contextColor](`${contextPercent}% context`) +
chalk.gray(')');
const leftLength = this.stripAnsi(leftSection).length;
const centerLength = this.stripAnsi(centerSection).length;
const rightLength = this.stripAnsi(rightSection).length;
const totalContentLength = leftLength + centerLength + rightLength;
const padding = Math.max(0, terminalWidth - totalContentLength - 2);
const paddingLeft = Math.floor(padding / 2);
const paddingRight = Math.ceil(padding / 2);
return (leftSection +
' '.repeat(paddingLeft) +
centerSection +
' '.repeat(paddingRight) +
rightSection);
}
update(updates) {
this.info = { ...this.info, ...updates };
this.redraw();
}
redraw() {
process.stdout.write('\x1B[s');
process.stdout.write(`\x1B[${process.stdout.rows};1H`);
process.stdout.write('\x1B[K');
process.stdout.write(this.render());
process.stdout.write('\x1B[u');
}
truncatePath(fullPath, maxLength) {
if (fullPath.length <= maxLength)
return fullPath;
const homedir = os.homedir();
let displayPath = fullPath.replace(homedir, '~');
if (displayPath.length <= maxLength)
return displayPath;
const parts = displayPath.split(path.sep);
if (parts.length > 3) {
return `${parts[0]}${path.sep}...${path.sep}${parts[parts.length - 1]}`;
}
return `...${displayPath.slice(-(maxLength - 3))}`;
}
stripAnsi(str) {
return str.replace(/\x1B\[[0-9;]*m/g, '');
}
}
export const statusBar = new StatusBar();
//# sourceMappingURL=statusBar.js.map