From 9c1f8fb89ad9932b1d493b77dedcc79c42b20496 Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 30 Jul 2026 14:23:49 +0100 Subject: [PATCH 1/5] Polish Share Compute settings Signed-off-by: kenny lopez --- .../ui/MeshComputeSettingsCard.tsx | 515 ++++++++++-------- .../settings/ui/AgentDefaultsSettingsCard.tsx | 2 +- desktop/tests/e2e/mesh-compute.spec.ts | 57 +- 3 files changed, 326 insertions(+), 248 deletions(-) diff --git a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx index fd7550eff0..dcefe8f672 100644 --- a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx +++ b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx @@ -1,9 +1,19 @@ import * as React from "react"; -import { ChevronDown, Cpu } from "lucide-react"; +import { ChevronDown } from "lucide-react"; +import { AnimatePresence, motion, useReducedMotion } from "motion/react"; -import { Input } from "@/shared/ui/input"; import { Switch } from "@/shared/ui/switch"; import { cn } from "@/shared/lib/cn"; +import { + AgentConfigTextInput, + AgentDropdownSelect, + type AgentDropdownOption, +} from "@/features/agents/ui/agentConfigControls"; +import { + CUSTOM_MODEL_DROPDOWN_VALUE, + PERSONA_FIELD_CONTROL_CLASS, + PERSONA_FIELD_SHELL_CLASS, +} from "@/features/agents/ui/agentConfigOptions"; import { meshStartNode, @@ -17,10 +27,6 @@ import type { MeshModelOption, MeshNodeStatus, } from "@/shared/api/tauriMesh"; -import { - SettingsOptionGroup, - SettingsOptionRow, -} from "@/features/settings/ui/SettingsOptionGroup"; import { SettingsSectionHeader } from "@/features/settings/ui/SettingsSectionHeader"; import { classifyModelRef } from "../classifyModelRef"; import { @@ -36,6 +42,20 @@ import { deriveServingIndicator } from "../servingUsage"; const MODEL_DRAFT_STORAGE_KEY = "buzz.mesh-compute.share.model.v1"; const MAX_VRAM_DRAFT_STORAGE_KEY = "buzz.mesh-compute.share.max-vram-gb.v1"; +// Keep the Share compute controls visually and behaviorally aligned with the +// agent configuration fields. This is intentionally the same shell used by +// AgentDefaultsEditor rather than a local approximation of a select. +const MESH_SELECT_TRIGGER_CLASS = cn( + PERSONA_FIELD_CONTROL_CLASS, + PERSONA_FIELD_SHELL_CLASS, + "h-11 px-3 py-2 leading-6 hover:bg-muted/40 focus:bg-muted/40 [&>svg]:text-muted-foreground/60", +); + +const SHARE_COMPUTE_REVEAL_TRANSITION = { + duration: 0.22, + ease: [0.23, 1, 0.32, 1], +} as const; + function readDraft(key: string): string { try { return window.localStorage.getItem(key) ?? ""; @@ -64,6 +84,7 @@ function writeDraft(key: string, value: string): void { * exposing implementation protocols or raw mesh controls. */ export function MeshComputeSettingsCard() { + const shouldReduceMotion = useReducedMotion(); const { status, error, refresh } = useMeshNodeStatus(); const [installedModels, setInstalledModels] = React.useState< MeshModelOption[] @@ -75,6 +96,7 @@ export function MeshComputeSettingsCard() { const [maxVramGb, setMaxVramGb] = React.useState(() => readDraft(MAX_VRAM_DRAFT_STORAGE_KEY), ); + const [isCustomModelEditing, setIsCustomModelEditing] = React.useState(false); const [advancedOpen, setAdvancedOpen] = React.useState(false); const [actionInFlight, setActionInFlight] = React.useState(false); const [pendingAction, setPendingAction] = React.useState< @@ -163,6 +185,7 @@ export function MeshComputeSettingsCard() { const controlsDisabled = actionInFlight || (slotOccupied && !isConsuming); const refClass = classifyModelRef(modelInput); const canStart = refClass.kind !== "unknown" && !actionInFlight; + const showSharingControls = isSharing || pendingAction === "start"; async function handleToggle(next: boolean) { // Never let the Share switch tear down a consume session. The switch is @@ -204,12 +227,7 @@ export function MeshComputeSettingsCard() {
- Share this machine with your relay. When on, other members can run - their agents here. - - } + description="Share this machine with members of this relay so they can run agents here." /> {error ? ( @@ -226,8 +244,8 @@ export function MeshComputeSettingsCard() { ) : null} - - +
+
- - {servingIndicator.show ? ( -

- {servingIndicator.label} - {servingIndicator.detail ? ( - - {" "} - · {servingIndicator.detail} - - ) : null} -

+ {!isSharing ? ( + ) : null}
- +
+ + { + setModelInput(next); + writeDraft(MODEL_DRAFT_STORAGE_KEY, next); + }} + /> -
- -
- { - const next = e.target.value; - setModelInput(next); - writeDraft(MODEL_DRAFT_STORAGE_KEY, next); - }} - placeholder="Qwen3-8B-Q4_K_M or hf://meshllm/qwen3-8b@main" - value={modelInput} - /> -

- Choose a suggested model below, or enter a model reference or - local file. Buzz downloads remote models when sharing starts. -

- {catalog && catalog.entries.length > 0 ? ( - { - setModelInput(name); - writeDraft(MODEL_DRAFT_STORAGE_KEY, name); - }} - selected={modelInput.trim()} +

Sharing

+
+ - ) : null} - {installedModels.length > 0 ? ( -
-

- Already installed on this machine: -

-
    - {installedModels.map((m) => ( -
  • - -
  • - ))} -
-
- ) : null} -
-
+ {servingIndicator.label} + {servingIndicator.detail ? ( + + {" "} + · {servingIndicator.detail} + + ) : null} +

+ ) : null} +
+
+ ) : null} -
- setAdvancedOpen((e.target as HTMLDetailsElement).open) - } - open={advancedOpen} - > - - - Advanced - -
- - { - const next = e.target.value; - setMaxVramGb(next); - writeDraft(MAX_VRAM_DRAFT_STORAGE_KEY, next); - }} - placeholder="No limit" - value={maxVramGb} - /> - {status?.consoleUrl ? ( -

- Debug console:{" "} - + {showSharingControls ? ( + +

-
- - -

- Only members of this relay can use this machine's shared compute. -

+ Advanced + + + {advancedOpen ? ( +
+ + { + const next = e.target.value; + setMaxVramGb(next); + writeDraft(MAX_VRAM_DRAFT_STORAGE_KEY, next); + }} + placeholder="No limit" + usePersonaInputStyle + value={maxVramGb} + /> + {status?.consoleUrl ? ( +

+ Debug console:{" "} + + {status.consoleUrl} + +

+ ) : null} +
+ ) : null} + + + ) : null} + + ); } @@ -465,100 +467,153 @@ const FIT_CLASS: Record = { }; /** - * Hardware-ranked curated model list (mesh-console's diagnose pattern). - * Click a row to fill the model field. Models too large for this machine are - * listed but disabled — honest about why, instead of hiding them. + * Share Compute's models use the agent configuration picker instead of a + * second, hand-rolled option system. The catalog remains hardware-aware, but + * its recommendations, installed models, and advanced choices now appear in + * the same searchable dropdown used when customizing an agent. */ -function CatalogPicker({ +function MeshModelPicker({ catalog, disabled, - onPick, - selected, + installedModels, + isCustomModelEditing, + model, + onCustomModelEditingChange, + onModelChange, }: { - catalog: MeshModelCatalog; + catalog: MeshModelCatalog | null; disabled: boolean; - onPick: (name: string) => void; - selected: string; + installedModels: readonly MeshModelOption[]; + isCustomModelEditing: boolean; + model: string; + onCustomModelEditingChange: (editing: boolean) => void; + onModelChange: (model: string) => void; }) { - const [expanded, setExpanded] = React.useState(false); - // Above the fold: the Buzz-curated picks (models known to work well with - // agents on shared compute). Below: everything else, as advanced options. - const curated = catalog.entries.filter((e) => e.curated); - const advanced = catalog.entries.filter((e) => !e.curated); - const visible = expanded ? catalog.entries : curated; + const options = React.useMemo(() => { + const seen = new Set(); + const catalogOptions = (catalog?.entries ?? []).map((entry) => { + seen.add(entry.name); + return { + disabled: entry.fit === "too_large", + label: , + value: entry.name, + }; + }); + const localOptions = installedModels.flatMap((installed) => { + if (seen.has(installed.id)) return []; + return [ + { + label: ( +
+ + {installed.name ?? installed.id} + + + Installed + +
+ ), + value: installed.id, + }, + ]; + }); + return [ + ...catalogOptions, + ...localOptions, + { label: "Custom model…", value: CUSTOM_MODEL_DROPDOWN_VALUE }, + ]; + }, [catalog?.entries, installedModels]); + const knownModel = options.some((option) => option.value === model.trim()); + const showCustomModelInput = + isCustomModelEditing || (model.trim().length > 0 && !knownModel); + const selectedValue = showCustomModelInput + ? CUSTOM_MODEL_DROPDOWN_VALUE + : model.trim(); + + function handleModelChange(next: string) { + if (next === CUSTOM_MODEL_DROPDOWN_VALUE) { + onCustomModelEditingChange(true); + return; + } + onCustomModelEditingChange(false); + onModelChange(next); + } + return ( -
+
+ + + {showCustomModelInput ? ( + onModelChange(event.target.value)} + placeholder="Qwen3-8B-Q4_K_M or hf://meshllm/qwen3-8b@main" + usePersonaInputStyle + value={model} + /> + ) : null}

