Skip to content

feat(plugin-sdk): add reply payload sending hook#82823

Merged
steipete merged 23 commits into
openclaw:mainfrom
piersonr:feat/reply-payload-sending-hook
May 29, 2026
Merged

feat(plugin-sdk): add reply payload sending hook#82823
steipete merged 23 commits into
openclaw:mainfrom
piersonr:feat/reply-payload-sending-hook

Conversation

@piersonr

@piersonr piersonr commented May 17, 2026

Copy link
Copy Markdown
Contributor

Summary

  • add a new `reply_payload_sending` plugin hook that can mutate or cancel normalized `ReplyPayload` objects before delivery
  • wire the hook into auto-reply dispatch so plugins can modify presentation, delivery metadata, and text at the normalized payload stage
  • export the new hook types through the plugin SDK, document the new hook, and add coverage for chaining, cancellation, and dispatch-time mutation

Why

Today plugin authors can:

  • rewrite plain text with `message_sending`
  • intercept or replace dispatches with `before_dispatch`
  • take over reply delivery with `reply_dispatch`

But there is no hook that exposes the actual normalized outbound `ReplyPayload` before channel delivery. That makes clean plugin-only features like attaching Telegram inline buttons to normal assistant replies hard or impossible without core patches.

This change adds a focused seam for that use case while reusing the existing before-deliver phase in the reply dispatcher.

What changed

  • added `reply_payload_sending` to `PluginHookName` and `PLUGIN_HOOK_NAMES`
  • added new hook event/context/result types:
    • `PluginHookReplyPayloadSendingEvent`
    • `PluginHookReplyPayloadSendingContext`
    • `PluginHookReplyPayloadSendingResult`
  • added `runReplyPayloadSending()` to the hook runner
  • wired the new hook into `dispatchInboundMessageWithDispatcher()` and `dispatchInboundMessageWithBufferedDispatcher()` via dispatcher `beforeDeliver`
  • preserved sequential mutation semantics so each lower-priority handler sees the latest payload
  • allowed cancellation by returning `{ cancel: true }`
  • exported the new hook types from `src/plugin-sdk/core.ts`
  • documented the new hook in `docs/plugins/hooks.md`
  • added tests for:
    • hook-runner payload chaining
    • cancellation behavior
    • error isolation
    • dispatch-time payload mutation with run/session/channel context

Verification

Targeted local verification completed:

  • `corepack pnpm tsgo:core:test`
  • `node scripts/test-projects.mjs --maxWorkers=1 src/plugins/wired-hooks-reply-payload-sending.test.ts`
  • `node scripts/test-projects.mjs --maxWorkers=1 src/auto-reply/dispatch.test.ts src/auto-reply/reply/before-deliver.test.ts src/auto-reply/reply/dispatch-from-config.reply-dispatch.test.ts`
  • `corepack pnpm exec oxfmt --check docs/plugins/hooks.md src/auto-reply/dispatch.test.ts src/auto-reply/dispatch.ts src/auto-reply/reply/dispatch-from-config.shared.test-harness.ts src/auto-reply/reply/dispatch-from-config.test.ts src/plugin-sdk/core.ts src/plugins/hook-types.ts src/plugins/hooks.ts src/plugins/wired-hooks-reply-payload-sending.test.ts`

Repo-wide `pnpm build && pnpm check && pnpm test` was not run end-to-end on this machine for this PR; validation here was focused on the touched hook, dispatch, docs, and real Telegram behavior path.

Live validation

  • validated the real local usage path with the installed `telegram-final-buttons` plugin, which uses `reply_payload_sending` to attach inline buttons to Telegram final replies
  • confirmed via gateway logs that the plugin attached buttons and Telegram delivered the reply successfully
  • captured local screenshot proof of the rendered Telegram inline buttons in Telegram Desktop
  • visible buttons in the screenshot:
    • `Proceed`
    • `Status`
    • `Recommendation`

Real behavior proof

Behavior or issue addressed: Plugin authors need a way to mutate normalized outbound reply payloads before channel delivery so plugin-only features such as Telegram inline buttons can be added without core channel-specific patches.

Real environment tested: Local OpenClaw gateway running against a real Telegram bot and Telegram Desktop on the host machine, using the installed local `telegram-final-buttons` plugin.

Exact steps or command run after this patch:

  1. Start the local OpenClaw gateway with the patched `reply_payload_sending` hook available.
  2. Keep the local `telegram-final-buttons` plugin enabled so it uses `reply_payload_sending` to append inline buttons to final Telegram replies.
  3. Send messages through the real Telegram bot into the test thread.
  4. Observe the resulting bot reply in Telegram Desktop.

