Files
Jyotisha/frontend/src/lib/agent-generation-settings.ts
T
Jesse_Chen 04463e9af3 feat(web): show consult runs as a Lucide timeline with sliced compose
Keep provider thinking on a separate channel so process talk is not billed as the spoken reply (BUG-359).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-23 14:38:50 +08:00

66 lines
2.3 KiB
TypeScript

/**
* 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<string, typeof thinking> = {
openai: thinking,
};
if (providerId) providerOptions[providerId] = thinking;
return {
modelSettings: {
maxOutputTokens: agentOutputTokenBudget(thinkingMode, {
answerTokens: options.answerTokens,
thinkingTokens: options.thinkingTokens,
}),
},
providerOptions,
};
}