The chat-completions refactor removed the legacy Perplexity "text"
extraction but left two tests asserting the old behavior, breaking
make check on every CI flavor:
- test_ai_parse_response_perplexity_text expected the legacy /v1/agent
nested format to parse; it now yields NULL — renamed to
test_ai_parse_response_legacy_text_format_unsupported.
- test_ai_parse_response_text_preferred_over_content expected "text"
to win; "content" is authoritative now — renamed to
test_ai_parse_response_content_preferred_over_text.
Add test_ai_set_provider_setting_reserved_key covering the new
reserved-key rejection.
Custom setting values were JSON-escaped but emitted unquoted, so any
non-numeric value (e.g. "high") produced an invalid JSON payload and
failed the whole request; quoting the value manually could not work
either, since the escaper turns quotes into \". Emit RFC 8259 scalars
(number/true/false/null) bare and everything else as a quoted JSON
string.
Reserved payload keys (model, messages, stream) would duplicate the
fixed fields with parser-dependent precedence; reject them in
ai_set_provider_setting (surfaced as an error by /ai set custom) and
skip them at payload-build time for settings loaded from hand-edited
prefs.
provider->settings was mutated on the main thread while the request
thread iterates it when building the payload; guard both sides with a
new per-provider settings_lock.
Also refresh stale docs: ai_parse_response no longer mentions the
dropped Perplexity "text" path, the payload docstring says "messages"
instead of "input", and the /ai help example uses a realistic scalar
setting.