Move agent AI defaults into Settings (#1919)

Signed-off-by: npub1d6t84ajeg9skp2609l2k6axgcme8x7g7u7luj352r03hcwreg7lqnxcsex <6e967af659416160ab4f2fd56d74c8c6f273791ee7bfc9468a1be37c387947be@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: npub1d6t84ajeg9skp2609l2k6axgcme8x7g7u7luj352r03hcwreg7lqnxcsex <6e967af659416160ab4f2fd56d74c8c6f273791ee7bfc9468a1be37c387947be@sprout-oss.stage.blox.sqprod.co>
Co-authored-by: Jordan Mecom <jm@squareup.com>
This commit is contained in:
morgmart
2026-07-15 16:34:25 -07:00
committed by GitHub
co-authored by npub1d6t84ajeg9skp2609l2k6axgcme8x7g7u7luj352r03hcwreg7lqnxcsex Jordan Mecom
parent 335413461b
commit 3e90dd5dd8
15 changed files with 238 additions and 64 deletions
@@ -0,0 +1,104 @@
import { useAppNavigation } from "@/app/navigation/useAppNavigation";
import type { InheritedDefault } from "./bakedEnvHelpers";
import { getPersonaProviderOptions } from "./personaDialogPickers";
import { Button } from "@/shared/ui/button";
function providerLabel(providerId: string) {
const option = getPersonaProviderOptions("", "buzz-agent").find(
(candidate) => candidate.id === providerId,
);
return option?.label ?? providerId;
}
export function formatAiDefaultsSummary({
provider,
model,
}: {
provider: InheritedDefault;
model: InheritedDefault;
}) {
const parts = [
provider.value ? providerLabel(provider.value) : null,
model.value || null,
].filter((value): value is string => Boolean(value));
return parts.length > 0 ? parts.join(" · ") : "Not configured";
}
export function AgentAiDefaultsNotice({
confirmNavigation = false,
explicitModel,
explicitProvider,
inheritedModel,
inheritedProvider,
}: {
confirmNavigation?: boolean;
explicitModel: string;
explicitProvider: string;
inheritedModel: InheritedDefault;
inheritedProvider: InheritedDefault;
}) {
const { goSettings } = useAppNavigation();
const inheritsProvider = explicitProvider.trim().length === 0;
const inheritsModel = explicitModel.trim().length === 0;
const usesCustomConfig = !inheritsProvider && !inheritsModel;
const requiredProviderMissing = inheritsProvider && !inheritedProvider.value;
const inheritedParts = [
inheritsProvider
? inheritedProvider.value
? `Provider ${providerLabel(inheritedProvider.value)}`
: "Provider not configured"
: null,
inheritsModel
? inheritedModel.value
? `Model ${inheritedModel.value}`
: "Model not configured"
: null,
].filter((value): value is string => Boolean(value));
return (
<div
className="flex flex-wrap items-center justify-between gap-2 rounded-lg border border-border/60 bg-muted/30 px-3 py-2"
data-testid="agent-ai-defaults-notice"
>
<div className="min-w-0">
<p className="text-xs font-medium text-foreground">
{usesCustomConfig
? "Custom AI configuration"
: requiredProviderMissing
? "AI defaults arent configured"
: inheritsProvider && inheritsModel
? "Uses AI defaults"
: "Partially uses AI defaults"}
</p>
<p className="text-xs text-muted-foreground">
{usesCustomConfig
? "This agent wont follow provider or model default changes."
: requiredProviderMissing
? "Choose a provider in AI defaults to use this agent."
: `${inheritedParts.join(" · ")}. Inherited fields follow future changes.`}
</p>
</div>
<Button
onClick={() => {
if (
confirmNavigation &&
!window.confirm(
"Leave this agent without saving? Your changes will be discarded.",
)
) {
return;
}
void goSettings("agents");
}}
size="xs"
type="button"
variant="link"
>
Edit AI defaults
</Button>
</div>
);
}
@@ -74,6 +74,7 @@ import {
getBakedProviderInheritLabel,
} from "./bakedEnvHelpers";
import { useAgentDialogDefaults } from "./useAgentDialogDefaults";
import { AgentAiDefaultsNotice } from "./AgentAiDefaults";
import { useProviderApiKeyFieldState } from "./providerApiKeyFieldState";
import { buildRuntimeModelProviderPayload } from "./agentDefinitionSubmitPayload";
@@ -864,6 +865,14 @@ export function AgentDefinitionDialog({
) : null}
</AnimatePresence>
<AgentAiDefaultsNotice
confirmNavigation
explicitModel={model}
explicitProvider={provider}
inheritedModel={inheritedModelDefault}
inheritedProvider={inheritedProviderDefault}
/>
{isCreateMode ? createRunSection : null}
<div className="space-y-3">
@@ -78,6 +78,7 @@ import {
} from "./bakedEnvHelpers";
import { getProviderApiKeyEnvVar } from "./personaDialogPickers";
import { useAgentDialogDefaults } from "./useAgentDialogDefaults";
import { AgentAiDefaultsNotice } from "./AgentAiDefaults";
import { useProviderApiKeyFieldState } from "./providerApiKeyFieldState";
const ADVANCED_FIELDS_MOTION_TRANSITION = {
@@ -1087,6 +1088,14 @@ export function AgentInstanceEditDialog({
</p>
</div>
<AgentAiDefaultsNotice
confirmNavigation
explicitModel={inheritedSubmission.model ?? ""}
explicitProvider={inheritedSubmission.provider ?? ""}
inheritedModel={inheritedModelDefault}
inheritedProvider={inheritedProviderDefault}
/>
{/* Advanced settings */}
<div className="space-y-3">
<button
+14 -3
View File
@@ -24,11 +24,20 @@ import { useManagedAgentActions } from "./useManagedAgentActions";
import { usePersonaActions } from "./usePersonaActions";
import { useTeamActions } from "./useTeamActions";
import { useProfilePanel } from "@/shared/context/ProfilePanelContext";
import { useAppNavigation } from "@/app/navigation/useAppNavigation";
import { useBakedBuildEnvQuery } from "@/features/agents/hooks";
import { useGlobalAgentConfig } from "@/features/agents/useGlobalAgentConfig";
import { PageHeader } from "@/shared/ui/PageHeader";
import { GlobalAgentConfigSettingsCard } from "@/features/settings/ui/GlobalAgentConfigSettingsCard";
import { formatAiDefaultsSummary } from "./AgentAiDefaults";
import { getInheritedAgentDefaults } from "./bakedEnvHelpers";
export function AgentsView() {
const { openPersonaProfilePanel, openProfilePanel } = useProfilePanel();
const { goSettings } = useAppNavigation();
const { globalConfig } = useGlobalAgentConfig();
const { data: bakedEnv } = useBakedBuildEnvQuery({ enabled: true });
const inheritedDefaults = getInheritedAgentDefaults(globalConfig, bakedEnv);
const aiDefaultsSummary = formatAiDefaultsSummary(inheritedDefaults);
const agents = useManagedAgentActions();
const personas = usePersonaActions();
const teamImportInputRef = React.useRef<HTMLInputElement | null>(null);
@@ -95,9 +104,11 @@ export function AgentsView() {
title="Agents"
/>
<div className="flex flex-col gap-8">
<GlobalAgentConfigSettingsCard />
<UnifiedAgentsSection
aiDefaultsSummary={aiDefaultsSummary}
onEditAiDefaults={() => {
void goSettings("agents");
}}
actionErrorMessage={agents.actionErrorMessage}
actionNoticeMessage={agents.actionNoticeMessage}
agents={agents.managedAgents}
@@ -32,6 +32,7 @@ import { PersonaActionsMenu } from "./PersonaActionsMenu";
import { buildUnifiedGroups, pickProfileAgent } from "./unifiedAgentGroups";
type UnifiedAgentsSectionProps = {
aiDefaultsSummary: string;
actionErrorMessage: string | null;
actionNoticeMessage: string | null;
agents: ManagedAgent[];
@@ -41,6 +42,7 @@ type UnifiedAgentsSectionProps = {
startingAgentPubkey: string | null;
startingPersonaIds: ReadonlySet<string>;
onBulkStopRunning: () => void;
onEditAiDefaults: () => void;
onOpenAgentProfile: (
pubkey: string,
options?: ProfilePanelOpenOptions,
@@ -74,6 +76,7 @@ const AGENT_CARD_GRID_CLASS = `${AGENT_CARD_COLUMN_CLASS} grid grid-cols-[repeat
export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
const {
actionErrorMessage,
aiDefaultsSummary,
actionNoticeMessage,
agents,
agentsError,
@@ -82,6 +85,7 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
startingAgentPubkey,
startingPersonaIds,
onBulkStopRunning,
onEditAiDefaults,
onOpenAgentProfile,
onOpenPersonaProfile,
onStartAgent,
@@ -160,11 +164,13 @@ export function UnifiedAgentsSection(props: UnifiedAgentsSectionProps) {
<AgentsListHeader
agentCount={agents.length}
aiDefaultsSummary={aiDefaultsSummary}
fileInputRef={fileInputRef}
handleFileChange={handleFileChange}
isActionPending={isActionPending}
runningCount={runningCount}
onBulkStopRunning={onBulkStopRunning}
onEditAiDefaults={onEditAiDefaults}
/>
{isLoading ? <LoadingSkeleton /> : null}
@@ -437,18 +443,22 @@ function firstAvatarUrl(
function AgentsListHeader({
agentCount,
aiDefaultsSummary,
fileInputRef,
handleFileChange,
isActionPending,
runningCount,
onBulkStopRunning,
onEditAiDefaults,
}: {
agentCount: number;
aiDefaultsSummary: string;
fileInputRef: React.RefObject<HTMLInputElement | null>;
handleFileChange: (e: React.ChangeEvent<HTMLInputElement>) => void;
isActionPending: boolean;
runningCount: number;
onBulkStopRunning: () => void;
onEditAiDefaults: () => void;
}) {
return (
<div className={AGENT_CARD_COLUMN_CLASS}>
@@ -461,7 +471,22 @@ function AgentsListHeader({
/>
<SectionHeader
title="Agents"
description="Agents in this community."
description={
<>
<span>Agents in this community.</span>
<span className="mt-1 flex flex-wrap items-center gap-x-1 text-xs">
<span>AI defaults: {aiDefaultsSummary}</span>
<Button
onClick={onEditAiDefaults}
size="xs"
type="button"
variant="link"
>
Edit defaults
</Button>
</span>
</>
}
action={
agentCount > 0 ? (
<DropdownMenu modal={false}>
@@ -96,7 +96,7 @@ export function getAdvancedInheritedSummary(
...(effort.value ? [`effort ${effort.value}`] : []),
...(globalEnvLabel ? [globalEnvLabel] : []),
];
return `Using global defaults: ${parts.join(" · ")}`;
return `Using AI defaults: ${parts.join(" · ")}`;
}
export function getInheritedAgentDefaults(
@@ -840,8 +840,8 @@ test("providerDefaultLabel_globalSet_returnsInheritLabel", () => {
const label = getDefaultLlmProviderLabel("buzz-agent", "anthropic");
assert.equal(
label,
"Inherit global default (anthropic)",
"global provider set must return 'Inherit global default (<provider>)'",
"Use AI defaults (anthropic)",
"global provider set must return 'Use AI defaults (<provider>)'",
);
});
@@ -850,7 +850,7 @@ test("providerDefaultLabel_globalSetWithWhitespace_trimsAndReturnsInherit", () =
const label = getDefaultLlmProviderLabel("buzz-agent", " openai ");
assert.equal(
label,
"Inherit global default (openai)",
"Use AI defaults (openai)",
"global provider with surrounding whitespace must be trimmed in label",
);
});
@@ -858,7 +858,7 @@ test("providerDefaultLabel_globalSetWithWhitespace_trimsAndReturnsInherit", () =
test("providerDefaultLabel_sharedCompute_neverLeaksInternalId", () => {
assert.equal(
getDefaultLlmProviderLabel("buzz-agent", "relay-mesh"),
"Inherit global default (Buzz shared compute)",
"Use AI defaults (Buzz shared compute)",
);
});
@@ -972,8 +972,8 @@ test("modelDefaultLabel_globalSet_returnsInheritLabel", () => {
const label = getDefaultLlmModelLabel("claude-opus-4-5");
assert.equal(
label,
"Inherit global default (claude-opus-4-5)",
"global model set must return 'Inherit global default (<model>)'",
"Use AI defaults (claude-opus-4-5)",
"global model set must return 'Use AI defaults (<model>)'",
);
});
@@ -982,7 +982,7 @@ test("modelDefaultLabel_globalSetWithWhitespace_trimsAndReturnsInherit", () => {
const label = getDefaultLlmModelLabel(" gpt-4o ");
assert.equal(
label,
"Inherit global default (gpt-4o)",
"Use AI defaults (gpt-4o)",
"global model with surrounding whitespace must be trimmed in label",
);
});
@@ -1131,11 +1131,11 @@ test("f3_templateDialog_localProviderBlankGlobalAnthropicNoModel_saveBlocked", (
test("f3_templateDialog_globalModelSet_zeroValueLabelIsInherit", () => {
// Case 3: global model set → the zero-value model dropdown option must show
// "Inherit global default (<model>)" not the generic "Default model".
// "Use AI defaults (<model>)" not the generic "Default model".
// getDefaultLlmModelLabel is what AgentDefinitionDialog now uses for that slot.
assert.equal(
getDefaultLlmModelLabel("claude-opus-4-5"),
"Inherit global default (claude-opus-4-5)",
"Use AI defaults (claude-opus-4-5)",
"zero-value model option label must show the global model name when set",
);
assert.equal(
@@ -1175,7 +1175,7 @@ test("f3b_buildTemplateModelDropdownOptions_anthropicGlobalModelSet_containsInhe
);
assert.equal(
inheritEntry.label,
"Inherit global default (claude-opus-4-5)",
"Use AI defaults (claude-opus-4-5)",
"inherit entry must carry the global model name",
);
});
@@ -1215,7 +1215,7 @@ test("f3b_buildTemplateModelDropdownOptions_blankProviderGlobalModelSet_noDouble
);
assert.equal(
autoEntries[0].label,
"Inherit global default (claude-opus-4-5)",
"Use AI defaults (claude-opus-4-5)",
"existing zero-value entry must be relabeled with the global model name",
);
});
@@ -271,21 +271,19 @@ export function getDefaultLlmProviderLabel(
) {
const trimmedGlobal = (globalProvider ?? "").trim();
return trimmedGlobal
? `Inherit global default (${providerDisplayLabel(trimmedGlobal)})`
? `Use AI defaults (${providerDisplayLabel(trimmedGlobal)})`
: "Select a provider\u2026";
}
/** Returns the zero-value model option label.
*
* When a global model is configured, the empty-model option reads
* `Inherit global default (<model>)` so users can see which model will run.
* `Use AI defaults (<model>)` so users can see which model will run.
* Otherwise falls back to the generic `"Default model"` placeholder.
*/
export function getDefaultLlmModelLabel(globalModel?: string) {
const trimmedGlobal = (globalModel ?? "").trim();
return trimmedGlobal
? `Inherit global default (${trimmedGlobal})`
: "Default model";
return trimmedGlobal ? `Use AI defaults (${trimmedGlobal})` : "Default model";
}
/**
@@ -294,7 +292,7 @@ export function getDefaultLlmModelLabel(globalModel?: string) {
*
* Explicit-model providers (e.g. anthropic) have their zero-value option
* filtered out by `getPersonaModelOptions`, so a relabel-only map would never
* produce the `Inherit global default (<model>)` entry. This helper prepends
* produce the `Use AI defaults (<model>)` entry. This helper prepends
* it when `globalModel` is non-empty AND no zero-value option already exists,
* making the inherited global model visible and selectable in the dropdown.
*
@@ -118,12 +118,12 @@ test("resolveInheritedRuntimeSubmission preserves a user-edited provider + env w
assert.equal(result.model, null);
});
test("resolveInheritedRuntimeSubmission clears an already-inheriting agent's provider override when the user picks Default", () => {
// Regression: an already-inheriting agent had a saved provider override
// (databricks). The user picks the "Default" option → empty local provider.
// Because the agent was NOT harness-pinned at open, this is a deliberate
// clear, not the inherit-transition — persist null (runtime default), do NOT
// resurrect the persona provider.
test("resolveInheritedRuntimeSubmission clears an already-inheriting agent's persona-backed provider and model to AI defaults", () => {
// Regression: an already-inheriting agent is linked to a persona with a
// provider and model. The user picks "Use AI defaults" for both fields.
// Because the agent was NOT harness-pinned at open, these empty local values
// are deliberate clears, not an inherit-transition — persist null for both
// rather than resurrecting the persona values.
const result = resolveInheritedRuntimeSubmission({
inheritHarness: true,
agentWasHarnessPinned: false,
@@ -135,6 +135,7 @@ test("resolveInheritedRuntimeSubmission clears an already-inheriting agent's pro
personaEnvVars: { ANTHROPIC_API_KEY: "sk-persona" },
});
assert.equal(result.provider, null);
assert.equal(result.model, null);
assert.deepEqual(result.envVars, {});
});
@@ -138,8 +138,8 @@ export function GlobalAgentConfigSettingsCard() {
data-testid="settings-global-agent-config"
>
<SectionHeader
title="Agent defaults"
description="Default settings for every agent running on this computer. You can override them for any individual agent or persona."
title="AI defaults"
description="Provider, model, effort, and environment settings inherited by local agents. Agent-specific settings always take priority."
/>
{isLoading ? (
@@ -63,6 +63,7 @@ import { MobilePairingCard } from "./MobilePairingCard";
import { ModerationQueueCard } from "./ModerationQueueCard";
import { NotificationSettingsCard } from "./NotificationSettingsCard";
import { PreventSleepSettingsCard } from "./PreventSleepSettingsCard";
import { GlobalAgentConfigSettingsCard } from "./GlobalAgentConfigSettingsCard";
import { ProfileSettingsCard } from "./ProfileSettingsCard";
import { UpdateChecker } from "../UpdateChecker";
import { SettingsSectionHeader } from "./SettingsSectionHeader";
@@ -712,7 +713,12 @@ export function renderSettingsSection(
case "experimental":
return <ExperimentalFeaturesCard />;
case "agents":
return <PreventSleepSettingsCard />;
return (
<div className="space-y-12">
<GlobalAgentConfigSettingsCard />
<PreventSleepSettingsCard />
</div>
);
case "channel-templates":
return <ChannelTemplatesSettingsCard />;
case "compute":
@@ -26,16 +26,25 @@ const CASCADE_AGENT_A_PUBKEY = "aa".repeat(32);
const CASCADE_AGENT_B_PUBKEY = "bb".repeat(32);
/**
* Navigate to the Agents view and wait for the global agent config card to
* finish loading (spinner gone). The card lives at the bottom of the view.
* Navigate to the Agents view and wait for its unified list to mount.
*/
async function openAgentsView(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
await expect(page.getByTestId("unified-agents-groups")).toBeVisible({
timeout: 10_000,
});
}
async function openAiDefaultsSettings(page: import("@playwright/test").Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByTestId("open-settings").click();
await page.getByTestId("profile-popover-settings").click();
await expect(page.getByTestId("settings-view")).toBeVisible();
await page.getByTestId("settings-nav-agents").click();
await expect(page.getByTestId("settings-global-agent-config")).toBeVisible({
timeout: 10_000,
});
// Spinner disappears once the load effect resolves.
await expect(page.locator(".animate-spin").first()).not.toBeVisible({
timeout: 5_000,
});
@@ -120,7 +129,7 @@ test.describe("agent lifecycle feedback screenshots", () => {
globalConfigRestartedCount: 2,
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
@@ -150,7 +159,7 @@ test.describe("agent lifecycle feedback screenshots", () => {
test("03-save-plain", async ({ page }) => {
await installMockBridge(page);
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
@@ -264,7 +273,7 @@ test.describe("agent lifecycle feedback screenshots", () => {
globalConfigRestartedCount: 1,
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
@@ -287,7 +296,7 @@ test.describe("agent lifecycle feedback screenshots", () => {
globalConfigFailedRestartCount: 1,
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
@@ -319,7 +328,7 @@ test.describe("agent lifecycle feedback screenshots", () => {
globalConfigSaveDelayMs: 2_000,
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
const provider = page.locator("#global-agent-provider");
@@ -24,12 +24,16 @@ import { waitForAnimations } from "../helpers/animations";
const SHOTS = "test-results/screenshots-dialogs";
/**
* Navigate to the agents view and wait for the global agent config card to
* finish its async load (spinner gone, card content visible).
* Open Settings Agents through the app UI and wait for the defaults card to
* finish loading. The CI static server does not provide SPA fallbacks for a
* direct `/settings` request.
*/
async function openAgentsView(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
async function openAiDefaultsSettings(page: import("@playwright/test").Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByTestId("open-settings").click();
await page.getByTestId("profile-popover-settings").click();
await expect(page.getByTestId("settings-view")).toBeVisible();
await page.getByTestId("settings-nav-agents").click();
await expect(page.getByTestId("settings-global-agent-config")).toBeVisible({
timeout: 10_000,
});
@@ -58,7 +62,7 @@ test.describe("agent provider dropdown screenshots", () => {
// BUZZ_AGENT_PROVIDER is baked and hideProviderIds is empty → v1 appears.
test("01-provider-dropdown-oss", async ({ page }) => {
await installMockBridge(page);
await openAgentsView(page);
await openAiDefaultsSettings(page);
const providerSelect = page.locator("#global-agent-provider");
await expect(providerSelect).toBeVisible({ timeout: 5_000 });
@@ -98,7 +102,7 @@ test.describe("agent provider dropdown screenshots", () => {
env_vars: {},
},
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const effortSelect = page.locator("#global-agent-thinking-effort");
await expect(effortSelect).toBeVisible({ timeout: 5_000 });
+3 -5
View File
@@ -202,14 +202,12 @@ test.describe("edit agent dialog", () => {
await openEditDialog(page);
await expect(page.locator("#edit-agent-llm-provider")).toHaveText(
"Inherit global default (anthropic)",
"Use AI defaults (anthropic)",
);
await expect(page.locator("#edit-agent-model")).toHaveText(
"Inherit global default (claude-opus-4-5)",
"Use AI defaults (claude-opus-4-5)",
);
await expect(
page.getByText("Using global defaults: effort low"),
).toBeVisible();
await expect(page.getByText("Using AI defaults: effort low")).toBeVisible();
});
test("profile Edit routes persona-linked agents to the definition editor", async ({
@@ -12,17 +12,19 @@ async function settleAnimations(page: import("@playwright/test").Page) {
}
/**
* Navigate to the Agents view (where GlobalAgentConfigSettingsCard lives) and
* wait for the card to finish loading.
* Open Settings Agents through the app UI and wait for the defaults card to
* load. CI serves the built SPA with a static file server, so navigating to
* `/settings` directly returns a 404 before the client router can start.
*/
async function openAgentsView(page: import("@playwright/test").Page) {
await page.goto("/");
await page.getByTestId("open-agents-view").click();
// Wait for the global agent config card to mount and finish its load effect.
async function openAiDefaultsSettings(page: import("@playwright/test").Page) {
await page.goto("/", { waitUntil: "domcontentloaded" });
await page.getByTestId("open-settings").click();
await page.getByTestId("profile-popover-settings").click();
await expect(page.getByTestId("settings-view")).toBeVisible();
await page.getByTestId("settings-nav-agents").click();
await expect(page.getByTestId("settings-global-agent-config")).toBeVisible({
timeout: 10_000,
});
// The card shows a spinner while loading; wait for it to disappear.
await expect(page.locator(".animate-spin").first()).not.toBeVisible({
timeout: 5_000,
});
@@ -65,7 +67,7 @@ test.describe("global agent config screenshots", () => {
},
});
await openAgentsView(page);
await openAiDefaultsSettings(page);
const card = page.getByTestId("settings-global-agent-config");
await card.scrollIntoViewIfNeeded();
@@ -187,14 +189,12 @@ test.describe("global agent config screenshots", () => {
await openCreateDialog(page);
await expect(page.locator("#persona-llm-provider")).toHaveText(
"Inherit global default (anthropic)",
"Use AI defaults (anthropic)",
);
await expect(page.locator("#persona-model")).toHaveText(
"Inherit global default (claude-opus-4-5)",
"Use AI defaults (claude-opus-4-5)",
);
await expect(
page.getByText("Using global defaults: effort low"),
).toBeVisible();
await expect(page.getByText("Using AI defaults: effort low")).toBeVisible();
});
// Shot 04: Create gate BLOCKED — no per-agent provider, no global provider