feat: add seat firmware workbench and OTA delivery
This commit is contained in:
@@ -75,6 +75,65 @@ async function main() {
|
||||
await page.locator('[data-execution-mode="dry_run"]').click();
|
||||
assert.equal(await page.evaluate(() => window.CognitiveAgentConsole.getExecutionMode()), "dry_run");
|
||||
|
||||
async function submitDraft(text) {
|
||||
const responsePromise = responseFor("/api/assistant/stream");
|
||||
await page.locator("#utterance").fill(text);
|
||||
await page.locator("#utterance").press("Enter");
|
||||
const response = await responsePromise;
|
||||
const body = responses.filter((item) => item.pathname === "/api/assistant/stream").at(-1).text;
|
||||
assert.equal(response.status(), 200, `${text}: ${body}`);
|
||||
const events = body.trim().split("\n").map((line) => JSON.parse(line));
|
||||
await waitIdle();
|
||||
const payload = events.find((event) => event.payload?.mode_profile_draft)?.payload;
|
||||
assert.ok(payload, `Missing draft for ${text}: ${body}`);
|
||||
assert.equal(payload.status, "succeeded");
|
||||
assert.equal(payload.execution_mode, "dry_run");
|
||||
const draft = payload.mode_profile_draft;
|
||||
const card = page.locator(`[data-assistant-mode-draft="${draft.source_request_id}"]`);
|
||||
await card.waitFor({ state: "visible" });
|
||||
assert.equal(await card.locator(".assistant-mode-draft-row").count(), draft.operation_count);
|
||||
return { payload, draft, card, request: posted.filter((item) => item.pathname === "/api/assistant/stream").at(-1).payload };
|
||||
}
|
||||
|
||||
// The original failing two-turn request must revise the server-owned
|
||||
// draft, not attempt immediate hardware execution or replace its seats.
|
||||
const recline = await submitDraft("构建一个躺平模式");
|
||||
const originalActions = recline.payload.actions;
|
||||
await recline.card.scrollIntoViewIfNeeded();
|
||||
await page.screenshot({ path: path.join(evidenceDir, "mode-device-addition-before.png") });
|
||||
const expanded = await submitDraft("在躺平模式中加入空调、氛围灯、阅读灯、车窗等设备动作");
|
||||
assert.deepEqual(expanded.request.mode_profile_draft_context, {
|
||||
name: recline.draft.name,
|
||||
source_request_id: recline.draft.source_request_id,
|
||||
vehicle_id: recline.draft.vehicle_id,
|
||||
});
|
||||
assert.notEqual(expanded.draft.source_request_id, recline.draft.source_request_id);
|
||||
assert.equal(expanded.draft.draft_revision, 2);
|
||||
const actionKey = (action) => `${action.capability}:${action.target?.instance || action.target?.zone || ""}`;
|
||||
const expandedActions = new Map(expanded.payload.actions.map((action) => [actionKey(action), action]));
|
||||
for (const original of originalActions) {
|
||||
assert.deepEqual(expandedActions.get(actionKey(original))?.parameters, original.parameters,
|
||||
"adding devices must preserve all existing action values");
|
||||
}
|
||||
for (const capability of ["climate.set_temperature", "interior_light.set_reading_power", "window.set_position"]) {
|
||||
assert.ok(expanded.payload.actions.some((action) => action.capability === capability), capability);
|
||||
}
|
||||
assert.ok(expanded.payload.actions.some((action) => action.domain === "ambient_light"));
|
||||
assert.ok(expanded.payload.actions.every((action) => action.domain !== "seat"
|
||||
|| (action.target?.instance || action.target?.zone) === "passenger"));
|
||||
assert.ok(expanded.draft.operation_count > recline.draft.operation_count);
|
||||
assert.equal(await recline.card.getAttribute("data-superseded"), "true");
|
||||
assert.equal(await recline.card.locator(".assistant-mode-draft-save").isDisabled(), true);
|
||||
assert.equal(posted.filter((item) => item.pathname === "/api/mode-profiles").length, 0);
|
||||
await expanded.card.scrollIntoViewIfNeeded();
|
||||
await page.screenshot({ path: path.join(evidenceDir, "mode-device-addition-after.png") });
|
||||
const temperatureEdit = await submitDraft("把躺平模式的空调温度调整到26度");
|
||||
assert.equal(temperatureEdit.request.mode_profile_draft_context.source_request_id, expanded.draft.source_request_id);
|
||||
assert.equal(temperatureEdit.draft.draft_revision, 3);
|
||||
assert.equal(temperatureEdit.draft.operation_count, expanded.draft.operation_count);
|
||||
assert.ok(temperatureEdit.payload.actions.some((action) => action.capability === "climate.set_temperature"
|
||||
&& action.parameters.temperature_c === 26));
|
||||
|
||||
// Exercise the same real assistant endpoint and rendered cards for both
|
||||
// implicit passenger selection and an explicit driver request. These
|
||||
// previews stay unsaved, so the timeline save/trial tests remain isolated.
|
||||
|
||||
Reference in New Issue
Block a user