openclaw - ✅(Solved) Fix replyToCurrent default false blocks implicit replyToId in followup queue [4 pull requests, 1 comments, 2 participants]

Official PRs (…)
ON THIS PAGE

Recommended Tools

×6

Utilities matched from this issue’s tags and category — try them while you read without losing context.

GitHub issue graph ai analysis

Paste a GitHub issue URL. We fetch that issue, discover linked issues from bodies/comments/timeline, collect linked pull requests, and produce a structured English report.

The report is written in English Markdown for sharing and archival.

Helpful · Quick feedback

Loading…
GitHub stats
openclaw/openclaw#66540Fetched 2026-04-15 06:25:42
View on GitHub
Comments
1
Participants
2
Timeline
5
Reactions
0
Timeline (top)
cross-referenced ×4commented ×1

Root Cause

In src/utils/directive-tags.ts, parseInlineDirectives returns replyToCurrent: false as the default:

if (!text.includes("[[")) {
    return {
        text: normalizeDirectiveWhitespace(text),
        audioAsVoice: false,
        replyToCurrent: false,  // ← default, NOT an explicit opt-out
        hasAudioTag: false,
        hasReplyTag: false,
    };
}

Fix Action

Fix

Remove the replyToCurrent === false check from the implicit replyToId assignment condition. The replyToCurrent flag should only be used to enable explicit reply-to-current behavior (when [[reply_to_current]] tag is present), not to block implicit behavior.

PR fix notes

PR #66547: fix(reply): keep implicit threading when replyToCurrent defaults false

Description (problem / solution / changelog)

Summary

  • Problem: implicit reply threading treated replyToCurrent: false as an explicit opt-out, even though that value is the default parse result when no [[reply_to_current]] tag is present.
  • Why it matters: threaded channels can silently lose replyToId and fall back to plain replies when payloads carry the default flag.
  • What changed: removed the false-default veto from resolveReplyThreadingForPayload and added a regression test for payloads that arrive with replyToCurrent: false.
  • What did NOT change (scope boundary): followup queue routing semantics, channel-specific transport logic, and directive parsing defaults.

Change Type (select all)

  • Bug fix
  • Feature
  • Refactor required for the fix
  • Docs
  • Security hardening
  • Chore/infra

Scope (select all touched areas)

  • Gateway / orchestration
  • Skills / tool execution
  • Auth / tokens
  • Memory / storage
  • Integrations
  • API / contracts
  • UI / DX
  • CI/CD / infra

Linked Issue/PR

  • Closes #66540
  • Related #66540
  • This PR fixes a bug or regression

Root Cause (if applicable)

  • Root cause: resolveReplyThreadingForPayload treated replyToCurrent === false as an explicit opt-out, but parseInlineDirectives emits false by default when there is no reply tag.
  • Missing detection / guardrail: nearby threading tests covered implicit threading and explicit tags, but not the default-false payload shape.
  • Contributing context (if known): this mostly affects paths where payloads are normalized before threading and keep the default replyToCurrent value.

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
    • Seam / integration test
    • End-to-end test
    • Existing coverage already sufficient
  • Target test or file: src/auto-reply/reply/reply-plumbing.test.ts
  • Scenario the test should lock in: a payload with replyToCurrent: false and no explicit replyToId should still receive the implicit currentMessageId when reply threading is enabled.
  • Why this is the smallest reliable guardrail: it exercises the shared threading helper directly, which is where the regression lives.
  • Existing test that already covers this (if any): None.
  • If no new test is added, why not: N/A

User-visible / Behavior Changes

  • Channels that rely on threaded replies no longer lose the implicit replyToId just because a payload carried the default replyToCurrent: false value.

Diagram (if applicable)

Before:
[payload with replyToCurrent:false] -> shared threading helper -> implicit replyToId blocked

After:
[payload with replyToCurrent:false] -> shared threading helper -> implicit replyToId preserved -> threaded reply delivered

Security Impact (required)

  • New permissions/capabilities? (Yes/No) No
  • Secrets/tokens handling changed? (Yes/No) No
  • New/changed network calls? (Yes/No) No
  • Command/tool execution surface changed? (Yes/No) No
  • Data access scope changed? (Yes/No) No
  • If any Yes, explain risk + mitigation:

Repro + Verification

Environment

  • OS: macOS 15
  • Runtime/container: Node 22 / Bun
  • Model/provider: N/A
  • Integration/channel (if any): shared reply threading path
  • Relevant config (redacted): default reply threading test fixtures

