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
+8 -8
View File
@@ -1,6 +1,7 @@
import { expect, test } from "@playwright/test";
import { parseAnswerUiBlock } from "../../src/features/agent/answer-ui/contract";
import { mockWorkbenchContext } from "./support/mock-workbench-context";
import { TEST_PROJECT_ID } from "./support/mock-scada-api";
// Explicit opt-in: two real conversation turns against a local dev Agent; ordinary learning checks may also run.
const realAgentUrl = process.env.TJWATER_ANSWER_UI_REAL_AGENT_URL;
@@ -16,6 +17,7 @@ test("real model publishes local components, restores them and receives form inp
const target = new URL(realAgentUrl!);
expect(["127.0.0.1", "localhost"]).toContain(target.hostname);
const base = `${target.origin}/api/v1`;
const headers = { "X-Project-Id": TEST_PROJECT_ID };
const health = await request.get(`${target.origin}/health`);
expect(health.ok()).toBe(true);
expect(await health.json()).toMatchObject({ ready: true, warmed_up: true });
@@ -33,12 +35,12 @@ test("real model publishes local components, restores them and receives form inp
})};`
})
);
const created = await request.post(`${base}/session`, { data: {} });
const created = await request.post(`${base}/session`, { headers, data: {} });
expect(created.ok()).toBe(true);
const id = (await created.json()).session_id as string;
const title = `本地交互回答验收 ${Date.now()}`;
const renamed = await request.patch(`${base}/session/${encodeURIComponent(id)}/title`, {
data: { title }
headers, data: { title }
});
expect(renamed.ok()).toBe(true);
page.on("pageerror", (error) => console.error("Real answer browser error:", error.message));
@@ -47,11 +49,9 @@ test("real model publishes local components, restores them and receives form inp
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByRole("button", { name: /展开 Agent 助手面板/ }).click();
const panel = page.getByRole("complementary", { name: "Agent 命令面板" });
await panel.getByRole("button", { name: "选择对话归属" }).click();
await page.getByRole("menuitem", { name: "个人会话", exact: true }).click();
await expect(panel.getByRole("button", { name: "选择 Agent 模型" })).toBeEnabled();
await panel.getByRole("button", { name: "打开 Agent 历史记录" }).click();
await panel
await page.getByRole("dialog", { name: "历史对话", exact: true })
.getByRole("button", { name: new RegExp(title) })
.first()
.click();
@@ -76,11 +76,11 @@ test("real model publishes local components, restores them and receives form inp
await expect(panel.getByRole("button", { name: "发送 Agent 指令" })).toBeVisible({
timeout: 180_000
});
await panel.getByRole("button", { name: "数据", exact: true }).first().click();
await panel.getByRole("tab", { name: "数据", exact: true }).first().click();
await expect(panel.getByRole("table").first()).toContainText("0.18");
await expect(panel.getByRole("table").first()).toContainText("10:00");
await expect(panel.getByLabel("现场位置(必填)")).toHaveValue("");
const storedResponse = await request.get(`${base}/session/${encodeURIComponent(id)}`);
const storedResponse = await request.get(`${base}/session/${encodeURIComponent(id)}`, { headers });
expect(storedResponse.ok()).toBe(true);
const stored = await storedResponse.json();
expect(stored.is_streaming).toBe(false);
@@ -122,7 +122,7 @@ test("real model publishes local components, restores them and receives form inp
});
await panel.screenshot({ path: "test-results/answer-ui-real-model.png" });
} finally {
const deleted = await request.delete(`${base}/session/${encodeURIComponent(id)}`);
const deleted = await request.delete(`${base}/session/${encodeURIComponent(id)}`, { headers });
expect(deleted.status()).toBe(204);
}
});