fix(rectification): keep collection denials from stalling the interview
A spoken no neither scored nor declined coverage, so relatives never closed and free-text turns left current_question null. Prefer a same-domain yearless scoring card before an unscoreable collect, resolve explicit collect denials as declined, and persist the next followup after an idle agent turn. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -10,7 +10,7 @@ import {
|
||||
transitionV9CaseStatus,
|
||||
} from "@/lib/rectification-agentic/v9/tool-service";
|
||||
import { decideFromDossier, rectificationFollowupCatalog } from "@/lib/rectification-agentic/v9/decision-from-dossier";
|
||||
import { applyRectificationChoice } from "@/lib/rectification-agentic/v9/answer-choice";
|
||||
import { applyRectificationChoice, applyCollectFocusDenial, persistNextInterviewIfIdle } from "@/lib/rectification-agentic/v9/answer-choice";
|
||||
import { mapRectificationRpcError } from "@/lib/rectification-agentic/v9/case-service";
|
||||
import { CHOICE_ACTION, STOP_ACTION } from "@/lib/rectification-agentic/v9/choice-action";
|
||||
import { runV9AgentTurn, type V9RunBilling } from "@/lib/rectification-agentic/v9/agent-run";
|
||||
@@ -29,8 +29,9 @@ import { parseAgentChoiceCopy } from "@/lib/rectification-agentic/v9/choice-card
|
||||
import {
|
||||
classifyRectificationTurnIntent,
|
||||
optionIdForAnswerClass,
|
||||
shouldDeclineCollectFocus,
|
||||
} from "@/lib/rectification-agentic/v9/turn-intent-classifier";
|
||||
import { persistServerOwnedFocus, openQuestionFromPersistedFocus } from "@/lib/rectification-agentic/v9/server-focus";
|
||||
import { persistServerOwnedFocus, openQuestionFromPersistedFocus, isCollectFocusSchema } from "@/lib/rectification-agentic/v9/server-focus";
|
||||
import { buildMethodFollowupPlan } from "@/lib/rectification-agentic/v9/method-followup";
|
||||
|
||||
export const runtime = "nodejs";
|
||||
@@ -385,6 +386,31 @@ export async function POST(request: Request) {
|
||||
await transitionV9CaseStatus(accounting, userId, caseId, "paused");
|
||||
return completedMessageResponse(applied.narration, requestId, caseId);
|
||||
}
|
||||
} else if (focus && isCollectFocusSchema(focus.expectedAnswerSchema)) {
|
||||
let classified = null;
|
||||
try {
|
||||
classified = await classifyRectificationTurnIntent(selectedModel, {
|
||||
focus,
|
||||
userMessage: parsed.data.message ?? "",
|
||||
caseStatus,
|
||||
signal: request.signal,
|
||||
});
|
||||
} catch {
|
||||
classified = null;
|
||||
}
|
||||
if (shouldDeclineCollectFocus(classified)) {
|
||||
const applied = await applyCollectFocusDenial(accounting, {
|
||||
userId,
|
||||
caseId,
|
||||
focusId: focus.id,
|
||||
});
|
||||
await persistV9DeterministicTurn(accounting, userId, caseId, {
|
||||
requestId,
|
||||
userMessage: parsed.data.message ?? null,
|
||||
assistantMessage: applied.narration,
|
||||
});
|
||||
return completedMessageResponse(applied.narration, requestId, caseId);
|
||||
}
|
||||
} else {
|
||||
let birthDate: string | null = null;
|
||||
try {
|
||||
@@ -617,6 +643,19 @@ export async function POST(request: Request) {
|
||||
if (!result.ok) {
|
||||
send({ type: "error", message: "生时校正暂时不可用,请稍后重试。" });
|
||||
} else {
|
||||
if (action === "message") {
|
||||
try {
|
||||
await persistNextInterviewIfIdle({
|
||||
accounting: accounting as never,
|
||||
userId,
|
||||
caseId,
|
||||
});
|
||||
} catch (error) {
|
||||
console.warn(
|
||||
`[rectification-v9] persist next interview after turn failed case=${caseId} reason=${error instanceof Error ? error.name : "Unknown"}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
send({ type: "done", emitted: true });
|
||||
}
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user