Script Filter Plugin
The Script Filter plugin removes runs of non-Latin characters (CJK, kana, hangul, …) that a model sometimes leaks into otherwise-Latin output. It strips them live during streaming (replacing each run with a placeholder) and, when the turn finishes, optionally translates the removed fragments back into the surrounding language and revises the message in place.
Configuration
plugins:
- module: codumentor.plugins.script_filter
class: ScriptFilterPlugin
priority: 70
args:
enabled: true
scope: both # both | content | thinking
placeholder: "□"
translate: true
target_language: auto # 'auto' = match the surrounding text
request_timeout_seconds: 20.0
defer_translation: true
Parameters
- enabled (optional): Strip characters at all (default:
true) - scope (optional): Where to strip —
"both","content"(visible answer), or"thinking"(reasoning) (default:"both") - placeholder (optional): Shown in place of each removed run during streaming;
""deletes with no marker and disables translation (default:"□") - translate (optional): Translate removed fragments when the turn finishes (default:
true) - target_language (optional): Language to translate into;
"auto"detects the dominant surrounding language (default:"auto") - request_timeout_seconds (optional): Hard timeout for synchronous translation (default:
20.0) - defer_translation (optional): Run finish-time translation as a background job (with retry) instead of blocking the turn; falls back to synchronous translation if no job queue is available (default:
true) - Advanced:
model_role,temperature,max_tokens,coalesce_adjacent,translation_max_attempts,translation_retry_backoff_seconds, and customunicode_ranges/patternfor the character set to strip.
How It Works
The plugin has no agent tools — it is pure content transformation via two hooks:
onLLMStream(priority 20, early): replaces target-character runs in each streamed delta with the placeholder and caches the removed text, keyed by the turn'srun_id.onBeforeSendResponse(priority 70): when the turn finishes, translates the cached fragments and edits them back into the final message (per segment for multi-segment turns).
When defer_translation is on, the finish-time translation runs as a script_filter_translation background job: it retries with backoff and rewrites both the displayed message (an SSE revision) and the LLM-history placeholder rows.
Notes
- The placeholder briefly flashes during streaming; the translation lands after the turn completes, as a post-hoc revision.
- If translation fails (or
placeholderis""), the placeholders simply remain — the turn is never blocked or corrupted. - Subagent output is left untouched.
- A settings widget toggles stripping/translation and sets the placeholder and target language.
- Finish-time message revision relies on the same machinery as the Permalink plugin's response correction.