fix(minecraft): validate LLM response structure to retry on invalid format

This commit is contained in:
Rin
2026-02-18 11:14:08 +08:00
committed by Neko Ayaka
parent c21b997569
commit 1c942a84c8
@@ -53,10 +53,19 @@ function extractJsonCandidate(input: string): string {
return trimmed return trimmed
} }
function validateLLMResponse(parsed: unknown): parsed is { thought: string, actions: unknown[] } {
if (typeof parsed !== 'object' || parsed === null)
return false
const obj = parsed as Record<string, unknown>
// Must have 'thought' (string) and 'actions' (array) at minimum
return typeof obj.thought === 'string' && Array.isArray(obj.actions)
}
function parseLLMResponseJson<T>(response: string): T { function parseLLMResponseJson<T>(response: string): T {
const candidate = extractJsonCandidate(response) const candidate = extractJsonCandidate(response)
let parsed: unknown
try { try {
return JSON.parse(candidate) as T parsed = JSON.parse(candidate)
} }
catch (err) { catch (err) {
const pos = getJsonErrorPosition(err) const pos = getJsonErrorPosition(err)
@@ -66,6 +75,14 @@ function parseLLMResponseJson<T>(response: string): T {
: candidate.slice(0, Math.min(candidate.length, 240)) : candidate.slice(0, Math.min(candidate.length, 240))
throw new Error(`Failed to parse LLM JSON response: ${toErrorMessage(err)}; snippet=${JSON.stringify(snippet)}`) throw new Error(`Failed to parse LLM JSON response: ${toErrorMessage(err)}; snippet=${JSON.stringify(snippet)}`)
} }
// Validate structure - LLM sometimes hallucinates wrong format (e.g., tool call format)
if (!validateLLMResponse(parsed)) {
const snippet = JSON.stringify(parsed).slice(0, 200)
throw new Error(`LLM returned malformed response (missing thought/actions): ${snippet}`)
}
return parsed as T
} }
function getErrorStatus(err: unknown): number | undefined { function getErrorStatus(err: unknown): number | undefined {