/** * Spoken-answer generation settings shared by consultation and rectification. * * DeepSeek hidden reasoning and visible content can share one `max_tokens` * cap. The spoken budget stays 16384; when provider thinking is on, the * output cap is spoken + thinking so CoT cannot pinch the user-facing reply. * Reasoning must travel on `reasoning-delta` / `thinking.delta`, never on * `answer.delta`. */ export const AGENT_ANSWER_OUTPUT_TOKENS = 16_384; export const AGENT_THINKING_OUTPUT_TOKENS = 8_192; export const AGENT_SLICE_ANSWER_OUTPUT_TOKENS = 8_192; export const AGENT_SLICE_THINKING_OUTPUT_TOKENS = 2_048; /** @deprecated Use AGENT_ANSWER_OUTPUT_TOKENS; kept as the compose-budget alias. */ export const AGENT_MAX_OUTPUT_TOKENS = AGENT_ANSWER_OUTPUT_TOKENS; export type ThinkingMode = "enabled" | "disabled"; export type ReasoningEffort = "low" | "medium" | "high"; export function agentOutputTokenBudget( thinking: ThinkingMode, options: { answerTokens?: number; thinkingTokens?: number } = {}, ): number { const answerTokens = options.answerTokens ?? AGENT_ANSWER_OUTPUT_TOKENS; if (thinking !== "enabled") return answerTokens; return answerTokens + (options.thinkingTokens ?? AGENT_THINKING_OUTPUT_TOKENS); } export function agentGenerationSettings( model?: unknown, options: { thinking?: ThinkingMode; answerTokens?: number; thinkingTokens?: number; reasoningEffort?: ReasoningEffort; } = {}, ) { const thinkingMode: ThinkingMode = options.thinking ?? "disabled"; const thinking = { thinking: { type: thinkingMode, ...(thinkingMode === "enabled" && options.reasoningEffort ? { reasoningEffort: options.reasoningEffort } : {}), }, }; const providerId = typeof model === "string" ? model : model && typeof model === "object" && "providerId" in model && typeof model.providerId === "string" ? model.providerId : undefined; const providerOptions: Record = { openai: thinking, }; if (providerId) providerOptions[providerId] = thinking; return { modelSettings: { maxOutputTokens: agentOutputTokenBudget(thinkingMode, { answerTokens: options.answerTokens, thinkingTokens: options.thinkingTokens, }), }, providerOptions, }; }