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;