fix(openai): flatten content to single line, eliminate \n escapes (Devvit 400 round 4)#35
Conversation
…0 round 4) PR #32 / #33 / #34 all shipped but `callOpenAI` still returns HTTP 400 "We could not parse the JSON body" in production v0.0.35. The only remaining variable separating our body from probe(f) (5610 B single user, 200 OK) is **escape-char density** -- specifically `\n` from `\n\n`-joined sections. This round eliminates `\n` from the wire body by collapsing whitespace and joining sections with a single space. Wire-body escape-char census (laptop measurement against the produced body): * v0.0.35: body 7498 B, \n=? \"=many \u=5 * v0.0.36: body 6856 B, \n=0 \"=294 \u=66 The system prompt + each few-shot user message goes through `s.replace(/\s+/g, ' ').trim()` before being joined into a single user-message content. No `\n` survives on the wire. `\"` (from inline `JSON.stringify(ex.assistant)`) still appears 294 times -- if v0.0.36 still 400s, escape `\"` is the next thing to address (would require expressing few-shot OUTPUT without quoted keys). Local POST of the v0.0.36 body to api.openai.com returns HTTP 200 with a valid compiled rule: ``` HTTP 200 first 250 chars of output: {"id":"r_new_account_modqueue","name":"New accounts -> mod queue", "sourceNL":"Send to mod queue any post from accounts less than 7 days old.", "on":["onPostSubmit"],"when":{"all":[{"fact":"author.accountAgeHours","op":"lt","value":168}]},... ``` Prompt fidelity preserved: * System instructions still present (just whitespace-collapsed) * Few-shot still expressed as `EXAMPLE N INPUT: ... OUTPUT: <json>` blocks * Task input + optional clarification still passed * response_format: { type: 'json_object' } still enforces JSON output Gates: `npm run check` 4/4 PASS.
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
|
Warning Rate limit exceeded
You’ve run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout. Please see our FAQ for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: Organization UI Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (1)
✨ 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.
Code Review
This pull request modifies the construction of the OpenAI prompt in src/server/index.ts by collapsing all whitespace and newlines into single spaces. This change is intended to reduce the density of escape characters in the HTTP request body to mitigate 400 errors. Feedback suggests that flattening the system prompt while it contains "//" comments is risky, as the LLM might treat the entire subsequent string as a comment; a code suggestion was provided to strip these comments before collapsing the text.
| 'OUTPUT:', | ||
| ].join('\n\n'); | ||
| 'SYSTEM INSTRUCTIONS:', | ||
| collapse(VIBE_MOD_SYSTEM_PROMPT), |
There was a problem hiding this comment.
Collapsing the system prompt into a single line while it contains // comments is risky. If the LLM interprets the flattened string as a single line of code-like text, it might treat everything following the first // (which appears early in the prompt at the id field definition) as a comment, effectively ignoring the bulk of the instructions, facts, and examples. Since newlines are being eliminated to avoid HTTP 400 errors, these comments should be stripped before flattening.
collapse(VIBE_MOD_SYSTEM_PROMPT.replace(/[ \\t]+\\/\\/.*$/gm, '')),…tent fix(openai): flatten content to single line, eliminate \n escapes (Devvit 400 round 4)
…Devvit 400 round 5) PR #32 (single message), #33 (source ASCII), #34 (drop reasoning_effort + verbosity), #35 (eliminate `\n` from content) all shipped. Production v0.0.36 still returns HTTP 400 "We could not parse the JSON body". Direct laptop POST of the same body returns 200; Devvit's HTTP plugin is corrupting the transit somewhere. Two-axis change in one PR: 1. Body as Uint8Array (not string). String bodies pass through Devvit's plugin as a JS string that the plugin re-encodes to UTF-8 before writing to the socket. Large stringified-JSON bodies appear to corrupt during that re-encode. Uint8Array bypasses it: bytes are final, plugin only streams them. Body is pure ASCII (line 1352 rewrite), so TextEncoder produces 1 byte per char. 2. Few-shot truncated to 1 example. probe(f) (5610 B single user, no extras) returned 200 three times in production; PR #32-#35 keeping 4 examples produced 6800-7500 B bodies that all 400'd. Truncating to 1 example keeps total body well under probe(f)'s known-good 5610 B. Plus: cap system-prompt length at 3500 chars to bound worst-case body size. Explicit Content-Length header added: bytes length passed verbatim, no Transfer-Encoding fallback. Diagnostic: body byte count is now logged ("body bytes = N") so we can compare wire body size against the production failure threshold. If 5 still 400s, the remaining hypothesis is Devvit's plugin transit limit itself being lower than ~5 KB, which would require a completely different strategy (chunked uploads, or workaround via a Reddit-side proxy). Gates: `npm run check` 4/4 PASS.
Round 4 of OpenAI HTTP 400 diagnosis. PR #32/#33/#34 shipped, still 400 in production. Remaining variable vs probe(f) (200 OK): escape-char density. This PR eliminates all \n from wire body. Local POST of new body returns 200 with valid compiled rule. CI 4/4 PASS. Probe data + measurements in commit message.
🤖 Generated with Claude Code