fix(frontend): recover rectification and consultation retries
Independent Staging Quality Gate / validate (push) Successful in 14m1s
Independent Staging Quality Gate / publish (push) Successful in 9m58s

This commit is contained in:
Jesse_Chen
2026-08-16 13:13:49 +08:00
parent 8ddcef4cf1
commit 9d8570640d
6 changed files with 124 additions and 12 deletions
+1
View File
@@ -597,6 +597,7 @@ button:disabled { cursor: default; opacity: .45; }
.product-entrypoint-footer small { min-width: 0; flex: 1; }
.product-entrypoint-action { display: inline-flex; flex: 0 0 auto; align-items: center; justify-content: flex-end; gap: var(--space-1); color: var(--color-action); font-size: var(--type-caption); font-weight: 600; white-space: nowrap; }
.product-entrypoint-action .starter-arrow { width: 15px; height: 15px; color: currentColor; }
.rectification-entry-error { grid-column: 1 / -1; margin: 0; }
.starter-loading { color: var(--color-ink-secondary); margin-left: 0; padding: var(--space-5); border-radius: var(--radius-lg); background: var(--color-canvas-muted); font-size: 14px; }
.starter-note { margin: 10px 0 0; color: var(--color-ink-secondary); line-height: 1.5; grid-column: 1 / -1; font-size: 13px; }
.message-list { margin: 0 auto; width: min(900px, 100%); padding: var(--space-8) var(--space-8) var(--space-16); }
+13 -9
View File
@@ -1118,6 +1118,9 @@ export default function Home() {
},
);
const rectificationCardLabel = rectificationEntryLabels[rectificationCardAction];
const rectificationErrorMessage = rectificationError === "profile_incomplete"
? "服务端未能读取完整出生资料,请重新确认并保存后再开始生时校正。"
: rectificationError;
const onboardingFingerprint = onboardingProfileFingerprint(profile);
useEffect(() => {
@@ -2411,14 +2414,10 @@ export default function Home() {
const payload = await response.json().catch(() => null);
if (!response.ok) {
const code = payload?.code;
if (code === "profile_incomplete" || code === "invalid_open_request") {
const step = missingProfileStep(profile);
if (step) {
setRectificationSessionId(null);
setRectificationCaseId(null);
setOnboardingStep(step);
setComposerNotice("请先完成出生资料,再开始生时校正。");
}
if (code === "profile_incomplete") {
handleRectificationProfileIncomplete();
} else if (code === "invalid_open_request") {
setRectificationError(payload?.error || "生时校正打开请求不正确,请刷新后重试。");
} else if (code === "active_case_conflict") {
setRectificationError(payload?.error || "仍有未完成的校正,请先回到当前校正。");
} else if (code === "case_session_not_found") {
@@ -2466,7 +2465,7 @@ export default function Home() {
void refreshRectificationEntrySummary();
return opened;
} catch {
setComposerNotice("生时校正会话暂时无法打开,请稍后重试。");
setRectificationError("生时校正会话暂时无法打开,请稍后重试。");
return null;
} finally {
rectificationOpenInFlight.current = false;
@@ -3391,6 +3390,11 @@ export default function Home() {
</div>
</article>
</section>
{rectificationError && !rectificationSurfaceOpen && (
<p className="form-error rectification-entry-error" role="alert">
{rectificationErrorMessage}
</p>
)}
<section className="starter-themes" aria-labelledby="starter-themes-heading">
<div className="starter-section-heading">
+9 -3
View File
@@ -186,13 +186,13 @@ export function createConsultationTools(ctx: ConsultationAgentContext) {
description: "Run one server-validated plan of up to six allowlisted personal Jyotish consultation domains. Use domains in priority order; birth data is server-bound and must never be supplied by the model.",
inputSchema: consultationToolInputSchema,
execute: async (input, context) => {
const domains = canonicalDomainPlan(input, ctx);
if (calculation) return calculation;
ctx.state.consultationToolStarted = true;
ctx.state.consultationToolCallCount += 1;
const startedAt = Date.now();
calculation = (async () => {
const currentCalculation = (async () => {
try {
const domains = canonicalDomainPlan(input, ctx);
const userIntent = ctx.plan?.userIntent ?? input.question;
await context.writer?.custom({
type: "data-jyotish-activity",
@@ -250,7 +250,13 @@ export function createConsultationTools(ctx: ConsultationAgentContext) {
throw error;
}
})();
return calculation;
calculation = currentCalculation;
try {
return await currentCalculation;
} catch (error) {
if (calculation === currentCalculation) calculation = null;
throw error;
}
},
});
return { "run-jyotish-consultation": consultationTool };