1import {
2 formatProviderSubagentStatus,
3 type ProviderSubagentStatus,
4} from "@t3tools/client-runtime/state/thread-execution";
5import { isOrchestrationV2WorkActive } from "@t3tools/contracts";
6import { View } from "react-native";
7
8import { AppText as Text } from "../../components/AppText";
9import { ProviderIcon } from "../../components/ProviderIcon";
10import { RequestActionButton } from "./RequestActionButton";
11import { useVisibleSecondClock } from "./use-visible-second-clock";
12
13/**
14 * Replaces the composer on a provider-native subagent thread. The provider
15 * runs that conversation, so there is nothing to send; the bar says which
16 * model is working, for how long, and leads back to the parent.
17 */
18export function ProviderSubagentBar(props: {
19 /** Driver and catalog icon of the provider running the subagent. */
20 readonly provider: { readonly driver: string; readonly iconUrl?: string | undefined } | null;
21 readonly modelLabel: string;
22 /** Reasoning effort as the composer names it, when the subagent has one. */
23 readonly effortLabel: string | null;
24 /** Null until the subagent's root turn arrives. */
25 readonly status: ProviderSubagentStatus | null;
26 readonly onOpenParent: (() => void) | null;
27}) {
28 const live = props.status !== null && isOrchestrationV2WorkActive(props.status.status);
29 const nowMs = useVisibleSecondClock(live);
30 const statusLabel = formatProviderSubagentStatus(props.status, nowMs);
31 const modelDescription =
32 props.effortLabel === null ? props.modelLabel : `${props.modelLabel}, ${props.effortLabel}`;
33
34 return (
35 <View className="flex-row items-center gap-3 rounded-[20px] border border-border-subtle bg-card-alt py-2 pe-2 ps-4">
36 {/* Only the text is one element, so "Open parent" stays reachable. */}
37 <View
38 accessible
39 accessibilityLabel={`${modelDescription} subagent, ${statusLabel}. It runs on its own and cannot take messages.`}
40 className="min-w-0 flex-1 gap-0.5"
41 >
42 <View className="min-w-0 flex-row items-center gap-1.5">
43 {props.provider ? (
44 <ProviderIcon
45 iconUrl={props.provider.iconUrl}
46 provider={props.provider.driver}
47 size={16}
48 />
49 ) : null}
50 <Text numberOfLines={1} className="min-w-0 shrink font-t3-bold text-sm text-foreground">
51 {props.modelLabel}
52 </Text>
53 {props.effortLabel === null ? null : (
54 <Text
55 numberOfLines={1}
56 className="shrink-0 font-sans text-sm text-foreground-secondary"
57 >
58 {props.effortLabel}
59 </Text>
60 )}
61 </View>
62 <Text
63 numberOfLines={1}
64 className="font-sans text-xs text-foreground-secondary"
65 style={{ fontVariant: ["tabular-nums"] }}
66 >
67 {statusLabel} · Runs on its own
68 </Text>
69 </View>
70 {props.onOpenParent ? (
71 <RequestActionButton label="Open parent" tone="secondary" onPress={props.onOpenParent} />
72 ) : null}
73 </View>
74 );
75}