Skip to content
Merged
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
6 changes: 5 additions & 1 deletion desktop/src/features/agents/ui/CreateAgentDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -820,14 +820,18 @@ export function CreateAgentDialog({
acpCommand={acpCommand}
agentArgs={agentArgs}
agentCommand={agentCommand}
envVars={envVars}
inheritedEnvVars={globalConfig.env_vars}
mcpCommand={mcpCommand}
mcpToolsets={mcpToolsets}
onParallelismChange={setParallelism}
modelTuningRuntimeId={selectedRuntimeId}
onAcpCommandChange={setAcpCommand}
onAgentArgsChange={setAgentArgs}
onAgentCommandChange={setAgentCommand}
onEnvVarsChange={setEnvVars}
onMcpCommandChange={setMcpCommand}
onMcpToolsetsChange={setMcpToolsets}
onParallelismChange={setParallelism}
onRelayUrlChange={setRelayUrl}
onSystemPromptChange={setSystemPrompt}
onTurnTimeoutChange={setTurnTimeoutSeconds}
Expand Down
213 changes: 213 additions & 0 deletions desktop/src/features/agents/ui/CreateAgentDialogSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,15 @@ import { cn } from "@/shared/lib/cn";
import { Input } from "@/shared/ui/input";
import { Textarea } from "@/shared/ui/textarea";
import { describeResolvedCommand } from "./agentUi";
import {
BUZZ_AGENT_MAX_CONTEXT_TOKENS,
BUZZ_AGENT_MAX_OUTPUT_TOKENS,
BUZZ_AGENT_MAX_ROUNDS,
BUZZ_AGENT_THINKING_EFFORT,
BUZZ_AGENT_THINKING_EFFORT_VALUES,
isBuzzAgentRuntime,
} from "./buzzAgentConfig";
import type { EnvVarsValue } from "./EnvVarsEditor";

export function CreateAgentBasicsFields({
name,
Expand Down Expand Up @@ -105,8 +114,11 @@ export function CreateAgentRuntimeFields({
acpCommand,
agentArgs,
agentCommand,
envVars,
inheritedEnvVars,
mcpCommand,
mcpToolsets,
modelTuningRuntimeId,
parallelism,
relayUrl,
selectedRuntimeId,
Expand All @@ -115,6 +127,7 @@ export function CreateAgentRuntimeFields({
onAcpCommandChange,
onAgentArgsChange,
onAgentCommandChange,
onEnvVarsChange,
onMcpCommandChange,
onMcpToolsetsChange,
onParallelismChange,
Expand All @@ -125,23 +138,54 @@ export function CreateAgentRuntimeFields({
acpCommand: string;
agentArgs: string;
agentCommand: string;
/** Current agent env vars map — used to read/write tier-1 knob overrides. */
envVars: EnvVarsValue;
/** Inherited baseline for tier-1 knobs (global → persona chain). Empty = no baseline. */
inheritedEnvVars: EnvVarsValue;
mcpCommand: string;
mcpToolsets: string;
/**
* The actual/prospective runtime id used to decide whether to show the
* buzz-agent model-tuning fields. Kept separate from `selectedRuntimeId`
* because Edit collapses `selectedRuntimeId` to the "inherit"/"custom"
* sentinel that drives the custom-command input — that sentinel must NOT
* be used to gate the model-tuning section.
*/
modelTuningRuntimeId: string;
parallelism: string;
relayUrl: string;
/**
* Drives the custom-command input only: "custom" shows it, anything else
* hides it. In Edit this carries the "inherit"/"custom" sentinel.
*/
selectedRuntimeId: string;
systemPrompt: string;
turnTimeoutSeconds: string;
onAcpCommandChange: (value: string) => void;
onAgentArgsChange: (value: string) => void;
onAgentCommandChange: (value: string) => void;
/** Called when a tier-1 field change writes/deletes a key in envVars. */
onEnvVarsChange: (updated: EnvVarsValue) => void;
onMcpCommandChange: (value: string) => void;
onMcpToolsetsChange: (value: string) => void;
onParallelismChange: (value: string) => void;
onRelayUrlChange: (value: string) => void;
onSystemPromptChange: (value: string) => void;
onTurnTimeoutChange: (value: string) => void;
}) {
const isBuzzAgent = isBuzzAgentRuntime(modelTuningRuntimeId);

/** Write or delete a single env var key. Empty string = inherit (delete). */
function handleEnvVarChange(key: string, value: string) {
const next = { ...envVars };
if (value === "") {
delete next[key];
} else {
next[key] = value;
}
onEnvVarsChange(next);
}

return (
<>
<div className="grid gap-4 md:grid-cols-2">
Expand Down Expand Up @@ -337,10 +381,179 @@ export function CreateAgentRuntimeFields({
Blank means no override. buzz-acp will not add a [System] prompt.
</p>
</div>

{/* Tier-1 buzz-agent model-tuning knobs — only shown for buzz-agent. */}
{isBuzzAgent ? (
<BuzzAgentModelTuningFields
envVars={envVars}
inheritedEnvVars={inheritedEnvVars}
onEnvVarChange={handleEnvVarChange}
/>
) : null}
</>
);
}

/**
* Dedicated editable fields for the four buzz-agent model-tuning knobs.
* Renders only when the selected runtime is buzz-agent.
*
* Empty field = inherit (key absent from envVars; placeholder shows baseline).
* Non-empty = explicit override written into envVars.
*/
function BuzzAgentModelTuningFields({
envVars,
inheritedEnvVars,
onEnvVarChange,
}: {
envVars: EnvVarsValue;
inheritedEnvVars: EnvVarsValue;
onEnvVarChange: (key: string, value: string) => void;
}) {
return (
<div className="space-y-4">
<p className="text-xs font-medium text-muted-foreground uppercase tracking-wide">
buzz-agent model tuning
</p>

<div className="grid gap-4 md:grid-cols-2">
{/* Thinking / Effort */}
<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="ba-thinking-effort">
Thinking / Effort
</label>
<select
className="flex h-9 w-full rounded-md border border-input bg-background px-3 py-2 text-sm shadow-xs"
data-testid="ba-thinking-effort-select"
id="ba-thinking-effort"
onChange={(event) =>
onEnvVarChange(BUZZ_AGENT_THINKING_EFFORT, event.target.value)
}
value={envVars[BUZZ_AGENT_THINKING_EFFORT] ?? ""}
>
<option value="">
{inheritedEnvVars[BUZZ_AGENT_THINKING_EFFORT]
? `Inherit (${inheritedEnvVars[BUZZ_AGENT_THINKING_EFFORT]})`
: "Inherit (agent default)"}
</option>
{BUZZ_AGENT_THINKING_EFFORT_VALUES.map((v) => (
<option key={v} value={v}>
{v}
</option>
))}
</select>
<p
className="text-xs text-muted-foreground"
id="help-ba-thinking-effort"
>
Controls how much reasoning effort the LLM applies per turn. Leave
blank to inherit from the global or persona default.
</p>
</div>

{/* Max Rounds */}
<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="ba-max-rounds">
Max rounds
</label>
<Input
aria-describedby="help-ba-max-rounds"
autoComplete="off"
data-testid="ba-max-rounds-input"
id="ba-max-rounds"
inputMode="numeric"
min="0"
onChange={(event) =>
onEnvVarChange(BUZZ_AGENT_MAX_ROUNDS, event.target.value)
}
placeholder={
inheritedEnvVars[BUZZ_AGENT_MAX_ROUNDS]
? `Inherit (${inheritedEnvVars[BUZZ_AGENT_MAX_ROUNDS]})`
: "Inherit (agent default)"
}
step="1"
type="number"
value={envVars[BUZZ_AGENT_MAX_ROUNDS] ?? ""}
/>
<p className="text-xs text-muted-foreground" id="help-ba-max-rounds">
Maximum LLM + tool-call rounds per turn. 0 = unlimited. Leave blank
to inherit.
</p>
</div>

{/* Max Output Tokens */}
<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="ba-max-output-tokens">
Max output tokens
</label>
<Input
aria-describedby="help-ba-max-output-tokens"
autoComplete="off"
data-testid="ba-max-output-tokens-input"
id="ba-max-output-tokens"
inputMode="numeric"
min="1"
onChange={(event) =>
onEnvVarChange(BUZZ_AGENT_MAX_OUTPUT_TOKENS, event.target.value)
}
placeholder={
inheritedEnvVars[BUZZ_AGENT_MAX_OUTPUT_TOKENS]
? `Inherit (${inheritedEnvVars[BUZZ_AGENT_MAX_OUTPUT_TOKENS]})`
: "Inherit (agent default)"
}
step="1"
type="number"
value={envVars[BUZZ_AGENT_MAX_OUTPUT_TOKENS] ?? ""}
/>
<p
className="text-xs text-muted-foreground"
id="help-ba-max-output-tokens"
>
Maximum tokens the LLM may generate per response. Leave blank to
inherit.
</p>
</div>

{/* Context Limit */}
<div className="space-y-1.5">
<label
className="text-sm font-medium"
htmlFor="ba-max-context-tokens"
>
Context limit
</label>
<Input
aria-describedby="help-ba-max-context-tokens"
autoComplete="off"
data-testid="ba-max-context-tokens-input"
id="ba-max-context-tokens"
inputMode="numeric"
min="1"
onChange={(event) =>
onEnvVarChange(BUZZ_AGENT_MAX_CONTEXT_TOKENS, event.target.value)
}
placeholder={
inheritedEnvVars[BUZZ_AGENT_MAX_CONTEXT_TOKENS]
? `Inherit (${inheritedEnvVars[BUZZ_AGENT_MAX_CONTEXT_TOKENS]})`
: "Inherit (agent default)"
}
step="1"
type="number"
value={envVars[BUZZ_AGENT_MAX_CONTEXT_TOKENS] ?? ""}
/>
<p
className="text-xs text-muted-foreground"
id="help-ba-max-context-tokens"
>
Maximum context window tokens buzz-agent tracks before a handoff.
Leave blank to inherit.
</p>
</div>
</div>
</div>
);
}

export function CreateAgentOptionToggles({
isSpawnSupported,
prereqs,
Expand Down
4 changes: 4 additions & 0 deletions desktop/src/features/agents/ui/EditAgentDialog.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -765,11 +765,15 @@ export function EditAgentDialog({
acpCommand={acpCommand}
agentArgs={agentArgs}
agentCommand={agentCommand}
envVars={envVars}
inheritedEnvVars={inheritedWithGlobal}
mcpCommand={mcpCommand}
mcpToolsets={mcpToolsets}
modelTuningRuntimeId={prospectiveRuntimeId}
onAcpCommandChange={setAcpCommand}
onAgentArgsChange={setAgentArgs}
onAgentCommandChange={setAgentCommand}
onEnvVarsChange={setEnvVars}
onMcpCommandChange={setMcpCommand}
onMcpToolsetsChange={setMcpToolsets}
onParallelismChange={setParallelism}
Expand Down
Loading
Loading