feat(consult): add an answer-step reasoning effort switch

The switch is off unless CONSULT_ANSWER_REASONING_EFFORT is set, so today's request body stays the same. A set value is sent as top-level reasoning_effort only on the answer step. The real A/B did not run: there is no model key.

Request-body probe, the named frontend tests (114 pass, 0 fail), tsc, and lint (0 errors) were run.

Co-Authored-By: Grok (agent loop)
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
jesse-ux
2026-10-15 08:31:19 +08:00
co-authored by Grok (agent loop) Cursor
parent 9274491681
commit ab7f66be14
13 changed files with 775 additions and 28 deletions
+22 -5
View File
@@ -75,6 +75,8 @@ import {
createConsultationRunClock,
consultationContinueGenerationSettings,
consultationGenerationSettings,
consultationGeneralPrepareStep,
consultAnswerEffortProviderOptions,
consultationNatalPrepareStep,
consultationWindowPrepareStep,
createConsultationAgentContext,
@@ -1288,6 +1290,8 @@ export async function POST(request: Request) {
prepareStep: (input: { stepNumber: number }) => consultationNatalPrepareStep({
stepNumber: input.stepNumber,
rectificationOffer: true,
answerReady: state.consultationToolCompleted,
model: selectedModel.model,
}),
};
const windowStreamOptions = {
@@ -1295,6 +1299,15 @@ export async function POST(request: Request) {
prepareStep: (input: { stepNumber: number }) => consultationWindowPrepareStep({
stepNumber: input.stepNumber,
rectificationOffer: true,
answerReady: state.consultationToolCompleted,
model: selectedModel.model,
}),
};
const generalStreamOptions = {
...streamOptions,
prepareStep: (input: { stepNumber: number }) => consultationGeneralPrepareStep({
stepNumber: input.stepNumber,
model: selectedModel.model,
}),
};
const answerPhaseSignal = runClock.answerSignal;
@@ -1305,10 +1318,10 @@ export async function POST(request: Request) {
agent: {
stream: (
messages: typeof baseMessages,
options: typeof streamOptions | typeof natalStreamOptions | typeof windowStreamOptions,
options: typeof streamOptions | typeof natalStreamOptions | typeof windowStreamOptions | typeof generalStreamOptions,
) => Promise<{ fullStream: AsyncIterable<unknown> | ReadableStream<unknown>; totalUsage: Promise<Usage> }>;
},
options: typeof streamOptions | typeof natalStreamOptions | typeof windowStreamOptions = streamOptions,
options: typeof streamOptions | typeof natalStreamOptions | typeof windowStreamOptions | typeof generalStreamOptions = streamOptions,
) {
try {
const result = await agent.stream(baseMessages, options);
@@ -1369,14 +1382,14 @@ export async function POST(request: Request) {
if (usesPublicDailyGeneralAgent(consultationMode, generalDailyContext)) {
state.workflowReceipt = workflowReceipt;
const agent = getGeneralJyotishAgent(selectedModel);
const result = await streamWithOverflowRetry(agent);
const result = await streamWithOverflowRetry(agent, generalStreamOptions);
// This mode has no calculation to require and no chart method to bind,
// so there is no contract for a retry to repair.
const retryForAnswer = async (retryHint?: string) => {
const retried = await agent.stream([
...baseMessages,
{ role: "user" as const, content: `上一轮没有输出任何回答文本。请直接给出这个问题的回答,不要只说明过程。${retryHint ? `\n${retryHint}` : ""}` },
], { ...streamOptions, abortSignal: answerPhaseSignal() });
], { ...generalStreamOptions, abortSignal: answerPhaseSignal() });
usages.push(retried.totalUsage);
return retried.fullStream;
};
@@ -1472,7 +1485,11 @@ export async function POST(request: Request) {
role: "user" as const,
content: `服务器窗口计算已经完成,但上一轮没有输出任何回答文本。请重新取回本次计算结果,然后直接给出回答;不要只描述过程或工具调用。${retryHint ? `\n${retryHint}` : ""}`,
},
], { ...streamOptions, abortSignal: answerPhaseSignal() });
], {
...streamOptions,
abortSignal: answerPhaseSignal(),
...consultAnswerEffortProviderOptions(selectedModel.model),
});
usages.push(retried.totalUsage);
return retried.fullStream;
};