| author | |
| committer | |
| log | e093789dd2340d8a41ee7ac12341fb011f9ff86c |
| tree | 220c3cd93841f2e49f594a1645c6189261c1ceda |
| parent | 7897a695e351b7e8ebaa0d8c693660291af18286 |
| signature | Signed by PGP key B5690EEEBB952194 |
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"; |
| 11 | import { Atom } from "effect/reactivity"; | 11 | import { Atom } from "effect/reactivity"; |
| 12 | import { Fragment, useMemo } from "react"; | 12 | import { useMemo } from "react"; |
| 13 | import { Alert, Pressable, View, type ColorValue } from "react-native"; | 13 | import { Alert, Pressable, View, type ColorValue } from "react-native"; |
| 14 | import { AppText as Text } from "../../components/AppText"; | 14 | import { AppText as Text } from "../../components/AppText"; |
| 15 | import { SymbolView } from "../../components/AppSymbol"; | 15 | import { 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 | ? undefined | 7646 | ? 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.label | 7654 | <> |
| 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"; |
| 18 | import { Fragment } from "react"; | ||
| 19 | import { formatSubagentDisplayTitle } from "@t3tools/client-runtime/state/subagent-display"; | 18 | import { formatSubagentDisplayTitle } from "@t3tools/client-runtime/state/subagent-display"; |
| 20 | import { | 19 | import { |
| 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 | <HandoffEndpoint | 568 | <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" /> |