17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
|
# File 'lib/n2b/base.rb', line 17
def get_config(reconfigure: false, advanced_flow: false)
config = load_config
api_key = ENV['CLAUDE_API_KEY'] || config['access_key'] _model = config['model']
is_first_time_core_setup = config['llm'].nil?
if api_key.nil? || api_key == '' || config['llm'].nil? || reconfigure
puts "--- N2B Core LLM Configuration ---"
print "Choose a language model to use (1:claude, 2:openai, 3:gemini, 4:openrouter, 5:ollama) [current: #{config['llm']}]: "
llm_choice = $stdin.gets.chomp
llm_choice = config['llm'] if llm_choice.empty? && !config['llm'].nil?
unless ['claude', 'openai', 'gemini', 'openrouter', 'ollama', '1', '2', '3', '4', '5'].include?(llm_choice)
puts "Invalid language model selection. Defaulting to 'claude' or previous if available."
llm_choice = config['llm'] || 'claude' end
selected_llm = case llm_choice
when '1', 'claude' then 'claude'
when '2', 'openai' then 'openai'
when '3', 'gemini' then 'gemini'
when '4', 'openrouter' then 'openrouter'
when '5', 'ollama' then 'ollama'
else config['llm'] || 'claude' end
config['llm'] = selected_llm
if selected_llm == 'ollama'
puts "\n--- Ollama Specific Configuration ---"
puts "Ollama typically runs locally and doesn't require an API key."
current_model = config['model']
model_choice = N2B::ModelConfig.get_model_choice(selected_llm, current_model) config['model'] = model_choice
current_ollama_api_url = config['ollama_api_url'] || N2M::Llm::Ollama::DEFAULT_OLLAMA_API_URI
print "Enter Ollama API base URL [current: #{current_ollama_api_url}]: "
ollama_api_url_input = $stdin.gets.chomp
config['ollama_api_url'] = ollama_api_url_input.empty? ? current_ollama_api_url : ollama_api_url_input
config.delete('access_key') else
puts "\n--- #{selected_llm.capitalize} Specific Configuration ---"
current_api_key = config['access_key']
print "Enter your #{selected_llm} API key #{ current_api_key.nil? || current_api_key.empty? ? '' : '[leave blank to keep current]' }: "
api_key_input = $stdin.gets.chomp
config['access_key'] = api_key_input if !api_key_input.empty?
config['access_key'] = current_api_key if api_key_input.empty? && !current_api_key.nil? && !current_api_key.empty?
if config['access_key'].nil? || config['access_key'].empty?
puts "API key is required for #{selected_llm}."
exit 1
end
current_model = config['model']
model_choice = N2B::ModelConfig.get_model_choice(selected_llm, current_model) config['model'] = model_choice
if selected_llm == 'openrouter'
current_site_url = config['openrouter_site_url'] || ""
print "Enter your OpenRouter Site URL (optional, for HTTP-Referer) [current: #{current_site_url}]: "
openrouter_site_url_input = $stdin.gets.chomp
config['openrouter_site_url'] = openrouter_site_url_input.empty? ? current_site_url : openrouter_site_url_input
current_site_name = config['openrouter_site_name'] || ""
print "Enter your OpenRouter Site Name (optional, for X-Title) [current: #{current_site_name}]: "
openrouter_site_name_input = $stdin.gets.chomp
config['openrouter_site_name'] = openrouter_site_name_input.empty? ? current_site_name : openrouter_site_name_input
end
end
prompt_for_advanced = advanced_flow || is_first_time_core_setup
if prompt_for_advanced
puts "\n--- Advanced Settings ---"
print "Would you like to configure advanced settings (e.g., Jira integration, privacy)? (y/n) [default: n]: "
choice = $stdin.gets.chomp.downcase
if choice == 'y'
puts "\n--- Jira Integration ---"
puts "You can generate a Jira API token here: https://support.atlassian.com/atlassian-account/docs/manage-api-tokens-for-your-atlassian-account/"
config['jira'] ||= {}
print "Jira Domain (e.g., your-company.atlassian.net) [current: #{config['jira']['domain']}]: "
config['jira']['domain'] = $stdin.gets.chomp.then { |val| val.empty? ? config['jira']['domain'] : val }
print "Jira Email Address [current: #{config['jira']['email']}]: "
config['jira']['email'] = $stdin.gets.chomp.then { |val| val.empty? ? config['jira']['email'] : val }
print "Jira API Token #{config['jira']['api_key'] ? '[leave blank to keep current]' : ''}: "
api_token_input = $stdin.gets.chomp
config['jira']['api_key'] = api_token_input if !api_token_input.empty?
print "Default Jira Project Key (optional, e.g., MYPROJ) [current: #{config['jira']['default_project']}]: "
config['jira']['default_project'] = $stdin.gets.chomp.then { |val| val.empty? ? config['jira']['default_project'] : val }
puts "\n--- Privacy Settings ---"
config['privacy'] ||= {}
puts "Allow sending shell command history to the LLM? (true/false) [current: #{config['privacy']['send_shell_history']}]"
config['privacy']['send_shell_history'] = $stdin.gets.chomp.then { |val| val.empty? ? config['privacy']['send_shell_history'] : (val.downcase == 'true') }
puts "Allow sending LLM interaction history (your prompts and LLM responses) to the LLM? (true/false) [current: #{config['privacy']['send_llm_history']}]"
config['privacy']['send_llm_history'] = $stdin.gets.chomp.then { |val| val.empty? ? config['privacy']['send_llm_history'] : (val.downcase == 'true') }
puts "Allow sending current directory to the LLM? (true/false) [current: #{config['privacy']['send_current_directory']}]"
config['privacy']['send_current_directory'] = $stdin.gets.chomp.then { |val| val.empty? ? config['privacy']['send_current_directory'] : (val.downcase == 'true') }
puts "Append n2b generated commands to your shell history file? (true/false) [current: #{config['append_to_shell_history']}]"
config['append_to_shell_history'] = $stdin.gets.chomp.then { |val| val.empty? ? config['append_to_shell_history'] : (val.downcase == 'true') }
config['privacy']['append_to_shell_history'] = config['append_to_shell_history']
else config['jira'] ||= {}
config['privacy'] ||= {}
config['privacy']['send_shell_history'] = config['privacy']['send_shell_history'] || false
config['privacy']['send_llm_history'] = config['privacy']['send_llm_history'] || true config['privacy']['send_current_directory'] = config['privacy']['send_current_directory'] || true config['append_to_shell_history'] = config['append_to_shell_history'] || false
config['privacy']['append_to_shell_history'] = config['append_to_shell_history']
end
else config['jira'] ||= {} config['privacy'] ||= {}
config['privacy']['send_shell_history'] = config['privacy']['send_shell_history'] || false
config['privacy']['send_llm_history'] = config['privacy']['send_llm_history'] || true
config['privacy']['send_current_directory'] = config['privacy']['send_current_directory'] || true
config['append_to_shell_history'] = config['append_to_shell_history'] || false
config['privacy']['append_to_shell_history'] = config['append_to_shell_history']
end
validation_errors = validate_config(config)
if validation_errors.any?
puts "\n⚠️ Configuration validation warnings:"
validation_errors.each { |error| puts " - #{error}" }
puts "Configuration saved with warnings."
end
puts "\nConfiguration saved to #{CONFIG_FILE}"
FileUtils.mkdir_p(File.dirname(CONFIG_FILE)) unless File.exist?(File.dirname(CONFIG_FILE))
File.write(CONFIG_FILE, config.to_yaml)
else
config['jira'] ||= {}
config['privacy'] ||= {}
config['privacy']['send_shell_history'] = config['privacy']['send_shell_history'] || false
config['privacy']['send_llm_history'] = config['privacy']['send_llm_history'] || true
config['privacy']['send_current_directory'] = config['privacy']['send_current_directory'] || true
current_append_setting = config.key?('append_to_shell_history') ? config['append_to_shell_history'] : false
config['append_to_shell_history'] = current_append_setting
config['privacy']['append_to_shell_history'] = config['privacy']['append_to_shell_history'] || current_append_setting
end
config
end
|