fix(analyzer): handle Claude CLI JSON array output format
Claude Code CLI outputs a JSON array instead of a single object:
[{type: "system", ...}, {type: "assistant", ...}, {type: "result", ...}]
This caused parse_json_response to fail with "jq: invalid JSON text"
because it assumed the top-level JSON was an object.
Changes:
- Detect if JSON is an array before parsing
- Extract the "result" type message from the array
- Preserve session_id from init message for continuity
- Normalize to object format for existing parsing logic
- Clean up temporary file after processing
Fixes #112
Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
parent
9b19d70e35
commit
5ce9bc81d7
3 changed files with 204 additions and 4 deletions
|
|
@ -55,12 +55,14 @@ detect_output_format() {
|
|||
|
||||
# Parse JSON response and extract structured fields
|
||||
# Creates .ralph/.json_parse_result with normalized analysis data
|
||||
# Supports TWO JSON formats:
|
||||
# Supports THREE JSON formats:
|
||||
# 1. Flat format: { status, exit_signal, work_type, files_modified, ... }
|
||||
# 2. Claude CLI format: { result, sessionId, metadata: { files_changed, has_errors, completion_status, ... } }
|
||||
# 2. Claude CLI object format: { result, sessionId, metadata: { files_changed, has_errors, completion_status, ... } }
|
||||
# 3. Claude CLI array format: [ {type: "system", ...}, {type: "assistant", ...}, {type: "result", ...} ]
|
||||
parse_json_response() {
|
||||
local output_file=$1
|
||||
local result_file="${2:-$RALPH_DIR/.json_parse_result}"
|
||||
local normalized_file=""
|
||||
|
||||
if [[ ! -f "$output_file" ]]; then
|
||||
echo "ERROR: Output file not found: $output_file" >&2
|
||||
|
|
@ -73,6 +75,29 @@ parse_json_response() {
|
|||
return 1
|
||||
fi
|
||||
|
||||
# Check if JSON is an array (Claude CLI array format)
|
||||
# Claude CLI outputs: [{type: "system", ...}, {type: "assistant", ...}, {type: "result", ...}]
|
||||
if jq -e 'type == "array"' "$output_file" >/dev/null 2>&1; then
|
||||
normalized_file=$(mktemp)
|
||||
|
||||
# Extract the "result" type message from the array (usually the last entry)
|
||||
# This contains: result, session_id, is_error, duration_ms, etc.
|
||||
local result_obj=$(jq '[.[] | select(.type == "result")] | .[-1] // {}' "$output_file" 2>/dev/null)
|
||||
|
||||
# Also extract session_id from init message if not in result object
|
||||
local init_session_id=$(jq -r '.[] | select(.type == "system" and .subtype == "init") | .session_id // empty' "$output_file" 2>/dev/null | head -1)
|
||||
|
||||
# Build normalized object merging result with session_id
|
||||
if [[ -n "$init_session_id" && "$init_session_id" != "null" ]]; then
|
||||
echo "$result_obj" | jq --arg sid "$init_session_id" '. + {sessionId: $sid}' > "$normalized_file"
|
||||
else
|
||||
echo "$result_obj" > "$normalized_file"
|
||||
fi
|
||||
|
||||
# Use normalized file for subsequent parsing
|
||||
output_file="$normalized_file"
|
||||
fi
|
||||
|
||||
# Detect JSON format by checking for Claude CLI fields
|
||||
local has_result_field=$(jq -r 'has("result")' "$output_file" 2>/dev/null)
|
||||
|
||||
|
|
@ -194,6 +219,11 @@ parse_json_response() {
|
|||
}
|
||||
}' > "$result_file"
|
||||
|
||||
# Cleanup temporary normalized file if created (for array format handling)
|
||||
if [[ -n "$normalized_file" && -f "$normalized_file" ]]; then
|
||||
rm -f "$normalized_file"
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue