aiwg
Version:
Deployment tool and support utility for AI context. Copies agents, skills, commands, rules, and behaviors into the paths each AI platform reads (Claude Code, Codex, Copilot, Cursor, Warp, OpenClaw, and 6 more) so one source of truth works across 10 platfo
224 lines • 6.73 kB
JavaScript
/**
* Shared CLI Display Utility Module
*
* Provides consistent, professional terminal output across all CLI commands.
* Wraps chalk, ora, and cli-table3 with TTY/CI-aware fallbacks.
*
* @issue #461
*/
import chalk from 'chalk';
// Environment detection
const isTTY = Boolean(process.stdout.isTTY);
const isCI = Boolean(process.env.CI ||
process.env.GITHUB_ACTIONS ||
process.env.GITLAB_CI ||
process.env.CIRCLECI ||
process.env.JENKINS_URL ||
process.env.GITEA_ACTIONS);
// Brand palette
const BRAND_HEX = '#818CF8'; // indigo-400 — brand mark / accent
const SUCCESS_HEX = '#34D399'; // emerald-400 — success indicators
/**
* Brand mark — ◆ in brand indigo color
*/
export function brandMark() {
return isTTY ? chalk.hex(BRAND_HEX)('◆') : '◆';
}
/**
* Brand-colored text for inline use
*/
export function accent(text) {
return isTTY ? chalk.hex(BRAND_HEX)(text) : text;
}
/**
* Horizontal rule separator
*/
export function rule(width = 42) {
const line = '─'.repeat(width);
console.log(isTTY ? chalk.dim(` ${line}`) : ` ${'-'.repeat(width)}`);
}
/**
* Styled message output functions
*/
export function success(msg) {
console.log(isTTY ? chalk.hex(SUCCESS_HEX)(` ✓ ${msg}`) : ` OK ${msg}`);
}
export function error(msg) {
console.error(isTTY ? chalk.red(` ✗ ${msg}`) : ` ERROR ${msg}`);
}
export function warn(msg) {
console.log(isTTY ? chalk.yellow(` ⚠ ${msg}`) : ` WARN ${msg}`);
}
export function info(msg) {
console.log(isTTY ? chalk.dim(` › ${msg}`) : ` ${msg}`);
}
export function header(msg) {
console.log(isTTY ? chalk.bold(msg) : msg);
}
export function dim(msg) {
console.log(isTTY ? chalk.dim(msg) : msg);
}
export function blank() {
console.log('');
}
/**
* Section — a labeled block with › prefixed items
*/
export function section(title, items) {
console.log(isTTY ? chalk.bold(` ${title}`) : ` ${title}`);
for (const item of items) {
console.log(isTTY ? ` ${chalk.dim('›')} ${item}` : ` › ${item}`);
}
}
/**
* Key-value display — aligned pairs
*/
export function keyValue(pairs) {
const maxKeyLen = Math.max(...Object.keys(pairs).map(k => k.length));
for (const [key, value] of Object.entries(pairs)) {
const label = isTTY ? chalk.dim(key.padEnd(maxKeyLen)) : key.padEnd(maxKeyLen);
console.log(` ${label} ${value}`);
}
}
/**
* Deployment summary line — "✓ Agents 101 deployed"
*/
export function deployCount(label, count) {
const padded = label.length >= 12 ? `${label} ` : label.padEnd(12);
if (isTTY) {
console.log(chalk.hex(SUCCESS_HEX)(' ✓ ') + chalk.bold(padded) + chalk.dim(`${count} deployed`));
}
else {
console.log(` OK ${padded}${count} deployed`);
}
}
const noopSpinner = {
start() { return this; },
stop() { return this; },
succeed(text) { if (text)
console.log(` OK ${text}`); return this; },
fail(text) { if (text)
console.error(` FAIL ${text}`); return this; },
text: '',
};
export async function spinner(msg) {
if (!isTTY || isCI) {
console.log(` ${msg}`);
return noopSpinner;
}
try {
const ora = (await import('ora')).default;
return ora({ text: msg, indent: 2 });
}
catch {
console.log(` ${msg}`);
return noopSpinner;
}
}
/**
* Table display — wraps cli-table3 if available, falls back to padded columns
*/
export async function table(headers, rows) {
try {
const Table = (await import('cli-table3')).default;
const t = new Table({
head: isTTY ? headers.map(h => chalk.bold(h)) : headers,
style: { head: [], border: [] },
});
for (const row of rows) {
t.push(row);
}
console.log(t.toString());
}
catch {
// Fallback: padded columns
const widths = headers.map((h, i) => Math.max(h.length, ...rows.map(r => (r[i] || '').length)));
console.log(headers.map((h, i) => h.padEnd(widths[i])).join(' '));
console.log(widths.map(w => '-'.repeat(w)).join(' '));
for (const row of rows) {
console.log(row.map((c, i) => (c || '').padEnd(widths[i])).join(' '));
}
}
}
/**
* Format a channel label with color
*/
export function channelLabel(channel) {
if (!isTTY)
return `[${channel}]`;
switch (channel) {
case 'stable': return chalk.green(`[${channel}]`);
case 'edge': return chalk.yellow(`[${channel}]`);
case 'dev': return chalk.cyan(`[${channel}]`);
case 'rc': return chalk.yellow(`[${channel}]`);
case 'beta': return chalk.yellow(`[${channel}]`);
case 'alpha': return chalk.yellow(`[${channel}]`);
case 'nightly': return chalk.magenta(`[${channel}]`);
default: return chalk.dim(`[${channel}]`);
}
}
/**
* Format a status check result line (for doctor)
*/
export function checkResult(name, status, message) {
const symbols = { ok: '✓', warn: '⚠', error: '✗', info: '○' };
const symbol = symbols[status] || '?';
if (!isTTY) {
console.log(` ${symbol} ${name}: ${message}`);
return;
}
const colors = {
ok: chalk.green,
warn: chalk.yellow,
error: chalk.red,
info: chalk.cyan,
};
const colorFn = colors[status] || chalk.dim;
console.log(` ${colorFn(symbol)} ${name}: ${message}`);
}
/**
* Summary bar for doctor results
*/
export function summaryBar(pass, warnings, errors) {
if (errors > 0) {
const msg = `${errors} error(s), ${warnings} warning(s), ${pass} passed`;
console.log(isTTY ? chalk.red(` ✗ ${msg}`) : ` FAIL ${msg}`);
}
else if (warnings > 0) {
const msg = `${warnings} warning(s), ${pass} passed`;
console.log(isTTY ? chalk.yellow(` ⚠ ${msg}`) : ` WARN ${msg}`);
}
else {
const msg = `${pass} passed`;
console.log(isTTY ? chalk.hex(SUCCESS_HEX)(` ✓ All ${msg}`) : ` OK All ${msg}`);
}
}
/**
* Bold text for inline use
*/
export function bold(text) {
return isTTY ? chalk.bold(text) : text;
}
/**
* Dimmed text for inline use
*/
export function dimText(text) {
return isTTY ? chalk.dim(text) : text;
}
/**
* Colored text for inline use
*/
export function green(text) {
return isTTY ? chalk.green(text) : text;
}
export function red(text) {
return isTTY ? chalk.red(text) : text;
}
export function yellow(text) {
return isTTY ? chalk.yellow(text) : text;
}
export function cyan(text) {
return isTTY ? chalk.cyan(text) : text;
}
export { isTTY, isCI, BRAND_HEX };
//# sourceMappingURL=ui.js.map