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
177 lines • 6.03 kB
JavaScript
/**
* Help Generator
*
* Dynamically generates CLI help text from the extension registry.
* Replaces hardcoded displayHelp() with registry-driven approach.
*
* @implements @.aiwg/architecture/decisions/ADR-001-unified-extension-system.md
* @tests @test/unit/cli/help-generator.test.ts
* @version 1.0.0
*/
/**
* Category display order and titles
*
* Determines the order in which command categories appear in help output.
*/
const CATEGORY_ORDER = [
{ category: 'framework', title: 'Framework Management' },
{ category: 'project', title: 'Project Setup' },
{ category: 'workspace', title: 'Workspace Management' },
{ category: 'mcp', title: 'MCP Server' },
{ category: 'toolsmith', title: 'Toolsmith (Runtime Discovery)' },
{ category: 'catalog', title: 'Model Catalog' },
{ category: 'utility', title: 'Utilities' },
{ category: 'plugin', title: 'Plugin Packaging' },
{ category: 'scaffolding', title: 'Scaffolding' },
{ category: 'channel', title: 'Channel Management' },
{ category: 'maintenance', title: 'Maintenance' },
{ category: 'ralph', title: 'Agent Loop (Iterative Execution)' },
{ category: 'orchestration', title: 'Orchestration (Mission Control)' },
{ category: 'index', title: 'Artifact Index' },
{ category: 'daemon', title: 'Daemon & Behaviors' },
{ category: 'agentic-tools', title: 'Agentic Tools (RLM chunk, fanout, search)' },
];
/**
* Command name column width for alignment
*/
const COMMAND_COL_WIDTH = 24;
/**
* Generate help text from registry
*
* Dynamically builds CLI help text by querying the extension registry for
* command extensions, grouping them by category, and formatting them for display.
*
* @param registry - Extension registry to query
* @returns Formatted help text
*
* @example
* ```typescript
* import { getRegistry } from '../extensions/registry.js';
* import { generateHelp } from './help-generator.js';
*
* const registry = getRegistry();
* const helpText = generateHelp(registry);
* console.log(helpText);
* ```
*/
export function generateHelp(registry) {
const lines = [];
// Header
lines.push('AIWG CLI');
lines.push('');
lines.push('Usage: aiwg <command> [options]');
lines.push('');
// Get commands by category (skills are the canonical source format for CLI commands)
const commands = [
...registry.getByType('skill'),
...registry.getByType('command'),
];
const byCategory = groupByCategory(commands);
// Generate sections in order
for (const { category, title } of CATEGORY_ORDER) {
const categoryCommands = byCategory.get(category);
if (!categoryCommands || categoryCommands.length === 0)
continue;
lines.push(`${title}:`);
for (const cmd of categoryCommands) {
const name = formatCommandName(cmd);
const desc = cmd.description;
lines.push(` ${name.padEnd(COMMAND_COL_WIDTH)} ${desc}`);
}
lines.push('');
}
// Platform options
lines.push('Platform Options (--provider):');
lines.push(' claude Claude Code (default)');
lines.push(' copilot GitHub Copilot');
lines.push(' factory Factory AI');
lines.push(' codex / openai OpenAI Codex');
lines.push(' cursor Cursor IDE');
lines.push(' opencode OpenCode');
lines.push(' warp Warp Terminal');
lines.push(' windsurf Windsurf');
lines.push('');
// Examples
lines.push('Examples:');
lines.push(' aiwg use sdlc Install SDLC framework');
lines.push(' aiwg -new Create new project');
lines.push(' aiwg doctor Check installation health');
lines.push('');
return lines.join('\n');
}
/**
* Group commands by category
*
* Takes a flat list of command extensions and organizes them into a Map
* keyed by category, with values being arrays of extensions.
*
* @param commands - Array of command extensions
* @returns Map of category to command extensions
*
* @example
* ```typescript
* const commands = registry.getByType('command');
* const grouped = groupByCategory(commands);
*
* const frameworkCommands = grouped.get('framework');
* console.log(`${frameworkCommands?.length} framework commands`);
* ```
*/
function groupByCategory(commands) {
const map = new Map();
for (const cmd of commands) {
const category = cmd.category || 'utility';
let list = map.get(category);
if (!list) {
list = [];
map.set(category, list);
}
list.push(cmd);
}
// Sort commands within each category by ID
// Use Array.from to convert values() iterator to array
Array.from(map.values()).forEach((list) => {
list.sort((a, b) => a.id.localeCompare(b.id));
});
return map;
}
/**
* Format command name with primary alias
*
* Returns a formatted command name string that includes the primary alias
* (if present) for display in help text.
*
* Format:
* - No aliases: "command-name"
* - With aliases: "command-name, -alias"
*
* @param cmd - Command extension
* @returns Formatted command name string
*
* @example
* ```typescript
* // Command with no aliases
* const name1 = formatCommandName(useCmd);
* // Returns: "use"
*
* // Command with aliases
* const name2 = formatCommandName(newCmd);
* // Returns: "new, -new"
*
* // Command with multiple aliases
* const name3 = formatCommandName(helpCmd);
* // Returns: "help, -h"
* ```
*/
function formatCommandName(cmd) {
// Get aliases from metadata
const metadata = cmd.metadata;
const aliases = metadata?.aliases || [];
// If no aliases, just return ID
if (aliases.length === 0) {
return cmd.id;
}
// Show command name with first alias
return `${cmd.id}, ${aliases[0]}`;
}
//# sourceMappingURL=help-generator.js.map