feat(asset-ai): generate contextual presentations and drilldown plans
ci/woodpecker/push/woodpecker Pipeline was successful

This commit is contained in:
shishengliang
2026-09-23 17:52:33 +08:00
parent b5a48b6417
commit dc0923b566
33 changed files with 6193 additions and 1165 deletions
@@ -84,7 +84,7 @@ test("assistant rejects unauthenticated direct calls before contacting a model",
const response = await router.request("/ask", { method: "POST", body: "{}" });
assert.equal(response.status, 401);
});
test("model receives no business results; permission-filtered rows stay in the response", async (t) => {
test("presentation receives authorized aggregates while vehicle rows stay in the internal response", async (t) => {
const oldKey = process.env.DEEPSEEK_API_KEY;
process.env.DEEPSEEK_API_KEY = "test-only";
const oldEnabled = process.env.ASSET_AI_EXTERNAL_ENABLED;
@@ -113,7 +113,7 @@ test("model receives no business results; permission-filtered rows stay in the r
kind: "query",
plan,
})
: "共有 2 台库存车辆。",
: JSON.stringify({results:[{id:"main",blocks:[{id:"summary",kind:"summary"}],interactions:[]}]}),
},
finish_reason: "stop",
},
@@ -143,7 +143,11 @@ test("model receives no business results; permission-filtered rows stay in the r
result.rows.map((r: { id: string }) => r.id),
["0", "2"],
);
assert.equal(prompts.length, 1);
assert.equal(prompts.length, 2);
const presentationInput = JSON.parse(JSON.parse(prompts[1]).messages[1].content);
assert.equal(presentationInput.stage, "presentation");
assert.equal(presentationInput.results[0].metrics[0].value, 2);
assert.equal(presentationInput.results[0].rows, undefined);
assert.ok(
prompts.every(
(p) =>
@@ -152,5 +156,5 @@ test("model receives no business results; permission-filtered rows stay in the r
!p.includes("plateNumber"),
),
);
assert.equal(events.filter((e) => e.type === "step").length, 3);
assert.equal(events.filter((e) => e.type === "step").length, 4);
});