From 672f245053286ef874d4402c95f5af88e6649f96 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Miko=C5=82aj=20Badyl?= Date: Sat, 28 Feb 2026 22:17:54 +0100 Subject: [PATCH] fix: cleanup dead code and improve error display --- internal/cli/handlers.go | 149 ----------------------------------- internal/cli/update.go | 19 ++--- internal/cli/update_tests.go | 7 +- internal/cli/utils.go | 23 +++++- 4 files changed, 34 insertions(+), 164 deletions(-) diff --git a/internal/cli/handlers.go b/internal/cli/handlers.go index a636a32..c0c6a77 100644 --- a/internal/cli/handlers.go +++ b/internal/cli/handlers.go @@ -273,85 +273,6 @@ func (m *TestUIModel) executeTool(toolCall agent.ToolCall) tea.Cmd { } } - if toolCall.Name == agent.ToolExecuteTest { - method, _ := toolCall.Arguments["method"].(string) - endpoint, _ := toolCall.Arguments["endpoint"].(string) - - if method == "" || endpoint == "" { - return toolResultMsg{ - toolID: toolCall.ID, - toolName: toolCall.Name, - result: nil, - err: fmt.Errorf("missing required parameters: method and endpoint"), - } - } - - expectedStatus := 200 - if es, ok := toolCall.Arguments["expected_status"].(float64); ok { - expectedStatus = int(es) - } else if es, ok := toolCall.Arguments["expected_status"].(int); ok { - expectedStatus = es - } - - headers := make(map[string]string) - if h, ok := toolCall.Arguments["headers"].(map[string]any); ok { - for k, v := range h { - if vs, ok := v.(string); ok { - headers[k] = vs - } - } - } - - var body any - if b, ok := toolCall.Arguments["body"]; ok { - body = b - } - - requiresAuth := false - if ra, ok := toolCall.Arguments["requires_auth"].(bool); ok { - requiresAuth = ra - } - - result, err := m.testExecutor.ExecuteTest(method, endpoint, headers, body, requiresAuth) - - if err != nil { - return toolResultMsg{ - toolID: toolCall.ID, - toolName: toolCall.Name, - result: map[string]any{ - "method": method, - "endpoint": endpoint, - "error": err.Error(), - "expected_status": expectedStatus, - "passed": false, - }, - err: err, - } - } - - passed := result.StatusCode == expectedStatus - - schemaErrors := m.validateResponseSchema(method, endpoint, result.StatusCode, result.ResponseBody) - - return toolResultMsg{ - toolID: toolCall.ID, - toolName: toolCall.Name, - result: map[string]any{ - "method": method, - "endpoint": endpoint, - "status_code": result.StatusCode, - "expected_status": expectedStatus, - "response_body": result.ResponseBody, - "headers": result.Headers, - "duration_ms": result.Duration.Milliseconds(), - "passed": passed, - "schema_valid": len(schemaErrors) == 0, - "schema_errors": schemaErrors, - }, - err: nil, - } - } - if toolCall.Name == agent.ToolGenerateReport { reportContent, _ := toolCall.Arguments["report_content"].(string) if reportContent == "" { @@ -471,76 +392,6 @@ func (m *TestUIModel) executeTool(toolCall agent.ToolCall) tea.Cmd { } func (m *TestUIModel) handleToolResult(toolName string, toolID string, result any) tea.Cmd { - if toolName == agent.ToolExecuteTest { - if resultMap, ok := result.(map[string]any); ok { - method, _ := resultMap["method"].(string) - endpoint, _ := resultMap["endpoint"].(string) - statusCode, _ := resultMap["status_code"].(int) - expectedStatus, _ := resultMap["expected_status"].(int) - responseBody, _ := resultMap["response_body"].(string) - durationMs, _ := resultMap["duration_ms"].(int64) - - var passed bool - if p, ok := resultMap["passed"].(bool); ok { - passed = p - } else { - passed = statusCode == expectedStatus - } - - methodStyle, ok := m.methodStyles[method] - if !ok { - methodStyle = lipgloss.NewStyle().Foreground(Theme.TextSubtle) - } - methodFormatted := methodStyle.Render(method) - - statusStyle := m.successStyle - statusIcon := "✓" - if !passed { - statusStyle = m.errorStyle - statusIcon = "✗" - if m.isHeadless { - m.headlessExitCode = 1 - } - } - - statusMsg := fmt.Sprintf(" Status: %d", statusCode) - if !passed && expectedStatus > 0 { - statusMsg += fmt.Sprintf(" (expected %d)", expectedStatus) - } - statusMsg += fmt.Sprintf(" | Duration: %dms", durationMs) - - m.addMessage("") - m.addMessage(statusStyle.Render(statusIcon) + " " + methodFormatted + " " + endpoint) - m.addMessage(m.subtleStyle.Render(statusMsg)) - - if len(responseBody) > 0 { - preview := responseBody - if len(preview) > 200 { - preview = preview[:200] + "..." - } - m.addMessage(m.subtleStyle.Render(" Response: " + preview)) - } - - if toolID != "" { - chatMsg := agent.ChatMessage{ - Role: "user", - FunctionResponse: &agent.FunctionResponseData{ - ID: toolID, - Name: agent.ToolExecuteTest, - Response: resultMap, - }, - } - m.conversationHistory = append(m.conversationHistory, chatMsg) - - // Save function response to conversation - m.saveChatMessageToConversation(chatMsg) - - // Send back to agent to continue - return m.sendChatMessage("") - } - return nil // No tool_use, so don't send response back - } - } if toolName == agent.ToolExecuteTestGroup { // Display results from test group diff --git a/internal/cli/update.go b/internal/cli/update.go index b333dff..67a94d7 100644 --- a/internal/cli/update.go +++ b/internal/cli/update.go @@ -1442,13 +1442,6 @@ func handleCommandsState(m *TestUIModel, msg tea.KeyMsg) (tea.Model, tea.Cmd) { } } -// showToolWidget displays a tool execution widget with title and details. -// Deprecated: use m.showToolMessage() instead. -func showToolWidget(m *TestUIModel, title string, details string) { - m.showToolMessage(title, details) - m.updateViewport() -} - // handleProcessToolCalls executes tool calls received from the agent. func handleProcessToolCalls(m *TestUIModel, _ processToolCallsMsg) (tea.Model, tea.Cmd) { if len(m.streamedToolCalls) > 0 { @@ -1471,7 +1464,8 @@ func handleProcessToolCalls(m *TestUIModel, _ processToolCallsMsg) (tea.Model, t } } details := strings.Join(endpointsList, ", ") - showToolWidget(m, "Getting endpoint details", details) + m.showToolMessage("Getting endpoint details", details) + m.updateViewport() } return m, m.executeTool(toolCall) @@ -1532,7 +1526,8 @@ func handleProcessToolCalls(m *TestUIModel, _ processToolCallsMsg) (tea.Model, t formatCount := len(exportsArg) label := fmt.Sprintf("%d format(s)", formatCount) - showToolWidget(m, "Exporting tests", label) + m.showToolMessage("Exporting tests", label) + m.updateViewport() m.agentState = StateUsingTool m.animationFrame = 0 m.spinner.Style = lipgloss.NewStyle().Foreground(Theme.Primary) @@ -1542,7 +1537,8 @@ func handleProcessToolCalls(m *TestUIModel, _ processToolCallsMsg) (tea.Model, t m.currentTestToolID = toolCall.ID m.currentTestToolName = agent.ToolGenerateReport - showToolWidget(m, "Generating PDF report", "") + m.showToolMessage("Generating PDF report", "") + m.updateViewport() m.agentState = StateUsingTool m.animationFrame = 0 m.spinner.Style = lipgloss.NewStyle().Foreground(Theme.Primary) @@ -1563,7 +1559,8 @@ func handleProcessToolCalls(m *TestUIModel, _ processToolCallsMsg) (tea.Model, t label = fmt.Sprintf("%ds delay — %s", seconds, reason) } - showToolWidget(m, "Waiting", label) + m.showToolMessage("Waiting", label) + m.updateViewport() m.agentState = StateUsingTool m.animationFrame = 0 m.spinner.Style = lipgloss.NewStyle().Foreground(Theme.Warning) diff --git a/internal/cli/update_tests.go b/internal/cli/update_tests.go index 17e415b..af6dff8 100644 --- a/internal/cli/update_tests.go +++ b/internal/cli/update_tests.go @@ -253,8 +253,11 @@ func handleRunNextTest(m *TestUIModel, _ runNextTestMsg) (tea.Model, tea.Cmd) { } if err != nil { - m.addMessage(fmt.Sprintf(" ✗ %s %s%s", methodFormatted, endpoint, authIndicator)) - m.addMessage(m.subtleStyle.Render(fmt.Sprintf(" Error: %s", err.Error()))) + m.addMessage(fmt.Sprintf(" %s %s %s%s", m.errorStyle.Render("✗"), methodFormatted, endpoint, authIndicator)) + m.addMessage(m.subtleStyle.Render(fmt.Sprintf(" Error: %s", friendlyError(err)))) + if m.isHeadless { + m.headlessExitCode = 1 + } m.testGroupResults = append(m.testGroupResults, map[string]any{ "method": method, diff --git a/internal/cli/utils.go b/internal/cli/utils.go index 4567fd7..e601d5d 100644 --- a/internal/cli/utils.go +++ b/internal/cli/utils.go @@ -87,6 +87,27 @@ func (m *TestUIModel) recreateHeader() tea.Cmd { return nil } +// friendlyError returns a short, human-readable version of common HTTP errors. +func friendlyError(err error) string { + msg := err.Error() + if strings.Contains(msg, "connection refused") { + return "connection refused" + } + if strings.Contains(msg, "no such host") { + return "host not found" + } + if strings.Contains(msg, "i/o timeout") || strings.Contains(msg, "context deadline exceeded") { + return "request timed out" + } + if strings.Contains(msg, "certificate") || strings.Contains(msg, "x509") { + return "TLS/certificate error" + } + if strings.Contains(msg, "EOF") { + return "connection closed unexpectedly" + } + return msg +} + func (m *TestUIModel) shouldAskForConfirmation(toolName string) bool { // Tools that are safe and don't need confirmation // ExecuteTestGroup is safe - user already approved the plan via checkboxes @@ -336,8 +357,6 @@ func (m *TestUIModel) loadConversationHistory() error { displayName = "Executing tests" case agent.ToolGenerateReport: displayName = "Generating PDF report" - case agent.ToolExecuteTest: - displayName = "Executing test" default: displayName = fmt.Sprintf("Tool: %s", toolName) }