fix(rectification): show the house table and hide the activity fold
Independent Staging Quality Gate / validate (push) Failing after 9m39s
Independent Staging Quality Gate / publish (push) Has been skipped

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
Jesse_Chen
2026-08-19 20:07:51 +08:00
parent 4c33329b0c
commit c8af18e90a
19 changed files with 438 additions and 100 deletions
@@ -44,9 +44,11 @@ function useMarkdownRenderer() {
export function ChatMessageContent({
text,
auditRows,
vargaSentence,
}: {
text: string;
auditRows?: readonly TechniqueAuditRow[];
vargaSentence?: string | null;
}) {
const renderMarkdown = useMarkdownRenderer();
const split = splitSpokenAnswerAndTechniqueAudit(text);
@@ -64,6 +66,7 @@ export function ChatMessageContent({
))}
</div>
) : null}
{vargaSentence ? <p className="message-varga-sentence">{vargaSentence}</p> : null}
{rows.length > 0 ? <TechniqueAuditDisclosure rows={rows} /> : null}
</div>
);
@@ -38,9 +38,11 @@ export function AgentAvatar() {
export function ChatMessageRow({
message,
showActivity = message.state !== "settled",
vargaSentence,
}: Readonly<{
message: ChatMessageView;
showActivity?: boolean;
vargaSentence?: string | null;
}>) {
const messageRow = useRef<HTMLElement>(null);
const assistantLabel = message.state === "thinking"
@@ -101,6 +103,7 @@ export function ChatMessageRow({
<ChatMessageContent
text={message.text}
auditRows={message.agentExecutionReceipt?.techniqueAuditTable}
vargaSentence={vargaSentence}
/>
)}
</>
@@ -6,6 +6,7 @@ import type {
PublicRectificationMethod,
PublicRectificationTool,
} from "@/lib/rectification-agentic/v9/public-receipt";
import { PUBLIC_RECTIFICATION_METHOD_LABELS } from "@/lib/rectification-varga-sentence";
const TOOL_LABELS: Readonly<Record<PublicRectificationTool, string>> = {
"rectification-read-case": "读取校正记录",
@@ -23,23 +24,7 @@ const TOOL_LABELS: Readonly<Record<PublicRectificationTool, string>> = {
"rectification-close-case": "完成校正记录",
};
const METHOD_LABELS: Readonly<Record<PublicRectificationMethod, string>> = {
"d1-rashi": "D1 本命盘",
"d2-hora": "D2 财帛分盘",
"d4-chaturthamsha": "D4 迁移分盘",
"d9-navamsa": "D9 婚姻分盘",
"d10-dashamsa": "D10 事业分盘",
"d11-labhamsha": "D11 收益分盘",
"d24-chaturvimshamsha": "D24 教育分盘",
"d30-trimshamsha": "D30 健康压力分盘",
"vimshottari-dasha": "Vimshottari",
"narayana-dasha": "Narayana",
gochara: "Gochara",
ashtakavarga: "Ashtakavarga",
shadbala: "Shadbala",
"arudha-pada": "Arudha Pada",
"functional-benefic-malefic": "本命功能吉凶星",
};
const METHOD_LABELS = PUBLIC_RECTIFICATION_METHOD_LABELS;
const METHOD_GROUPS: readonly Readonly<{
label: string;
@@ -16,10 +16,10 @@ import {
type RectificationCandidateResult,
} from "@/lib/rectification-candidate-result";
import { membershipHref } from "@/lib/membership";
import { vargaSentenceFromMethods } from "@/lib/rectification-varga-sentence";
import {
isPublicRectificationMethod,
isPublicRectificationTool,
type PublicRectificationTool,
} from "@/lib/rectification-agentic/v9/public-receipt";
import type { PublicLanguageModel } from "@/lib/public-models";
import { ChatMessageRow } from "./chat-message-row";
@@ -27,8 +27,8 @@ import {
ChatMessageActions,
toggleChatMessageFeedback,
} from "./chat-message-actions";
import { CompletedActivityReceipt } from "./completed-activity-receipt";
import { ModelSelector } from "./model-selector";
import { RectificationHouseTableView } from "./rectification-house-table";
import { Button } from "./ui/button";
import { Textarea } from "./ui/textarea";
@@ -74,33 +74,11 @@ type RectificationAgenticChatProps = Readonly<{
type RenderMessage = ChatMessageView & {
renderKey: string;
activeActivity?: PublicActivity;
completedReceipt?: CompletedActivityReceiptView;
failed?: boolean;
turnId?: string;
};
type PublicActivity = Readonly<{
tool: PublicRectificationTool;
label: string;
}>;
const ACTIVE_TOOL_LABELS: Readonly<Record<PublicRectificationTool, string>> = {
"rectification-read-case": "正在读取校正记录…",
"rectification-set-focus": "正在设置对话焦点…",
"rectification-resolve-focus": "正在处理当前焦点…",
"rectification-record-evidence-batch": "正在整理多条事件证据…",
"rectification-propose-evidence": "正在整理事件证据…",
"rectification-confirm-evidence": "正在确认事件证据…",
"rectification-revise-evidence": "正在修订事件证据…",
"rectification-compare-candidates": "正在比较候选时间…",
"rectification-read-diagnostics": "正在检查候选稳健性…",
"rectification-offer-candidates": "正在生成候选建议…",
"rectification-accept-candidate": "正在采用候选时间…",
"rectification-confirm-birth-time": "正在确认校正时间…",
"rectification-close-case": "正在完成校正记录…",
};
function completedReceiptFromPersisted(receipt: PersistedTurn["receipt"]): CompletedActivityReceiptView {
if (!receipt) return { steps: [], methods: [] };
if (Array.isArray(receipt.tool_activities)) {
@@ -132,13 +110,6 @@ export function toggleRectificationFeedback(
return toggleChatMessageFeedback(current, requested);
}
function activityPhase(tool: PublicRectificationTool): NonNullable<ChatMessageView["activity"]>["phase"] {
if (tool === "rectification-compare-candidates" || tool === "rectification-read-diagnostics") {
return "chart-calculation";
}
return "evidence-validation";
}
function hasActivityReceipt(receipt: CompletedActivityReceiptView): boolean {
return receipt.steps.length > 0 || receipt.methods.length > 0 || Boolean(receipt.failedTool);
}
@@ -354,13 +325,7 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
} else if (event.type === "tool.activity") {
const tool = isPublicRectificationTool(event.tool) ? event.tool : null;
if (!tool) continue;
if (event.status === "started") {
const activeActivity = { tool, label: ACTIVE_TOOL_LABELS[tool] } satisfies PublicActivity;
setMessages((current) => current.map((message) => message.renderKey === assistantRenderKey
? { ...message, activeActivity }
: message));
continue;
}
if (event.status === "started") continue;
if (event.status !== "completed" && event.status !== "failed") continue;
activityReceiptState = reduceRectificationActivityReceipt(activityReceiptState, {
tool,
@@ -370,12 +335,6 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
: [],
});
completedReceipt = receiptFromRectificationActivityState(activityReceiptState);
setMessages((current) => current.map((message) => message.renderKey === assistantRenderKey
? {
...message,
activeActivity: message.activeActivity?.tool === tool ? undefined : message.activeActivity,
}
: message));
}
}
}
@@ -389,7 +348,6 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
...message,
text: parsed.text,
state: "settled",
activeActivity: undefined,
completedReceipt,
failed: false,
turnId: completedTurnId,
@@ -400,7 +358,6 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
...message,
text: "",
state: "settled",
activeActivity: undefined,
completedReceipt,
failed: true,
}];
@@ -431,7 +388,6 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
...message,
text: "",
state: "settled",
activeActivity: undefined,
completedReceipt,
failed: true,
}]
@@ -564,27 +520,23 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
&& !readonly
&& regeneratingMessageKey === null;
const displayedMessage = regenerating
? { ...message, text: "", state: "thinking" as const, activeActivity: undefined }
? { ...message, text: "", state: "thinking" as const }
: message;
const vargaSentence = message.state === "settled" && !message.failed
? vargaSentenceFromMethods(message.completedReceipt?.methods)
: null;
return (
<div key={message.renderKey} className="rectification-message-wrap rectification-message-entry">
{message.state === "settled" && message.failed && !message.completedReceipt?.failedTool && (
{message.state === "settled" && message.failed && (
<p className="rectification-activity-failure" role="status">
</p>
)}
{message.state === "settled" && message.completedReceipt && (
<CompletedActivityReceipt receipt={message.completedReceipt} />
)}
{(!message.failed || Boolean(displayedMessage.text) || regenerating) && (
<ChatMessageRow
message={{
...displayedMessage,
activity: displayedMessage.activeActivity
? { phase: activityPhase(displayedMessage.activeActivity.tool), label: displayedMessage.activeActivity.label }
: undefined,
}}
showActivity={displayedMessage.state === "thinking" || Boolean(displayedMessage.activeActivity)}
message={displayedMessage}
showActivity={displayedMessage.state === "thinking"}
vargaSentence={vargaSentence}
/>
)}
{showActions && !regenerating && (
@@ -603,6 +555,9 @@ export function RectificationAgenticChat(props: RectificationAgenticChatProps) {
</div>
);
})}
{candidateResult?.houseTable && (
<RectificationHouseTableView table={candidateResult.houseTable} />
)}
{candidateResult?.selectionAllowed && (
<section className="rectification-candidates" aria-label="生时校正候选时间">
<div className="rectification-candidates-heading">
@@ -0,0 +1,38 @@
"use client";
import type { RectificationHouseTable } from "@/lib/rectification-candidate-result";
export function RectificationHouseTableView({
table,
}: Readonly<{ table: RectificationHouseTable }>) {
return (
<section className="rectification-house-table" aria-label="本命宫位表">
<div className="rectification-house-table__heading">
<strong></strong>
<span>
{table.time} {table.lagna}
</span>
</div>
<div className="markdown-table">
<table>
<thead>
<tr>
<th scope="col"></th>
<th scope="col"></th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
{table.houses.map((house) => (
<tr key={house.house}>
<th scope="row">{house.house}</th>
<td>{house.sign}</td>
<td>{house.occupants.length > 0 ? house.occupants.join("、") : "—"}</td>
</tr>
))}
</tbody>
</table>
</div>
</section>
);
}