|
@@ -1789,6 +1789,7 @@ function InlineTool(props: {
|
|
|
complete: any
|
|
complete: any
|
|
|
pending: string
|
|
pending: string
|
|
|
spinner?: boolean
|
|
spinner?: boolean
|
|
|
|
|
+ subagent?: boolean
|
|
|
children: JSX.Element
|
|
children: JSX.Element
|
|
|
part: ToolPart
|
|
part: ToolPart
|
|
|
onClick?: () => void
|
|
onClick?: () => void
|
|
@@ -1829,6 +1830,7 @@ function InlineTool(props: {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<InlineToolRow
|
|
<InlineToolRow
|
|
|
|
|
+ id={`tool-inline-${props.subagent ? "subagent-" : ""}${props.part.id}`}
|
|
|
icon={props.icon}
|
|
icon={props.icon}
|
|
|
iconColor={props.iconColor}
|
|
iconColor={props.iconColor}
|
|
|
color={fg()}
|
|
color={fg()}
|
|
@@ -1840,6 +1842,7 @@ function InlineTool(props: {
|
|
|
complete={props.complete}
|
|
complete={props.complete}
|
|
|
pending={props.pending}
|
|
pending={props.pending}
|
|
|
spinner={props.spinner}
|
|
spinner={props.spinner}
|
|
|
|
|
+ subagent={props.subagent}
|
|
|
separateAfter={(id) =>
|
|
separateAfter={(id) =>
|
|
|
sync.data.message[ctx.sessionID]?.some((message) => message.role === "user" && message.id === id) ?? false
|
|
sync.data.message[ctx.sessionID]?.some((message) => message.role === "user" && message.id === id) ?? false
|
|
|
}
|
|
}
|
|
@@ -1860,6 +1863,7 @@ function InlineTool(props: {
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
export function InlineToolRow(props: {
|
|
export function InlineToolRow(props: {
|
|
|
|
|
+ id?: string
|
|
|
icon: string
|
|
icon: string
|
|
|
iconColor?: RGBA
|
|
iconColor?: RGBA
|
|
|
color?: RGBA
|
|
color?: RGBA
|
|
@@ -1871,6 +1875,7 @@ export function InlineToolRow(props: {
|
|
|
complete: any
|
|
complete: any
|
|
|
pending: string
|
|
pending: string
|
|
|
spinner?: boolean
|
|
spinner?: boolean
|
|
|
|
|
+ subagent?: boolean
|
|
|
children: JSX.Element
|
|
children: JSX.Element
|
|
|
separateAfter?: (id: string | undefined) => boolean
|
|
separateAfter?: (id: string | undefined) => boolean
|
|
|
onMouseOver?: () => void
|
|
onMouseOver?: () => void
|
|
@@ -1881,6 +1886,7 @@ export function InlineToolRow(props: {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<box
|
|
<box
|
|
|
|
|
+ id={props.id}
|
|
|
marginTop={margin()}
|
|
marginTop={margin()}
|
|
|
paddingLeft={3}
|
|
paddingLeft={3}
|
|
|
onMouseOver={props.onMouseOver}
|
|
onMouseOver={props.onMouseOver}
|
|
@@ -1895,9 +1901,12 @@ export function InlineToolRow(props: {
|
|
|
const children = parent.getChildren()
|
|
const children = parent.getChildren()
|
|
|
const index = children.indexOf(el)
|
|
const index = children.indexOf(el)
|
|
|
const previous = children[index - 1]
|
|
const previous = children[index - 1]
|
|
|
|
|
+ const previousInline = previous?.id.startsWith("tool-inline-") ?? false
|
|
|
|
|
+ const previousSubagent = previous?.id.startsWith("tool-inline-subagent-") ?? false
|
|
|
setMargin(
|
|
setMargin(
|
|
|
previous?.id.startsWith("text-") ||
|
|
previous?.id.startsWith("text-") ||
|
|
|
previous?.id.startsWith("tool-block-") ||
|
|
previous?.id.startsWith("tool-block-") ||
|
|
|
|
|
+ (previousInline && previousSubagent !== Boolean(props.subagent)) ||
|
|
|
props.separateAfter?.(previous?.id)
|
|
props.separateAfter?.(previous?.id)
|
|
|
? 1
|
|
? 1
|
|
|
: 0,
|
|
: 0,
|
|
@@ -2123,8 +2132,8 @@ function Read(props: ToolProps<typeof ReadTool>) {
|
|
|
Read {pathFormatter.format(props.input.filePath)} {input(props.input, ["filePath"])}
|
|
Read {pathFormatter.format(props.input.filePath)} {input(props.input, ["filePath"])}
|
|
|
</InlineTool>
|
|
</InlineTool>
|
|
|
<For each={loaded()}>
|
|
<For each={loaded()}>
|
|
|
- {(filepath) => (
|
|
|
|
|
- <box paddingLeft={3}>
|
|
|
|
|
|
|
+ {(filepath, index) => (
|
|
|
|
|
+ <box id={`tool-inline-loaded-${props.part.id}-${index()}`} paddingLeft={3}>
|
|
|
<text paddingLeft={3} fg={theme.textMuted}>
|
|
<text paddingLeft={3} fg={theme.textMuted}>
|
|
|
↳ Loaded {pathFormatter.format(filepath)}
|
|
↳ Loaded {pathFormatter.format(filepath)}
|
|
|
</text>
|
|
</text>
|
|
@@ -2190,11 +2199,14 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
tools().findLast((x) => (x.state.status === "running" || x.state.status === "completed") && x.state.title),
|
|
tools().findLast((x) => (x.state.status === "running" || x.state.status === "completed") && x.state.title),
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
- const isRunning = createMemo(() => props.part.state.status === "running")
|
|
|
|
|
|
|
+ const status = createMemo(() => sync.data.session_status[props.metadata.sessionId ?? ""])
|
|
|
|
|
+ const isRunning = createMemo(
|
|
|
|
|
+ () => props.part.state.status === "running" || (props.metadata.background === true && status() !== undefined),
|
|
|
|
|
+ )
|
|
|
const retry = createMemo(() => {
|
|
const retry = createMemo(() => {
|
|
|
- const status = sync.data.session_status[props.metadata.sessionId ?? ""]
|
|
|
|
|
- if (status?.type !== "retry") return
|
|
|
|
|
- return status
|
|
|
|
|
|
|
+ const value = status()
|
|
|
|
|
+ if (value?.type !== "retry") return
|
|
|
|
|
+ return value
|
|
|
})
|
|
})
|
|
|
|
|
|
|
|
const duration = createMemo(() => {
|
|
const duration = createMemo(() => {
|
|
@@ -2214,20 +2226,15 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
if (isRunning() && retrying) {
|
|
if (isRunning() && retrying) {
|
|
|
content.push(`↳ ${Locale.truncate(retrying.message, 80)} [retrying attempt #${retrying.attempt}]`)
|
|
content.push(`↳ ${Locale.truncate(retrying.message, 80)} [retrying attempt #${retrying.attempt}]`)
|
|
|
} else if (isRunning() && tools().length > 0) {
|
|
} else if (isRunning() && tools().length > 0) {
|
|
|
- // content[0] += ` · ${tools().length} toolcalls`
|
|
|
|
|
if (current()) {
|
|
if (current()) {
|
|
|
const state = current()!.state
|
|
const state = current()!.state
|
|
|
const title = state.status === "running" || state.status === "completed" ? state.title : undefined
|
|
const title = state.status === "running" || state.status === "completed" ? state.title : undefined
|
|
|
content.push(`↳ ${Locale.titlecase(current()!.tool)} ${title}`)
|
|
content.push(`↳ ${Locale.titlecase(current()!.tool)} ${title}`)
|
|
|
- } else content.push(`↳ ${tools().length} toolcalls`)
|
|
|
|
|
|
|
+ } else content.push(`↳ ${formatSubagentToolcalls(tools().length)}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- if (props.part.state.status === "completed") {
|
|
|
|
|
- content.push(
|
|
|
|
|
- props.metadata.background === true
|
|
|
|
|
- ? `└ ${tools().length} toolcalls`
|
|
|
|
|
- : `└ ${tools().length} toolcalls · ${Locale.duration(duration())}`,
|
|
|
|
|
- )
|
|
|
|
|
|
|
+ if (!isRunning() && props.part.state.status === "completed") {
|
|
|
|
|
+ content.push(`↳ ${formatCompletedSubagentDetail(tools().length, Locale.duration(duration()))}`)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
return content.join("\n")
|
|
return content.join("\n")
|
|
@@ -2235,7 +2242,8 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
|
|
|
|
|
return (
|
|
return (
|
|
|
<InlineTool
|
|
<InlineTool
|
|
|
- icon="│"
|
|
|
|
|
|
|
+ icon={props.part.state.status === "completed" ? "✓" : "│"}
|
|
|
|
|
+ subagent={true}
|
|
|
color={retry() ? theme.error : undefined}
|
|
color={retry() ? theme.error : undefined}
|
|
|
spinner={isRunning()}
|
|
spinner={isRunning()}
|
|
|
complete={props.input.description}
|
|
complete={props.input.description}
|
|
@@ -2254,6 +2262,15 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
)
|
|
)
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+export function formatSubagentToolcalls(count: number) {
|
|
|
|
|
+ return `${count} toolcall${count === 1 ? "" : "s"}`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+export function formatCompletedSubagentDetail(toolcalls: number, duration: string) {
|
|
|
|
|
+ if (toolcalls === 0) return duration
|
|
|
|
|
+ return `${formatSubagentToolcalls(toolcalls)} · ${duration}`
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
function Edit(props: ToolProps<typeof EditTool>) {
|
|
function Edit(props: ToolProps<typeof EditTool>) {
|
|
|
const ctx = use()
|
|
const ctx = use()
|
|
|
const { theme, syntax } = useTheme()
|
|
const { theme, syntax } = useTheme()
|