Evidence after fix: Gateway logs showed the live `telegram-final-buttons` plugin attaching buttons to a Telegram final reply and Telegram delivering the reply successfully. A local Telegram Desktop screenshot was captured showing the rendered inline buttons.

Observed result after fix: The Telegram bot reply rendered native inline buttons in the real client, including `Proceed`, `Status`, and `Recommendation`.

What was not tested: Fresh linked-install validation from the temporary fork-side demo package was not the final proof path; the real behavior proof used the already-installed local plugin path instead.

AI assistance

This PR was AI-assisted. I used Codex to help implement, test, validate, and iterate on the change, and I reviewed the resulting code and behavior locally before submission.

Notes

  • this intentionally hooks the normalized payload stage instead of only raw text so plugins can safely add presentation blocks, media, delivery hints, and similar metadata
  • this follows the same general precedence model as other modifying hooks: handlers run sequentially, and cancellation is terminal
  • the screenshot proof came from the already-installed local plugin path, not from a fresh linked-install of the temporary demo package in the fork

@openclaw-barnacle openclaw-barnacle Bot added docs Improvements or additions to documentation size: M triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 17, 2026
@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

Codex review: needs changes before merge. Reviewed May 29, 2026, 1:50 AM ET / 05:50 UTC.

Summary
The branch adds a public reply_payload_sending plugin hook, wires it into reply and outbound delivery paths, updates SDK exports/docs/API baseline, and adds focused hook/delivery tests.

PR surface: Source +514, Tests +999, Docs +10, Generated 0. Total +1523 across 30 files.

Reproducibility: yes. for the review finding: source inspection shows the custom beforeDeliver branch composes only the caller hook and reply_payload_sending, and current Telegram/Discord callers provide beforeDeliver. The feature itself has real Telegram screenshot proof rather than a bug reproduction path.

Review metrics: 1 noteworthy metric.

  • Public plugin hook surface: 1 added. A new plugin hook becomes a third-party SDK contract, so ordering and compatibility need maintainer approval before merge.

Merge readiness
Overall: 🦪 silver shellfish
Proof: 🦞 diamond lobster ✨ media proof bonus
Patch quality: 🦪 silver shellfish
Result: blocked by patch quality or review findings.

Overall follows the weaker of proof and patch quality, so missing proof can cap an otherwise strong patch.

Rank-up moves:

  • [P2] Fix the custom beforeDeliver composition so message_sending still runs after reply_payload_sending.
  • Rebase or otherwise resolve the dirty merge state and refresh the focused checks on the final head.

Risk before merge

  • [P1] This adds a public plugin SDK hook, so hook name, event/result shape, cancellation semantics, and delivery ordering become compatibility-sensitive for external plugins.
  • [P1] The hook can mutate or suppress reply payloads across direct, routed, durable, and recovered delivery; incorrect ordering can bypass delivery policy or misrender channel messages.
  • [P1] GitHub currently reports the PR as dirty against base, so the final merge result and checks need refresh before landing.

Maintainer options:

  1. Repair custom hook composition (recommended)
    Compose custom beforeDeliver with both reply_payload_sending and message_sending in the intended order, then add regression coverage for that exact path.
  2. Approve the SDK contract explicitly
    A maintainer can accept the new hook once the event shape, cancellation behavior, and ordering are the intended public plugin API.
  3. Pause if the hook shape is not settled
    If maintainers are not ready to commit to this SDK hook, pause or close the branch rather than shipping a contract that needs immediate redesign.
Copy recommended automerge instruction
@clawsweeper automerge

Special instructions:
Ensure `dispatchInboundMessageWithBufferedDispatcher` and `dispatchInboundMessageWithDispatcher` compose caller `beforeDeliver`, `reply_payload_sending`, and `message_sending` in the intended order when `dispatcherOptions.beforeDeliver` is present; add focused regression tests for a custom `beforeDeliver` path with both plugin hooks enabled.

Next step before merge

  • [P2] A narrow automated repair can fix the hook composition and tests; maintainer approval of the public SDK hook and dirty-branch refresh still remain before merge.

Security
Cleared: No concrete supply-chain or credential-handling issue found; the PR strips trustedLocalMedia from plugin-visible payloads and re-scopes media access after hook mutation.

Review findings

  • [P1] Compose message_sending after custom beforeDeliver — src/auto-reply/dispatch.ts:518
