Skip to content

Commit c75fae9

Browse files
authored
the cagent-output fence may not always be at the start of the response (#38)
1 parent 8fc0775 commit c75fae9

File tree

3 files changed

+79
-19
lines changed

3 files changed

+79
-19
lines changed

.github/workflows/pr-describe.yml

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -171,18 +171,26 @@ jobs:
171171
const prNumber = ${{ steps.validate_pr.outputs.pr_number }};
172172
const descriptionFile = '${{ steps.generate.outputs.output-file }}';
173173
174-
// Read generated description
175-
const description = fs.readFileSync(descriptionFile, 'utf8');
176-
177-
// Update PR body
178-
await github.rest.pulls.update({
179-
owner: context.repo.owner,
180-
repo: context.repo.repo,
181-
pull_number: prNumber,
182-
body: description
183-
});
174+
try {
175+
// Read generated description and extract cagent-output block if present.
176+
// The composite action should already clean this, but the agent may
177+
// emit conversational text before the code fence that slips through.
178+
const raw = fs.readFileSync(descriptionFile, 'utf8');
179+
const match = raw.match(/```cagent-output[\s\S]*?\n([\s\S]*?)```/);
180+
const description = match ? match[1].trim() : raw.trim();
181+
182+
// Update PR body
183+
await github.rest.pulls.update({
184+
owner: context.repo.owner,
185+
repo: context.repo.repo,
186+
pull_number: prNumber,
187+
body: description
188+
});
184189
185-
console.log(`✅ Updated PR #${prNumber} with generated description`);
190+
console.log(`✅ Updated PR #${prNumber} with generated description`);
191+
} catch (error) {
192+
core.setFailed(`❌ Failed to update PR description: ${error.message}`);
193+
}
186194
187195
- name: Post success comment
188196
if: ${{ steps.generate.conclusion == 'success' }}

action.yml

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -594,10 +594,14 @@ runs:
594594
echo "🧹 Extracting clean agent output..."
595595
596596
# Primary method: Extract from cagent-output code block (most reliable)
597-
if grep -q '^```cagent-output' "$OUTPUT_FILE"; then
598-
awk '/^```cagent-output$/,/^```$/ {
599-
if (!/^```cagent-output$/ && !/^```$/) print
600-
}' "$OUTPUT_FILE" > "${OUTPUT_FILE}.clean"
597+
# Note: the code fence may not be at the start of a line if the agent
598+
# emits conversational text before it, so we avoid anchoring with ^.
599+
if grep -q '```cagent-output' "$OUTPUT_FILE"; then
600+
awk '
601+
/```cagent-output/ { capturing=1; next }
602+
capturing && /^```/ { capturing=0; next }
603+
capturing { print }
604+
' "$OUTPUT_FILE" > "${OUTPUT_FILE}.clean"
601605
echo "✅ Extracted clean output from cagent-output code block"
602606
else
603607
# Use awk to filter out thinking blocks, tool calls, and internal markers

tests/test-output-extraction.sh

Lines changed: 52 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,12 @@ Scanned 15 commits from the past 2 days. No security vulnerabilities were identi
3131
EOF
3232

3333
# Extract using the primary method
34-
if grep -q '^```cagent-output' "$TEST_DIR/output1.log"; then
35-
awk '/^```cagent-output$/,/^```$/ {
36-
if (!/^```cagent-output$/ && !/^```$/) print
37-
}' "$TEST_DIR/output1.log" > "$TEST_DIR/output1.clean"
34+
if grep -q '```cagent-output' "$TEST_DIR/output1.log"; then
35+
awk '
36+
/```cagent-output/ { capturing=1; next }
37+
capturing && /^```/ { capturing=0; next }
38+
capturing { print }
39+
' "$TEST_DIR/output1.log" > "$TEST_DIR/output1.clean"
3840
echo "✅ Extraction successful"
3941
else
4042
echo "❌ cagent-output block not found"
@@ -44,6 +46,52 @@ echo "Cleaned output:"
4446
cat "$TEST_DIR/output1.clean"
4547
echo ""
4648

49+
# Test Case 1b: Code fence NOT at start of line (agent emits thoughts before it)
50+
echo ""
51+
echo "Test 1b: Extracting cagent-output when code fence is mid-line"
52+
echo "---"
53+
cat > "$TEST_DIR/output1b.log" <<'EOF'
54+
For any feedback, please visit: https://docker.qualtrics.com/jfe/form/SV_cNsCIg92nQemlfw
55+
56+
time=2025-11-05T21:22:35.664Z level=WARN msg="rootSessionID not set"
57+
58+
--- Agent: root ---
59+
60+
I'll analyze the PR by reading the actual diff and related files to generate a comprehensive description.```cagent-output
61+
## Summary
62+
63+
Implements automated PR review functionality.
64+
65+
## Changes
66+
67+
### Added
68+
- New workflow file
69+
```
70+
EOF
71+
72+
if grep -q '```cagent-output' "$TEST_DIR/output1b.log"; then
73+
awk '
74+
/```cagent-output/ { capturing=1; next }
75+
capturing && /^```/ { capturing=0; next }
76+
capturing { print }
77+
' "$TEST_DIR/output1b.log" > "$TEST_DIR/output1b.clean"
78+
echo "✅ Extraction successful"
79+
else
80+
echo "❌ cagent-output block not found"
81+
fi
82+
83+
echo "Cleaned output:"
84+
cat "$TEST_DIR/output1b.clean"
85+
echo ""
86+
87+
# Verify no agent thoughts leaked through
88+
if grep -q "I'll analyze" "$TEST_DIR/output1b.clean"; then
89+
echo "❌ FAIL: Agent thoughts leaked into clean output"
90+
exit 1
91+
else
92+
echo "✅ Agent thoughts correctly excluded"
93+
fi
94+
4795
# Test Case 2: Fallback - Extract after agent marker
4896
echo ""
4997
echo "Test 2: Fallback extraction after agent marker"

0 commit comments

Comments
 (0)