Coverage for src / osiris_cli / command_palette.py: 0%

50 statements  

« prev     ^ index     » next       coverage.py v7.13.0, created at 2025-12-27 17:41 +0200

1#!/usr/bin/env python3 

2""" 

3Enhanced Command Palette for Osiris CLI v4.0 

4Beautiful, automatic, interactive menu system 

5""" 

6 

7import questionary 

8from questionary import Style 

9from rich.console import Console 

10from rich.table import Table 

11from rich.panel import Panel 

12from typing import Optional, List, Dict 

13 

14console = Console() 

15 

16# Custom style for the command palette 

17PALETTE_STYLE = Style([ 

18 ('qmark', 'fg:#3b82f6 bold'), 

19 ('question', 'bold'), 

20 ('answer', 'fg:#10b981 bold'), 

21 ('pointer', 'fg:#3b82f6 bold'), 

22 ('highlighted', 'fg:#3b82f6 bold'), 

23 ('selected', 'fg:#10b981'), 

24 ('separator', 'fg:#6b7280'), 

25 ('instruction', 'fg:#9ca3af'), 

26 ('text', ''), 

27 ('disabled', 'fg:#6b7280 italic') 

28]) 

29 

30# Command definitions with rich metadata 

31COMMANDS = { 

32 "Core": [ 

33 {"name": "/help", "desc": "Show complete command reference with examples", "icon": "📚"}, 

34 {"name": "/exit", "desc": "Exit Osiris CLI gracefully", "icon": "👋"}, 

35 ], 

36 "Model & Provider": [ 

37 {"name": "/model", "desc": "Change AI model (gpt-4, claude-3.5, etc.)", "icon": "🤖"}, 

38 {"name": "/provider", "desc": "Switch AI provider (openai, anthropic, etc.)", "icon": "🔄"}, 

39 {"name": "/yolo", "desc": "Toggle autonomous mode (auto-approve all tools)", "icon": "⚡"}, 

40 ], 

41 "Memory System": [ 

42 {"name": "/remember", "desc": "Add key:value to agent's long-term memory", "icon": "🧠"}, 

43 {"name": "/forget", "desc": "Remove a key from agent memory", "icon": "🗑️"}, 

44 {"name": "/memory", "desc": "Display all stored memories and skills", "icon": "💾"}, 

45 {"name": "/init", "desc": "Interactive wizard to initialize agent memory", "icon": "✨"}, 

46 {"name": "/skill", "desc": "Teach the agent a new capability or skill", "icon": "🎓"}, 

47 ], 

48 "Session Management": [ 

49 {"name": "/session", "desc": "List and manage saved conversation sessions", "icon": "📂"}, 

50 {"name": "/clear", "desc": "Clear screen while keeping conversation history", "icon": "🧹"}, 

51 {"name": "/reset", "desc": "Reset conversation but preserve agent memory", "icon": "🔄"}, 

52 ], 

53 "Context & Tools": [ 

54 {"name": "/context", "desc": "Show loaded OSIRIS.md context files", "icon": "📄"}, 

55 {"name": "/tools", "desc": "List all 13+ available tools and capabilities", "icon": "🛠️"}, 

56 ], 

57 "Advanced Features": [ 

58 {"name": "/shadow", "desc": "Test mode - preview changes before applying", "icon": "👻"}, 

59 {"name": "/vim", "desc": "Toggle Vim-style keybindings (: prompt)", "icon": "⌨️"}, 

60 {"name": "/plan", "desc": "Request AI to create execution plan first", "icon": "📋"}, 

61 ], 

62} 

63 

64 

65async def show_command_palette() -> Optional[str]: 

66 """ 

67 Display beautiful command palette and return selected command. 

68 Returns None if cancelled. 

69 """ 

70 # Build choices list with rich formatting 

71 choices = [] 

72 

73 for category, commands in COMMANDS.items(): 

74 # Add category separator 

75 choices.append(questionary.Separator(f"\n═══ {category} ═══")) 

76 

77 # Add commands in this category 

78 for cmd in commands: 

79 icon = cmd.get("icon", "•") 

80 name = cmd["name"] 

81 desc = cmd["desc"] 

82 # Format: "icon /command - description" 

83 choice_text = f"{icon} {name:<12}{desc}" 

84 choices.append(questionary.Choice(title=choice_text, value=name)) 

85 

86 # Add cancel option 

87 choices.append(questionary.Separator("\n───────────────────────────────────────")) 

88 choices.append(questionary.Choice(title="❌ Cancel", value=None)) 

89 

90 # Show the palette 

91 try: 

92 result = await questionary.select( 

93 "Select a command:", 

94 choices=choices, 

95 style=PALETTE_STYLE, 

96 use_shortcuts=True, 

97 use_arrow_keys=True, 

98 use_indicator=True, 

99 instruction="(Use arrow keys, type to filter, Enter to select)", 

100 ).ask_async() 

101 

102 return result 

103 except (KeyboardInterrupt, EOFError): 

104 return None 

105 

106 

107def show_command_table(): 

108 """Display all commands in a beautiful table""" 

109 table = Table(title="🎯 Osiris CLI Commands", show_header=True, header_style="bold cyan") 

110 table.add_column("Command", style="cyan", width=15) 

111 table.add_column("Description", style="white") 

112 table.add_column("Category", style="magenta", width=20) 

113 

114 for category, commands in COMMANDS.items(): 

115 for cmd in commands: 

116 icon = cmd.get("icon", "•") 

117 table.add_row( 

118 f"{icon} {cmd['name']}", 

119 cmd['desc'], 

120 category 

121 ) 

122 

123 console.print(table) 

124 

125 

126def search_commands(query: str) -> List[Dict]: 

127 """Search commands by name or description""" 

128 query = query.lower() 

129 results = [] 

130 

131 for category, commands in COMMANDS.items(): 

132 for cmd in commands: 

133 if query in cmd["name"].lower() or query in cmd["desc"].lower(): 

134 results.append({**cmd, "category": category}) 

135 

136 return results 

137 

138 

139if __name__ == "__main__": 

140 # Test the palette 

141 console.print("\n[bold cyan]Osiris Command Palette Demo[/bold cyan]\n") 

142 

143 selected = show_command_palette() 

144 

145 if selected: 

146 console.print(f"\n[green]✓[/green] Selected: [bold]{selected}[/bold]\n") 

147 else: 

148 console.print("\n[yellow]Cancelled[/yellow]\n")