feat(workbench): integrate operational workflows and map state

This commit is contained in:
2026-09-24 04:34:46 +08:00
parent 1752b9ef84
commit 436d5500f1
76 changed files with 5081 additions and 1937 deletions
@@ -1,7 +1,9 @@
import { cleanup, fireEvent, render, screen } from "@testing-library/react";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { ScheduledConditionRecord } from "../types";
import { ConditionDetailPanel } from "./scheduled-condition-detail-panel";
import type { ScheduledConditionRecord, ScheduledWorkOrderItem } from "../types";
import { ConditionDetailPanel, WorkOrderSubtasksPanel } from "./scheduled-condition-detail-panel";
import { createVisibleTickerCards } from "./agent-task-ticker-utils";
import { createConditionConversationPrompt } from "../utils/scheduled-condition-prompts";
const baseCondition: ScheduledConditionRecord = {
id: "schedule-run-1",
@@ -21,9 +23,61 @@ const baseCondition: ScheduledConditionRecord = {
modelName: "TJWater scheduler"
};
it("does not infer water-quality progress or conversation steps from elapsed time", () => {
const condition: ScheduledConditionRecord = { ...baseCondition, taskId: "water-quality-complaint", dataSource: "mock", status: "running" };
const [card] = createVisibleTickerCards([condition], 0, Date.now());
expect(card.view.progressValue).toBeUndefined();
expect(card.view.currentStep?.title).toBe("Agent 执行计划");
expect(createConditionConversationPrompt(condition)).not.toContain("工作流步骤");
});
describe("scheduled condition backend boundaries", () => {
afterEach(cleanup);
it("keeps Chinese work-order time labels in the application font", () => {
const workOrder: ScheduledWorkOrderItem = {
id: "demo-work-order",
kind: "work_order",
code: "WO-DEMO",
scheduledAt: "2026-09-23T10:00:00Z",
title: "演示预约维修",
summary: "验证中文时间标签",
status: "pending",
riskLevel: "normal",
updatedAt: Date.parse("2026-09-23T10:00:00Z"),
source: "演示数据",
dispatcher: "调度岗",
priority: "normal",
dataSource: "mock",
subtasks: [{
id: "field-service",
title: "现场维修",
summary: "按预约窗口处理",
status: "pending",
scheduledAt: "2026-09-23T10:00:00Z",
location: "测试点",
assignee: "维修班组",
durationMinutes: 60,
replyWindowMinutes: 30,
stages: [{
id: "dispatch",
sequence: 1,
title: "派发",
status: "pending",
owner: "调度岗",
timeLabel: "待安排",
description: "确认预约窗口。"
}],
replyRequirements: ["回填处理结果"]
}]
};
render(<WorkOrderSubtasksPanel condition={workOrder} />);
const timeLabel = screen.getByText("待安排", { exact: true });
expect(timeLabel).toHaveClass("tabular-nums");
expect(timeLabel).not.toHaveClass("font-mono");
});
it("shows only persisted evidence for a failed backend condition", () => {
render(
<ConditionDetailPanel
@@ -57,6 +111,25 @@ describe("scheduled condition backend boundaries", () => {
expect(screen.queryByText("演示进度")).not.toBeInTheDocument();
});
it("does not expose operational-task model, session or duration metadata", () => {
render(
<ConditionDetailPanel
condition={{
...baseCondition,
dataSource: "operational_tasks",
modelName: "TJWater operational task",
sessionId: "browser-session-1"
}}
dataSource="operational_tasks"
onContinueConversation={vi.fn()}
/>
);
expect(screen.queryByText("TJWater operational task")).not.toBeInTheDocument();
expect(screen.queryByText("browser-session-1")).not.toBeInTheDocument();
expect(screen.queryByText("未记录")).not.toBeInTheDocument();
});
it("keeps the mock work-order interaction but labels it as a local demo draft", () => {
render(
<ConditionDetailPanel
@@ -81,7 +154,7 @@ describe("scheduled condition backend boundaries", () => {
expect(screen.queryByText("系统工单已提交")).not.toBeInTheDocument();
});
it("renders an event-triggered water-quality task as a workflow before opening chat", () => {
it("does not expose the removed mock Agent execution path", () => {
const onContinueConversation = vi.fn();
render(
<ConditionDetailPanel
@@ -103,10 +176,9 @@ describe("scheduled condition backend boundaries", () => {
/>
);
expect(screen.getByText("演示执行流程 · 水质投诉调查流程")).toBeVisible();
expect(screen.getAllByText("校验上游水质监测").at(-1)).toBeVisible();
expect(screen.getAllByText("核查二次供水").at(-1)).toBeVisible();
fireEvent.click(screen.getByRole("button", { name: "与 Agent 协同" }));
expect(onContinueConversation).toHaveBeenCalledOnce();
expect(screen.getByText("后端运行状态")).toBeVisible();
expect(screen.queryByText(/演示执行流程/)).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "与 Agent 协同" })).not.toBeInTheDocument();
expect(onContinueConversation).not.toHaveBeenCalled();
});
});