Skip to content

Commit 026f1e5

Browse files
committed
Show provider icons for active sidebar threads
1 parent 9385314 commit 026f1e5

3 files changed

Lines changed: 81 additions & 10 deletions

File tree

apps/web/src/components/Sidebar.logic.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,36 @@ describe("resolveThreadStatusPill", () => {
441441
).toMatchObject({ label: "Working", pulse: true });
442442
});
443443

444+
it("exposes the codex provider when a codex thread is running", () => {
445+
expect(
446+
resolveThreadStatusPill({
447+
thread: {
448+
...baseThread,
449+
session: {
450+
...baseThread.session,
451+
provider: "codex",
452+
status: "running",
453+
},
454+
},
455+
}),
456+
).toMatchObject({ label: "Working", workingProvider: "codex", pulse: true });
457+
});
458+
459+
it("exposes the claude provider when a claude thread is running", () => {
460+
expect(
461+
resolveThreadStatusPill({
462+
thread: {
463+
...baseThread,
464+
session: {
465+
...baseThread.session,
466+
provider: "claudeAgent",
467+
status: "running",
468+
},
469+
},
470+
}),
471+
).toMatchObject({ label: "Working", workingProvider: "claudeAgent", pulse: true });
472+
});
473+
444474
it("shows plan ready when a settled plan turn has a proposed plan ready for follow-up", () => {
445475
expect(
446476
resolveThreadStatusPill({

apps/web/src/components/Sidebar.logic.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import * as React from "react";
22
import type { SidebarProjectSortOrder, SidebarThreadSortOrder } from "@t3tools/contracts/settings";
3+
import type { ProviderKind } from "@t3tools/contracts";
34
import type { SidebarThreadSummary, Thread } from "../types";
45
import { cn } from "../lib/utils";
56
import { isLatestTurnSettled } from "../session-logic";
@@ -31,6 +32,7 @@ export interface ThreadStatusPill {
3132
colorClass: string;
3233
dotClass: string;
3334
pulse: boolean;
35+
workingProvider?: ProviderKind;
3436
}
3537

3638
const THREAD_STATUS_PRIORITY: Record<ThreadStatusPill["label"], number> = {
@@ -337,6 +339,7 @@ export function resolveThreadStatusPill(input: {
337339
colorClass: "text-sky-600 dark:text-sky-300/80",
338340
dotClass: "bg-sky-500 dark:bg-sky-300/80",
339341
pulse: true,
342+
workingProvider: thread.session.provider,
340343
};
341344
}
342345

@@ -346,6 +349,7 @@ export function resolveThreadStatusPill(input: {
346349
colorClass: "text-sky-600 dark:text-sky-300/80",
347350
dotClass: "bg-sky-500 dark:bg-sky-300/80",
348351
pulse: true,
352+
workingProvider: thread.session.provider,
349353
};
350354
}
351355

apps/web/src/components/Sidebar.tsx

Lines changed: 47 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import {
1212
TriangleAlertIcon,
1313
} from "lucide-react";
1414
import { ProjectFavicon } from "./ProjectFavicon";
15+
import { ClaudeAI, OpenAI } from "./Icons";
1516
import { autoAnimate } from "@formkit/auto-animate";
1617
import React, { useCallback, useEffect, memo, useMemo, useRef, useState } from "react";
1718
import { useShallow } from "zustand/react/shallow";
@@ -233,24 +234,56 @@ interface PrStatusIndicator {
233234

234235
type ThreadPr = GitStatusResult["pr"];
235236

237+
function providerStatusIconClassName(provider: ThreadStatusPill["workingProvider"]): string {
238+
if (provider === "claudeAgent") {
239+
return "text-[#d97757]";
240+
}
241+
242+
if (provider === "codex") {
243+
return "text-foreground";
244+
}
245+
246+
return "";
247+
}
248+
236249
function ThreadStatusLabel({
237250
status,
238251
compact = false,
239252
}: {
240253
status: ThreadStatusPill;
241254
compact?: boolean;
242255
}) {
256+
const isCodex = status.workingProvider === "codex";
257+
const statusIcon =
258+
status.workingProvider === "claudeAgent" ? (
259+
<ClaudeAI
260+
className={`size-3 ${providerStatusIconClassName(status.workingProvider)} ${
261+
status.pulse ? "animate-pulse" : ""
262+
}`}
263+
/>
264+
) : isCodex ? (
265+
<OpenAI
266+
className={`size-3 ${providerStatusIconClassName(status.workingProvider)} ${
267+
status.pulse ? "animate-pulse" : ""
268+
}`}
269+
/>
270+
) : null;
271+
243272
if (compact) {
244273
return (
245274
<span
246275
title={status.label}
247276
className={`inline-flex size-3.5 shrink-0 items-center justify-center ${status.colorClass}`}
248277
>
249-
<span
250-
className={`size-[9px] rounded-full ${status.dotClass} ${
251-
status.pulse ? "animate-pulse" : ""
252-
}`}
253-
/>
278+
{statusIcon ? (
279+
statusIcon
280+
) : (
281+
<span
282+
className={`size-[9px] rounded-full ${status.dotClass} ${
283+
status.pulse ? "animate-pulse" : ""
284+
}`}
285+
/>
286+
)}
254287
<span className="sr-only">{status.label}</span>
255288
</span>
256289
);
@@ -261,11 +294,15 @@ function ThreadStatusLabel({
261294
title={status.label}
262295
className={`inline-flex items-center gap-1 text-[10px] ${status.colorClass}`}
263296
>
264-
<span
265-
className={`h-1.5 w-1.5 rounded-full ${status.dotClass} ${
266-
status.pulse ? "animate-pulse" : ""
267-
}`}
268-
/>
297+
{statusIcon ? (
298+
statusIcon
299+
) : (
300+
<span
301+
className={`h-1.5 w-1.5 rounded-full ${status.dotClass} ${
302+
status.pulse ? "animate-pulse" : ""
303+
}`}
304+
/>
305+
)}
269306
<span className="hidden md:inline">{status.label}</span>
270307
</span>
271308
);

0 commit comments

Comments
 (0)