Steps

  1. Build a reply payload with text: \"hello\", replyToCurrent: false, and no explicit replyToId.
  2. Call applyReplyThreading with replyToMode: \"all\" and currentMessageId: \"42\".
  3. Inspect the resolved payload.

Expected

  • The payload keeps implicit threading and resolves replyToId to 42.

Actual

  • Before this change, the shared helper left replyToId unset because it treated the default false flag as an explicit opt-out.

Evidence

Attach at least one:

  • Failing test/log before + passing after
  • Trace/log snippets
  • Screenshot/recording
  • Perf numbers (if relevant)

Human Verification (required)

  • Verified scenarios: direct helper repro for implicit threading with and without replyToCurrent: false; narrow test run for src/auto-reply/reply/reply-plumbing.test.ts and src/auto-reply/reply/followup-delivery.test.ts.
  • Edge cases checked: explicit [[reply_to_current]] coverage remained green; followup delivery tests remained green.
  • What you did not verify: live channel roundtrips on a real threaded integration.

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? (Yes/No) Yes
  • Config/env changes? (Yes/No) No
  • Migration needed? (Yes/No) No
  • If yes, exact upgrade steps:

Risks and Mitigations

  • Risk: payloads that intentionally relied on replyToCurrent: false as an opt-out could now thread implicitly.
    • Mitigation: the codebase already models explicit opt-in via reply tags and explicit replyToId; the regression test locks in that the default parse value is not treated as an explicit opt-out.

AI Assistance

  • AI assistance: used for implementation and test authoring; the change and verification steps above were reviewed before opening this PR.
  • Testing level: repo pre-commit checks passed during commit, plus targeted reply-threading tests were run locally.

Made with Cursor

Changed files

  • src/auto-reply/reply/reply-payloads-base.ts (modified, +1/-4)
  • src/auto-reply/reply/reply-plumbing.test.ts (modified, +12/-0)

PR #66554: fix(reply): remove replyToCurrent===false check blocking implicit replyToId

Description (problem / solution / changelog)

Fixes #66540

When processing queued/followup messages, resolveReplyThreadingForPayload incorrectly treats replyToCurrent: false (default value from parseInlineDirectives) as an explicit opt-out, preventing implicit replyToId assignment.

This causes followup messages to lose their replyToId, resulting in plain text replies instead of quote replies on channels like WeChat.

Changes

  • Remove replyToCurrent === false condition from implicit replyToId assignment
  • Add test case verifying replyToCurrent: false doesn't block implicit threading
  • Preserve replyToCurrent flag behavior for explicit [[reply_to_current]] tags

Impact

Fixes message threading for queued/followup messages on all channels

Testing

✅ All existing tests pass ✅ New test case validates the fix

Changed files

  • PR_COLLATERAL_65510.md (added, +177/-0)
  • extensions/firecrawl/src/config.ts (modified, +17/-1)
  • src/plugin-sdk/secret-input.ts (modified, +5/-1)
  • src/utils/normalize-secret-input.ts (modified, +28/-0)

PR #66556: fix(telegram): filter undefined paths to prevent voice transcription failure

Description (problem / solution / changelog)

Fixes #62496

When Telegram voice notes have undefined paths in allMedia array, the transcription preflight fails because normalizeAttachments filters out entries where both path and url are undefined, causing silent transcription failure.

Root cause: allMedia.map((m) => m.path) creates array with undefined values when voice note path is not set, then normalizeAttachments drops all attachments.

Changes

  • Filter undefined paths with .filter(Boolean) before creating MediaPaths array
  • Apply fix to both bot-message-context.body.ts and bot-message-context.session.ts
  • Add test case for handling voice messages with undefined paths gracefully

Impact

Telegram voice transcription now works even when some media paths are undefined

Testing

✅ All existing tests pass ✅ New test case validates the fix

Changed files

  • extensions/telegram/src/bot-message-context.body.ts (modified, +1/-1)
  • extensions/telegram/src/bot-message-context.session.ts (modified, +2/-2)

PR #66562: fix(reply): keep implicit threading when replyToCurrent defaults false

Description (problem / solution / changelog)

Fixes issue where implicit threading was lost when replyToCurrent defaults to false.

Problem

  • When replyToCurrent defaults false, implicit threading context was not preserved
  • Messages lost their thread association in conversations

