feat: establish unified administration and model context baseline

This commit is contained in:
Codex
2026-09-12 18:03:15 +02:00
parent 840344706f
commit f52bf22e05
74 changed files with 2334 additions and 523 deletions
@@ -14,6 +14,11 @@ import type {
} from "../api/catalog-databases";
import { Toaster } from "../components/ui/sonner";
import { DatabaseManagementPage } from "./DatabaseManagementPage";
import { workspacePreferences } from "../workspaces/preferences";
import { ComposerFooter } from "./SteerInput";
import { useSessionStore } from "../store/sessionStore";
beforeEach(() => { localStorage.clear(); });
const noSecrets = {
password: false,
@@ -142,7 +147,7 @@ function makeDescriptionGenerationRun(
return {
id: "77777777-7777-4777-8777-777777777777",
databaseId: "11111111-1111-4111-8111-111111111111",
modelId: "local-qwen",
modelId: "local/qwen",
scope: "selected_columns",
language: "it",
status: "queued",
@@ -221,8 +226,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
updatedAt: "2026-08-31T09:00:00Z",
})),
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
);
renderPage({ rows: [makeDatabase()], presentation: "fleet" });
@@ -231,8 +236,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
expect(pageHeading).toBeVisible();
const applicationBar = pageHeading.closest("header");
expect(applicationBar).not.toBeNull();
expect(within(applicationBar!).getByRole("region", { name: "Catalog status" })).toBeVisible();
expect(within(applicationBar!).getByRole("group", { name: "Database management actions" })).toBeVisible();
expect(screen.getByRole("region", { name: "Catalog status" })).toBeVisible();
expect(screen.getByRole("group", { name: "Database management actions" })).toBeVisible();
expect(screen.queryByText("Thoth catalog · Fleet ledger")).not.toBeInTheDocument();
expect(screen.queryByText("Inspect physical metadata, curate descriptions and control catalog operations.")).not.toBeInTheDocument();
expect(screen.queryByRole("button", { name: "Back to workspace" })).not.toBeInTheDocument();
@@ -241,8 +246,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
const summary = screen.getByRole("region", { name: "Fleet summary" });
expect(await within(summary).findByText("2,275")).toBeVisible();
expect(within(summary).getByText("75%")).toBeVisible();
const modelSelector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
expect(modelSelector).toHaveValue("local-qwen");
const modelSelector = await screen.findByRole("combobox", { name: "Global LLM model" });
expect(modelSelector).toHaveValue("local/qwen");
const databaseRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
const tablesAction = within(databaseRow).getByRole("button", { name: "View tables for Policlinico San Donato" });
@@ -253,10 +258,10 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
const manager = screen.getByRole("main", { name: "Database management" });
await user.click(within(databaseRow).getByRole("button", { name: "Edit Policlinico San Donato" }));
const editDrawer = await screen.findByRole("dialog", { name: "Edit database" });
const editDrawer = await screen.findByRole("region", { name: "Edit database form" });
expect(manager).toContainElement(editDrawer);
expect(editDrawer).toHaveAttribute("aria-modal", "false");
await user.click(within(editDrawer).getByRole("button", { name: "Close database panel" }));
expect(screen.queryByRole("dialog", { name: "Edit database" })).not.toBeInTheDocument();
await user.click(within(editDrawer).getByRole("button", { name: "Back to list" }));
const restoredDatabaseRow = await screen.findByRole("row", { name: /Policlinico San Donato/ });
await user.click(within(restoredDatabaseRow).getByRole("checkbox", { name: /toggle row selection/i }));
@@ -264,8 +269,8 @@ test("renders Fleet Ledger with real metrics, conceptual row tooltips, and persi
expect(within(actionPicker).getByRole("option", { name: /^Synchronize all(?:,|$)/ })).toBeVisible();
expect(within(actionPicker).queryByRole("option", { name: "Synchronize all columns" })).not.toBeInTheDocument();
await user.selectOptions(actionPicker, "generate-missing");
expect(screen.getAllByRole("combobox", { name: "Metadata-generation LLM model" })).toHaveLength(1);
expect(modelSelector).toHaveValue("local-qwen");
expect(screen.getAllByRole("combobox", { name: "Global LLM model" })).toHaveLength(1);
expect(modelSelector).toHaveValue("local/qwen");
});
@@ -471,7 +476,7 @@ test("offers catalog configuration directly on an unconfigured Fleet workspace",
name: "Configure catalog for Research laboratory",
}));
const drawer = await screen.findByRole("dialog", { name: "Configure catalog" });
const drawer = await screen.findByRole("region", { name: "Configure catalog form" });
expect(within(drawer).getByLabelText("Workspace")).toHaveAttribute("readonly");
expect(within(drawer).getByLabelText("Workspace")).toHaveValue("Research laboratory");
});
@@ -555,7 +560,7 @@ test("reopens database synchronization history when no run is active", async ()
await user.click(within(databaseRow).getByRole("button", {
name: "View Policlinico San Donato",
}));
await user.click(screen.getByRole("button", { name: "Sync history" }));
await user.click(screen.getByRole("button", { name: "View schema synchronization logs" }));
const drawer = await screen.findByRole("dialog", { name: "Schema synchronization" });
expect(drawer).toBeVisible();
@@ -567,22 +572,53 @@ test("reopens database synchronization history when no run is active", async ()
test("selects the configured metadata-description model by default", async () => {
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [
{ id: "openai-mini", label: "OpenAI Mini" },
{ id: "local-qwen", label: "Local Qwen" },
{ id: "openai/mini", label: "OpenAI Mini" },
{ id: "local/qwen", label: "Local Qwen" },
],
default: "local-qwen",
default: "local/qwen",
})));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
await waitFor(() => expect(selector).toHaveValue("local-qwen"));
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
await waitFor(() => expect(selector).toHaveValue("local/qwen"));
});
test("Core and Admin share one canonical selection, including models with the same short ID", async () => {
const models = [{ id: "local/qwen", label: "Local Qwen" }, { id: "remote/qwen", label: "Remote Qwen" }];
server.use(
http.get("/api/catalog/databases", () => HttpResponse.json([makeDatabase()])),
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models, default: "local/qwen" })),
http.get("/api/models", () => HttpResponse.json({ models: models.map((m) => ({
provider: m.id.split("/")[0], id: "qwen", name: m.label, reasoning: false,
})) })),
http.get("/api/settings", () => HttpResponse.json({ provider: "local", model: "qwen" })),
);
const client = new QueryClient({ defaultOptions: { queries: { retry: false } } });
render(<QueryClientProvider client={client}><ComposerFooter /><DatabaseManagementPage canManage canManageSecrets /></QueryClientProvider>);
const admin = await screen.findByRole("combobox", { name: "Global LLM model" });
const core = await screen.findByRole("combobox", { name: "Model" });
await waitFor(() => expect(admin).toHaveValue("local/qwen"));
act(() => useSessionStore.getState().setAgentActive(true));
expect(core).toBeDisabled();
expect(admin).toBeDisabled();
act(() => useSessionStore.getState().setAgentActive(false));
act(() => client.setQueryData(["description-generation-runs", 50], [makeDescriptionGenerationRun()]));
await waitFor(() => expect(core).toBeDisabled());
await waitFor(() => expect(admin).toBeDisabled());
act(() => client.setQueryData(["description-generation-runs", 50], []));
await waitFor(() => expect(core).toBeEnabled());
await waitFor(() => expect(admin).toBeEnabled());
await userEvent.selectOptions(admin, "remote/qwen");
await waitFor(() => expect(core).toHaveValue("remote/qwen"));
await userEvent.selectOptions(core, "local/qwen");
await waitFor(() => expect(admin).toHaveValue("local/qwen"));
});
test("keeps both run-history buttons visible beside the metadata-description selector", async () => {
const user = userEvent.setup();
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
const toolbar = screen.getByRole("group", { name: "Database management controls" });
const metadataControls = screen.getByRole("group", { name: "Metadata description controls" });
const actions = screen.getByRole("group", { name: "Database management actions" });
@@ -622,22 +658,23 @@ test("keeps both run-history buttons visible beside the metadata-description sel
expect(within(suggestionDrawer).getByText("No sensitivity analysis runs yet.")).toBeVisible();
});
test("changes the metadata-description model in page-local state", async () => {
test("changes the global model shared with Core", async () => {
const user = userEvent.setup();
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [
{ id: "openai-mini", label: "OpenAI Mini" },
{ id: "local-qwen", label: "Local Qwen" },
{ id: "openai/mini", label: "OpenAI Mini" },
{ id: "local/qwen", label: "Local Qwen" },
],
default: "local-qwen",
default: "local/qwen",
})));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
await waitFor(() => expect(selector).toHaveValue("local-qwen"));
await user.selectOptions(selector, "openai-mini");
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
await waitFor(() => expect(selector).toHaveValue("local/qwen"));
await user.selectOptions(selector, "openai/mini");
expect(selector).toHaveValue("openai-mini");
expect(selector).toHaveValue("openai/mini");
expect(workspacePreferences.load()).toMatchObject({ provider: "openai", model: "mini" });
});
test("explains application setup when no metadata-description model is configured", async () => {
@@ -647,7 +684,7 @@ test("explains application setup when no metadata-description model is configure
})));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
expect(selector).toBeDisabled();
expect(await screen.findByText(
"No metadata-generation LLM model is configured for this installation.",
@@ -661,11 +698,11 @@ test("uses a safe disabled setup state when metadata-description models are unav
}, { status: 503 })));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
await waitFor(() => expect(selector).toHaveDisplayValue("Model choices unavailable"));
expect(selector).toBeDisabled();
expect(screen.getByText(
"Metadata-generation LLM model choices are unavailable.",
"Global LLM model choices are unavailable.",
)).toBeVisible();
expect(screen.queryByText("internal model registry details")).not.toBeInTheDocument();
});
@@ -674,12 +711,12 @@ test.each([null, "missing-model"])(
"disables metadata-description selection when the public response has no usable default (%s)",
async (configuredDefault) => {
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "openai-mini", label: "OpenAI Mini" }],
models: [{ id: "openai/mini", label: "OpenAI Mini" }],
default: configuredDefault,
})));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
await waitFor(() => expect(selector).toHaveDisplayValue("No usable model configured"));
expect(selector).toBeDisabled();
expect(screen.getByText(
@@ -691,7 +728,7 @@ test.each([null, "missing-model"])(
test("renders only the public metadata-generation model contract", async () => {
server.use(http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{
id: "approved-model",
id: "approved/model",
label: "Approved model",
provider: "private-provider",
model: "private/upstream-model",
@@ -699,12 +736,12 @@ test("renders only the public metadata-generation model contract", async () => {
apiKeyEnv: "PRIVATE_MODEL_API_KEY",
credential: "raw-private-credential",
}],
default: "approved-model",
default: "approved/model",
})));
renderPage();
const selector = await screen.findByRole("combobox", { name: "Metadata-generation LLM model" });
await waitFor(() => expect(selector).toHaveValue("approved-model"));
const selector = await screen.findByRole("combobox", { name: "Global LLM model" });
await waitFor(() => expect(selector).toHaveValue("approved/model"));
expect(within(selector).getAllByRole("option").map((option) => option.textContent))
.toEqual(["Approved model"]);
expect(document.body).not.toHaveTextContent(/private-provider|private\/upstream-model/);
@@ -766,8 +803,8 @@ test("discloses source sampling before starting Generate missing descriptions",
let startBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
startBody = await request.json();
@@ -793,7 +830,7 @@ test("discloses source sampling before starting Generate missing descriptions",
await user.click(screen.getByRole("button", { name: "Generate missing descriptions" }));
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "missing",
}));
expect(screen.queryByText(/replace existing generated descriptions/i)).not.toBeInTheDocument();
@@ -805,8 +842,8 @@ test("keeps Fleet Generate missing descriptions behind the source-data disclosur
let generationStarts = 0;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => {
generationStarts += 1;
@@ -822,8 +859,8 @@ test("keeps Fleet Generate missing descriptions behind the source-data disclosur
"generate-missing",
);
await waitFor(() => expect(screen.getByRole("combobox", {
name: "Metadata-generation LLM model",
})).toHaveValue("local-qwen"));
name: "Global LLM model",
})).toHaveValue("local/qwen"));
await user.click(screen.getByRole("button", { name: "Run action" }));
expect(screen.getByRole("note", {
@@ -896,8 +933,8 @@ test("confirms generating all descriptions, supports cancel, and sends the datab
let startBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
startBody = await request.json();
@@ -929,7 +966,7 @@ test("confirms generating all descriptions, supports cancel, and sends the datab
await user.click(screen.getByRole("button", { name: "Generate all descriptions" }));
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "all",
}));
expect(await screen.findByRole("dialog", { name: "Description generation" })).toBeVisible();
@@ -939,8 +976,8 @@ test("keeps the database selected and safely explains when no descriptions are e
const user = userEvent.setup();
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => HttpResponse.json({
code: "description_generation_no_eligible_targets",
@@ -985,8 +1022,8 @@ test.each([
});
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => (
HttpResponse.json(queuedRun, { status: 202 })
@@ -1036,8 +1073,8 @@ test.each([
reason: "database.manage is absent",
canManage: false,
rows: [makeDatabase()],
models: [{ id: "local-qwen", label: "Local Qwen" }],
configuredDefault: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
configuredDefault: "local/qwen",
selectedRows: 1,
},
{
@@ -1052,8 +1089,8 @@ test.each([
reason: "the Workspace Database is not configured",
canManage: true,
rows: [unconfigured],
models: [{ id: "local-qwen", label: "Local Qwen" }],
configuredDefault: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
configuredDefault: "local/qwen",
selectedRows: 1,
},
{
@@ -1067,8 +1104,8 @@ test.each([
workspaceName: "Radiology",
}),
],
models: [{ id: "local-qwen", label: "Local Qwen" }],
configuredDefault: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
configuredDefault: "local/qwen",
selectedRows: 2,
},
])("disables database-wide generation when $reason", async ({
@@ -1102,8 +1139,8 @@ test("disables database-wide generation while a description generation is active
const queuedRun = makeDescriptionGenerationRun({ scope: "missing" });
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", () => (
HttpResponse.json(queuedRun, { status: 202 })
@@ -1871,8 +1908,8 @@ test("starts description generation for multiple selected tables", async () => {
let startBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
patientsTable,
@@ -1903,7 +1940,7 @@ test("starts description generation for multiple selected tables", async () => {
await user.click(generate);
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "selected_tables",
targetIds: [patientsTable.id, visitsTable.id],
}));
@@ -1919,7 +1956,7 @@ test("generates descriptions for every column in selected tables", async () => {
const queuedRun = makeDescriptionGenerationRun({ scope: "selected_columns", total: 1 });
let startBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models: [{ id: "local-qwen", label: "Local Qwen" }], default: "local-qwen" })),
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({ models: [{ id: "local/qwen", label: "Local Qwen" }], default: "local/qwen" })),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get(`/api/catalog/databases/:databaseId/tables/${patientsTable.id}/columns`, () => HttpResponse.json([patientIdColumn])),
http.post("/api/catalog/databases/:databaseId/description-generation-runs", async ({ request }) => {
@@ -1938,7 +1975,7 @@ test("generates descriptions for every column in selected tables", async () => {
await user.click(await screen.findByRole("menuitem", { name: "Generate descriptions for all columns" }));
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "selected_columns",
targetIds: [patientIdColumn.id],
}));
@@ -2059,8 +2096,8 @@ test("keeps selected tables when description generation cannot start", async ()
};
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
patientsTable,
@@ -2113,8 +2150,8 @@ test("refreshes Catalog Tables and Catalog Columns after table generation comple
let tableReads = 0;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => {
tableReads += 1;
@@ -2320,10 +2357,10 @@ test("starts one selected column with the configured default model", async () =>
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [
{ id: "openai-mini", label: "OpenAI Mini" },
{ id: "local-qwen", label: "Local Qwen" },
{ id: "openai/mini", label: "OpenAI Mini" },
{ id: "local/qwen", label: "Local Qwen" },
],
default: "local-qwen",
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
@@ -2353,7 +2390,7 @@ test("starts one selected column with the configured default model", async () =>
await user.click(await screen.findByRole("menuitem", { name: "Generate column description" }));
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "selected_columns",
targetIds: [patientIdColumn.id],
}));
@@ -2373,8 +2410,8 @@ test("shows database sensitivity analysis only for a selection and rejects multi
});
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.post("/api/catalog/databases/:databaseId/sensitive-data-suggestions", () => {
suggestionCalls += 1;
@@ -2495,8 +2532,8 @@ test("requests database-level sensitivity analysis for the only selected databas
const run = makeSensitivityAnalysisRun({ scope: "all", total: 1 });
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/sensitive-data-suggestion-runs", () => {
historyCalls += 1;
@@ -2539,8 +2576,8 @@ test("refetches sensitivity analysis history after a failed request", async () =
let historyCalls = 0;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/sensitive-data-suggestion-runs", () => {
historyCalls += 1;
@@ -2579,8 +2616,8 @@ test("requests sensitivity analysis only for selected tables", async () => {
let suggestionBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([
patientsTable,
@@ -2650,8 +2687,8 @@ test("allows a human downgrade and saves only explicit sensitivity changes", asy
const patches: Array<{ columnId: string; body: unknown }> = [];
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get(
@@ -2777,8 +2814,8 @@ test("polls a description run and renders its events in sequence order", async (
const eventAfters: number[] = [];
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
@@ -2814,7 +2851,7 @@ test("polls a description run and renders its events in sequence order", async (
await user.click(await screen.findByRole("menuitem", { name: "Generate column description" }));
const drawer = await screen.findByRole("dialog", { name: "Description generation" });
expect(within(drawer).getByText(/local-qwen/)).toBeVisible();
expect(within(drawer).getByText(/local[/]qwen/)).toBeVisible();
expect(within(drawer).getByText(/selected columns/)).toBeVisible();
expect(await within(drawer).findByRole("heading", { name: "Completed" }, { timeout: 4_000 })).toBeVisible();
expect(within(drawer).getByText("1", { selector: "[data-count='total']" })).toBeVisible();
@@ -2852,8 +2889,8 @@ test("refreshes Catalog Tables and Catalog Columns after column generation compl
let columns = [patientIdColumn];
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => {
tableReads += 1;
@@ -2907,8 +2944,8 @@ test("keeps the selected column and shows a safe message when generation cannot
const user = userEvent.setup();
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),
@@ -2938,13 +2975,13 @@ test("shows a basic failed run without exposing private model or provider fields
const user = userEvent.setup();
let columnReads = 0;
const queuedRun = {
...makeDescriptionGenerationRun({ modelId: "approved-model" }),
...makeDescriptionGenerationRun({ modelId: "approved/model" }),
provider: "private-provider",
apiKey: "sk-private-key",
};
const failedRun = {
...makeDescriptionGenerationRun({
modelId: "approved-model",
modelId: "approved/model",
status: "failed",
processed: 1,
failed: 1,
@@ -2963,13 +3000,13 @@ test("shows a basic failed run without exposing private model or provider fields
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{
id: "approved-model",
id: "approved/model",
label: "Approved model",
provider: "private-provider",
upstreamModel: "private/upstream-model",
apiKeyEnv: "PRIVATE_MODEL_API_KEY",
}],
default: "approved-model",
default: "approved/model",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => {
@@ -3022,8 +3059,8 @@ test("offers generation and consolidation for multiple selected columns", async
let startBody: unknown;
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => (
@@ -3063,7 +3100,7 @@ test("offers generation and consolidation for multiple selected columns", async
await user.click(generate);
await waitFor(() => expect(startBody).toEqual({
modelId: "local-qwen",
modelId: "local/qwen",
scope: "selected_columns",
targetIds: [patientIdColumn.id, patientNameColumn.id],
}));
@@ -3072,7 +3109,7 @@ test("offers generation and consolidation for multiple selected columns", async
});
test.each([
{ name: "database.manage is absent", canManage: false, models: [{ id: "local-qwen", label: "Local Qwen" }], configuredDefault: "local-qwen" },
{ name: "database.manage is absent", canManage: false, models: [{ id: "local/qwen", label: "Local Qwen" }], configuredDefault: "local/qwen" },
{ name: "no usable model is configured", canManage: true, models: [], configuredDefault: null },
])("disables selected table and column generation when $name", async ({ canManage, models, configuredDefault }) => {
const user = userEvent.setup();
@@ -3113,8 +3150,8 @@ test("disables another generation start while the selected-column run is active"
const queuedRun = makeDescriptionGenerationRun();
server.use(
http.get("/api/catalog/metadata-generation/models", () => HttpResponse.json({
models: [{ id: "local-qwen", label: "Local Qwen" }],
default: "local-qwen",
models: [{ id: "local/qwen", label: "Local Qwen" }],
default: "local/qwen",
})),
http.get("/api/catalog/databases/:databaseId/tables", () => HttpResponse.json([patientsTable])),
http.get("/api/catalog/databases/:databaseId/tables/:tableId/columns", () => HttpResponse.json([patientIdColumn])),