Skip to content

Commit 58138ea

Browse files
ralyodioclaude
andcommitted
fix(autoblog): two Anthropic SDK foot-guns hiding behind structured-output
Why detect+enrich looked like it "prefilled with placeholders": the LLM call was silently failing, leaving niche/audiences/description empty, so the form fell through to its placeholder text. Two distinct bugs, both in lib/lx/detectBlog.ts (and one repeating in lib/lx/articleGen.ts). 1. `zodOutputFormat` needs `zod/v4`. @anthropic-ai/sdk@0.95.x's helpers/zod.mjs does `import * as z from 'zod/v4'` and calls `z.toJSONSchema(...)` — a v4-only API. Importing plain "zod" gives a v3 schema whose `_def` shape v4 can't read → "Cannot read properties of undefined (reading 'def')" at runtime. lib/audit/claude-engine.ts already imports from "zod/v4" with a warning comment; the new lx/ files missed it. 2. Haiku 4.5 rejects `output_config.effort`. Adaptive thinking is a Sonnet/Opus feature. Passing effort to Haiku returns 400 "This model does not support the effort parameter." Drop effort + thinking for Haiku-only call sites; keep them on the article-generation call (Sonnet) where they're valid. Reproduced locally against crawlproof.com — discover finds blog + sitemap; enrichment now returns a real { niche, target_audiences, description } in ~5s on Haiku 4.5. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent b7f31fc commit 58138ea

2 files changed

Lines changed: 11 additions & 4 deletions

File tree

‎lib/lx/articleGen.ts‎

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,10 @@
1515
import type { SupabaseClient } from "@supabase/supabase-js";
1616
import OpenAI from "openai";
1717
import Anthropic from "@anthropic-ai/sdk";
18-
import { z } from "zod";
18+
// The SDK's zod helper imports from "zod/v4" internally and calls
19+
// z.toJSONSchema() — a v4-only API. Importing plain "zod" gives v3
20+
// schemas whose `_def` shape v4 can't read.
21+
import { z } from "zod/v4";
1922
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";
2023
import { markdownToHtml } from "../markdown";
2124

‎lib/lx/detectBlog.ts‎

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,11 @@
2626

2727
import Anthropic from "@anthropic-ai/sdk";
2828
import { zodOutputFormat } from "@anthropic-ai/sdk/helpers/zod";
29-
import { z } from "zod";
29+
// The SDK's zod helper imports from "zod/v4" internally and calls
30+
// z.toJSONSchema() — a v4-only API. Importing plain "zod" gives v3
31+
// schemas whose `_def` shape v4 can't read, producing the
32+
// "Cannot read properties of undefined (reading 'def')" crash.
33+
import { z } from "zod/v4";
3034
import { detectSitemapUrl } from "./sitemap";
3135

3236
const FETCH_TIMEOUT_MS = 8000;
@@ -460,9 +464,9 @@ export async function enrichBlogProfile(
460464
const stream = anthropic.messages.stream({
461465
model: HAIKU_MODEL,
462466
max_tokens: 700,
463-
thinking: { type: "disabled" },
467+
// Haiku 4.5 has no adaptive thinking and rejects the `effort`
468+
// parameter — only Sonnet/Opus accept it. Pass `format` alone.
464469
output_config: {
465-
effort: "low",
466470
// eslint-disable-next-line @typescript-eslint/no-explicit-any
467471
format: zodOutputFormat(ProfileLLMOutput as any),
468472
},

0 commit comments

Comments
 (0)