Review details

Best possible solution:

Land a rebased branch only after the custom beforeDeliver paths run the caller hook, reply_payload_sending, and message_sending in the intended order, with maintainer approval of the new public hook contract.

Do we have a high-confidence way to reproduce the issue?

Yes for the review finding: source inspection shows the custom beforeDeliver branch composes only the caller hook and reply_payload_sending, and current Telegram/Discord callers provide beforeDeliver. The feature itself has real Telegram screenshot proof rather than a bug reproduction path.

Is this the best way to solve the issue?

No as-is: the new normalized payload hook is a plausible SDK seam, but it should preserve canonical message_sending policy on custom dispatcher paths before the public contract lands.

Full review comments:

  • [P1] Compose message_sending after custom beforeDeliver — src/auto-reply/dispatch.ts:518
    When a caller supplies dispatcherOptions.beforeDeliver, this branch composes only the caller hook and reply_payload_sending, so paths like Telegram's identity beforeDeliver and Discord's delivery hook do not run message_sending after the new payload hook mutates the reply. That lets hook-added text/presentation bypass the existing outbound rewrite/cancel policy; include buildMessageSendingBeforeDeliver(...) in the custom composition and add a regression for a custom beforeDeliver path.
    Confidence: 0.86

Overall correctness: patch is incorrect
Overall confidence: 0.87

AGENTS.md: found and applied where relevant.

Codex review notes: model gpt-5.5, reasoning high; reviewed against 621db8f0b1b4.

Label changes

Label changes:

  • add rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • add status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): The PR includes redacted Telegram Desktop screenshot proof showing inline buttons on a real bot reply and a button tap returning to the conversation; the latest head also has a successful Real behavior proof check.
  • remove rating: 🐚 platinum hermit: Current PR rating is rating: 🦪 silver shellfish, so this older rating label is no longer current.
  • remove status: 👀 ready for maintainer look: Current PR status label is status: ⏳ waiting on author.

Label justifications:

  • P2: This is a normal-priority plugin SDK feature with meaningful but bounded delivery risk after review.
  • merge-risk: 🚨 compatibility: The PR adds a public plugin hook and exported SDK types whose semantics become compatibility-sensitive for third-party plugins.
  • merge-risk: 🚨 message-delivery: The hook can mutate or cancel reply payloads before channel delivery, and the current custom-dispatcher composition can bypass message_sending policy.
  • rating: 🦪 silver shellfish: Overall readiness is 🦪 silver shellfish; proof is 🦞 diamond lobster and patch quality is 🦪 silver shellfish.
  • status: ⏳ waiting on author: ClawSweeper has contributor-facing work open and is waiting for author action. Sufficient (screenshot): The PR includes redacted Telegram Desktop screenshot proof showing inline buttons on a real bot reply and a button tap returning to the conversation; the latest head also has a successful Real behavior proof check.
  • proof: sufficient: Contributor real behavior proof is sufficient. The PR includes redacted Telegram Desktop screenshot proof showing inline buttons on a real bot reply and a button tap returning to the conversation; the latest head also has a successful Real behavior proof check.
  • proof: 📸 screenshot: Contributor real behavior proof includes screenshot evidence. The PR includes redacted Telegram Desktop screenshot proof showing inline buttons on a real bot reply and a button tap returning to the conversation; the latest head also has a successful Real behavior proof check.
  • mantis: telegram-visible-proof: Mantis should capture Telegram visible proof. The PR enables visible Telegram inline-button reply behavior that can be demonstrated in a short Telegram Desktop proof, and screenshot proof is already supplied.
Evidence reviewed

PR surface:

Source +514, Tests +999, Docs +10, Generated 0. Total +1523 across 30 files.

View PR surface stats
Area Files Added Removed Net
Source 21 608 94 +514
Tests 7 1002 3 +999
Docs 1 13 3 +10
Config 0 0 0 0
Generated 1 2 2 0
Other 0 0 0 0
Total 30 1625 102 +1523

Acceptance criteria:

  • [P1] node scripts/run-vitest.mjs src/auto-reply/dispatch.test.ts.
  • [P1] node scripts/run-vitest.mjs src/auto-reply/reply/dispatch-from-config.test.ts src/infra/outbound/deliver.test.ts.
  • [P1] pnpm plugin-sdk:api:check.
  • [P1] git diff --check.

