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
66 changes: 57 additions & 9 deletions desktop/src/features/agents/ui/CreateAgentDialogSections.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ export function CreateAgentBasicsFields({
Agent name
</label>
<Input
aria-describedby="help-agent-name"
autoCapitalize="none"
autoCorrect="off"
data-testid="agent-name-input"
Expand All @@ -31,7 +32,7 @@ export function CreateAgentBasicsFields({
spellCheck={false}
value={name}
/>
<p className="text-xs text-muted-foreground">
<p className="text-xs text-muted-foreground" id="help-agent-name">
Used as the local label and synced to the agent profile display name
when the relay accepts the create-time auth.
</p>
Expand Down Expand Up @@ -139,22 +140,38 @@ export function CreateAgentRuntimeFields({
Relay URL
</label>
<Input
aria-describedby="help-agent-relay-url"
id="agent-relay-url"
onChange={(event) => onRelayUrlChange(event.target.value)}
placeholder="Leave blank to use the desktop relay"
value={relayUrl}
/>
<p
className="text-xs text-muted-foreground"
id="help-agent-relay-url"
>
WebSocket URL of the relay this agent connects to. Leave blank to
use the built-in desktop relay.
</p>
</div>

<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="agent-acp-command">
ACP command
</label>
<Input
aria-describedby="help-agent-acp-command"
id="agent-acp-command"
onChange={(event) => onAcpCommandChange(event.target.value)}
value={acpCommand}
/>
<p
className="text-xs text-muted-foreground"
id="help-agent-acp-command"
>
The sprout-acp binary path or alias used to launch the ACP harness
process.
</p>
</div>
</div>

Expand All @@ -167,10 +184,18 @@ export function CreateAgentRuntimeFields({
Custom agent runtime command
</label>
<Input
aria-describedby="help-agent-runtime-command"
id="agent-runtime-command"
onChange={(event) => onAgentCommandChange(event.target.value)}
value={agentCommand}
/>
<p
className="text-xs text-muted-foreground"
id="help-agent-runtime-command"
>
Full path or shell command for the agent binary when no known ACP
runtime was detected.
</p>
</div>
) : null}

Expand All @@ -180,13 +205,17 @@ export function CreateAgentRuntimeFields({
Agent runtime args
</label>
<Input
aria-describedby="help-agent-runtime-args"
id="agent-runtime-args"
onChange={(event) => onAgentArgsChange(event.target.value)}
placeholder="Comma-separated"
value={agentArgs}
/>
<p className="text-xs text-muted-foreground">
`sprout-acp` splits args on commas, matching the testing guide.
<p
className="text-xs text-muted-foreground"
id="help-agent-runtime-args"
>
sprout-acp splits args on commas, matching the testing guide.
</p>
</div>

Expand All @@ -195,29 +224,42 @@ export function CreateAgentRuntimeFields({
MCP command
</label>
<Input
aria-describedby="help-agent-mcp-command"
id="agent-mcp-command"
onChange={(event) => onMcpCommandChange(event.target.value)}
value={mcpCommand}
/>
<p
className="text-xs text-muted-foreground"
id="help-agent-mcp-command"
>
Command the ACP harness uses to start the MCP tool server for this
agent.
</p>
</div>

<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="agent-timeout">
Turn timeout
</label>
<Input
aria-describedby="help-agent-timeout"
id="agent-timeout"
onChange={(event) => onTurnTimeoutChange(event.target.value)}
placeholder="300"
value={turnTimeoutSeconds}
/>
<p className="text-xs text-muted-foreground" id="help-agent-timeout">
Seconds before an agent turn is cancelled. Defaults to 300.
</p>
</div>

<div className="space-y-1.5">
<label className="text-sm font-medium" htmlFor="agent-parallelism">
Parallelism
</label>
<Input
aria-describedby="help-agent-parallelism"
data-testid="agent-parallelism-input"
id="agent-parallelism"
inputMode="numeric"
Expand All @@ -229,8 +271,11 @@ export function CreateAgentRuntimeFields({
type="number"
value={parallelism}
/>
<p className="text-xs text-muted-foreground">
Number of ACP worker subprocesses. `sprout-acp` allows 1-32.
<p
className="text-xs text-muted-foreground"
id="help-agent-parallelism"
>
Number of ACP worker subprocesses. sprout-acp allows 1-32.
</p>
</div>
</div>
Expand All @@ -240,15 +285,18 @@ export function CreateAgentRuntimeFields({
System prompt override
</label>
<Textarea
aria-describedby="help-agent-system-prompt"
data-testid="agent-system-prompt-input"
id="agent-system-prompt"
onChange={(event) => onSystemPromptChange(event.target.value)}
placeholder="Leave blank to send no ACP system prompt"
value={systemPrompt}
/>
<p className="text-xs text-muted-foreground">
Blank means no override. `sprout-acp` will not add a `[System]`
prompt.
<p
className="text-xs text-muted-foreground"
id="help-agent-system-prompt"
>
Blank means no override. sprout-acp will not add a [System] prompt.
</p>
</div>
</>
Expand Down Expand Up @@ -302,7 +350,7 @@ export function CreateAgentOptionToggles({
<p className="mt-1 text-sm text-foreground/70">
{prereqs !== null && !isMintSupported
? `Unavailable until ${prereqs.admin.command} is installed.`
: "Use `sprout-admin` to create a bearer token for this agent."}
: "Use sprout-admin to create a bearer token for this agent."}
</p>
</button>

Expand Down
82 changes: 70 additions & 12 deletions desktop/src/features/agents/ui/ManagedAgentRow.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -321,14 +321,26 @@ function AgentActionsMenu({
onClick={() => onStart(agent.pubkey)}
>
<Play className="h-4 w-4" />
{isActive ? "Redeploy" : "Deploy"}
<div className="flex flex-col">
<span>{isActive ? "Redeploy" : "Deploy"}</span>
<span className="text-xs font-normal text-muted-foreground">
{isActive
? "Push a new deployment to the provider"
: "Deploy this agent to the provider"}
</span>
</div>
</DropdownMenuItem>
<DropdownMenuItem
disabled={isActionPending}
onClick={() => onStop(agent.pubkey)}
>
<Square className="h-4 w-4" />
Shutdown
<div className="flex flex-col">
<span>Shutdown</span>
<span className="text-xs font-normal text-muted-foreground">
Stop the provider deployment and free its resources
</span>
</div>
</DropdownMenuItem>
</>
) : isActive ? (
Expand All @@ -337,15 +349,25 @@ function AgentActionsMenu({
onClick={() => onStop(agent.pubkey)}
>
<Square className="h-4 w-4" />
Stop
<div className="flex flex-col">
<span>Stop</span>
<span className="text-xs font-normal text-muted-foreground">
Stop the running ACP harness process
</span>
</div>
</DropdownMenuItem>
) : (
<DropdownMenuItem
disabled={isActionPending}
onClick={() => onStart(agent.pubkey)}
>
<Play className="h-4 w-4" />
Spawn
<div className="flex flex-col">
<span>Spawn</span>
<span className="text-xs font-normal text-muted-foreground">
Launch the local ACP harness process for this agent
</span>
</div>
</DropdownMenuItem>
)}

Expand All @@ -354,28 +376,50 @@ function AgentActionsMenu({
onClick={() => onAddToChannel(agent)}
>
<UserPlus className="h-4 w-4" />
Add to channel
<div className="flex flex-col">
<span>Add to channel</span>
<span className="text-xs font-normal text-muted-foreground">
Invite this agent to a channel so it can participate in
conversations
</span>
</div>
</DropdownMenuItem>

<DropdownMenuItem
disabled={isActionPending}
onClick={() => onMintToken(agent.pubkey, agent.name)}
>
<KeyRound className="h-4 w-4" />
Mint token
<div className="flex flex-col">
<span>Mint token</span>
<span className="text-xs font-normal text-muted-foreground">
Generate a bearer token this agent uses to authenticate with the
relay
</span>
</div>
</DropdownMenuItem>

<DropdownMenuItem
onClick={() => navigator.clipboard.writeText(agent.pubkey)}
>
<Clipboard className="h-4 w-4" />
Copy pubkey
<div className="flex flex-col">
<span>Copy pubkey</span>
<span className="text-xs font-normal text-muted-foreground">
Copy the agent&apos;s public key to the clipboard
</span>
</div>
</DropdownMenuItem>

{agent.backend.type === "local" ? (
<DropdownMenuItem onClick={() => onOpenLogs(agent.pubkey)}>
<FileText className="h-4 w-4" />
View logs
<div className="flex flex-col">
<span>View logs</span>
<span className="text-xs font-normal text-muted-foreground">
Show the ACP harness stdout/stderr log inline
</span>
</div>
</DropdownMenuItem>
) : null}

Expand All @@ -387,9 +431,18 @@ function AgentActionsMenu({
}
>
<Power className="h-4 w-4" />
{agent.startOnAppLaunch
? "Disable auto-start"
: "Enable auto-start"}
<div className="flex flex-col">
<span>
{agent.startOnAppLaunch
? "Disable auto-start"
: "Enable auto-start"}
</span>
<span className="text-xs font-normal text-muted-foreground">
{agent.startOnAppLaunch
? "Stop launching this agent automatically when the desktop app starts"
: "Launch this agent automatically every time the desktop app starts"}
</span>
</div>
</DropdownMenuItem>
) : null}

Expand All @@ -401,7 +454,12 @@ function AgentActionsMenu({
onClick={() => onDelete(agent.pubkey)}
>
<Trash2 className="h-4 w-4" />
Delete
<div className="flex flex-col">
<span>Delete</span>
<span className="text-xs font-normal text-muted-foreground">
Permanently remove this agent profile from the desktop app
</span>
</div>
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
Expand Down
Loading
Loading