claudetool/bash: include partial output when command times out

Co-Authored-By: sketch <hello@sketch.dev>
Change-ID: s829d2dbdfda28988k
diff --git a/claudetool/bash.go b/claudetool/bash.go
index f3f0491..adbd12c 100644
--- a/claudetool/bash.go
+++ b/claudetool/bash.go
@@ -138,7 +138,12 @@
 
 	// For foreground commands, use executeBash
 	out, execErr := executeBash(ctx, req)
+	// If there's a timeout error, we still want to return the partial output
 	if execErr != nil {
+		if out != "" && strings.Contains(execErr.Error(), "timed out") {
+			// Return both the partial output and the error
+			return llm.TextContent(out), execErr
+		}
 		return nil, execErr
 	}
 	return llm.TextContent(out), nil
@@ -182,7 +187,13 @@
 	close(done)
 
 	if execCtx.Err() == context.DeadlineExceeded {
-		return "", fmt.Errorf("command timed out after %s", req.timeout())
+		// Get the partial output that was captured before the timeout
+		partialOutput := output.String()
+		// Truncate if the output is too large
+		if len(partialOutput) > maxBashOutputLength {
+			partialOutput = partialOutput[:maxBashOutputLength] + "\n[output truncated due to size]\n"
+		}
+		return partialOutput, fmt.Errorf("command timed out after %s - partial output included", req.timeout())
 	}
 	longOutput := output.Len() > maxBashOutputLength
 	var outstr string