diff --git a/apps/worker/src/lib/deepseek.ts b/apps/worker/src/lib/deepseek.ts index b1045b6..123c480 100644 --- a/apps/worker/src/lib/deepseek.ts +++ b/apps/worker/src/lib/deepseek.ts @@ -64,13 +64,15 @@ export async function callDeepSeek(opts: { const model = modelForTier(opts.tier); const url = `${BASE}/v1/messages`; - const body = { + const enableThinking = (process.env.DEEPSEEK_THINKING ?? "false") === "true"; + const body: Record = { model, max_tokens: opts.maxOutputTokens, temperature: opts.temperature ?? 0.3, system: opts.systemPrompt, messages: [{ role: "user" as const, content: opts.userPrompt }], }; + if (!enableThinking) body.thinking = { type: "disabled" }; const start = Date.now(); let res: Response; @@ -97,9 +99,13 @@ export async function callDeepSeek(opts: { } catch { throw new DeepSeekError(res.status, `non-json: ${text.slice(0, 200)}`); } - const content = parsed?.content?.[0]?.text; + // V4 models may emit a "thinking" block before the final "text" block. + // Find the first text block; thinking blocks are not billed as output_tokens. + const blocks = Array.isArray(parsed?.content) ? parsed.content : []; + const textBlock = blocks.find((b: any) => b && b.type === "text" && typeof b.text === "string"); + const content = textBlock?.text; if (typeof content !== "string") { - throw new DeepSeekError(res.status, `no content text: ${text.slice(0, 200)}`); + throw new DeepSeekError(res.status, `no text block (got types: ${blocks.map((b: any) => b?.type).join(",")})`); } const usage = parsed.usage ?? {};