fix(FN-2662): clarify project default model setting
This commit is contained in:
@@ -1882,6 +1882,11 @@ export function SettingsModal({
|
|||||||
const resolvedPlanningModel = resolvePlanningSettingsModel(form);
|
const resolvedPlanningModel = resolvePlanningSettingsModel(form);
|
||||||
const resolvedDefaultModel = resolveProjectDefaultModel(form);
|
const resolvedDefaultModel = resolveProjectDefaultModel(form);
|
||||||
const resolvedTitleSummarizerModel = resolveTitleSummarizerSettingsModel(form);
|
const resolvedTitleSummarizerModel = resolveTitleSummarizerSettingsModel(form);
|
||||||
|
const getProjectLaneLabel = (lane: ModelLane) => lane.laneId === "default" ? "Project Default Model" : lane.label;
|
||||||
|
const getProjectLaneHelperText = (lane: ModelLane) =>
|
||||||
|
lane.laneId === "default"
|
||||||
|
? "Project-wide default AI model used when no more specific task or project lane override is set."
|
||||||
|
: lane.helperText;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
@@ -1922,6 +1927,7 @@ export function SettingsModal({
|
|||||||
<p className="settings-description">
|
<p className="settings-description">
|
||||||
Override global model settings at the project level. Each lane controls a specific AI usage context.
|
Override global model settings at the project level. Each lane controls a specific AI usage context.
|
||||||
Unset lanes inherit from the corresponding global lane.
|
Unset lanes inherit from the corresponding global lane.
|
||||||
|
The Project Default Model is the fallback for this project when a more specific lane is unset.
|
||||||
</p>
|
</p>
|
||||||
{modelsLoading ? (
|
{modelsLoading ? (
|
||||||
<div className="settings-empty-state">Loading available models…</div>
|
<div className="settings-empty-state">Loading available models…</div>
|
||||||
@@ -1935,11 +1941,12 @@ export function SettingsModal({
|
|||||||
const status = getLaneStatus(lane);
|
const status = getLaneStatus(lane);
|
||||||
const value = getLaneValue(lane);
|
const value = getLaneValue(lane);
|
||||||
const isOverridden = status === "overridden";
|
const isOverridden = status === "overridden";
|
||||||
|
const laneLabel = getProjectLaneLabel(lane);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="form-group" key={lane.laneId}>
|
<div className="form-group" key={lane.laneId}>
|
||||||
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.25rem" }}>
|
<div style={{ display: "flex", alignItems: "center", gap: "0.5rem", marginBottom: "0.25rem" }}>
|
||||||
<label htmlFor={`${lane.laneId}Model`}>{lane.label}</label>
|
<label htmlFor={`${lane.laneId}Model`}>{laneLabel}</label>
|
||||||
<span
|
<span
|
||||||
className={`settings-lane-badge ${isOverridden ? "settings-lane-badge--override" : "settings-lane-badge--inherited"}`}
|
className={`settings-lane-badge ${isOverridden ? "settings-lane-badge--override" : "settings-lane-badge--inherited"}`}
|
||||||
title={isOverridden ? "Explicitly set for this project" : "Inherited from global settings"}
|
title={isOverridden ? "Explicitly set for this project" : "Inherited from global settings"}
|
||||||
@@ -1951,11 +1958,11 @@ export function SettingsModal({
|
|||||||
<div style={{ flex: 1 }}>
|
<div style={{ flex: 1 }}>
|
||||||
<CustomModelDropdown
|
<CustomModelDropdown
|
||||||
id={`${lane.laneId}Model`}
|
id={`${lane.laneId}Model`}
|
||||||
label={lane.label}
|
label={laneLabel}
|
||||||
models={availableModels}
|
models={availableModels}
|
||||||
value={value}
|
value={value}
|
||||||
onChange={(val) => updateLaneValue(lane, val)}
|
onChange={(val) => updateLaneValue(lane, val)}
|
||||||
placeholder="Use global"
|
placeholder={lane.laneId === "default" ? "Use global default" : "Use global"}
|
||||||
favoriteProviders={favoriteProviders}
|
favoriteProviders={favoriteProviders}
|
||||||
onToggleFavorite={handleToggleFavorite}
|
onToggleFavorite={handleToggleFavorite}
|
||||||
favoriteModels={favoriteModels}
|
favoriteModels={favoriteModels}
|
||||||
@@ -1975,7 +1982,7 @@ export function SettingsModal({
|
|||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
<small>
|
<small>
|
||||||
{lane.helperText} Falls back to: {lane.fallbackOrder}.
|
{getProjectLaneHelperText(lane)} Falls back to: {lane.fallbackOrder}.
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -415,7 +415,9 @@ describe("SettingsModal", () => {
|
|||||||
|
|
||||||
await userEvent.click(screen.getByRole("button", { name: "Project Models" }));
|
await userEvent.click(screen.getByRole("button", { name: "Project Models" }));
|
||||||
|
|
||||||
const defaultSection = screen.getByLabelText("Default Model").closest(".form-group");
|
expect(screen.getByText(/The Project Default Model is the fallback for this project/i)).toBeInTheDocument();
|
||||||
|
|
||||||
|
const defaultSection = screen.getByLabelText("Project Default Model").closest(".form-group");
|
||||||
expect(defaultSection).toBeTruthy();
|
expect(defaultSection).toBeTruthy();
|
||||||
expect(within(defaultSection as HTMLElement).getByText("Inherited (Global)")).toBeInTheDocument();
|
expect(within(defaultSection as HTMLElement).getByText("Inherited (Global)")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
@@ -444,7 +446,7 @@ describe("SettingsModal", () => {
|
|||||||
await waitForSettingsModalReady();
|
await waitForSettingsModalReady();
|
||||||
|
|
||||||
await userEvent.click(screen.getByRole("button", { name: "Project Models" }));
|
await userEvent.click(screen.getByRole("button", { name: "Project Models" }));
|
||||||
await userEvent.click(screen.getByLabelText("Default Model"));
|
await userEvent.click(screen.getByLabelText("Project Default Model"));
|
||||||
await userEvent.click(screen.getByText("GPT-4o"));
|
await userEvent.click(screen.getByText("GPT-4o"));
|
||||||
await userEvent.click(screen.getByText("Save"));
|
await userEvent.click(screen.getByText("Save"));
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user