Skip to content

v0.4.3 — Foundation: PHPStan, security hardening, SSE parser + modal carve

Choose a tag to compare

@oxyc oxyc released this 29 May 14:54
· 19 commits to main since this release
58282b4

No-behaviour-change maintenance release. Four small waves of cleanup that make the next round of feature work safer to touch.

Foundation (CI)

  • PHPStan level 5 added to the lint job, 52 pre-existing errors fixed (return-type narrowing on ToolProviderInterface::getTools, dead is_wp_error checks, ?? new \stdClass precedence). Builds now fail on new static-analysis regressions.
  • Jest wired up for client-side helpers; first suite covers editor/diff.js (17 tests).

Security hardening

  • Prompt-injection defence on selection context. ChatEndpoint::buildSelectionPreamble now strips control characters and wraps user-selected text in a labelled tilde fence so block content can't smuggle instructions into the system prompt path.
  • Try/finally on temp files in ImageGenerationToolProvider::sideloadBinary — orphan files no longer accumulate when the sideload fails mid-flight.

SSE parser consolidation

  • Extracted SseStreamReader (131 LOC) — every streaming provider was hand-rolling the same curl + line-buffered data: parser. Anthropic/OpenAI-compatible/Gemini now delegate, shedding ~150 LOC of duplication.
  • Fixed a real precedence bug in Gemini's mime-type guess ('image/' . pathinfo(...) ?: 'jpeg' defaulted to the whole string when no extension was present).

assistant-modal.jsx carve-up

  • 2577 LOC → 778 LOC (−70%) split across 8 focused modules: MicButton, ReadAloudController, UndoContext, ToolCallFallback, Messages, Composer, SidePanels, skills-cache. Render order, hook order, and ref identities preserved end-to-end; verified by manual smoke (list → edit → undo) on generogrowth.

Misc

  • Plugin::polylangVoiceLanguages bare catch replaced with logged \Throwable catch (was hiding silent failures).
  • MessageLoop token accumulators now cast through (int) so providers returning numeric strings can't poison the running total.
  • new static()new self() in Plugin::getInstance for tighter typing.

Full changelog: v0.4.2...v0.4.3