From e8c04e77983dbbf54d62a59eb074e7fd130c9d24 Mon Sep 17 00:00:00 2001 From: Dejvino Date: Sun, 13 Sep 2026 20:30:54 +0200 Subject: [PATCH] =?UTF-8?q?LLM:=20allow=20sparse=20optional=20edits=20?= =?UTF-8?q?=E2=80=94=20disable=20strict=20JSON=20schema?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Responses API via Vercel AI Gateway requires `required` to include every key when `strict:true`. Our TweakEditsSchema has 7 optional song knobs, so sparse edits (e.g. only {brightness: 0.3}) were rejected with 400: Missing 'arrangement'. - src/llm/llmTweak.js: createOpenAI({ strictJsonSchema: false }) so the gateway accepts optional properties; keeps zod validation + clampEdits as the real guardrail. - src/llm/spec.js: drop .strict() on TweakEditsSchema — extra keys are stripped rather than erroring, more robust against model drift. Co-Authored-By: Claude --- flow-state/src/llm/llmTweak.js | 1 + flow-state/src/llm/spec.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/flow-state/src/llm/llmTweak.js b/flow-state/src/llm/llmTweak.js index b1f89df..859f7d8 100644 --- a/flow-state/src/llm/llmTweak.js +++ b/flow-state/src/llm/llmTweak.js @@ -97,6 +97,7 @@ export async function requestSongTweak({ spec, track, look, hint = '', config = baseURL: isDev ? '/__llm/v1' : cfg.gatewayUrl, apiKey: cfg.apiKey, fetch: isDev ? proxyFetch : undefined, + strictJsonSchema: false, }); const modelId = cfg.model; diff --git a/flow-state/src/llm/spec.js b/flow-state/src/llm/spec.js index f1e9794..72a5ae9 100644 --- a/flow-state/src/llm/spec.js +++ b/flow-state/src/llm/spec.js @@ -19,7 +19,7 @@ export const TweakEditsSchema = z.object({ dynamics: z.number().min(0).max(1).optional(), transition: z.number().min(0).max(1).optional(), arrangement: z.enum(ARRANGEMENT_VALUES).optional(), -}).strict(); +}); export const TweakResultSchema = z.object({ rationale: z.string().min(1).max(800),