mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-10 05:12:14 +00:00
The Anthropic client steered JSON replies by appending an assistant turn containing an opening brace and gluing the brace back onto the reply. Current Claude models (the 4.6 / 4.7 / 4.8 family, Opus 5, Sonnet 5, Fable 5 and 5.1) reject an assistant prefill with HTTP 400, so every JSON surface on the provider (briefing, status cards, document and lab extraction) failed for a self-hoster on a current model while plain chat kept working. Drop the prefill on every model. The request now carries a plain instruction on the last user turn to reply with a single JSON object and nothing else, and the reply is narrowed to the outermost object body via a shared extractJsonObject helper, so a fenced or prefixed answer still parses. The insights stripJsonFences helper delegates to the same function rather than keeping a second copy. The tool-use path is unchanged. Reported independently by @sweidinger.
27 lines
971 B
TypeScript
27 lines
971 B
TypeScript
/**
|
|
* Isolate the JSON object body of a model reply.
|
|
*
|
|
* Providers without a native JSON mode (Anthropic, the local endpoints)
|
|
* are steered by a prompt instruction alone, and a compliant model still
|
|
* routinely wraps its object in a ```json fence or puts a sentence in
|
|
* front of it. This helper drops a leading/trailing fence and narrows to
|
|
* the outermost `{` ... `}` span so `JSON.parse` sees the object.
|
|
*
|
|
* It is a no-op on already-clean JSON and on fence-free prose with no
|
|
* braces: both return the trimmed input, so a prose fallback downstream
|
|
* still works.
|
|
*/
|
|
export function extractJsonObject(raw: string): string {
|
|
let text = raw.trim();
|
|
const fenced = text.match(/^```(?:json)?\s*\n?([\s\S]*?)\n?```$/i);
|
|
if (fenced) {
|
|
text = fenced[1].trim();
|
|
}
|
|
const first = text.indexOf("{");
|
|
const last = text.lastIndexOf("}");
|
|
if (first !== -1 && last !== -1 && last > first) {
|
|
return text.slice(first, last + 1);
|
|
}
|
|
return text;
|
|
}
|