From 464d2c82302b6cea1eb057f751e8a13a5595458a Mon Sep 17 00:00:00 2001 From: Khalid A Date: Fri, 17 Apr 2026 20:07:16 -0500 Subject: [PATCH] Fix LLM returning null for repo_relative_path in routing Two changes: 1. Add `format: "json"` to Ollama API calls so the model enforces JSON output mode, reducing malformed responses 2. Strengthen the routing prompt with explicit type constraints ("NEVER null or empty"), rules to copy manifest paths exactly, and a concrete example response This fixes the validation error: "repo_relative_path: Expected string, received null" from qwen3.5:397b-cloud. Co-Authored-By: Claude Sonnet 4.6 --- server/src/llm/client.ts | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/server/src/llm/client.ts b/server/src/llm/client.ts index c3d6638..1a0570b 100644 --- a/server/src/llm/client.ts +++ b/server/src/llm/client.ts @@ -20,7 +20,7 @@ async function ollamaChat(messages: Array<{ role: string; content: string }>, mo 'Content-Type': 'application/json', ...(OLLAMA_API_KEY ? { Authorization: `Bearer ${OLLAMA_API_KEY}` } : {}), }, - body: JSON.stringify({ model, messages, stream: false }), + body: JSON.stringify({ model, messages, stream: false, format: 'json' }), }); if (!resp.ok) { @@ -124,14 +124,20 @@ export async function routeEditIntent(params: RouteEditIntentParams, chat?: LlmC role: 'system', content: `You are a routing assistant for a website CMS. Given a natural language edit request and a manifest of available content sections, determine which section file the edit applies to. -Return a JSON object with: -- "repo_relative_path": the path of the target section file -- "needs_clarification": true if the request is ambiguous -- "reason": short explanation -- "clarification_message": (only if needs_clarification) a question to ask the user +Return a JSON object with EXACTLY these fields: +- "repo_relative_path": a STRING — the path of the target section file from the manifest (e.g. "content/sections/hero.json"). NEVER null or empty. +- "needs_clarification": a boolean — true only if the request is genuinely ambiguous between multiple sections +- "reason": a short string explaining the routing decision +- "clarification_message": a string (only when needs_clarification is true) — a question to ask the user -If the request is about showing/hiding/enabling/disabling a section, route to that section's file. -If the request mentions events, route to "content/events.json".`, +Rules: +- "repo_relative_path" MUST be one of the paths listed in the MANIFEST. Copy it exactly. +- If the request is about showing/hiding/enabling/disabling a section, route to that section's file. +- If the request mentions events, route to "content/events.json". +- When in doubt, pick the most likely section rather than marking ambiguous. + +Example response: +{"repo_relative_path": "content/sections/hero.json", "needs_clarification": false, "reason": "Request about hero section headline"}`, }, { role: 'user',