Skip to content

Commit 08e0a03

Browse files
author
npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5
committed
fix(desktop): pin harness when Custom command selected in EditAgentDialog
Selecting Custom command for an inheriting persona-linked agent left inheritHarness=true because that branch had no catalog runtime, so Save silently followed the inherit path and discarded the custom command. Clear inheritance for any explicit runtime selection so the command input becomes editable and the pin path persists the choice. Signed-off-by: npub13fn4ahfnvaa2qwylvegdgeajqs0mph6v4qsw4jcqnw4mjh3hzh2quuucm5 <8a675edd33677aa0389f6650d467b2041fb0df4ca820eacb009babb95e3715d4@sprout-oss.stage.blox.sqprod.co>
1 parent aded896 commit 08e0a03

2 files changed

Lines changed: 67 additions & 6 deletions

File tree

desktop/src/features/agents/ui/EditAgentDialog.tsx

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -260,19 +260,23 @@ export function EditAgentDialog({
260260
// effect will no longer overwrite selectedRuntimeId after this point.
261261
runtimeTouched.current = true;
262262

263-
setSelectedRuntimeId(nextRuntimeId || "custom");
263+
const resolvedRuntimeId = nextRuntimeId || "custom";
264+
setSelectedRuntimeId(resolvedRuntimeId);
265+
266+
// Any explicit runtime selection pins the harness — this is the
267+
// authoritative override. Disabling inheritance ensures the choice is
268+
// actually persisted (Save follows the pin path, not the inherit path) and
269+
// that the Advanced command input becomes editable for the custom case.
270+
// "Custom command" has no catalog entry, so it must clear inheritance here
271+
// rather than relying on the concrete-runtime branch below.
272+
setInheritHarness(false);
264273

265274
// When switching to a catalog-known runtime, update the agent command to
266275
// its resolved command so the command field stays consistent.
267276
if (nextRuntime?.command) {
268277
setAgentCommand(nextRuntime.command);
269278
const newArgs = nextRuntime.defaultArgs.join(",");
270279
setAgentArgs(newArgs);
271-
// Selecting a concrete catalog runtime pins the harness — this is the
272-
// authoritative override. Disabling inheritance ensures the runtime is
273-
// actually persisted and prevents a mismatched provider from being saved
274-
// against an inherited runtime that will actually run something else.
275-
setInheritHarness(false);
276280
}
277281

278282
// Clear model when switching away from a runtime with a different model scope.

desktop/src/features/agents/ui/editAgentProviderDiscovery.test.mjs

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,6 +335,63 @@ test("editAgent_runtimeDropdown_pinsHarnessWhenConcreteCatalogRuntimeSelected",
335335
);
336336
});
337337

338+
// ── Custom command as a runtime pin ──────────────────────────────────────────
339+
//
340+
// "Custom command" has no catalog entry (nextRuntime === undefined), so it must
341+
// clear inheritance directly in the handler rather than relying on the
342+
// concrete-runtime branch. Without this, an inheriting persona-linked agent that
343+
// picks "Custom command" keeps inheritHarness=true, the command input stays
344+
// gated behind !inheritHarness, and Save silently follows the inherit path —
345+
// discarding the custom-command intent.
346+
347+
test("editAgent_runtimeDropdown_pinsHarnessWhenCustomCommandSelected", () => {
348+
// Simulate handleRuntimeDropdownChange("custom") for an inherited agent.
349+
let inheritHarness = true; // starts inherited
350+
351+
const NO_RUNTIME_DROPDOWN_VALUE = "__none__";
352+
const nextValue = "custom";
353+
const nextRuntimeId =
354+
nextValue === NO_RUNTIME_DROPDOWN_VALUE ? "" : nextValue;
355+
const nextRuntime = undefined; // "custom" has no catalog entry
356+
357+
// The fixed handler clears inheritance for ANY explicit selection, before the
358+
// concrete-runtime branch (which never runs for a custom command).
359+
inheritHarness = false;
360+
if (nextRuntime?.command) {
361+
// concrete-runtime branch — not taken for custom command
362+
}
363+
364+
assert.equal(nextRuntimeId, "custom");
365+
assert.equal(
366+
inheritHarness,
367+
false,
368+
"selecting 'Custom command' must set inheritHarness=false so the command input is editable and Save takes the pin path",
369+
);
370+
});
371+
372+
test("editAgent_customCommandSelected_savePinsCustomCommandNotInherit", () => {
373+
// After the custom-command selection clears inheritance, the submit path must
374+
// pin the (edited) custom command rather than following the inherit sentinel.
375+
const inheritHarness = false; // cleared by the custom-command selection
376+
const agentOriginalCommand = ""; // was inheriting, no command
377+
const agentCommandOverride = null;
378+
const editedCustomCommand = "/opt/bin/my-custom-agent";
379+
380+
const agentCommandUpdate = inheritHarness
381+
? agentCommandOverride != null
382+
? ""
383+
: undefined
384+
: editedCustomCommand.trim() !== agentOriginalCommand
385+
? editedCustomCommand.trim()
386+
: undefined;
387+
388+
assert.equal(
389+
agentCommandUpdate,
390+
"/opt/bin/my-custom-agent",
391+
"custom command must be persisted as a pin, not silently dropped by the inherit path",
392+
);
393+
});
394+
338395
test("editAgent_inheritedAgentRuntimeSwitch_producesConsistentCommandProviderPair", () => {
339396
// Bad path before fix: inheritHarness stays true, so agentCommandUpdate is
340397
// undefined (agent still inherits Claude), but provider="databricks_v2" persists.

0 commit comments

Comments
 (0)