diff --git a/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx b/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx index 2b0c32a775..c1f08c7df6 100644 --- a/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx +++ b/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx @@ -45,6 +45,7 @@ import { connectionFromConfig, harnessAllowsModel, harnessSupportsUserMcp, + isPiHarnessValue, modelIdFromConfig, modelLabel, providerForModel, @@ -172,7 +173,7 @@ export function useModelHarness({ // is harness-filtered: selecting a model sets BOTH the model id and its provider, fed by the // `/inspect` capability map below. const harnessValue = typeof harness.kind === "string" ? (harness.kind as string) : null - const isPiHarness = harnessValue === "pi_core" || harnessValue === "pi_agenta" + const isPiHarness = isPiHarnessValue(harnessValue) const llm = config.llm const modelId = useMemo(() => modelIdFromConfig(llm), [llm]) const connection = useMemo(() => connectionFromConfig(llm), [llm]) diff --git a/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts b/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts index 527e648a90..622e928747 100644 --- a/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts +++ b/web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/connectionUtils.ts @@ -163,6 +163,16 @@ function capsFor( return capabilities[harness] ?? null } +/** + * Whether a harness value is one of the Pi harnesses. An absent `harness.kind` (`null`/`undefined`) + * runs as `pi_core` at runtime (see `agents/dtos.py`'s `harness: str = "pi_core"` default), so it + * counts as Pi here too — otherwise the Pi permissions controls stay hidden for a run that is + * actually enforcing them (#5661). + */ +export function isPiHarnessValue(harness: string | null | undefined): boolean { + return harness == null || harness === "pi_core" || harness === "pi_agenta" +} + /** External MCP authoring is available only when the selected harness publishes it. */ export function harnessSupportsUserMcp( capabilities: HarnessCapabilitiesMap | null | undefined, diff --git a/web/packages/agenta-entity-ui/tests/unit/connectionUtils.test.ts b/web/packages/agenta-entity-ui/tests/unit/connectionUtils.test.ts index 4c6b727406..13ec55cf48 100644 --- a/web/packages/agenta-entity-ui/tests/unit/connectionUtils.test.ts +++ b/web/packages/agenta-entity-ui/tests/unit/connectionUtils.test.ts @@ -20,6 +20,7 @@ import { harnessAllowsProvider, harnessSupportsUserMcp, isDeploymentProviderKind, + isPiHarnessValue, modelIdFromConfig, modelSelectionMode, providerForModel, @@ -195,6 +196,14 @@ describe("connectionUtils: capability gating (inspect-fed)", () => { expect(modelSelectionMode(CAPABILITIES, "claude")).toBe("alias") }) + it("treats an absent harness.kind as pi_core, matching the runner default (#5661)", () => { + expect(isPiHarnessValue(undefined)).toBe(true) + expect(isPiHarnessValue(null)).toBe(true) + expect(isPiHarnessValue("pi_core")).toBe(true) + expect(isPiHarnessValue("pi_agenta")).toBe(true) + expect(isPiHarnessValue("claude")).toBe(false) + }) + it("is permissive when the map or harness is missing", () => { expect(allowedProviders(null, "pi_core")).toEqual(["*"]) expect(allowedProviders(CAPABILITIES, "future-harness")).toEqual(["*"])