fix(api): align frontend with project-scoped backend
Use project-scoped endpoints and run IDs for current project, SCADA metadata, historical time series, migrated DMA results, and sensor placement runs. The regressions recurred because tests mocked pre-interceptor and new-only payload shapes, while history queries relied on implicit global scheme state and unbounded request fan-out. Cover post-interceptor pages, migrated result_rows, explicit run_id routing, multi-element requests, request limits, and cancellation.
This commit is contained in:
@@ -30,6 +30,7 @@ import {
|
||||
describeApplyLayerStyle,
|
||||
parseApplyLayerStylePayload,
|
||||
} from "./toolCallStyleHelpers";
|
||||
import { buildViewHistoryAction } from "./historyToolAction";
|
||||
|
||||
/* ------------------------------------------------------------------ */
|
||||
/* Interactive card rendered inside a chat bubble for tool actions */
|
||||
@@ -428,17 +429,7 @@ function buildAction(toolCall: ToolCall): ChatToolAction | null {
|
||||
};
|
||||
}
|
||||
case "view_history": {
|
||||
const historyRange = resolveTimeRange();
|
||||
return {
|
||||
type: "view_history",
|
||||
featureInfos:
|
||||
(params.feature_infos as [string, string][] | undefined) ?? [],
|
||||
dataType:
|
||||
(params.data_type as "realtime" | "scheme" | "none" | undefined) ??
|
||||
"realtime",
|
||||
startTime: historyRange.startTime,
|
||||
endTime: historyRange.endTime,
|
||||
};
|
||||
return buildViewHistoryAction(params);
|
||||
}
|
||||
case "view_scada": {
|
||||
const scadaRange = resolveTimeRange();
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
import { buildViewHistoryAction } from "./historyToolAction";
|
||||
|
||||
describe("buildViewHistoryAction", () => {
|
||||
it("preserves the scheme run ID from Agent tool parameters", () => {
|
||||
expect(
|
||||
buildViewHistoryAction({
|
||||
feature_infos: [["P-1", "pipe"]],
|
||||
data_type: "scheme",
|
||||
run_id: " 99dd4142-368b-54cb-bfca-d59ee48f6298 ",
|
||||
}),
|
||||
).toEqual(
|
||||
expect.objectContaining({
|
||||
featureInfos: [["P-1", "pipe"]],
|
||||
dataType: "scheme",
|
||||
runId: "99dd4142-368b-54cb-bfca-d59ee48f6298",
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
it("normalizes invalid history parameters", () => {
|
||||
expect(
|
||||
buildViewHistoryAction({
|
||||
feature_infos: [["", "pipe"], "invalid"],
|
||||
data_type: "unexpected",
|
||||
runId: " ",
|
||||
}),
|
||||
).toEqual({
|
||||
type: "view_history",
|
||||
featureInfos: [],
|
||||
dataType: "realtime",
|
||||
runId: undefined,
|
||||
startTime: undefined,
|
||||
endTime: undefined,
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,43 @@
|
||||
import type { ChatToolAction } from "@/store/chatToolStore";
|
||||
|
||||
type ViewHistoryAction = Extract<ChatToolAction, { type: "view_history" }>;
|
||||
|
||||
const readOptionalString = (value: unknown) =>
|
||||
typeof value === "string" && value.trim() ? value.trim() : undefined;
|
||||
|
||||
export const buildViewHistoryAction = (
|
||||
params: Record<string, unknown>,
|
||||
): ViewHistoryAction => {
|
||||
const rawFeatureInfos = Array.isArray(params.feature_infos)
|
||||
? params.feature_infos
|
||||
: [];
|
||||
const featureInfos = rawFeatureInfos
|
||||
.filter(
|
||||
(item): item is [unknown, unknown] =>
|
||||
Array.isArray(item) && item.length >= 2,
|
||||
)
|
||||
.map(
|
||||
([id, type]) => [String(id).trim(), String(type).trim()] as [string, string],
|
||||
)
|
||||
.filter(([id, type]) => id.length > 0 && type.length > 0);
|
||||
const rawDataType = params.data_type;
|
||||
const dataType =
|
||||
rawDataType === "realtime" ||
|
||||
rawDataType === "scheme" ||
|
||||
rawDataType === "none"
|
||||
? rawDataType
|
||||
: "realtime";
|
||||
|
||||
return {
|
||||
type: "view_history",
|
||||
featureInfos,
|
||||
dataType,
|
||||
runId: readOptionalString(params.run_id ?? params.runId),
|
||||
startTime: readOptionalString(
|
||||
params.start_time ?? params.startTime ?? params.from ?? params.start,
|
||||
),
|
||||
endTime: readOptionalString(
|
||||
params.end_time ?? params.endTime ?? params.to ?? params.end,
|
||||
),
|
||||
};
|
||||
};
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
describeApplyLayerStyle,
|
||||
parseApplyLayerStylePayload,
|
||||
} from "../toolCallStyleHelpers";
|
||||
import { buildViewHistoryAction } from "../historyToolAction";
|
||||
|
||||
type ToolCallEvent = StreamEvent & { type: "tool_call" };
|
||||
|
||||
@@ -253,21 +254,12 @@ const buildToolAction = (
|
||||
}
|
||||
|
||||
if (tool === "view_history") {
|
||||
const featureInfos = (params.feature_infos as [string, string][] | undefined) ?? [];
|
||||
const { startTime, endTime } = resolveTimeRange(params);
|
||||
const action = buildViewHistoryAction(params);
|
||||
return {
|
||||
action: {
|
||||
type: "view_history",
|
||||
featureInfos,
|
||||
dataType:
|
||||
(params.data_type as "realtime" | "scheme" | "none" | undefined) ??
|
||||
"realtime",
|
||||
startTime,
|
||||
endTime,
|
||||
},
|
||||
action,
|
||||
kind: "panel",
|
||||
title: "打开计算结果曲线",
|
||||
description: compactNames(featureInfos.map(([id]) => id)),
|
||||
description: compactNames(action.featureInfos.map(([id]) => id)),
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user