Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,12 @@ function isPermissionPolicy(value: unknown): value is PermissionPolicy {
return typeof value === "string" && PERMISSION_POLICY_VALUES.has(value)
}

export function resolveHarnessKindValue(harness: {kind?: string} | null | undefined): string {
// default to the pi_core harness when none is set
const kind = harness?.kind
return typeof kind === "string" ? kind : "pi_core"
Comment on lines +88 to +91

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🔴 Critical | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

tsconfig="$(fd -t f -i '^tsconfig.*\.json$' web/packages/agenta-entity-ui | head -n 1)"
test -n "$tsconfig"

pnpm --dir web exec tsc --noEmit --pretty false -p "${tsconfig#web/}"

Repository: Agenta-AI/agenta

Length of output: 4853


🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="web/packages/agenta-entity-ui/src/DrillInView/SchemaControls/agentTemplate/useModelHarness.tsx"
if [ ! -f "$file" ]; then
  echo "missing: $file"
  fd -i 'useModelHarness\.tsx$' web/packages/agenta-entity-ui || true
  exit 1
fi

echo "=== file location ==="
echo "$file"

echo "=== lines around resolver and call sites ==="
sed -n '70,105p;165,185p;365,385p;820,835p' "$file" | cat -n

echo "=== exact resolver line ==="
grep -n "export function resolveHarnessKindValue" "$file"

echo "=== asObject import/usages in file ==="
rg -n "asObject|resolveHarnessKindValue|type .*Record<string|Record<string" "$file"

echo "=== package tsconfig relevant content ==="
sed -n '1,80p' web/packages/agenta-entity-ui/tsconfig.json

Repository: Agenta-AI/agenta

Length of output: 7439


Align the resolver type with the actual configuration type.

harness comes from asObject("harness"), which returns Record<string, unknown>, while resolveHarnessKindValue is declared as {kind?: string} | null | undefined. This type mismatch makes the calls at Lines 180 and 377 fail type checking. Model the input as {kind?: unknown} | null | undefined, with no change to the runtime behavior.

Proposed fix
-export function resolveHarnessKindValue(harness: {kind?: string} | null | undefined): string {
+export function resolveHarnessKindValue(
+    harness: {kind?: unknown} | null | undefined,
+): string {
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
export function resolveHarnessKindValue(harness: {kind?: string} | null | undefined): string {
// default to the pi_core harness when none is set
const kind = harness?.kind
return typeof kind === "string" ? kind : "pi_core"
export function resolveHarnessKindValue(
harness: {kind?: unknown} | null | undefined,
): string {
// default to the pi_core harness when none is set
const kind = harness?.kind
return typeof kind === "string" ? kind : "pi_core"

}

export function useModelHarness({
schema,
config,
Expand Down Expand Up @@ -171,7 +177,7 @@ export function useModelHarness({
// carries through extra keys (e.g. `extras`) so a form edit never silently drops them. The picker
// 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 harnessValue = resolveHarnessKindValue(harness)
const isPiHarness = harnessValue === "pi_core" || harnessValue === "pi_agenta"
const llm = config.llm
const modelId = useMemo(() => modelIdFromConfig(llm), [llm])
Expand Down Expand Up @@ -368,7 +374,7 @@ export function useModelHarness({
// names the model the way the picker did.
const modelSummary =
[
enumLabel(harnessProps.kind, harness.kind),
enumLabel(harnessProps.kind, resolveHarnessKindValue(harness)),
modelLabel(capabilities, harnessValue, modelId) ?? enumLabel(props.llm, modelId),
]
.filter(Boolean)
Expand Down Expand Up @@ -822,7 +828,7 @@ export function useModelHarness({
<HarnessSelectControl
schema={harnessProps.kind}
visibleValues={harnessList}
value={(harness.kind as string | null) ?? null}
value={harnessValue}
onChange={(v) => setSection("harness", {...harness, kind: v})}
withTooltip={withTooltip}
disabled={disabled}
Expand Down
23 changes: 23 additions & 0 deletions web/packages/agenta-entity-ui/tests/unit/useModelHarness.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/**
* Unit tests for the resolveHarnessKindValue function used by the model harness UI.
*
* These tests lock in the fallback behavior for omitted or undefined harness values and confirm
* that explicit harness selections such as `pi_agenta` and `claude` are preserved unchanged.
* Runs under @agenta/entity-ui's own vitest runner.
*/
import {describe, expect, it} from "vitest"

import {resolveHarnessKindValue} from "../../src/DrillInView/SchemaControls/agentTemplate/useModelHarness"

describe("resolveHarnessKindValue", () => {
it("defaults an omitted harness kind to pi_core", () => {
expect(resolveHarnessKindValue({})).toBe("pi_core")
expect(resolveHarnessKindValue({kind: undefined})).toBe("pi_core")
})

it("preserves explicit harness kinds", () => {
expect(resolveHarnessKindValue({kind: "pi_agenta"})).toBe("pi_agenta")
expect(resolveHarnessKindValue({kind: "claude"})).toBe("claude")
expect(resolveHarnessKindValue({kind: "codex"})).toBe("codex")
})
})
Loading