- Recommended for this machine - {catalog.gpuName ? ` (${catalog.gpuName}, ` : " ("} - {catalog.vramDisplay} AI memory): + {catalog + ? `Recommended for this machine${catalog.gpuName ? ` (${catalog.gpuName}, ${catalog.vramDisplay} AI memory)` : ""}.` + : "Choose a model or enter a model reference or local file."}{" "} + Buzz downloads remote models when sharing starts.

-
    - {visible.map((entry) => { - const isSelected = entry.name === selected; - const tooLarge = entry.fit === "too_large"; - return ( -
  • - -
  • - ); - })} -
- {advanced.length > 0 ? ( - +
+ ); +} + +function MeshModelOptionLabel({ entry }: { entry: MeshCatalogEntry }) { + return ( +
+ {entry.name} + {entry.size} + + {FIT_LABEL[entry.fit]} + + {entry.recommended ? ( + + Recommended + + ) : null} + {entry.installed ? ( + + Installed + + ) : null} + {!entry.curated ? ( + + Advanced + ) : null}
); } function StatusLine({ + displayModel, isConsuming, + omitSharingVerb = false, pendingAction, status, }: { + displayModel?: string; isConsuming: boolean; + omitSharingVerb?: boolean; pendingAction: "start" | "stop" | null; status: MeshNodeStatus | null; }) { @@ -583,12 +638,10 @@ function StatusLine({ return

Checking status…

; } const { state, health, modelId, modelName } = status; - const modelLabel = modelName ?? modelId ?? ""; + const modelLabel = displayModel ?? modelName ?? modelId ?? ""; if (state === "off") { - return ( -

Not sharing right now.

- ); + return null; } if (state === "starting") { const reason = @@ -614,7 +667,9 @@ function StatusLine({ } return (

- Sharing{modelLabel ? ` ${modelLabel}` : ""} with relay members. + {omitSharingVerb ? "" : "Sharing"} + {modelLabel ? `${omitSharingVerb ? "" : " "}${modelLabel}` : ""} with + relay members.

); } diff --git a/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx b/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx index f59d544d8f..b05f28236b 100644 --- a/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx +++ b/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx @@ -11,7 +11,7 @@ export function AgentDefaultsSettingsCard() { title="Agent defaults" description="Provider, model, effort, and environment settings inherited by local agents. Agent-specific settings always take priority." /> - + ); } diff --git a/desktop/tests/e2e/mesh-compute.spec.ts b/desktop/tests/e2e/mesh-compute.spec.ts index b2e8fc28a9..6e44488657 100644 --- a/desktop/tests/e2e/mesh-compute.spec.ts +++ b/desktop/tests/e2e/mesh-compute.spec.ts @@ -15,9 +15,11 @@ type E2eWindow = Window & { }) => void; }; -test("Share compute selects the curated default and starts and stops sharing", async ({ - page, -}) => { +test("Share compute chooses a model before sharing", async ({ page }) => { + const modelRef = "hf://demo/SmolLM2-135M-Instruct-GGUF:Q4_K_M"; + await page.addInitScript((model) => { + window.localStorage.setItem("buzz.mesh-compute.share.model.v1", model); + }, modelRef); await installMockBridge(page); await page.goto("/"); await openSettings(page, "compute"); @@ -26,19 +28,31 @@ test("Share compute selects the curated default and starts and stops sharing", a const toggle = page.getByTestId("mesh-share-compute-toggle"); const model = page.getByTestId("mesh-share-compute-model"); - await expect(card).toContainText("Not sharing right now"); - await expect(card).toContainText( - "Choose a suggested model below, or enter a model reference or local file", - ); - await expect(model).toHaveValue("Gemma-4-E4B-it-Q4_K_M"); + await expect(card).not.toContainText("Not sharing right now"); + await expect( + page.getByTestId("mesh-share-compute-options-motion"), + ).toHaveCount(0); + await expect( + page.getByTestId("mesh-share-compute-sharing-status"), + ).toHaveCount(0); + await expect(model).toBeVisible(); await expect(toggle).toBeEnabled(); + + await toggle.click(); + await expect( + page.getByTestId("mesh-share-compute-options-motion"), + ).toBeVisible(); + await expect( + page.getByTestId("mesh-share-compute-sharing-status"), + ).toBeVisible(); + await expect(model).toBeVisible(); await expect(card).toContainText( "Buzz downloads remote models when sharing starts", ); - - await toggle.click(); await expect(toggle).toBeChecked(); - await expect(card).toContainText("Sharing Gemma 4 E4B with relay members"); + await expect( + page.getByTestId("mesh-share-compute-sharing-status"), + ).toContainText("SmolLM2 135M with relay members"); await expect .poll(() => page.evaluate(() => (window as E2eWindow).__BUZZ_E2E_COMMANDS__ ?? []), @@ -53,13 +67,20 @@ test("Share compute selects the curated default and starts and stops sharing", a .toContainEqual({ command: "mesh_start_node", payload: { - request: { mode: "serve", modelId: "Gemma-4-E4B-it-Q4_K_M" }, + request: { mode: "serve", modelId: modelRef }, }, }); await toggle.click(); await expect(toggle).not.toBeChecked(); - await expect(card).toContainText("Not sharing right now"); + await expect(card).not.toContainText("Not sharing right now"); + await expect( + page.getByTestId("mesh-share-compute-options-motion"), + ).toHaveCount(0); + await expect( + page.getByTestId("mesh-share-compute-sharing-status"), + ).toHaveCount(0); + await expect(model).toBeVisible(); await expect .poll(() => page.evaluate(() => (window as E2eWindow).__BUZZ_E2E_COMMANDS__ ?? []), @@ -97,18 +118,20 @@ test("a consuming client can switch to sharing its saved local model", async ({ const card = page.getByTestId("settings-mesh-share-compute"); const toggle = page.getByTestId("mesh-share-compute-toggle"); - const model = page.getByTestId("mesh-share-compute-model"); - await expect(card).toContainText( "This machine is currently using another member's shared compute", ); await expect(card).toContainText("Buzz may briefly restart"); await expect(toggle).not.toBeChecked(); - await expect(model).toBeEnabled(); - await expect(model).toHaveValue(localModel); + await expect( + page.getByTestId("mesh-share-compute-options-motion"), + ).toHaveCount(0); await expect(toggle).toBeEnabled(); await toggle.click(); await expect(toggle).toBeChecked(); + await expect(page.getByLabel("Custom model reference")).toHaveValue( + localModel, + ); const commands = await page.evaluate(() => ({ names: (window as E2eWindow).__BUZZ_E2E_COMMANDS__ ?? [], From 5e4713f4296922ece9ead8a7a5aebc8e6f840d22 Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 30 Jul 2026 14:44:31 +0100 Subject: [PATCH 2/5] test(desktop): cover share compute picker Signed-off-by: kenny lopez --- desktop/tests/e2e/global-agent-config-screenshots.spec.ts | 1 + desktop/tests/e2e/mesh-compute.spec.ts | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/desktop/tests/e2e/global-agent-config-screenshots.spec.ts b/desktop/tests/e2e/global-agent-config-screenshots.spec.ts index 7ec1daa236..278dbeefb6 100644 --- a/desktop/tests/e2e/global-agent-config-screenshots.spec.ts +++ b/desktop/tests/e2e/global-agent-config-screenshots.spec.ts @@ -226,6 +226,7 @@ test.describe("global agent config screenshots", () => { await page .getByTestId("global-agent-default-harness-option-claude") .click(); + await waitForAnimations(page); await expect(page.getByTestId("global-agent-model")).toHaveText( /Default model/, ); diff --git a/desktop/tests/e2e/mesh-compute.spec.ts b/desktop/tests/e2e/mesh-compute.spec.ts index 6e44488657..5787185e42 100644 --- a/desktop/tests/e2e/mesh-compute.spec.ts +++ b/desktop/tests/e2e/mesh-compute.spec.ts @@ -127,11 +127,11 @@ test("a consuming client can switch to sharing its saved local model", async ({ page.getByTestId("mesh-share-compute-options-motion"), ).toHaveCount(0); await expect(toggle).toBeEnabled(); - await toggle.click(); - await expect(toggle).toBeChecked(); await expect(page.getByLabel("Custom model reference")).toHaveValue( localModel, ); + await toggle.click(); + await expect(toggle).toBeChecked(); const commands = await page.evaluate(() => ({ names: (window as E2eWindow).__BUZZ_E2E_COMMANDS__ ?? [], From 790cb7f9ef648e4cc36f2116bd3640a3dc35655f Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 30 Jul 2026 14:56:18 +0100 Subject: [PATCH 3/5] fix(desktop): preserve share compute options Signed-off-by: kenny lopez --- .../ui/MeshComputeSettingsCard.tsx | 158 +++++++++--------- 1 file changed, 78 insertions(+), 80 deletions(-) diff --git a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx index dcefe8f672..acf038b30f 100644 --- a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx +++ b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx @@ -293,41 +293,57 @@ export function MeshComputeSettingsCard() { }} /> - {isSharing ? ( -
+ + {advancedOpen ? ( +
+ + { + const next = e.target.value; + setMaxVramGb(next); + writeDraft(MAX_VRAM_DRAFT_STORAGE_KEY, next); + }} + placeholder="No limit" + usePersonaInputStyle + value={maxVramGb} /> - {servingIndicator.show ? ( -

- {servingIndicator.label} - {servingIndicator.detail ? ( - - {" "} - · {servingIndicator.detail} - - ) : null} + {status?.consoleUrl ? ( +

+ Debug console:{" "} + + {status.consoleUrl} +

) : null}
-
- ) : null} + ) : null} +
{showSharingControls ? ( @@ -344,57 +360,39 @@ export function MeshComputeSettingsCard() { : SHARE_COMPUTE_REVEAL_TRANSITION } > -
- - {advancedOpen ? ( -
- - { - const next = e.target.value; - setMaxVramGb(next); - writeDraft(MAX_VRAM_DRAFT_STORAGE_KEY, next); - }} - placeholder="No limit" - usePersonaInputStyle - value={maxVramGb} - /> - {status?.consoleUrl ? ( -

- Debug console:{" "} - - {status.consoleUrl} - -

- ) : null} -
- ) : null} -
+ {servingIndicator.show ? ( +

+ {servingIndicator.label} + {servingIndicator.detail ? ( + + {" "} + · {servingIndicator.detail} + + ) : null} +

+ ) : null} + + ) : null}
From 7383bdb849ab4190cc5900578824714527d7d496 Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 30 Jul 2026 15:03:36 +0100 Subject: [PATCH 4/5] fix(desktop): preserve custom mesh model edits Signed-off-by: kenny lopez --- .../mesh-compute/ui/MeshComputeSettingsCard.tsx | 8 +++++++- desktop/tests/e2e/mesh-compute.spec.ts | 12 ++++++++---- 2 files changed, 15 insertions(+), 5 deletions(-) diff --git a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx index acf038b30f..bf2d8e7c22 100644 --- a/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx +++ b/desktop/src/features/mesh-compute/ui/MeshComputeSettingsCard.tsx @@ -559,7 +559,13 @@ function MeshModelPicker({ aria-label="Custom model reference" autoCorrect="off" disabled={disabled} - onChange={(event) => onModelChange(event.target.value)} + onChange={(event) => { + // A stored custom ref starts out inferred rather than explicitly + // selected. Mark it as an active custom edit before applying a + // cleared value so the field stays mounted while it is replaced. + onCustomModelEditingChange(true); + onModelChange(event.target.value); + }} placeholder="Qwen3-8B-Q4_K_M or hf://meshllm/qwen3-8b@main" usePersonaInputStyle value={model} diff --git a/desktop/tests/e2e/mesh-compute.spec.ts b/desktop/tests/e2e/mesh-compute.spec.ts index 5787185e42..df86893050 100644 --- a/desktop/tests/e2e/mesh-compute.spec.ts +++ b/desktop/tests/e2e/mesh-compute.spec.ts @@ -127,9 +127,11 @@ test("a consuming client can switch to sharing its saved local model", async ({ page.getByTestId("mesh-share-compute-options-motion"), ).toHaveCount(0); await expect(toggle).toBeEnabled(); - await expect(page.getByLabel("Custom model reference")).toHaveValue( - localModel, - ); + const customModel = page.getByLabel("Custom model reference"); + await expect(customModel).toHaveValue(localModel); + await customModel.fill(""); + await expect(customModel).toBeVisible(); + await customModel.fill("hf://demo/replacement-model:Q4_K_M"); await toggle.click(); await expect(toggle).toBeChecked(); @@ -140,6 +142,8 @@ test("a consuming client can switch to sharing its saved local model", async ({ expect(commands.names).not.toContain("mesh_stop_node"); expect(commands.payloads).toContainEqual({ command: "mesh_start_node", - payload: { request: { mode: "serve", modelId: localModel } }, + payload: { + request: { mode: "serve", modelId: "hf://demo/replacement-model:Q4_K_M" }, + }, }); }); From d09ab41c65c8980af6be645493d6434f42c21b35 Mon Sep 17 00:00:00 2001 From: kenny lopez Date: Thu, 30 Jul 2026 15:09:24 +0100 Subject: [PATCH 5/5] fix(desktop): keep agent defaults editable Signed-off-by: kenny lopez --- desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx b/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx index b05f28236b..f59d544d8f 100644 --- a/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx +++ b/desktop/src/features/settings/ui/AgentDefaultsSettingsCard.tsx @@ -11,7 +11,7 @@ export function AgentDefaultsSettingsCard() { title="Agent defaults" description="Provider, model, effort, and environment settings inherited by local agents. Agent-specific settings always take priority." /> - + ); }