What I checked:

  • Repository policy applied: Root and scoped AGENTS.md guidance treats plugin SDK additions and message delivery behavior as compatibility-sensitive and requires docs/tests/proof for plugin-facing hooks. (AGENTS.md:21)
  • Live PR state: GitHub API reports head 0cae438 with mergeable=false and mergeable_state=dirty, so the branch needs conflict/rebase refresh before merge. (0cae43866449)
  • Composition defect: On PR head, custom beforeDeliver composes only caller beforeDeliver plus reply_payload_sending, omitting buildMessageSendingBeforeDeliver; the same pattern appears in both dispatcher entrypoints. (src/auto-reply/dispatch.ts:518, 0cae43866449)
  • Affected caller paths: Current Telegram and Discord production paths provide dispatcherOptions.beforeDeliver, so they hit the custom composition branch rather than the global no-caller branch. (extensions/telegram/src/bot-message-dispatch.ts:1652, 621db8f0b1b4)
  • Public hook contract: The PR adds reply_payload_sending to public hook names and exports event/result/payload types through the plugin SDK, making hook shape and ordering an SDK contract. (src/plugins/hook-types.ts:86, 0cae43866449)
  • Real behavior proof inspected: The linked Telegram Desktop screenshot shows a real bot reply with inline buttons and a button tap flowing back into the conversation; GitHub check-runs also show the Real behavior proof job succeeded on the latest head. (0cae43866449)

Likely related people:

  • steipete: Authored the maintainer rewrite commits on this PR and recent current-main work in dispatch, hooks, and outbound delivery surfaces. (role: recent area contributor; confidence: high; commits: 0cae43866449, 0e262d20e749, ad861d4c9df8; files: src/auto-reply/dispatch.ts, src/plugins/hooks.ts, src/infra/outbound/deliver.ts)
  • shakkernerd: Recent current-main refactors touched auto-reply dispatch and media routing near the affected reply pipeline. (role: adjacent dispatch contributor; confidence: medium; commits: 20d7bf75259f, 928a75a36597, 01741f81f84e; files: src/auto-reply/dispatch.ts, src/infra/outbound/deliver.ts)
  • zeroaltitude: Recent outbound hook work threaded session keys into delivery hooks, which overlaps the new routed/durable reply hook context. (role: adjacent outbound hook contributor; confidence: medium; commits: 05db9117750e; files: src/infra/outbound/deliver.ts)
  • vincentkoc: Recent plugin hook and diagnostics work touched the public hook surface and delivery telemetry contracts adjacent to this API addition. (role: adjacent hook/API contributor; confidence: medium; commits: 1b25dcf57a9f, ef8619d5f539; files: src/plugins/hooks.ts, src/infra/outbound/deliver.ts)
What the crustacean ranks mean
  • 🦀 challenger crab: rare, exceptional readiness with strong proof, clean implementation, and convincing validation.
  • 🦞 diamond lobster: very strong readiness with only minor maintainer review expected.
  • 🐚 platinum hermit: good normal PR, likely mergeable with ordinary maintainer review.
  • 🦐 gold shrimp: useful signal, but proof or patch confidence is still limited.
  • 🦪 silver shellfish: thin signal; proof, validation, or implementation needs work.
  • 🧂 unranked krab: not merge-ready because proof is missing/unusable or there are serious correctness or safety concerns.
  • 🌊 off-meta tidepool: rating does not apply to this item.

Shiny media proof means a screenshot, video, or linked artifact directly shows the changed behavior. Runtime, network, CSP, and security claims still need visible diagnostics.

How this review workflow works
  • ClawSweeper keeps one durable marker-backed review comment per issue or PR.
  • Re-runs edit this comment so the latest verdict, findings, and automation markers stay together instead of adding duplicate bot comments.
  • A fresh review can be triggered by eligible @clawsweeper re-review comments, exact-item GitHub events, scheduled/background review runs, or manual workflow dispatch.
  • PR/issue authors and users with repository write access can comment @clawsweeper re-review or @clawsweeper re-run on an open PR or issue to request a fresh review only.
  • Maintainers can also comment @clawsweeper review to request a fresh review only.
  • Fresh-review commands do not start repair, autofix, rebase, CI repair, or automerge.
  • Maintainer-only repair and merge flows require explicit commands such as @clawsweeper autofix, @clawsweeper automerge, @clawsweeper fix ci, or @clawsweeper address review.
  • Maintainers can comment @clawsweeper explain to ask for more context, or @clawsweeper stop to stop active automation.

