jay-code
Version:
Streamlined AI CLI orchestration engine with mathematical rigor and enterprise-grade reliability
571 lines (511 loc) • 21.3 kB
text/typescript
/**
* Shell completion generator for Jay-Code CLI
*/
import chalk from 'chalk';
import { promises as fs } from 'node:fs';
export class CompletionGenerator {
private commands = [
'start',
'agent',
'task',
'memory',
'config',
'status',
'monitor',
'session',
'workflow',
'repl',
'version',
'completion',
];
private subcommands = {
agent: ['spawn', 'list', 'terminate', 'info'],
task: ['create', 'list', 'status', 'cancel', 'workflow'],
memory: ['query', 'export', 'import', 'stats', 'cleanup'],
config: ['show', 'get', 'set', 'init', 'validate'],
session: ['list', 'save', 'restore', 'delete', 'export', 'import', 'info', 'clean'],
workflow: ['run', 'validate', 'list', 'status', 'stop', 'template'],
};
async generate(shell: string, install: boolean = false): Promise<void> {
const detectedShell = shell === 'detect' ? await this.detectShell() : shell;
switch (detectedShell) {
case 'bash':
await this.generateBashCompletion(install);
break;
case 'zsh':
await this.generateZshCompletion(install);
break;
case 'fish':
await this.generateFishCompletion(install);
break;
default:
console.error(chalk.red(`Unsupported shell: ${detectedShell}`));
console.log(chalk.gray('Supported shells: bash, zsh, fish'));
break;
}
}
private async detectShell(): Promise<string> {
const shell = process.env['SHELL'] || '';
if (shell.includes('bash')) return 'bash';
if (shell.includes('zsh')) return 'zsh';
if (shell.includes('fish')) return 'fish';
console.log(chalk.yellow('Could not detect shell, defaulting to bash'));
return 'bash';
}
private async generateBashCompletion(install: boolean): Promise<void> {
const script = this.getBashCompletionScript();
if (install) {
await this.installBashCompletion(script);
} else {
console.log(script);
}
}
private async generateZshCompletion(install: boolean): Promise<void> {
const script = this.getZshCompletionScript();
if (install) {
await this.installZshCompletion(script);
} else {
console.log(script);
}
}
private async generateFishCompletion(install: boolean): Promise<void> {
const script = this.getFishCompletionScript();
if (install) {
await this.installFishCompletion(script);
} else {
console.log(script);
}
}
private getBashCompletionScript(): string {
return `# Jay-Code bash completion
_claude_flow_completion() {
local cur prev words cword
_init_completion || return
case \${words[1]} in
agent)
case \${words[2]} in
spawn)
COMPREPLY=($(compgen -W "coordinator researcher implementer analyst custom" -- "$cur"))
return
;;
terminate|info)
# In production, this would complete with actual agent IDs
COMPREPLY=($(compgen -W "agent-001 agent-002 agent-003" -- "$cur"))
return
;;
*)
COMPREPLY=($(compgen -W "${this.subcommands.agent.join(' ')}" -- "$cur"))
return
;;
esac
;;
task)
case \${words[2]} in
create)
if [[ \${#words[@]} -eq 4 ]]; then
COMPREPLY=($(compgen -W "research implementation analysis coordination" -- "$cur"))
fi
return
;;
status|cancel)
# In production, this would complete with actual task IDs
COMPREPLY=($(compgen -W "task-001 task-002 task-003" -- "$cur"))
return
;;
workflow)
COMPREPLY=($(compgen -f -X '!*.@(json|yaml|yml)' -- "$cur"))
return
;;
*)
COMPREPLY=($(compgen -W "${this.subcommands.task.join(' ')}" -- "$cur"))
return
;;
esac
;;
memory)
COMPREPLY=($(compgen -W "${this.subcommands.memory.join(' ')}" -- "$cur"))
return
;;
config)
COMPREPLY=($(compgen -W "${this.subcommands.config.join(' ')}" -- "$cur"))
return
;;
session)
case \${words[2]} in
restore|delete|info|export)
# In production, this would complete with actual session IDs
COMPREPLY=($(compgen -W "session-001 session-002 session-003" -- "$cur"))
return
;;
import)
COMPREPLY=($(compgen -f -X '!*.@(json|yaml|yml)' -- "$cur"))
return
;;
*)
COMPREPLY=($(compgen -W "${this.subcommands.session.join(' ')}" -- "$cur"))
return
;;
esac
;;
workflow)
case \${words[2]} in
run|validate)
COMPREPLY=($(compgen -f -X '!*.@(json|yaml|yml)' -- "$cur"))
return
;;
template)
COMPREPLY=($(compgen -W "research implementation coordination" -- "$cur"))
return
;;
status|stop)
# In production, this would complete with actual workflow IDs
COMPREPLY=($(compgen -W "workflow-001 workflow-002 workflow-003" -- "$cur"))
return
;;
*)
COMPREPLY=($(compgen -W "${this.subcommands.workflow.join(' ')}" -- "$cur"))
return
;;
esac
;;
completion)
COMPREPLY=($(compgen -W "bash zsh fish" -- "$cur"))
return
;;
*)
COMPREPLY=($(compgen -W "${this.commands.join(' ')}" -- "$cur"))
return
;;
esac
}
complete -F _claude_flow_completion jay-code`;
}
private getZshCompletionScript(): string {
return `#compdef jay-code
# Jay-Code zsh completion
_claude_flow() {
local context state state_descr line
typeset -A opt_args
_arguments -C \\
'(-h --help)'{-h,--help}'[Show help information]' \\
'(-v --verbose)'{-v,--verbose}'[Enable verbose logging]' \\
'(-q --quiet)'{-q,--quiet}'[Suppress non-essential output]' \\
'(-c --config)'{-c,--config}'[Path to configuration file]:config file:_files -g "*.json"' \\
'--log-level[Set log level]:level:(debug info warn error)' \\
'--no-color[Disable colored output]' \\
'--json[Output in JSON format]' \\
'--profile[Use named configuration profile]:profile:' \\
'1: :_claude_flow_commands' \\
'*::arg:->args'
case $state in
args)
case $words[1] in
agent)
_claude_flow_agent
;;
task)
_claude_flow_task
;;
memory)
_claude_flow_memory
;;
config)
_claude_flow_config
;;
session)
_claude_flow_session
;;
workflow)
_claude_flow_workflow
;;
completion)
_arguments \\
'--install[Install completion script automatically]' \\
'1: :(bash zsh fish)'
;;
esac
;;
esac
}
_claude_flow_commands() {
local commands
commands=(
'start:Start the Jay-Code orchestration system'
'agent:Manage Jay-Code agents'
'task:Manage tasks'
'memory:Manage agent memory'
'config:Manage Jay-Code configuration'
'status:Show Jay-Code system status'
'monitor:Start live monitoring dashboard'
'session:Manage Jay-Code sessions'
'workflow:Execute and manage workflows'
'repl:Start interactive REPL mode'
'version:Show detailed version information'
'completion:Generate shell completion scripts'
)
_describe 'commands' commands
}
_claude_flow_agent() {
case $words[2] in
spawn)
_arguments \\
'(-n --name)'{-n,--name}'[Agent name]:name:' \\
'(-p --priority)'{-p,--priority}'[Agent priority]:priority:' \\
'(-m --max-tasks)'{-m,--max-tasks}'[Maximum concurrent tasks]:max:' \\
'--system-prompt[Custom system prompt]:prompt:' \\
'1: :(coordinator researcher implementer analyst custom)'
;;
terminate|info)
_arguments '1: :_claude_flow_agents'
;;
*)
_arguments '1: :(${this.subcommands.agent.join(' ')})'
;;
esac
}
_claude_flow_task() {
case $words[2] in
create)
_arguments \\
'(-p --priority)'{-p,--priority}'[Task priority]:priority:' \\
'(-d --dependencies)'{-d,--dependencies}'[Comma-separated dependency task IDs]:deps:' \\
'(-i --input)'{-i,--input}'[Task input as JSON]:input:' \\
'(-a --assign)'{-a,--assign}'[Assign to specific agent]:agent:_claude_flow_agents' \\
'1: :(research implementation analysis coordination)' \\
'2: :_message_or_description'
;;
workflow)
_arguments '1: :_files -g "*.json *.yaml *.yml"'
;;
status|cancel)
_arguments '1: :_claude_flow_tasks'
;;
*)
_arguments '1: :(${this.subcommands.task.join(' ')})'
;;
esac
}
_claude_flow_memory() {
_arguments '1: :(${this.subcommands.memory.join(' ')})'
}
_claude_flow_config() {
_arguments '1: :(${this.subcommands.config.join(' ')})'
}
_claude_flow_session() {
case $words[2] in
restore|delete|info|export)
_arguments '1: :_claude_flow_sessions'
;;
import)
_arguments '1: :_files -g "*.json *.yaml *.yml"'
;;
*)
_arguments '1: :(${this.subcommands.session.join(' ')})'
;;
esac
}
_claude_flow_workflow() {
case $words[2] in
run|validate)
_arguments '1: :_files -g "*.json *.yaml *.yml"'
;;
template)
_arguments '1: :(research implementation coordination)'
;;
status|stop)
_arguments '1: :_claude_flow_workflows'
;;
*)
_arguments '1: :(${this.subcommands.workflow.join(' ')})'
;;
esac
}
# Helper functions for completion
_claude_flow_agents() {
# In production, this would query the running orchestrator
local agents
agents=('agent-001:Coordinator Agent' 'agent-002:Research Agent' 'agent-003:Implementation Agent')
_describe 'agents' agents
}
_claude_flow_tasks() {
# In production, this would query the running orchestrator
local tasks
tasks=('task-001:Research Task' 'task-002:Analysis Task' 'task-003:Implementation Task')
_describe 'tasks' tasks
}
_claude_flow_sessions() {
# In production, this would query saved sessions
local sessions
sessions=('session-001:Research Session' 'session-002:Development Session' 'session-003:Analysis Session')
_describe 'sessions' sessions
}
_claude_flow_workflows() {
# In production, this would query running workflows
local workflows
workflows=('workflow-001:Research Workflow' 'workflow-002:Implementation Workflow')
_describe 'workflows' workflows
}
_message_or_description() {
_message 'task description'
}
_claude_flow "$@"`;
}
private getFishCompletionScript(): string {
return `# Jay-Code fish completion
function __fish_claude_flow_needs_command
set cmd (commandline -opc)
if [ (count $cmd) -eq 1 ]
return 0
end
return 1
end
function __fish_claude_flow_using_command
set cmd (commandline -opc)
if [ (count $cmd) -gt 1 ]
if [ $argv[1] = $cmd[2] ]
return 0
end
end
return 1
end
# Main commands
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'start' -d 'Start the Jay-Code orchestration system'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'agent' -d 'Manage Jay-Code agents'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'task' -d 'Manage tasks'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'memory' -d 'Manage agent memory'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'config' -d 'Manage Jay-Code configuration'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'status' -d 'Show Jay-Code system status'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'monitor' -d 'Start live monitoring dashboard'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'session' -d 'Manage Jay-Code sessions'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'workflow' -d 'Execute and manage workflows'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'repl' -d 'Start interactive REPL mode'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'version' -d 'Show detailed version information'
complete -f -c jay-code -n '__fish_claude_flow_needs_command' -a 'completion' -d 'Generate shell completion scripts'
# Global options
complete -c jay-code -s h -l help -d 'Show help information'
complete -c jay-code -s v -l verbose -d 'Enable verbose logging'
complete -c jay-code -s q -l quiet -d 'Suppress non-essential output'
complete -c jay-code -s c -l config -r -d 'Path to configuration file'
complete -c jay-code -l log-level -r -a 'debug info warn error' -d 'Set log level'
complete -c jay-code -l no-color -d 'Disable colored output'
complete -c jay-code -l json -d 'Output in JSON format'
complete -c jay-code -l profile -r -d 'Use named configuration profile'
# Agent subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command agent' -a 'spawn' -d 'Spawn a new agent'
complete -f -c jay-code -n '__fish_claude_flow_using_command agent' -a 'list' -d 'List all agents'
complete -f -c jay-code -n '__fish_claude_flow_using_command agent' -a 'terminate' -d 'Terminate an agent'
complete -f -c jay-code -n '__fish_claude_flow_using_command agent' -a 'info' -d 'Get agent information'
# Task subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command task' -a 'create' -d 'Create a new task'
complete -f -c jay-code -n '__fish_claude_flow_using_command task' -a 'list' -d 'List all tasks'
complete -f -c jay-code -n '__fish_claude_flow_using_command task' -a 'status' -d 'Get task status'
complete -f -c jay-code -n '__fish_claude_flow_using_command task' -a 'cancel' -d 'Cancel a task'
complete -f -c jay-code -n '__fish_claude_flow_using_command task' -a 'workflow' -d 'Execute workflow from file'
# Memory subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command memory' -a 'query' -d 'Query memory entries'
complete -f -c jay-code -n '__fish_claude_flow_using_command memory' -a 'export' -d 'Export memory to file'
complete -f -c jay-code -n '__fish_claude_flow_using_command memory' -a 'import' -d 'Import memory from file'
complete -f -c jay-code -n '__fish_claude_flow_using_command memory' -a 'stats' -d 'Show memory statistics'
complete -f -c jay-code -n '__fish_claude_flow_using_command memory' -a 'cleanup' -d 'Clean up old entries'
# Config subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command config' -a 'show' -d 'Show current configuration'
complete -f -c jay-code -n '__fish_claude_flow_using_command config' -a 'get' -d 'Get specific config value'
complete -f -c jay-code -n '__fish_claude_flow_using_command config' -a 'set' -d 'Set config value'
complete -f -c jay-code -n '__fish_claude_flow_using_command config' -a 'init' -d 'Initialize config file'
complete -f -c jay-code -n '__fish_claude_flow_using_command config' -a 'validate' -d 'Validate config file'
# Session subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'list' -d 'List all saved sessions'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'save' -d 'Save current session state'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'restore' -d 'Restore a saved session'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'delete' -d 'Delete a saved session'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'export' -d 'Export session to file'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'import' -d 'Import session from file'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'info' -d 'Show detailed session information'
complete -f -c jay-code -n '__fish_claude_flow_using_command session' -a 'clean' -d 'Clean up old sessions'
# Workflow subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'run' -d 'Execute a workflow from file'
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'validate' -d 'Validate a workflow file'
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'list' -d 'List running workflows'
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'status' -d 'Show workflow execution status'
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'stop' -d 'Stop a running workflow'
complete -f -c jay-code -n '__fish_claude_flow_using_command workflow' -a 'template' -d 'Generate workflow templates'
# Completion subcommands
complete -f -c jay-code -n '__fish_claude_flow_using_command completion' -a 'bash zsh fish'`;
}
private async installBashCompletion(script: string): Promise<void> {
const possiblePaths = [
'/etc/bash_completion.d/jay-code',
'/usr/local/etc/bash_completion.d/jay-code',
`${process.env['HOME']}/.local/share/bash-completion/completions/jay-code`,
`${process.env['HOME']}/.bash_completion.d/jay-code`,
];
for (const path of possiblePaths) {
try {
const dir = path.substring(0, path.lastIndexOf('/'));
await Deno.mkdir(dir, { recursive: true });
await fs.writeFile(path, script);
console.log(chalk.green('✓ Bash completion installed'));
console.log(`${chalk.white('Location:')} ${path}`);
console.log(chalk.gray('Restart your shell or run: source ~/.bashrc'));
return;
} catch (error) {
// Try next path
continue;
}
}
console.error(chalk.red('Failed to install bash completion'));
console.log(
chalk.gray('You can manually save the completion script to a bash completion directory'),
);
}
private async installZshCompletion(script: string): Promise<void> {
const possiblePaths = [
`${process.env['HOME']}/.zsh/completions/_jay-code`,
'/usr/local/share/zsh/site-functions/_jay-code',
'/usr/share/zsh/site-functions/_jay-code',
];
for (const path of possiblePaths) {
try {
const dir = path.substring(0, path.lastIndexOf('/'));
await Deno.mkdir(dir, { recursive: true });
await fs.writeFile(path, script);
console.log(chalk.green('✓ Zsh completion installed'));
console.log(`${chalk.white('Location:')} ${path}`);
console.log(chalk.gray('Restart your shell or run: autoload -U compinit && compinit'));
return;
} catch (error) {
// Try next path
continue;
}
}
console.error(chalk.red('Failed to install zsh completion'));
console.log(
chalk.gray('You can manually save the completion script to your zsh completion directory'),
);
}
private async installFishCompletion(script: string): Promise<void> {
const possiblePaths = [
`${process.env['HOME']}/.config/fish/completions/jay-code.fish`,
'/usr/local/share/fish/completions/jay-code.fish',
'/usr/share/fish/completions/jay-code.fish',
];
for (const path of possiblePaths) {
try {
const dir = path.substring(0, path.lastIndexOf('/'));
await Deno.mkdir(dir, { recursive: true });
await fs.writeFile(path, script);
console.log(chalk.green('✓ Fish completion installed'));
console.log(`${chalk.white('Location:')} ${path}`);
console.log(chalk.gray('Completions will be available in new fish sessions'));
return;
} catch (error) {
// Try next path
continue;
}
}
console.error(chalk.red('Failed to install fish completion'));
console.log(
chalk.gray('You can manually save the completion script to your fish completion directory'),
);
}
}