diff --git a/scripts/openclaw-tui-internal-filter.md b/scripts/openclaw-tui-internal-filter.md new file mode 100644 index 0000000..ac8d7d0 --- /dev/null +++ b/scripts/openclaw-tui-internal-filter.md @@ -0,0 +1,28 @@ +# TUI Internal Runtime Event Filter (local patch) + +This workspace carries a **local** patch workflow to suppress internal subagent handoff blocks from the OpenClaw TUI chat log. + +## Commands + +```bash +scripts/openclaw-tui-internal-filter.sh check +scripts/openclaw-tui-internal-filter.sh apply +scripts/openclaw-tui-internal-filter.sh revert +``` + +## Update-safe workflow + +Prefer: + +```bash +scripts/openclaw-update-safe.sh +``` + +This runs `openclaw update ...` and then re-checks/re-applies the TUI patch if needed. + +## Notes + +- Patch target: `~/.npm-global/lib/node_modules/openclaw/dist/tui-LeOEBhMz.js` +- Apply is idempotent. +- Backups are stored in `patches/openclaw-tui-internal-filter/` (ignored by git). +- If upstream code shape changes, apply aborts safely instead of forcing an unsafe patch. diff --git a/scripts/openclaw-tui-internal-filter.sh b/scripts/openclaw-tui-internal-filter.sh new file mode 100755 index 0000000..a0412c1 --- /dev/null +++ b/scripts/openclaw-tui-internal-filter.sh @@ -0,0 +1,115 @@ +#!/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 diff --git a/scripts/openclaw-update-safe.sh b/scripts/openclaw-update-safe.sh new file mode 100755 index 0000000..6e7f04f --- /dev/null +++ b/scripts/openclaw-update-safe.sh @@ -0,0 +1,30 @@ +#!/usr/bin/env bash +set -euo pipefail + +# Safe updater wrapper: +# 1) runs normal OpenClaw update flow +# 2) re-applies local TUI internal-event filter patch if needed + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PATCH_SCRIPT="$SCRIPT_DIR/openclaw-tui-internal-filter.sh" + +if [[ ! -x "$PATCH_SCRIPT" ]]; then + echo "error: missing patch script: $PATCH_SCRIPT" >&2 + exit 2 +fi + +openclaw update "$@" + +# Skip patching for purely informational paths +if [[ "${1:-}" == "status" || "${1:-}" == "wizard" || "${1:-}" == "--dry-run" ]]; then + echo "note: update command did not modify install; patch status unchanged." + "$PATCH_SCRIPT" check || true + exit 0 +fi + +echo "Re-validating TUI internal-event filter patch..." +if "$PATCH_SCRIPT" check; then + echo "patch already present." +else + "$PATCH_SCRIPT" apply +fi