chore: save current work
This commit is contained in:
@@ -18,8 +18,7 @@ export function CadProgressPart({ data }: { data: CadProgress }) {
|
||||
const statusLabel = isRunning ? "进行中" : isWaiting ? data.lifecycle === "waiting_retry" ? "等待重试" : "等待确认" : isError ? "失败" : status === "success" ? "完成" : data.status;
|
||||
const Icon = data.step === "tool_call" ? Wrench : data.step.includes("review") || data.step === "final_review" ? Eye : data.step === "rollback" ? RotateCcw : data.step.includes("requirements") || data.step.includes("checklist") ? FileCheck : data.step.includes("diagnostic") ? Search : isError || isWaiting ? AlertTriangle : Check;
|
||||
const evidence = data.evidence || (Array.isArray(data.review?.evidence) ? data.review.evidence.map(String) : []);
|
||||
const documentTitle = data.step === "requirements_review" ? "需求合同复核" : "";
|
||||
const documentMarkdown = data.step === "requirements_document" ? withoutRequirementsFilename(data.markdown || "") : data.markdown || "";
|
||||
const documentMarkdown = data.markdown || "";
|
||||
return (
|
||||
<div className={`cad-message cad-progress${isError ? " is-error" : ""}${isWaiting ? " is-waiting" : ""}`} role="status" aria-live="polite">
|
||||
<div className="cad-message-heading">
|
||||
@@ -32,8 +31,7 @@ export function CadProgressPart({ data }: { data: CadProgress }) {
|
||||
{data.questions?.length ? <ul className="cad-waiting-questions">{data.questions.map((question, index) => <li key={`${question}-${index}`}>{question}</li>)}</ul> : null}
|
||||
{data.issues?.length ? <ul className="cad-waiting-questions">{data.issues.map((issue, index) => <li key={`${issue}-${index}`}>{issue}</li>)}</ul> : null}
|
||||
{data.verificationWarnings?.length ? <details className="cad-event-details" open><summary>验证风险 ({data.verificationWarnings.length})</summary><ul>{data.verificationWarnings.map((warning, index) => <li key={`${warning}-${index}`}>{warning}</li>)}</ul></details> : null}
|
||||
{data.appliedNormalizations?.length ? <details className="cad-event-details"><summary>自动归一化 ({data.appliedNormalizations.length})</summary><JsonTree data={data.appliedNormalizations} /></details> : null}
|
||||
{documentMarkdown ? <details className="cad-event-details cad-document-details" open={data.step === "requirements_document"}><summary>{documentTitle || "文档内容"}</summary><MarkdownDocument>{documentMarkdown}</MarkdownDocument></details> : null}
|
||||
{documentMarkdown ? <details className="cad-event-details cad-document-details"><summary>文档内容</summary><MarkdownDocument>{documentMarkdown}</MarkdownDocument></details> : null}
|
||||
{data.arguments ? <details className="cad-event-details"><summary>调用参数</summary><JsonTree data={data.arguments} /></details> : null}
|
||||
{data.result !== undefined ? <details className="cad-event-details"><summary>执行结果</summary><JsonTree data={data.result} /></details> : null}
|
||||
{evidence.length ? <details className="cad-event-details"><summary>证据 ({evidence.length})</summary><ul>{evidence.map((item, index) => <li key={`${item}-${index}`}>{item}</li>)}</ul></details> : null}
|
||||
@@ -41,13 +39,6 @@ export function CadProgressPart({ data }: { data: CadProgress }) {
|
||||
);
|
||||
}
|
||||
|
||||
function withoutRequirementsFilename(markdown: string) {
|
||||
return markdown
|
||||
.replace(/^\s*#{1,6}\s*`?requirements\.md`?\s*\n+/i, "")
|
||||
.replace(/^\s*`?requirements\.md`?\s*\n+/i, "")
|
||||
.trimStart();
|
||||
}
|
||||
|
||||
export function CadResultPart({ data }: { data: CadResult }) {
|
||||
const downloads: Array<[string, string]> = data.checkpoint ? [] : [
|
||||
["STEP", data.stepPath],
|
||||
@@ -69,7 +60,6 @@ export function CadResultPart({ data }: { data: CadResult }) {
|
||||
</div>
|
||||
{data.referenceIds.length ? <div className="cad-result-notes"><strong>参考</strong><span>{data.referenceIds.join(";")}</span></div> : null}
|
||||
{data.verificationWarnings?.length ? <div className="cad-result-notes"><strong>验证风险</strong><span>{data.verificationWarnings.join(";")}</span></div> : null}
|
||||
{data.appliedNormalizations?.length ? <details className="cad-event-details"><summary>自动归一化 ({data.appliedNormalizations.length})</summary><JsonTree data={data.appliedNormalizations} /></details> : null}
|
||||
{downloads.length ? <div className="download-row">
|
||||
{downloads.map(([label, path]) => (
|
||||
<a key={label} className="download-link" href={encodeArtifactUrl(data.taskId, path)} download aria-label={`下载 ${label}`}>
|
||||
|
||||
@@ -32,7 +32,6 @@ function resultForRevision(task: TaskRecord, revisionId: string, checkpoint: boo
|
||||
lifecycle: task.lifecycle || "completed",
|
||||
verificationStatus: task.verification_status,
|
||||
verificationWarnings: task.verification_warnings || [],
|
||||
appliedNormalizations: task.applied_normalizations || [],
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -77,7 +77,6 @@ export function restoreTaskProjection(messages: CadUIMessage[], task: TaskRecord
|
||||
userActionRequired: Boolean(task.user_action_required),
|
||||
verificationStatus: task.verification_status,
|
||||
verificationWarnings: task.verification_warnings || [],
|
||||
appliedNormalizations: task.applied_normalizations || [],
|
||||
};
|
||||
return [...messages, {
|
||||
id: `projection_${task.task_id}_${task.state_version || 0}`,
|
||||
|
||||
@@ -46,7 +46,7 @@ test("keeps terminal schema field errors visible to the CAD error part", () => {
|
||||
event: "cad_error",
|
||||
data: {
|
||||
stage: "generation",
|
||||
tool: "patch_requirements_draft",
|
||||
tool: "submit_requirements_spec",
|
||||
message: "Author repeatedly failed the schema.",
|
||||
fieldErrors: [{ path: "/patches", message: "Field required" }],
|
||||
},
|
||||
@@ -54,7 +54,7 @@ test("keeps terminal schema field errors visible to the CAD error part", () => {
|
||||
assert.equal(chunk?.type, "data-cad-error");
|
||||
assert.deepEqual("data" in chunk! ? chunk.data : null, {
|
||||
stage: "generation",
|
||||
tool: "patch_requirements_draft",
|
||||
tool: "submit_requirements_spec",
|
||||
message: "Author repeatedly failed the schema.",
|
||||
fieldErrors: [{ path: "/patches", message: "Field required" }],
|
||||
});
|
||||
@@ -69,7 +69,7 @@ test("maps a waiting terminal into a visible user-decision state", () => {
|
||||
lifecycle: "waiting_for_user",
|
||||
message: "Requirements need a user decision.",
|
||||
questions: [question],
|
||||
reviewPath: "documents/requirements-review.json",
|
||||
clarificationPath: "documents/requirements-clarification.json",
|
||||
},
|
||||
}, "text_1");
|
||||
assert.equal(chunk?.type, "data-cad-progress");
|
||||
@@ -81,7 +81,7 @@ test("maps a waiting terminal into a visible user-decision state", () => {
|
||||
taskId: "cad_abc",
|
||||
lifecycle: "waiting_for_user",
|
||||
questions: [question],
|
||||
reviewPath: "documents/requirements-review.json",
|
||||
clarificationPath: "documents/requirements-clarification.json",
|
||||
});
|
||||
});
|
||||
|
||||
@@ -90,7 +90,7 @@ test("restores a complete waiting terminal from the task projection", () => {
|
||||
task_id: "cad_abc", current_revision: "", lifecycle: "waiting_for_user", phase: "WAITING_FOR_USER",
|
||||
state_version: 7, message: "A decision is required.", questions: ["Four holes or six?"],
|
||||
blocker_type: "requirements_ambiguity", user_action_required: true,
|
||||
verification_status: "verified", verification_warnings: [], applied_normalizations: [], revisions: [],
|
||||
verification_status: "pending", verification_warnings: [], revisions: [],
|
||||
});
|
||||
const part = restored[0].parts[0];
|
||||
assert.equal(part.type, "data-cad-progress");
|
||||
@@ -101,14 +101,14 @@ test("restores a complete waiting terminal from the task projection", () => {
|
||||
}
|
||||
});
|
||||
|
||||
test("keeps unmet review issues visible when requirements review cannot converge", () => {
|
||||
const issue = "The counterbores need a feature-scoped front-side claim.";
|
||||
test("keeps explicit runtime issues visible when generation stops", () => {
|
||||
const issue = "The selected host face is unavailable.";
|
||||
const chunk = backendEventToUiChunk({
|
||||
event: "task_terminal",
|
||||
data: {
|
||||
taskId: "cad_abc",
|
||||
lifecycle: "waiting_for_user",
|
||||
message: "Requirements review did not converge.",
|
||||
message: "Runtime validation stopped generation.",
|
||||
issues: [issue],
|
||||
},
|
||||
}, "text_1");
|
||||
@@ -117,7 +117,7 @@ test("keeps unmet review issues visible when requirements review cannot converge
|
||||
step: "task_terminal",
|
||||
label: "生成任务",
|
||||
status: "waiting",
|
||||
message: "Requirements review did not converge.",
|
||||
message: "Runtime validation stopped generation.",
|
||||
taskId: "cad_abc",
|
||||
lifecycle: "waiting_for_user",
|
||||
issues: [issue],
|
||||
|
||||
@@ -20,7 +20,7 @@ export function backendEventToUiChunk(
|
||||
data: { ...item.data, sequence },
|
||||
};
|
||||
}
|
||||
if (["requirements_review", "action_selection", "tool_call", "candidate_result", "candidate_review", "final_review", "task_terminal"].includes(item.event)) {
|
||||
if (["image_observation", "requirements_ready", "completion_result_ready", "action_selection", "tool_call", "candidate_result", "candidate_review", "final_review", "task_terminal"].includes(item.event)) {
|
||||
const review = item.data.review && typeof item.data.review === "object"
|
||||
? item.data.review as Record<string, unknown>
|
||||
: null;
|
||||
@@ -44,7 +44,7 @@ export function backendEventToUiChunk(
|
||||
type: "data-cad-progress",
|
||||
id: `event_${eventId}`,
|
||||
data: { step: item.event, label: ({
|
||||
requirements_review: "需求合同独立复核", action_selection: "动作选择", tool_call: "建模工具", candidate_result: "候选构建", candidate_review: "候选独立复核", final_review: "最终独立复核", task_terminal: "生成任务",
|
||||
image_observation: "参考图片观察", requirements_ready: "需求规格已就绪", completion_result_ready: "完成结果已就绪", action_selection: "动作选择", tool_call: "建模工具", candidate_result: "候选构建", candidate_review: "候选独立复核", final_review: "最终独立复核", task_terminal: "生成任务",
|
||||
} as Record<string, string>)[item.event], status, ...metadata, message: String(
|
||||
item.data.message || item.data.reason
|
||||
|| (Array.isArray(item.data.questions) ? item.data.questions.map(String).filter(Boolean).join(";") : "")
|
||||
@@ -56,13 +56,11 @@ export function backendEventToUiChunk(
|
||||
...(item.data.lifecycle ? { lifecycle: String(item.data.lifecycle) } : {}),
|
||||
...(Array.isArray(item.data.questions) ? { questions: item.data.questions.map(String).filter(Boolean) } : {}),
|
||||
...(Array.isArray(item.data.issues) ? { issues: item.data.issues.map(String).filter(Boolean) } : {}),
|
||||
...(Array.isArray(item.data.unresolved) ? { unresolved: item.data.unresolved } : {}),
|
||||
...(item.data.blockerType ? { blockerType: String(item.data.blockerType) } : {}),
|
||||
...(typeof item.data.userActionRequired === "boolean" ? { userActionRequired: item.data.userActionRequired } : {}),
|
||||
...(item.data.verificationStatus ? { verificationStatus: String(item.data.verificationStatus) } : {}),
|
||||
...(Array.isArray(item.data.verificationWarnings) ? { verificationWarnings: item.data.verificationWarnings.map(String).filter(Boolean) } : {}),
|
||||
...(Array.isArray(item.data.appliedNormalizations) ? { appliedNormalizations: item.data.appliedNormalizations } : {}),
|
||||
...(item.data.reviewPath ? { reviewPath: String(item.data.reviewPath) } : {}),
|
||||
...(item.data.clarificationPath ? { clarificationPath: String(item.data.clarificationPath) } : {}),
|
||||
...(item.data.timestamp ? { timestamp: String(item.data.timestamp) } : {}),
|
||||
...(item.data.markdown ? { markdown: String(item.data.markdown) } : {}),
|
||||
...(item.data.tool ? { tool: String(item.data.tool) } : {}),
|
||||
|
||||
@@ -18,14 +18,12 @@ export type CadProgress = {
|
||||
evidence?: string[];
|
||||
questions?: string[];
|
||||
issues?: string[];
|
||||
unresolved?: Array<{ draftId?: string; reasonCode?: string; question?: string }>;
|
||||
blockerType?: string;
|
||||
userActionRequired?: boolean;
|
||||
verificationStatus?: "verified" | "completed_with_risks" | string;
|
||||
verificationWarnings?: string[];
|
||||
appliedNormalizations?: Array<Record<string, unknown>>;
|
||||
review?: Record<string, unknown>;
|
||||
reviewPath?: string;
|
||||
clarificationPath?: string;
|
||||
lifecycle?: "running" | "completed" | "failed" | "waiting_retry" | "waiting_for_user" | string;
|
||||
attempt?: number;
|
||||
maxAttempts?: number;
|
||||
@@ -47,7 +45,6 @@ export type CadResult = {
|
||||
lifecycle?: "running" | "completed" | "failed" | string;
|
||||
verificationStatus?: "verified" | "completed_with_risks" | string;
|
||||
verificationWarnings?: string[];
|
||||
appliedNormalizations?: Array<Record<string, unknown>>;
|
||||
};
|
||||
|
||||
export type CadError = {
|
||||
@@ -118,14 +115,16 @@ export type TaskRecord = {
|
||||
phase?: string;
|
||||
state_version?: number;
|
||||
active_candidate_id?: string;
|
||||
requirements_draft?: Record<string, unknown> | null;
|
||||
requirements_draft_path?: string;
|
||||
requirements_review?: Record<string, unknown> | null;
|
||||
requirements_review_path?: string;
|
||||
requirements_spec?: Record<string, unknown> | null;
|
||||
requirements_spec_path?: string;
|
||||
clarification_path?: string;
|
||||
requirements_contract?: Record<string, unknown> | null;
|
||||
requirements_contract_path?: string;
|
||||
requirements_markdown?: string | null;
|
||||
completion_markdown?: string | null;
|
||||
completion_target_markdown?: string | null;
|
||||
completion_target_path?: string;
|
||||
completion_result_markdown?: string | null;
|
||||
completion_result_path?: string;
|
||||
claim_summary?: Array<{
|
||||
requirement_id: string;
|
||||
claim_id: string;
|
||||
@@ -145,7 +144,6 @@ export type TaskRecord = {
|
||||
user_action_required?: boolean;
|
||||
verification_status?: "verified" | "completed_with_risks" | string;
|
||||
verification_warnings?: string[];
|
||||
applied_normalizations?: Array<Record<string, unknown>>;
|
||||
revisions: TaskRevision[];
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user