remove dead code

This commit is contained in:
Cheikh Seck committed 2026-04-11 22:14:50 +00:00
1 parent f4b6175d25
commit fc74de2b53
15 files changed
-1041

No files matched your search

-4
View File
@@ -23,7 +23,3 @@ func readClipboardText() []byte {
func readClipboardImage() []byte {
return clipboard.Read(clipboard.FmtImage)
}
func readClipboardImagePath() string {
return ""
}
-66
View File
@@ -1225,10 +1225,6 @@ func (m *mcpLog) Printf(format string, args ...interface{}) {
m.lines = append(m.lines, fmt.Sprintf(format, args...))
}
func (m *mcpLog) Print(args ...interface{}) {
m.lines = append(m.lines, fmt.Sprint(args...))
}
func (m *mcpLog) Println(args ...interface{}) {
m.lines = append(m.lines, fmt.Sprint(args...))
}
@@ -2241,68 +2237,6 @@ func formatElapsed(totalSeconds int) string {
return fmt.Sprintf("%ds", totalSeconds)
}
func parseToolCall(text string) (string, string, map[string]interface{}, bool) {
text = strings.TrimSpace(text)
if strings.HasPrefix(text, "{") {
var toolData map[string]interface{}
if err := json.Unmarshal([]byte(text), &toolData); err == nil {
if name, ok := toolData["name"].(string); ok {
args := make(map[string]interface{})
if toolArgs, ok := toolData["arguments"].(map[string]interface{}); ok {
args = toolArgs
} else if toolArgs, ok := toolData["args"].(map[string]interface{}); ok {
args = toolArgs
}
return name, name, args, true
}
}
}
lines := strings.Split(text, "\n")
for _, line := range lines {
trimmed := strings.TrimSpace(line)
lower := strings.ToLower(trimmed)
if strings.HasPrefix(lower, "call:") || strings.HasPrefix(lower, "tool_call:") || strings.HasPrefix(lower, "execute:") {
parts := strings.SplitN(trimmed, ":", 2)
if len(parts) < 2 {
continue
}
toolPart := strings.TrimSpace(parts[1])
name := ""
args := make(map[string]interface{})
if idx := strings.Index(toolPart, "("); idx > 0 {
name = strings.TrimSpace(toolPart[:idx])
argsStr := strings.Trim(toolPart[idx:], "()")
args = parseArgs(argsStr)
}
if name != "" {
return name, name, args, true
}
}
}
return "", "", nil, false
}
func parseArgs(argsStr string) map[string]interface{} {
args := make(map[string]interface{})
if argsStr == "" {
return args
}
parts := strings.Split(argsStr, ",")
for _, part := range parts {
part = strings.TrimSpace(part)
if idx := strings.Index(part, "="); idx > 0 {
key := strings.TrimSpace(part[:idx])
value := strings.TrimSpace(part[idx+1:])
value = strings.Trim(value, "\"'")
args[key] = value
}
}
return args
}
func callTool(ctx context.Context, servers []MCPServer, name string, args map[string]interface{}, timeoutSecs int, autoDenyRestrictedPaths bool) (string, error) {
//log.Println("args", args)
-7
View File
@@ -635,13 +635,6 @@ func promptTruncateRunes(s string, max int) string {
return string(runes[:max-3]) + "..."
}
func promptFormatCommitDate(t time.Time) string {
if t.IsZero() {
return ""
}
return t.Format("2006-01-02 15:04")
}
func commonPrefix(values []string) string {
if len(values) == 0 {
return ""
-234
View File
@@ -2,12 +2,10 @@ package agent
import (
"context"
"encoding/json"
"fmt"
"log"
"strings"
"sync"
"time"
"github.com/cheikh2shift/godex/internal/config"
"github.com/cheikh2shift/godex/internal/mcp"
@@ -32,14 +30,6 @@ type ToolCallResult struct {
Arguments string
}
func (t *ToolCallResult) ParseArguments() (map[string]interface{}, error) {
var result map[string]interface{}
if err := json.Unmarshal([]byte(t.Arguments), &result); err != nil {
return nil, err
}
return result, nil
}
// SendPrompt dispatches the prompt to the configured provider via the registry.
func SendPrompt(ctx context.Context, provider *config.Provider, prompt string) (string, error) {
if provider == nil {
@@ -58,26 +48,6 @@ func SendPrompt(ctx context.Context, provider *config.Provider, prompt string) (
return strings.TrimSpace(resp), nil
}
// SendPromptWithThink dispatches the prompt with a thinking callback.
func SendPromptWithThink(ctx context.Context, provider *config.Provider, prompt string, onThink func(string)) (string, error) {
if provider == nil {
return "", fmt.Errorf("no provider provided")
}
p, err := GetProvider(provider)
if err != nil {
return "", err
}
p.SetThinkCallback(onThink)
defer p.SetThinkCallback(nil)
resp, err := p.Send(ctx, prompt)
if err != nil {
return "", err
}
return strings.TrimSpace(resp), nil
}
func CancelPrompt(provider *config.Provider) {
if provider == nil {
@@ -101,33 +71,6 @@ func CancelPrompt(provider *config.Provider) {
mcpExecutorsMu.Unlock()
}
// CallTool executes an MCP tool call.
func CallTool(ctx context.Context, provider *config.Provider, toolName string, args map[string]interface{}) (string, error) {
if provider == nil {
return "", fmt.Errorf("no provider provided")
}
p, err := GetProvider(provider)
if err != nil {
return "", err
}
return p.CallTool(ctx, toolName, args)
}
// GetTools returns the available MCP tools for a provider.
func GetTools(provider *config.Provider) []providers.Tool {
if provider == nil {
return nil
}
p, err := GetProvider(provider)
if err != nil {
return nil
}
return p.Tools()
}
func SetProviderTools(provider *config.Provider, tools []providers.Tool) {
p, err := GetProvider(provider)
@@ -139,15 +82,6 @@ func SetProviderTools(provider *config.Provider, tools []providers.Tool) {
}
}
func SubmitProviderToolResult(provider *config.Provider, toolCallID, result string) {
p, err := GetProvider(provider)
if err != nil {
return
}
if pt, ok := p.(interface{ SubmitToolResult(string, string) }); ok {
pt.SubmitToolResult(toolCallID, result)
}
}
func RegisterMCPExecutor(provider *config.Provider, executor *mcp.MCPToolExecutor) {
if provider == nil || executor == nil {
@@ -213,171 +147,3 @@ func GetProvider(cfg *config.Provider) (providers.Provider, error) {
func cacheKey(cfg *config.Provider) string {
return fmt.Sprintf("%s|%s|%s|%s", cfg.Type, cfg.Name, cfg.Model, cfg.Endpoint)
}
type ToolCall struct {
ID string
Name string
Arguments map[string]interface{}
}
type ToolCallResponse struct {
ID string
Result string
Err error
}
func LaunchToolsInParallel(ctx context.Context, provider *config.Provider, toolCalls []ToolCall) []ToolCallResponse {
if len(toolCalls) == 0 {
return nil
}
providerName := "unknown"
if provider != nil {
providerName = provider.Name
}
fmt.Printf("\n")
fmt.Printf(" %s %s %s\n", "╔═══════════════════════════════════════════════════╗", "\033[1;36m🚀 LAUNCHING TOOLS IN PARALLEL\033[0m", "")
fmt.Printf(" %s %s %s\n", "║", fmt.Sprintf("\033[1;33mProvider:\033[0m %s", providerName), " ║")
fmt.Printf(" %s %s %s\n", "║", fmt.Sprintf("\033[1;33mTotal:\033[0m %d tools", len(toolCalls)), " ║")
fmt.Printf(" %s %s %s\n", "╚═══════════════════════════════════════════════════╝", " ", "")
cyan := "\033[1;36m"
green := "\033[1;32m"
yellow := "\033[1;33m"
reset := "\033[0m"
for i, tc := range toolCalls {
arrow := "➤"
argsJSON, _ := json.Marshal(tc.Arguments)
fmt.Printf(" %s %s[%d]%s %s%s%s %s%s%s\n",
arrow, cyan, i+1, reset,
green, tc.Name, reset,
yellow, string(argsJSON), reset)
}
fmt.Println()
var wg sync.WaitGroup
responses := make([]ToolCallResponse, len(toolCalls))
resultCh := make(chan struct {
index int
response ToolCallResponse
}, len(toolCalls))
startTime := time.Now()
for i, tc := range toolCalls {
wg.Add(1)
go func(index int, call ToolCall) {
defer wg.Done()
select {
case resultCh <- struct {
index int
response ToolCallResponse
}{index, ToolCallResponse{ID: call.ID, Result: "⏳ running..."}}:
default:
}
select {
case <-ctx.Done():
resultCh <- struct {
index int
response ToolCallResponse
}{index, ToolCallResponse{ID: call.ID, Err: ctx.Err()}}
return
default:
}
var result string
var err error
if provider != nil {
result, err = CallTool(ctx, provider, call.Name, call.Arguments)
} else {
err = fmt.Errorf("no provider configured")
}
response := ToolCallResponse{
ID: call.ID,
Result: result,
Err: err,
}
select {
case resultCh <- struct {
index int
response ToolCallResponse
}{index, response}:
default:
}
}(i, tc)
}
go func() {
wg.Wait()
close(resultCh)
}()
for result := range resultCh {
responses[result.index] = result.response
}
elapsed := time.Since(startTime)
fmt.Printf("\n")
fmt.Printf(" %s %s %s\n", "╔═══════════════════════════════════════════════════╗", "\033[1;32m✓ TOOLS COMPLETED\033[0m", "")
fmt.Printf(" %s %s %s\n", "║", fmt.Sprintf("\033[1;33mTime:\033[0m %v", elapsed), " ║")
fmt.Printf(" %s %s %s\n", "╚═══════════════════════════════════════════════════╝", " ", "")
for i, resp := range responses {
statusIcon := "✓"
if resp.Err != nil {
statusIcon = "✗"
}
statusColor := green
if resp.Err != nil {
statusColor = "\033[1;31m"
}
resultPreview := resp.Result
toolName := toolCalls[i].Name
if toolName == "read_image" {
// Full output for read_image
resultPreview = resp.Result
} else if toolName == "read_pdf" {
// Truncate read_pdf but with higher limit
if len(resultPreview) > 5000 {
resultPreview = resultPreview[:5000] + "\n... (truncated)"
}
} else {
// Truncate other tools
if len(resultPreview) > 2500 {
resultPreview = resultPreview[:2500] + "\n... (truncated)"
}
}
if len(resultPreview) > 60 {
resultPreview = resultPreview[:60] + "..."
}
name := toolCalls[i].Name
if len(name) > 25 {
name = name[:25] + "..."
}
fmt.Printf(" %s %s[%d]%s %s%-25s%s %s%s%s\n",
statusIcon,
cyan, i+1, reset,
statusColor, name, reset,
yellow, resultPreview, reset)
}
fmt.Println()
if ctx.Err() != nil {
fmt.Printf(" ⚠️ %s\n", ctx.Err())
}
return responses
}
-266
View File
@@ -1,266 +0,0 @@
package agent
import (
"fmt"
"strings"
projectctx "github.com/cheikh2shift/godex/internal/context"
)
const (
toolIntroFmt = `You have access to MCP tools. Use them to accomplish tasks.
You can call multiple tools in a single response to be more efficient.
To call tools, you MUST respond with one or more JSON objects, each in its own markdown code block.
Example:
` + "```" + `json
{
"name": "read_file",
"arguments": {
"path": "/absolute/path/to/file"
}
}
` + "```" + `
IMPORTANT: Execute tools FIRST, then provide the final answer. Do NOT include any final answer, summary, or "FINAL_ANSWER:" until AFTER you have executed all necessary tools and received their results. If you need to run commands/tests to verify something, run them first before answering.
If you need to start a server/service or any long-running process, you MUST use background: true and continue.
Project tree:
%s
User prompt:
%s`
toolFollowupFmt = "Tool results:\n%s\n\nPlease proceed or provide the FINAL_ANSWER if complete."
)
type ToolRequest struct {
Reads []string
Greps []projectctx.GrepRequest
Tree bool
Description string
}
func ToolIntroPrompt(prompt, tree string) string {
if strings.TrimSpace(tree) == "" {
tree = "(tree unavailable)"
}
return fmt.Sprintf(toolIntroFmt, tree, prompt)
}
func ToolFollowupPrompt(excerpts string) string {
return fmt.Sprintf(toolFollowupFmt, excerpts)
}
func ParseToolRequests(text string) (ToolRequest, bool) {
lines := strings.Split(text, "\n")
req := ToolRequest{}
for _, line := range lines {
trimmed := strings.TrimSpace(line)
lower := strings.ToLower(trimmed)
switch {
case lower == "tree":
req.Tree = true
case strings.HasPrefix(lower, "read:") || strings.HasPrefix(lower, "request:"):
parts := strings.SplitN(trimmed, ":", 2)
if len(parts) < 2 {
continue
}
req.Reads = append(req.Reads, splitList(parts[1])...)
case strings.HasPrefix(lower, "grep:"):
parts := strings.SplitN(trimmed, ":", 2)
if len(parts) < 2 {
continue
}
spec := strings.TrimSpace(parts[1])
if pattern, paths, ok := parseGrepSpec(spec); ok {
req.Greps = append(req.Greps, projectctx.GrepRequest{Pattern: pattern, Paths: paths})
continue
}
if looksLikePath(spec) {
req.Reads = append(req.Reads, spec)
}
}
}
if len(req.Reads) == 0 && len(req.Greps) == 0 && !req.Tree {
return ToolRequest{}, false
}
var descParts []string
if req.Tree {
descParts = append(descParts, "TREE")
}
if len(req.Reads) > 0 {
descParts = append(descParts, fmt.Sprintf("READ: %s", strings.Join(req.Reads, ", ")))
}
for _, grep := range req.Greps {
descParts = append(descParts, fmt.Sprintf("GREP: %s | %s", grep.Pattern, strings.Join(grep.Paths, ", ")))
}
req.Description = strings.Join(descParts, " | ")
return req, true
}
func parseGrepSpec(spec string) (string, []string, bool) {
pieces := strings.SplitN(spec, "|", 2)
if len(pieces) < 2 {
return "", nil, false
}
left := strings.TrimSpace(pieces[0])
right := strings.TrimSpace(pieces[1])
if left == "" || right == "" {
return "", nil, false
}
if looksLikePath(left) && looksLikeGrepCommand(right) {
if extracted := extractGrepPattern(right); extracted != "" {
return extracted, []string{left}, true
}
}
pattern := left
paths := filterPaths(splitList(right))
if pattern == "" || len(paths) == 0 {
return "", nil, false
}
if looksLikeGrepCommand(pattern) {
return "", nil, false
}
return pattern, paths, true
}
func looksLikePath(value string) bool {
if strings.ContainsAny(value, " \t") {
return false
}
return strings.Contains(value, "/") || strings.Contains(value, ".")
}
func looksLikeGrepCommand(value string) bool {
lower := strings.ToLower(value)
return strings.Contains(lower, "grep") || strings.Contains(lower, "rg ") || strings.Contains(lower, "ripgrep")
}
func extractGrepPattern(value string) string {
if extracted := extractQuoted(value); extracted != "" {
return extracted
}
lower := strings.ToLower(value)
if idx := strings.Index(lower, "grep"); idx >= 0 {
rest := strings.TrimSpace(value[idx+4:])
rest = strings.TrimLeft(rest, "-n ")
if rest != "" {
return strings.Fields(rest)[0]
}
}
return ""
}
func extractQuoted(value string) string {
for _, quote := range []string{"'", `"`} {
if start := strings.Index(value, quote); start >= 0 {
if end := strings.Index(value[start+1:], quote); end >= 0 {
return value[start+1 : start+1+end]
}
}
}
return ""
}
func filterPaths(paths []string) []string {
var out []string
for _, p := range paths {
if p == "" {
continue
}
if looksLikeGrepCommand(p) || strings.Contains(p, "|") {
continue
}
out = append(out, p)
}
return out
}
func ExtractCommandsFromResponse(text string) []string {
return extractCommandBlocks(text)
}
func ExtractCommandFromResponse(text string) (string, bool) {
commands := extractCommandBlocks(text)
if len(commands) == 0 {
return "", false
}
return commands[0], true
}
func extractCommandBlocks(text string) []string {
lines := strings.Split(text, "\n")
var commands []string
for i := 0; i < len(lines); i++ {
trimmed := strings.TrimSpace(lines[i])
lower := strings.ToLower(trimmed)
prefix := ""
for _, p := range []string{"run:", "command:", "execute:"} {
if strings.HasPrefix(lower, p) {
prefix = p
break
}
}
if prefix == "" {
continue
}
command := strings.TrimSpace(trimmed[len(prefix):])
if command == "" {
continue
}
marker := heredocMarker(command)
if marker == "" {
commands = append(commands, command)
continue
}
var block strings.Builder
block.WriteString(command)
block.WriteString("\n")
for j := i + 1; j < len(lines); j++ {
block.WriteString(lines[j])
block.WriteString("\n")
if strings.TrimSpace(lines[j]) == marker {
i = j
break
}
}
commands = append(commands, strings.TrimRight(block.String(), "\n"))
}
return commands
}
func heredocMarker(command string) string {
idx := strings.Index(command, "<<")
if idx == -1 {
return ""
}
rest := strings.TrimSpace(command[idx+2:])
if rest == "" {
return ""
}
fields := strings.Fields(rest)
if len(fields) == 0 {
return ""
}
marker := strings.Trim(fields[0], "'\"")
if marker == "" {
return ""
}
return marker
}
func splitList(raw string) []string {
parts := strings.Split(raw, ",")
var out []string
for _, part := range parts {
item := strings.TrimSpace(part)
if item != "" {
out = append(out, item)
}
}
return out
}
-217
View File
@@ -1,8 +1,6 @@
package context
import (
"bufio"
"fmt"
"io/fs"
"os"
"path/filepath"
@@ -13,11 +11,7 @@ import (
)
const (
maxFileSizeBytes = 200 * 1024
maxTreeLines = 500
maxSnippetBytes = 8 * 1024
maxTotalBytes = 50 * 1024
maxGrepHits = 200
treeCacheName = ".gtree"
)
@@ -87,146 +81,6 @@ func BuildTree(root string) (string, error) {
return tree, nil
}
// ResolvePaths expands requested paths/globs against the project root.
func ResolvePaths(root string, requested []string) ([]string, error) {
ig := loadGitignore(root)
wanted := map[string]struct{}{}
patterns := make([]string, 0, len(requested))
for _, entry := range requested {
entry = strings.TrimSpace(entry)
if entry == "" {
continue
}
patterns = append(patterns, filepath.ToSlash(entry))
}
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
rel, relErr := filepath.Rel(root, path)
if relErr != nil {
return relErr
}
if rel == "." {
return nil
}
slashRel := filepath.ToSlash(rel)
if shouldIgnorePath(ig, slashRel) {
if d.IsDir() {
return filepath.SkipDir
}
return nil
}
if d.IsDir() {
return nil
}
for _, pattern := range patterns {
if pattern == slashRel {
wanted[slashRel] = struct{}{}
continue
}
if strings.ContainsAny(pattern, "*?[") {
if ok, _ := filepath.Match(pattern, slashRel); ok {
wanted[slashRel] = struct{}{}
}
}
}
return nil
})
if err != nil {
return nil, err
}
results := make([]string, 0, len(wanted))
for path := range wanted {
results = append(results, path)
}
sort.Strings(results)
return results, nil
}
// ReadFiles returns file excerpts for the requested paths.
func ReadFiles(root string, paths []string) (string, error) {
var buf strings.Builder
total := 0
for _, rel := range paths {
abs := filepath.Join(root, filepath.FromSlash(rel))
info, err := os.Stat(abs)
if err != nil || info.IsDir() {
continue
}
if info.Size() > maxFileSizeBytes {
continue
}
data, err := os.ReadFile(abs)
if err != nil || isBinary(data) {
continue
}
content := string(data)
if len(content) > maxSnippetBytes {
content = content[:maxSnippetBytes]
}
entry := fmt.Sprintf("FILE: %s\n%s\n\n", rel, content)
if total+len(entry) > maxTotalBytes {
break
}
buf.WriteString(entry)
total += len(entry)
}
return strings.TrimSpace(buf.String()), nil
}
// GrepFiles searches for patterns in requested files.
func GrepFiles(root string, req GrepRequest) (string, error) {
pattern := strings.TrimSpace(req.Pattern)
if pattern == "" {
return "", nil
}
paths := req.Paths
if len(paths) == 0 {
lower := strings.ToLower(pattern)
if strings.Contains(lower, "grep") || strings.Contains(lower, "rg ") || strings.Contains(pattern, "|") {
return "", nil
}
return grepAll(root, pattern)
}
var buf strings.Builder
count := 0
for _, rel := range paths {
abs := filepath.Join(root, filepath.FromSlash(rel))
info, err := os.Stat(abs)
if err != nil || info.IsDir() {
continue
}
if info.Size() > maxFileSizeBytes {
continue
}
file, err := os.Open(abs)
if err != nil {
continue
}
scanner := bufio.NewScanner(file)
lineNo := 0
for scanner.Scan() {
lineNo++
line := scanner.Text()
if strings.Contains(line, pattern) {
buf.WriteString(fmt.Sprintf("GREP: %s:%d: %s\n", rel, lineNo, line))
count++
if count >= maxGrepHits {
break
}
}
}
_ = file.Close()
if count >= maxGrepHits {
break
}
}
return strings.TrimSpace(buf.String()), nil
}
func loadGitignore(root string) *ignore.GitIgnore {
path := filepath.Join(root, ".gitignore")
@@ -274,74 +128,3 @@ func writeTreeCache(root, tree string) error {
path := filepath.Join(root, treeCacheName)
return os.WriteFile(path, []byte(tree), 0o644)
}
func isBinary(data []byte) bool {
for _, b := range data {
if b == 0 {
return true
}
}
return false
}
func grepAll(root, pattern string) (string, error) {
ig := loadGitignore(root)
var buf strings.Builder
count := 0
err := filepath.WalkDir(root, func(path string, d fs.DirEntry, err error) error {
if err != nil {
return err
}
rel, relErr := filepath.Rel(root, path)
if relErr != nil {
return relErr
}
if rel == "." {
return nil
}
slashRel := filepath.ToSlash(rel)
if shouldIgnorePath(ig, slashRel) {
if d.IsDir() {
return filepath.SkipDir
}
return nil
}
if d.IsDir() {
return nil
}
info, infoErr := d.Info()
if infoErr != nil || info.IsDir() {
return nil
}
if info.Size() > maxFileSizeBytes {
return nil
}
file, err := os.Open(path)
if err != nil {
return nil
}
scanner := bufio.NewScanner(file)
lineNo := 0
for scanner.Scan() {
lineNo++
line := scanner.Text()
if strings.Contains(line, pattern) {
buf.WriteString(fmt.Sprintf("GREP: %s:%d: %s\n", slashRel, lineNo, line))
count++
if count >= maxGrepHits {
break
}
}
}
_ = file.Close()
if count >= maxGrepHits {
return fs.SkipAll
}
return nil
})
if err != nil && err != fs.SkipAll {
return "", err
}
return strings.TrimSpace(buf.String()), nil
}
-4
View File
@@ -17,10 +17,6 @@ import (
"time"
)
func GetWorkingDir() (string, error) {
return os.Getwd()
}
var runCmdMu sync.Mutex
// Job represents a running background job managed by a goroutine
-7
View File
@@ -137,13 +137,6 @@ func (m *MCPToolExecutor) buildArgs() []string {
return nil
}
func (m *MCPToolExecutor) buildTransport() string {
if m.server.Transport == "stdio" {
return "stdio"
}
return "stdio"
}
func listTools(ctx context.Context, mcpClient *client.Client) ([]Tool, error) {
result, err := mcpClient.ListTools(ctx, mcp.ListToolsRequest{})
if err != nil {
-13
View File
@@ -7,7 +7,6 @@ import (
"log"
"os"
"os/exec"
"path/filepath"
"runtime"
"strings"
"sync"
@@ -194,18 +193,6 @@ func StartVisionServer(ctx context.Context) error {
return EnsureOCR(ctx)
}
func checkServerHealth(url string) bool {
return false
}
func getGodexBinDir() (string, error) {
home, err := os.UserHomeDir()
if err != nil {
return "", err
}
return filepath.Join(home, ".godex", "bin"), nil
}
func DownloadVisionServer(ctx context.Context) error {
visionDebug("Attempting to install tesseract...")
-38
View File
@@ -5,7 +5,6 @@ import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"slices"
"strings"
)
@@ -96,43 +95,6 @@ type DownloadProgress struct {
Filename string
}
func DownloadProgressCallback(progress chan<- DownloadProgress) func(bytesRead int64, contentLength int64, done bool) {
return func(bytesRead int64, contentLength int64, done bool) {
if progress != nil {
progress <- DownloadProgress{
Downloaded: bytesRead,
Total: contentLength,
}
}
}
}
func GetGGUFQuantizations(ctx context.Context, modelID string) ([]string, error) {
files, err := getGGUFFiles(ctx, modelID)
if err != nil {
return nil, err
}
quants := make(map[string]string)
quantRe := regexp.MustCompile(`-([A-Za-z0-9_]+)\.gguf$`)
for _, f := range files {
matches := quantRe.FindStringSubmatch(f)
if len(matches) >= 2 {
quant := matches[1]
if _, exists := quants[quant]; !exists {
quants[quant] = f
}
}
}
result := make([]string, 0, len(quants))
for q := range quants {
result = append(result, q)
}
return result, nil
}
var quantOrder = map[string]int{
"Q2_K": 1,
"Q3_K_S": 2,
-18
View File
@@ -63,24 +63,6 @@ func TestGetDownloadURL(t *testing.T) {
}
}
func TestGetGGUFQuantizations(t *testing.T) {
ctx := context.Background()
quants, err := GetGGUFQuantizations(ctx, "Qwen/Qwen2.5-3B-Instruct-GGUF")
if err != nil {
t.Fatalf("Failed to get quantizations: %v", err)
}
if len(quants) == 0 {
t.Fatal("Expected quantizations, got none")
}
t.Logf("Found %d quantizations:", len(quants))
for _, q := range quants {
t.Logf(" - %s", q)
}
}
func TestResolveModelPathWithDownload(t *testing.T) {
t.Skip("Skipping download test - requires user input for quantization selection")
}
-42
View File
@@ -1565,45 +1565,3 @@ func (p *llamaProvider) SetModel(model string, contextLimit int) error {
return nil
}
func GetLlamaContextLimitFromModel(model string) (int, error) {
return 0, fmt.Errorf("context limit detection from model name not implemented for llama.cpp")
}
func parseModelContext(model string) int {
re := regexp.MustCompile(`-(\d+)k[_-]?ctx`)
matches := re.FindStringSubmatch(strings.ToLower(model))
if len(matches) >= 2 {
if val, err := strconv.Atoi(matches[1]); err == nil {
return val * 1000
}
}
knownModels := map[string]int{
"qwen2.5-coder": 8192,
"qwen2.5": 8192,
"qwen2": 8192,
"llama3": 8192,
"llama3.1": 128 * 1000,
"llama3.2": 128 * 1000,
"codellama": 16384,
"mistral": 32768,
"mixtral": 32768,
"phi": 4096,
"phi3": 4096,
"gemma": 8192,
"gemma2": 8192,
"stablelm": 8192,
"deepseek-coder": 16384,
"deepseek": 16384,
}
modelLower := strings.ToLower(model)
for prefix, ctx := range knownModels {
if strings.Contains(modelLower, prefix) {
return ctx
}
}
return 4096
}
-50
View File
@@ -13,33 +13,6 @@ import (
"time"
)
func TestParseModelContextFromName(t *testing.T) {
tests := []struct {
model string
expected int
}{
{"qwen2.5-coder:3b", 8192},
{"qwen2.5:7b", 8192},
{"llama3:8b", 8192},
{"mistral:7b", 32768},
{"mixtral:8x7b", 32768},
{"codellama:34b", 16384},
{"phi3:14b", 4096},
{"gemma:7b", 8192},
{"deepseek-coder:33b", 16384},
{"unknown-model", 4096},
}
for _, tt := range tests {
t.Run(tt.model, func(t *testing.T) {
result := parseModelContext(tt.model)
if result != tt.expected {
t.Errorf("parseModelContext(%q) = %d, want %d", tt.model, result, tt.expected)
}
})
}
}
func TestResolveModelPathLocal(t *testing.T) {
tests := []struct {
model string
@@ -225,29 +198,6 @@ func TestGetQuantizationDescription(t *testing.T) {
}
}
func TestModelDownloadURLIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
quants, err := GetGGUFQuantizations(ctx, "Qwen/Qwen2.5-3B-Instruct-GGUF")
if err != nil {
t.Skipf("could not fetch quantizations: %v", err)
}
if len(quants) == 0 {
t.Fatal("expected at least one quantization")
}
t.Logf("Found %d quantizations for Qwen/Qwen2.5-3B-Instruct-GGUF:", len(quants))
for _, q := range quants[:min(5, len(quants))] {
t.Logf(" - %s", q)
}
}
func TestLlamaGetGGUFFilesIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
-47
View File
@@ -367,50 +367,3 @@ func TestGetOllamaContextLimitNonexistent(t *testing.T) {
t.Error("expected error for nonexistent model, got nil")
}
}
func TestGetGGUFQuantizationsIntegration(t *testing.T) {
if testing.Short() {
t.Skip("Skipping integration test in short mode")
}
ctx, cancel := context.WithTimeout(context.Background(), 60*time.Second)
defer cancel()
tests := []struct {
modelID string
wantQuants []string
}{
{"Qwen/Qwen2.5-3B-Instruct-GGUF", []string{"Q4_K_M", "Q4_K_S", "Q5_K_M"}},
}
for _, tt := range tests {
t.Run(tt.modelID, func(t *testing.T) {
quants, err := GetGGUFQuantizations(ctx, tt.modelID)
if err != nil {
t.Skipf("failed to fetch quantizations for %s: %v", tt.modelID, err)
}
if len(quants) == 0 {
t.Error("expected at least one quantization")
}
t.Logf("Model %s: found %d quantizations", tt.modelID, len(quants))
for _, q := range quants {
t.Logf(" - %s", q)
}
for _, want := range tt.wantQuants {
found := false
for _, q := range quants {
if q == want {
found = true
break
}
}
if !found {
t.Logf("expected quantization %s not found (may be acceptable)", want)
}
}
})
}
}
-28
View File
@@ -334,21 +334,6 @@ func (p *openRouterProvider) Send(ctx context.Context, prompt string) (string, e
return "", lastErr
}
// extractUserInput extracts the actual user input from the full prompt
// by finding "User request:" or "User asked:" and returning everything after it
func extractUserInput(prompt string) string {
// Try to find "User request:" first (new format)
if idx := strings.Index(prompt, "User request:"); idx != -1 {
return strings.TrimSpace(prompt[idx+len("User request:"):])
}
// Fall back to "User asked:" (follow-up format)
if idx := strings.Index(prompt, "User asked:"); idx != -1 {
return strings.TrimSpace(prompt[idx+len("User asked:"):])
}
// Fall back to returning the whole prompt if markers not found
return prompt
}
func buildResponsesInput(messages []map[string]interface{}) []map[string]interface{} {
input := make([]map[string]interface{}, 0, len(messages))
for _, msg := range messages {
@@ -573,19 +558,6 @@ func (p *openRouterProvider) SetStatusChannel(ch chan<- string) {
p.statusCh = ch
}
func (p *openRouterProvider) sendStatus(msg string) {
p.mu.Lock()
ch := p.statusCh
p.mu.Unlock()
if ch == nil {
return
}
select {
case ch <- msg:
default:
}
}
func pickMessageContent(content, reasoning string, details []reasoningDetail) string {
candidates := []string{
content,