Skip to content

Commit 90677d0

Browse files
committed
fix: parse Codex JSONL responses in Ralph loop (#89)
1 parent 208c2eb commit 90677d0

15 files changed

Lines changed: 778 additions & 189 deletions

ralph/drivers/claude-code.sh

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,49 @@ driver_supports_sessions() {
112112
return 0 # true
113113
}
114114

115-
# Stream filter for live output (jq filter for JSON streaming)
115+
# Claude Code supports stream-json live output.
116+
driver_supports_live_output() {
117+
return 0 # true
118+
}
119+
120+
# Prepare command arguments for live stream-json output.
121+
driver_prepare_live_command() {
122+
LIVE_CMD_ARGS=()
123+
local skip_next=false
124+
125+
for arg in "${CLAUDE_CMD_ARGS[@]}"; do
126+
if [[ "$skip_next" == "true" ]]; then
127+
LIVE_CMD_ARGS+=("stream-json")
128+
skip_next=false
129+
elif [[ "$arg" == "--output-format" ]]; then
130+
LIVE_CMD_ARGS+=("$arg")
131+
skip_next=true
132+
else
133+
LIVE_CMD_ARGS+=("$arg")
134+
fi
135+
done
136+
137+
if [[ "$skip_next" == "true" ]]; then
138+
return 1
139+
fi
140+
141+
LIVE_CMD_ARGS+=("--verbose" "--include-partial-messages")
142+
}
143+
144+
# Stream filter for raw Claude stream-json events.
116145
driver_stream_filter() {
117-
echo '.content // empty | select(type == "string")'
146+
echo '
147+
if .type == "stream_event" then
148+
if .event.type == "content_block_delta" and .event.delta.type == "text_delta" then
149+
.event.delta.text
150+
elif .event.type == "content_block_start" and .event.content_block.type == "tool_use" then
151+
"\n\n⚡ [" + .event.content_block.name + "]\n"
152+
elif .event.type == "content_block_stop" then
153+
"\n"
154+
else
155+
empty
156+
end
157+
else
158+
empty
159+
end'
118160
}

ralph/drivers/codex.sh

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,16 @@ driver_supports_sessions() {
7575
return 0 # true - Codex supports session resume
7676
}
7777

78+
# Codex JSONL output is already suitable for live display.
79+
driver_supports_live_output() {
80+
return 0 # true
81+
}
82+
83+
driver_prepare_live_command() {
84+
LIVE_CMD_ARGS=("${CLAUDE_CMD_ARGS[@]}")
85+
}
86+
7887
# Codex outputs JSONL events
7988
driver_stream_filter() {
80-
echo 'select(.type == "message") | .content // empty'
89+
echo 'select(.type == "item.completed" and .item.type == "agent_message") | (.item.text // ([.item.content[]? | select(.type == "output_text") | .text] | join("\n")) // empty)'
8190
}

ralph/drivers/copilot.sh

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,11 @@ driver_supports_sessions() {
8282
return 1 # false — session IDs not capturable from -p output
8383
}
8484

85+
# Copilot CLI does not expose structured live output for jq streaming.
86+
driver_supports_live_output() {
87+
return 1 # false
88+
}
89+
8590
# Copilot CLI outputs plain text only (no JSON streaming).
8691
# Passthrough filter — no transformation needed.
8792
driver_stream_filter() {

ralph/drivers/cursor.sh

Lines changed: 10 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
# Known limitations:
66
# - CLI is in beta — binary name and flags may change
77
# - NDJSON stream format assumes {type: "text", content: "..."} events
8-
# - Session ID capture from output not yet validated
8+
# - Session continuity is disabled until Cursor exposes a stable capturable session ID
99

1010
driver_name() {
1111
echo "cursor"
@@ -85,11 +85,6 @@ driver_build_command() {
8585
# NDJSON streaming output
8686
CLAUDE_CMD_ARGS+=("--output-format" "stream-json")
8787

88-
# Session resume — gated on CLAUDE_USE_CONTINUE to respect --no-continue flag
89-
if [[ "$CLAUDE_USE_CONTINUE" == "true" && -n "$session_id" ]]; then
90-
CLAUDE_CMD_ARGS+=("--resume" "$session_id")
91-
fi
92-
9388
# Build prompt with context prepended
9489
local prompt_content
9590
if driver_running_on_windows; then
@@ -107,7 +102,15 @@ $prompt_content"
107102
}
108103

109104
driver_supports_sessions() {
110-
return 0 # true — Cursor supports --resume
105+
return 1 # false — session IDs are not capturable from current NDJSON output
106+
}
107+
108+
driver_supports_live_output() {
109+
return 0 # true
110+
}
111+
112+
driver_prepare_live_command() {
113+
LIVE_CMD_ARGS=("${CLAUDE_CMD_ARGS[@]}")
111114
}
112115

113116
# Cursor CLI outputs NDJSON events

0 commit comments

Comments
 (0)