diff --git a/packages/tui/internal/app/app.go b/packages/tui/internal/app/app.go index c753c335..d79cecb8 100644 --- a/packages/tui/internal/app/app.go +++ b/packages/tui/internal/app/app.go @@ -110,8 +110,12 @@ func New( slog.Debug("Loaded config", "config", configInfo) - // Create commands client - assuming server runs on same host with port 3000 - commandsClient := commands.NewCommandsClient("http://localhost:3000") + // Create commands client using the same base URL as the HTTP client + baseURL := os.Getenv("OPENCODE_SERVER") + if baseURL == "" { + baseURL = "http://localhost:4096" // Default fallback + } + commandsClient := commands.NewCommandsClient(baseURL) app := &App{ Info: appInfo, diff --git a/packages/tui/internal/commands/client.go b/packages/tui/internal/commands/client.go index 73e6bad7..b3c8d5a6 100644 --- a/packages/tui/internal/commands/client.go +++ b/packages/tui/internal/commands/client.go @@ -56,7 +56,7 @@ func NewCommandsClient(baseURL string) *CommandsClient { // ListCustomCommands fetches all available custom commands from the server func (c *CommandsClient) ListCustomCommands(ctx context.Context) ([]CustomCommand, error) { - url := fmt.Sprintf("%s/commands", c.baseURL) + url := fmt.Sprintf("%scommands", c.baseURL) req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { @@ -83,7 +83,7 @@ func (c *CommandsClient) ListCustomCommands(ctx context.Context) ([]CustomComman // GetCustomCommand fetches a specific custom command from the server func (c *CommandsClient) GetCustomCommand(ctx context.Context, name string) (*CustomCommand, error) { - url := fmt.Sprintf("%s/commands/%s", c.baseURL, name) + url := fmt.Sprintf("%scommands/%s", c.baseURL, name) req, err := http.NewRequestWithContext(ctx, "GET", url, nil) if err != nil { @@ -114,7 +114,7 @@ func (c *CommandsClient) GetCustomCommand(ctx context.Context, name string) (*Cu // ExecuteCustomCommand executes a custom command on the server func (c *CommandsClient) ExecuteCustomCommand(ctx context.Context, name string, arguments *string) (*ExecuteCommandResponse, error) { - url := fmt.Sprintf("%s/commands/%s/execute", c.baseURL, name) + url := fmt.Sprintf("%scommands/%s/execute", c.baseURL, name) reqBody := ExecuteCommandRequest{ Arguments: arguments, diff --git a/packages/tui/internal/commands/command.go b/packages/tui/internal/commands/command.go index 32126686..34440199 100644 --- a/packages/tui/internal/commands/command.go +++ b/packages/tui/internal/commands/command.go @@ -314,9 +314,9 @@ func IsValidCustomCommand(commandName string, configPath string) bool { return false } -// IsValidCustomCommandWithClient checks if a custom command exists via server or filesystem +// IsValidCustomCommandWithClient checks if a custom command exists via server func IsValidCustomCommandWithClient(commandName string, configPath string, client *CommandsClient) bool { - // Try server first if client is available + // Use server endpoint if client is available if client != nil { ctx := context.Background() exists, err := client.CustomCommandExists(ctx, commandName) @@ -325,8 +325,8 @@ func IsValidCustomCommandWithClient(commandName string, configPath string, clien } } - // Fallback to local filesystem check - return IsValidCustomCommand(commandName, configPath) + // Return false if server is not available or returns an error + return false } func LoadFromConfig(config *opencode.Config) CommandRegistry { diff --git a/packages/tui/internal/completions/commands.go b/packages/tui/internal/completions/commands.go index 1750625d..bfbe2c25 100644 --- a/packages/tui/internal/completions/commands.go +++ b/packages/tui/internal/completions/commands.go @@ -1,13 +1,12 @@ package completions import ( - "bufio" "context" - "io/fs" - "os" + "fmt" + "log/slog" "path/filepath" - "regexp" "sort" + "strconv" "strings" "github.com/charmbracelet/lipgloss/v2" @@ -66,98 +65,29 @@ func getCustomCommandCompletionItem(cmd CustomCommandFile, space int, t theme.Th }) } -// parseMarkdownMetadata extracts description from markdown frontmatter or first heading -func parseMarkdownMetadata(filePath string) string { - file, err := os.Open(filePath) - if err != nil { - return "" - } - defer file.Close() - - scanner := bufio.NewScanner(file) - - // Check for YAML frontmatter - if scanner.Scan() { - firstLine := strings.TrimSpace(scanner.Text()) - if firstLine == "---" { - // Parse YAML frontmatter - descriptionRegex := regexp.MustCompile(`(?i)^description:\s*(.+)$`) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if line == "---" { - break - } - if matches := descriptionRegex.FindStringSubmatch(line); len(matches) > 1 { - return strings.Trim(matches[1], `"'`) - } - } - } else { - // Check if first line is a heading and use it as description - if strings.HasPrefix(firstLine, "#") { - return strings.TrimSpace(strings.TrimLeft(firstLine, "#")) - } - } - } - - // If no frontmatter, look for first heading - file.Seek(0, 0) - scanner = bufio.NewScanner(file) - for scanner.Scan() { - line := strings.TrimSpace(scanner.Text()) - if strings.HasPrefix(line, "#") { - return strings.TrimSpace(strings.TrimLeft(line, "#")) - } - // Stop at first non-empty, non-comment line - if line != "" && !strings.HasPrefix(line, "