P2-1 (agent-runner.ts): Restrict direct completion notice to
block-streaming runs. The condition now checks blockStreamingEnabled
in addition to opts?.onBlockReply, preventing duplicate completion
notices in non-streaming sessions where verboseNotices already handles
the compaction-complete text.
P2-2 (agent-runner-execution.ts): Emit compaction start notice when
streaming is off. blockReplyHandler is a no-op for non-streaming runs,
so add a direct fallback path: when blockStreamingEnabled is false and
opts.onBlockReply is present, send the start notice directly with
applyReplyToMode threading applied.
Enqueueing the completion notice into blockReplyPipeline before flush
caused didStream() to return true even when no assistant content was
streamed. buildReplyPayloads drops all finalPayloads when didStream()
is true, so the real assistant reply could be silently discarded on
non-streaming model paths (e.g. pi-embedded-subscribe) that fill
assistantTexts without emitting block replies.
Fix: move the completion notice send to *after* pipeline flush+stop,
using a fire-and-forget Promise.race with blockReplyTimeoutMs. This
keeps the timeout guarantee (satisfying the previous P1) while not
touching didStream() at all.
Non-streaming fallback (verboseNotices) is unchanged.
Addresses P1 review comment on PR #38805.
Previously the completion notice bypassed the block-reply pipeline by
calling opts.onBlockReply directly after the pipeline had already been
flushed and stopped. This meant timeout/abort handling and serial
delivery guarantees did not apply to the notice, risking stalls or
out-of-order delivery in streaming/routed runs.
Fix: enqueue the completion notice into blockReplyPipeline *before*
flush so it is delivered through the same path as every other block
reply. The non-streaming fallback (verboseNotices) is preserved for
runs where no pipeline exists.
Also removes the now-unnecessary direct opts.onBlockReply call and
cleans up the redundant suffix in the pre-flush path (count suffix is
still included in the verboseNotices fallback path where count is
available).
Addresses P1 review comment on PR #38805.
Compaction start and completion notices were sent via raw
opts.onBlockReply, bypassing createBlockReplyDeliveryHandler and the
applyReplyToMode pipeline. In channels configured with
replyToMode=all|first, this caused compaction notices to be delivered
as unthreaded top-level messages while all other replies stayed
threaded — inconsistent and noisy.
Fix agent-runner-execution.ts: extract createBlockReplyDeliveryHandler
result into blockReplyHandler and share it between onBlockReply and the
compaction start notice in onAgentEvent. Both now use the same handler.
Fix agent-runner.ts: inject currentMessageId + replyToCurrent into the
completion notice payload before passing through applyReplyToMode, so
threading directives are honoured consistently with normal replies.
Closes the P2 review comment on PR #38805 (agent-runner.ts:701).
In block-streaming mode, the reply pipeline bypasses buildReplyPayloads,
so notices only pushed to verboseNotices were never delivered to the user.
The start notice ("🧹 Compacting context...") was already sent via
opts.onBlockReply directly in agent-runner-execution.ts; mirror the same
path for the completion notice.
- If opts.onBlockReply is present (streaming mode): await onBlockReply
with the completion text directly, so it reaches the user immediately.
- Otherwise (non-streaming): push to verboseNotices as before so it gets
prepended to the final payload batch.
Also consolidate the verbose vs. non-verbose text selection into a single
completionText variable, removing the redundant pop/push pattern.
During auto-compaction the agent goes silent for several seconds while
the context is summarised. Users on every channel (Discord, Feishu,
Telegram, webchat …) had no indication that something was happening —
leading to confusion and duplicate messages.
Changes:
- agent-runner-execution.ts: listen for compaction phase='start' event
and immediately deliver a "🧹 Compacting context..." notice via the
existing onBlockReply callback. This fires for every channel because
onBlockReply is the universal in-run delivery path.
- agent-runner.ts: make the completion notice unconditional (was
previously guarded behind verboseEnabled). Non-verbose users now see
"✅ Context compacted (count N)."; verbose users continue to see the
legacy "🧹 Auto-compaction complete (count N)." wording.
Why onBlockReply for start?
onBlockReply is already wired to every channel adapter and fires during
the live run, so the notice arrives in-band with zero new plumbing.
Using verboseNotices (appended after the run) would be too late and
would miss the start signal entirely.
Fixes: users seeing silent pauses of 5-15 s with no feedback during
compaction on any channel.
- Added a test to ensure no warnings for legacy Brave config when bundled web search allowlist compatibility is applied.
- Updated validation logic to incorporate compatibility configuration for bundled web search plugins.
- Refactored the ensureRegistry function to utilize the new compatibility handling.
* test: align extension runtime mocks with plugin-sdk
Update stale extension tests to mock the plugin-sdk runtime barrels that production code now imports, and harden the Signal tool-result harness around system-event assertions so the channels lane matches current extension boundaries.
Regeneration-Prompt: |
Verify the failing channels-lane tests against current origin/main in an isolated worktree before changing anything. If the failures reproduce on main, keep the fix test-only unless production behavior is clearly wrong. Recent extension refactors moved Telegram, WhatsApp, and Signal code onto plugin-sdk runtime barrels, so update stale tests that still mock old core module paths to intercept the seams production code now uses. For Signal reaction notifications, avoid brittle assertions that depend on shared queued system-event state when a direct harness spy on enqueue behavior is sufficient. Preserve scope: only touch the failing tests and their local harness, then rerun the reproduced targeted tests plus the full channels lane and repo check gate.
* test: fix extension test drift on main
* fix: lazy-load bundled web search plugin registry
* test: make matrix sweeper failure injection portable
* fix: split heavy matrix runtime-api seams
* fix: simplify bundled web search id lookup
* test: tolerate windows env key casing
Reuse pi-ai's Anthropic client injection seam for streaming, and add
the OpenClaw-side provider discovery, auth, model catalog, and tests
needed to expose anthropic-vertex cleanly.
Signed-off-by: sallyom <somalley@redhat.com>