fix: forward forceDocument through sendPayload path (follow-up to #45111)#46119
fix: forward forceDocument through sendPayload path (follow-up to #45111)#46119thepagent wants to merge 68 commits intoopenclaw:mainfrom
Conversation
sendPayload in telegramOutbound did not accept or forward forceDocument, so --force-document was silently ignored for payloads with channelData (e.g. inline-button payloads). Also, deliverOutboundPayloadsCore did not include forceDocument in sendOverrides passed to handler.sendPayload. Fixes the two missing links: - extensions/telegram/src/outbound-adapter.ts: accept forceDocument in sendPayload and pass it through to sendTelegramPayloadMessages baseOpts - src/infra/outbound/deliver.ts: include forceDocument in sendOverrides Reported as follow-up to openclaw#45111.
Greptile SummaryThis PR correctly fixes a two-link chain that caused Key observations:
Confidence Score: 5/5
Last reviewed commit: 64eb2c3 |
| @@ -156,6 +157,7 @@ export const telegramOutbound: ChannelOutboundAdapter = { | |||
| baseOpts: { | |||
| ...baseOpts, | |||
| mediaLocalRoots, | |||
| forceDocument: forceDocument ?? false, | |||
There was a problem hiding this comment.
No test coverage for the fixed path
The existing sendPayload tests in channel.test.ts (lines 294 and 327) don't pass or assert forceDocument, so the regression this PR fixes has no test to prevent it from silently breaking again. Consider adding a test along the lines of the existing forceDocument test in send.test.ts (line 895) but targeting sendPayload with channelData present — verifying that forceDocument: true in the context is forwarded to the underlying send call.
Prompt To Fix With AI
This is a comment left during a code review.
Path: extensions/telegram/src/outbound-adapter.ts
Line: 144-160
Comment:
**No test coverage for the fixed path**
The existing `sendPayload` tests in `channel.test.ts` (lines 294 and 327) don't pass or assert `forceDocument`, so the regression this PR fixes has no test to prevent it from silently breaking again. Consider adding a test along the lines of the existing `forceDocument` test in `send.test.ts` (line 895) but targeting `sendPayload` with `channelData` present — verifying that `forceDocument: true` in the context is forwarded to the underlying send call.
How can I resolve this? If you propose a fix, please make it concise.There was a problem hiding this comment.
Added in c1f0de8.
New describe block in channel.test.ts calls sendPayload with channelData present and forceDocument: true, then asserts the underlying send receives forceDocument: true. This directly guards the regression.
|
@codex @greptile-apps please re-review, test coverage has been added in c1f0de8. |
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: c1f0de8d31
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| baseOpts: { | ||
| ...baseOpts, | ||
| mediaLocalRoots, | ||
| forceDocument: forceDocument ?? false, |
There was a problem hiding this comment.
Patch Telegram plugin path that is actually registered
This change updates extensions/telegram/src/outbound-adapter.ts, but bundled runtime registration still wires Telegram via extensions/telegram/index.ts to telegramPlugin in extensions/telegram/src/channel.ts, and outbound delivery resolves plugin.outbound from that registry entry (src/channels/plugins/outbound/load.ts). Because telegramPlugin.outbound.sendPayload still builds send options without forceDocument, the normal channels.telegram delivery path continues to ignore --force-document for payloads with channelData, so the intended fix is not applied in production.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Good catch. Fixed in 64eb2c3 — channel.ts is the production path; added forceDocument to buildTelegramSendOptions and destructured it in sendPayload.
The telegramPlugin.outbound.sendPayload in channel.ts is the actual production path used by the plugin registry. It was not forwarding forceDocument, making the fix in outbound-adapter.ts ineffective. - Add forceDocument to buildTelegramSendOptions params and output - Destructure and pass forceDocument in sendPayload Addresses Codex review on openclaw#46119.
* ci: move docker release to GitHub-hosted runners * ci: annotate docker release runner guardrails
* feat(agent): add /btw side questions * fix(agent): gate and log /btw reviews * feat(btw): isolate side-question delivery * test(reply): update route reply runtime mocks * fix(btw): complete side-result delivery across clients * fix(gateway): handle streamed btw side results * fix(telegram): unblock btw side questions * fix(reply): make external btw replies explicit * fix(chat): keep btw side results ephemeral in internal history * fix(btw): address remaining review feedback * fix(chat): preserve btw history on mobile refresh * fix(acp): keep btw replies out of prompt history * refactor(btw): narrow side questions to live channels * fix(btw): preserve channel typing indicators * fix(btw): keep side questions isolated in chat * fix(outbound): restore typed channel send deps * fix(btw): avoid blocking replies on transcript persistence * fix(btw): keep side questions fast * docs(commands): document btw slash command * docs(changelog): add btw side questions entry * test(outbound): align session transcript mocks
* ci: add docker release backfill workflow * ci: add manual backfill support to docker release * ci: keep docker latest tags off manual backfills
…w#46301) * fix: avoid configure startup plugin stalls * fix: credit configure startup changelog entry
* fix(btw): stop persisting side questions * docs(btw): document side-question behavior
* Slack: forward reply blocks in DM delivery * Slack: preserve reply blocks in preview finalization * Slack: cover block-only DM replies * Changelog: note Slack interactive reply fix
* Docs: document Telegram force-document sends * Docs: note Telegram document send behavior * Docs: clarify memory file precedence * Docs: align default AGENTS memory guidance * Docs: update workspace FAQ memory note * Docs: document gateway status require-rpc * Docs: add require-rpc to gateway CLI index
Fixes openclaw#43322 * fix(feishu): clear stale streamingStartPromise on card creation failure When FeishuStreamingSession.start() throws (HTTP 400), the catch block sets streaming = null but leaves streamingStartPromise dangling. The guard in startStreaming() checks streamingStartPromise first, so all future deliver() calls silently skip streaming - the session locks permanently. Clear streamingStartPromise in the catch block so subsequent messages can retry streaming instead of dropping all future replies. Fixes openclaw#43322 * test(feishu): wrap push override in try/finally for cleanup safety
Fixes openclaw#42931 When gateway.auth.mode is set to "none", authentication succeeds with method "none" but sharedAuthOk remains false because the auth-context only recognises token/password/trusted-proxy methods. This causes all pairing-skip conditions to fail, so Control UI browser connections get closed with code 1008 "pairing required" despite auth being disabled. Short-circuit the skipPairing check: if the operator explicitly disabled authentication, device pairing (which is itself an auth mechanism) must also be bypassed. Fixes openclaw#42931
Fixes openclaw#43057 * fix(auth): clear stale lockout on re-login Clear stale `auth_permanent` and `billing` disabled state for all profiles matching the target provider when `openclaw models auth login` is invoked, so users locked out by expired or revoked OAuth tokens can recover by re-authenticating instead of waiting for the cooldown timer. Uses the agent-scoped store (`loadAuthProfileStoreForRuntime`) for correct multi-agent profile resolution and wraps the housekeeping in try/catch so corrupt store files never block re-authentication. Fixes openclaw#43057 * test(auth): remove unnecessary non-null assertions oxlint no-unnecessary-type-assertion: invocationCallOrder[0] already returns number, not number | undefined.
…nclaw#46066) Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: scoootscooob <[email protected]> Co-authored-by: Tak Hoffman <[email protected]>
… restarts (openclaw#46290) Signed-off-by: sallyom <[email protected]>
… providers Fixes openclaw#46142 Stop forcing supportsUsageInStreaming=false on non-native openai-completions endpoints. Most OpenAI-compatible APIs (DashScope, DeepSeek, Groq, Together, etc.) handle stream_options: { include_usage: true } correctly. The blanket disable broke usage/cost tracking for all non-OpenAI providers. supportsDeveloperRole is still forced off for non-native endpoints since the developer message role is genuinely OpenAI-specific. Users on backends that reject stream_options can opt out with compat.supportsUsageInStreaming: false in their model config. Fixes openclaw#46142
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
13 similar comments
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
8 similar comments
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
|
Closing this PR because it looks dirty (too many unrelated or unexpected changes). This usually happens when a branch picks up unrelated commits or a merge went sideways. Please recreate the PR from a clean branch. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: cd34387874
ℹ️ About Codex in GitHub
Your team has set up Codex to 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 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| broadcastChatFinal({ | ||
| context, | ||
| runId: clientRunId, | ||
| sessionKey: rawSessionKey, | ||
| }); |
There was a problem hiding this comment.
Preserve /btw reply fallback for chat-only clients
This branch emits a chat.side_result and then sends chat final without a message, which means clients that only consume chat events will lose the /btw answer entirely; I verified ui/src/ui/app-gateway.ts only handles agent and chat events and has no chat.side_result handler. Because BTW responses are not persisted to history, those clients cannot recover the answer after the final event, so /btw appears to do nothing outside updated consumers (currently TUI).
Useful? React with 👍 / 👎.
The telegramPlugin.outbound.sendPayload in channel.ts is the actual production path used by the plugin registry. It was not forwarding forceDocument, making the fix in outbound-adapter.ts ineffective. - Add forceDocument to buildTelegramSendOptions params and output - Destructure and pass forceDocument in sendPayload Addresses Codex review on #46119.
Follow-up to #45111.
Problem
--force-documentwas silently ignored whenever a payload carried TelegramchannelData(e.g. inline-button payloads). Two links in the chain were missing:deliverOutboundPayloadsCorebuiltsendOverrideswithoutforceDocument, so it was never passed tohandler.sendPayload.telegramOutbound.sendPayloaddid not acceptforceDocumentin its destructured params, and did not forward it tosendTelegramPayloadMessagesviabaseOpts.The
sendMediapath was already correct (fixed in #45111); only thesendPayloadpath was affected.Fix
Changes
src/infra/outbound/deliver.ts— addforceDocumenttosendOverridesextensions/telegram/src/outbound-adapter.ts— accept and forwardforceDocumentinsendPayload