fix: add clear separator between metadata and user message#41299
fix: add clear separator between metadata and user message#41299puppylpg wants to merge 1 commit into
Conversation
Greptile SummaryThis PR addresses an LLM parsing issue by inserting an explicit Issues found:
Confidence Score: 2/5
Last reviewed commit: c2cd9f0 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c2cd9f06ab
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: d0ab9b0a9e
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
8f97557 to
4f98411
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f502cb1b9a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
5b49e83 to
8487e81
Compare
8487e81 to
4f98411
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad61ebd9e5
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5f24d4eda1
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
puppylpg
left a comment
There was a problem hiding this comment.
All review comments have been addressed:
- ✅ Separator now stripped by both
stripInboundMetadataandstripLeadingInboundMetadata - ✅ Only strip separator when full pattern
---+**User Message:**is present - ✅ Skip leading blank lines before checking separator
- ✅ Only strip separator when metadata was actually removed (
strippedMetadataflag) - ✅ Added
_sep: truemarker to distinguish new format from legacy - ✅ Only add
_sepmarker when conversation info has actual fields
Thanks for the thorough review!
a7fe27e to
7f6bc91
Compare
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 7f6bc918d2
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| @@ -303,7 +303,9 @@ export async function runPreparedReply( | |||
| ); | |||
| const baseBodyForPrompt = isBareSessionReset | |||
| ? baseBodyFinal | |||
| : [inboundUserContext, baseBodyFinal].filter(Boolean).join("\n\n"); | |||
| : inboundUserContext | |||
| ? `${inboundUserContext}\n\n---\n**User Message:**\n${baseBodyFinal}` | |||
There was a problem hiding this comment.
Gate separator injection on marker-capable metadata
The new ---\n**User Message:** wrapper is added whenever inboundUserContext is non-empty, but both sanitizers only remove that wrapper when they detect "_sep" inside stripped metadata. buildInboundUserContextPrefix can still emit metadata without a conversation block (for example sender-only direct contexts), so those messages get the separator injected but never stripped in TUI/web/gateway/session views, leaving user-visible ---/**User Message:** prefixes. Please only inject the wrapper when the emitted metadata includes the marker, or make separator stripping independent of the conversation block marker.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in commit 2a5ea09 (fix: gate separator injection on hasSeparatorMarker flag). The separator is now only injected when inboundUserContextResult.hasSeparatorMarker is true. The hasSeparatorMarker flag is set for both conversation info blocks and sender info blocks, ensuring consistent injection/stripping for all metadata types.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3366efbb11
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| if (line.includes('"_sep"')) { | ||
| hasNewFormatMarker = true; |
There was a problem hiding this comment.
Parse
_sep marker structurally before stripping separator
The new marker detection uses a raw substring check (line.includes('"_sep"')) inside any stripped JSON block, so legacy metadata can be misclassified as “new format” when user-controlled fields contain that text (for example a quoted/replied body value like _sep). In that case, if the real user message begins with the two-line pattern --- + **User Message:**, both sanitizers will now strip those legitimate leading lines even though no formatter-injected separator was present. Please parse the metadata JSON and require a top-level _sep: true marker instead of matching arbitrary JSON text.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in commit 1af618e (fix: parse _sep marker structurally before stripping separator). The detection now uses JSON.parse() to parse the metadata block, then checks "_sep" in parsed using the in operator. This prevents false positives from user-controlled fields that happen to contain the text _sep.
|
Good catch! I've updated the marker detection to parse JSON structurally instead of using raw substring checks. Now both
This prevents false positives when user-controlled fields (like quoted message bodies) happen to contain the text Commit: a36dd9b |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a36dd9b67a
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // Only strip the separator if we actually stripped metadata AND the metadata | ||
| // contains the new format marker (_sep). This prevents corrupting legacy user | ||
| // content that happens to start with the separator pattern. | ||
| if (strippedMetadata && hasNewFormatMarker) { |
There was a problem hiding this comment.
Restrict separator stripping to leading metadata blocks
stripInboundMetadata now removes the leading --- + **User Message:** pair whenever any stripped block contains _sep, but this check does not verify that the stripped metadata was actually a leading OpenClaw prefix. In the gateway/web/session sanitization paths that call this function, a user message that intentionally starts with those two lines can lose them if the same message later includes a quoted metadata block (for example copied logs containing _sep). This is new content corruption introduced by the separator-removal pass; gate separator removal on stripping metadata from the start of the message.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in commit 137ddca (fix: restrict separator stripping to leading metadata blocks only). The seenUserContent flag ensures that only metadata at the start of the message (before any user content) can trigger separator removal. A metadata block appearing later in the text (e.g., quoted logs) is ignored for separator-stripping purposes.
|
You're right, this was a bug. Fixed in commit f7a0336. Now Added a This prevents corrupting user content that:
|
|
Rebased onto latest main and updated PR description with real behavior proof. All tests passing (39/39). Ready for review. |
|
ClawSweeper applied the proposed close for this PR.
|
Summary
runtime-context-prompt.ts: When inbound metadata is present,buildCurrentInboundPrompt()injects---openclaw:user-msg---separator between the context prefix and the user prompt.strip-inbound-meta.ts: AddstripUserMessageSeparator()post-processing in bothstripInboundMetadata(webchat/API/gateway) andstripLeadingInboundMetadata(TUI) to remove the separator after metadata blocks are stripped. Gated ondidStripMetadataflag for defense-in-depth.strip-inbound-meta.test.ts: 7 new tests covering separator stripping and legacy preservation.buildInboundUserContextPrefix, no metadata format changes.Why
---openclaw:user-msg---instead of---\n**User Message:**The separator is a program-generated marker that cannot exist in any legacy stored message or user-typed content. This eliminates the need for complex detection logic (
_sepmarkers,seenUserContentflags, structural JSON parsing) and makes legacy message compatibility trivial: the stripper only removes---openclaw:user-msg---, which legacy data never contains.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
---openclaw:user-msg---separator between metadata and user content, reducing "message is empty" false positives.Security Impact (required)
NoNoNoNoNoRepro + Verification
Environment
Steps
buildCurrentInboundPrompt()stripInboundMetadata/stripLeadingInboundMetadataremoves the separator in user-facing viewsExpected
Actual
Evidence
---preservation, sentinel-without-metadata-block edge case, legacy message preservationReal behavior proof
Live CLI verification on the rebased branch (
b69cb795):Behavior or issue addressed: Metadata and user message content are joined with only double newlines, causing the LLM to misinterpret the message structure and ignore actual user content.
Real environment tested: Local OpenClaw development setup on Ubuntu 24.04 with Node v24.15.0.
Exact steps or command run after this patch:
npx tsx proof-test.mjs- Live CLI verification of separator injection and strippingpnpm test strip-inbound-meta- Unit tests for the new separator logicEvidence after fix:
---openclaw:user-msg---
Hello, how are you?
✅ Separator ---openclaw:user-msg--- is present between metadata and user message
Hello, how are you?
✅ No separator injected when metadata is absent
stripInboundMetadata (metadata + separator):
Input: (metadata + separator + user message)
Output: Hello, how are you?
✅ Metadata and separator both removed
stripLeadingInboundMetadata (metadata + separator):
Input: (metadata + separator + user message)
Output: Hello, how are you?
✅ Metadata and separator both removed in leading-only strip mode
Legacy message (no metadata, user has --- in content):
Input: Hello\n\n---\nSome user markdown
Output: Hello\n\n---\nSome user markdown (preserved intact)
✅ Legacy user content preserved, no false stripping
=== All checks passed ===