fix(web): exit rectification when the probe pool is exhausted (BUG-558)
Stop falling through to "say another event" after dated and occupation collect are done. Deliver an adopt path or a gate sentence, and add a spoken-collect stop control. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -33,7 +33,7 @@ import { createAdminSupabaseClient } from "@/lib/supabase/admin";
|
||||
import { createServerSupabaseClient } from "@/lib/supabase/server";
|
||||
import { defaultMessageOrigin, isRectificationMessageOrigin } from "@/lib/rectification-agentic/v9/message-origin";
|
||||
import { previousInferenceFromReceipt } from "@/lib/rectification-agentic/v9/inference-adapter";
|
||||
import { parseAgentChoiceCopy } from "@/lib/rectification-agentic/v9/choice-card";
|
||||
import { CHOICE_STOP_LABEL, parseAgentChoiceCopy } from "@/lib/rectification-agentic/v9/choice-card";
|
||||
import {
|
||||
classifyRectificationTurnIntent,
|
||||
optionIdForAnswerClass,
|
||||
@@ -283,6 +283,58 @@ export async function POST(request: Request) {
|
||||
const actionId = parsed.data.actionId;
|
||||
const focusId = parsed.data.focusId;
|
||||
const expectedRevision = parsed.data.expectedRevision;
|
||||
if (action === "stop_and_review") {
|
||||
if (!actionId) {
|
||||
return NextResponse.json(
|
||||
{ error: "选择题请求缺少 actionId" },
|
||||
{ status: 400 },
|
||||
);
|
||||
}
|
||||
if (!focusId) {
|
||||
try {
|
||||
await transitionV9CaseStatus(accounting, userId, caseId, "paused");
|
||||
const idle = await persistNextInterviewIfIdle({
|
||||
accounting,
|
||||
userId,
|
||||
caseId,
|
||||
narrateAdopt,
|
||||
});
|
||||
const assistantMessage = idle.hostNarration || nonConvergingRangeNarration({ variant: "delivery" });
|
||||
const turn = await persistV9DeterministicTurn(accounting, userId, caseId, {
|
||||
requestId,
|
||||
userMessage: CHOICE_STOP_LABEL,
|
||||
assistantMessage,
|
||||
});
|
||||
return NextResponse.json({
|
||||
type: "choice.applied",
|
||||
action: "applied",
|
||||
replayed: false,
|
||||
status: "narrated",
|
||||
narrationPersisted: true,
|
||||
focusId: null,
|
||||
questionId: parsed.data.questionId ?? null,
|
||||
optionId: "stop",
|
||||
probeId: null,
|
||||
caseRevision: expectedRevision ?? 0,
|
||||
narration: assistantMessage,
|
||||
userMessage: CHOICE_STOP_LABEL,
|
||||
turnId: turn.turnId,
|
||||
});
|
||||
} catch (error) {
|
||||
if (error instanceof RectificationToolServiceError) {
|
||||
const mapped = mapRectificationRpcError(error);
|
||||
return NextResponse.json(
|
||||
{ error: mapped.message, message: mapped.message, code: mapped.code },
|
||||
{ status: mapped.status },
|
||||
);
|
||||
}
|
||||
return NextResponse.json(
|
||||
{ error: "选择题处理失败", message: "请稍后重试。" },
|
||||
{ status: 500 },
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!actionId || !focusId || expectedRevision === undefined) {
|
||||
return NextResponse.json(
|
||||
{ error: "选择题请求缺少 actionId、focusId 或 expectedRevision" },
|
||||
@@ -417,7 +469,7 @@ export async function POST(request: Request) {
|
||||
return completedMessageResponse(applied.narration, requestId, caseId, applied.turnId);
|
||||
}
|
||||
}
|
||||
if (classified.intent === "stop_rectification") {
|
||||
if (classified.intent === "stop_rectification" || classified.intent === "ask_about_result") {
|
||||
const previous = previousInferenceFromReceipt(dossier.latestResult?.decisionReceipt ?? null);
|
||||
const applied = await applyRectificationChoice(accounting, {
|
||||
userId,
|
||||
@@ -449,6 +501,26 @@ export async function POST(request: Request) {
|
||||
} catch {
|
||||
classified = null;
|
||||
}
|
||||
if (classified?.intent === "stop_rectification" || classified?.intent === "ask_about_result") {
|
||||
const previous = previousInferenceFromReceipt(dossier.latestResult?.decisionReceipt ?? null);
|
||||
const applied = await applyRectificationChoice(accounting, {
|
||||
userId,
|
||||
caseId,
|
||||
sessionId,
|
||||
actionId: requestId,
|
||||
action: STOP_ACTION,
|
||||
focusId: focus.id,
|
||||
questionId: focus.questionId,
|
||||
probeId: typeof focus.expectedAnswerSchema.probe_id === "string"
|
||||
? focus.expectedAnswerSchema.probe_id
|
||||
: null,
|
||||
optionId: "stop",
|
||||
expectedRevision: previous?.revision ?? 0,
|
||||
userDisplay: parsed.data.message ?? null,
|
||||
});
|
||||
await transitionV9CaseStatus(accounting, userId, caseId, "paused");
|
||||
return completedMessageResponse(applied.narration, requestId, caseId, applied.turnId);
|
||||
}
|
||||
if (shouldDeclineCollectFocus(classified)) {
|
||||
const continueToAgent = shouldContinueAgentForDatedEvent(classified);
|
||||
const applied = await applyCollectFocusDenial(accounting, {
|
||||
|
||||
Reference in New Issue
Block a user