summaryrefslogtreecommitdiff
path: root/internal/executor
diff options
context:
space:
mode:
Diffstat (limited to 'internal/executor')
-rw-r--r--internal/executor/gemini.go40
1 files changed, 39 insertions, 1 deletions
diff --git a/internal/executor/gemini.go b/internal/executor/gemini.go
index 67ea7dd..bf284c6 100644
--- a/internal/executor/gemini.go
+++ b/internal/executor/gemini.go
@@ -3,6 +3,7 @@ package executor
import (
"context"
"fmt"
+ "io"
"log/slog"
"os"
"os/exec"
@@ -53,6 +54,7 @@ func (r *GeminiRunner) Run(ctx context.Context, t *task.Task, e *storage.Executi
if err := os.MkdirAll(logDir, 0700); err != nil {
return fmt.Errorf("creating log dir: %w", err)
}
+
if e.StdoutPath == "" {
e.StdoutPath = filepath.Join(logDir, "stdout.log")
e.StderrPath = filepath.Join(logDir, "stderr.log")
@@ -137,7 +139,7 @@ func (r *GeminiRunner) execOnce(ctx context.Context, args []string, workingDir,
go func() {
defer wg.Done()
// Reusing parseStream as the JSONL format should be compatible
- costUSD, streamErr = parseStream(stdoutR, stdoutFile, r.Logger)
+ costUSD, streamErr = parseGeminiStream(stdoutR, stdoutFile, r.Logger)
stdoutR.Close()
}()
@@ -164,6 +166,42 @@ func (r *GeminiRunner) execOnce(ctx context.Context, args []string, workingDir,
return nil
}
+// parseGeminiStream reads streaming JSON from the gemini CLI, unwraps markdown
+// code blocks, writes the inner JSON to w, and returns (costUSD, error).
+// For now, it focuses on unwrapping and writing, not detailed parsing of cost/errors.
+func parseGeminiStream(r io.Reader, w io.Writer, logger *slog.Logger) (float64, error) {
+ fullOutput, err := io.ReadAll(r)
+ if err != nil {
+ return 0, fmt.Errorf("reading full gemini output: %w", err)
+ }
+
+ outputStr := strings.TrimSpace(string(fullOutput)) // Trim leading/trailing whitespace/newlines from the whole output
+
+ jsonContent := outputStr // Default to raw output if no markdown block is found or malformed
+ jsonStartIdx := strings.Index(outputStr, "```json")
+ if jsonStartIdx != -1 {
+ // Found "```json", now look for the closing "```"
+ jsonEndIdx := strings.LastIndex(outputStr, "```")
+ if jsonEndIdx != -1 && jsonEndIdx > jsonStartIdx {
+ // Extract content between the markdown fences.
+ jsonContent = outputStr[jsonStartIdx+len("```json"):jsonEndIdx]
+ jsonContent = strings.TrimSpace(jsonContent) // Trim again after extraction, to remove potential inner newlines
+ } else {
+ logger.Warn("Malformed markdown JSON block from Gemini (missing closing ``` or invalid structure), falling back to raw output.", "outputLength", len(outputStr))
+ }
+ } else {
+ logger.Warn("No markdown JSON block found from Gemini, falling back to raw output.", "outputLength", len(outputStr))
+ }
+
+ // Write the (possibly extracted and trimmed) JSON content to the writer.
+ _, writeErr := w.Write([]byte(jsonContent))
+ if writeErr != nil {
+ return 0, fmt.Errorf("writing extracted gemini json: %w", writeErr)
+ }
+
+ return 0, nil // For now, no cost/error parsing for Gemini stream
+}
+
func (r *GeminiRunner) buildArgs(t *task.Task, e *storage.Execution, questionFile string) []string {
// Gemini CLI uses a different command structure: gemini "instructions" [flags]