Solution

  • Modified conversation binding to maintain implicit threading
  • Ensures thread context is preserved across message exchanges
  • Maintains backward compatibility with existing behavior

Fixes #66540

Changed files

  • src/auto-reply/reply/reply-delivery.ts (modified, +5/-3)
  • src/auto-reply/reply/reply-payloads-base.ts (modified, +5/-1)
  • src/auto-reply/reply/reply-plumbing.test.ts (modified, +26/-0)

Code Example

params.payload.replyToId || params.payload.replyToCurrent === false || !implicitReplyToId || !allowImplicitReplyToCurrentMessage

---

if (!text.includes("[[")) {
    return {
        text: normalizeDirectiveWhitespace(text),
        audioAsVoice: false,
        replyToCurrent: false,  // ← default, NOT an explicit opt-out
        hasAudioTag: false,
        hasReplyTag: false,
    };
}
RAW_BUFFERClick to expand / collapse

Bug: replyToCurrent: false default blocks implicit replyToId in followup queue

Problem

When processing queued/followup messages, resolveReplyThreadingForPayload in reply-payloads-base.ts checks:

params.payload.replyToId || params.payload.replyToCurrent === false || !implicitReplyToId || !allowImplicitReplyToCurrentMessage

The condition params.payload.replyToCurrent === false prevents implicit replyToId from being set. However, replyToCurrent: false is the default value returned by parseInlineDirectives when the model response doesn't contain a [[reply_to_current]] tag — it doesn't represent an explicit opt-out.

This causes followup/queued messages to lose their replyToId, resulting in plain text replies instead of quote replies on channels like WeChat that rely on replyToId for message quoting.

Root Cause

In src/utils/directive-tags.ts, parseInlineDirectives returns replyToCurrent: false as the default:

if (!text.includes("[[")) {
    return {
        text: normalizeDirectiveWhitespace(text),
        audioAsVoice: false,
        replyToCurrent: false,  // ← default, NOT an explicit opt-out
        hasAudioTag: false,
        hasReplyTag: false,
    };
}

Impact

  • First message in a turn: works (process.ts deliver callback has ctx.MessageSid fallback)
  • Queued/followup messages: broken (route-reply → channel.ts outbound, no fallback, replyToId is null)

Fix

Remove the replyToCurrent === false check from the implicit replyToId assignment condition. The replyToCurrent flag should only be used to enable explicit reply-to-current behavior (when [[reply_to_current]] tag is present), not to block implicit behavior.

extent analysis

TL;DR

Remove the replyToCurrent === false check from the implicit replyToId assignment condition in resolveReplyThreadingForPayload to fix the issue with followup/queued messages losing their replyToId.

Guidance

  • Identify the resolveReplyThreadingForPayload function in reply-payloads-base.ts and locate the condition that checks params.payload.replyToCurrent === false.
  • Remove the params.payload.replyToCurrent === false part from the condition to allow implicit replyToId to be set when replyToCurrent is not explicitly set to true.
  • Verify that followup/queued messages now correctly set the replyToId and result in quote replies on channels like WeChat.
  • Test the fix with different scenarios, including messages with and without the [[reply_to_current]] tag, to ensure the change does not introduce any regressions.

Example

// Before
params.payload.replyToId || params.payload.replyToCurrent === false || !implicitReplyToId || !allowImplicitReplyToCurrentMessage

// After
params.payload.replyToId || !implicitReplyToId || !allowImplicitReplyToCurrentMessage

Notes

This fix assumes that the replyToCurrent flag is only intended to enable explicit reply-to-current behavior when the [[reply_to_current]] tag is present. Removing the replyToCurrent === false check may have unintended consequences if the flag is used elsewhere in the codebase to block implicit behavior.

Recommendation

Apply the workaround by removing the replyToCurrent === false check, as it is a targeted fix that addresses the specific issue with followup/queued messages losing their replyToId.

Vote matrix · Quick signals

Works
Did the solution work? Tap to confirm.
Easy Fix
Was it a quick fix?
Time Saver
Did it save you time?
Blocking
Was it severely blocking?
Common Issue
Are others likely hitting this too?
Flaky / Intermittent
Is it intermittent?
Verified / Reproducible
Can you reproduce it reliably?
Loading…

Still need to ship something?

×6

Another batch ranked right after the header list — different links, same matching logic.

Back to top recommendations

TRENDING

openclaw - ✅(Solved) Fix replyToCurrent default false blocks implicit replyToId in followup queue [4 pull requests, 1 comments, 2 participants]