fix: clean up orchestrator chat UX

- Tool call names now show human-readable labels ("Dispatched agent"
  instead of "spawn_agent"), deduped if called multiple times
- Model label only shown when a real value is returned; "unknown"
  and null are suppressed; model names shortened (GLM-5, Gemini)

Made-with: Cursor
This commit is contained in:
2026-02-27 18:15:50 -08:00
parent fe89087cc5
commit b2b3424b05
2 changed files with 33 additions and 7 deletions

View File

@@ -74,7 +74,7 @@ export async function POST(
reasoning: data.reasoning ?? null, reasoning: data.reasoning ?? null,
toolCalls: data.toolCalls ?? [], toolCalls: data.toolCalls ?? [],
turns: data.turns ?? 0, turns: data.turns ?? 0,
model: data.model ?? "unknown", model: data.model || null,
sessionId, sessionId,
}); });
} catch (err) { } catch (err) {

View File

@@ -37,6 +37,29 @@ interface OrchestratorChatProps {
placeholder?: string; placeholder?: string;
} }
// ---------------------------------------------------------------------------
// Friendly labels for tool call names
// ---------------------------------------------------------------------------
const TOOL_LABELS: Record<string, string> = {
spawn_agent: "Dispatched agent",
get_job_status: "Checked job",
list_repos: "Listed repos",
list_all_issues: "Checked issues",
list_all_apps: "Checked deployments",
get_app_status: "Checked app status",
read_repo_file: "Read file",
deploy_app: "Triggered deploy",
gitea_create_issue: "Created issue",
gitea_list_issues: "Listed issues",
gitea_close_issue: "Closed issue",
gitea_comment_issue: "Added comment",
};
function friendlyToolName(raw: string): string {
return TOOL_LABELS[raw] ?? raw.replace(/_/g, " ");
}
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
// Suggestion chips shown before the first message // Suggestion chips shown before the first message
// --------------------------------------------------------------------------- // ---------------------------------------------------------------------------
@@ -88,13 +111,14 @@ function MessageBubble({ msg }: { msg: Message }) {
<div className="flex flex-wrap items-center gap-1.5 px-1"> <div className="flex flex-wrap items-center gap-1.5 px-1">
{msg.toolCalls && msg.toolCalls.length > 0 && ( {msg.toolCalls && msg.toolCalls.length > 0 && (
<div className="flex flex-wrap gap-1"> <div className="flex flex-wrap gap-1">
{msg.toolCalls.map((t, i) => ( {/* Deduplicate tool calls before rendering */}
{[...new Set(msg.toolCalls)].map((t, i) => (
<span <span
key={i} key={i}
className="inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-muted border border-border text-muted-foreground font-mono" className="inline-flex items-center gap-1 text-[10px] px-1.5 py-0.5 rounded bg-muted border border-border text-muted-foreground"
> >
<Wrench className="h-2.5 w-2.5" /> <Wrench className="h-2.5 w-2.5 shrink-0" />
{t} {friendlyToolName(t)}
</span> </span>
))} ))}
</div> </div>
@@ -109,8 +133,10 @@ function MessageBubble({ msg }: { msg: Message }) {
{showReasoning ? <ChevronUp className="h-2.5 w-2.5" /> : <ChevronDown className="h-2.5 w-2.5" />} {showReasoning ? <ChevronUp className="h-2.5 w-2.5" /> : <ChevronDown className="h-2.5 w-2.5" />}
</button> </button>
)} )}
{msg.model && ( {msg.model && msg.model !== "unknown" && (
<span className="text-[10px] text-muted-foreground/60 ml-auto">{msg.model}</span> <span className="text-[10px] text-muted-foreground/60 ml-auto">
{msg.model.includes("glm") ? "GLM-5" : msg.model.includes("gemini") ? "Gemini" : msg.model}
</span>
)} )}
</div> </div>
)} )}