Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions cmd/grpc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,12 +88,8 @@ var grpcTestCmd = &cobra.Command{
fmt.Println("\nStep 5: Testing gRPC connection...")
tlsCreds := credentials.NewTLS(tlsCfg)

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

grpcConn, err := grpc.DialContext(ctx, grpcAddr,
grpcConn, err := grpc.NewClient(grpcAddr,
grpc.WithTransportCredentials(tlsCreds),
grpc.WithBlock(),
)
if err != nil {
fmt.Printf("❌ gRPC dial failed: %v\n", err)
Expand Down
29 changes: 0 additions & 29 deletions cmd/seed_dev.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,3 @@
//go:build dev

package cmd

import (
"seedfast/cli/internal/manifest"

"github.com/pterm/pterm"
)

// showEndpointIndicators displays visual indicators for endpoint sources in dev builds.
// Shows [PROD] if using production endpoints, or [CUSTOM] if using custom build-time endpoints.
func showEndpointIndicators() {
if manifest.CustomBackendURL != "" || manifest.CustomGrpcURL != "" {
// Custom endpoints - at least one build-time variable is set
pterm.Println(pterm.NewStyle(pterm.FgYellow, pterm.Bold).Sprint("[CUSTOM]") +
pterm.NewStyle(pterm.FgYellow).Sprint(" Using custom endpoints:"))

if manifest.CustomBackendURL != "" {
pterm.Printf(" → Backend: %s\n", manifest.CustomBackendURL)
}
if manifest.CustomGrpcURL != "" {
pterm.Printf(" → gRPC: %s\n", manifest.CustomGrpcURL)
}
pterm.Println()
} else {
// Production endpoints - both build-time variables are empty
pterm.Println(pterm.NewStyle(pterm.FgGreen, pterm.Bold).Sprint("[PROD]") +
pterm.NewStyle(pterm.FgGreen).Sprint(" Using production endpoints"))
pterm.Println()
}
}
6 changes: 0 additions & 6 deletions cmd/seed_prod.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,3 @@
//go:build !dev

package cmd

// showEndpointIndicators is a no-op in production builds.
// No visual indicators are shown for endpoint sources.
func showEndpointIndicators() {
// No-op in production builds
}
6 changes: 0 additions & 6 deletions cmd/seed_tui_prod.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,3 @@
//go:build !dev

package cmd

// isTUIOutputMode always returns false in production builds.
// The TUI renderer is only available in dev builds.
func isTUIOutputMode() bool {
return false
}
4 changes: 2 additions & 2 deletions cmd/tuidemo/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,7 @@ func runInteractive(p *tea.Program) {
for _, ts := range tables {
p.Send(tui.TableStartedMsg{Name: ts.Name, Remaining: len(tables)})
sleep(randMs(800, 1500))
p.Send(tui.TableDoneMsg{Name: ts.Name, RecordsCount: ts.RecordsCount})
p.Send(tui.TableDoneMsg(ts))
}

sleep(300)
Expand Down Expand Up @@ -303,7 +303,7 @@ func sendSeedingFlow(p *tea.Program, tables []tui.TableSpec, failures map[string
if reason, failed := failures[ts.Name]; failed {
p.Send(tui.TableFailedMsg{Name: ts.Name, Reason: reason})
} else {
p.Send(tui.TableDoneMsg{Name: ts.Name, RecordsCount: ts.RecordsCount})
p.Send(tui.TableDoneMsg(ts))
}
}

Expand Down
56 changes: 0 additions & 56 deletions cmd/ui_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,59 +2,3 @@
// Licensed under the MIT License. See LICENSE file in the project root for details.

package cmd

import (
"fmt"
"io"
"sync"
"time"
)

// startInlineSpinner starts a simple inline spinner animation on a single line.
// It displays rotating animation frames followed by the provided text, updating
// the same line in the terminal. The spinner runs in a separate goroutine and
// can be stopped by calling the returned function.
//
// The spinner automatically clears the line when stopped and handles text length
// limits to prevent display issues. It uses the provided frames array for animation
// and updates at the specified interval.
//
// Parameters:
// - w: The io.Writer to write the spinner to (typically os.Stdout or os.Stderr)
// - text: The text to display after the spinner animation
// - frames: Array of strings representing animation frames (e.g., ["|", "/", "-", "\\"])
// - interval: Time duration between frame updates
//
// Returns a function that stops the spinner and cleans up when called.
func startInlineSpinner(w io.Writer, text string, frames []string, interval time.Duration) func() {
stop := make(chan struct{})
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
i := 0
ticker := time.NewTicker(interval)
defer ticker.Stop()
for {
select {
case <-stop:
line := fmt.Sprintf("%s %s", frames[i%len(frames)], text)
// Clear the spinner line completely, then return
fmt.Fprintf(w, "\r%*s\r", len(line), "")
return
case <-ticker.C:
line := fmt.Sprintf("%s %s", frames[i%len(frames)], text)
fmt.Fprintf(w, "\r%s", line)
// primitive protection against very long lines
if len(line) > 2000 {
line = line[:2000]
}
i++
}
}
}()
return func() {
close(stop)
wg.Wait()
}
}
2 changes: 1 addition & 1 deletion internal/dsn/postgres.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ func (r *PostgreSQLResolver) Parse(dsn string) (*DSNInfo, error) {

// Detect scheme (postgres:// or postgresql://)
scheme := ""
remainder := dsn
var remainder string
if strings.HasPrefix(dsn, "postgresql://") {
scheme = "postgresql"
remainder = strings.TrimPrefix(dsn, "postgresql://")
Expand Down
12 changes: 6 additions & 6 deletions internal/mcpserver/handlers.go
Original file line number Diff line number Diff line change
Expand Up @@ -433,7 +433,7 @@ func (s *Server) updateRunFromEvent(ctx context.Context, run *store.Run, event u
ElapsedMs: elapsedMs,
}
if run.Summary.Failures == nil && failedTables > 0 {
// Preserve existing failures
run.Summary.Failures = make(map[string]string) // TODO: Preserve existing failures from prior summary
}
}

Expand Down Expand Up @@ -480,7 +480,7 @@ func (s *Server) toolRunStatus(ctx context.Context, args json.RawMessage) (CallT
sb.WriteString(fmt.Sprintf("Completed: %s\n", run.CompletedAt.Format(time.RFC3339)))
}

sb.WriteString(fmt.Sprintf("\nProgress:\n"))
sb.WriteString("\nProgress:\n")
sb.WriteString(fmt.Sprintf(" Tables: %d/%d (%.1f%%)\n",
run.Progress.CompletedTables, run.Progress.TotalTables, run.Progress.Percent))
sb.WriteString(fmt.Sprintf(" Rows: %d\n", run.Progress.TotalRows))
Expand All @@ -496,7 +496,7 @@ func (s *Server) toolRunStatus(ctx context.Context, args json.RawMessage) (CallT
}

if run.Summary != nil {
sb.WriteString(fmt.Sprintf("\nSummary:\n"))
sb.WriteString("\nSummary:\n")
sb.WriteString(fmt.Sprintf(" Success: %v\n", run.Summary.Success))
sb.WriteString(fmt.Sprintf(" Total Tables: %d\n", run.Summary.TotalTables))
sb.WriteString(fmt.Sprintf(" Succeeded: %d\n", run.Summary.SuccessTables))
Expand Down Expand Up @@ -561,7 +561,7 @@ func (s *Server) toolRunCancel(ctx context.Context, args json.RawMessage) (CallT
// toolPlansList lists all seeding plans in current session.
func (s *Server) toolPlansList(ctx context.Context, args json.RawMessage) (CallToolResult, error) {
var input plansListInput
if args != nil && len(args) > 0 {
if len(args) > 0 {
if err := json.Unmarshal(args, &input); err != nil {
return CallToolResult{}, fmt.Errorf("invalid arguments: %w", err)
}
Expand Down Expand Up @@ -672,7 +672,7 @@ func (s *Server) toolPlanCreate(ctx context.Context, args json.RawMessage) (Call
}

var sb strings.Builder
sb.WriteString(fmt.Sprintf("Plan created successfully\n"))
sb.WriteString("Plan created successfully\n")
sb.WriteString(fmt.Sprintf("Plan ID: %s\n", plan.ID))
sb.WriteString(fmt.Sprintf("Scope: %s\n", plan.Scope))
sb.WriteString(fmt.Sprintf("Tables (%d): %s\n", len(plan.Tables), strings.Join(plan.Tables, ", ")))
Expand Down Expand Up @@ -721,7 +721,7 @@ func (s *Server) toolPlanUpdate(ctx context.Context, args json.RawMessage) (Call
}

var sb strings.Builder
sb.WriteString(fmt.Sprintf("Plan updated successfully\n"))
sb.WriteString("Plan updated successfully\n")
sb.WriteString(fmt.Sprintf("Plan ID: %s\n", plan.ID))
sb.WriteString(fmt.Sprintf("Scope: %s\n", plan.Scope))
sb.WriteString(fmt.Sprintf("Tables (%d): %s\n", len(plan.Tables), strings.Join(plan.Tables, ", ")))
Expand Down
2 changes: 1 addition & 1 deletion internal/orchestration/auth_validator.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ func outputAuthError(message, hint, errorCode string) {
Message: message + ". " + hint,
Code: errorCode,
})
json.NewEncoder(os.Stdout).Encode(event)
_ = json.NewEncoder(os.Stdout).Encode(event)
} else {
fmt.Println("🔐 " + message)
fmt.Println(" " + hint)
Expand Down
16 changes: 8 additions & 8 deletions internal/orchestration/event_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ func (eh *EventHandler) handleStreamError(ev seeding.Event) {
// Stop UI immediately
eh.headerSpinner.Stop()
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand All @@ -262,7 +262,7 @@ func (eh *EventHandler) handleStreamError(ev seeding.Event) {
// Stop UI immediately
eh.headerSpinner.Stop()
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand All @@ -282,7 +282,7 @@ func (eh *EventHandler) handleStreamError(ev seeding.Event) {
// Stop UI immediately and notify
// no prep spinner in the new UI
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand Down Expand Up @@ -322,7 +322,7 @@ func (eh *EventHandler) handleSubscriptionBlocked(ev seeding.Event) {
// Stop UI immediately
eh.headerSpinner.Stop()
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand All @@ -345,7 +345,7 @@ func (eh *EventHandler) handleStreamClosed(ev seeding.Event) {

// no prep spinner in the new UI
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand Down Expand Up @@ -393,7 +393,7 @@ func (eh *EventHandler) handlePlanProposed(ev seeding.Event) error {

// Replan/reset UI
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
eh.stopArea()
Expand Down Expand Up @@ -493,7 +493,7 @@ func (eh *EventHandler) handleAskHuman(ev seeding.Event) error {

// If we were already planning, stop that spinner before showing a new question
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}

Expand Down Expand Up @@ -682,7 +682,7 @@ func (eh *EventHandler) handleTableStarted(ev seeding.Event) error {
if eh.state.AwaitingDecision {
eh.state.AwaitingDecision = false
if eh.state.PlanningActive && eh.state.PlanSpinner != nil {
eh.state.PlanSpinner.Stop()
_ = eh.state.PlanSpinner.Stop()
eh.state.PlanningActive = false
}
}
Expand Down
7 changes: 0 additions & 7 deletions internal/orchestration/prompt_runner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package orchestration

import (
"context"
"errors"
"strings"
"time"

Expand All @@ -21,12 +20,6 @@ type promptResult struct {
TimedOut bool
}

// Errors returned by RunPrompt.
var (
errPromptCancelled = errors.New("prompt cancelled by user")
errPromptTimeout = errors.New("prompt input timeout")
)

// PromptConfig configures a standalone prompt run.
type PromptConfig struct {
QuestionID string
Expand Down
Loading