feat: add project-aware agent workspace
Generic Container CI/CD / test-build-publish (push) Successful in 2m9s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 2m39s

This commit is contained in:
2026-10-22 18:52:18 +08:00
parent c6a0e74e72
commit 2d8506fea0
191 changed files with 12373 additions and 3556 deletions
@@ -21,17 +21,20 @@ import {
import { InvestigationDiagramView } from "./investigation-diagram-view";
import { InvestigationExpandCard } from "./investigation-expand-card";
import { useReportUpdateMotion } from "../hooks/use-report-update-motion";
import { ExpandableReading } from "@/shared/ui/reading-workspace";
import { InvestigationReportBlocks } from "./investigation-report-blocks";
import { InvestigationReportNavigation, type InvestigationReportSection } from "./investigation-report-navigation";
type ReportSelection = { snapshot: OperationalTaskReport; diagram: InvestigationDiagram | null };
type Props = {
task: OperationalTask;
onContinue: (discussion?: InvestigationDiscussion) => void;
onContinue: (discussion?: InvestigationDiscussion) => Promise<boolean | void> | boolean | void;
renderAction: (action: OperationalTaskAction) => ReactNode;
renderEvidence: (evidence: OperationalTaskEvidence) => ReactNode;
onLoadReports?: (offset: number) => Promise<OperationalTaskReportPage>;
onReportViewed?: (generation: number, revision: number) => void;
focusActionId?: string | null;
onLocate?: (targets: InvestigationMapTarget[]) => void;
onLocate?: (targets: InvestigationMapTarget[]) => Promise<unknown> | void;
};
const roundLabel = (snapshot: OperationalTaskReport) =>
@@ -167,6 +170,17 @@ export function InvestigationTaskReport({
const timeline = investigationTimeline(task, snapshot);
const reportRef = useReportUpdateMotion(task.task_id,
`${snapshot?.execution_generation}:${snapshot?.revision}:${progress?.run_id}:${progress?.revision}`, live);
const sections: InvestigationReportSection[] = [
"任务报告",
...(report?.ui_blocks?.length ? ["交互分析" as const] : []),
...(live ? ["当前调查进展" as const] : []),
...(pendingActions.length ? ["当前需处理" as const] : []),
...(completedActions.length ? ["处置进展" as const] : []),
...(report?.data_gaps?.length ? ["数据缺口" as const] : []),
...(diagram ? ["调查脉络" as const] : []),
"主要依据", "任务时间线",
...(onLoadReports ? ["报告版本" as const] : []),
];
useEffect(() => {
if (snapshot?.execution_generation == null || !onReportViewed) return;
@@ -209,6 +223,8 @@ export function InvestigationTaskReport({
};
return (
<ExpandableReading title={snapshot?.report.title ?? task.title}
summary={<p>{snapshot?.report.current_conclusion ?? task.summary}</p>}>
<article ref={reportRef} aria-label="调查任务报告" className="investigation-report surface-reading">
<header className="investigation-report-header">
<div className="min-w-0">
@@ -244,6 +260,8 @@ export function InvestigationTaskReport({
</Button>
</header>
<InvestigationReportNavigation reportRef={reportRef} sections={sections} />
{latestAvailable ? (
<div className="investigation-report-update" role="status">
<span>正在阅读历史报告{olderRevision ? ",已有新报告" : ""}</span>
@@ -254,9 +272,8 @@ export function InvestigationTaskReport({
) : null}
<InvestigationExpandCard title="当前结果" label="任务报告" disabled={!report}
revision={`${snapshot?.execution_generation}:${snapshot?.revision}`} preview={<>
<div className="flex flex-wrap items-center justify-between gap-2">
{report ? (
revision={`${snapshot?.execution_generation}:${snapshot?.revision}`}
headingAccessory={report ? (
<StatusBadge tone={insufficient ? "warning" : "neutral"}>
{insufficient
? "证据不足"
@@ -265,9 +282,10 @@ export function InvestigationTaskReport({
: "结果未记录"}
</StatusBadge>
) : null}
</div>
preview={<>
{report && snapshot ? (
<>
{previousRound || olderRevision || insufficient || report.stage !== "final" || report.outcome !== "concluded" ? (
<p className="mt-3 text-sm font-semibold leading-6 text-[var(--ink)]">
{previousRound
? task.status === "queued" || task.status === "running"
@@ -283,11 +301,10 @@ export function InvestigationTaskReport({
: "无法形成结论 · 正在结束本轮"
: report.stage === "interim"
? "阶段性判断"
: report.outcome === "concluded"
? "调查结论"
: "历史报告内容"}
: "历史报告内容"}
</p>
<p className="investigation-conclusion-preview mt-1 text-sm leading-6 text-[var(--ink)]">{formatInvestigationText(report.current_conclusion)}</p>
) : null}
<p className="investigation-conclusion-preview mt-2 text-sm leading-6 text-[var(--ink)]">{formatInvestigationText(report.current_conclusion)}</p>
<p className="mt-2 text-xs leading-5 text-[var(--ink-muted)]">
结论边界:{formatInvestigationText(report.conclusion_boundary)}
</p>
@@ -318,6 +335,8 @@ export function InvestigationTaskReport({
</> : <p className="text-sm text-[var(--ink-muted)]">尚未发布本轮调查报告。</p>}
</InvestigationExpandCard>
{snapshot ? <InvestigationReportBlocks task={task} snapshot={snapshot} onContinue={onContinue} onLocate={onLocate} /> : null}
{live ? <section aria-label="当前调查进展" className="investigation-report-section">
<h3 className="text-sm font-semibold text-[var(--ink)]">当前调查进展</h3>
<p className="mt-2 whitespace-pre-wrap break-words text-sm leading-6 text-[var(--ink)]">{formatInvestigationText(progress?.progress.summary ?? "尚未发布本轮调查进展。")}</p>
@@ -622,6 +641,7 @@ export function InvestigationTaskReport({
任务更新于 {dateLabel(task.updated_at)}
</p>
</article>
</ExpandableReading>
);
}