feat: expand intelligent investigation workspace
Generic Container CI/CD / test-build-publish (push) Successful in 1m52s
Frontend CI/CD / build-test-publish-and-deploy (push) Successful in 1m52s

This commit is contained in:
2026-10-30 17:30:19 +08:00
parent ddd03dbff6
commit c0e4231b83
223 changed files with 13155 additions and 5304 deletions
@@ -28,7 +28,67 @@ describe("recent activities for Agent suggestions", () => {
describe("recommendation cache lifecycle", () => {
let root: Root | undefined;
afterEach(async () => { if (root) await act(async () => root!.unmount()); root = undefined; vi.restoreAllMocks(); });
afterEach(async () => { if (root) await act(async () => root!.unmount()); root = undefined; vi.useRealTimers(); vi.restoreAllMocks(); });
it("retries failures after cache expiry with a bounded budget and supports manual retry", async () => {
vi.useFakeTimers();
root = createRoot(document.createElement("div"));
const request = vi.fn<Parameters<typeof useAgentPromptSuggestions>[0]["request"]>().mockRejectedValue(new Error("unavailable"));
const empty: never[] = [];
let result: ReturnType<typeof useAgentPromptSuggestions>;
function Probe() {
result = useAgentPromptSuggestions({ enabled: true, model: "fixture/model", cacheScope: "a", sessionId: null,
request, alerts: empty, alertDataSource: "backend", conditions: empty, runtimeDataSource: "backend", artifact: null, sessions: empty });
return null;
}
await act(async () => root!.render(createElement(WorkbenchSessionProvider, null, createElement(Probe))));
expect(result!.unavailable).toBe(true);
expect(request).toHaveBeenCalledTimes(1);
await act(async () => { await vi.advanceTimersByTimeAsync(30_000); });
expect(request).toHaveBeenCalledTimes(2);
await act(async () => { await vi.advanceTimersByTimeAsync(30_000); });
expect(request).toHaveBeenCalledTimes(3);
await act(async () => { await vi.advanceTimersByTimeAsync(300_000); });
expect(request).toHaveBeenCalledTimes(3);
request.mockResolvedValueOnce([{ question: "核查压力数据", activityId: null }]);
await act(async () => result!.retry());
expect(request).toHaveBeenCalledTimes(4);
expect(result!.suggestions[0]?.question).toBe("核查压力数据");
expect(result!.unavailable).toBe(false);
});
it("retries cached failures on service recovery while preserving successful recommendations", async () => {
root = createRoot(document.createElement("div"));
const request = vi.fn<Parameters<typeof useAgentPromptSuggestions>[0]["request"]>()
.mockRejectedValueOnce(new Error("offline")).mockResolvedValue([{ question: "核查压力数据", activityId: null }]);
const empty: never[] = [];
function Probe({ recoveryVersion }: { recoveryVersion: number }) {
useAgentPromptSuggestions({ enabled: true, model: "fixture/model", cacheScope: "a", recoveryVersion, sessionId: null,
request, alerts: empty, alertDataSource: "backend", conditions: empty, runtimeDataSource: "backend", artifact: null, sessions: empty });
return null;
}
for (const recoveryVersion of [0, 1, 2]) {
await act(async () => root!.render(createElement(WorkbenchSessionProvider, null, createElement(Probe, { recoveryVersion }))));
}
expect(request).toHaveBeenCalledTimes(2);
});
it("waits for a model and cancels automatic retries when the panel is disabled", async () => {
vi.useFakeTimers();
root = createRoot(document.createElement("div"));
const request = vi.fn(async () => { throw new Error("unavailable"); });
const empty: never[] = [];
function Probe({ model, enabled }: { model: string; enabled: boolean }) {
useAgentPromptSuggestions({ enabled, model, cacheScope: "a", sessionId: null,
request, alerts: empty, alertDataSource: "backend", conditions: empty, runtimeDataSource: "backend", artifact: null, sessions: empty });
return null;
}
const render = async (model: string, enabled: boolean) => act(async () => root!.render(createElement(WorkbenchSessionProvider, null, createElement(Probe, { model, enabled }))));
await render("", true);
expect(request).not.toHaveBeenCalled();
await render("fixture/model", true);
expect(request).toHaveBeenCalledTimes(1);
await render("fixture/model", false);
await act(async () => { await vi.advanceTimersByTimeAsync(90_000); });
expect(request).toHaveBeenCalledTimes(1);
});
it("reuses recommendations across history refresh, panel reopen and a new empty conversation", async () => {
const container = document.createElement("div");
root = createRoot(container);