diff options
Diffstat (limited to 'internal/executor/classifier.go')
| -rw-r--r-- | internal/executor/classifier.go | 43 |
1 files changed, 35 insertions, 8 deletions
diff --git a/internal/executor/classifier.go b/internal/executor/classifier.go index 79ebc27..28581ea 100644 --- a/internal/executor/classifier.go +++ b/internal/executor/classifier.go @@ -39,14 +39,14 @@ Claude: - claude-3-5-haiku-20241022 (fast, cheap) Gemini: -- gemini-2.0-flash-lite (fastest, most efficient, best for simple tasks) -- gemini-2.0-flash (fast, multimodal) +- gemini-2.5-flash-lite (fastest, most efficient, best for simple tasks) +- gemini-3-flash-preview (fast, multimodal) - gemini-1.5-flash (fast, balanced) - gemini-1.5-pro (more powerful, larger context) Selection Criteria: - Agent: Prefer the one with least running tasks and no active rate limit. -- Model: Select based on task complexity. Use powerful models (opus, pro) for complex reasoning/coding, flash-lite/flash/haiku for simple tasks. +- Model: Select based on task complexity. Use powerful models (opus, pro, pro-preview) for complex reasoning/coding, flash-lite/flash/haiku for simple tasks. Task: Name: %s @@ -81,7 +81,7 @@ func (c *Classifier) Classify(ctx context.Context, taskName, instructions string // Use a minimal model for classification to be fast and cheap. args := []string{ "--prompt", prompt, - "--model", "gemini-2.0-flash-lite", + "--model", "gemini-2.5-flash-lite", "--output-format", "json", } @@ -94,15 +94,42 @@ func (c *Classifier) Classify(ctx context.Context, taskName, instructions string return nil, fmt.Errorf("classifier failed: %w", err) } - var cls Classification - // Gemini might wrap the JSON in markdown code blocks. - cleanOut := strings.TrimSpace(string(out)) + // 1. Parse the JSON envelope from the gemini CLI. + var cliOut struct { + Response string `json:"response"` + } + if err := json.Unmarshal(out, &cliOut); err != nil { + // If it's not JSON, it might be raw text (though we requested JSON). + // This can happen if the CLI prints "Loaded cached credentials" or other info. + cliOut.Response = string(out) + } + + // 2. Extract the model response from the "response" field if present. + // If it was already raw text, cliOut.Response will have it. + cleanOut := strings.TrimSpace(cliOut.Response) + + // 3. Clean up "Loaded cached credentials" or other noise that might be in the string + // if we fell back to string(out). + if strings.Contains(cleanOut, "Loaded cached credentials.") { + lines := strings.Split(cleanOut, "\n") + var modelLines []string + for _, line := range lines { + if !strings.Contains(line, "Loaded cached credentials.") { + modelLines = append(modelLines, line) + } + } + cleanOut = strings.TrimSpace(strings.Join(modelLines, "\n")) + } + + // 4. Gemini might wrap the JSON in markdown code blocks. cleanOut = strings.TrimPrefix(cleanOut, "```json") + cleanOut = strings.TrimPrefix(cleanOut, "```") // fallback cleanOut = strings.TrimSuffix(cleanOut, "```") cleanOut = strings.TrimSpace(cleanOut) + var cls Classification if err := json.Unmarshal([]byte(cleanOut), &cls); err != nil { - return nil, fmt.Errorf("failed to parse classification JSON: %w\nOutput: %s", err, cleanOut) + return nil, fmt.Errorf("failed to parse classification JSON: %w\nOriginal Output: %s\nCleaned Output: %s", err, string(out), cleanOut) } return &cls, nil |
