Skip to content

dispatchReplyWithBufferedBlockDispatcher swallows deliver info.kind parameter #215

@Jerry-Xin

Description

@Jerry-Xin

Problem

The dmwork adapter cannot distinguish between streaming block chunks and the final reply in its deliver callback because OpenClaw core's createNormalizedOutboundDeliverer() swallows the second info parameter.

Background

OpenClaw core provides a kind field via the second parameter of the deliver callback:

deliver: async (payload: ReplyPayload, info: { kind: 'tool' | 'block' | 'final' }) => { ... }
  • block — intermediate streaming chunk
  • tool — tool call result
  • final — final complete reply

Discord receives info.kind correctly because it uses createReplyDispatcherWithTyping(), which passes (payload, info) directly to the deliver callback.

DMWork does not receive info.kind because it uses dispatchReplyWithBufferedBlockDispatcher(), which internally wraps the deliver callback with createNormalizedOutboundDeliverer():

// In reply-payload-*.js (OpenClaw core)
function createNormalizedOutboundDeliverer(handler) {
    return async (payload) => {  // <-- only payload, info is dropped!
        await handler(normalizeOutboundReplyPayload(payload));
    };
}

The wrapper only forwards payload, silently discarding the info argument. As a result, info is always undefined in the dmwork adapter's deliver callback.

Impact

Without info.kind, the adapter cannot distinguish streaming chunks from the final message. The previous workaround (draft-edit pattern using editMessage) caused issue #213 — forwarded/copied messages showing stale pre-edit content.

Possible Solutions

  1. Upstream fix: Fix createNormalizedOutboundDeliverer to forward info:

    return async (payload, info) => {
        await handler(normalizeOutboundReplyPayload(payload), info);
    };
  2. Switch to createReplyDispatcherWithTyping: Align with Discord's approach (larger refactor).

  3. Workaround (current PR fix: buffer deliver text and send once after dispatcher completes #214): Buffer all text in deliver, send once after dispatcher completes. Works but loses streaming typing effect.

Related

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions