Coverage for src / moai_adk / cli / prompts / init_prompts.py: 15.56%

45 statements  

« prev     ^ index     » next       coverage.py v7.12.0, created at 2025-11-20 20:52 +0900

1"""Project initialization prompts 

2 

3Collect interactive project settings 

4""" 

5 

6from pathlib import Path 

7from typing import TypedDict 

8 

9import questionary 

10from rich.console import Console 

11 

12console = Console() 

13 

14 

15class ProjectSetupAnswers(TypedDict): 

16 """Project setup answers""" 

17 

18 project_name: str 

19 mode: str # personal | team (default from init) 

20 locale: str # ko | en | ja | zh | other (default from init) 

21 language: str | None # Will be set in /alfred:0-project 

22 author: str # Will be set in /alfred:0-project 

23 custom_language: str | None # User input for "other" language option 

24 

25 

26def prompt_project_setup( 

27 project_name: str | None = None, 

28 is_current_dir: bool = False, 

29 project_path: Path | None = None, 

30 initial_locale: str | None = None, 

31) -> ProjectSetupAnswers: 

32 """Project setup prompt 

33 

34 Args: 

35 project_name: Project name (asks when None) 

36 is_current_dir: Whether the current directory is being used 

37 project_path: Project path (used to derive the name) 

38 initial_locale: Preferred locale provided via CLI (optional) 

39 

40 Returns: 

41 Project setup answers 

42 

43 Raises: 

44 KeyboardInterrupt: When user cancels the prompt (Ctrl+C) 

45 """ 

46 answers: ProjectSetupAnswers = { 

47 "project_name": "", 

48 "mode": "personal", # Default: will be configurable in /alfred:0-project 

49 "locale": "en", # Default: will be configurable in /alfred:0-project 

50 "language": None, # Will be detected in /alfred:0-project 

51 "author": "", # Will be set in /alfred:0-project 

52 "custom_language": None, # User input for other language 

53 } 

54 

55 try: 

56 # SIMPLIFIED: Only ask for project name 

57 # All other settings (mode, locale, language, author) are now configured in /alfred:0-project 

58 

59 # 1. Project name (only when not using the current directory) 

60 if not is_current_dir: 

61 if project_name: 

62 answers["project_name"] = project_name 

63 console.print(f"[cyan]📦 Project Name:[/cyan] {project_name}") 

64 else: 

65 result = questionary.text( 

66 "📦 Project Name:", 

67 default="my-moai-project", 

68 validate=lambda text: len(text) > 0 or "Project name is required", 

69 ).ask() 

70 if result is None: 

71 raise KeyboardInterrupt 

72 answers["project_name"] = result 

73 else: 

74 # Use the current directory name 

75 # Note: Path.cwd() reflects the process working directory (Codex CLI cwd) 

76 # Prefer project_path when provided (user execution location) 

77 if project_path: 

78 answers["project_name"] = project_path.name 

79 else: 

80 answers["project_name"] = Path.cwd().name # fallback 

81 console.print( 

82 f"[cyan]📦 Project Name:[/cyan] {answers['project_name']} [dim](current directory)[/dim]" 

83 ) 

84 

85 # 2. Language selection - Korean, English, Japanese, Chinese, Other 

86 console.print("\n[blue]🌐 Language Selection[/blue]") 

87 

88 # Build choices list 

89 language_choices = [ 

90 "Korean (한국어)", 

91 "English", 

92 "Japanese (日本語)", 

93 "Chinese (中文)", 

94 "Other - Manual input", 

95 ] 

96 

97 # Determine default choice index 

98 language_values = ["ko", "en", "ja", "zh", "other"] 

99 default_locale = initial_locale or "en" 

100 default_index = language_values.index(default_locale) if default_locale in language_values else 1 

101 

102 language_choice_name = questionary.select( 

103 "Select your conversation language:", 

104 choices=language_choices, 

105 default=language_choices[default_index], 

106 ).ask() 

107 

108 # Map choice name back to value 

109 choice_mapping = { 

110 "Korean (한국어)": "ko", 

111 "English": "en", 

112 "Japanese (日本語)": "ja", 

113 "Chinese (中文)": "zh", 

114 "Other - Manual input": "other", 

115 } 

116 language_choice = choice_mapping.get(language_choice_name) 

117 

118 if language_choice is None: 

119 raise KeyboardInterrupt 

120 

121 if language_choice == "other": 

122 # Prompt for manual input 

123 custom_lang = questionary.text( 

124 "Enter your language:", 

125 validate=lambda text: len(text) > 0 or "Language is required", 

126 ).ask() 

127 

128 if custom_lang is None: 

129 raise KeyboardInterrupt 

130 

131 answers["custom_language"] = custom_lang 

132 answers["locale"] = "other" # When ISO code is not available 

133 console.print(f"[cyan]🌐 Selected Language:[/cyan] {custom_lang}") 

134 else: 

135 answers["locale"] = language_choice 

136 language_names = { 

137 "ko": "Korean (한국어)", 

138 "en": "English", 

139 "ja": "Japanese (日本語)", 

140 "zh": "Chinese (中文)", 

141 } 

142 console.print( 

143 f"[cyan]🌐 Selected Language:[/cyan] {language_names.get(language_choice, language_choice)}" 

144 ) 

145 

146 return answers 

147 

148 except KeyboardInterrupt: 

149 console.print("\n[yellow]Setup cancelled by user[/yellow]") 

150 raise