summaryrefslogtreecommitdiff
path: root/internal/executor/classifier.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/executor/classifier.go')
-rw-r--r--internal/executor/classifier.go43
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