fix(tui): strip inbound metadata blocks from user text#22319
fix(tui): strip inbound metadata blocks from user text#22319Kansodata wants to merge 110 commits intoopenclaw:mainfrom
Conversation
* vincentkoc-code/security-fix-hono-2026.2.20: Security: bump hono for timing-safe auth hardening
* fix(docker): pin base images to SHA256 digests for supply chain security Pin all 9 Dockerfiles to immutable SHA256 digests to prevent supply chain attacks where a compromised upstream image could be silently pulled into production builds. Also add Docker ecosystem to Dependabot configuration for automated digest updates. Images pinned: - node:22-bookworm@sha256:cd7bcd2e7a1e6f72052feb023c7f6b722205d3fcab7bbcbd2d1bfdab10b1e935 - node:22-bookworm-slim@sha256:3cfe526ec8dd62013b8843e8e5d4877e297b886e5aace4a59fec25dc20736e45 - debian:bookworm-slim@sha256:98f4b71de414932439ac6ac690d7060df1f27161073c5036a7553723881bffbe - ubuntu:24.04@sha256:cd1dba651b3080c3686ecf4e3c4220f026b521fb76978881737d24f200828b2b Fixes openclaw#7731 Co-Authored-By: Claude Opus 4.5 <[email protected]> * test(docker): add digest pinning regression coverage --------- Co-authored-by: Claude Opus 4.5 <[email protected]>
…nclaw#21086) * fix: treat HTTP 503 as failover-eligible for LLM provider errors When LLM SDKs wrap 503 responses, the leading "503" prefix is lost (e.g. Google Gemini returns "high demand" / "UNAVAILABLE" without a numeric prefix). The existing isTransientHttpError only matches messages starting with "503 ...", so these wrapped errors silently skip failover — no profile rotation, no model fallback. This patch closes that gap: - resolveFailoverReasonFromError: map HTTP status 503 → rate_limit (covers structured error objects with a status field) - ERROR_PATTERNS.overloaded: add /\b503\b/, "service unavailable", "high demand" (covers message-only classification when the leading status prefix is absent) Existing isTransientHttpError behavior is unchanged; these additions are complementary and only fire for errors that previously fell through unclassified. * fix: address review feedback — drop /\b503\b/ pattern, add test coverage - Remove `/\b503\b/` from ERROR_PATTERNS.overloaded to resolve the semantic inconsistency noted by reviewers: `isTransientHttpError` already handles messages prefixed with "503" (→ "timeout"), so a redundant overloaded pattern would classify the same class of errors differently depending on message formatting. - Keep "service unavailable" and "high demand" patterns — these are the real gap-fillers for SDK-rewritten messages that lack a numeric prefix. - Add test case for JSON-wrapped 503 error body containing "overloaded" to strengthen coverage. * fix: unify 503 classification — status 503 → timeout (consistent with isTransientHttpError) resolveFailoverReasonFromError previously mapped status 503 → "rate_limit", while the string-based isTransientHttpError mapped "503 ..." → "timeout". Align both paths: structured {status: 503} now also returns "timeout", matching the existing transient-error convention. Both reasons are failover-eligible, so runtime behavior is unchanged. --------- Co-authored-by: Vincent Koc <[email protected]>
…verbose logs, and WebUI (openclaw#20704)
…0988) * fix(slack): pass recipient_team_id and recipient_user_id to streaming API calls The Slack Agents & AI Apps streaming API (chat.startStream / chat.stopStream) requires recipient_team_id and recipient_user_id parameters. Without them, stopStream fails with 'missing_recipient_team_id' (all contexts) or 'missing_recipient_user_id' (DM contexts), causing streamed messages to disappear after generation completes. This passes: - team_id (from auth.test at provider startup, stored in monitor context) - user_id (from the incoming message sender, for DM recipient identification) through to the ChatStreamer via recipient_team_id and recipient_user_id options. Fixes openclaw#19839, openclaw#20847, openclaw#20299, openclaw#19791, openclaw#20337 AI-assisted: Written with Claude (Opus 4.6) via OpenClaw. Lightly tested (unit tests pass, live workspace verification in progress). * fix(slack): disable block streaming when native streaming is active When Slack native streaming (`chat.startStream`/`stopStream`) is enabled, `disableBlockStreaming` was set to `false`, which activated the app-level block streaming pipeline. This pipeline intercepted agent output, sent it via block replies, then dropped the final payloads that would have flowed through `deliverWithStreaming` to the Slack streaming API — resulting in zero replies delivered. Set `disableBlockStreaming: true` when native streaming is active so the final reply flows through the Slack streaming API path as intended. Co-Authored-By: Claude Opus 4.6 <[email protected]> --------- Co-authored-by: Claude Opus 4.6 <[email protected]> Co-authored-by: Vincent Koc <[email protected]>
…#11046) - Changed "cask" to "formula" in SKILL.md for consistency. - Enhanced formula parsing in frontmatter.ts to trim whitespace and fallback to cask if formula is not provided.
…penclaw#21447) Fixes the pairing required regression from openclaw#21236 for legacy paired devices created without roles/scopes metadata. Detects legacy paired metadata shape and skips upgrade enforcement while backfilling metadata in place on reconnect. Co-authored-by: Josh Avant <[email protected]> Co-authored-by: Val Alexander <[email protected]>
Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 0427165 Co-authored-by: adhitShet <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…enclaw#21410) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 7b8fe75 Co-authored-by: adhitShet <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…claw#21408) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 993860b Co-authored-by: adhitShet <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…#21332) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: b6c8d1e Co-authored-by: adhitShet <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…nclaw#21231) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 68adbf5 Co-authored-by: ahdernasr <[email protected]> Co-authored-by: joshavant <[email protected]> Reviewed-by: @joshavant
…law#21303) Merged via /review-pr -> /prepare-pr -> /merge-pr. Prepared head SHA: 20d058d Co-authored-by: adhitShet <[email protected]> Co-authored-by: gumadeiras <[email protected]> Reviewed-by: @gumadeiras
…18786) thanks @rodrigouroz Verified: - pnpm install --frozen-lockfile - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: rodrigouroz <[email protected]> Co-authored-by: Tak Hoffman <[email protected]>
…openclaw#21533) thanks @Takhoffman Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: Tak Hoffman <[email protected]>
…aw#20508) thanks @echoVic Verified: - pnpm build - pnpm check - pnpm test:macmini Co-authored-by: echoVic <[email protected]> Co-authored-by: Tak Hoffman <[email protected]>
|
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. |
26 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. |
|
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. |
|
Superseded by clean reroute: #22345. |
Summary
Describe the problem and fix in 2–5 bullets:
Conversation info (untrusted metadata)JSON blocks) instead of only user-authored text.role: "user"insrc/tui/tui-formatters.ts, removing known inbound metadata blocks before rendering.Change Type (select all)
Scope (select all touched areas)
Linked Issue/PR
User-visible / Behavior Changes
Security Impact (required)
Yes/No) NoYes/No) NoYes/No) NoYes/No) NoYes/No) NoYes, explain risk + mitigation:Repro + Verification
Environment
Steps
extractTextFromMessage).Expected
Actual
Evidence
Attach at least one:
Human Verification (required)
What you personally verified (not just CI), and how:
pnpm vitest run src/tui/tui-formatters.test.tspasses.assistant) content with similar text is preserved.Compatibility / Migration
Yes/No) YesYes/No) NoYes/No) NoFailure Recovery (if this breaks)
fix(tui): strip inbound metadata blocks from user text.src/tui/tui-formatters.ts,src/tui/tui-formatters.test.ts.Risks and Mitigations
Greptile Summary
Adds metadata block stripping for TUI user messages to prevent internal scaffolding from appearing in the chat UI. The implementation correctly identifies and removes known inbound metadata headers (conversation info, sender, thread starter, replied message, forwarded context, chat history) that are prefixed to user messages, cleaning up the visual presentation while preserving the actual user text.
Key changes:
INBOUND_METADATA_HEADERSarray matching the canonical source insrc/auto-reply/reply/inbound-meta.ts:94-180stripLeadingInboundMetadataBlocks()that loops to remove multiple consecutive metadata blocksrole: "user"messages inextractTextFromMessage(), preserving assistant messages unchangedObservations:
\r\nand\nline endingsConfidence Score: 5/5
Last reviewed commit: 477c588