Skip to content

v0.12.0

Choose a tag to compare

@PaulArgoud PaulArgoud released this 09 Jun 17:17
· 3 commits to main since this release

Compatibility pass for mxchat-basic 3.2.8, which makes the Custom Provider
/ Azure OpenAI embedding path work end-to-end (both knowledge-base indexing
and live queries route through the configured endpoint). That activates a path
our dimension auto-detection didn't cover: mxchat stamps the active model as
custom:<id>, a value absent from every embedding registry, so vectors from a
non-1536-dim local model (nomic-embed-text 768, bge-large 1024, Azure
text-embedding-3-large 3072, …) were sized against a silent 1536 default.

No schema migration. Built-in models are unaffected. Safe drop-in from 0.11.1.

Added

  • Empirical dimension probe for Custom / Azure OpenAI providers. When
    MxChat is embedding through a custom endpoint, the Vector schema admin
    section now shows a Detect dimension button. It embeds a probe string via
    mxchat-basic's own MxChat_Utils::generate_embedding_custom() (honouring the
    exact Base URL / auth scheme / model the operator configured), measures the
    returned vector, and caches the result keyed to the active model in
    mxchat_duckdb_custom_embedding_dim. New AJAX handler
    wp_ajax_mxchat_duckdb_detect_dimension (nonce + manage_options gated).
  • MxChat_DuckDB_Options::is_custom_embedding_model(),
    active_embedding_model(), store_probed_custom_dim(), and
    probed_custom_dim() helpers.

Changed

  • detect_embedding_dim() recognises custom:<id> models. For custom
    providers it returns the probed dimension when one was measured against the
    current model, falling back to a 1536 placeholder (clearly labelled in the
    UI as such) otherwise — instead of silently treating the custom model as a
    1536-dim built-in. A stale probe from a previously-configured custom model is
    ignored once the model id changes. Built-in models still resolve through
    mxchat-basic's registry exactly as before.

Notes

  • The insert-time dimension guard in Vector_Store already rejected mismatched
    vectors loudly, so this was never silent corruption — but operators on local
    embedding stacks (the plugin's core audience) no longer have to hand-compute
    the dimension.

Performance & correctness

  • Metrics no longer write wp_options on every query. observe_latency() /
    record() are on the hottest path (a cache hit still recorded a counter),
    and each call did a read-modify-write of the metrics option plus an O(n)
    window trim. They now append to a request-scoped buffer that is merged into
    the option in a single write on shutdown. This drops metrics writes from
    N-per-request to 1-per-request, removes a per-query wp_options write from
    the cache-hit path, and moves the window trim off the hot path. It also
    shrinks the lost-update race (concurrent read-modify-writes dropping samples)
    from per-query to per-request. snapshot() merges the pending buffer so
    within-request reads stay consistent.
  • Compactor sweeps stale-generation query-cache transients. The O(1)
    cache-generation bump makes superseded _transient_mxd_q_* rows unreachable
    but never deletes them; on write-heavy installs they could accumulate in
    wp_options faster than WordPress' expired-transient GC reclaims them. The
    daily compactor now deletes every query-cache transient that isn't the
    current generation. It runs before the sync-freshness guard, so busy
    installs (which early-return on "last sync too recent") still get the sweep.
    No-op under an external object cache.
  • Hardened DuckDB CLI JSON parsing. execute_cli() previously did a single
    json_decode and silently returned [] (no rows, no error) on anything but
    one clean JSON value — so concatenated result sets (init-SQL output + the
    real query) or NDJSON could swallow real results. Parsing now falls back to
    the last top-level array, then to line-by-line NDJSON, before giving up.
  • Memoised CLI-binary autodetection for the request (a mirrored install
    builds two backends, each of which would otherwise re-stat the candidate
    paths and re-spawn command -v), and hoisted the transient-error class/anchor
    lists to constants.

Added (extensibility)

  • mxchat_duckdb_filter_fields filter — map extra Pinecone-style filter
    field names to physical columns (for add-ons storing custom per-vector
    metadata). Column names are validated against /^[a-zA-Z0-9_]+$/ before they
    touch SQL, so a bad entry is dropped rather than becoming an injection vector.
    See docs/HOOKS.md.

CI

  • Fixed the composer audit job. It ran composer install --no-dev then a
    plain composer audit, which errored with "No installed packages found"
    because the plugin has zero runtime dependencies. It now audits the locked
    production set directly (composer audit --locked --no-dev --abandoned=report):
    a no-op that stays green today and trips the instant a vulnerable production
    dependency is introduced.