authorgravatar for 97427849+flamboh@users.noreply.github.comoliver <97427849+flamboh@users.noreply.github.com> 2026-10-14 10:49:18-07:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2026-10-14 17:49:18+00:00
loge093789dd2340d8a41ee7ac12341fb011f9ff86c
tree220c3cd93841f2e49f594a1645c6189261c1ceda
parent7897a695e351b7e8ebaa0d8c693660291af18286
signature Signed by PGP key B5690EEEBB952194

fix(web): subagent lists in the composer banner no longer start lines with a comma (#19170)


3 files changed, 41 insertions(+), 26 deletions(-)

apps/mobile/src/features/threads/thread-handoff-row.tsx+8-5
...@@ -9,7 +9,7 @@ import type {...@@ -9,7 +9,7 @@ import type {
9 ServerProvider,9 ServerProvider,
10} from "@t3tools/contracts";10} from "@t3tools/contracts";
11import { Atom } from "effect/reactivity";11import { Atom } from "effect/reactivity";
12import { Fragment, useMemo } from "react";12import { useMemo } from "react";
13import { Alert, Pressable, View, type ColorValue } from "react-native";13import { Alert, Pressable, View, type ColorValue } from "react-native";
14import { AppText as Text } from "../../components/AppText";14import { AppText as Text } from "../../components/AppText";
15import { SymbolView } from "../../components/AppSymbol";15import { SymbolView } from "../../components/AppSymbol";
...@@ -76,14 +76,17 @@ export function ThreadHandoffDivider(props: {...@@ -76,14 +76,17 @@ export function ThreadHandoffDivider(props: {
76 >76 >
77 <View className="flex-row flex-wrap items-center justify-center gap-1.5">77 <View className="flex-row flex-wrap items-center justify-center gap-1.5">
78 {endpoints.from.map((endpoint, index) => (78 {endpoints.from.map((endpoint, index) => (
79 <Fragment key={`${endpoint.instanceId}:${endpoint.model ?? ""}`}>79 <View
80 {index > 0 ? (80 key={`${endpoint.instanceId}:${endpoint.model ?? ""}`}
81 className="max-w-full flex-row items-center"
82 >
83 <HandoffEndpoint {...endpoint} providers={config?.providers ?? []} />
84 {index < endpoints.from.length - 1 ? (
81 <Text accessible={false} className="text-xs text-foreground-muted">85 <Text accessible={false} className="text-xs text-foreground-muted">
82 ,86 ,
83 </Text>87 </Text>
84 ) : null}88 ) : null}
85 <HandoffEndpoint {...endpoint} providers={config?.providers ?? []} />89 </View>
86 </Fragment>
87 ))}90 ))}
88 {endpoints.from.length > 0 ? (91 {endpoints.from.length > 0 ? (
89 <SymbolView name="arrow.right" size={12} tintColor={props.iconColor} />92 <SymbolView name="arrow.right" size={12} tintColor={props.iconColor} />
apps/web/src/components/ChatView.tsx+23-13
...@@ -7472,10 +7472,13 @@ export default function ChatView(props: ChatViewProps) {...@@ -7472,10 +7472,13 @@ export default function ChatView(props: ChatViewProps) {
7472 : `${childThreadInputs.length} subagents need input`,7472 : `${childThreadInputs.length} subagents need input`,
7473 description: childThreadInputs.map((child, index) => (7473 description: childThreadInputs.map((child, index) => (
7474 <Fragment key={child.id}>7474 <Fragment key={child.id}>
7475 {index > 0 ? ", " : null}7475 {index > 0 ? " " : null}
7476 <InlineButton tone="muted" onClick={() => onOpenRelatedThread(child.id)}>7476 <span className="whitespace-nowrap">
7477 {child.title}7477 <InlineButton tone="muted" onClick={() => onOpenRelatedThread(child.id)}>
7478 </InlineButton>7478 {child.title}
7479 </InlineButton>
7480 {index < childThreadInputs.length - 1 ? "," : null}
7481 </span>
7479 </Fragment>7482 </Fragment>
7480 )),7483 )),
7481 actions: (7484 actions: (
...@@ -7643,19 +7646,26 @@ export default function ChatView(props: ChatViewProps) {...@@ -7643,19 +7646,26 @@ export default function ChatView(props: ChatViewProps) {
7643 ? undefined7646 ? undefined
7644 : presentation.items.map((item, index) => {7647 : presentation.items.map((item, index) => {
7645 const childThreadId = item.childThreadId;7648 const childThreadId = item.childThreadId;
7649 const separator = index < presentation.items.length - 1 ? "," : null;
7646 return (7650 return (
7647 <Fragment key={item.taskId}>7651 <Fragment key={item.taskId}>
7648 {index > 0 ? ", " : null}7652 {index > 0 ? " " : null}
7649 {childThreadId === undefined ? (7653 {childThreadId === undefined ? (
7650 item.label7654 <>
7651 ) : (
7652 <InlineButton
7653 tone="muted"
7654 aria-label={`Open subagent ${item.label}`}
7655 onClick={() => onOpenRelatedThread(childThreadId)}
7656 >
7657 {item.label}7655 {item.label}
7658 </InlineButton>7656 {separator}
7657 </>
7658 ) : (
7659 <span className="whitespace-nowrap">
7660 <InlineButton
7661 tone="muted"
7662 aria-label={`Open subagent ${item.label}`}
7663 onClick={() => onOpenRelatedThread(childThreadId)}
7664 >
7665 {item.label}
7666 </InlineButton>
7667 {separator}
7668 </span>
7659 )}7669 )}
7660 </Fragment>7670 </Fragment>
7661 );7671 );
apps/web/src/components/chat/V2LifecycleRow.tsx+10-8
...@@ -15,7 +15,6 @@ import {...@@ -15,7 +15,6 @@ import {
15 type HandoffEndpoints,15 type HandoffEndpoints,
16 type HandoffTimelineRun,16 type HandoffTimelineRun,
17} from "@t3tools/client-runtime/handoff";17} from "@t3tools/client-runtime/handoff";
18import { Fragment } from "react";
19import { formatSubagentDisplayTitle } from "@t3tools/client-runtime/state/subagent-display";18import { formatSubagentDisplayTitle } from "@t3tools/client-runtime/state/subagent-display";
20import {19import {
21 ProviderDriverKind,20 ProviderDriverKind,
...@@ -562,18 +561,21 @@ export function HandoffRow(props: {...@@ -562,18 +561,21 @@ export function HandoffRow(props: {
562 detail={561 detail={
563 <span className="inline-flex min-w-0 flex-wrap items-center justify-center gap-1.5">562 <span className="inline-flex min-w-0 flex-wrap items-center justify-center gap-1.5">
564 {fromEndpoints.map((endpoint, index) => (563 {fromEndpoints.map((endpoint, index) => (
565 <Fragment key={`${endpoint.instanceId}:${endpoint.model ?? ""}`}>564 <span
566 {index > 0 ? (565 key={`${endpoint.instanceId}:${endpoint.model ?? ""}`}
567 <span aria-hidden="true" className="-ml-1">566 className="inline-flex min-w-0 items-center"
568 ,567 >
569 </span>
570 ) : null}
571 <HandoffEndpoint568 <HandoffEndpoint
572 providers={props.providers}569 providers={props.providers}
573 instanceId={endpoint.instanceId}570 instanceId={endpoint.instanceId}
574 model={endpoint.model}571 model={endpoint.model}
575 />572 />
576 </Fragment>573 {index < fromEndpoints.length - 1 ? (
574 <span aria-hidden="true" className="ml-0.5">
575 ,
576 </span>
577 ) : null}
578 </span>
577 ))}579 ))}
578 {fromEndpoints.length > 0 ? (580 {fromEndpoints.length > 0 ? (
579 <ArrowRightIcon aria-hidden="true" className="size-3 shrink-0" />581 <ArrowRightIcon aria-hidden="true" className="size-3 shrink-0" />