@@ -222,6 +222,212 @@ func SetupOllama() {
222222 fmt .Println ()
223223}
224224
225+ // ConnectSQLite auto-detects an existing SQLite database and verifies the connection.
226+ // It reads the current config for the DB name, tests the file exists, and saves/confirms config.
227+ func ConnectSQLite () {
228+ reader := bufio .NewReader (os .Stdin )
229+ cfg := config .CurrentConfig ()
230+
231+ fmt .Println ()
232+ fmt .Printf (noticeColor , "=== Connect to Existing SQLite Database ===\n " )
233+ fmt .Println ()
234+ fmt .Println (" This will connect SCMD to an already-existing SQLite database." )
235+ fmt .Println (" The database file must exist in ~/.scmd/" )
236+ fmt .Println (" Press Enter to accept the default value shown in brackets." )
237+ fmt .Println ()
238+
239+ if cfg .DBName == "" {
240+ cfg .DBName = "scmd"
241+ }
242+ cfg .DBName = prompt (reader , "Database name (filename without .db)" , cfg .DBName )
243+
244+ if cfg .TBName == "" {
245+ cfg .TBName = "data"
246+ }
247+ cfg .TBName = prompt (reader , "Table name" , cfg .TBName )
248+
249+ if cfg .EmbeddingDim == "" {
250+ cfg .EmbeddingDim = "384"
251+ }
252+ cfg .EmbeddingDim = prompt (reader , "Embedding dimension" , cfg .EmbeddingDim )
253+
254+ // Set db_type and clear PostgreSQL-specific fields
255+ cfg .DBType = "sqlite"
256+ cfg .DBHost = ""
257+ cfg .DBPort = ""
258+ cfg .DBUser = ""
259+ cfg .DBPass = ""
260+
261+ // Derive the expected file path
262+ home , err := os .UserHomeDir ()
263+ if err != nil {
264+ fmt .Printf (errorColor , fmt .Sprintf (" Error: cannot determine home directory: %v\n " , err ))
265+ os .Exit (1 )
266+ }
267+ dbPath := home + "/.scmd/" + cfg .DBName + ".db"
268+
269+ fmt .Println ()
270+ fmt .Printf (" Checking for database file: %s\n " , dbPath )
271+
272+ if _ , err := os .Stat (dbPath ); os .IsNotExist (err ) {
273+ fmt .Printf (errorColor , fmt .Sprintf ("\n Error: database file not found: %s\n " , dbPath ))
274+ fmt .Println ()
275+ fmt .Println (" If you want to create a new SQLite database, use:" )
276+ fmt .Println (" scmd --create-db-sqlite" )
277+ fmt .Println ()
278+ os .Exit (1 )
279+ }
280+ fmt .Printf (successColor , " ✓ Database file found.\n " )
281+
282+ // Save config
283+ fmt .Println ()
284+ fmt .Printf (noticeColor , "Saving configuration...\n " )
285+ if err := config .SaveConfig (cfg ); err != nil {
286+ fmt .Printf (errorColor , fmt .Sprintf ("Error saving config: %v\n " , err ))
287+ os .Exit (1 )
288+ }
289+ fmt .Printf (successColor , fmt .Sprintf (" ✓ Config saved to %s\n " , config .ConfigFilePath ()))
290+
291+ // Reload and verify connection
292+ config .LoadConfig ()
293+ fmt .Println ()
294+ fmt .Printf (noticeColor , "Verifying connection...\n " )
295+ if err := database .InitDB (); err != nil {
296+ fmt .Printf (errorColor , fmt .Sprintf (" ✗ Could not connect: %v\n " , err ))
297+ os .Exit (1 )
298+ }
299+ database .CloseDB ()
300+
301+ fmt .Println ()
302+ fmt .Printf (successColor , "=== SQLite Connection Configured ===\n " )
303+ fmt .Println ()
304+ fmt .Printf (" Database file: %s\n " , dbPath )
305+ fmt .Printf (" Table name: %s\n " , cfg .TBName )
306+ fmt .Println ()
307+ fmt .Println (" You can now run scmd normally." )
308+ fmt .Println ()
309+ }
310+
311+ // ConnectPostgreSQL runs an interactive wizard to connect to an existing PostgreSQL database.
312+ // It prompts for all connection details step-by-step, tests the connection, and saves config.
313+ func ConnectPostgreSQL () {
314+ reader := bufio .NewReader (os .Stdin )
315+ cfg := config .CurrentConfig ()
316+
317+ fmt .Println ()
318+ fmt .Printf (noticeColor , "=== Connect to Existing PostgreSQL Database ===\n " )
319+ fmt .Println ()
320+ fmt .Println (" This will configure SCMD to connect to an already-existing PostgreSQL database." )
321+ fmt .Println (" The database and table must already exist." )
322+ fmt .Println (" Press Enter to accept the default value shown in brackets." )
323+ fmt .Println ()
324+
325+ // Step 1: host
326+ if cfg .DBHost == "" {
327+ cfg .DBHost = "localhost"
328+ }
329+ fmt .Printf (noticeColor , " Step 1 of 7: Database host\n " )
330+ cfg .DBHost = prompt (reader , "Host" , cfg .DBHost )
331+ fmt .Println ()
332+
333+ // Step 2: port
334+ if cfg .DBPort == "" {
335+ cfg .DBPort = "5432"
336+ }
337+ fmt .Printf (noticeColor , " Step 2 of 7: Database port\n " )
338+ cfg .DBPort = prompt (reader , "Port" , cfg .DBPort )
339+ fmt .Println ()
340+
341+ // Step 3: user
342+ fmt .Printf (noticeColor , " Step 3 of 7: Database user\n " )
343+ cfg .DBUser = prompt (reader , "User" , cfg .DBUser )
344+ fmt .Println ()
345+
346+ // Step 4: password
347+ fmt .Printf (noticeColor , " Step 4 of 7: Database password\n " )
348+ cfg .DBPass = promptPassword (reader , "Password" , cfg .DBPass )
349+ fmt .Println ()
350+
351+ // Step 5: database name
352+ if cfg .DBName == "" {
353+ cfg .DBName = "scmd"
354+ }
355+ fmt .Printf (noticeColor , " Step 5 of 7: Database name\n " )
356+ cfg .DBName = prompt (reader , "Database name" , cfg .DBName )
357+ fmt .Println ()
358+
359+ // Step 6: table name
360+ if cfg .TBName == "" {
361+ cfg .TBName = "data"
362+ }
363+ fmt .Printf (noticeColor , " Step 6 of 7: Table name\n " )
364+ cfg .TBName = prompt (reader , "Table name" , cfg .TBName )
365+ fmt .Println ()
366+
367+ // Step 7: embedding dimension
368+ if cfg .EmbeddingDim == "" {
369+ cfg .EmbeddingDim = "384"
370+ }
371+ fmt .Printf (noticeColor , " Step 7 of 7: Embedding dimension\n " )
372+ cfg .EmbeddingDim = prompt (reader , "Embedding dimension" , cfg .EmbeddingDim )
373+ fmt .Println ()
374+
375+ // Set db_type
376+ cfg .DBType = "postgresql"
377+
378+ // Summary before saving
379+ fmt .Println ()
380+ fmt .Printf (noticeColor , " Connection summary:\n " )
381+ fmt .Printf (" Host: %s\n " , cfg .DBHost )
382+ fmt .Printf (" Port: %s\n " , cfg .DBPort )
383+ fmt .Printf (" User: %s\n " , cfg .DBUser )
384+ fmt .Printf (" Password: ****\n " )
385+ fmt .Printf (" Database: %s\n " , cfg .DBName )
386+ fmt .Printf (" Table: %s\n " , cfg .TBName )
387+ fmt .Printf (" Emb. dim: %s\n " , cfg .EmbeddingDim )
388+ fmt .Println ()
389+
390+ confirm := prompt (reader , "Save and test this connection? (yes/no)" , "yes" )
391+ if confirm != "yes" && confirm != "y" {
392+ fmt .Printf (errorColor , " Cancelled. No changes were saved.\n " )
393+ fmt .Println ()
394+ os .Exit (0 )
395+ }
396+
397+ // Save config
398+ fmt .Println ()
399+ fmt .Printf (noticeColor , "Saving configuration...\n " )
400+ if err := config .SaveConfig (cfg ); err != nil {
401+ fmt .Printf (errorColor , fmt .Sprintf (" Error saving config: %v\n " , err ))
402+ os .Exit (1 )
403+ }
404+ fmt .Printf (successColor , fmt .Sprintf (" ✓ Config saved to %s\n " , config .ConfigFilePath ()))
405+
406+ // Reload and test connection
407+ config .LoadConfig ()
408+ fmt .Println ()
409+ fmt .Printf (noticeColor , "Testing connection...\n " )
410+ if err := database .InitDB (); err != nil {
411+ fmt .Printf (errorColor , fmt .Sprintf (" ✗ Connection failed: %v\n " , err ))
412+ fmt .Println ()
413+ fmt .Println (" Check your credentials and ensure the PostgreSQL server is reachable." )
414+ fmt .Println (" Config has been saved — re-run this command to update it." )
415+ fmt .Println ()
416+ os .Exit (1 )
417+ }
418+ database .CloseDB ()
419+
420+ fmt .Println ()
421+ fmt .Printf (successColor , "=== PostgreSQL Connection Configured ===\n " )
422+ fmt .Println ()
423+ fmt .Printf (" Host: %s:%s\n " , cfg .DBHost , cfg .DBPort )
424+ fmt .Printf (" Database: %s\n " , cfg .DBName )
425+ fmt .Printf (" Table: %s\n " , cfg .TBName )
426+ fmt .Println ()
427+ fmt .Println (" You can now run scmd normally." )
428+ fmt .Println ()
429+ }
430+
225431// SetupGemini runs the interactive Gemini AI server setup wizard.
226432func SetupGemini () {
227433 reader := bufio .NewReader (os .Stdin )
0 commit comments