From bde21992bdacf72f226bad26fd87583d1ee4b7d1 Mon Sep 17 00:00:00 2001 From: Nils Briggen Date: Mon, 8 Jun 2026 23:52:51 +0200 Subject: [PATCH] Let complete() accept coerce/preprocess schemas (fix tsc -b build) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The "creatures" alias fix wraps the balance schema in z.preprocess, whose input type is `unknown`. complete()'s `schema?: ZodType` pinned input=output=T, so T inferred as unknown and `res.data.add` failed under tsc -b (project build). Loosen schema input to `ZodType` — T stays pinned to the schema output, but coerce/preprocess/transform schemas (input ≠ T) are accepted. Pin the advisor call's type param to BalanceSuggestion, matching the other complete<...> call sites. Co-Authored-By: Claude Opus 4.8 (1M context) --- src/features/assistant/useEncounterAdvisor.ts | 2 +- src/lib/llm/types.ts | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/features/assistant/useEncounterAdvisor.ts b/src/features/assistant/useEncounterAdvisor.ts index 6b1ce20..eae059e 100644 --- a/src/features/assistant/useEncounterAdvisor.ts +++ b/src/features/assistant/useEncounterAdvisor.ts @@ -127,7 +127,7 @@ export function useEncounterAdvisor(campaign: Campaign, encounter: Encounter) { if (canUseLlm) { const prompt = buildBalancePrompt(ctx, { difficulty: current, targetDifficulty: target, candidates }); - const res = await complete(getLlmConfig(), { system: prompt.system, user: prompt.user, schema: balanceSuggestionSchema }); + const res = await complete(getLlmConfig(), { system: prompt.system, user: prompt.user, schema: balanceSuggestionSchema }); if (res.ok && 'data' in res) { const valid = res.data.add.filter((a) => candidates.some((c) => c.name === a.name)); if (valid.length) { diff --git a/src/lib/llm/types.ts b/src/lib/llm/types.ts index 67fb822..82e32a2 100644 --- a/src/lib/llm/types.ts +++ b/src/lib/llm/types.ts @@ -1,4 +1,4 @@ -import type { ZodType } from 'zod'; +import type { ZodType, ZodTypeDef } from 'zod'; export type LlmProvider = 'anthropic' | 'openai-compatible'; @@ -34,8 +34,10 @@ export interface CompleteOptions { system: string; /** User message. */ user: string; - /** When provided, structured JSON output is requested and validated against it. */ - schema?: ZodType; + /** When provided, structured JSON output is requested and validated against it. + * Input is left open (`any`) so schemas using coerce/preprocess/transform — whose + * parsed input type differs from T — are accepted; T is pinned to the output. */ + schema?: ZodType; /** A short name describing the JSON shape (used by providers that require it). */ schemaName?: string; signal?: AbortSignal;