#!/usr/bin/env bash set -euo pipefail MODE="${1:-check}" TUI_FILE="${OPENCLAW_TUI_DIST:-$HOME/.npm-global/lib/node_modules/openclaw/dist/tui-LeOEBhMz.js}" PATCH_DIR="${OPENCLAW_TUI_PATCH_DIR:-$HOME/.openclaw/workspace/patches/openclaw-tui-internal-filter}" MARKER='function looksLikeInternalRuntimeContext(text) {' if [[ ! -f "$TUI_FILE" ]]; then echo "error: TUI dist file not found: $TUI_FILE" >&2 exit 2 fi mkdir -p "$PATCH_DIR" is_patched() { rg -q "looksLikeInternalRuntimeContext\(text\)" "$TUI_FILE" } check_mode() { if is_patched; then echo "patched: yes" return 0 fi echo "patched: no" return 1 } apply_mode() { if is_patched; then echo "already patched: $TUI_FILE" return 0 fi local ts backup ts="$(date -u +"%Y%m%dT%H%M%SZ")" backup="$PATCH_DIR/tui-LeOEBhMz.js.$ts.bak" cp "$TUI_FILE" "$backup" TUI_FILE="$TUI_FILE" python3 - <<'PY' from pathlib import Path import os import sys path = Path(os.environ["TUI_FILE"]) text = path.read_text(encoding="utf-8") old = '''function extractTextFromMessage(message, opts) { \tconst record = asMessageRecord(message); \tif (!record) return ""; \tconst text = extractTextBlocks(record.content, opts); \tif (text) { \t\tif (record.role === "user") return stripLeadingInboundMetadata(text); \t\treturn text; \t} \tconst errorText = formatAssistantErrorFromRecord(record); \tif (!errorText) return ""; \treturn errorText; } ''' new = '''function looksLikeInternalRuntimeContext(text) { \tif (!text) return false; \treturn text.includes("OpenClaw runtime context (internal):") && text.includes("[Internal task completion event]"); } function extractTextFromMessage(message, opts) { \tconst record = asMessageRecord(message); \tif (!record) return ""; \tconst text = extractTextBlocks(record.content, opts); \tif (text) { \t\tconst normalized = record.role === "user" ? stripLeadingInboundMetadata(text) : text; \t\tif (looksLikeInternalRuntimeContext(normalized)) return ""; \t\treturn normalized; \t} \tconst errorText = formatAssistantErrorFromRecord(record); \tif (!errorText) return ""; \treturn errorText; } ''' if old not in text: print("error: expected upstream function block not found; aborting for safety", file=sys.stderr) sys.exit(3) path.write_text(text.replace(old, new, 1), encoding="utf-8") print("patched") PY # Parse sanity check (module import) node -e "import(process.argv[1]).then(()=>console.log('syntax:ok')).catch((e)=>{console.error(e);process.exit(1);})" "$TUI_FILE" echo "backup: $backup" echo "patched file: $TUI_FILE" echo "restart TUI to pick up changes." } revert_mode() { local latest latest="$(ls -1t "$PATCH_DIR"/tui-LeOEBhMz.js.*.bak 2>/dev/null | head -n1 || true)" if [[ -z "$latest" ]]; then echo "error: no backup found in $PATCH_DIR" >&2 exit 4 fi cp "$latest" "$TUI_FILE" node -e "import(process.argv[1]).then(()=>console.log('syntax:ok')).catch((e)=>{console.error(e);process.exit(1);})" "$TUI_FILE" echo "restored from: $latest" } case "$MODE" in check) check_mode ;; apply) apply_mode ;; revert) revert_mode ;; *) echo "usage: $0 [check|apply|revert]" >&2 exit 1 ;; esac