Parallelize deferred media understanding calls in resolveSummaryLines and
applyDeferredMediaToQueuedRuns using Promise.allSettled so media API calls
run concurrently while summary line order stays sequential.
Replace findFirstOccurrenceBeforeFileBlocks (which truncated at the first
<file> tag) with findLastOccurrenceOutsideFileBlocks that searches the full
prompt via lastIndexOf and skips matches inside <file>…</file> blocks. This
fixes body replacement when thread/history context has extracted file blocks
before the current queued message body.
Add regression test for body appearing after thread-history file blocks.
Replace regex-based file extraction detection (FILE_BLOCK_RE.test) with a
DeferredFileBlocksExtracted mutation marker on FollowupMediaContext. The old
approach scanned user body text for '<file name=' patterns, which could
false-positive on literal user messages. The new approach compares Body
against RawBody (never mutated by the primary path) to detect file extraction,
then stores a boolean marker for subsequent checks.
Fixes 2 & 4 (linked):
- Added DeferredFileBlocksExtracted marker to FollowupMediaContext type
- Mutation detection uses RawBody (not CommandBody) as reference to avoid
false-positives when /think directives differ between Body and CommandBody
- snapshotUpdatedMediaContext propagates the marker via appliedFile
Fixes 1, 3, 5, 6 were already addressed by prior commits on this branch.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Scope file-block stripping to body region only, preserving file blocks
in quoted/replied text and thread history above the body
- Gate file-extraction skip on mutation evidence (Body differs from
resolved original) instead of raw '<file name=' text matching to avoid
false-positives on user messages containing literal XML
- Document collect-mode scope limitation in applyDeferredMediaUnderstandingToQueuedRun
- Rename duplicate test description to distinguish body-alongside-text case
- Prefer updated prompt over original summaryLine in overflow summaries
so captioned voice note transcripts are surfaced
Voice notes arriving while the agent is mid-turn were queued as
followup messages without audio transcription. The followup runner
called runEmbeddedPiAgent directly, bypassing applyMediaUnderstanding.
This adds a mediaContext field to FollowupRun that snapshots the
original message's media fields. Before the agent run, the followup
runner checks whether media understanding was applied. If not (empty
MediaUnderstanding), it calls applyMediaUnderstanding and rebuilds the
prompt with the transcript, matching the primary path's formatting.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
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>