|
|
@@ -54,6 +54,7 @@ import { useRenderer, useTerminalDimensions, type JSX } from "@opentui/solid"
|
|
|
import { useSDK } from "@tui/context/sdk"
|
|
|
import { useEditorContext } from "@tui/context/editor"
|
|
|
import { useDialog } from "../../ui/dialog"
|
|
|
+import { DialogAlert } from "../../ui/dialog-alert"
|
|
|
import { TodoItem } from "../../component/todo-item"
|
|
|
import { DialogMessage } from "./dialog-message"
|
|
|
import type { PromptInfo } from "../../component/prompt/history"
|
|
|
@@ -409,15 +410,19 @@ export function Session() {
|
|
|
|
|
|
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() {
|
|
|
if (children().length === 1) return
|
|
|
const next = children().find((x) => !!x.parentID)
|
|
|
- if (next) {
|
|
|
- navigate({
|
|
|
- type: "session",
|
|
|
- sessionID: next.id,
|
|
|
- })
|
|
|
- }
|
|
|
+ if (next) enterChild(next.id)
|
|
|
}
|
|
|
|
|
|
function moveChild(direction: number) {
|
|
|
@@ -428,12 +433,7 @@ export function Session() {
|
|
|
|
|
|
if (next >= sessions.length) next = 0
|
|
|
if (next < 0) next = sessions.length - 1
|
|
|
- if (sessions[next]) {
|
|
|
- navigate({
|
|
|
- type: "session",
|
|
|
- sessionID: sessions[next].id,
|
|
|
- })
|
|
|
- }
|
|
|
+ if (sessions[next]) enterChild(sessions[next].id)
|
|
|
}
|
|
|
|
|
|
function childSessionHandler(func: () => void) {
|
|
|
@@ -1007,8 +1007,8 @@ export function Session() {
|
|
|
category: "Session",
|
|
|
hidden: true,
|
|
|
run: () => {
|
|
|
- moveFirstChild()
|
|
|
dialog.clear()
|
|
|
+ moveFirstChild()
|
|
|
},
|
|
|
},
|
|
|
{
|
|
|
@@ -1035,8 +1035,8 @@ export function Session() {
|
|
|
hidden: true,
|
|
|
enabled: !!session()?.parentID,
|
|
|
run: childSessionHandler(() => {
|
|
|
- moveChild(1)
|
|
|
dialog.clear()
|
|
|
+ moveChild(1)
|
|
|
}),
|
|
|
},
|
|
|
{
|
|
|
@@ -1046,8 +1046,8 @@ export function Session() {
|
|
|
hidden: true,
|
|
|
enabled: !!session()?.parentID,
|
|
|
run: childSessionHandler(() => {
|
|
|
- moveChild(-1)
|
|
|
dialog.clear()
|
|
|
+ moveChild(-1)
|
|
|
}),
|
|
|
},
|
|
|
])
|
|
|
@@ -1758,6 +1758,7 @@ function GenericTool(props: ToolProps<any>) {
|
|
|
function InlineTool(props: {
|
|
|
icon: string
|
|
|
iconColor?: RGBA
|
|
|
+ color?: RGBA
|
|
|
complete: any
|
|
|
pending: string
|
|
|
spinner?: boolean
|
|
|
@@ -1779,6 +1780,7 @@ function InlineTool(props: {
|
|
|
})
|
|
|
|
|
|
const fg = createMemo(() => {
|
|
|
+ if (props.color) return props.color
|
|
|
if (permission()) return theme.warning
|
|
|
if (hover() && props.onClick) return theme.text
|
|
|
if (props.complete) return theme.textMuted
|
|
|
@@ -2063,8 +2065,10 @@ function WebSearch(props: ToolProps<typeof WebSearchTool>) {
|
|
|
}
|
|
|
|
|
|
function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
+ const { theme } = useTheme()
|
|
|
const { navigate } = useRoute()
|
|
|
const sync = useSync()
|
|
|
+ const dialog = useDialog()
|
|
|
|
|
|
onMount(() => {
|
|
|
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 retry = createMemo(() => {
|
|
|
+ const status = sync.data.session_status[props.metadata.sessionId ?? ""]
|
|
|
+ if (status?.type !== "retry") return
|
|
|
+ return status
|
|
|
+ })
|
|
|
|
|
|
const duration = createMemo(() => {
|
|
|
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
|
|
|
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`
|
|
|
if (current()) {
|
|
|
const state = current()!.state
|
|
|
@@ -2123,6 +2135,7 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
return (
|
|
|
<InlineTool
|
|
|
icon="│"
|
|
|
+ color={retry() ? theme.error : undefined}
|
|
|
spinner={isRunning()}
|
|
|
complete={props.input.description}
|
|
|
pending="Delegating..."
|
|
|
@@ -2131,6 +2144,8 @@ function Task(props: ToolProps<typeof TaskTool>) {
|
|
|
if (props.metadata.sessionId) {
|
|
|
navigate({ type: "session", sessionID: props.metadata.sessionId })
|
|
|
}
|
|
|
+ const status = retry()
|
|
|
+ if (status) void DialogAlert.show(dialog, "Retry Error", status.message)
|
|
|
}}
|
|
|
>
|
|
|
{content()}
|