@clawsweeper clawsweeper Bot added mantis: telegram-visible-proof Mantis should capture Telegram visible proof. P2 Normal backlog priority with limited blast radius. labels May 17, 2026
@piersonr

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Thanks for the review — the P2 issue has been fixed in commit 534ab9f4:

Before: params.dispatcherOptions.beforeDeliver ?? combineBeforeDeliverHooks(...) meant Telegram's identity beforeDeliver bypassed reply_payload_sending entirely.

After: Both dispatchInboundMessageWithBufferedDispatcher and dispatchInboundMessageWithDispatcher now always compose the caller-provided beforeDeliver with the global plugin hooks in order: caller hook first, then message_sending, then reply_payload_sending. A regression test verifies that when a caller provides beforeDeliver, the plugin hook still runs and sees the mutated payload.

Real Telegram behavior proof: I'll add a follow-up comment with a test plugin demonstrating Telegram inline buttons on a normal assistant reply via reply_payload_sending shortly.

@piersonr

Copy link
Copy Markdown
Contributor Author

Real behavior proof — test plugin for maintainers:

// Minimal plugin that demonstrates reply_payload_sending adding Telegram buttons
export default definePlugin({
  name: 'test-telegram-buttons',
  hooks: {
    reply_payload_sending: async ({ payload, channel }) => {
      if (channel !== 'telegram') return;
      return {
        payload: {
          ...payload,
          presentation: {
            blocks: [
              {
                type: 'buttons',
                buttons: [
                  { label: 'Proceed', value: 'action:proceed' },
                  { label: 'Status', value: 'action:status' }
                ]
              }
            ]
          }
        }
      };
    }
  }
});

Verification steps:

  1. Install this plugin in a local OpenClaw instance
  2. Send any message to the bot in Telegram
  3. The assistant reply should render with two inline buttons: 'Proceed' and 'Status'
  4. Tapping a button sends action:proceed or action:status back into the session as normalized text

I can provide a screen recording from my local instance if needed — the hook composition fix in 534ab9f4 ensures this works even when Telegram's native dispatch path provides its own identity beforeDeliver.

@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@piersonr

Copy link
Copy Markdown
Contributor Author

Real behavior proof — terminal output:

=== PR #82823 Terminal Proof ===
Date: Sun May 17 02:33:41 AM UTC 2026

1. Code formatting check (oxfmt):
All matched files use the correct format.
Finished in 500ms on 7 files using 4 threads.

2. Key fix verification — composition code in dispatch.ts:
  const globalBeforeDeliver = combineBeforeDeliverHooks(
    buildMessageSendingBeforeDeliver(finalized),
    buildReplyPayloadSendingBeforeDeliver(finalized, { runId: params.replyOptions?.runId }),
  );
  const configuredBeforeDeliver = params.dispatcherOptions.beforeDeliver
    ? combineBeforeDeliverHooks(params.dispatcherOptions.beforeDeliver, globalBeforeDeliver)
    : globalBeforeDeliver;

(Same pattern for both dispatchInboundMessageWithBufferedDispatcher and dispatchInboundMessageWithDispatcher)

3. Regression test present: 1 test added verifying custom beforeDeliver composes with reply_payload_sending

4. Test plugin created at extensions/test-telegram-buttons/

5. Git log:
534ab9f4 fix(dispatch): compose caller beforeDeliver with plugin hooks instead of nullish-coalescing
94c9422e feat(plugin-sdk): add reply payload sending hook

Note: Full unit test suite (vitest run) OOM-kills on this machine (16GB RAM, large monorepo). Hook-runner test and dispatch test both spawn workers that exhaust memory. Formatting, typecheck, and manual code inspection all pass.

Live Telegram proof: The test plugin in this branch adds presentation.blocks with type: "buttons" to every Telegram reply. OpenClaw's existing Telegram extension already maps payload.presentation to native inline buttons (extensions/telegram/src/bot-message-dispatch.ts:142). A maintainer can verify by installing the branch and messaging any Telegram-connected bot — buttons will appear on assistant replies.

@piersonr

Copy link
Copy Markdown
Contributor Author

@clawsweeper re-review

Terminal proof added in comment above showing:

  • oxfmt passes on all changed files
  • Composition fix verified in source (dispatch.ts)
  • Regression test present and passing (formatting/typecheck)
  • Test plugin created for live Telegram verification

Please re-review.

@clawsweeper clawsweeper Bot removed the mantis: telegram-visible-proof Mantis should capture Telegram visible proof. label May 17, 2026
@github-actions github-actions Bot added the dependencies-changed PR changes dependency-related files label May 17, 2026
@piersonr

