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
51 changes: 47 additions & 4 deletions crates/agent-gateway/web/src/lib/chat/uiMessages.ts
Original file line number Diff line number Diff line change
Expand Up @@ -143,9 +143,10 @@ function summarizeBashTimeout(value: unknown) {

export function summarizeToolCall(
toolCall: ToolCall,
options?: { includeName?: boolean },
options?: { includeName?: boolean; includeManagerAction?: boolean },
) {
const includeName = options?.includeName ?? true;
const includeManagerAction = options?.includeManagerAction ?? true;
const args = toolCall.arguments || {};
const name = toolCall.name;
const path = summarizeToolArg(args.path);
Expand Down Expand Up @@ -207,30 +208,72 @@ export function summarizeToolCall(
]
: name === "SkillsManager"
? [
typeof args.action === "string" ? `action=${args.action}` : null,
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
path ? `path=${path}` : null,
typeof args.offset === "number" ? `start=${args.offset + 1}` : null,
typeof args.length === "number" ? `limit=${args.length}` : null,
typeof args.source === "string" ? `source=${summarizeToolArg(args.source)}` : null,
typeof args.name === "string" ? `name=${summarizeToolArg(args.name)}` : null,
typeof args.conflict === "string" ? `conflict=${summarizeToolArg(args.conflict)}` : null,
]
: name === "CronTaskManager"
? [
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
typeof args.task_id === "string" ? `task=${summarizeToolArg(args.task_id)}` : null,
typeof args.name === "string" ? `name=${summarizeToolArg(args.name)}` : null,
typeof args.type === "string" ? `type=${summarizeToolArg(args.type)}` : null,
]
: name === "MemoryManager"
? [
typeof args.action === "string" ? `action=${args.action}` : null,
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
typeof args.slug === "string" ? `slug=${summarizeToolArg(args.slug)}` : null,
typeof args.scope === "string" ? `scope=${summarizeToolArg(args.scope)}` : null,
typeof args.type === "string" ? `type=${summarizeToolArg(args.type)}` : null,
typeof args.query === "string" ? `query=${summarizeToolArg(args.query)}` : null,
]
: name === "McpManager"
? [
typeof args.action === "string" ? `action=${args.action}` : null,
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
typeof args.server_id === "string" ? `server=${summarizeToolArg(args.server_id)}` : null,
Array.isArray(args.server_ids) ? `servers=${args.server_ids.length}` : null,
typeof args.conflict === "string" ? `conflict=${summarizeToolArg(args.conflict)}` : null,
args.include_schema === true ? "includeSchema=true" : null,
]
: name === "TunnelManager"
? [
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
typeof args.targetUrl === "string"
? `target=${summarizeToolArg(args.targetUrl)}`
: null,
typeof args.slug === "string" ? `slug=${summarizeToolArg(args.slug)}` : null,
typeof args.id === "string" ? `id=${summarizeToolArg(args.id)}` : null,
]
: name === "SSHManager" || name === "SshManager"
? [
includeManagerAction && typeof args.action === "string"
? `action=${args.action}`
: null,
typeof args.host_id === "string"
? `host=${summarizeToolArg(args.host_id)}`
: null,
typeof args.session_id === "string"
? `session=${summarizeToolArg(args.session_id)}`
: null,
typeof args.path === "string" ? `path=${path}` : null,
typeof args.command === "string"
? `command=${summarizeToolArg(args.command)}`
: null,
]
: name === "Agent"
? [
typeof args.agent_id === "string" ? `agent=${summarizeToolArg(args.agent_id)}` : null,
Expand Down
54 changes: 52 additions & 2 deletions crates/agent-gateway/web/src/pages/chat/AssistantBubble.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import type { ImageContent, ToolResultMessage, Usage } from "../../lib/agentType
import {
Bot,
Brain,
Clock3,
ChevronRight,
Eye,
ImageIcon,
Expand All @@ -11,6 +12,7 @@ import {
FilePenLine,
FolderTree,
Loader2,
Link2,
Plug,
Search,
Server,
Expand Down Expand Up @@ -488,8 +490,10 @@ function getToolMeta(name: string): { Icon: IconComponent; accent: string; categ
case "Read": return { Icon: Eye, accent: "var(--tool-file-accent)", category: "file" };
case "Image": return { Icon: ImageIcon, accent: "var(--tool-file-accent)", category: "file" };
case "SkillsManager": return { Icon: Eye, accent: "var(--tool-file-accent)", category: "file" };
case "CronTaskManager": return { Icon: Clock3, accent: "var(--tool-list-accent)", category: "system" };
case "MemoryManager": return { Icon: Brain, accent: "var(--tool-list-accent)", category: "system" };
case "McpManager": return { Icon: Plug, accent: "var(--tool-list-accent)", category: "mcp" };
case "TunnelManager": return { Icon: Link2, accent: "var(--tool-list-accent)", category: "system" };
case "SSHManager":
case "SshManager": return { Icon: Server, accent: "var(--tool-bash-accent)", category: "terminal" };
case "Agent": return { Icon: Bot, accent: "var(--tool-list-accent)", category: "system" };
Expand Down Expand Up @@ -667,6 +671,39 @@ function getToolDisplayName(name: string) {
return name;
}

const TOOL_CARD_ACTION_NAMES = new Set([
"SkillsManager",
"CronTaskManager",
"McpManager",
"MemoryManager",
"TunnelManager",
"SSHManager",
]);

function getManagerToolActionName(toolCall: {
name: string;
arguments?: Record<string, unknown>;
}) {
const name = getToolDisplayName(toolCall.name);
if (!TOOL_CARD_ACTION_NAMES.has(name)) return "";
const args = toolCall.arguments || {};
const action = displayString(args.action);
if (action) return action;
if (name === "SkillsManager") {
return displayString(args.path) ? "read" : "list";
}
return "";
}

function getToolDisplayTitle(toolCall: {
name: string;
arguments?: Record<string, unknown>;
}) {
const name = getToolDisplayName(toolCall.name);
const action = getManagerToolActionName(toolCall);
return { name, action };
}

function groupRoundBlocks(blocks: UiRound["blocks"]): GroupedRoundBlock[] {
const groupedBlocks: GroupedRoundBlock[] = [];
let pendingTools: ToolTraceItem[] = [];
Expand Down Expand Up @@ -2355,6 +2392,7 @@ function isBuiltinShareToolName(name: string) {
"SkillsManager",
"SSHManager",
"SshManager",
"TunnelManager",
"Write",
].includes(trimmed);
}
Expand Down Expand Up @@ -2393,9 +2431,15 @@ function ToolCallItem({
? ""
: isDelegateAgentCard
? getDelegateAgentInlineSummary(item)
: summarizeToolCall(item.toolCall, { includeName: false });
: summarizeToolCall(item.toolCall, {
includeName: false,
includeManagerAction: false,
});
const meta = getToolMeta(item.toolCall.name);
const ToolIcon = meta.Icon;
const title = isRedactedToolContent
? { name: getToolDisplayName(item.toolCall.name), action: "" }
: getToolDisplayTitle(item.toolCall);

const dotClass = isRunning
? "bg-[hsl(var(--chat-running))] animate-pulse"
Expand Down Expand Up @@ -2449,7 +2493,13 @@ function ToolCallItem({

<div className="flex min-w-0 flex-1 items-center gap-1.5">
<span className="shrink-0 text-[12.5px] font-semibold tracking-[-0.01em] text-foreground/90">
{getToolDisplayName(item.toolCall.name)}
{title.name}
{title.action ? (
<span className="font-mono font-semibold text-muted-foreground/70">
{" · "}
{title.action}
</span>
) : null}
</span>

{isBash && firstLine ? (
Expand Down
Loading
Loading