fix(tui): surface subagent retry status (#29591)
This commit is contained in:
@@ -54,6 +54,7 @@ import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
|||||||
import { useSDK } from "@tui/context/sdk"
|
import { useSDK } from "@tui/context/sdk"
|
||||||
import { useEditorContext } from "@tui/context/editor"
|
import { useEditorContext } from "@tui/context/editor"
|
||||||
import { useDialog } from "../../ui/dialog"
|
import { useDialog } from "../../ui/dialog"
|
||||||
|
import { DialogAlert } from "../../ui/dialog-alert"
|
||||||
import { TodoItem } from "../../component/todo-item"
|
import { TodoItem } from "../../component/todo-item"
|
||||||
import { DialogMessage } from "./dialog-message"
|
import { DialogMessage } from "./dialog-message"
|
||||||
import type { PromptInfo } from "../../component/prompt/history"
|
import type { PromptInfo } from "../../component/prompt/history"
|
||||||
@@ -409,15 +410,19 @@ export function Session() {
|
|||||||
|
|
||||||
const local = useLocal()
|
const local = useLocal()
|
||||||
|
|
||||||
|
function enterChild(sessionID: string) {
|
||||||
|
navigate({
|
||||||
|
type: "session",
|
||||||
|
sessionID,
|
||||||
|
})
|
||||||
|
const status = sync.data.session_status[sessionID]
|
||||||
|
if (status?.type === "retry") void DialogAlert.show(dialog, "Retry Error", status.message)
|
||||||
|
}
|
||||||
|
|
||||||
function moveFirstChild() {
|
function moveFirstChild() {
|
||||||
if (children().length === 1) return
|
if (children().length === 1) return
|
||||||
const next = children().find((x) => !!x.parentID)
|
const next = children().find((x) => !!x.parentID)
|
||||||
if (next) {
|
if (next) enterChild(next.id)
|
||||||
navigate({
|
|
||||||
type: "session",
|
|
||||||
sessionID: next.id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function moveChild(direction: number) {
|
function moveChild(direction: number) {
|
||||||
@@ -428,12 +433,7 @@ export function Session() {
|
|||||||
|
|
||||||
if (next >= sessions.length) next = 0
|
if (next >= sessions.length) next = 0
|
||||||
if (next < 0) next = sessions.length - 1
|
if (next < 0) next = sessions.length - 1
|
||||||
if (sessions[next]) {
|
if (sessions[next]) enterChild(sessions[next].id)
|
||||||
navigate({
|
|
||||||
type: "session",
|
|
||||||
sessionID: sessions[next].id,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function childSessionHandler(func: () => void) {
|
function childSessionHandler(func: () => void) {
|
||||||
@@ -1007,8 +1007,8 @@ export function Session() {
|
|||||||
category: "Session",
|
category: "Session",
|
||||||
hidden: true,
|
hidden: true,
|
||||||
run: () => {
|
run: () => {
|
||||||
moveFirstChild()
|
|
||||||
dialog.clear()
|
dialog.clear()
|
||||||
|
moveFirstChild()
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1035,8 +1035,8 @@ export function Session() {
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
enabled: !!session()?.parentID,
|
enabled: !!session()?.parentID,
|
||||||
run: childSessionHandler(() => {
|
run: childSessionHandler(() => {
|
||||||
moveChild(1)
|
|
||||||
dialog.clear()
|
dialog.clear()
|
||||||
|
moveChild(1)
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -1046,8 +1046,8 @@ export function Session() {
|
|||||||
hidden: true,
|
hidden: true,
|
||||||
enabled: !!session()?.parentID,
|
enabled: !!session()?.parentID,
|
||||||
run: childSessionHandler(() => {
|
run: childSessionHandler(() => {
|
||||||
moveChild(-1)
|
|
||||||
dialog.clear()
|
dialog.clear()
|
||||||
|
moveChild(-1)
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
])
|
])
|
||||||
@@ -1758,6 +1758,7 @@ function GenericTool(props: ToolProps<any>) {
|
|||||||
function InlineTool(props: {
|
function InlineTool(props: {
|
||||||
icon: string
|
icon: string
|
||||||
iconColor?: RGBA
|
iconColor?: RGBA
|
||||||
|
color?: RGBA
|
||||||
complete: any
|
complete: any
|
||||||
pending: string
|
pending: string
|
||||||
spinner?: boolean
|
spinner?: boolean
|
||||||
@@ -1779,6 +1780,7 @@ function InlineTool(props: {
|
|||||||
})
|
})
|
||||||
|
|
||||||
const fg = createMemo(() => {
|
const fg = createMemo(() => {
|
||||||
|
if (props.color) return props.color
|
||||||
if (permission()) return theme.warning
|
if (permission()) return theme.warning
|
||||||
if (hover() && props.onClick) return theme.text
|
if (hover() && props.onClick) return theme.text
|
||||||
if (props.complete) return theme.textMuted
|
if (props.complete) return theme.textMuted
|
||||||
@@ -2063,8 +2065,10 @@ function WebSearch(props: ToolProps<typeof WebSearchTool>) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function Task(props: ToolProps<typeof TaskTool>) {
|
function Task(props: ToolProps<typeof TaskTool>) {
|
||||||
|
const { theme } = useTheme()
|
||||||
const { navigate } = useRoute()
|
const { navigate } = useRoute()
|
||||||
const sync = useSync()
|
const sync = useSync()
|
||||||
|
const dialog = useDialog()
|
||||||
|
|
||||||
onMount(() => {
|
onMount(() => {
|
||||||
if (props.metadata.sessionId && !sync.data.message[props.metadata.sessionId]?.length)
|
if (props.metadata.sessionId && !sync.data.message[props.metadata.sessionId]?.length)
|
||||||
@@ -2086,6 +2090,11 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|||||||
)
|
)
|
||||||
|
|
||||||
const isRunning = createMemo(() => props.part.state.status === "running")
|
const isRunning = createMemo(() => props.part.state.status === "running")
|
||||||
|
const retry = createMemo(() => {
|
||||||
|
const status = sync.data.session_status[props.metadata.sessionId ?? ""]
|
||||||
|
if (status?.type !== "retry") return
|
||||||
|
return status
|
||||||
|
})
|
||||||
|
|
||||||
const duration = createMemo(() => {
|
const duration = createMemo(() => {
|
||||||
const first = messages().find((x) => x.role === "user")?.time.created
|
const first = messages().find((x) => x.role === "user")?.time.created
|
||||||
@@ -2100,7 +2109,10 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|||||||
props.metadata.background === true ? `${props.input.description} (background)` : props.input.description
|
props.metadata.background === true ? `${props.input.description} (background)` : props.input.description
|
||||||
let content = [`${Locale.titlecase(props.input.subagent_type ?? "General")} Task — ${description}`]
|
let content = [`${Locale.titlecase(props.input.subagent_type ?? "General")} Task — ${description}`]
|
||||||
|
|
||||||
if (isRunning() && tools().length > 0) {
|
const retrying = retry()
|
||||||
|
if (isRunning() && retrying) {
|
||||||
|
content.push(`↳ ${Locale.truncate(retrying.message, 80)} [retrying attempt #${retrying.attempt}]`)
|
||||||
|
} else if (isRunning() && tools().length > 0) {
|
||||||
// content[0] += ` · ${tools().length} toolcalls`
|
// content[0] += ` · ${tools().length} toolcalls`
|
||||||
if (current()) {
|
if (current()) {
|
||||||
const state = current()!.state
|
const state = current()!.state
|
||||||
@@ -2123,6 +2135,7 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|||||||
return (
|
return (
|
||||||
<InlineTool
|
<InlineTool
|
||||||
icon="│"
|
icon="│"
|
||||||
|
color={retry() ? theme.error : undefined}
|
||||||
spinner={isRunning()}
|
spinner={isRunning()}
|
||||||
complete={props.input.description}
|
complete={props.input.description}
|
||||||
pending="Delegating..."
|
pending="Delegating..."
|
||||||
@@ -2131,6 +2144,8 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|||||||
if (props.metadata.sessionId) {
|
if (props.metadata.sessionId) {
|
||||||
navigate({ type: "session", sessionID: props.metadata.sessionId })
|
navigate({ type: "session", sessionID: props.metadata.sessionId })
|
||||||
}
|
}
|
||||||
|
const status = retry()
|
||||||
|
if (status) void DialogAlert.show(dialog, "Retry Error", status.message)
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{content()}
|
{content()}
|
||||||
|
|||||||
Reference in New Issue
Block a user