feat(skills): Grok Imagine image gen via DroidProxy OAuth - #226
Conversation
Document subscription-based image generation through the local proxy and ship a Factory skill that posts to /v1/images/generations so Droid can save images without an XAI_API_KEY.
|
Caution Review failedThe pull request is closed. ℹ️ Recent review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
📝 WalkthroughSummary by CodeRabbit
WalkthroughDocuments a new Grok Imagine skill, its installation and invocation through DroidProxy, cross-platform image-saving procedures, request parameters, troubleshooting guidance, and OAuth-based routing details. ChangesGrok Imagine integration
Estimated code review effort: 2 (Simple) | ~10 minutes Poem
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In @.factory/skills/grok-imagine/SKILL.md:
- Around line 94-102: Update the example around the image-generation curl
request to capture the API response, check and surface any .error value, extract
the temporary .data[0].url, and immediately download it with curl -fsSL to a
saved output file instead of only printing the URL.
- Line 88: Update the base64 decoding command in the image output flow to use a
platform-correct decoder on macOS and Linux. Detect the platform with uname and
invoke BSD base64 with -D on macOS while retaining -d for Linux, or use an
equivalent portable decoding approach; preserve writing the decoded data to OUT.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Organization UI
Review profile: CHILL
Plan: Pro Plus
Run ID: aac782d0-210a-4efe-9cba-572ab51af8b5
📒 Files selected for processing (3)
.factory/skills/grok-imagine/SKILL.mdREADME.mdSETUP.md
| exit 1 | ||
| fi | ||
|
|
||
| echo "$RESP" | jq -r '.data[0].b64_json' | base64 -d > "$OUT" |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== locate SKILL.md =="
fd -a 'SKILL\.md$' . | sed -n '1,50p'
echo
echo "== target excerpt =="
if [ -f .factory/skills/grok-imagine/SKILL.md ]; then
nl -ba .factory/skills/grok-imagine/SKILL.md | sed -n '70,100p'
fi
echo
echo "== base64 decode flags in target =="
rg -n 'base64|jq -r|b64_json|uname|platform|macOS|Darwin' .factory/skills/grok-imagine/SKILL.md || true
echo
echo "== local base64 flags =="
base64 --version 2>&1 | sed -n '1,5p' || true
printf '\n'
printf 'ABC==' | base64 -d >/tmp/base64_gnu_probe.out && cat /tmp/base64_gnu_probe.out || true
printf '\n'
printf 'ABC==' | base64 -D >/tmp/base64_bsd_probe.out && cat /tmp/base64_bsd_probe.out || true
printf '\n'
stat -c '%s' /tmp/base64_gnu_probe.out /tmp/base64_bsd_probe.out 2>/dev/null || trueRepository: nikships/droidproxy
Length of output: 242
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== git-tracked SKILL.md candidates =="
git ls-files | awk '$0 ~ /(SKILL|README|instruction|prompt).*\.md$/i {print}' | sed -n '1,80p'
echo
echo "== target file exists and excerpt =="
if [ -f .factory/skills/grok-imagine/SKILL.md ]; then
awk 'NR>=70 && NR<=100 {printf "%6d\t%s\n", NR, $0}' .factory/skills/grok-imagine/SKILL.md
else
echo "missing .factory/skills/grok-imagine/SKILL.md"
fi
echo
echo "== relevant symbols =="
grep -nE 'base64|jq -r|b64_json|uname|platform|macOS|Darwin|OUT|RESP' .factory/skills/grok-imagine/SKILL.md || true
echo
echo "== local base64 implementation =="
case "$(uname -s)" in
Linux) printf 'linux\n' ;;
Darwin) printf 'darwin\n' ;;
*) printf '%s\n' "$(uname -s)" ;;
esac
command -v base64 || true
base64 --version 2>&1 | sed -n '1,4p' || true
printf 'ABC==' | base64 -d >/tmp/base_probe.out && hexdump -C /tmp/base_probe.out || true
printf 'ABC==' | base64 -D >/tmp/base_probe_D.out && hexdump -C /tmp/base_probe_D.out || trueRepository: nikships/droidproxy
Length of output: 2689
Use a platform-correct base64 decoder.
This section is macOS/Linux and uses base64 -d, which fails under macOS’s BSD base64 that requires -D. Branch on uname or use a portable decoder.
Proposed fix
-echo "$RESP" | jq -r '.data[0].b64_json' | base64 -d > "$OUT"
+if [[ "$(uname -s)" == "Darwin" ]]; then
+ echo "$RESP" | jq -r '.data[0].b64_json' | base64 -D > "$OUT"
+else
+ echo "$RESP" | jq -r '.data[0].b64_json' | base64 -d > "$OUT"
+fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| echo "$RESP" | jq -r '.data[0].b64_json' | base64 -d > "$OUT" | |
| if [[ "$(uname -s)" == "Darwin" ]]; then | |
| echo "$RESP" | jq -r '.data[0].b64_json' | base64 -D > "$OUT" | |
| else | |
| echo "$RESP" | jq -r '.data[0].b64_json' | base64 -d > "$OUT" | |
| fi |
🧰 Tools
🪛 SkillSpector (2.3.11)
[warning] 66: [E1] External Transmission: Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Remediation: Verify the destination URL is trusted and necessary. Remove or replace with documented APIs. Ensure no secrets, tokens, or PII are transmitted.
(Data Exfiltration (E1))
[warning] 36: [RA2] Session Persistence: Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Remediation: Remove any persistence mechanisms (cron jobs, startup scripts, state files). Skills should not maintain state across sessions without explicit user consent.
(Rogue Agent (RA2))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.factory/skills/grok-imagine/SKILL.md at line 88, Update the base64 decoding
command in the image output flow to use a platform-correct decoder on macOS and
Linux. Detect the platform with uname and invoke BSD base64 with -D on macOS
while retaining -d for Linux, or use an equivalent portable decoding approach;
preserve writing the decoded data to OUT.
| ```bash | ||
| PROMPT='Mountain landscape at sunrise' | ||
| curl -sS http://localhost:8317/v1/images/generations \ | ||
| -H "Content-Type: application/json" \ | ||
| -H "Authorization: Bearer dummy-not-used" \ | ||
| -d "$(jq -n --arg p "$PROMPT" \ | ||
| '{model:"grok-imagine-image", prompt:$p, aspect_ratio:"16:9"}')" \ | ||
| | jq -r '.data[0].url' | ||
| ``` |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟠 Major | ⚡ Quick win
Download the temporary URL instead of only printing it.
This example emits .data[0].url to stdout, while the skill requires URL results to be downloaded promptly and saved. Capture the response, handle .error, then download the URL with curl -fsSL before it expires.
🧰 Tools
🪛 Betterleaks (1.6.1)
[high] 96-98: Discovered a potential authorization token provided in a curl command header, which could compromise the curl accessed resource.
(curl-auth-header)
🪛 SkillSpector (2.3.11)
[warning] 66: [E1] External Transmission: Data is being sent to an external URL. This could be legitimate telemetry or data exfiltration. Manual review is recommended.
Remediation: Verify the destination URL is trusted and necessary. Remove or replace with documented APIs. Ensure no secrets, tokens, or PII are transmitted.
(Data Exfiltration (E1))
[warning] 36: [RA2] Session Persistence: Skill establishes unauthorized persistence across sessions via cron jobs, startup scripts, or state files. Session persistence allows an attacker to maintain access beyond the current interaction.
Remediation: Remove any persistence mechanisms (cron jobs, startup scripts, state files). Skills should not maintain state across sessions without explicit user consent.
(Rogue Agent (RA2))
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In @.factory/skills/grok-imagine/SKILL.md around lines 94 - 102, Update the
example around the image-generation curl request to capture the API response,
check and surface any .error value, extract the temporary .data[0].url, and
immediately download it with curl -fsSL to a saved output file instead of only
printing the URL.
Keep the skill at the repo root instead of under .factory/, and update README/SETUP install paths accordingly.
Summary
.factory/skills/grok-imagine/SKILL.mdthat generates images through DroidProxy (POST http://localhost:8317/v1/images/generationswithgrok-imagine-image/grok-imagine-image-quality).XAI_API_KEYwhen Grok is connected in Settings.README.mdandSETUP.mdso users know chat models alone do not call Imagine; they need this skill (or an equivalent shell/MCP call).Why
Droid chat does not invoke xAI's image endpoint. Hermes and Grok Build expose first-class image tools; with DroidProxy, the auth tunnel already works for any
grok-*model on the image path — this skill is the missing agent-facing surface.How to use (after merge)
Requires DroidProxy running + Grok connected. Then ask Droid to generate an image.
Test plan
curl -sS http://localhost:8317/v1/images/generationswith modelgrok-imagine-imageand a short prompt returns URL orb64_json~/.factory/skills/grok-imagineand ask Droid to generate an image and write a file