|
|
@@ -1978,6 +1978,7 @@ function InlineTool(props: {
|
|
|
pending: string
|
|
|
failure?: string
|
|
|
spinner?: boolean
|
|
|
+ status?: JSX.Element
|
|
|
children: JSX.Element
|
|
|
part: SessionMessageAssistantTool
|
|
|
onClick?: () => void
|
|
|
@@ -2028,6 +2029,7 @@ function InlineTool(props: {
|
|
|
pending={props.pending}
|
|
|
failure={props.failure}
|
|
|
spinner={props.spinner}
|
|
|
+ status={props.status}
|
|
|
onMouseOver={() => clickable() && setHover(true)}
|
|
|
onMouseOut={() => setHover(false)}
|
|
|
onMouseUp={() => {
|
|
|
@@ -2057,6 +2059,7 @@ export function InlineToolRow(props: {
|
|
|
pending: string
|
|
|
failure?: string
|
|
|
spinner?: boolean
|
|
|
+ status?: JSX.Element
|
|
|
children: JSX.Element
|
|
|
onMouseOver?: () => void
|
|
|
onMouseOut?: () => void
|
|
|
@@ -2066,7 +2069,16 @@ export function InlineToolRow(props: {
|
|
|
<box paddingLeft={3} onMouseOver={props.onMouseOver} onMouseOut={props.onMouseOut} onMouseUp={props.onMouseUp}>
|
|
|
<Switch>
|
|
|
<Match when={props.spinner}>
|
|
|
- <Spinner color={props.color} children={props.children} />
|
|
|
+ <Show when={props.status} fallback={<Spinner color={props.color} children={props.children} />}>
|
|
|
+ {(status) => (
|
|
|
+ <box flexDirection="row" gap={1}>
|
|
|
+ <Spinner color={props.color} />
|
|
|
+ <InlineToolLabel color={props.color} status={status()}>
|
|
|
+ {props.children}
|
|
|
+ </InlineToolLabel>
|
|
|
+ </box>
|
|
|
+ )}
|
|
|
+ </Show>
|
|
|
</Match>
|
|
|
<Match when={true}>
|
|
|
<Show fallback={<Spinner color={props.color}>{props.pending}</Spinner>} when={props.complete || props.failed}>
|
|
|
@@ -2078,13 +2090,28 @@ export function InlineToolRow(props: {
|
|
|
>
|
|
|
{props.icon}
|
|
|
</text>
|
|
|
- <text
|
|
|
- flexGrow={1}
|
|
|
- fg={props.failed ? props.errorColor : props.color}
|
|
|
- attributes={props.denied ? TextAttributes.STRIKETHROUGH : undefined}
|
|
|
+ <Show
|
|
|
+ when={props.status}
|
|
|
+ fallback={
|
|
|
+ <text
|
|
|
+ flexGrow={1}
|
|
|
+ fg={props.failed ? props.errorColor : props.color}
|
|
|
+ attributes={props.denied ? TextAttributes.STRIKETHROUGH : undefined}
|
|
|
+ >
|
|
|
+ {props.failed && !props.complete ? (props.failure ?? props.children) : props.children}
|
|
|
+ </text>
|
|
|
+ }
|
|
|
>
|
|
|
- {props.failed && !props.complete ? (props.failure ?? props.children) : props.children}
|
|
|
- </text>
|
|
|
+ {(status) => (
|
|
|
+ <InlineToolLabel
|
|
|
+ color={props.failed ? props.errorColor : props.color}
|
|
|
+ denied={props.denied}
|
|
|
+ status={status()}
|
|
|
+ >
|
|
|
+ {props.failed && !props.complete ? (props.failure ?? props.children) : props.children}
|
|
|
+ </InlineToolLabel>
|
|
|
+ )}
|
|
|
+ </Show>
|
|
|
</box>
|
|
|
</Show>
|
|
|
</Match>
|
|
|
@@ -2098,6 +2125,32 @@ export function InlineToolRow(props: {
|
|
|
)
|
|
|
}
|
|
|
|
|
|
+function InlineToolLabel(props: { color?: RGBA; denied?: boolean; status: JSX.Element; children: JSX.Element }) {
|
|
|
+ return (
|
|
|
+ <box flexDirection="row" flexWrap="wrap" columnGap={1} flexGrow={1}>
|
|
|
+ <text
|
|
|
+ maxWidth="100%"
|
|
|
+ flexShrink={0}
|
|
|
+ fg={props.color}
|
|
|
+ attributes={props.denied ? TextAttributes.STRIKETHROUGH : undefined}
|
|
|
+ >
|
|
|
+ {props.children}
|
|
|
+ </text>
|
|
|
+ {props.status}
|
|
|
+ </box>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
+function StatusBadge(props: { children: string }) {
|
|
|
+ const { theme } = useTheme()
|
|
|
+ return (
|
|
|
+ <text flexShrink={0} bg={theme.backgroundElement} fg={theme.textMuted}>
|
|
|
+ {" "}
|
|
|
+ {props.children}{" "}
|
|
|
+ </text>
|
|
|
+ )
|
|
|
+}
|
|
|
+
|
|
|
function BlockTool(props: {
|
|
|
title?: string
|
|
|
path?: { label: string; value: string }
|
|
|
@@ -2241,9 +2294,7 @@ function Shell(props: ToolProps) {
|
|
|
</Show>
|
|
|
</Show>
|
|
|
<Show when={shellID()}>
|
|
|
- <text>
|
|
|
- <span style={{ bg: theme.backgroundElement, fg: theme.textMuted }}> Background </span>
|
|
|
- </text>
|
|
|
+ <StatusBadge>Background</StatusBadge>
|
|
|
</Show>
|
|
|
<Show when={collapsed().overflow}>
|
|
|
<text fg={theme.textMuted}>{expanded() ? "Click to collapse" : "Click to expand"}</text>
|
|
|
@@ -2386,20 +2437,17 @@ function Subagent(props: ToolProps) {
|
|
|
const id = sessionID()
|
|
|
if (id) navigate({ type: "session", sessionID: id })
|
|
|
}}
|
|
|
+ status={
|
|
|
+ props.input.background === true || props.metadata.status === "running" ? (
|
|
|
+ <StatusBadge>Background</StatusBadge>
|
|
|
+ ) : undefined
|
|
|
+ }
|
|
|
>
|
|
|
- {formatSubagentTitle(
|
|
|
- Locale.titlecase(stringValue(props.input.agent) ?? stringValue(props.input.subagent_type) ?? "General"),
|
|
|
- description() ?? "Subagent",
|
|
|
- props.input.background === true || props.metadata.status === "running",
|
|
|
- )}
|
|
|
+ {`${Locale.titlecase(stringValue(props.input.agent) ?? stringValue(props.input.subagent_type) ?? "General")} Subagent — ${description() ?? "Subagent"}`}
|
|
|
</InlineTool>
|
|
|
)
|
|
|
}
|
|
|
|
|
|
-export function formatSubagentTitle(agent: string, description: string, background: boolean) {
|
|
|
- return `${agent} Subagent — ${description}${background ? " [background]" : ""}`
|
|
|
-}
|
|
|
-
|
|
|
export function formatSubagentRetry(attempt: number, message: string) {
|
|
|
return `Retrying (attempt ${attempt}) · ${message}`
|
|
|
}
|