From 3d1fa75b60971b7eb76a72180caa0086a6da21b7 Mon Sep 17 00:00:00 2001 From: Dotta Date: Wed, 22 Jul 2026 13:34:15 +0000 Subject: [PATCH] Fix configuration section composition and model fallback Co-Authored-By: Paperclip --- .../agent-configuration-shell.test.ts | 6 +- .../components/agent-configuration-shell.tsx | 5 +- ui/src/pages/AgentDetail.tsx | 214 +++++++++--------- 3 files changed, 110 insertions(+), 115 deletions(-) diff --git a/ui/src/components/agent-configuration-shell.test.ts b/ui/src/components/agent-configuration-shell.test.ts index 981ad9af922..a1922c26902 100644 --- a/ui/src/components/agent-configuration-shell.test.ts +++ b/ui/src/components/agent-configuration-shell.test.ts @@ -13,7 +13,7 @@ describe("agent configuration shell", () => { expect([...filterAgentConfigurationSections("sandbox")]).toEqual(["danger"]); }); - it("resolves adapter defaults to a concrete model label", () => { + it("does not guess an inherited adapter model from available choices", () => { const agent = { adapterType: "claude_local", adapterConfig: { modelReasoningEffort: "high" }, @@ -22,8 +22,8 @@ describe("agent configuration shell", () => { defaultEnvironmentId: null, } as unknown as Agent; - expect(resolveEffectiveConfiguration(agent, [{ id: "claude-fable-5", label: "Claude Fable 5" }], 2)).toMatchObject({ - model: "Claude Fable 5 · high", + expect(resolveEffectiveConfiguration(agent, 2)).toMatchObject({ + model: "Adapter default · high", modelInherited: true, environmentInherited: true, apiKeyCount: 2, diff --git a/ui/src/components/agent-configuration-shell.tsx b/ui/src/components/agent-configuration-shell.tsx index 5f22d327a55..45eed5f08b6 100644 --- a/ui/src/components/agent-configuration-shell.tsx +++ b/ui/src/components/agent-configuration-shell.tsx @@ -1,7 +1,6 @@ import type { ReactNode } from "react"; import { Search, Zap } from "lucide-react"; import type { Agent, AgentEnvConfig } from "@paperclipai/shared"; -import type { AdapterModel } from "../api/agents"; import { adapterLabels } from "./agent-config-primitives"; import { Badge } from "@/components/ui/badge"; import { cn } from "../lib/utils"; @@ -44,7 +43,7 @@ function readString(value: unknown): string { return typeof value === "string" ? value : ""; } -export function resolveEffectiveConfiguration(agent: Agent, adapterModels: AdapterModel[] = [], apiKeyCount = 0) { +export function resolveEffectiveConfiguration(agent: Agent, apiKeyCount = 0) { const adapterConfig = (agent.adapterConfig ?? {}) as Record; const runtimeConfig = (agent.runtimeConfig ?? {}) as Record; const heartbeat = (runtimeConfig.heartbeat ?? {}) as Record; @@ -52,7 +51,7 @@ export function resolveEffectiveConfiguration(agent: Agent, adapterModels: Adapt const cheap = (profiles.cheap ?? {}) as Record; const cheapConfig = (cheap.adapterConfig ?? {}) as Record; const explicitModel = readString(adapterConfig.model); - const resolvedModel = explicitModel || adapterModels[0]?.label || adapterModels[0]?.id || "Adapter default"; + const resolvedModel = explicitModel || "Adapter default"; const effort = readString(adapterConfig.modelReasoningEffort || adapterConfig.reasoningEffort || adapterConfig.effort || adapterConfig.variant || adapterConfig.mode); const env = (adapterConfig.env ?? {}) as AgentEnvConfig; return { diff --git a/ui/src/pages/AgentDetail.tsx b/ui/src/pages/AgentDetail.tsx index c34853a0356..e149159badc 100644 --- a/ui/src/pages/AgentDetail.tsx +++ b/ui/src/pages/AgentDetail.tsx @@ -1758,14 +1758,9 @@ function AgentConfigurePage({ queryKey: queryKeys.agents.keys(agentId), queryFn: () => agentsApi.listKeys(agentId, companyId), }); - const { data: adapterModels = [] } = useQuery({ - queryKey: companyId ? queryKeys.agents.adapterModels(companyId, agent.adapterType) : ["agents", "none", "adapter-models", agent.adapterType], - queryFn: () => agentsApi.adapterModels(companyId!, agent.adapterType), - enabled: Boolean(companyId), - }); const effectiveConfig = useMemo( - () => resolveEffectiveConfiguration(agent, adapterModels, keys.filter((key) => !key.revokedAt).length), - [adapterModels, agent, keys], + () => resolveEffectiveConfiguration(agent, keys.filter((key) => !key.revokedAt).length), + [agent, keys], ); const handleDirtyDetailsChange = useCallback((details: { count: number; sections: string[] }) => { setDirtyDetails(details); @@ -1817,20 +1812,6 @@ function AgentConfigurePage({ hideInstructionsFile visibleSections={visibleSections} /> - {visibleSections.has("keys") ? ( - -

Long-lived keys for external processes acting as this agent. Runs receive short-lived tokens automatically.

- -
- ) : null} - {visibleSections.has("danger") ? ( - -
- Adapter-specific sandbox bypass, permission skipping, and deprecated values remain draftable in the runtime form. They are grouped here for navigation while the field internals stay unchanged in P1. -
-
- ) : null} - {/* Configuration Revisions — collapsible at the bottom */} {visibleSections.has("history") ?