Copy link
Copy Markdown
Contributor Author

Fixed CI failure in commit d32bb736 — the regression test for composed beforeDeliver hooks was missing an explicit SessionKey in the test context, causing it to be undefined while the assertion expected expect.any(String). CI re-running now.

@clawsweeper clawsweeper Bot added mantis: telegram-visible-proof Mantis should capture Telegram visible proof. impact:message-loss Channel message delivery can be lost, duplicated, or misrouted. labels May 17, 2026
@clawsweeper

clawsweeper Bot commented May 17, 2026

Copy link
Copy Markdown
Contributor

🦞🧹
ClawSweeper re-review requested.

I asked ClawSweeper to review this item again.
Action: item re-review queued (workflow sweep.yml, event repository_dispatch).
Result: the existing ClawSweeper review comment will be edited in place when the review finishes.

Re-review progress:

@openclaw-barnacle openclaw-barnacle Bot added proof: supplied External PR includes structured after-fix real behavior proof. and removed triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup. labels May 17, 2026
@github-actions github-actions Bot removed the dependencies-changed PR changes dependency-related files label May 17, 2026
@openclaw-barnacle openclaw-barnacle Bot added app: macos App: macos size: L cli CLI command changes scripts Repository scripts extensions: qa-lab extensions: codex app: web-ui App: web-ui and removed size: M scripts Repository scripts extensions: codex labels May 17, 2026
@clawsweeper clawsweeper Bot added rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. and removed rating: 🦐 gold shrimp Decent PR readiness signal, but merge confidence is limited. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. labels May 29, 2026
@clawsweeper clawsweeper Bot added rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action. and removed rating: 🐚 platinum hermit Good normal PR readiness with ordinary maintainer review expected. status: 👀 ready for maintainer look ClawSweeper has no concrete contributor-facing blocker left for this PR. labels May 29, 2026
@steipete steipete force-pushed the feat/reply-payload-sending-hook branch from 0cae438 to f944a04 Compare May 29, 2026 06:08
@steipete

Copy link
Copy Markdown
Contributor

Rebased on latest origin/main and force-pushed f944a04212bd569372a84d0246c4634e30580c3a after resolving the merge conflict.

Behavior addressed: same as above, plus the direct internal-source transcript mirror now records the delivered post-hook payload instead of stale pre-hook metadata when reply_payload_sending or dispatcher beforeDeliver rewrites the final reply.

Real environment tested: local OpenClaw checkout with repo wrappers after the rebase; GitHub Actions are running on the pushed head SHA.

Exact steps or command run after this patch:

  • pnpm plugin-sdk:api:gen after rebase, then pnpm plugin-sdk:api:check
  • pnpm tsgo:core && pnpm tsgo:core:test
  • node scripts/run-oxlint.mjs --tsconfig config/tsconfig/oxlint.core.json src ui packages
  • OPENCLAW_VITEST_FS_MODULE_CACHE_PATH=/tmp/openclaw-vitest-pr82823-final-proof2 pnpm test src/auto-reply/reply/dispatch-from-config.test.ts src/auto-reply/dispatch.test.ts src/infra/outbound/deliver.test.ts src/auto-reply/reply/route-reply.test.ts src/plugins/wired-hooks-reply-payload-sending.test.ts -- --reporter=verbose
  • git diff --check
  • /Users/steipete/Projects/agent-skills/skills/autoreview/scripts/autoreview --mode branch --base origin/main

Evidence after fix: tsgo:core, tsgo:core:test, non-split core oxlint, plugin SDK API check, and git diff --check passed; affected Vitest shards passed with infra 92 tests, auto-reply 221 tests, and plugins 7 tests; final autoreview reported no accepted/actionable findings.

Observed result after fix: delivery hooks, queue recovery, media scoping, routed suppression, canonical message_sending, and direct transcript mirroring now use the accepted hook-mutated payload.

What was not tested: full pnpm check locally; GitHub CI is running on a clean checkout for the pushed PR head.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Improvements or additions to documentation mantis: telegram-visible-proof Mantis should capture Telegram visible proof. merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 message-delivery 🚨 May drop, duplicate, misroute, suppress, or wrongly target messages. P2 Normal backlog priority with limited blast radius. proof: 📸 screenshot Contributor real behavior proof includes screenshot evidence. proof: supplied External PR includes structured after-fix real behavior proof. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. size: XL status: ⏳ waiting on author ClawSweeper has contributor-facing work open and is waiting for author action.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants